@korsolutions/guidon 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. package/dist/commonjs/babel.config.js +15 -0
  2. package/dist/commonjs/babel.config.js.map +1 -0
  3. package/dist/commonjs/bob.config.js +11 -0
  4. package/dist/commonjs/bob.config.js.map +1 -0
  5. package/dist/commonjs/components/GuidonOverlay.js +206 -0
  6. package/dist/commonjs/components/GuidonOverlay.js.map +1 -0
  7. package/dist/commonjs/components/GuidonProvider.js +157 -0
  8. package/dist/commonjs/components/GuidonProvider.js.map +1 -0
  9. package/dist/commonjs/components/GuidonTarget.js +108 -0
  10. package/dist/commonjs/components/GuidonTarget.js.map +1 -0
  11. package/dist/commonjs/components/GuidonTooltip.js +422 -0
  12. package/dist/commonjs/components/GuidonTooltip.js.map +1 -0
  13. package/dist/commonjs/components/index.js +40 -0
  14. package/dist/commonjs/components/index.js.map +1 -0
  15. package/dist/commonjs/hooks/index.js +13 -0
  16. package/dist/commonjs/hooks/index.js.map +1 -0
  17. package/dist/commonjs/hooks/useGuidonRef.js +132 -0
  18. package/dist/commonjs/hooks/useGuidonRef.js.map +1 -0
  19. package/dist/commonjs/index.js +143 -0
  20. package/dist/commonjs/index.js.map +1 -0
  21. package/dist/commonjs/package.json +1 -0
  22. package/dist/commonjs/persistence/adapters.js +213 -0
  23. package/dist/commonjs/persistence/adapters.js.map +1 -0
  24. package/dist/commonjs/persistence/hooks.js +153 -0
  25. package/dist/commonjs/persistence/hooks.js.map +1 -0
  26. package/dist/commonjs/persistence/index.js +28 -0
  27. package/dist/commonjs/persistence/index.js.map +1 -0
  28. package/dist/commonjs/store.js +305 -0
  29. package/dist/commonjs/store.js.map +1 -0
  30. package/dist/commonjs/tsconfig.json +32 -0
  31. package/dist/commonjs/types.js +6 -0
  32. package/dist/commonjs/types.js.map +1 -0
  33. package/dist/module/babel.config.js +15 -0
  34. package/dist/module/babel.config.js.map +1 -0
  35. package/dist/module/bob.config.js +11 -0
  36. package/dist/module/bob.config.js.map +1 -0
  37. package/dist/module/components/GuidonOverlay.js +201 -0
  38. package/dist/module/components/GuidonOverlay.js.map +1 -0
  39. package/dist/module/components/GuidonProvider.js +152 -0
  40. package/dist/module/components/GuidonProvider.js.map +1 -0
  41. package/dist/module/components/GuidonTarget.js +104 -0
  42. package/dist/module/components/GuidonTarget.js.map +1 -0
  43. package/dist/module/components/GuidonTooltip.js +417 -0
  44. package/dist/module/components/GuidonTooltip.js.map +1 -0
  45. package/dist/module/components/index.js +7 -0
  46. package/dist/module/components/index.js.map +1 -0
  47. package/dist/module/hooks/index.js +4 -0
  48. package/dist/module/hooks/index.js.map +1 -0
  49. package/dist/module/hooks/useGuidonRef.js +129 -0
  50. package/dist/module/hooks/useGuidonRef.js.map +1 -0
  51. package/dist/module/index.js +17 -0
  52. package/dist/module/index.js.map +1 -0
  53. package/dist/module/package.json +1 -0
  54. package/dist/module/persistence/adapters.js +203 -0
  55. package/dist/module/persistence/adapters.js.map +1 -0
  56. package/dist/module/persistence/hooks.js +148 -0
  57. package/dist/module/persistence/hooks.js.map +1 -0
  58. package/dist/module/persistence/index.js +5 -0
  59. package/dist/module/persistence/index.js.map +1 -0
  60. package/dist/module/store.js +295 -0
  61. package/dist/module/store.js.map +1 -0
  62. package/dist/module/tsconfig.json +32 -0
  63. package/dist/module/types.js +4 -0
  64. package/dist/module/types.js.map +1 -0
  65. package/dist/typescript/commonjs/components/GuidonOverlay.d.ts +9 -0
  66. package/dist/typescript/commonjs/components/GuidonOverlay.d.ts.map +1 -0
  67. package/dist/typescript/commonjs/components/GuidonProvider.d.ts +14 -0
  68. package/dist/typescript/commonjs/components/GuidonProvider.d.ts.map +1 -0
  69. package/dist/typescript/commonjs/components/GuidonTarget.d.ts +7 -0
  70. package/dist/typescript/commonjs/components/GuidonTarget.d.ts.map +1 -0
  71. package/dist/typescript/commonjs/components/GuidonTooltip.d.ts +24 -0
  72. package/dist/typescript/commonjs/components/GuidonTooltip.d.ts.map +1 -0
  73. package/dist/typescript/commonjs/components/index.d.ts +5 -0
  74. package/dist/typescript/commonjs/components/index.d.ts.map +1 -0
  75. package/dist/typescript/commonjs/hooks/index.d.ts +2 -0
  76. package/dist/typescript/commonjs/hooks/index.d.ts.map +1 -0
  77. package/dist/typescript/commonjs/hooks/useGuidonRef.d.ts +35 -0
  78. package/dist/typescript/commonjs/hooks/useGuidonRef.d.ts.map +1 -0
  79. package/dist/typescript/commonjs/index.d.ts +7 -0
  80. package/dist/typescript/commonjs/index.d.ts.map +1 -0
  81. package/dist/typescript/commonjs/package.json +1 -0
  82. package/dist/typescript/commonjs/persistence/adapters.d.ts +57 -0
  83. package/dist/typescript/commonjs/persistence/adapters.d.ts.map +1 -0
  84. package/dist/typescript/commonjs/persistence/hooks.d.ts +29 -0
  85. package/dist/typescript/commonjs/persistence/hooks.d.ts.map +1 -0
  86. package/dist/typescript/commonjs/persistence/index.d.ts +3 -0
  87. package/dist/typescript/commonjs/persistence/index.d.ts.map +1 -0
  88. package/dist/typescript/commonjs/store.d.ts +89 -0
  89. package/dist/typescript/commonjs/store.d.ts.map +1 -0
  90. package/dist/{index-D_JFvCIg.d.mts → typescript/commonjs/types.d.ts} +40 -104
  91. package/dist/typescript/commonjs/types.d.ts.map +1 -0
  92. package/dist/typescript/module/components/GuidonOverlay.d.ts +9 -0
  93. package/dist/typescript/module/components/GuidonOverlay.d.ts.map +1 -0
  94. package/dist/typescript/module/components/GuidonProvider.d.ts +14 -0
  95. package/dist/typescript/module/components/GuidonProvider.d.ts.map +1 -0
  96. package/dist/typescript/module/components/GuidonTarget.d.ts +7 -0
  97. package/dist/typescript/module/components/GuidonTarget.d.ts.map +1 -0
  98. package/dist/typescript/module/components/GuidonTooltip.d.ts +24 -0
  99. package/dist/typescript/module/components/GuidonTooltip.d.ts.map +1 -0
  100. package/dist/typescript/module/components/index.d.ts +5 -0
  101. package/dist/typescript/module/components/index.d.ts.map +1 -0
  102. package/dist/typescript/module/hooks/index.d.ts +2 -0
  103. package/dist/typescript/module/hooks/index.d.ts.map +1 -0
  104. package/dist/typescript/module/hooks/useGuidonRef.d.ts +35 -0
  105. package/dist/typescript/module/hooks/useGuidonRef.d.ts.map +1 -0
  106. package/dist/typescript/module/index.d.ts +7 -0
  107. package/dist/typescript/module/index.d.ts.map +1 -0
  108. package/dist/typescript/module/package.json +1 -0
  109. package/dist/typescript/module/persistence/adapters.d.ts +57 -0
  110. package/dist/typescript/module/persistence/adapters.d.ts.map +1 -0
  111. package/dist/typescript/module/persistence/hooks.d.ts +29 -0
  112. package/dist/typescript/module/persistence/hooks.d.ts.map +1 -0
  113. package/dist/typescript/module/persistence/index.d.ts +3 -0
  114. package/dist/typescript/module/persistence/index.d.ts.map +1 -0
  115. package/dist/typescript/module/store.d.ts +89 -0
  116. package/dist/typescript/module/store.d.ts.map +1 -0
  117. package/dist/{index-D_JFvCIg.d.ts → typescript/module/types.d.ts} +40 -104
  118. package/dist/typescript/module/types.d.ts.map +1 -0
  119. package/package.json +25 -13
  120. package/src/babel.config.js +18 -0
  121. package/src/bob.config.js +14 -0
  122. package/src/components/GuidonOverlay.tsx +60 -4
  123. package/src/components/GuidonProvider.tsx +29 -1
  124. package/src/components/GuidonTarget.tsx +26 -16
  125. package/src/components/GuidonTooltip.tsx +143 -9
  126. package/src/hooks/index.ts +1 -0
  127. package/src/hooks/useGuidonRef.ts +154 -0
  128. package/src/index.ts +6 -0
  129. package/src/store.ts +40 -0
  130. package/src/tsconfig.json +32 -0
  131. package/src/types.ts +32 -2
  132. package/dist/index.d.mts +0 -128
  133. package/dist/index.d.ts +0 -128
  134. package/dist/index.js +0 -1097
  135. package/dist/index.js.map +0 -1
  136. package/dist/index.mjs +0 -1072
  137. package/dist/index.mjs.map +0 -1
  138. package/dist/persistence/index.d.mts +0 -2
  139. package/dist/persistence/index.d.ts +0 -2
  140. package/dist/persistence/index.js +0 -300
  141. package/dist/persistence/index.js.map +0 -1
  142. package/dist/persistence/index.mjs +0 -291
  143. package/dist/persistence/index.mjs.map +0 -1
