@flamingo-stack/openframe-frontend-core 0.0.263 → 0.0.264

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 (68) hide show
  1. package/dist/{chunk-C3FAOQAH.cjs → chunk-3LWUHLPK.cjs} +28 -28
  2. package/dist/{chunk-C3FAOQAH.cjs.map → chunk-3LWUHLPK.cjs.map} +1 -1
  3. package/dist/{chunk-U7UDESAU.js → chunk-6ZEKKAAL.js} +2 -2
  4. package/dist/{chunk-YC357BPF.js → chunk-JOUI6TQY.js} +3 -3
  5. package/dist/{chunk-2XUWR7AH.cjs → chunk-P67D545X.cjs} +11 -11
  6. package/dist/{chunk-2XUWR7AH.cjs.map → chunk-P67D545X.cjs.map} +1 -1
  7. package/dist/{chunk-3DC6MHW6.cjs → chunk-QLWBBCI5.cjs} +491 -391
  8. package/dist/chunk-QLWBBCI5.cjs.map +1 -0
  9. package/dist/{chunk-36HLBLDK.cjs → chunk-SIYHXLFH.cjs} +462 -454
  10. package/dist/chunk-SIYHXLFH.cjs.map +1 -0
  11. package/dist/{chunk-ALEKX56R.js → chunk-SSUUMPAQ.js} +2 -2
  12. package/dist/{chunk-6AIXHYBZ.js → chunk-VYTU7JZR.js} +64 -56
  13. package/dist/chunk-VYTU7JZR.js.map +1 -0
  14. package/dist/{chunk-6GBA6YJN.js → chunk-ZMFT5XOB.js} +576 -476
  15. package/dist/chunk-ZMFT5XOB.js.map +1 -0
  16. package/dist/{chunk-XKA7UFED.cjs → chunk-ZOOTBYZO.cjs} +30 -30
  17. package/dist/{chunk-XKA7UFED.cjs.map → chunk-ZOOTBYZO.cjs.map} +1 -1
  18. package/dist/components/chat/index.cjs +3 -3
  19. package/dist/components/chat/index.js +2 -2
  20. package/dist/components/contact/index.cjs +4 -4
  21. package/dist/components/contact/index.js +3 -3
  22. package/dist/components/features/index.cjs +3 -3
  23. package/dist/components/features/index.js +2 -2
  24. package/dist/components/features/notifications/notification-drawer.d.ts.map +1 -1
  25. package/dist/components/features/notifications/notifications-context.d.ts +9 -1
  26. package/dist/components/features/notifications/notifications-context.d.ts.map +1 -1
  27. package/dist/components/index.cjs +50 -50
  28. package/dist/components/index.js +4 -4
  29. package/dist/components/navigation/index.cjs +3 -3
  30. package/dist/components/navigation/index.js +2 -2
  31. package/dist/components/navigation/sliding-sidebar.d.ts.map +1 -1
  32. package/dist/components/related-content/index.cjs +4 -4
  33. package/dist/components/related-content/index.js +3 -3
  34. package/dist/components/tickets/index.cjs +58 -58
  35. package/dist/components/tickets/index.js +4 -4
  36. package/dist/components/ui/drawer.d.ts +5 -0
  37. package/dist/components/ui/drawer.d.ts.map +1 -1
  38. package/dist/components/ui/index.cjs +3 -3
  39. package/dist/components/ui/index.js +2 -2
  40. package/dist/hooks/index.cjs +6 -2
  41. package/dist/hooks/index.cjs.map +1 -1
  42. package/dist/hooks/index.js +5 -1
  43. package/dist/hooks/ui/index.d.ts +6 -4
  44. package/dist/hooks/ui/index.d.ts.map +1 -1
  45. package/dist/hooks/ui/use-header-height.d.ts +8 -0
  46. package/dist/hooks/ui/use-header-height.d.ts.map +1 -0
  47. package/dist/hooks/ui/use-horizontal-scrollbar.d.ts.map +1 -1
  48. package/dist/hooks/ui/use-notification-permission.d.ts +14 -0
  49. package/dist/hooks/ui/use-notification-permission.d.ts.map +1 -0
  50. package/dist/index.cjs +7 -3
  51. package/dist/index.cjs.map +1 -1
  52. package/dist/index.js +6 -2
  53. package/package.json +1 -1
  54. package/src/components/features/notifications/notification-drawer.tsx +51 -2
  55. package/src/components/features/notifications/notifications-context.tsx +26 -0
  56. package/src/components/navigation/sliding-sidebar.tsx +3 -82
  57. package/src/components/ui/drawer.tsx +17 -6
  58. package/src/hooks/ui/index.ts +6 -4
  59. package/src/hooks/ui/use-header-height.ts +55 -0
  60. package/src/hooks/ui/use-horizontal-scrollbar.ts +19 -2
  61. package/src/hooks/ui/use-notification-permission.ts +64 -0
  62. package/dist/chunk-36HLBLDK.cjs.map +0 -1
  63. package/dist/chunk-3DC6MHW6.cjs.map +0 -1
  64. package/dist/chunk-6AIXHYBZ.js.map +0 -1
  65. package/dist/chunk-6GBA6YJN.js.map +0 -1
  66. /package/dist/{chunk-U7UDESAU.js.map → chunk-6ZEKKAAL.js.map} +0 -0
  67. /package/dist/{chunk-YC357BPF.js.map → chunk-JOUI6TQY.js.map} +0 -0
  68. /package/dist/{chunk-ALEKX56R.js.map → chunk-SSUUMPAQ.js.map} +0 -0
@@ -33,373 +33,65 @@ import {
33
33
  XmarkIcon
34
34
  } from "./chunk-4WZOFD46.js";
35
35
 
