@makroz/mobile 1.0.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 (232) hide show
  1. package/LICENSE +33 -0
  2. package/README.md +19 -0
  3. package/dist/auth/MkAuthContext.d.ts +72 -0
  4. package/dist/auth/MkAuthContext.d.ts.map +1 -0
  5. package/dist/auth/MkAuthContext.js +19 -0
  6. package/dist/auth/MkAuthContext.js.map +1 -0
  7. package/dist/auth/MkAuthForm.d.ts +31 -0
  8. package/dist/auth/MkAuthForm.d.ts.map +1 -0
  9. package/dist/auth/MkAuthForm.js +180 -0
  10. package/dist/auth/MkAuthForm.js.map +1 -0
  11. package/dist/auth/MkAuthProvider.d.ts +57 -0
  12. package/dist/auth/MkAuthProvider.d.ts.map +1 -0
  13. package/dist/auth/MkAuthProvider.js +282 -0
  14. package/dist/auth/MkAuthProvider.js.map +1 -0
  15. package/dist/auth/secureStorage.d.ts +63 -0
  16. package/dist/auth/secureStorage.d.ts.map +1 -0
  17. package/dist/auth/secureStorage.js +104 -0
  18. package/dist/auth/secureStorage.js.map +1 -0
  19. package/dist/auth/types.d.ts +65 -0
  20. package/dist/auth/types.d.ts.map +1 -0
  21. package/dist/auth/types.js +10 -0
  22. package/dist/auth/types.js.map +1 -0
  23. package/dist/auth/useMkAuth.d.ts +17 -0
  24. package/dist/auth/useMkAuth.d.ts.map +1 -0
  25. package/dist/auth/useMkAuth.js +24 -0
  26. package/dist/auth/useMkAuth.js.map +1 -0
  27. package/dist/components/MkAccordion.d.ts +19 -0
  28. package/dist/components/MkAccordion.d.ts.map +1 -0
  29. package/dist/components/MkAccordion.js +49 -0
  30. package/dist/components/MkAccordion.js.map +1 -0
  31. package/dist/components/MkAlert.d.ts +18 -0
  32. package/dist/components/MkAlert.d.ts.map +1 -0
  33. package/dist/components/MkAlert.js +35 -0
  34. package/dist/components/MkAlert.js.map +1 -0
  35. package/dist/components/MkAvatar.d.ts +12 -0
  36. package/dist/components/MkAvatar.d.ts.map +1 -0
  37. package/dist/components/MkAvatar.js +33 -0
  38. package/dist/components/MkAvatar.js.map +1 -0
  39. package/dist/components/MkBadge.d.ts +11 -0
  40. package/dist/components/MkBadge.d.ts.map +1 -0
  41. package/dist/components/MkBadge.js +22 -0
  42. package/dist/components/MkBadge.js.map +1 -0
  43. package/dist/components/MkButton.d.ts +13 -0
  44. package/dist/components/MkButton.d.ts.map +1 -0
  45. package/dist/components/MkButton.js +53 -0
  46. package/dist/components/MkButton.js.map +1 -0
  47. package/dist/components/MkCard.d.ts +15 -0
  48. package/dist/components/MkCard.d.ts.map +1 -0
  49. package/dist/components/MkCard.js +25 -0
  50. package/dist/components/MkCard.js.map +1 -0
  51. package/dist/components/MkCheck.d.ts +18 -0
  52. package/dist/components/MkCheck.d.ts.map +1 -0
  53. package/dist/components/MkCheck.js +33 -0
  54. package/dist/components/MkCheck.js.map +1 -0
  55. package/dist/components/MkDatePicker.d.ts +30 -0
  56. package/dist/components/MkDatePicker.d.ts.map +1 -0
  57. package/dist/components/MkDatePicker.js +87 -0
  58. package/dist/components/MkDatePicker.js.map +1 -0
  59. package/dist/components/MkDivider.d.ts +11 -0
  60. package/dist/components/MkDivider.d.ts.map +1 -0
  61. package/dist/components/MkDivider.js +28 -0
  62. package/dist/components/MkDivider.js.map +1 -0
  63. package/dist/components/MkDropDown.d.ts +37 -0
  64. package/dist/components/MkDropDown.d.ts.map +1 -0
  65. package/dist/components/MkDropDown.js +82 -0
  66. package/dist/components/MkDropDown.js.map +1 -0
  67. package/dist/components/MkEmptyState.d.ts +11 -0
  68. package/dist/components/MkEmptyState.d.ts.map +1 -0
  69. package/dist/components/MkEmptyState.js +16 -0
  70. package/dist/components/MkEmptyState.js.map +1 -0
  71. package/dist/components/MkFileUpload.d.ts +63 -0
  72. package/dist/components/MkFileUpload.d.ts.map +1 -0
  73. package/dist/components/MkFileUpload.js +80 -0
  74. package/dist/components/MkFileUpload.js.map +1 -0
  75. package/dist/components/MkIcons.d.ts +15 -0
  76. package/dist/components/MkIcons.d.ts.map +1 -0
  77. package/dist/components/MkIcons.js +35 -0
  78. package/dist/components/MkIcons.js.map +1 -0
  79. package/dist/components/MkInfiniteList.d.ts +22 -0
  80. package/dist/components/MkInfiniteList.d.ts.map +1 -0
  81. package/dist/components/MkInfiniteList.js +62 -0
  82. package/dist/components/MkInfiniteList.js.map +1 -0
  83. package/dist/components/MkInput.d.ts +16 -0
  84. package/dist/components/MkInput.d.ts.map +1 -0
  85. package/dist/components/MkInput.js +66 -0
  86. package/dist/components/MkInput.js.map +1 -0
  87. package/dist/components/MkLoading.d.ts +12 -0
  88. package/dist/components/MkLoading.d.ts.map +1 -0
  89. package/dist/components/MkLoading.js +20 -0
  90. package/dist/components/MkLoading.js.map +1 -0
  91. package/dist/components/MkModal.d.ts +20 -0
  92. package/dist/components/MkModal.d.ts.map +1 -0
  93. package/dist/components/MkModal.js +71 -0
  94. package/dist/components/MkModal.js.map +1 -0
  95. package/dist/components/MkProgressBar.d.ts +13 -0
  96. package/dist/components/MkProgressBar.d.ts.map +1 -0
  97. package/dist/components/MkProgressBar.js +27 -0
  98. package/dist/components/MkProgressBar.js.map +1 -0
  99. package/dist/components/MkRadio.d.ts +20 -0
  100. package/dist/components/MkRadio.d.ts.map +1 -0
  101. package/dist/components/MkRadio.js +35 -0
  102. package/dist/components/MkRadio.js.map +1 -0
  103. package/dist/components/MkSearchInput.d.ts +21 -0
  104. package/dist/components/MkSearchInput.d.ts.map +1 -0
  105. package/dist/components/MkSearchInput.js +44 -0
  106. package/dist/components/MkSearchInput.js.map +1 -0
  107. package/dist/components/MkSelect.d.ts +16 -0
  108. package/dist/components/MkSelect.d.ts.map +1 -0
  109. package/dist/components/MkSelect.js +75 -0
  110. package/dist/components/MkSelect.js.map +1 -0
  111. package/dist/components/MkSkeleton.d.ts +13 -0
  112. package/dist/components/MkSkeleton.d.ts.map +1 -0
  113. package/dist/components/MkSkeleton.js +32 -0
  114. package/dist/components/MkSkeleton.js.map +1 -0
  115. package/dist/components/MkSwitch.d.ts +13 -0
  116. package/dist/components/MkSwitch.d.ts.map +1 -0
  117. package/dist/components/MkSwitch.js +68 -0
  118. package/dist/components/MkSwitch.js.map +1 -0
  119. package/dist/components/MkTable.d.ts +39 -0
  120. package/dist/components/MkTable.d.ts.map +1 -0
  121. package/dist/components/MkTable.js +47 -0
  122. package/dist/components/MkTable.js.map +1 -0
  123. package/dist/components/MkTabs.d.ts +19 -0
  124. package/dist/components/MkTabs.d.ts.map +1 -0
  125. package/dist/components/MkTabs.js +38 -0
  126. package/dist/components/MkTabs.js.map +1 -0
  127. package/dist/components/MkTextArea.d.ts +17 -0
  128. package/dist/components/MkTextArea.d.ts.map +1 -0
  129. package/dist/components/MkTextArea.js +18 -0
  130. package/dist/components/MkTextArea.js.map +1 -0
  131. package/dist/components/MkToastRenderer.d.ts +3 -0
  132. package/dist/components/MkToastRenderer.d.ts.map +1 -0
  133. package/dist/components/MkToastRenderer.js +133 -0
  134. package/dist/components/MkToastRenderer.js.map +1 -0
  135. package/dist/components/MkTooltip.d.ts +15 -0
  136. package/dist/components/MkTooltip.d.ts.map +1 -0
  137. package/dist/components/MkTooltip.js +36 -0
  138. package/dist/components/MkTooltip.js.map +1 -0
  139. package/dist/components/MkWindowList.d.ts +47 -0
  140. package/dist/components/MkWindowList.d.ts.map +1 -0
  141. package/dist/components/MkWindowList.js +50 -0
  142. package/dist/components/MkWindowList.js.map +1 -0
  143. package/dist/components/index.d.ts +30 -0
  144. package/dist/components/index.d.ts.map +1 -0
  145. package/dist/components/index.js +33 -0
  146. package/dist/components/index.js.map +1 -0
  147. package/dist/context/MkApiContext.d.ts +15 -0
  148. package/dist/context/MkApiContext.d.ts.map +1 -0
  149. package/dist/context/MkApiContext.js +27 -0
  150. package/dist/context/MkApiContext.js.map +1 -0
  151. package/dist/context/MkAuthContext.d.ts +19 -0
  152. package/dist/context/MkAuthContext.d.ts.map +1 -0
  153. package/dist/context/MkAuthContext.js +86 -0
  154. package/dist/context/MkAuthContext.js.map +1 -0
  155. package/dist/context/MkConfirmContext.d.ts +8 -0
  156. package/dist/context/MkConfirmContext.d.ts.map +1 -0
  157. package/dist/context/MkConfirmContext.js +36 -0
  158. package/dist/context/MkConfirmContext.js.map +1 -0
  159. package/dist/context/MkToastContext.d.ts +19 -0
  160. package/dist/context/MkToastContext.d.ts.map +1 -0
  161. package/dist/context/MkToastContext.js +86 -0
  162. package/dist/context/MkToastContext.js.map +1 -0
  163. package/dist/hooks/filePicker.types.d.ts +13 -0
  164. package/dist/hooks/filePicker.types.d.ts.map +1 -0
  165. package/dist/hooks/filePicker.types.js +7 -0
  166. package/dist/hooks/filePicker.types.js.map +1 -0
  167. package/dist/hooks/useApi.d.ts +19 -0
  168. package/dist/hooks/useApi.d.ts.map +1 -0
  169. package/dist/hooks/useApi.js +78 -0
  170. package/dist/hooks/useApi.js.map +1 -0
  171. package/dist/hooks/useApi.test.d.ts +2 -0
  172. package/dist/hooks/useApi.test.d.ts.map +1 -0
  173. package/dist/hooks/useApi.test.js +10 -0
  174. package/dist/hooks/useApi.test.js.map +1 -0
  175. package/dist/hooks/useMkCrud.d.ts +39 -0
  176. package/dist/hooks/useMkCrud.d.ts.map +1 -0
  177. package/dist/hooks/useMkCrud.js +118 -0
  178. package/dist/hooks/useMkCrud.js.map +1 -0
  179. package/dist/hooks/useMkDebounce.d.ts +24 -0
  180. package/dist/hooks/useMkDebounce.d.ts.map +1 -0
  181. package/dist/hooks/useMkDebounce.js +36 -0
  182. package/dist/hooks/useMkDebounce.js.map +1 -0
  183. package/dist/hooks/useMkEffectDebug.d.ts +6 -0
  184. package/dist/hooks/useMkEffectDebug.d.ts.map +1 -0
  185. package/dist/hooks/useMkEffectDebug.js +23 -0
  186. package/dist/hooks/useMkEffectDebug.js.map +1 -0
  187. package/dist/hooks/useMkEvent.d.ts +42 -0
  188. package/dist/hooks/useMkEvent.d.ts.map +1 -0
  189. package/dist/hooks/useMkEvent.js +49 -0
  190. package/dist/hooks/useMkEvent.js.map +1 -0
  191. package/dist/hooks/useMkFilePickerCli.d.ts +59 -0
  192. package/dist/hooks/useMkFilePickerCli.d.ts.map +1 -0
  193. package/dist/hooks/useMkFilePickerCli.js +68 -0
  194. package/dist/hooks/useMkFilePickerCli.js.map +1 -0
  195. package/dist/hooks/useMkFilePickerExpo.d.ts +38 -0
  196. package/dist/hooks/useMkFilePickerExpo.d.ts.map +1 -0
  197. package/dist/hooks/useMkFilePickerExpo.js +68 -0
  198. package/dist/hooks/useMkFilePickerExpo.js.map +1 -0
  199. package/dist/hooks/useMkForm.d.ts +43 -0
  200. package/dist/hooks/useMkForm.d.ts.map +1 -0
  201. package/dist/hooks/useMkForm.js +115 -0
  202. package/dist/hooks/useMkForm.js.map +1 -0
  203. package/dist/hooks/useMkInfiniteList.d.ts +16 -0
  204. package/dist/hooks/useMkInfiniteList.d.ts.map +1 -0
  205. package/dist/hooks/useMkInfiniteList.js +58 -0
  206. package/dist/hooks/useMkInfiniteList.js.map +1 -0
  207. package/dist/hooks/useMkList.d.ts +61 -0
  208. package/dist/hooks/useMkList.d.ts.map +1 -0
  209. package/dist/hooks/useMkList.js +55 -0
  210. package/dist/hooks/useMkList.js.map +1 -0
  211. package/dist/hooks/useMkLocalStorage.d.ts +6 -0
  212. package/dist/hooks/useMkLocalStorage.d.ts.map +1 -0
  213. package/dist/hooks/useMkLocalStorage.js +28 -0
  214. package/dist/hooks/useMkLocalStorage.js.map +1 -0
  215. package/dist/hooks/useMkPrevious.d.ts +6 -0
  216. package/dist/hooks/useMkPrevious.d.ts.map +1 -0
  217. package/dist/hooks/useMkPrevious.js +13 -0
  218. package/dist/hooks/useMkPrevious.js.map +1 -0
  219. package/dist/hooks/useMkToggle.d.ts +6 -0
  220. package/dist/hooks/useMkToggle.d.ts.map +1 -0
  221. package/dist/hooks/useMkToggle.js +13 -0
  222. package/dist/hooks/useMkToggle.js.map +1 -0
  223. package/dist/index.d.ts +29 -0
  224. package/dist/index.d.ts.map +1 -0
  225. package/dist/index.js +32 -0
  226. package/dist/index.js.map +1 -0
  227. package/dist/theme/MkThemeProvider.d.ts +14 -0
  228. package/dist/theme/MkThemeProvider.d.ts.map +1 -0
  229. package/dist/theme/MkThemeProvider.js +22 -0
  230. package/dist/theme/MkThemeProvider.js.map +1 -0
  231. package/eslint-plugin-mk/index.js +20 -0
  232. package/package.json +66 -0