@@ -1,291 +0,0 @@
1
- import { useState, useEffect, useCallback } from 'react';
2
-
3
- // src/persistence/adapters.ts
4
- var STORAGE_KEY_PREFIX = "@guidon:";
5
- var createNoopAdapter = () => ({
6
- loadProgress: async () => null,
7
- saveProgress: async () => {
8
- },
9
- loadAllProgress: async () => ({}),
10
- clearProgress: async () => {
11
- }
12
- });
13
- var createMemoryAdapter = () => {
14
- const store = {};
15
- return {
16
- loadProgress: async (guidonId) => store[guidonId] ?? null,
17
- saveProgress: async (progress) => {
18
- store[progress.guidonId] = progress;
19
- },
20
- loadAllProgress: async () => ({ ...store }),
21
- clearProgress: async (guidonId) => {
22
- delete store[guidonId];
23
- }
24
- };
25
- };
26
- var createLocalStorageAdapter = (keyPrefix = STORAGE_KEY_PREFIX) => ({
27
- loadProgress: async (guidonId) => {
28
- if (typeof window === "undefined" || !window.localStorage) {
29
- return null;
30
- }
31
- try {
32
- const data = localStorage.getItem(`${keyPrefix}${guidonId}`);
33
- return data ? JSON.parse(data) : null;
34
- } catch {
35
- return null;
36
- }
37
- },
38
- saveProgress: async (progress) => {
39
- if (typeof window === "undefined" || !window.localStorage) {
40
- return;
41
- }
42
- try {
43
- localStorage.setItem(
44
- `${keyPrefix}${progress.guidonId}`,
45
- JSON.stringify(progress)
46
- );
47
- } catch {
48
- }
49
- },
50
- loadAllProgress: async () => {
51
- if (typeof window === "undefined" || !window.localStorage) {
52
- return {};
53
- }
54
- const result = {};
55
- try {
56
- for (let i = 0; i < localStorage.length; i++) {
57
- const key = localStorage.key(i);
58
- if (key?.startsWith(keyPrefix)) {
59
- const data = localStorage.getItem(key);
60
- if (data) {
61
- const progress = JSON.parse(data);
62
- result[progress.guidonId] = progress;
63
- }
64
- }
65
- }
66
- } catch {
67
- }
68
- return result;
69
- },
70
- clearProgress: async (guidonId) => {
71
- if (typeof window === "undefined" || !window.localStorage) {
72
- return;
73
- }
74
- try {
75
- localStorage.removeItem(`${keyPrefix}${guidonId}`);
76
- } catch {
77
- }
78
- }
79
- });
80
- var createAsyncStorageAdapter = (asyncStorage, keyPrefix = STORAGE_KEY_PREFIX) => ({
81
- loadProgress: async (guidonId) => {
82
- try {
83
- const data = await asyncStorage.getItem(`${keyPrefix}${guidonId}`);
84
- return data ? JSON.parse(data) : null;
85
- } catch {
86
- return null;
87
- }
88
- },
89
- saveProgress: async (progress) => {
90
- try {
91
- await asyncStorage.setItem(
92
- `${keyPrefix}${progress.guidonId}`,
93
- JSON.stringify(progress)
94
- );
95
- } catch {
96
- }
97
- },
98
- loadAllProgress: async () => {
99
- const result = {};
100
- try {
101
- const allKeys = await asyncStorage.getAllKeys();
102
- const relevantKeys = allKeys.filter((key) => key.startsWith(keyPrefix));
103
- const pairs = await asyncStorage.multiGet(relevantKeys);
104
- for (const [, value] of pairs) {
105
- if (value) {
106
- const progress = JSON.parse(value);
107
- result[progress.guidonId] = progress;
108
- }
109
- }
110
- } catch {
111
- }
112
- return result;
113
- },
114
- clearProgress: async (guidonId) => {
115
- try {
116
- await asyncStorage.removeItem(`${keyPrefix}${guidonId}`);
117
- } catch {
118
- }
119
- }
120
- });
121
- var createApiAdapter = (handlers) => {
122
- const noopAdapter = createNoopAdapter();
123
- return {
124
- loadProgress: handlers.loadProgress ?? noopAdapter.loadProgress,
125
- saveProgress: handlers.saveProgress ?? noopAdapter.saveProgress,
126
- loadAllProgress: handlers.loadAllProgress ?? noopAdapter.loadAllProgress,
127
- clearProgress: handlers.clearProgress ?? noopAdapter.clearProgress
128
- };
129
- };
130
- var createCompositeAdapter = (adapters) => ({
131
- loadProgress: async (guidonId) => {
132
- for (const adapter of adapters) {
133
- const progress = await adapter.loadProgress(guidonId);
134
- if (progress) return progress;
135
- }
136
- return null;
137
- },
138
- saveProgress: async (progress) => {
139
- await Promise.all(adapters.map((adapter) => adapter.saveProgress(progress)));
140
- },
141
- loadAllProgress: async () => {
142
- const result = {};
143
- for (const adapter of adapters) {
144
- if (adapter.loadAllProgress) {
145
- const data = await adapter.loadAllProgress();
146
- Object.assign(result, data);
147
- }
148
- }
149
- return result;
150
- },
151
- clearProgress: async (guidonId) => {
152
- await Promise.all(
153
- adapters.map((adapter) => adapter.clearProgress?.(guidonId))
154
- );
155
- }
156
- });
157
- function useGuidonPersistence(adapter, guidonId) {
158
- const [progress, setProgress] = useState(null);
159
- const [isLoading, setIsLoading] = useState(true);
160
- const [error, setError] = useState(null);
161
- useEffect(() => {
162
- if (!adapter) {
163
- setIsLoading(false);
164
- return;
165
- }
166
- let mounted = true;
167
- const loadProgress = async () => {
168
- try {
169
- setIsLoading(true);
170
- setError(null);
171
- const data = await adapter.loadProgress(guidonId);
172
- if (mounted) {
173
- setProgress(data);
174
- }
175
- } catch (err) {
176
- if (mounted) {
177
- setError(err instanceof Error ? err.message : "Failed to load progress");
178
- }
179
- } finally {
180
- if (mounted) {
181
- setIsLoading(false);
182
- }
183
- }
184
- };
185
- loadProgress();
186
- return () => {
187
- mounted = false;
188
- };
189
- }, [adapter, guidonId]);
190
- const saveProgress = useCallback(
191
- async (newProgress) => {
192
- if (!adapter) return;
193
- const fullProgress = {
194
- ...newProgress,
195
- guidonId
196
- };
197
- try {
198
- setError(null);
199
- await adapter.saveProgress(fullProgress);
200
- setProgress(fullProgress);
201
- } catch (err) {
202
- setError(err instanceof Error ? err.message : "Failed to save progress");
203
- throw err;
204
- }
205
- },
206
- [adapter, guidonId]
207
- );
208
- const clearProgress = useCallback(async () => {
209
- if (!adapter?.clearProgress) return;
210
- try {
211
- setError(null);
212
- await adapter.clearProgress(guidonId);
213
- setProgress(null);
214
- } catch (err) {
215
- setError(err instanceof Error ? err.message : "Failed to clear progress");
216
- throw err;
217
- }
218
- }, [adapter, guidonId]);
219
- const markCompleted = useCallback(async () => {
220
- const currentCount = progress?.completionCount ?? 0;
221
- await saveProgress({
222
- completed: true,
223
- completedAt: (/* @__PURE__ */ new Date()).toISOString(),
224
- completionCount: currentCount + 1
225
- });
226
- }, [saveProgress, progress?.completionCount]);
227
- const markStepViewed = useCallback(
228
- async (stepIndex) => {
229
- await saveProgress({
230
- completed: progress?.completed ?? false,
231
- lastStepIndex: stepIndex,
232
- completedAt: progress?.completedAt,
233
- completionCount: progress?.completionCount
234
- });
235
- },
236
- [saveProgress, progress]
237
- );
238
- return {
239
- progress,
240
- isLoading,
241
- error,
242
- isCompleted: progress?.completed ?? false,
243
- hasStarted: progress !== null,
244
- saveProgress,
245
- clearProgress,
246
- markCompleted,
247
- markStepViewed
248
- };
249
- }
250
- function useShouldShowGuidon(adapter, guidonId, options) {
251
- const { progress, isLoading } = useGuidonPersistence(adapter, guidonId);
252
- const [shouldShow, setShouldShow] = useState(false);
253
- const [isChecking, setIsChecking] = useState(true);
254
- useEffect(() => {
255
- if (isLoading) return;
256
- const checkCondition = async () => {
257
- setIsChecking(true);
258
- if (options?.forceShow) {
259
- setShouldShow(true);
260
- setIsChecking(false);
261
- return;
262
- }
263
- if (progress?.completed) {
264
- setShouldShow(false);
265
- setIsChecking(false);
266
- return;
267
- }
268
- if (options?.additionalCondition) {
269
- try {
270
- const result = await options.additionalCondition();
271
- setShouldShow(result);
272
- } catch {
273
- setShouldShow(true);
274
- }
275
- } else {
276
- setShouldShow(true);
277
- }
278
- setIsChecking(false);
279
- };
280
- checkCondition();
281
- }, [isLoading, progress?.completed, options?.forceShow, options?.additionalCondition]);
282
- return {
283
- shouldShow,
284
- isChecking: isLoading || isChecking,
285
- isCompleted: progress?.completed ?? false
286
- };
287
- }
288
-
289
- export { createApiAdapter, createAsyncStorageAdapter, createCompositeAdapter, createLocalStorageAdapter, createMemoryAdapter, createNoopAdapter, useGuidonPersistence, useShouldShowGuidon };
290
- //# sourceMappingURL=index.mjs.map
291
- //# sourceMappingURL=index.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/persistence/adapters.ts","../../src/persistence/hooks.ts"],"names":[],"mappings":";;;AAEA,IAAM,kBAAA,GAAqB,UAAA;AAMpB,IAAM,oBAAoB,OAAiC;AAAA,EAChE,cAAc,YAAY,IAAA;AAAA,EAC1B,cAAc,YAAY;AAAA,EAAC,CAAA;AAAA,EAC3B,eAAA,EAAiB,aAAa,EAAC,CAAA;AAAA,EAC/B,eAAe,YAAY;AAAA,EAAC;AAC9B,CAAA;AAMO,IAAM,sBAAsB,MAAgC;AACjE,EAAA,MAAM,QAAwC,EAAC;AAE/C,EAAA,OAAO;AAAA,IACL,YAAA,EAAc,OAAO,QAAA,KAAa,KAAA,CAAM,QAAQ,CAAA,IAAK,IAAA;AAAA,IACrD,YAAA,EAAc,OAAO,QAAA,KAAa;AAChC,MAAA,KAAA,CAAM,QAAA,CAAS,QAAQ,CAAA,GAAI,QAAA;AAAA,IAC7B,CAAA;AAAA,IACA,eAAA,EAAiB,aAAa,EAAE,GAAG,KAAA,EAAM,CAAA;AAAA,IACzC,aAAA,EAAe,OAAO,QAAA,KAAa;AACjC,MAAA,OAAO,MAAM,QAAQ,CAAA;AAAA,IACvB;AAAA,GACF;AACF;AAMO,IAAM,yBAAA,GAA4B,CACvC,SAAA,GAAoB,kBAAA,MACU;AAAA,EAC9B,YAAA,EAAc,OAAO,QAAA,KAAa;AAChC,IAAA,IAAI,OAAO,MAAA,KAAW,WAAA,IAAe,CAAC,OAAO,YAAA,EAAc;AACzD,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,IAAI;AACF,MAAA,MAAM,OAAO,YAAA,CAAa,OAAA,CAAQ,GAAG,SAAS,CAAA,EAAG,QAAQ,CAAA,CAAE,CAAA;AAC3D,MAAA,OAAO,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA,GAAI,IAAA;AAAA,IACnC,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,IAAA;AAAA,IACT;AAAA,EACF,CAAA;AAAA,EACA,YAAA,EAAc,OAAO,QAAA,KAAa;AAChC,IAAA,IAAI,OAAO,MAAA,KAAW,WAAA,IAAe,CAAC,OAAO,YAAA,EAAc;AACzD,MAAA;AAAA,IACF;AACA,IAAA,IAAI;AACF,MAAA,YAAA,CAAa,OAAA;AAAA,QACX,CAAA,EAAG,SAAS,CAAA,EAAG,QAAA,CAAS,QAAQ,CAAA,CAAA;AAAA,QAChC,IAAA,CAAK,UAAU,QAAQ;AAAA,OACzB;AAAA,IACF,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACF,CAAA;AAAA,EACA,iBAAiB,YAAY;AAC3B,IAAA,IAAI,OAAO,MAAA,KAAW,WAAA,IAAe,CAAC,OAAO,YAAA,EAAc;AACzD,MAAA,OAAO,EAAC;AAAA,IACV;AACA,IAAA,MAAM,SAAyC,EAAC;AAChD,IAAA,IAAI;AACF,MAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,YAAA,CAAa,QAAQ,CAAA,EAAA,EAAK;AAC5C,QAAA,MAAM,GAAA,GAAM,YAAA,CAAa,GAAA,CAAI,CAAC,CAAA;AAC9B,QAAA,IAAI,GAAA,EAAK,UAAA,CAAW,SAAS,CAAA,EAAG;AAC9B,UAAA,MAAM,IAAA,GAAO,YAAA,CAAa,OAAA,CAAQ,GAAG,CAAA;AACrC,UAAA,IAAI,IAAA,EAAM;AACR,YAAA,MAAM,QAAA,GAAW,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA;AAChC,YAAA,MAAA,CAAO,QAAA,CAAS,QAAQ,CAAA,GAAI,QAAA;AAAA,UAC9B;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAA,CAAA,MAAQ;AAAA,IAER;AACA,IAAA,OAAO,MAAA;AAAA,EACT,CAAA;AAAA,EACA,aAAA,EAAe,OAAO,QAAA,KAAa;AACjC,IAAA,IAAI,OAAO,MAAA,KAAW,WAAA,IAAe,CAAC,OAAO,YAAA,EAAc;AACzD,MAAA;AAAA,IACF;AACA,IAAA,IAAI;AACF,MAAA,YAAA,CAAa,UAAA,CAAW,CAAA,EAAG,SAAS,CAAA,EAAG,QAAQ,CAAA,CAAE,CAAA;AAAA,IACnD,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACF;AACF,CAAA;AAUO,IAAM,yBAAA,GAA4B,CACvC,YAAA,EAOA,SAAA,GAAoB,kBAAA,MACU;AAAA,EAC9B,YAAA,EAAc,OAAO,QAAA,KAAa;AAChC,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,GAAO,MAAM,YAAA,CAAa,OAAA,CAAQ,GAAG,SAAS,CAAA,EAAG,QAAQ,CAAA,CAAE,CAAA;AACjE,MAAA,OAAO,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA,GAAI,IAAA;AAAA,IACnC,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,IAAA;AAAA,IACT;AAAA,EACF,CAAA;AAAA,EACA,YAAA,EAAc,OAAO,QAAA,KAAa;AAChC,IAAA,IAAI;AACF,MAAA,MAAM,YAAA,CAAa,OAAA;AAAA,QACjB,CAAA,EAAG,SAAS,CAAA,EAAG,QAAA,CAAS,QAAQ,CAAA,CAAA;AAAA,QAChC,IAAA,CAAK,UAAU,QAAQ;AAAA,OACzB;AAAA,IACF,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACF,CAAA;AAAA,EACA,iBAAiB,YAAY;AAC3B,IAAA,MAAM,SAAyC,EAAC;AAChD,IAAA,IAAI;AACF,MAAA,MAAM,OAAA,GAAU,MAAM,YAAA,CAAa,UAAA,EAAW;AAC9C,MAAA,MAAM,YAAA,GAAe,QAAQ,MAAA,CAAO,CAAC,QAAQ,GAAA,CAAI,UAAA,CAAW,SAAS,CAAC,CAAA;AACtE,MAAA,MAAM,KAAA,GAAQ,MAAM,YAAA,CAAa,QAAA,CAAS,YAAY,CAAA;AACtD,MAAA,KAAA,MAAW,GAAG,KAAK,CAAA,IAAK,KAAA,EAAO;AAC7B,QAAA,IAAI,KAAA,EAAO;AACT,UAAA,MAAM,QAAA,GAAW,IAAA,CAAK,KAAA,CAAM,KAAK,CAAA;AACjC,UAAA,MAAA,CAAO,QAAA,CAAS,QAAQ,CAAA,GAAI,QAAA;AAAA,QAC9B;AAAA,MACF;AAAA,IACF,CAAA,CAAA,MAAQ;AAAA,IAER;AACA,IAAA,OAAO,MAAA;AAAA,EACT,CAAA;AAAA,EACA,aAAA,EAAe,OAAO,QAAA,KAAa;AACjC,IAAA,IAAI;AACF,MAAA,MAAM,aAAa,UAAA,CAAW,CAAA,EAAG,SAAS,CAAA,EAAG,QAAQ,CAAA,CAAE,CAAA;AAAA,IACzD,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACF;AACF,CAAA;AAoBO,IAAM,gBAAA,GAAmB,CAC9B,QAAA,KAC6B;AAC7B,EAAA,MAAM,cAAc,iBAAA,EAAkB;AACtC,EAAA,OAAO;AAAA,IACL,YAAA,EAAc,QAAA,CAAS,YAAA,IAAgB,WAAA,CAAY,YAAA;AAAA,IACnD,YAAA,EAAc,QAAA,CAAS,YAAA,IAAgB,WAAA,CAAY,YAAA;AAAA,IACnD,eAAA,EAAiB,QAAA,CAAS,eAAA,IAAmB,WAAA,CAAY,eAAA;AAAA,IACzD,aAAA,EAAe,QAAA,CAAS,aAAA,IAAiB,WAAA,CAAY;AAAA,GACvD;AACF;AAOO,IAAM,sBAAA,GAAyB,CACpC,QAAA,MAC8B;AAAA,EAC9B,YAAA,EAAc,OAAO,QAAA,KAAa;AAChC,IAAA,KAAA,MAAW,WAAW,QAAA,EAAU;AAC9B,MAAA,MAAM,QAAA,GAAW,MAAM,OAAA,CAAQ,YAAA,CAAa,QAAQ,CAAA;AACpD,MAAA,IAAI,UAAU,OAAO,QAAA;AAAA,IACvB;AACA,IAAA,OAAO,IAAA;AAAA,EACT,CAAA;AAAA,EACA,YAAA,EAAc,OAAO,QAAA,KAAa;AAChC,IAAA,MAAM,OAAA,CAAQ,GAAA,CAAI,QAAA,CAAS,GAAA,CAAI,CAAC,YAAY,OAAA,CAAQ,YAAA,CAAa,QAAQ,CAAC,CAAC,CAAA;AAAA,EAC7E,CAAA;AAAA,EACA,iBAAiB,YAAY;AAC3B,IAAA,MAAM,SAAyC,EAAC;AAChD,IAAA,KAAA,MAAW,WAAW,QAAA,EAAU;AAC9B,MAAA,IAAI,QAAQ,eAAA,EAAiB;AAC3B,QAAA,MAAM,IAAA,GAAO,MAAM,OAAA,CAAQ,eAAA,EAAgB;AAC3C,QAAA,MAAA,CAAO,MAAA,CAAO,QAAQ,IAAI,CAAA;AAAA,MAC5B;AAAA,IACF;AACA,IAAA,OAAO,MAAA;AAAA,EACT,CAAA;AAAA,EACA,aAAA,EAAe,OAAO,QAAA,KAAa;AACjC,IAAA,MAAM,OAAA,CAAQ,GAAA;AAAA,MACZ,SAAS,GAAA,CAAI,CAAC,YAAY,OAAA,CAAQ,aAAA,GAAgB,QAAQ,CAAC;AAAA,KAC7D;AAAA,EACF;AACF,CAAA;ACzNO,SAAS,oBAAA,CACd,SACA,QAAA,EACA;AACA,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAI,SAAgC,IAAI,CAAA;AACpE,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAI,SAAS,IAAI,CAAA;AAC/C,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAwB,IAAI,CAAA;AAGtD,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,OAAA,EAAS;AACZ,MAAA,YAAA,CAAa,KAAK,CAAA;AAClB,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,OAAA,GAAU,IAAA;AAEd,IAAA,MAAM,eAAe,YAAY;AAC/B,MAAA,IAAI;AACF,QAAA,YAAA,CAAa,IAAI,CAAA;AACjB,QAAA,QAAA,CAAS,IAAI,CAAA;AACb,QAAA,MAAM,IAAA,GAAO,MAAM,OAAA,CAAQ,YAAA,CAAa,QAAQ,CAAA;AAChD,QAAA,IAAI,OAAA,EAAS;AACX,UAAA,WAAA,CAAY,IAAI,CAAA;AAAA,QAClB;AAAA,MACF,SAAS,GAAA,EAAK;AACZ,QAAA,IAAI,OAAA,EAAS;AACX,UAAA,QAAA,CAAS,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,yBAAyB,CAAA;AAAA,QACzE;AAAA,MACF,CAAA,SAAE;AACA,QAAA,IAAI,OAAA,EAAS;AACX,UAAA,YAAA,CAAa,KAAK,CAAA;AAAA,QACpB;AAAA,MACF;AAAA,IACF,CAAA;AAEA,IAAA,YAAA,EAAa;AAEb,IAAA,OAAO,MAAM;AACX,MAAA,OAAA,GAAU,KAAA;AAAA,IACZ,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,OAAA,EAAS,QAAQ,CAAC,CAAA;AAEtB,EAAA,MAAM,YAAA,GAAe,WAAA;AAAA,IACnB,OAAO,WAAA,KAAkD;AACvD,MAAA,IAAI,CAAC,OAAA,EAAS;AAEd,MAAA,MAAM,YAAA,GAA+B;AAAA,QACnC,GAAG,WAAA;AAAA,QACH;AAAA,OACF;AAEA,MAAA,IAAI;AACF,QAAA,QAAA,CAAS,IAAI,CAAA;AACb,QAAA,MAAM,OAAA,CAAQ,aAAa,YAAY,CAAA;AACvC,QAAA,WAAA,CAAY,YAAY,CAAA;AAAA,MAC1B,SAAS,GAAA,EAAK;AACZ,QAAA,QAAA,CAAS,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,yBAAyB,CAAA;AACvE,QAAA,MAAM,GAAA;AAAA,MACR;AAAA,IACF,CAAA;AAAA,IACA,CAAC,SAAS,QAAQ;AAAA,GACpB;AAEA,EAAA,MAAM,aAAA,GAAgB,YAAY,YAAY;AAC5C,IAAA,IAAI,CAAC,SAAS,aAAA,EAAe;AAE7B,IAAA,IAAI;AACF,MAAA,QAAA,CAAS,IAAI,CAAA;AACb,MAAA,MAAM,OAAA,CAAQ,cAAc,QAAQ,CAAA;AACpC,MAAA,WAAA,CAAY,IAAI,CAAA;AAAA,IAClB,SAAS,GAAA,EAAK;AACZ,MAAA,QAAA,CAAS,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,0BAA0B,CAAA;AACxE,MAAA,MAAM,GAAA;AAAA,IACR;AAAA,EACF,CAAA,EAAG,CAAC,OAAA,EAAS,QAAQ,CAAC,CAAA;AAEtB,EAAA,MAAM,aAAA,GAAgB,YAAY,YAAY;AAC5C,IAAA,MAAM,YAAA,GAAe,UAAU,eAAA,IAAmB,CAAA;AAClD,IAAA,MAAM,YAAA,CAAa;AAAA,MACjB,SAAA,EAAW,IAAA;AAAA,MACX,WAAA,EAAA,iBAAa,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,MACpC,iBAAiB,YAAA,GAAe;AAAA,KACjC,CAAA;AAAA,EACH,CAAA,EAAG,CAAC,YAAA,EAAc,QAAA,EAAU,eAAe,CAAC,CAAA;AAE5C,EAAA,MAAM,cAAA,GAAiB,WAAA;AAAA,IACrB,OAAO,SAAA,KAAsB;AAC3B,MAAA,MAAM,YAAA,CAAa;AAAA,QACjB,SAAA,EAAW,UAAU,SAAA,IAAa,KAAA;AAAA,QAClC,aAAA,EAAe,SAAA;AAAA,QACf,aAAa,QAAA,EAAU,WAAA;AAAA,QACvB,iBAAiB,QAAA,EAAU;AAAA,OAC5B,CAAA;AAAA,IACH,CAAA;AAAA,IACA,CAAC,cAAc,QAAQ;AAAA,GACzB;AAEA,EAAA,OAAO;AAAA,IACL,QAAA;AAAA,IACA,SAAA;AAAA,IACA,KAAA;AAAA,IACA,WAAA,EAAa,UAAU,SAAA,IAAa,KAAA;AAAA,IACpC,YAAY,QAAA,KAAa,IAAA;AAAA,IACzB,YAAA;AAAA,IACA,aAAA;AAAA,IACA,aAAA;AAAA,IACA;AAAA,GACF;AACF;AAKO,SAAS,mBAAA,CACd,OAAA,EACA,QAAA,EACA,OAAA,EAMA;AACA,EAAA,MAAM,EAAE,QAAA,EAAU,SAAA,EAAU,GAAI,oBAAA,CAAqB,SAAS,QAAQ,CAAA;AACtE,EAAA,MAAM,CAAC,UAAA,EAAY,aAAa,CAAA,GAAI,SAAS,KAAK,CAAA;AAClD,EAAA,MAAM,CAAC,UAAA,EAAY,aAAa,CAAA,GAAI,SAAS,IAAI,CAAA;AAEjD,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,SAAA,EAAW;AAEf,IAAA,MAAM,iBAAiB,YAAY;AACjC,MAAA,aAAA,CAAc,IAAI,CAAA;AAGlB,MAAA,IAAI,SAAS,SAAA,EAAW;AACtB,QAAA,aAAA,CAAc,IAAI,CAAA;AAClB,QAAA,aAAA,CAAc,KAAK,CAAA;AACnB,QAAA;AAAA,MACF;AAGA,MAAA,IAAI,UAAU,SAAA,EAAW;AACvB,QAAA,aAAA,CAAc,KAAK,CAAA;AACnB,QAAA,aAAA,CAAc,KAAK,CAAA;AACnB,QAAA;AAAA,MACF;AAGA,MAAA,IAAI,SAAS,mBAAA,EAAqB;AAChC,QAAA,IAAI;AACF,UAAA,MAAM,MAAA,GAAS,MAAM,OAAA,CAAQ,mBAAA,EAAoB;AACjD,UAAA,aAAA,CAAc,MAAM,CAAA;AAAA,QACtB,CAAA,CAAA,MAAQ;AACN,UAAA,aAAA,CAAc,IAAI,CAAA;AAAA,QACpB;AAAA,MACF,CAAA,MAAO;AAEL,QAAA,aAAA,CAAc,IAAI,CAAA;AAAA,MACpB;AAEA,MAAA,aAAA,CAAc,KAAK,CAAA;AAAA,IACrB,CAAA;AAEA,IAAA,cAAA,EAAe;AAAA,EACjB,CAAA,EAAG,CAAC,SAAA,EAAW,QAAA,EAAU,WAAW,OAAA,EAAS,SAAA,EAAW,OAAA,EAAS,mBAAmB,CAAC,CAAA;AAErF,EAAA,OAAO;AAAA,IACL,UAAA;AAAA,IACA,YAAY,SAAA,IAAa,UAAA;AAAA,IACzB,WAAA,EAAa,UAAU,SAAA,IAAa;AAAA,GACtC;AACF","file":"index.mjs","sourcesContent":["import type { GuidonPersistenceAdapter, GuidonProgress } from '../types';\n\nconst STORAGE_KEY_PREFIX = '@guidon:';\n\n/**\n * No-op adapter that doesn't persist anything\n * Useful for testing or when persistence is not needed\n */\nexport const createNoopAdapter = (): GuidonPersistenceAdapter => ({\n loadProgress: async () => null,\n saveProgress: async () => {},\n loadAllProgress: async () => ({}),\n clearProgress: async () => {},\n});\n\n/**\n * Memory adapter that stores progress in memory\n * Data is lost when the app is closed\n */\nexport const createMemoryAdapter = (): GuidonPersistenceAdapter => {\n const store: Record<string, GuidonProgress> = {};\n\n return {\n loadProgress: async (guidonId) => store[guidonId] ?? null,\n saveProgress: async (progress) => {\n store[progress.guidonId] = progress;\n },\n loadAllProgress: async () => ({ ...store }),\n clearProgress: async (guidonId) => {\n delete store[guidonId];\n },\n };\n};\n\n/**\n * localStorage adapter for web\n * Only works in browser environments\n */\nexport const createLocalStorageAdapter = (\n keyPrefix: string = STORAGE_KEY_PREFIX\n): GuidonPersistenceAdapter => ({\n loadProgress: async (guidonId) => {\n if (typeof window === 'undefined' || !window.localStorage) {\n return null;\n }\n try {\n const data = localStorage.getItem(`${keyPrefix}${guidonId}`);\n return data ? JSON.parse(data) : null;\n } catch {\n return null;\n }\n },\n saveProgress: async (progress) => {\n if (typeof window === 'undefined' || !window.localStorage) {\n return;\n }\n try {\n localStorage.setItem(\n `${keyPrefix}${progress.guidonId}`,\n JSON.stringify(progress)\n );\n } catch {\n // Silently fail if storage is full\n }\n },\n loadAllProgress: async () => {\n if (typeof window === 'undefined' || !window.localStorage) {\n return {};\n }\n const result: Record<string, GuidonProgress> = {};\n try {\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i);\n if (key?.startsWith(keyPrefix)) {\n const data = localStorage.getItem(key);\n if (data) {\n const progress = JSON.parse(data) as GuidonProgress;\n result[progress.guidonId] = progress;\n }\n }\n }\n } catch {\n // Silently fail\n }\n return result;\n },\n clearProgress: async (guidonId) => {\n if (typeof window === 'undefined' || !window.localStorage) {\n return;\n }\n try {\n localStorage.removeItem(`${keyPrefix}${guidonId}`);\n } catch {\n // Silently fail\n }\n },\n});\n\n/**\n * AsyncStorage adapter for React Native\n * Requires @react-native-async-storage/async-storage to be installed\n *\n * @example\n * import AsyncStorage from '@react-native-async-storage/async-storage';\n * const adapter = createAsyncStorageAdapter(AsyncStorage);\n */\nexport const createAsyncStorageAdapter = (\n asyncStorage: {\n getItem: (key: string) => Promise<string | null>;\n setItem: (key: string, value: string) => Promise<void>;\n removeItem: (key: string) => Promise<void>;\n getAllKeys: () => Promise<readonly string[]>;\n multiGet: (keys: readonly string[]) => Promise<readonly [string, string | null][]>;\n },\n keyPrefix: string = STORAGE_KEY_PREFIX\n): GuidonPersistenceAdapter => ({\n loadProgress: async (guidonId) => {\n try {\n const data = await asyncStorage.getItem(`${keyPrefix}${guidonId}`);\n return data ? JSON.parse(data) : null;\n } catch {\n return null;\n }\n },\n saveProgress: async (progress) => {\n try {\n await asyncStorage.setItem(\n `${keyPrefix}${progress.guidonId}`,\n JSON.stringify(progress)\n );\n } catch {\n // Silently fail\n }\n },\n loadAllProgress: async () => {\n const result: Record<string, GuidonProgress> = {};\n try {\n const allKeys = await asyncStorage.getAllKeys();\n const relevantKeys = allKeys.filter((key) => key.startsWith(keyPrefix));\n const pairs = await asyncStorage.multiGet(relevantKeys);\n for (const [, value] of pairs) {\n if (value) {\n const progress = JSON.parse(value) as GuidonProgress;\n result[progress.guidonId] = progress;\n }\n }\n } catch {\n // Silently fail\n }\n return result;\n },\n clearProgress: async (guidonId) => {\n try {\n await asyncStorage.removeItem(`${keyPrefix}${guidonId}`);\n } catch {\n // Silently fail\n }\n },\n});\n\n/**\n * Create a custom API adapter for backend persistence\n * This is a factory function that creates an adapter based on your API endpoints\n *\n * @example\n * const adapter = createApiAdapter({\n * loadProgress: async (guidonId) => {\n * const response = await fetch(`/api/guidon/${guidonId}`);\n * return response.json();\n * },\n * saveProgress: async (progress) => {\n * await fetch(`/api/guidon/${progress.guidonId}`, {\n * method: 'POST',\n * body: JSON.stringify(progress),\n * });\n * },\n * });\n */\nexport const createApiAdapter = (\n handlers: Partial<GuidonPersistenceAdapter>\n): GuidonPersistenceAdapter => {\n const noopAdapter = createNoopAdapter();\n return {\n loadProgress: handlers.loadProgress ?? noopAdapter.loadProgress,\n saveProgress: handlers.saveProgress ?? noopAdapter.saveProgress,\n loadAllProgress: handlers.loadAllProgress ?? noopAdapter.loadAllProgress,\n clearProgress: handlers.clearProgress ?? noopAdapter.clearProgress,\n };\n};\n\n/**\n * Combine multiple adapters (e.g., save to both local and API)\n * Loads from the first adapter that returns data\n * Saves to all adapters\n */\nexport const createCompositeAdapter = (\n adapters: GuidonPersistenceAdapter[]\n): GuidonPersistenceAdapter => ({\n loadProgress: async (guidonId) => {\n for (const adapter of adapters) {\n const progress = await adapter.loadProgress(guidonId);\n if (progress) return progress;\n }\n return null;\n },\n saveProgress: async (progress) => {\n await Promise.all(adapters.map((adapter) => adapter.saveProgress(progress)));\n },\n loadAllProgress: async () => {\n const result: Record<string, GuidonProgress> = {};\n for (const adapter of adapters) {\n if (adapter.loadAllProgress) {\n const data = await adapter.loadAllProgress();\n Object.assign(result, data);\n }\n }\n return result;\n },\n clearProgress: async (guidonId) => {\n await Promise.all(\n adapters.map((adapter) => adapter.clearProgress?.(guidonId))\n );\n },\n});\n","import { useCallback, useEffect, useState } from 'react';\nimport type { GuidonPersistenceAdapter, GuidonProgress } from '../types';\n\n/**\n * Hook to manage guidon's walkthrough progress with a persistence adapter\n */\nexport function useGuidonPersistence(\n adapter: GuidonPersistenceAdapter | undefined,\n guidonId: string\n) {\n const [progress, setProgress] = useState<GuidonProgress | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n // Load progress on mount\n useEffect(() => {\n if (!adapter) {\n setIsLoading(false);\n return;\n }\n\n let mounted = true;\n\n const loadProgress = async () => {\n try {\n setIsLoading(true);\n setError(null);\n const data = await adapter.loadProgress(guidonId);\n if (mounted) {\n setProgress(data);\n }\n } catch (err) {\n if (mounted) {\n setError(err instanceof Error ? err.message : 'Failed to load progress');\n }\n } finally {\n if (mounted) {\n setIsLoading(false);\n }\n }\n };\n\n loadProgress();\n\n return () => {\n mounted = false;\n };\n }, [adapter, guidonId]);\n\n const saveProgress = useCallback(\n async (newProgress: Omit<GuidonProgress, 'guidonId'>) => {\n if (!adapter) return;\n\n const fullProgress: GuidonProgress = {\n ...newProgress,\n guidonId,\n };\n\n try {\n setError(null);\n await adapter.saveProgress(fullProgress);\n setProgress(fullProgress);\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to save progress');\n throw err;\n }\n },\n [adapter, guidonId]\n );\n\n const clearProgress = useCallback(async () => {\n if (!adapter?.clearProgress) return;\n\n try {\n setError(null);\n await adapter.clearProgress(guidonId);\n setProgress(null);\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to clear progress');\n throw err;\n }\n }, [adapter, guidonId]);\n\n const markCompleted = useCallback(async () => {\n const currentCount = progress?.completionCount ?? 0;\n await saveProgress({\n completed: true,\n completedAt: new Date().toISOString(),\n completionCount: currentCount + 1,\n });\n }, [saveProgress, progress?.completionCount]);\n\n const markStepViewed = useCallback(\n async (stepIndex: number) => {\n await saveProgress({\n completed: progress?.completed ?? false,\n lastStepIndex: stepIndex,\n completedAt: progress?.completedAt,\n completionCount: progress?.completionCount,\n });\n },\n [saveProgress, progress]\n );\n\n return {\n progress,\n isLoading,\n error,\n isCompleted: progress?.completed ?? false,\n hasStarted: progress !== null,\n saveProgress,\n clearProgress,\n markCompleted,\n markStepViewed,\n };\n}\n\n/**\n * Hook to check if a guidon should be shown\n */\nexport function useShouldShowGuidon(\n adapter: GuidonPersistenceAdapter | undefined,\n guidonId: string,\n options?: {\n /** Show even if completed (for replay) */\n forceShow?: boolean;\n /** Additional condition to check */\n additionalCondition?: () => boolean | Promise<boolean>;\n }\n) {\n const { progress, isLoading } = useGuidonPersistence(adapter, guidonId);\n const [shouldShow, setShouldShow] = useState(false);\n const [isChecking, setIsChecking] = useState(true);\n\n useEffect(() => {\n if (isLoading) return;\n\n const checkCondition = async () => {\n setIsChecking(true);\n\n // If forceShow is true, always show\n if (options?.forceShow) {\n setShouldShow(true);\n setIsChecking(false);\n return;\n }\n\n // If already completed, don't show\n if (progress?.completed) {\n setShouldShow(false);\n setIsChecking(false);\n return;\n }\n\n // Check additional condition if provided\n if (options?.additionalCondition) {\n try {\n const result = await options.additionalCondition();\n setShouldShow(result);\n } catch {\n setShouldShow(true); // Default to showing on error\n }\n } else {\n // Default: show if not completed\n setShouldShow(true);\n }\n\n setIsChecking(false);\n };\n\n checkCondition();\n }, [isLoading, progress?.completed, options?.forceShow, options?.additionalCondition]);\n\n return {\n shouldShow,\n isChecking: isLoading || isChecking,\n isCompleted: progress?.completed ?? false,\n };\n}\n"]}