36
- // src/hooks/ui/use-local-storage.ts
37
- import { useEffect, useRef, useState } from "react";
38
- function useLocalStorage(key, initialValue) {
39
- const [storedValue, setStoredValue] = useState(() => {
40
- try {
41
- if (typeof window !== "undefined") {
42
- const item = window.localStorage.getItem(key);
43
- return item ? JSON.parse(item) : initialValue;
44
- }
45
- } catch (error) {
46
- console.error(`Error reading localStorage key "${key}":`, error);
47
- }
48
- return initialValue;
49
- });
50
- const isInitialized = useRef(true);
51
- const isFromStorageEvent = useRef(false);
36
+ // src/hooks/ui/use-header-height.ts
37
+ import { useEffect, useState } from "react";
38
+ function useHeaderHeight(defaultHeight = 64) {
39
+ const [height, setHeight] = useState(defaultHeight);
52
40
  useEffect(() => {
53
- if (!isInitialized.current) return;
54
- const handleStorageChange = (e) => {
55
- if (e.key === key && e.newValue !== null) {
56
- try {
57
- const newValue = JSON.parse(e.newValue);
58
- isFromStorageEvent.current = true;
59
- setStoredValue(newValue);
60
- console.log(`\u{1F504} Updated localStorage key "${key}" from storage event`);
61
- } catch (error) {
62
- console.error(`Error parsing storage event for key "${key}":`, error);
63
- }
64
- }
41
+ const measure = () => {
42
+ let total = 0;
43
+ const header2 = document.querySelector("header");
44
+ if (header2) total += header2.offsetHeight;
45
+ const bar2 = document.querySelector("[data-announcement-bar]");
46
+ if (bar2 instanceof HTMLElement) total += bar2.offsetHeight;
47
+ setHeight(total > 0 ? total : defaultHeight);
65
48
  };
66
- const handleCustomStorageUpdate = (e) => {
67
- if (e.detail.key === key) {
68
- try {
69
- if (e.detail.newValue === null || e.detail.newValue === void 0) {
70
- isFromStorageEvent.current = true;
71
- setStoredValue(initialValue);
72
- console.log(`\u{1F504} Cleared localStorage key "${key}" from custom storage event`);
73
- } else {
74
- const newValue = JSON.parse(e.detail.newValue);
75
- isFromStorageEvent.current = true;
76
- setStoredValue(newValue);
77
- console.log(`\u{1F504} Updated localStorage key "${key}" from custom storage event`);
78
- }
79
- } catch (error) {
80
- console.error(`Error parsing custom storage event for key "${key}":`, error);
49
+ measure();
50
+ const resizeObserver = new ResizeObserver(measure);
51
+ const header = document.querySelector("header");
52
+ if (header) resizeObserver.observe(header);
53
+ const bar = document.querySelector("[data-announcement-bar]");
54
+ if (bar) resizeObserver.observe(bar);
55
+ const mutationObserver = new MutationObserver((mutations) => {
56
+ for (const mutation of mutations) {
57
+ if (mutation.type === "childList" || mutation.type === "attributes") {
58
+ measure();
59
+ const newBar = document.querySelector("[data-announcement-bar]");
60
+ if (newBar) resizeObserver.observe(newBar);
81
61
  }
82
62
  }
83
- };
84
- window.addEventListener("storage", handleStorageChange);
85
- window.addEventListener("localStorageUpdate", handleCustomStorageUpdate);
86
- return () => {
87
- window.removeEventListener("storage", handleStorageChange);
88
- window.removeEventListener("localStorageUpdate", handleCustomStorageUpdate);
89
- };
90
- }, [key]);
91
- useEffect(() => {
92
- if (!isInitialized.current) return;
93
- if (isFromStorageEvent.current) {
94
- isFromStorageEvent.current = false;
95
- return;
96
- }
97
- try {
98
- if (typeof window !== "undefined") {
99
- window.localStorage.setItem(key, JSON.stringify(storedValue));
100
- }
101
- } catch (error) {
102
- console.error(`Error writing to localStorage key "${key}":`, error);
103
- }
104
- }, [key, storedValue]);
105
- const setValue = (value) => {
106
- try {
107
- const valueToStore = value instanceof Function ? value(storedValue) : value;
108
- setStoredValue(valueToStore);
109
- } catch (error) {
110
- console.error(`Error setting value for localStorage key "${key}":`, error);
111
- }
112
- };
113
- return [storedValue, setValue];
114
- }
115
-
116
- // src/hooks/ui/use-media-query.ts
117
- import { useLayoutEffect, useState as useState2 } from "react";
118
- function useMediaQuery(query) {
119
- const [matches, setMatches] = useState2(void 0);
120
- useLayoutEffect(() => {
121
- const matchMedia = window.matchMedia(query);
122
- const handleChange = () => {
123
- setMatches(matchMedia.matches);
124
- };
125
- handleChange();
126
- matchMedia.addEventListener("change", handleChange);
127
- return () => {
128
- matchMedia.removeEventListener("change", handleChange);
129
- };
130
- }, [query]);
131
- return matches;
132
- }
133
- var breakpoints = {
134
- md: "(min-width: 800px)",
135
- // Tablet: 50rem
136
- lg: "(min-width: 1280px)"
137
- // Desktop: 80rem
138
- };
139
- function useSmUp() {
140
- return useMdUp();
141
- }
142
- function useMdUp() {
143
- const matches = useMediaQuery(breakpoints.md);
144
- return matches === void 0 ? void 0 : matches;
145
- }
146
- function useLgUp() {
147
- const matches = useMediaQuery(breakpoints.lg);
148
- return matches === void 0 ? void 0 : matches;
149
- }
150
-
151
- // src/hooks/ui/use-memoized-callback.ts
152
- import { useCallback, useRef as useRef2 } from "react";
153
- function useMemoizedCallback(callback, dependencies) {
154
- const callbackRef = useRef2(callback);
155
- const dependenciesRef = useRef2(dependencies);
156
- callbackRef.current = callback;
157
- const depsChanged = dependencies.some((dep, i) => !Object.is(dep, dependenciesRef.current[i]));
158
- if (depsChanged) {
159
- dependenciesRef.current = dependencies;
160
- }
161
- return useCallback(((...args) => callbackRef.current(...args)), [depsChanged]);
162
- }
163
-
164
- // src/hooks/ui/use-onboarding-state.ts
165
- import { useState as useState3, useEffect as useEffect2, useCallback as useCallback2 } from "react";
166
-
167
- // src/utils/onboarding-storage.ts
168
- var DEFAULT_STATE = {
169
- completedSteps: [],
170
- skippedSteps: [],
171
- dismissed: false,
172
- lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
173
- };
174
- function saveOnboardingState(key, state) {
175
- if (typeof window === "undefined") return;
176
- try {
177
- localStorage.setItem(key, JSON.stringify(state));
178
- console.log("\u{1F4BE} Saved onboarding state:", state);
179
- if (typeof window !== "undefined") {
180
- window.dispatchEvent(
181
- new CustomEvent("localStorageUpdate", {
182
- detail: { key, newValue: JSON.stringify(state) }
183
- })
184
- );
185
- }
186
- } catch (err) {
187
- console.warn("[onboarding-storage] Failed saving to localStorage:", err);
188
- }
189
- }
190
- function loadOnboardingState(key) {
191
- if (typeof window === "undefined") return DEFAULT_STATE;
192
- try {
193
- const raw = localStorage.getItem(key);
194
- if (!raw) return DEFAULT_STATE;
195
- const parsed = JSON.parse(raw);
196
- return parsed;
197
- } catch (err) {
198
- console.warn("[onboarding-storage] Failed parsing localStorage data:", err);
199
- return DEFAULT_STATE;
200
- }
201
- }
202
- function markMultipleComplete(key, stepIds) {
203
- const state = loadOnboardingState(key);
204
- const newState = {
205
- ...state,
206
- completedSteps: [.../* @__PURE__ */ new Set([...state.completedSteps, ...stepIds])],
207
- skippedSteps: state.skippedSteps.filter((id) => !stepIds.includes(id)),
208
- lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
209
- };
210
- saveOnboardingState(key, newState);
211
- return newState;
212
- }
213
- function markStepComplete(key, stepId) {
214
- return markMultipleComplete(key, [stepId]);
215
- }
216
- function markStepSkipped(key, stepId) {
217
- const state = loadOnboardingState(key);
218
- const newState = {
219
- ...state,
220
- skippedSteps: [.../* @__PURE__ */ new Set([...state.skippedSteps, stepId])],
221
- completedSteps: state.completedSteps.filter((id) => id !== stepId),
222
- lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
223
- };
224
- saveOnboardingState(key, newState);
225
- return newState;
226
- }
227
- function dismissOnboarding(key) {
228
- const state = loadOnboardingState(key);
229
- const newState = {
230
- ...state,
231
- dismissed: true,
232
- lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
233
- };
234
- saveOnboardingState(key, newState);
235
- return newState;
236
- }
237
-
238
- // src/hooks/ui/use-onboarding-state.ts
239
- function useOnboardingState(storageKey = "openframe-onboarding-state") {
240
- const [state, setState] = useState3(() => loadOnboardingState(storageKey));
241
- const [, forceUpdate] = useState3(0);
242
- useEffect2(() => {
243
- const handleStorageUpdate = (e) => {
244
- if (e.detail.key === storageKey) {
245
- const newState = loadOnboardingState(storageKey);
246
- setState(newState);
247
- forceUpdate((prev) => prev + 1);
248
- console.log("\u{1F504} State updated from storage event:", newState);
249
- }
250
- };
251
- window.addEventListener("localStorageUpdate", handleStorageUpdate);
63
+ });
64
+ mutationObserver.observe(document.body, {
65
+ childList: true,
66
+ subtree: true,
67
+ attributes: true,
68
+ attributeFilter: ["data-announcement-bar"]
69
+ });
252
70
  return () => {
253
- window.removeEventListener("localStorageUpdate", handleStorageUpdate);
71
+ resizeObserver.disconnect();
72
+ mutationObserver.disconnect();
254
73
  };
255
- }, [storageKey]);
256
- const markComplete = useCallback2((stepId) => {
257
- console.log(`\u{1F3AF} markComplete called for: "${stepId}"`);
258
- const newState = markStepComplete(storageKey, stepId);
259
- setState(newState);
260
- forceUpdate((prev) => prev + 1);
261
- }, [storageKey]);
262
- const markSkipped = useCallback2((stepId) => {
263
- console.log(`\u23ED\uFE0F markSkipped called for: "${stepId}"`);
264
- const newState = markStepSkipped(storageKey, stepId);
265
- setState(newState);
266
- forceUpdate((prev) => prev + 1);
267
- }, [storageKey]);
268
- const dismissOnboarding2 = useCallback2(() => {
269
- console.log(`\u{1F6AB} dismissOnboarding called`);
270
- const newState = dismissOnboarding(storageKey);
271
- setState(newState);
272
- forceUpdate((prev) => prev + 1);
273
- }, [storageKey]);
274
- const markMultipleComplete2 = useCallback2((stepIds) => {
275
- console.log(`\u{1F3AF} markMultipleComplete called for:`, stepIds);
276
- const newState = markMultipleComplete(storageKey, stepIds);
277
- setState(newState);
278
- forceUpdate((prev) => prev + 1);
279
- console.log(`\u{1F4DD} State after batch:`, newState);
280
- }, [storageKey]);
281
- const isStepComplete = useCallback2((stepId) => {
282
- return state.completedSteps.includes(stepId);
283
- }, [state.completedSteps]);
284
- const isStepSkipped = useCallback2((stepId) => {
285
- return state.skippedSteps.includes(stepId);
286
- }, [state.skippedSteps]);
287
- const allStepsComplete = useCallback2((steps) => {
288
- return steps.every((step) => isStepComplete(step.id) || isStepSkipped(step.id));
289
- }, [isStepComplete, isStepSkipped]);
290
- return {
291
- state,
292
- markComplete,
293
- markSkipped,
294
- dismissOnboarding: dismissOnboarding2,
295
- isStepComplete,
296
- isStepSkipped,
297
- allStepsComplete,
298
- markMultipleComplete: markMultipleComplete2
299
- };
300
- }
301
-
302
- // src/hooks/ui/use-table-pagination.ts
303
- import { useMemo } from "react";
304
- function useTablePagination(config) {
305
- return useMemo(() => {
306
- if (!config) return void 0;
307
- if (config.type === "client") {
308
- if (config.totalPages <= 1) return void 0;
309
- return {
310
- hasNextPage: config.currentPage < config.totalPages,
311
- hasPreviousPage: config.currentPage > 1,
312
- isFirstPage: config.currentPage === 1,
313
- startCursor: (config.currentPage - 1).toString(),
314
- endCursor: config.currentPage.toString(),
315
- currentCount: config.itemCount,
316
- itemName: config.itemName || "items",
317
- onNext: () => config.onNext(),
318
- onPrevious: () => config.onPrevious(),
319
- showInfo: config.showInfo ?? true
320
- };
321
- } else {
322
- return {
323
- hasNextPage: config.hasNextPage,
324
- hasPreviousPage: config.hasLoadedBeyondFirst,
325
- isFirstPage: !config.hasLoadedBeyondFirst,
326
- startCursor: config.startCursor,
327
- endCursor: config.endCursor,
328
- currentCount: config.itemCount,
329
- itemName: config.itemName || "items",
330
- onNext: config.onNext,
331
- onPrevious: config.onReset,
332
- // Previous button goes back to first page
333
- showInfo: config.showInfo ?? true
334
- };
335
- }
336
- }, [config]);
337
- }
338
-
339
- // src/hooks/ui/use-throttle.ts
340
- import { useState as useState4, useEffect as useEffect3, useRef as useRef3 } from "react";
341
- function useThrottle(value, limit = 200) {
342
- const [throttledValue, setThrottledValue] = useState4(value);
343
- const lastUpdated = useRef3(Date.now());
344
- useEffect3(() => {
345
- const now = Date.now();
346
- const elapsed = now - lastUpdated.current;
347
- if (elapsed >= limit) {
348
- setThrottledValue(value);
349
- lastUpdated.current = now;
350
- } else {
351
- const timerId = setTimeout(() => {
352
- setThrottledValue(value);
353
- lastUpdated.current = Date.now();
354
- }, limit - elapsed);
355
- return () => {
356
- clearTimeout(timerId);
357
- };
358
- }
359
- }, [value, limit]);
360
- return throttledValue;
361
- }
362
-
363
- // src/hooks/ui/use-window-size.ts
364
- import { useLayoutEffect as useLayoutEffect2, useState as useState5 } from "react";
365
- function useWindowSize() {
366
- const [windowSize, setWindowSize] = useState5({
367
- width: 0,
368
- height: 0
369
- });
370
- const [isClient, setIsClient] = useState5(false);
371
- useLayoutEffect2(() => {
372
- setIsClient(true);
373
- if (!isClient) return;
374
- const handleResize = () => {
375
- setWindowSize({
376
- width: window.innerWidth,
377
- height: window.innerHeight
378
- });
379
- };
380
- handleResize();
381
- window.addEventListener("resize", handleResize);
382
- return () => window.removeEventListener("resize", handleResize);
383
- }, [isClient]);
384
- return windowSize;
74
+ }, [defaultHeight]);
75
+ return height;
385
76
  }
386
77
 
387
78
  // src/hooks/ui/use-horizontal-scrollbar.ts
388
- import { useRef as useRef4, useState as useState6, useCallback as useCallback3 } from "react";
79
+ import { useRef, useState as useState2, useCallback } from "react";
389
80
  function useHorizontalScrollbar() {
390
- const scrollElRef = useRef4(null);
391
- const trackRef = useRef4(null);
392
- const thumbRef = useRef4(null);
393
- const roRef = useRef4(null);
394
- const [thumbRatio, setThumbRatio] = useState6(0);
395
- const [canScrollLeft, setCanScrollLeft] = useState6(false);
396
- const [canScrollRight, setCanScrollRight] = useState6(false);
397
- const prevCanScrollLeftRef = useRef4(false);
398
- const prevCanScrollRightRef = useRef4(false);
399
- const isDraggingRef = useRef4(false);
400
- const dragStartRef = useRef4({ mouseX: 0, scrollLeft: 0 });
401
- const rafIdRef = useRef4(0);
402
- const syncThumbToDOM = useCallback3(() => {
81
+ const scrollElRef = useRef(null);
82
+ const trackRef = useRef(null);
83
+ const thumbRef = useRef(null);
84
+ const roRef = useRef(null);
85
+ const moRef = useRef(null);
86
+ const [thumbRatio, setThumbRatio] = useState2(0);
87
+ const [canScrollLeft, setCanScrollLeft] = useState2(false);
88
+ const [canScrollRight, setCanScrollRight] = useState2(false);
89
+ const prevCanScrollLeftRef = useRef(false);
90
+ const prevCanScrollRightRef = useRef(false);
91
+ const isDraggingRef = useRef(false);
92
+ const dragStartRef = useRef({ mouseX: 0, scrollLeft: 0 });
93
+ const rafIdRef = useRef(0);
94
+ const syncThumbToDOM = useCallback(() => {
403
95
  const el = scrollElRef.current;
404
96
  const thumb = thumbRef.current;
405
97
  if (!el || !thumb) return;
@@ -412,7 +104,7 @@ function useHorizontalScrollbar() {
412
104
  const fraction = Math.min(Math.max(el.scrollLeft, 0), maxScroll) / maxScroll;
413
105
  thumb.style.left = `${fraction * (1 - ratio) * 100}%`;
414
106
  }, []);
415
- const syncEdgeFades = useCallback3(() => {
107
+ const syncEdgeFades = useCallback(() => {
416
108
  const el = scrollElRef.current;
417
109
  if (!el) return;
418
110
  const maxScroll = el.scrollWidth - el.clientWidth;
@@ -440,7 +132,7 @@ function useHorizontalScrollbar() {
440
132
  setCanScrollRight(right);
441
133
  }
442
134
  }, []);
443
- const measure = useCallback3(() => {
135
+ const measure = useCallback(() => {
444
136
  const el = scrollElRef.current;
445
137
  if (!el) return;
446
138
  const ratio = el.clientWidth / el.scrollWidth;
@@ -448,11 +140,15 @@ function useHorizontalScrollbar() {
448
140
  syncThumbToDOM();
449
141
  syncEdgeFades();
450
142
  }, [syncThumbToDOM, syncEdgeFades]);
451
- const scrollRef = useCallback3((node) => {
143
+ const scrollRef = useCallback((node) => {
452
144
  if (roRef.current) {
453
145
  roRef.current.disconnect();
454
146
  roRef.current = null;
455
147
  }
148
+ if (moRef.current) {
149
+ moRef.current.disconnect();
150
+ moRef.current = null;
151
+ }
456
152
  if (rafIdRef.current) {
457
153
  cancelAnimationFrame(rafIdRef.current);
458
154
  rafIdRef.current = 0;
@@ -461,8 +157,19 @@ function useHorizontalScrollbar() {
461
157
  if (node) {
462
158
  const ratio = node.clientWidth / node.scrollWidth;
463
159
  setThumbRatio(ratio >= 1 ? 0 : ratio);
464
- roRef.current = new ResizeObserver(measure);
465
- roRef.current.observe(node);
160
+ const ro = new ResizeObserver(measure);
161
+ roRef.current = ro;
162
+ const observeAll = () => {
163
+ ro.disconnect();
164
+ ro.observe(node);
165
+ for (const child of Array.from(node.children)) ro.observe(child);
166
+ };
167
+ observeAll();
168
+ moRef.current = new MutationObserver(() => {
169
+ observeAll();
170
+ measure();
171
+ });
172
+ moRef.current.observe(node, { childList: true });
466
173
  requestAnimationFrame(() => {
467
174
  syncThumbToDOM();
468
175
  syncEdgeFades();
@@ -475,7 +182,7 @@ function useHorizontalScrollbar() {
475
182
  setCanScrollRight(false);
476
183
  }
477
184
  }, [measure, syncThumbToDOM, syncEdgeFades]);
478
- const onScroll = useCallback3(() => {
185
+ const onScroll = useCallback(() => {
479
186
  if (isDraggingRef.current) return;
480
187
  if (rafIdRef.current) cancelAnimationFrame(rafIdRef.current);
481
188
  rafIdRef.current = requestAnimationFrame(() => {
@@ -483,7 +190,7 @@ function useHorizontalScrollbar() {
483
190
  syncEdgeFades();
484
191
  });
485
192
  }, [syncThumbToDOM, syncEdgeFades]);
486
- const onTrackClick = useCallback3((e) => {
193
+ const onTrackClick = useCallback((e) => {
487
194
  if (e.target.closest("[data-scrollbar-thumb]")) return;
488
195
  const track = trackRef.current;
489
196
  const el = scrollElRef.current;
@@ -501,13 +208,13 @@ function useHorizontalScrollbar() {
501
208
  const targetScrollLeft = targetFraction * (el.scrollWidth - el.clientWidth);
502
209
  el.scrollTo({ left: targetScrollLeft, behavior: "smooth" });
503
210
  }, []);
504
- const onTrackWheel = useCallback3((e) => {
211
+ const onTrackWheel = useCallback((e) => {
505
212
  const el = scrollElRef.current;
506
213
  if (!el) return;
507
214
  e.preventDefault();
508
215
  el.scrollLeft += e.deltaX || e.deltaY;
509
216
  }, []);
510
- const onThumbPointerDown = useCallback3((e) => {
217
+ const onThumbPointerDown = useCallback((e) => {
511
218
  e.preventDefault();
512
219
  e.stopPropagation();
513
220
  const el = scrollElRef.current;
@@ -518,7 +225,7 @@ function useHorizontalScrollbar() {
518
225
  target.setPointerCapture(e.pointerId);
519
226
  target.style.cursor = "grabbing";
520
227
  }, []);
521
- const onThumbPointerMove = useCallback3((e) => {
228
+ const onThumbPointerMove = useCallback((e) => {
522
229
  if (!isDraggingRef.current) return;
523
230
  const el = scrollElRef.current;
524
231
  const track = trackRef.current;
@@ -538,7 +245,7 @@ function useHorizontalScrollbar() {
538
245
  syncThumbToDOM();
539
246
  syncEdgeFades();
540
247
  }, [syncThumbToDOM, syncEdgeFades]);
541
- const onThumbPointerUp = useCallback3((e) => {
248
+ const onThumbPointerUp = useCallback((e) => {
542
249
  isDraggingRef.current = false;
543
250
  const target = e.currentTarget;
544
251
  target.releasePointerCapture(e.pointerId);
@@ -561,7 +268,7 @@ function useHorizontalScrollbar() {
561
268
  }
562
269
 
563
270
  // src/hooks/ui/use-image-edge-color.ts
564
- import { useState as useState7, useEffect as useEffect4 } from "react";
271
+ import { useState as useState3, useEffect as useEffect2 } from "react";
565
272
  function extractEdgeColor(img) {
566
273
  const canvas = document.createElement("canvas");
567
274
  const ctx = canvas.getContext("2d");
@@ -603,51 +310,357 @@ function extractEdgeColor(img) {
603
310
  }
604
311
  }
605
312
  }
606
- if (buckets.size === 0) return "#000000";
607
- let bestBucket = null;
608
- for (const bucket of buckets.values()) {
609
- if (!bestBucket || bucket.count > bestBucket.count) {
610
- bestBucket = bucket;
611
- }
313
+ if (buckets.size === 0) return "#000000";
314
+ let bestBucket = null;
315
+ for (const bucket of buckets.values()) {
316
+ if (!bestBucket || bucket.count > bestBucket.count) {
317
+ bestBucket = bucket;
318
+ }
319
+ }
320
+ if (!bestBucket || bestBucket.count === 0) return "#000000";
321
+ const r = Math.round(bestBucket.r / bestBucket.count);
322
+ const g = Math.round(bestBucket.g / bestBucket.count);
323
+ const b = Math.round(bestBucket.b / bestBucket.count);
324
+ return `rgb(${r}, ${g}, ${b})`;
325
+ }
326
+ function useImageEdgeColor(imageUrl, fallback = "#000000") {
327
+ const [color, setColor] = useState3(fallback);
328
+ useEffect2(() => {
329
+ if (!imageUrl) {
330
+ setColor(fallback);
331
+ return;
332
+ }
333
+ let cancelled = false;
334
+ const img = new Image();
335
+ img.crossOrigin = "anonymous";
336
+ img.onload = () => {
337
+ if (cancelled) return;
338
+ try {
339
+ setColor(extractEdgeColor(img));
340
+ } catch {
341
+ setColor(fallback);
342
+ }
343
+ };
344
+ img.onerror = () => {
345
+ if (cancelled) return;
346
+ setColor(fallback);
347
+ };
348
+ img.src = imageUrl;
349
+ return () => {
350
+ cancelled = true;
351
+ };
352
+ }, [imageUrl, fallback]);
353
+ return color;
354
+ }
355
+
356
+ // src/hooks/ui/use-local-storage.ts
357
+ import { useEffect as useEffect3, useRef as useRef2, useState as useState4 } from "react";
358
+ function useLocalStorage(key, initialValue) {
359
+ const [storedValue, setStoredValue] = useState4(() => {
360
+ try {
361
+ if (typeof window !== "undefined") {
362
+ const item = window.localStorage.getItem(key);
363
+ return item ? JSON.parse(item) : initialValue;
364
+ }
365
+ } catch (error) {
366
+ console.error(`Error reading localStorage key "${key}":`, error);
367
+ }
368
+ return initialValue;
369
+ });
370
+ const isInitialized = useRef2(true);
371
+ const isFromStorageEvent = useRef2(false);
372
+ useEffect3(() => {
373
+ if (!isInitialized.current) return;
374
+ const handleStorageChange = (e) => {
375
+ if (e.key === key && e.newValue !== null) {
376
+ try {
377
+ const newValue = JSON.parse(e.newValue);
378
+ isFromStorageEvent.current = true;
379
+ setStoredValue(newValue);
380
+ console.log(`\u{1F504} Updated localStorage key "${key}" from storage event`);
381
+ } catch (error) {
382
+ console.error(`Error parsing storage event for key "${key}":`, error);
383
+ }
384
+ }
385
+ };
386
+ const handleCustomStorageUpdate = (e) => {
387
+ if (e.detail.key === key) {
388
+ try {
389
+ if (e.detail.newValue === null || e.detail.newValue === void 0) {
390
+ isFromStorageEvent.current = true;
391
+ setStoredValue(initialValue);
392
+ console.log(`\u{1F504} Cleared localStorage key "${key}" from custom storage event`);
393
+ } else {
394
+ const newValue = JSON.parse(e.detail.newValue);
395
+ isFromStorageEvent.current = true;
396
+ setStoredValue(newValue);
397
+ console.log(`\u{1F504} Updated localStorage key "${key}" from custom storage event`);
398
+ }
399
+ } catch (error) {
400
+ console.error(`Error parsing custom storage event for key "${key}":`, error);
401
+ }
402
+ }
403
+ };
404
+ window.addEventListener("storage", handleStorageChange);
405
+ window.addEventListener("localStorageUpdate", handleCustomStorageUpdate);
406
+ return () => {
407
+ window.removeEventListener("storage", handleStorageChange);
408
+ window.removeEventListener("localStorageUpdate", handleCustomStorageUpdate);
409
+ };
410
+ }, [key]);
411
+ useEffect3(() => {
412
+ if (!isInitialized.current) return;
413
+ if (isFromStorageEvent.current) {
414
+ isFromStorageEvent.current = false;
415
+ return;
416
+ }
417
+ try {
418
+ if (typeof window !== "undefined") {
419
+ window.localStorage.setItem(key, JSON.stringify(storedValue));
420
+ }
421
+ } catch (error) {
422
+ console.error(`Error writing to localStorage key "${key}":`, error);
423
+ }
424
+ }, [key, storedValue]);
425
+ const setValue = (value) => {
426
+ try {
427
+ const valueToStore = value instanceof Function ? value(storedValue) : value;
428
+ setStoredValue(valueToStore);
429
+ } catch (error) {
430
+ console.error(`Error setting value for localStorage key "${key}":`, error);
431
+ }
432
+ };
433
+ return [storedValue, setValue];
434
+ }
435
+
436
+ // src/hooks/ui/use-media-query.ts
437
+ import { useLayoutEffect, useState as useState5 } from "react";
438
+ function useMediaQuery(query) {
439
+ const [matches, setMatches] = useState5(void 0);
440
+ useLayoutEffect(() => {
441
+ const matchMedia = window.matchMedia(query);
442
+ const handleChange = () => {
443
+ setMatches(matchMedia.matches);
444
+ };
445
+ handleChange();
446
+ matchMedia.addEventListener("change", handleChange);
447
+ return () => {
448
+ matchMedia.removeEventListener("change", handleChange);
449
+ };
450
+ }, [query]);
451
+ return matches;
452
+ }
453
+ var breakpoints = {
454
+ md: "(min-width: 800px)",
455
+ // Tablet: 50rem
456
+ lg: "(min-width: 1280px)"
457
+ // Desktop: 80rem
458
+ };
459
+ function useSmUp() {
460
+ return useMdUp();
461
+ }
462
+ function useMdUp() {
463
+ const matches = useMediaQuery(breakpoints.md);
464
+ return matches === void 0 ? void 0 : matches;
465
+ }
466
+ function useLgUp() {
467
+ const matches = useMediaQuery(breakpoints.lg);
468
+ return matches === void 0 ? void 0 : matches;
469
+ }
470
+
471
+ // src/hooks/ui/use-memoized-callback.ts
472
+ import { useCallback as useCallback2, useRef as useRef3 } from "react";
473
+ function useMemoizedCallback(callback, dependencies) {
474
+ const callbackRef = useRef3(callback);
475
+ const dependenciesRef = useRef3(dependencies);
476
+ callbackRef.current = callback;
477
+ const depsChanged = dependencies.some((dep, i) => !Object.is(dep, dependenciesRef.current[i]));
478
+ if (depsChanged) {
479
+ dependenciesRef.current = dependencies;
480
+ }
481
+ return useCallback2(((...args) => callbackRef.current(...args)), [depsChanged]);
482
+ }
483
+
484
+ // src/hooks/ui/use-notification-permission.ts
485
+ import { useCallback as useCallback3, useEffect as useEffect4, useState as useState6 } from "react";
486
+ function useNotificationPermission() {
487
+ const [supported, setSupported] = useState6(false);
488
+ const [permission, setPermission] = useState6("default");
489
+ useEffect4(() => {
490
+ if (typeof window === "undefined" || !("Notification" in window)) return;
491
+ setSupported(true);
492
+ const sync = () => setPermission(Notification.permission);
493
+ sync();
494
+ let cancelled = false;
495
+ let status;
496
+ navigator.permissions?.query({ name: "notifications" }).then((s) => {
497
+ if (cancelled) return;
498
+ status = s;
499
+ s.addEventListener("change", sync);
500
+ }).catch(() => void 0);
501
+ document.addEventListener("visibilitychange", sync);
502
+ window.addEventListener("focus", sync);
503
+ return () => {
504
+ cancelled = true;
505
+ status?.removeEventListener("change", sync);
506
+ document.removeEventListener("visibilitychange", sync);
507
+ window.removeEventListener("focus", sync);
508
+ };
509
+ }, []);
510
+ const request = useCallback3(async () => {
511
+ if (typeof window === "undefined" || !("Notification" in window)) {
512
+ return "denied";
513
+ }
514
+ const result = await new Promise((resolve) => {
515
+ const maybePromise = Notification.requestPermission(resolve);
516
+ if (maybePromise && typeof maybePromise.then === "function") void maybePromise.then(resolve);
517
+ });
518
+ setPermission(Notification.permission);
519
+ return result;
520
+ }, []);
521
+ return { supported, permission, request };
522
+ }
523
+
524
+ // src/hooks/ui/use-onboarding-state.ts
525
+ import { useState as useState7, useEffect as useEffect5, useCallback as useCallback4 } from "react";
526
+
527
+ // src/utils/onboarding-storage.ts
528
+ var DEFAULT_STATE = {
529
+ completedSteps: [],
530
+ skippedSteps: [],
531
+ dismissed: false,
532
+ lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
533
+ };
534
+ function saveOnboardingState(key, state) {
535
+ if (typeof window === "undefined") return;
536
+ try {
537
+ localStorage.setItem(key, JSON.stringify(state));
538
+ console.log("\u{1F4BE} Saved onboarding state:", state);
539
+ if (typeof window !== "undefined") {
540
+ window.dispatchEvent(
541
+ new CustomEvent("localStorageUpdate", {
542
+ detail: { key, newValue: JSON.stringify(state) }
543
+ })
544
+ );
545
+ }
546
+ } catch (err) {
547
+ console.warn("[onboarding-storage] Failed saving to localStorage:", err);
548
+ }
549
+ }
550
+ function loadOnboardingState(key) {
551
+ if (typeof window === "undefined") return DEFAULT_STATE;
552
+ try {
553
+ const raw = localStorage.getItem(key);
554
+ if (!raw) return DEFAULT_STATE;
555
+ const parsed = JSON.parse(raw);
556
+ return parsed;
557
+ } catch (err) {
558
+ console.warn("[onboarding-storage] Failed parsing localStorage data:", err);
559
+ return DEFAULT_STATE;
612
560
  }
613
- if (!bestBucket || bestBucket.count === 0) return "#000000";
614
- const r = Math.round(bestBucket.r / bestBucket.count);
615
- const g = Math.round(bestBucket.g / bestBucket.count);
616
- const b = Math.round(bestBucket.b / bestBucket.count);
617
- return `rgb(${r}, ${g}, ${b})`;
618
561
  }
619
- function useImageEdgeColor(imageUrl, fallback = "#000000") {
620
- const [color, setColor] = useState7(fallback);
621
- useEffect4(() => {
622
- if (!imageUrl) {
623
- setColor(fallback);
624
- return;
625
- }
626
- let cancelled = false;
627
- const img = new Image();
628
- img.crossOrigin = "anonymous";
629
- img.onload = () => {
630
- if (cancelled) return;
631
- try {
632
- setColor(extractEdgeColor(img));
633
- } catch {
634
- setColor(fallback);
562
+ function markMultipleComplete(key, stepIds) {
563
+ const state = loadOnboardingState(key);
564
+ const newState = {
565
+ ...state,
566
+ completedSteps: [.../* @__PURE__ */ new Set([...state.completedSteps, ...stepIds])],
567
+ skippedSteps: state.skippedSteps.filter((id) => !stepIds.includes(id)),
568
+ lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
569
+ };
570
+ saveOnboardingState(key, newState);
571
+ return newState;
572
+ }
573
+ function markStepComplete(key, stepId) {
574
+ return markMultipleComplete(key, [stepId]);
575
+ }
576
+ function markStepSkipped(key, stepId) {
577
+ const state = loadOnboardingState(key);
578
+ const newState = {
579
+ ...state,
580
+ skippedSteps: [.../* @__PURE__ */ new Set([...state.skippedSteps, stepId])],
581
+ completedSteps: state.completedSteps.filter((id) => id !== stepId),
582
+ lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
583
+ };
584
+ saveOnboardingState(key, newState);
585
+ return newState;
586
+ }
587
+ function dismissOnboarding(key) {
588
+ const state = loadOnboardingState(key);
589
+ const newState = {
590
+ ...state,
591
+ dismissed: true,
592
+ lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
593
+ };
594
+ saveOnboardingState(key, newState);
595
+ return newState;
596
+ }
597
+
598
+ // src/hooks/ui/use-onboarding-state.ts
599
+ function useOnboardingState(storageKey = "openframe-onboarding-state") {
600
+ const [state, setState] = useState7(() => loadOnboardingState(storageKey));
601
+ const [, forceUpdate] = useState7(0);
602
+ useEffect5(() => {
603
+ const handleStorageUpdate = (e) => {
604
+ if (e.detail.key === storageKey) {
605
+ const newState = loadOnboardingState(storageKey);
606
+ setState(newState);
607
+ forceUpdate((prev) => prev + 1);
608
+ console.log("\u{1F504} State updated from storage event:", newState);
635
609
  }
636
610
  };
637
- img.onerror = () => {
638
- if (cancelled) return;
639
- setColor(fallback);
640
- };
641
- img.src = imageUrl;
611
+ window.addEventListener("localStorageUpdate", handleStorageUpdate);
642
612
  return () => {
643
- cancelled = true;
613
+ window.removeEventListener("localStorageUpdate", handleStorageUpdate);
644
614
  };
645
- }, [imageUrl, fallback]);
646
- return color;
615
+ }, [storageKey]);
616
+ const markComplete = useCallback4((stepId) => {
617
+ console.log(`\u{1F3AF} markComplete called for: "${stepId}"`);
618
+ const newState = markStepComplete(storageKey, stepId);
619
+ setState(newState);
620
+ forceUpdate((prev) => prev + 1);
621
+ }, [storageKey]);
622
+ const markSkipped = useCallback4((stepId) => {
623
+ console.log(`\u23ED\uFE0F markSkipped called for: "${stepId}"`);
624
+ const newState = markStepSkipped(storageKey, stepId);
625
+ setState(newState);
626
+ forceUpdate((prev) => prev + 1);
627
+ }, [storageKey]);
628
+ const dismissOnboarding2 = useCallback4(() => {
629
+ console.log(`\u{1F6AB} dismissOnboarding called`);
630
+ const newState = dismissOnboarding(storageKey);
631
+ setState(newState);
632
+ forceUpdate((prev) => prev + 1);
633
+ }, [storageKey]);
634
+ const markMultipleComplete2 = useCallback4((stepIds) => {
635
+ console.log(`\u{1F3AF} markMultipleComplete called for:`, stepIds);
636
+ const newState = markMultipleComplete(storageKey, stepIds);
637
+ setState(newState);
638
+ forceUpdate((prev) => prev + 1);
639
+ console.log(`\u{1F4DD} State after batch:`, newState);
640
+ }, [storageKey]);
641
+ const isStepComplete = useCallback4((stepId) => {
642
+ return state.completedSteps.includes(stepId);
643
+ }, [state.completedSteps]);
644
+ const isStepSkipped = useCallback4((stepId) => {
645
+ return state.skippedSteps.includes(stepId);
646
+ }, [state.skippedSteps]);
647
+ const allStepsComplete = useCallback4((steps) => {
648
+ return steps.every((step) => isStepComplete(step.id) || isStepSkipped(step.id));
649
+ }, [isStepComplete, isStepSkipped]);
650
+ return {
651
+ state,
652
+ markComplete,
653
+ markSkipped,
654
+ dismissOnboarding: dismissOnboarding2,
655
+ isStepComplete,
656
+ isStepSkipped,
657
+ allStepsComplete,
658
+ markMultipleComplete: markMultipleComplete2
659
+ };
647
660
  }
648
661
 
649
662
  // src/hooks/ui/use-search.ts
650
- import { useState as useState8, useEffect as useEffect5, useCallback as useCallback4 } from "react";
663
+ import { useState as useState8, useEffect as useEffect6, useCallback as useCallback5 } from "react";
651
664
  function useSearch(config) {
652
665
  const { searchFn, mapResult, debounceMs = 300, minQueryLength = 2 } = config;
653
666
  const [query, setQuery] = useState8("");
@@ -655,11 +668,11 @@ function useSearch(config) {
655
668
  const [isLoading, setIsLoading] = useState8(false);
656
669
  const [error, setError] = useState8(null);
657
670
  const debouncedQuery = useDebounce(query, debounceMs);
658
- const clearResults = useCallback4(() => {
671
+ const clearResults = useCallback5(() => {
659
672
  setResults([]);
660
673
  setError(null);
661
674
  }, []);
662
- useEffect5(() => {
675
+ useEffect6(() => {
663
676
  if (!debouncedQuery || debouncedQuery.length < minQueryLength) {
664
677
  setResults([]);
665
678
  setIsLoading(false);
@@ -694,8 +707,93 @@ function useSearch(config) {
694
707
  return { query, setQuery, results, isLoading, error, clearResults };
695
708
  }
696
709
 
710
+ // src/hooks/ui/use-table-pagination.ts
711
+ import { useMemo } from "react";
712
+ function useTablePagination(config) {
713
+ return useMemo(() => {
714
+ if (!config) return void 0;
715
+ if (config.type === "client") {
716
+ if (config.totalPages <= 1) return void 0;
717
+ return {
718
+ hasNextPage: config.currentPage < config.totalPages,
719
+ hasPreviousPage: config.currentPage > 1,
720
+ isFirstPage: config.currentPage === 1,
721
+ startCursor: (config.currentPage - 1).toString(),
722
+ endCursor: config.currentPage.toString(),
723
+ currentCount: config.itemCount,
724
+ itemName: config.itemName || "items",
725
+ onNext: () => config.onNext(),
726
+ onPrevious: () => config.onPrevious(),
727
+ showInfo: config.showInfo ?? true
728
+ };
729
+ } else {
730
+ return {
731
+ hasNextPage: config.hasNextPage,
732
+ hasPreviousPage: config.hasLoadedBeyondFirst,
733
+ isFirstPage: !config.hasLoadedBeyondFirst,
734
+ startCursor: config.startCursor,
735
+ endCursor: config.endCursor,
736
+ currentCount: config.itemCount,
737
+ itemName: config.itemName || "items",
738
+ onNext: config.onNext,
739
+ onPrevious: config.onReset,
740
+ // Previous button goes back to first page
741
+ showInfo: config.showInfo ?? true
742
+ };
743
+ }
744
+ }, [config]);
745
+ }
746
+
747
+ // src/hooks/ui/use-throttle.ts
748
+ import { useState as useState9, useEffect as useEffect7, useRef as useRef4 } from "react";
749
+ function useThrottle(value, limit = 200) {
750
+ const [throttledValue, setThrottledValue] = useState9(value);
751
+ const lastUpdated = useRef4(Date.now());
752
+ useEffect7(() => {
753
+ const now = Date.now();
754
+ const elapsed = now - lastUpdated.current;
755
+ if (elapsed >= limit) {
756
+ setThrottledValue(value);
757
+ lastUpdated.current = now;
758
+ } else {
759
+ const timerId = setTimeout(() => {
760
+ setThrottledValue(value);
761
+ lastUpdated.current = Date.now();
762
+ }, limit - elapsed);
763
+ return () => {
764
+ clearTimeout(timerId);
765
+ };
766
+ }
767
+ }, [value, limit]);
768
+ return throttledValue;
769
+ }
770
+
771
+ // src/hooks/ui/use-window-size.ts
772
+ import { useLayoutEffect as useLayoutEffect2, useState as useState10 } from "react";
773
+ function useWindowSize() {
774
+ const [windowSize, setWindowSize] = useState10({
775
+ width: 0,
776
+ height: 0
777
+ });
778
+ const [isClient, setIsClient] = useState10(false);
779
+ useLayoutEffect2(() => {
780
+ setIsClient(true);
781
+ if (!isClient) return;
782
+ const handleResize = () => {
783
+ setWindowSize({
784
+ width: window.innerWidth,
785
+ height: window.innerHeight
786
+ });
787
+ };
788
+ handleResize();
789
+ window.addEventListener("resize", handleResize);
790
+ return () => window.removeEventListener("resize", handleResize);
791
+ }, [isClient]);
792
+ return windowSize;
793
+ }
794
+
697
795
  // src/hooks/platform/use-platform-config.ts
698
- import { useState as useState9, useEffect as useEffect6 } from "react";
796
+ import { useState as useState11, useEffect as useEffect8 } from "react";
699
797
 
700
798
  // src/utils/platform-config.tsx
701
799
  import { Globe } from "lucide-react";
@@ -873,10 +971,10 @@ function getPlatformIconComponent(platformName, className = "h-6 w-6") {
873
971
  var platformCache = null;
874
972
  var fetchPromise = null;
875
973
  function usePlatformConfig() {
876
- const [platforms, setPlatforms] = useState9(platformCache || []);
877
- const [isLoading, setIsLoading] = useState9(!platformCache);
878
- const [error, setError] = useState9(null);
879
- useEffect6(() => {
974
+ const [platforms, setPlatforms] = useState11(platformCache || []);
975
+ const [isLoading, setIsLoading] = useState11(!platformCache);
976
+ const [error, setError] = useState11(null);
977
+ useEffect8(() => {
880
978
  if (platformCache) {
881
979
  setPlatforms(platformCache);
882
980
  setIsLoading(false);
@@ -1325,16 +1423,16 @@ var useToast = () => ({
1325
1423
  });
1326
1424
 
1327
1425
  // src/hooks/use-contact-submission.ts
1328
- import { useState as useState11, useCallback as useCallback5, useEffect as useEffect7 } from "react";
1426
+ import { useState as useState13, useCallback as useCallback6, useEffect as useEffect9 } from "react";
1329
1427
  init_next_navigation();
1330
1428
  function useContactSubmission(options = {}) {
1331
1429
  const { userId, successRedirectUrl, successToastMessage, onSuccess } = options;
1332
1430
  const { toast: toast2 } = useToast();
1333
1431
  const router = useRouter();
1334
1432
  const { contactUrl } = useRequiredEndpointsRuntime();
1335
- const [isSubmitting, setIsSubmitting] = useState11(false);
1336
- const [isSuccess, setIsSuccess] = useState11(false);
1337
- const submit = useCallback5(async (formData) => {
1433
+ const [isSubmitting, setIsSubmitting] = useState13(false);
1434
+ const [isSuccess, setIsSuccess] = useState13(false);
1435
+ const submit = useCallback6(async (formData) => {
1338
1436
  if (isSubmitting) return;
1339
1437
  setIsSubmitting(true);
1340
1438
  try {
@@ -1369,7 +1467,7 @@ function useContactSubmission(options = {}) {
1369
1467
  setIsSubmitting(false);
1370
1468
  }
1371
1469
  }, [isSubmitting, toast2, userId, successToastMessage, contactUrl]);
1372
- useEffect7(() => {
1470
+ useEffect9(() => {
1373
1471
  if (isSuccess && successRedirectUrl) {
1374
1472
  console.log("\u{1F680} Contact submission successful, redirecting to:", successRedirectUrl);
1375
1473
  const timer = setTimeout(() => {
@@ -1383,7 +1481,7 @@ function useContactSubmission(options = {}) {
1383
1481
  return () => clearTimeout(timer);
1384
1482
  }
1385
1483
  }, [isSuccess, successRedirectUrl, router]);
1386
- useEffect7(() => {
1484
+ useEffect9(() => {
1387
1485
  if (isSuccess && onSuccess) {
1388
1486
  onSuccess();
1389
1487
  }
@@ -1392,19 +1490,19 @@ function useContactSubmission(options = {}) {
1392
1490
  }
1393
1491
 
1394
1492
  // src/hooks/use-quick-action-hint.ts
1395
- import { useEffect as useEffect8, useState as useState12, useRef as useRef5, useCallback as useCallback6 } from "react";
1493
+ import { useEffect as useEffect10, useState as useState14, useRef as useRef5, useCallback as useCallback7 } from "react";
1396
1494
  function useQuickActionHint({
1397
1495
  actionCount,
1398
1496
  cycleDuration = 5e3,
1399
1497
  enabled = true
1400
1498
  }) {
1401
- const [activeHintIndex, setActiveHintIndex] = useState12(-1);
1499
+ const [activeHintIndex, setActiveHintIndex] = useState14(-1);
1402
1500
  const containerRef = useRef5(null);
1403
1501
  const timeoutRef = useRef5(null);
1404
1502
  const cycleCountRef = useRef5(0);
1405
1503
  const currentIndexRef = useRef5(0);
1406
1504
  const sequenceRef = useRef5([]);
1407
- const shuffleIndices = useCallback6((length) => {
1505
+ const shuffleIndices = useCallback7((length) => {
1408
1506
  const indices = Array.from({ length }, (_, i) => i);
1409
1507
  for (let i = indices.length - 1; i > 0; i--) {
1410
1508
  const j = Math.floor(Math.random() * (i + 1));
@@ -1412,7 +1510,7 @@ function useQuickActionHint({
1412
1510
  }
1413
1511
  return indices;
1414
1512
  }, []);
1415
- const stopHint = useCallback6(() => {
1513
+ const stopHint = useCallback7(() => {
1416
1514
  if (timeoutRef.current) {
1417
1515
  clearTimeout(timeoutRef.current);
1418
1516
  timeoutRef.current = null;
@@ -1422,7 +1520,7 @@ function useQuickActionHint({
1422
1520
  currentIndexRef.current = 0;
1423
1521
  sequenceRef.current = [];
1424
1522
  }, []);
1425
- const advanceHint = useCallback6(() => {
1523
+ const advanceHint = useCallback7(() => {
1426
1524
  if (currentIndexRef.current === 0) {
1427
1525
  sequenceRef.current = shuffleIndices(actionCount);
1428
1526
  }
@@ -1435,7 +1533,7 @@ function useQuickActionHint({
1435
1533
  }
1436
1534
  timeoutRef.current = setTimeout(advanceHint, cycleDuration);
1437
1535
  }, [actionCount, cycleDuration, shuffleIndices]);
1438
- useEffect8(() => {
1536
+ useEffect10(() => {
1439
1537
  if (!enabled || actionCount === 0) {
1440
1538
  return;
1441
1539
  }
@@ -1461,7 +1559,7 @@ function useQuickActionHint({
1461
1559
  }
1462
1560
 
1463
1561
  // src/hooks/use-copy-to-clipboard.ts
1464
- import { useCallback as useCallback7, useState as useState13 } from "react";
1562
+ import { useCallback as useCallback8, useState as useState15 } from "react";
1465
1563
  function useCopyToClipboard({
1466
1564
  successTitle = "Copied",
1467
1565
  successDescription = "Copied to clipboard",
@@ -1470,8 +1568,8 @@ function useCopyToClipboard({
1470
1568
  resetDelay = 2e3
1471
1569
  } = {}) {
1472
1570
  const { toast: toast2 } = useToast();
1473
- const [copied, setCopied] = useState13(false);
1474
- const copy = useCallback7(
1571
+ const [copied, setCopied] = useState15(false);
1572
+ const copy = useCallback8(
1475
1573
  async (text) => {
1476
1574
  try {
1477
1575
  await navigator.clipboard.writeText(text);
@@ -1488,7 +1586,7 @@ function useCopyToClipboard({
1488
1586
  }
1489
1587
 
1490
1588
  // src/hooks/use-batch-images.ts
1491
- import { useEffect as useEffect9, useMemo as useMemo2, useState as useState14, useRef as useRef6 } from "react";
1589
+ import { useEffect as useEffect11, useMemo as useMemo2, useState as useState16, useRef as useRef6 } from "react";
1492
1590
  var globalBatchImageConfig = {};
1493
1591
  function configureBatchImageFetch(config) {
1494
1592
  globalBatchImageConfig = { ...globalBatchImageConfig, ...config };
@@ -1561,14 +1659,14 @@ async function batchFetchAuthenticatedImages(imageUrls, config) {
1561
1659
  return results;
1562
1660
  }
1563
1661
  function useBatchImages(imageUrls, config) {
1564
- const [fetchedImages, setFetchedImages] = useState14({});
1565
- const [loading, setLoading] = useState14(false);
1662
+ const [fetchedImages, setFetchedImages] = useState16({});
1663
+ const [loading, setLoading] = useState16(false);
1566
1664
  const uniqueUrls = useMemo2(
1567
1665
  () => Array.from(new Set(imageUrls.filter((url) => Boolean(url)))),
1568
1666
  [imageUrls]
1569
1667
  );
1570
1668
  const requestedUrls = useRef6(/* @__PURE__ */ new Set());
1571
- useEffect9(() => {
1669
+ useEffect11(() => {
1572
1670
  if (uniqueUrls.length === 0) {
1573
1671
  setFetchedImages({});
1574
1672
  return;
@@ -1598,7 +1696,7 @@ function useBatchImages(imageUrls, config) {
1598
1696
  }
1599
1697
 
1600
1698
  // src/hooks/use-authenticated-image.ts
1601
- import { useEffect as useEffect10, useState as useState15, useRef as useRef7 } from "react";
1699
+ import { useEffect as useEffect12, useState as useState17, useRef as useRef7 } from "react";
1602
1700
  var globalImageConfig = {};
1603
1701
  var imageCache = /* @__PURE__ */ new Map();
1604
1702
  var pendingRequests = /* @__PURE__ */ new Map();
@@ -1627,11 +1725,11 @@ function getImageConfig() {
1627
1725
  };
1628
1726
  }
1629
1727
  function useAuthenticatedImage(imageUrl, refreshKey, config) {
1630
- const [fetchedImageUrl, setFetchedImageUrl] = useState15();
1631
- const [isLoading, setIsLoading] = useState15(false);
1632
- const [error, setError] = useState15(null);
1728
+ const [fetchedImageUrl, setFetchedImageUrl] = useState17();
1729
+ const [isLoading, setIsLoading] = useState17(false);
1730
+ const [error, setError] = useState17(null);
1633
1731
  const currentCacheKeyRef = useRef7(null);
1634
- useEffect10(() => {
1732
+ useEffect12(() => {
1635
1733
  if (!imageUrl) {
1636
1734
  setFetchedImageUrl(void 0);
1637
1735
  setIsLoading(false);
@@ -1742,7 +1840,7 @@ function useAuthenticatedImage(imageUrl, refreshKey, config) {
1742
1840
  });
1743
1841
  pendingRequests.set(cacheKey, fetchPromise2);
1744
1842
  }, [imageUrl, refreshKey, config]);
1745
- useEffect10(() => {
1843
+ useEffect12(() => {
1746
1844
  return () => {
1747
1845
  if (currentCacheKeyRef.current) {
1748
1846
  const entry = imageCache.get(currentCacheKeyRef.current);
@@ -1757,7 +1855,7 @@ function useAuthenticatedImage(imageUrl, refreshKey, config) {
1757
1855
 
1758
1856
  // src/hooks/state/use-query-params.ts
1759
1857
  init_next_navigation();
1760
- import { useEffect as useEffect11, useState as useState16, useMemo as useMemo3, useCallback as useCallback8 } from "react";
1858
+ import { useEffect as useEffect13, useState as useState18, useMemo as useMemo3, useCallback as useCallback9 } from "react";
1761
1859
 
1762
1860
  // src/hooks/state/graphql-parser.ts
1763
1861
  import {
@@ -2219,14 +2317,14 @@ var introspector = new GraphQLIntrospector();
2219
2317
  function useQueryParams(query, options = {}) {
2220
2318
  const router = useRouter();
2221
2319
  const searchParams = useSearchParams();
2222
- const [isLoading, setIsLoading] = useState16(true);
2223
- const [isReady, setIsReady] = useState16(false);
2224
- const [error, setError] = useState16(null);
2225
- const [schema, setSchema] = useState16({});
2320
+ const [isLoading, setIsLoading] = useState18(true);
2321
+ const [isReady, setIsReady] = useState18(false);
2322
+ const [error, setError] = useState18(null);
2323
+ const [schema, setSchema] = useState18({});
2226
2324
  const defaultValues = options.defaultValues || {};
2227
2325
  const skipIntrospection = options.skipIntrospection || false;
2228
2326
  const debug = options.debug || false;
2229
- useEffect11(() => {
2327
+ useEffect13(() => {
2230
2328
  async function initialize() {
2231
2329
  try {
2232
2330
  if (debug) console.log("[useQueryParams] Initializing...");
@@ -2296,14 +2394,14 @@ function useQueryParams(query, options = {}) {
2296
2394
  });
2297
2395
  return result;
2298
2396
  }, [searchParams]);
2299
- const updateUrl = useCallback8((newParams) => {
2397
+ const updateUrl = useCallback9((newParams) => {
2300
2398
  const url = newParams.toString() ? `?${newParams.toString()}` : window.location.pathname;
2301
2399
  if (debug) {
2302
2400
  console.log("[useQueryParams] Updating URL:", url);
2303
2401
  }
2304
2402
  router.replace(url, { scroll: false });
2305
2403
  }, [router, debug]);
2306
- const setParam = useCallback8((key, value) => {
2404
+ const setParam = useCallback9((key, value) => {
2307
2405
  if (!isReady) {
2308
2406
  console.warn("[useQueryParams] Schema not ready, cannot set param");
2309
2407
  return;
@@ -2317,7 +2415,7 @@ function useQueryParams(query, options = {}) {
2317
2415
  console.error("[useQueryParams] Failed to set param:", err);
2318
2416
  }
2319
2417
  }, [variables, schema, isReady, updateUrl]);
2320
- const setParams = useCallback8((updates) => {
2418
+ const setParams = useCallback9((updates) => {
2321
2419
  if (!isReady) {
2322
2420
  console.warn("[useQueryParams] Schema not ready, cannot set params");
2323
2421
  return;
@@ -2331,7 +2429,7 @@ function useQueryParams(query, options = {}) {
2331
2429
  console.error("[useQueryParams] Failed to set params:", err);
2332
2430
  }
2333
2431
  }, [variables, schema, isReady, updateUrl]);
2334
- const clearParamsHandler = useCallback8((keys) => {
2432
+ const clearParamsHandler = useCallback9((keys) => {
2335
2433
  if (!isReady) {
2336
2434
  console.warn("[useQueryParams] Schema not ready, cannot clear params");
2337
2435
  return;
@@ -2345,7 +2443,7 @@ function useQueryParams(query, options = {}) {
2345
2443
  console.error("[useQueryParams] Failed to clear params:", err);
2346
2444
  }
2347
2445
  }, [variables, schema, isReady, updateUrl]);
2348
- const resetParams = useCallback8(() => {
2446
+ const resetParams = useCallback9(() => {
2349
2447
  if (debug) {
2350
2448
  console.log("[useQueryParams] Resetting params");
2351
2449
  }
@@ -2378,7 +2476,7 @@ function applyParamMapping(schema, mapping) {
2378
2476
 
2379
2477
  // src/hooks/state/use-api-params.ts
2380
2478
  init_next_navigation();
2381
- import { useCallback as useCallback9, useMemo as useMemo4, useRef as useRef8 } from "react";
2479
+ import { useCallback as useCallback10, useMemo as useMemo4, useRef as useRef8 } from "react";
2382
2480
  function useContentStable(value, key) {
2383
2481
  const ref = useRef8(void 0);
2384
2482
  if (ref.current && ref.current.key === key) return ref.current.value;
@@ -2437,7 +2535,7 @@ function useApiParams(schema, options = {}) {
2437
2535
  prevParamsRef.current = result;
2438
2536
  return result;
2439
2537
  }, [searchString, schemaKey, debug]);
2440
- const addParamToSearchParams = useCallback9((searchParams, key, value) => {
2538
+ const addParamToSearchParams = useCallback10((searchParams, key, value) => {
2441
2539
  if (value === void 0 || value === "" || value === null) {
2442
2540
  return;
2443
2541
  }
@@ -2465,7 +2563,7 @@ function useApiParams(schema, options = {}) {
2465
2563
  }
2466
2564
  return newParams;
2467
2565
  }, [params, schemaKey, flattenedSchema, addParamToSearchParams]);
2468
- const updateUrl = useCallback9((newParams, keysToRemove = []) => {
2566
+ const updateUrl = useCallback10((newParams, keysToRemove = []) => {
2469
2567
  const finalParams = new URLSearchParams(searchString);
2470
2568
  keysToRemove.forEach((key) => {
2471
2569
  if (key in stableSchema) {
@@ -2501,7 +2599,7 @@ function useApiParams(schema, options = {}) {
2501
2599
  }
2502
2600
  return false;
2503
2601
  };
2504
- const setParam = useCallback9((key, value) => {
2602
+ const setParam = useCallback10((key, value) => {
2505
2603
  const config = stableSchema[key];
2506
2604
  if (!config) {
2507
2605
  console.warn(`[useApiParams] Unknown parameter: ${key}`);
@@ -2515,7 +2613,7 @@ function useApiParams(schema, options = {}) {
2515
2613
  updateUrl(newParams);
2516
2614
  }
2517
2615
  }, [schemaKey, updateUrl, addParamToSearchParams]);
2518
- const setParams = useCallback9((updates) => {
2616
+ const setParams = useCallback10((updates) => {
2519
2617
  const newParams = new URLSearchParams();
2520
2618
  const keysToRemove = [];
2521
2619
  for (const [key, value] of Object.entries(updates)) {
@@ -2532,11 +2630,11 @@ function useApiParams(schema, options = {}) {
2532
2630
  }
2533
2631
  updateUrl(newParams, keysToRemove);
2534
2632
  }, [schemaKey, updateUrl, addParamToSearchParams]);
2535
- const clearParams2 = useCallback9((keys) => {
2633
+ const clearParams2 = useCallback10((keys) => {
2536
2634
  const newParams = new URLSearchParams();
2537
2635
  updateUrl(newParams, keys);
2538
2636
  }, [updateUrl]);
2539
- const resetParams = useCallback9(() => {
2637
+ const resetParams = useCallback10(() => {
2540
2638
  if (debug) {
2541
2639
  console.log("[useApiParams] Resetting params");
2542
2640
  }
@@ -2573,7 +2671,7 @@ function createSearchParams(params) {
2573
2671
  }
2574
2672
 
2575
2673
  // src/hooks/state/use-cursor-pagination-state.ts
2576
- import { useCallback as useCallback10, useEffect as useEffect12, useRef as useRef9, useState as useState17 } from "react";
2674
+ import { useCallback as useCallback11, useEffect as useEffect14, useRef as useRef9, useState as useState19 } from "react";
2577
2675
  var urlSchema = {
2578
2676
  search: { type: "string", default: "" },
2579
2677
  cursor: { type: "string", default: "" }
@@ -2584,13 +2682,13 @@ function useCursorPaginationState(options) {
2584
2682
  onSearchChange
2585
2683
  } = options;
2586
2684
  const { params, setParam, setParams } = useApiParams(urlSchema);
2587
- const [searchInput, setSearchInput] = useState17(params.search || "");
2588
- const [hasLoadedBeyondFirst, setHasLoadedBeyondFirst] = useState17(false);
2589
- const [initialLoadCount, setInitialLoadCount] = useState17(0);
2685
+ const [searchInput, setSearchInput] = useState19(params.search || "");
2686
+ const [hasLoadedBeyondFirst, setHasLoadedBeyondFirst] = useState19(false);
2687
+ const [initialLoadCount, setInitialLoadCount] = useState19(0);
2590
2688
  const lastSearchRef = useRef9(null);
2591
2689
  const isSyncingFromUrl = useRef9(false);
2592
2690
  const isInitialLoadInProgress = useRef9(true);
2593
- useEffect12(() => {
2691
+ useEffect14(() => {
2594
2692
  if (isInitialLoadInProgress.current) return;
2595
2693
  const urlSearch = params.search || "";
2596
2694
  if (urlSearch !== searchInput) {
@@ -2601,7 +2699,7 @@ function useCursorPaginationState(options) {
2601
2699
  }, 0);
2602
2700
  }
2603
2701
  }, [params.search, initialLoadCount]);
2604
- useEffect12(() => {
2702
+ useEffect14(() => {
2605
2703
  if (isInitialLoadInProgress.current) return;
2606
2704
  if (isSyncingFromUrl.current) return;
2607
2705
  if (searchInput !== params.search) {
@@ -2612,7 +2710,7 @@ function useCursorPaginationState(options) {
2612
2710
  });
2613
2711
  }
2614
2712
  }, [searchInput, params.search, setParams, initialLoadCount]);
2615
- useEffect12(() => {
2713
+ useEffect14(() => {
2616
2714
  if (initialLoadCount === 0) {
2617
2715
  const cursor = params.cursor || null;
2618
2716
  const search = params.search || "";
@@ -2626,7 +2724,7 @@ function useCursorPaginationState(options) {
2626
2724
  });
2627
2725
  }
2628
2726
  }, []);
2629
- useEffect12(() => {
2727
+ useEffect14(() => {
2630
2728
  if (isInitialLoadInProgress.current) return;
2631
2729
  if (initialLoadCount === 0) return;
2632
2730
  const currentSearch = params.search || "";
@@ -2636,7 +2734,7 @@ function useCursorPaginationState(options) {
2636
2734
  onSearchChange(currentSearch);
2637
2735
  }
2638
2736
  }, [params.search, onSearchChange, initialLoadCount]);
2639
- const handleNextPage = useCallback10(
2737
+ const handleNextPage = useCallback11(
2640
2738
  async (endCursor, fetchFn) => {
2641
2739
  setParam("cursor", endCursor);
2642
2740
  await fetchFn();
@@ -2644,7 +2742,7 @@ function useCursorPaginationState(options) {
2644
2742
  },
2645
2743
  [setParam]
2646
2744
  );
2647
- const handleResetToFirstPage = useCallback10(
2745
+ const handleResetToFirstPage = useCallback11(
2648
2746
  async (fetchFn) => {
2649
2747
  setParam("cursor", "");
2650
2748
  await fetchFn();
@@ -2666,16 +2764,16 @@ function useCursorPaginationState(options) {
2666
2764
  }
2667
2765
 
2668
2766
  // src/hooks/nats/use-nats-client.ts
2669
- import { useEffect as useEffect13, useMemo as useMemo5, useState as useState18 } from "react";
2767
+ import { useEffect as useEffect15, useMemo as useMemo5, useState as useState20 } from "react";
2670
2768
  function useNatsClient(clientOptions, options = {}) {
2671
2769
  const { autoConnect = true } = options;
2672
2770
  const client = useMemo5(() => {
2673
2771
  if (!clientOptions) return null;
2674
2772
  return createNatsClient(clientOptions);
2675
2773
  }, [clientOptions]);
2676
- const [status, setStatus] = useState18("disconnected");
2677
- const [lastError, setLastError] = useState18(null);
2678
- useEffect13(() => {
2774
+ const [status, setStatus] = useState20("disconnected");
2775
+ const [lastError, setLastError] = useState20(null);
2776
+ useEffect15(() => {
2679
2777
  if (!client) {
2680
2778
  setStatus("disconnected");
2681
2779
  setLastError(null);
@@ -2808,7 +2906,7 @@ function useAccessCodeIntegration() {
2808
2906
  }
2809
2907
 
2810
2908
  // src/hooks/use-humanity-signals.ts
2811
- import { useCallback as useCallback11, useRef as useRef10 } from "react";
2909
+ import { useCallback as useCallback12, useRef as useRef10 } from "react";
2812
2910
 
2813
2911
  // src/utils/humanity-signals.ts
2814
2912
  var HONEYPOT_FIELD = "contact_url_confirm";
@@ -2834,14 +2932,14 @@ var splitCsvEnv = (s) => s?.split(",").map((t) => t.trim()).filter(Boolean) ?? [
2834
2932
  function useHumanitySignals() {
2835
2933
  const ref = useRef10(null);
2836
2934
  const mountedAt = useRef10(typeof performance !== "undefined" ? performance.now() : 0);
2837
- const getSignals = useCallback11(
2935
+ const getSignals = useCallback12(
2838
2936
  () => ({
2839
2937
  [HONEYPOT_FIELD]: ref.current?.value ?? "",
2840
2938
  [ELAPSED_MS_FIELD]: typeof performance !== "undefined" ? Math.round(performance.now() - mountedAt.current) : 0
2841
2939
  }),
2842
2940
  []
2843
2941
  );
2844
- const resetSignals = useCallback11(() => {
2942
+ const resetSignals = useCallback12(() => {
2845
2943
  if (ref.current) ref.current.value = "";
2846
2944
  if (typeof performance !== "undefined") mountedAt.current = performance.now();
2847
2945
  }, []);
@@ -2849,6 +2947,9 @@ function useHumanitySignals() {
2849
2947
  }
2850
2948
 
2851
2949
  export {
2950
+ useHeaderHeight,
2951
+ useHorizontalScrollbar,
2952
+ useImageEdgeColor,
2852
2953
  useLocalStorage,
2853
2954
  useMediaQuery,
2854
2955
  breakpoints,
@@ -2856,13 +2957,12 @@ export {
2856
2957
  useMdUp,
2857
2958
  useLgUp,
2858
2959
  useMemoizedCallback,
2960
+ useNotificationPermission,
2859
2961
  useOnboardingState,
2962
+ useSearch,
2860
2963
  useTablePagination,
2861
2964
  useThrottle,
2862
2965
  useWindowSize,
2863
- useHorizontalScrollbar,
2864
- useImageEdgeColor,
2865
- useSearch,
2866
2966
  platformIcons,
2867
2967
  platformColors,
2868
2968
  platformDisplayNames,
@@ -2939,4 +3039,4 @@ export {
2939
3039
  splitCsvEnv,
2940
3040
  useHumanitySignals
2941
3041
  };
2942
- //# sourceMappingURL=chunk-6GBA6YJN.js.map
3042
+ //# sourceMappingURL=chunk-ZMFT5XOB.js.map