@@ -0,0 +1,282 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ /**
3
+ * `MkAuthProvider` — the React provider that powers `useMkAuth`.
4
+ *
5
+ * Responsibilities:
6
+ * - Hydrate tokens + user from `expo-secure-store` on mount.
7
+ * - Expose `login`, `logout`, `refresh`, `hasAbility` via context.
8
+ * - Provide a memoised `authedFetch` helper that automatically
9
+ * attaches the access token and refreshes once on 401.
10
+ *
11
+ * Networking note: this provider does NOT use TanStack Query
12
+ * (the mk-director monorepo does not currently declare it as a
13
+ * peer dep). It uses the same plain `fetch`-based pattern that
14
+ * the legacy `useApi.ts` hook uses, so the surface stays
15
+ * consistent across the package. Consumers that need query
16
+ * caching should layer TanStack Query on top of `authedFetch`
17
+ * at the call site.
18
+ */
19
+ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
20
+ import { MkAuthContext } from './MkAuthContext';
21
+ import { clearAll, getAccessToken, getRefreshToken, getUser, setAccessToken, setRefreshToken, setUser, } from './secureStorage';
22
+ /**
23
+ * Normalise the refresh response payload into our internal shape.
24
+ */
25
+ function normaliseRefreshPayload(raw) {
26
+ var _a, _b;
27
+ const accessToken = (_a = raw.access_token) !== null && _a !== void 0 ? _a : raw.accessToken;
28
+ const refreshToken = (_b = raw.refresh_token) !== null && _b !== void 0 ? _b : raw.refreshToken;
29
+ if (!accessToken || !refreshToken) {
30
+ throw new Error('Refresh response missing access or refresh token');
31
+ }
32
+ return { accessToken, refreshToken };
33
+ }
34
+ /**
35
+ * Helper: read both tokens from SecureStore in a single batch.
36
+ */
37
+ async function readPersistedSession() {
38
+ const [access, refresh, user] = await Promise.all([
39
+ getAccessToken(),
40
+ getRefreshToken(),
41
+ getUser(),
42
+ ]);
43
+ return { access, refresh, user };
44
+ }
45
+ /**
46
+ * The provider component.
47
+ *
48
+ * Marked `'use client'` equivalent — RN doesn't use the Next.js
49
+ * `'use client'` directive, but conceptually this component is
50
+ * a Client Component (it owns state, effects, and side effects).
51
+ */
52
+ export function MkAuthProvider({ scope, apiBaseUrl,
53
+ // Accepted for forward-compat; not yet enforced.
54
+ requestTimeoutMs: _requestTimeoutMs = 15000, children, }) {
55
+ const [user, setUserState] = useState(null);
56
+ const [isLoading, setIsLoading] = useState(true);
57
+ const [error, setError] = useState(null);
58
+ // Used to deduplicate concurrent refresh calls: if a 401
59
+ // arrives while a refresh is already in flight, all callers
60
+ // share the same promise instead of each firing a refresh.
61
+ const refreshInFlight = useRef(null);
62
+ // Stable ref to the latest `scope` / `apiBaseUrl` so the
63
+ // `authedFetch` closure doesn't capture stale values.
64
+ const baseUrlRef = useRef(apiBaseUrl);
65
+ const scopeRef = useRef(scope);
66
+ useEffect(() => {
67
+ baseUrlRef.current = apiBaseUrl;
68
+ scopeRef.current = scope;
69
+ }, [apiBaseUrl, scope]);
70
+ const buildUrl = useCallback((path) => {
71
+ const base = baseUrlRef.current.replace(/\/+$/, '');
72
+ const cleanPath = path.startsWith('/') ? path : `/${path}`;
73
+ return `${base}${cleanPath}`;
74
+ }, []);
75
+ // --- internal: refresh ---
76
+ const doRefresh = useCallback(async () => {
77
+ // Coalesce concurrent refresh calls.
78
+ if (refreshInFlight.current) {
79
+ return refreshInFlight.current;
80
+ }
81
+ const promise = (async () => {
82
+ const current = await getRefreshToken();
83
+ if (!current) {
84
+ return null;
85
+ }
86
+ try {
87
+ const res = await fetch(buildUrl(`/api/${scopeRef.current}/auth/refresh`), {
88
+ method: 'POST',
89
+ headers: { 'Content-Type': 'application/json' },
90
+ body: JSON.stringify({ refreshToken: current }),
91
+ });
92
+ if (!res.ok) {
93
+ return null;
94
+ }
95
+ const raw = (await res.json());
96
+ const tokens = normaliseRefreshPayload(raw);
97
+ await Promise.all([
98
+ setAccessToken(tokens.accessToken),
99
+ setRefreshToken(tokens.refreshToken),
100
+ ]);
101
+ if (raw.user) {
102
+ await setUser(raw.user);
103
+ setUserState(raw.user);
104
+ }
105
+ return tokens;
106
+ }
107
+ catch (_a) {
108
+ return null;
109
+ }
110
+ })();
111
+ refreshInFlight.current = promise;
112
+ try {
113
+ return await promise;
114
+ }
115
+ finally {
116
+ refreshInFlight.current = null;
117
+ }
118
+ }, [buildUrl]);
119
+ // --- mount: hydrate from SecureStore ---
120
+ useEffect(() => {
121
+ let cancelled = false;
122
+ void (async () => {
123
+ setIsLoading(true);
124
+ try {
125
+ const persisted = await readPersistedSession();
126
+ if (cancelled)
127
+ return;
128
+ if (persisted.user) {
129
+ // We have a user in SecureStore — trust it
130
+ // until a 401 proves otherwise. The actual
131
+ // /me check happens lazily on the first
132
+ // authed request, which keeps the cold-start
133
+ // path fast.
134
+ setUserState(persisted.user);
135
+ }
136
+ if (!persisted.access && persisted.refresh) {
137
+ // Access token missing but refresh token is
138
+ // present — try to silently mint a new one.
139
+ const tokens = await doRefresh();
140
+ if (cancelled)
141
+ return;
142
+ if (!tokens) {
143
+ await clearAll();
144
+ setUserState(null);
145
+ }
146
+ }
147
+ else if (!persisted.access && !persisted.refresh) {
148
+ setUserState(null);
149
+ }
150
+ }
151
+ catch (e) {
152
+ if (cancelled)
153
+ return;
154
+ setError(e instanceof Error ? e : new Error(String(e)));
155
+ }
156
+ finally {
157
+ if (!cancelled) {
158
+ setIsLoading(false);
159
+ }
160
+ }
161
+ })();
162
+ return () => {
163
+ cancelled = true;
164
+ };
165
+ }, [doRefresh]);
166
+ // --- login ---
167
+ const login = useCallback(async (input) => {
168
+ var _a, _b;
169
+ setIsLoading(true);
170
+ setError(null);
171
+ try {
172
+ const res = await fetch(buildUrl(`/api/${scopeRef.current}/auth/login`), {
173
+ method: 'POST',
174
+ headers: { 'Content-Type': 'application/json' },
175
+ body: JSON.stringify(input),
176
+ });
177
+ if (!res.ok) {
178
+ // Try to extract a structured error message
179
+ // from the backend; fall back to status text.
180
+ let message = `Login failed (${res.status})`;
181
+ try {
182
+ const body = (await res.json());
183
+ if (body.message) {
184
+ message = body.message;
185
+ }
186
+ else if (body.errors) {
187
+ const firstField = Object.values(body.errors)[0];
188
+ if (firstField && firstField[0]) {
189
+ message = firstField[0];
190
+ }
191
+ }
192
+ }
193
+ catch (_c) {
194
+ // Body wasn't JSON — keep the generic message.
195
+ }
196
+ throw new Error(message);
197
+ }
198
+ const body = (await res.json());
199
+ const accessToken = (_a = body.access_token) !== null && _a !== void 0 ? _a : body.accessToken;
200
+ const refreshToken = (_b = body.refresh_token) !== null && _b !== void 0 ? _b : body.refreshToken;
201
+ if (!accessToken || !refreshToken) {
202
+ throw new Error('Login response missing tokens');
203
+ }
204
+ await Promise.all([
205
+ setAccessToken(accessToken),
206
+ setRefreshToken(refreshToken),
207
+ setUser(body.user),
208
+ ]);
209
+ setUserState(body.user);
210
+ return body.user;
211
+ }
212
+ catch (e) {
213
+ const err = e instanceof Error ? e : new Error(String(e));
214
+ setError(err);
215
+ throw err;
216
+ }
217
+ finally {
218
+ setIsLoading(false);
219
+ }
220
+ }, [buildUrl]);
221
+ // --- logout ---
222
+ const logout = useCallback(async () => {
223
+ // Best-effort: tell the backend, then ALWAYS wipe local state.
224
+ const access = await getAccessToken();
225
+ try {
226
+ if (access) {
227
+ await fetch(buildUrl(`/api/${scopeRef.current}/auth/logout`), {
228
+ method: 'POST',
229
+ headers: {
230
+ 'Content-Type': 'application/json',
231
+ Authorization: `Bearer ${access}`,
232
+ },
233
+ });
234
+ }
235
+ }
236
+ catch (_a) {
237
+ // Backend unreachable — continue with local cleanup.
238
+ }
239
+ await clearAll();
240
+ setUserState(null);
241
+ setError(null);
242
+ }, [buildUrl]);
243
+ // --- hasAbility ---
244
+ const hasAbility = useCallback((ability) => {
245
+ var _a;
246
+ if (!((_a = user === null || user === void 0 ? void 0 : user.role) === null || _a === void 0 ? void 0 : _a.abilities)) {
247
+ return false;
248
+ }
249
+ // The `abilities` string is pipe-delimited:
250
+ // "users:CRUD|roles:R"
251
+ // A user "has" the ability if any entry matches
252
+ // either exactly or as a prefix (`ability:...`).
253
+ const entries = user.role.abilities.split('|');
254
+ return entries.some((entry) => {
255
+ const [name] = entry.split(':');
256
+ return name === ability;
257
+ });
258
+ }, [user]);
259
+ // --- public refresh wrapper ---
260
+ const refresh = useCallback(async () => {
261
+ const tokens = await doRefresh();
262
+ if (!tokens) {
263
+ // Refresh failed → the user is effectively logged out.
264
+ await clearAll();
265
+ setUserState(null);
266
+ }
267
+ return tokens;
268
+ }, [doRefresh]);
269
+ const value = useMemo(() => ({
270
+ user,
271
+ isAuthenticated: user !== null,
272
+ isLoading,
273
+ error,
274
+ login,
275
+ logout,
276
+ refresh,
277
+ hasAbility,
278
+ }), [user, isLoading, error, login, logout, refresh, hasAbility]);
279
+ return _jsx(MkAuthContext.Provider, { value: value, children: children });
280
+ }
281
+ export default MkAuthProvider;
282
+ //# sourceMappingURL=MkAuthProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MkAuthProvider.js","sourceRoot":"","sources":["../../src/auth/MkAuthProvider.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Thin wrapper around `expo-secure-store` for credentials.
3
+ *
4
+ * IMPORTANT: This module is the SOLE place in `@mk/mobile` that
5
+ * touches persistent credential storage. Do NOT introduce
6
+ * `AsyncStorage` for tokens — they are credentials and must live in
7
+ * the device keychain (iOS) / Keystore (Android).
8
+ *
9
+ * The module imports `expo-secure-store` at the top level so the
10
+ * Vitest test suite can `vi.mock('expo-secure-store', ...)` to
11
+ * substitute an in-memory implementation.
12
+ */
13
+ import type { AdminDto } from './types';
14
+ /**
15
+ * SecureStore keys. Keep these stable — they are part of the
16
+ * on-disk schema. If you ever need to bump them (e.g. for a
17
+ * breaking schema change) use a migration rather than a rename.
18
+ */
19
+ export declare const SECURE_KEYS: {
20
+ readonly accessToken: "access_token";
21
+ readonly refreshToken: "refresh_token";
22
+ readonly user: "user";
23
+ };
24
+ export type SecureKey = (typeof SECURE_KEYS)[keyof typeof SECURE_KEYS];
25
+ /**
26
+ * Get the persisted access token, or `null` if none is stored
27
+ * or the store is unavailable (e.g. running in a test that
28
+ * mocked `expo-secure-store` without a backing map).
29
+ */
30
+ export declare function getAccessToken(): Promise<string | null>;
31
+ /**
32
+ * Persist the access token. `null` clears it.
33
+ */
34
+ export declare function setAccessToken(token: string | null): Promise<void>;
35
+ /**
36
+ * Get the persisted refresh token, or `null` if none is stored.
37
+ */
38
+ export declare function getRefreshToken(): Promise<string | null>;
39
+ /**
40
+ * Persist the refresh token. `null` clears it.
41
+ */
42
+ export declare function setRefreshToken(token: string | null): Promise<void>;
43
+ /**
44
+ * Get the persisted admin user, or `null` if none is stored.
45
+ *
46
+ * The user is JSON-serialised — SecureStore stores strings only.
47
+ */
48
+ export declare function getUser(): Promise<AdminDto | null>;
49
+ /**
50
+ * Persist the admin user. `null` clears it.
51
+ */
52
+ export declare function setUser(user: AdminDto | null): Promise<void>;
53
+ /**
54
+ * Wipe all three credential keys. Called on logout and on any
55
+ * unrecoverable refresh failure.
56
+ *
57
+ * The implementation is best-effort: a single failed `deleteItemAsync`
58
+ * is swallowed because the *next* successful login will overwrite
59
+ * the value anyway, and we don't want a transient SecureStore
60
+ * hiccup to brick the user out of the app.
61
+ */
62
+ export declare function clearAll(): Promise<void>;
63
+ //# sourceMappingURL=secureStorage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secureStorage.d.ts","sourceRoot":"","sources":["../../src/auth/secureStorage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAExC;;;;GAIG;AACH,eAAO,MAAM,WAAW;;;;CAId,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,OAAO,WAAW,CAAC,CAAC;AAEvE;;;;GAIG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAE7D;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAMxE;AAED;;GAEG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAE9D;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAMzE;AAED;;;;GAIG;AACH,wBAAsB,OAAO,IAAI,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAaxD;AAED;;GAEG;AACH,wBAAsB,OAAO,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAMlE;AAED;;;;;;;;GAQG;AACH,wBAAsB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAM9C"}
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Thin wrapper around `expo-secure-store` for credentials.
3
+ *
4
+ * IMPORTANT: This module is the SOLE place in `@mk/mobile` that
5
+ * touches persistent credential storage. Do NOT introduce
6
+ * `AsyncStorage` for tokens — they are credentials and must live in
7
+ * the device keychain (iOS) / Keystore (Android).
8
+ *
9
+ * The module imports `expo-secure-store` at the top level so the
10
+ * Vitest test suite can `vi.mock('expo-secure-store', ...)` to
11
+ * substitute an in-memory implementation.
12
+ */
13
+ import * as SecureStore from 'expo-secure-store';
14
+ /**
15
+ * SecureStore keys. Keep these stable — they are part of the
16
+ * on-disk schema. If you ever need to bump them (e.g. for a
17
+ * breaking schema change) use a migration rather than a rename.
18
+ */
19
+ export const SECURE_KEYS = {
20
+ accessToken: 'access_token',
21
+ refreshToken: 'refresh_token',
22
+ user: 'user',
23
+ };
24
+ /**
25
+ * Get the persisted access token, or `null` if none is stored
26
+ * or the store is unavailable (e.g. running in a test that
27
+ * mocked `expo-secure-store` without a backing map).
28
+ */
29
+ export async function getAccessToken() {
30
+ return SecureStore.getItemAsync(SECURE_KEYS.accessToken);
31
+ }
32
+ /**
33
+ * Persist the access token. `null` clears it.
34
+ */
35
+ export async function setAccessToken(token) {
36
+ if (token === null) {
37
+ await SecureStore.deleteItemAsync(SECURE_KEYS.accessToken);
38
+ return;
39
+ }
40
+ await SecureStore.setItemAsync(SECURE_KEYS.accessToken, token);
41
+ }
42
+ /**
43
+ * Get the persisted refresh token, or `null` if none is stored.
44
+ */
45
+ export async function getRefreshToken() {
46
+ return SecureStore.getItemAsync(SECURE_KEYS.refreshToken);
47
+ }
48
+ /**
49
+ * Persist the refresh token. `null` clears it.
50
+ */
51
+ export async function setRefreshToken(token) {
52
+ if (token === null) {
53
+ await SecureStore.deleteItemAsync(SECURE_KEYS.refreshToken);
54
+ return;
55
+ }
56
+ await SecureStore.setItemAsync(SECURE_KEYS.refreshToken, token);
57
+ }
58
+ /**
59
+ * Get the persisted admin user, or `null` if none is stored.
60
+ *
61
+ * The user is JSON-serialised — SecureStore stores strings only.
62
+ */
63
+ export async function getUser() {
64
+ const raw = await SecureStore.getItemAsync(SECURE_KEYS.user);
65
+ if (!raw) {
66
+ return null;
67
+ }
68
+ try {
69
+ return JSON.parse(raw);
70
+ }
71
+ catch (_a) {
72
+ // Corrupt payload — treat as a missing user so the next
73
+ // login flow can recover.
74
+ await SecureStore.deleteItemAsync(SECURE_KEYS.user);
75
+ return null;
76
+ }
77
+ }
78
+ /**
79
+ * Persist the admin user. `null` clears it.
80
+ */
81
+ export async function setUser(user) {
82
+ if (user === null) {
83
+ await SecureStore.deleteItemAsync(SECURE_KEYS.user);
84
+ return;
85
+ }
86
+ await SecureStore.setItemAsync(SECURE_KEYS.user, JSON.stringify(user));
87
+ }
88
+ /**
89
+ * Wipe all three credential keys. Called on logout and on any
90
+ * unrecoverable refresh failure.
91
+ *
92
+ * The implementation is best-effort: a single failed `deleteItemAsync`
93
+ * is swallowed because the *next* successful login will overwrite
94
+ * the value anyway, and we don't want a transient SecureStore
95
+ * hiccup to brick the user out of the app.
96
+ */
97
+ export async function clearAll() {
98
+ await Promise.allSettled([
99
+ SecureStore.deleteItemAsync(SECURE_KEYS.accessToken),
100
+ SecureStore.deleteItemAsync(SECURE_KEYS.refreshToken),
101
+ SecureStore.deleteItemAsync(SECURE_KEYS.user),
102
+ ]);
103
+ }
104
+ //# sourceMappingURL=secureStorage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secureStorage.js","sourceRoot":"","sources":["../../src/auth/secureStorage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,WAAW,MAAM,mBAAmB,CAAC;AAGjD;;;;GAIG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG;IACvB,WAAW,EAAE,cAAc;IAC3B,YAAY,EAAE,eAAe;IAC7B,IAAI,EAAE,MAAM;CACN,CAAC;AAIX;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc;IAChC,OAAO,WAAW,CAAC,YAAY,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;AAC7D,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,KAAoB;IACrD,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACjB,MAAM,WAAW,CAAC,eAAe,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;QAC3D,OAAO;IACX,CAAC;IACD,MAAM,WAAW,CAAC,YAAY,CAAC,WAAW,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;AACnE,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe;IACjC,OAAO,WAAW,CAAC,YAAY,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC;AAC9D,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,KAAoB;IACtD,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACjB,MAAM,WAAW,CAAC,eAAe,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC;QAC5D,OAAO;IACX,CAAC;IACD,MAAM,WAAW,CAAC,YAAY,CAAC,WAAW,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;AACpE,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO;IACzB,MAAM,GAAG,GAAG,MAAM,WAAW,CAAC,YAAY,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IAC7D,IAAI,CAAC,GAAG,EAAE,CAAC;QACP,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,IAAI,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAa,CAAC;IACvC,CAAC;IAAC,WAAM,CAAC;QACL,wDAAwD;QACxD,0BAA0B;QAC1B,MAAM,WAAW,CAAC,eAAe,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QACpD,OAAO,IAAI,CAAC;IAChB,CAAC;AACL,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAAqB;IAC/C,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAChB,MAAM,WAAW,CAAC,eAAe,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QACpD,OAAO;IACX,CAAC;IACD,MAAM,WAAW,CAAC,YAAY,CAAC,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;AAC3E,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ;IAC1B,MAAM,OAAO,CAAC,UAAU,CAAC;QACrB,WAAW,CAAC,eAAe,CAAC,WAAW,CAAC,WAAW,CAAC;QACpD,WAAW,CAAC,eAAe,CAAC,WAAW,CAAC,YAAY,CAAC;QACrD,WAAW,CAAC,eAAe,CAAC,WAAW,CAAC,IAAI,CAAC;KAChD,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Auth types for `@mk/mobile`.
3
+ *
4
+ * Wire-format DTOs returned by the MK-Director backend
5
+ * (e.g. Laravel `mk-laravel` package). Keep these decoupled from
6
+ * the existing `MkUser` in `@mk/core` — this is the new
7
+ * SecureStore-backed auth surface introduced in MK-MOB-1.0.3.
8
+ */
9
+ /**
10
+ * Standard admin record as returned by `/api/{scope}/auth/me` and friends.
11
+ *
12
+ * `abilities` is a pipe-delimited string in the format
13
+ * `"users:CRUD|roles:R"` — the same convention the legacy
14
+ * `MkAuthContext` uses via `canUser` from `@mk/core`.
15
+ */
16
+ export interface AdminDto {
17
+ id: string | number;
18
+ name: string;
19
+ email: string;
20
+ role?: {
21
+ name: string;
22
+ abilities: string;
23
+ };
24
+ [key: string]: unknown;
25
+ }
26
+ /**
27
+ * Access + refresh token pair persisted in `expo-secure-store`.
28
+ *
29
+ * - `accessToken` is short-lived (15 min) and sent on every API request.
30
+ * - `refreshToken` is long-lived and only used by the auto-refresh
31
+ * interceptor inside `MkAuthProvider`.
32
+ */
33
+ export interface AuthTokens {
34
+ accessToken: string;
35
+ refreshToken: string;
36
+ }
37
+ /**
38
+ * Payload accepted by `POST /api/{scope}/auth/login`.
39
+ *
40
+ * The `scope` itself comes from the provider props, NOT the body,
41
+ * so this is just the user-supplied credentials.
42
+ */
43
+ export interface LoginInput {
44
+ email: string;
45
+ password: string;
46
+ }
47
+ /**
48
+ * Internal representation of the refresh-token response.
49
+ *
50
+ * Mirrors the wire shape returned by the Laravel `refresh` endpoint.
51
+ */
52
+ export interface RefreshResponse {
53
+ accessToken: string;
54
+ refreshToken: string;
55
+ user?: AdminDto;
56
+ }
57
+ /**
58
+ * Internal representation of the login response.
59
+ */
60
+ export interface LoginResponse {
61
+ user: AdminDto;
62
+ accessToken: string;
63
+ refreshToken: string;
64
+ }
65
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;;;;;GAMG;AACH,MAAM,WAAW,QAAQ;IACrB,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE;QACH,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;KACrB,CAAC;IACF,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CAC1B;AAED;;;;;;GAMG;AACH,MAAM,WAAW,UAAU;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACxB;AAED;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,QAAQ,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC1B,IAAI,EAAE,QAAQ,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACxB"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Auth types for `@mk/mobile`.
3
+ *
4
+ * Wire-format DTOs returned by the MK-Director backend
5
+ * (e.g. Laravel `mk-laravel` package). Keep these decoupled from
6
+ * the existing `MkUser` in `@mk/core` — this is the new
7
+ * SecureStore-backed auth surface introduced in MK-MOB-1.0.3.
8
+ */
9
+ export {};
10
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * `useMkAuth` — the public hook for consuming the auth context.
3
+ *
4
+ * Kept in its own module so the *type* of the context (and the
5
+ * `createContext` call) can be imported in isolation by tests
6
+ * and tooling without dragging in the full provider tree.
7
+ */
8
+ import { type MkAuthContextValue } from './MkAuthContext';
9
+ /**
10
+ * Access the current auth context value.
11
+ *
12
+ * Throws if used outside an `<MkAuthProvider>` — this is a
13
+ * developer error, not a runtime condition, so failing loudly
14
+ * is the right call.
15
+ */
16
+ export declare function useMkAuth(): MkAuthContextValue;
17
+ //# sourceMappingURL=useMkAuth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useMkAuth.d.ts","sourceRoot":"","sources":["../../src/auth/useMkAuth.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAiB,KAAK,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAEzE;;;;;;GAMG;AACH,wBAAgB,SAAS,IAAI,kBAAkB,CAM9C"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * `useMkAuth` — the public hook for consuming the auth context.
3
+ *
4
+ * Kept in its own module so the *type* of the context (and the
5
+ * `createContext` call) can be imported in isolation by tests
6
+ * and tooling without dragging in the full provider tree.
7
+ */
8
+ import { useContext } from 'react';
9
+ import { MkAuthContext } from './MkAuthContext';
10
+ /**
11
+ * Access the current auth context value.
12
+ *
13
+ * Throws if used outside an `<MkAuthProvider>` — this is a
14
+ * developer error, not a runtime condition, so failing loudly
15
+ * is the right call.
16
+ */
17
+ export function useMkAuth() {
18
+ const ctx = useContext(MkAuthContext);
19
+ if (!ctx) {
20
+ throw new Error('useMkAuth must be used within an <MkAuthProvider>');
21
+ }
22
+ return ctx;
23
+ }
24
+ //# sourceMappingURL=useMkAuth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useMkAuth.js","sourceRoot":"","sources":["../../src/auth/useMkAuth.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AACnC,OAAO,EAAE,aAAa,EAA2B,MAAM,iBAAiB,CAAC;AAEzE;;;;;;GAMG;AACH,MAAM,UAAU,SAAS;IACrB,MAAM,GAAG,GAAG,UAAU,CAAC,aAAa,CAAC,CAAC;IACtC,IAAI,CAAC,GAAG,EAAE,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACzE,CAAC;IACD,OAAO,GAAG,CAAC;AACf,CAAC"}
@@ -0,0 +1,19 @@
1
+ import React from 'react';
2
+ import type { ViewStyle } from 'react-native';
3
+ export interface MkAccordionItem {
4
+ key: string;
5
+ title: string;
6
+ content: React.ReactNode;
7
+ disabled?: boolean;
8
+ }
9
+ export interface MkAccordionProps {
10
+ items: MkAccordionItem[];
11
+ multiple?: boolean;
12
+ defaultExpanded?: string[];
13
+ expanded?: string[];
14
+ onChange?: (expandedKeys: string[]) => void;
15
+ variant?: 'default' | 'bordered' | 'separated';
16
+ style?: ViewStyle;
17
+ }
18
+ export declare const MkAccordion: React.FC<MkAccordionProps>;
19
+ //# sourceMappingURL=MkAccordion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MkAccordion.d.ts","sourceRoot":"","sources":["../../src/components/MkAccordion.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAgC,MAAM,OAAO,CAAC;AACrD,OAAO,KAAK,EAAE,SAAS,EAAC,MAAM,cAAc,CAAC;AAU7C,MAAM,WAAW,eAAe;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC7B,KAAK,EAAE,eAAe,EAAE,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,QAAQ,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IAC5C,OAAO,CAAC,EAAE,SAAS,GAAG,UAAU,GAAG,WAAW,CAAC;IAC/C,KAAK,CAAC,EAAE,SAAS,CAAC;CACrB;AAED,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CAqElD,CAAC"}