@caffeinebounce/ui 0.62.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +39 -0
  3. package/dist/FinancialStatementTable-BNUrdTU4.d.cts +249 -0
  4. package/dist/FinancialStatementTable-BNUrdTU4.d.ts +249 -0
  5. package/dist/NewsletterSignup-BPreFi5W.d.cts +37 -0
  6. package/dist/NewsletterSignup-BPreFi5W.d.ts +37 -0
  7. package/dist/TestimonialsSection-DtPu2OeR.d.ts +736 -0
  8. package/dist/TestimonialsSection-z-yotRfv.d.cts +736 -0
  9. package/dist/UnifiedTableControls-CG299y9h.d.ts +1233 -0
  10. package/dist/UnifiedTableControls-CIjRpNhy.d.cts +1233 -0
  11. package/dist/blog.d.cts +99 -0
  12. package/dist/blog.d.ts +99 -0
  13. package/dist/blog.js +292 -0
  14. package/dist/blog.mjs +279 -0
  15. package/dist/button-BHnoRUkF.d.cts +34 -0
  16. package/dist/button-BHnoRUkF.d.ts +34 -0
  17. package/dist/charts.d.cts +80 -0
  18. package/dist/charts.d.ts +80 -0
  19. package/dist/charts.js +19 -0
  20. package/dist/charts.mjs +2 -0
  21. package/dist/chunk-33JR5SYE.js +44 -0
  22. package/dist/chunk-3NDB4YPC.js +247 -0
  23. package/dist/chunk-5RW4PYZ6.js +1504 -0
  24. package/dist/chunk-5THF4YP6.mjs +155 -0
  25. package/dist/chunk-6BUBNZPG.mjs +164 -0
  26. package/dist/chunk-6DVWMJ3H.mjs +7029 -0
  27. package/dist/chunk-6TGV2DNP.js +120 -0
  28. package/dist/chunk-72JGQ7IJ.mjs +1498 -0
  29. package/dist/chunk-7DHKQODW.mjs +2932 -0
  30. package/dist/chunk-7IKHZKAC.js +160 -0
  31. package/dist/chunk-ADIDI7AJ.js +11 -0
  32. package/dist/chunk-BFWX5GJZ.mjs +940 -0
  33. package/dist/chunk-BMFQG6RA.mjs +5537 -0
  34. package/dist/chunk-C4UT5V3P.js +65 -0
  35. package/dist/chunk-CC4KUIKC.js +2004 -0
  36. package/dist/chunk-D3QXPL47.mjs +1814 -0
  37. package/dist/chunk-DQWHYBV2.js +36 -0
  38. package/dist/chunk-E42B4GSB.js +993 -0
  39. package/dist/chunk-ESZ7CBA2.js +1007 -0
  40. package/dist/chunk-EYJJQVV4.js +111 -0
  41. package/dist/chunk-FRRS2YZH.mjs +129 -0
  42. package/dist/chunk-G5TQWWQA.mjs +37 -0
  43. package/dist/chunk-GAIQJCAZ.js +5612 -0
  44. package/dist/chunk-GMBGWOCR.mjs +48 -0
  45. package/dist/chunk-GUSTCU2W.mjs +105 -0
  46. package/dist/chunk-HBLKVQIQ.mjs +23 -0
  47. package/dist/chunk-HMAMMC72.js +26 -0
  48. package/dist/chunk-IMKLN273.mjs +9 -0
  49. package/dist/chunk-J6OLBSZR.js +250 -0
  50. package/dist/chunk-JAE45W2T.js +28 -0
  51. package/dist/chunk-JORVSG52.js +606 -0
  52. package/dist/chunk-KB7UXIQZ.mjs +984 -0
  53. package/dist/chunk-KGGQ5NZV.js +186 -0
  54. package/dist/chunk-KHCC5UKW.mjs +22 -0
  55. package/dist/chunk-KRRIRS6A.mjs +1945 -0
  56. package/dist/chunk-LQCVRWVF.js +48 -0
  57. package/dist/chunk-MHZXUOGN.mjs +168 -0
  58. package/dist/chunk-MPZFPU4X.js +349 -0
  59. package/dist/chunk-MVYRNJA6.js +74 -0
  60. package/dist/chunk-N6AFNFZR.mjs +565 -0
  61. package/dist/chunk-OFQLWSUR.mjs +214 -0
  62. package/dist/chunk-OLAAXLXY.mjs +219 -0
  63. package/dist/chunk-OZZWDIOY.js +1859 -0
  64. package/dist/chunk-PZRI43EZ.js +111 -0
  65. package/dist/chunk-Q256HRYD.js +176 -0
  66. package/dist/chunk-Q52ZEL62.mjs +223 -0
  67. package/dist/chunk-R26Y7LGJ.js +142 -0
  68. package/dist/chunk-RBUYW6QQ.js +39 -0
  69. package/dist/chunk-RVEFPVZF.mjs +43 -0
  70. package/dist/chunk-SORWLKOK.js +96 -0
  71. package/dist/chunk-STEP6C4C.mjs +33 -0
  72. package/dist/chunk-T5R6HUDG.mjs +22 -0
  73. package/dist/chunk-T6ZBA6VJ.js +7109 -0
  74. package/dist/chunk-UM7WMXIU.js +2995 -0
  75. package/dist/chunk-VBD4Q5LL.mjs +117 -0
  76. package/dist/chunk-WOITB4JL.js +195 -0
  77. package/dist/chunk-YKZEKJMZ.mjs +71 -0
  78. package/dist/chunk-YL7RZRHM.mjs +103 -0
  79. package/dist/chunk-YSLD2HLP.mjs +346 -0
  80. package/dist/chunk-ZFLZA7UP.mjs +140 -0
  81. package/dist/chunk-ZKUIUE7W.mjs +26 -0
  82. package/dist/chunk-ZOA7B32D.js +248 -0
  83. package/dist/data-table.d.cts +46 -0
  84. package/dist/data-table.d.ts +46 -0
  85. package/dist/data-table.js +270 -0
  86. package/dist/data-table.mjs +13 -0
  87. package/dist/editor.d.cts +89 -0
  88. package/dist/editor.d.ts +89 -0
  89. package/dist/editor.js +10 -0
  90. package/dist/editor.mjs +1 -0
  91. package/dist/forms.d.cts +142 -0
  92. package/dist/forms.d.ts +142 -0
  93. package/dist/forms.js +24 -0
  94. package/dist/forms.mjs +11 -0
  95. package/dist/hooks-8ORd7T1A.d.cts +751 -0
  96. package/dist/hooks-B2jU1GVT.d.ts +751 -0
  97. package/dist/hooks.d.cts +6 -0
  98. package/dist/hooks.d.ts +6 -0
  99. package/dist/hooks.js +99 -0
  100. package/dist/hooks.mjs +10 -0
  101. package/dist/index.d.cts +3141 -0
  102. package/dist/index.d.ts +3141 -0
  103. package/dist/index.js +7332 -0
  104. package/dist/index.mjs +5876 -0
  105. package/dist/layouts-DPfDDF53.d.cts +1001 -0
  106. package/dist/layouts-DPfDDF53.d.ts +1001 -0
  107. package/dist/layouts.d.cts +4 -0
  108. package/dist/layouts.d.ts +4 -0
  109. package/dist/layouts.js +100 -0
  110. package/dist/layouts.mjs +11 -0
  111. package/dist/marketing-3d.d.cts +51 -0
  112. package/dist/marketing-3d.d.ts +51 -0
  113. package/dist/marketing-3d.js +553 -0
  114. package/dist/marketing-3d.mjs +526 -0
  115. package/dist/marketing.d.cts +583 -0
  116. package/dist/marketing.d.ts +583 -0
  117. package/dist/marketing.js +299 -0
  118. package/dist/marketing.mjs +10 -0
  119. package/dist/media.d.cts +29 -0
  120. package/dist/media.d.ts +29 -0
  121. package/dist/media.js +189 -0
  122. package/dist/media.mjs +182 -0
  123. package/dist/navigation.d.cts +591 -0
  124. package/dist/navigation.d.ts +591 -0
  125. package/dist/navigation.js +108 -0
  126. package/dist/navigation.mjs +15 -0
  127. package/dist/portal.d.cts +58 -0
  128. package/dist/portal.d.ts +58 -0
  129. package/dist/portal.js +403 -0
  130. package/dist/portal.mjs +395 -0
  131. package/dist/primitives.d.cts +508 -0
  132. package/dist/primitives.d.ts +508 -0
  133. package/dist/primitives.js +295 -0
  134. package/dist/primitives.mjs +14 -0
  135. package/dist/settings.d.cts +216 -0
  136. package/dist/settings.d.ts +216 -0
  137. package/dist/settings.js +34 -0
  138. package/dist/settings.mjs +9 -0
  139. package/dist/shared-Dqn36QHZ.d.cts +4 -0
  140. package/dist/shared-Dqn36QHZ.d.ts +4 -0
  141. package/dist/styles.css +1213 -0
  142. package/package.json +189 -0
  143. package/styles.css +1 -0
@@ -0,0 +1,1007 @@
1
+ 'use strict';
2
+
3
+ var chunkUM7WMXIU_js = require('./chunk-UM7WMXIU.js');
4
+ var react = require('react');
5
+ var dateFns = require('date-fns');
6
+ var sonner = require('sonner');
7
+
8
+ var DEFAULT_MAX_ERRORS = 20;
9
+ var DEFAULT_STORAGE_KEY = "session_errors";
10
+ var listenersInitialized = false;
11
+ var currentStorageKey = DEFAULT_STORAGE_KEY;
12
+ var currentMaxErrors = DEFAULT_MAX_ERRORS;
13
+ function addError(error) {
14
+ if (typeof window === "undefined") return;
15
+ try {
16
+ const stored = sessionStorage.getItem(currentStorageKey);
17
+ const errors = stored ? JSON.parse(stored) : [];
18
+ const truncatedError = {
19
+ ...error,
20
+ stack: error.stack?.slice(0, 2e3)
21
+ };
22
+ errors.push(truncatedError);
23
+ if (errors.length > currentMaxErrors) {
24
+ errors.shift();
25
+ }
26
+ sessionStorage.setItem(currentStorageKey, JSON.stringify(errors));
27
+ } catch (e) {
28
+ if (e instanceof DOMException && (e.name === "QuotaExceededError" || e.code === 22)) {
29
+ console.warn(
30
+ "[useSessionErrors] sessionStorage quota exceeded. Recent errors may not be tracked."
31
+ );
32
+ } else {
33
+ console.warn("[useSessionErrors] Failed to store error:", e);
34
+ }
35
+ }
36
+ }
37
+ function initializeErrorListeners() {
38
+ if (listenersInitialized || typeof window === "undefined") return;
39
+ listenersInitialized = true;
40
+ const handleError = (event) => {
41
+ addError({
42
+ message: event.message || "Unknown error",
43
+ stack: event.error?.stack,
44
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
45
+ type: "error"
46
+ });
47
+ };
48
+ const handleRejection = (event) => {
49
+ const reason = event.reason;
50
+ addError({
51
+ message: reason instanceof Error ? reason.message : String(reason) || "Unhandled promise rejection",
52
+ stack: reason instanceof Error ? reason.stack : void 0,
53
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
54
+ type: "unhandledrejection"
55
+ });
56
+ };
57
+ window.addEventListener("error", handleError);
58
+ window.addEventListener("unhandledrejection", handleRejection);
59
+ }
60
+ function useSessionErrors(options = {}) {
61
+ const { maxErrors = DEFAULT_MAX_ERRORS, storageKey = DEFAULT_STORAGE_KEY } = options;
62
+ if (!listenersInitialized) {
63
+ currentMaxErrors = maxErrors;
64
+ currentStorageKey = storageKey;
65
+ } else if (process.env.NODE_ENV !== "production" && (maxErrors !== currentMaxErrors || storageKey !== currentStorageKey)) {
66
+ console.warn(
67
+ `[useSessionErrors] Hook called with different options than initial configuration. Global listeners use: { maxErrors: ${currentMaxErrors}, storageKey: "${currentStorageKey}" }. Received: { maxErrors: ${maxErrors}, storageKey: "${storageKey}" }. Only the first configuration is used for global error listeners.`
68
+ );
69
+ }
70
+ react.useEffect(() => {
71
+ initializeErrorListeners();
72
+ }, []);
73
+ const getErrors = react.useCallback(() => {
74
+ if (typeof window === "undefined") return [];
75
+ try {
76
+ const stored = sessionStorage.getItem(storageKey);
77
+ return stored ? JSON.parse(stored) : [];
78
+ } catch {
79
+ return [];
80
+ }
81
+ }, [storageKey]);
82
+ const clearErrors = react.useCallback(() => {
83
+ if (typeof window === "undefined") return;
84
+ try {
85
+ sessionStorage.removeItem(storageKey);
86
+ } catch {
87
+ }
88
+ }, [storageKey]);
89
+ return { getErrors, clearErrors };
90
+ }
91
+ function useComparisonData({
92
+ useDataHook,
93
+ currentParams,
94
+ comparisonRanges,
95
+ comparisonMode,
96
+ comparisonPeriods,
97
+ toEntries,
98
+ getPeriodKey
99
+ }) {
100
+ const { data: response, isLoading } = useDataHook(currentParams);
101
+ const shouldFetchComparison = comparisonMode !== "none";
102
+ const comparisonEnabled = [0, 1, 2].map(
103
+ (index) => shouldFetchComparison && !!comparisonRanges[index]
104
+ );
105
+ const { data: compResp0 } = useDataHook({
106
+ ...currentParams,
107
+ periodStart: comparisonRanges[0]?.start ?? "",
108
+ periodEnd: comparisonRanges[0]?.end ?? "",
109
+ enabled: comparisonEnabled[0],
110
+ keepPrevious: true
111
+ });
112
+ const { data: compResp1 } = useDataHook({
113
+ ...currentParams,
114
+ periodStart: comparisonRanges[1]?.start ?? "",
115
+ periodEnd: comparisonRanges[1]?.end ?? "",
116
+ enabled: comparisonEnabled[1],
117
+ keepPrevious: true
118
+ });
119
+ const { data: compResp2 } = useDataHook({
120
+ ...currentParams,
121
+ periodStart: comparisonRanges[2]?.start ?? "",
122
+ periodEnd: comparisonRanges[2]?.end ?? "",
123
+ enabled: comparisonEnabled[2],
124
+ keepPrevious: true
125
+ });
126
+ const rawData = response?.data ?? [];
127
+ const entries = react.useMemo(() => {
128
+ const current = toEntries(rawData);
129
+ if (comparisonMode === "none") return current;
130
+ const compDataSets = [compResp0, compResp1, compResp2].filter(Boolean);
131
+ const compEntries = compDataSets.flatMap(
132
+ (result) => toEntries(result?.data ?? [])
133
+ );
134
+ return [...compEntries, ...current];
135
+ }, [rawData, comparisonMode, compResp0, compResp1, compResp2, toEntries]);
136
+ const currentPeriodCount = react.useMemo(
137
+ () => new Set(rawData.map(getPeriodKey)).size,
138
+ [rawData, getPeriodKey]
139
+ );
140
+ const currentPeriodKeys = react.useMemo(
141
+ () => Array.from(new Set(rawData.map(getPeriodKey))).sort(
142
+ (a, b) => b.localeCompare(a)
143
+ ),
144
+ [rawData, getPeriodKey]
145
+ );
146
+ const totalVisiblePeriodCount = react.useMemo(
147
+ () => new Set(entries.map((entry) => entry.period_first_day)).size,
148
+ [entries]
149
+ );
150
+ const showVariance = totalVisiblePeriodCount === 2 && !(comparisonMode === "previous" && comparisonPeriods > 1);
151
+ return {
152
+ response,
153
+ isLoading,
154
+ rawData,
155
+ entries,
156
+ currentPeriodCount,
157
+ currentPeriodKeys,
158
+ totalVisiblePeriodCount,
159
+ showVariance,
160
+ classes: response?.classes ?? [],
161
+ departments: response?.departments ?? []
162
+ };
163
+ }
164
+ function fallbackCopy(text) {
165
+ try {
166
+ const textarea = document.createElement("textarea");
167
+ textarea.value = text;
168
+ textarea.style.position = "fixed";
169
+ textarea.style.left = "-9999px";
170
+ textarea.style.top = "-9999px";
171
+ document.body.appendChild(textarea);
172
+ textarea.select();
173
+ const ok = document.execCommand("copy");
174
+ document.body.removeChild(textarea);
175
+ return ok;
176
+ } catch {
177
+ return false;
178
+ }
179
+ }
180
+ function useCopyToClipboard({
181
+ timeout = 2e3
182
+ } = {}) {
183
+ const [isCopied, setIsCopied] = react.useState(false);
184
+ const [copiedId, setCopiedId] = react.useState(null);
185
+ const copyToClipboard = react.useCallback(
186
+ (value, id) => {
187
+ if (typeof window === "undefined" || !value) return;
188
+ const onSuccess = () => {
189
+ setIsCopied(true);
190
+ if (id) setCopiedId(id);
191
+ setTimeout(() => {
192
+ setIsCopied(false);
193
+ if (id) setCopiedId(null);
194
+ }, timeout);
195
+ };
196
+ if (navigator.clipboard?.writeText) {
197
+ navigator.clipboard.writeText(value).then(onSuccess).catch(() => {
198
+ fallbackCopy(value) && onSuccess();
199
+ });
200
+ return;
201
+ }
202
+ fallbackCopy(value) && onSuccess();
203
+ },
204
+ [timeout]
205
+ );
206
+ return { isCopied, copiedId, copyToClipboard };
207
+ }
208
+ function useDebounce(value, delay = 500) {
209
+ const [debouncedValue, setDebouncedValue] = react.useState(value);
210
+ react.useEffect(() => {
211
+ const timer = setTimeout(() => {
212
+ setDebouncedValue(value);
213
+ }, delay);
214
+ return () => {
215
+ clearTimeout(timer);
216
+ };
217
+ }, [value, delay]);
218
+ return debouncedValue;
219
+ }
220
+ function getDefaultLtmRange() {
221
+ const now = /* @__PURE__ */ new Date();
222
+ const year = now.getFullYear();
223
+ const month = now.getMonth();
224
+ const start = new Date(year - 1, month, 1);
225
+ const end = new Date(year, month + 1, 0);
226
+ return {
227
+ start: start.toISOString().slice(0, 10),
228
+ end: end.toISOString().slice(0, 10)
229
+ };
230
+ }
231
+ function useFinancialStatementState({
232
+ initialGranularity = "ltm",
233
+ initialComparisonMode = "none",
234
+ initialComparisonPeriods = 1
235
+ } = {}) {
236
+ const defaultRange = react.useMemo(() => getDefaultLtmRange(), []);
237
+ const [granularity, setGranularity] = react.useState(initialGranularity);
238
+ const [periodStart, setPeriodStart] = react.useState(defaultRange.start);
239
+ const [periodEnd, setPeriodEnd] = react.useState(defaultRange.end);
240
+ const [timeUnit, setTimeUnit] = react.useState("month");
241
+ const [comparisonMode, setComparisonMode] = react.useState(
242
+ initialComparisonMode
243
+ );
244
+ const [comparisonPeriods, setComparisonPeriods] = react.useState(
245
+ initialComparisonPeriods
246
+ );
247
+ const [comparisonCustomStart, setComparisonCustomStart] = react.useState();
248
+ const [comparisonCustomEnd, setComparisonCustomEnd] = react.useState();
249
+ const [selectedClass, setSelectedClass] = react.useState("");
250
+ const [selectedDepartment, setSelectedDepartment] = react.useState("");
251
+ const [mobileFiltersOpen, setMobileFiltersOpen] = react.useState(false);
252
+ const [hideZeroRows, setHideZeroRows] = react.useState(true);
253
+ const [showRowTotals, setShowRowTotals] = react.useState(false);
254
+ const handlePeriodChange = react.useCallback(
255
+ (params) => {
256
+ setGranularity(params.granularity);
257
+ setPeriodStart(params.periodStart);
258
+ setPeriodEnd(params.periodEnd);
259
+ setTimeUnit(params.timeUnit);
260
+ },
261
+ []
262
+ );
263
+ const handleComparisonChange = react.useCallback(
264
+ (params) => {
265
+ if (granularity === "ltm") {
266
+ const ltmDefault = params.mode === "previous" && params.periods === 11;
267
+ if (!ltmDefault) {
268
+ const end = dateFns.endOfMonth(dateFns.parseISO(periodEnd));
269
+ const start = dateFns.startOfMonth(end);
270
+ setGranularity("month");
271
+ setTimeUnit("month");
272
+ setPeriodStart(start.toISOString().slice(0, 10));
273
+ setPeriodEnd(end.toISOString().slice(0, 10));
274
+ }
275
+ }
276
+ setComparisonMode(params.mode);
277
+ setComparisonPeriods(params.periods);
278
+ setComparisonCustomStart(params.customStart);
279
+ setComparisonCustomEnd(params.customEnd);
280
+ },
281
+ [granularity, periodEnd]
282
+ );
283
+ const priorRange = react.useMemo(() => {
284
+ const start = /* @__PURE__ */ new Date(`${periodStart}T00:00:00`);
285
+ const end = /* @__PURE__ */ new Date(`${periodEnd}T00:00:00`);
286
+ const durationMs = end.getTime() - start.getTime();
287
+ const priorEnd = new Date(start.getTime() - 1);
288
+ const priorStart = new Date(priorEnd.getTime() - durationMs);
289
+ return {
290
+ start: priorStart.toISOString().slice(0, 10),
291
+ end: priorEnd.toISOString().slice(0, 10)
292
+ };
293
+ }, [periodStart, periodEnd]);
294
+ const comparisonRanges = react.useMemo(() => {
295
+ if (comparisonMode === "none") return [];
296
+ if (comparisonMode === "custom" && comparisonCustomStart && comparisonCustomEnd) {
297
+ return [{ start: comparisonCustomStart, end: comparisonCustomEnd }];
298
+ }
299
+ const start = /* @__PURE__ */ new Date(`${periodStart}T00:00:00`);
300
+ const end = /* @__PURE__ */ new Date(`${periodEnd}T00:00:00`);
301
+ const durationMs = end.getTime() - start.getTime();
302
+ const ranges = [];
303
+ if (comparisonMode === "previous") {
304
+ const dayCount = Math.round(durationMs / 864e5) + 1;
305
+ const cEnd = new Date(start);
306
+ cEnd.setDate(cEnd.getDate() - 1);
307
+ const cStart = new Date(cEnd);
308
+ cStart.setDate(cStart.getDate() - (dayCount * comparisonPeriods - 1));
309
+ return [
310
+ {
311
+ start: cStart.toISOString().slice(0, 10),
312
+ end: cEnd.toISOString().slice(0, 10)
313
+ }
314
+ ];
315
+ }
316
+ for (let i = 1; i <= comparisonPeriods; i++) {
317
+ if (comparisonMode === "same-period-last-year") {
318
+ const cStart = new Date(start);
319
+ cStart.setFullYear(cStart.getFullYear() - i);
320
+ const cEnd = new Date(end);
321
+ cEnd.setFullYear(cEnd.getFullYear() - i);
322
+ ranges.push({
323
+ start: cStart.toISOString().slice(0, 10),
324
+ end: cEnd.toISOString().slice(0, 10)
325
+ });
326
+ }
327
+ }
328
+ return ranges;
329
+ }, [
330
+ comparisonMode,
331
+ comparisonPeriods,
332
+ comparisonCustomStart,
333
+ comparisonCustomEnd,
334
+ periodStart,
335
+ periodEnd
336
+ ]);
337
+ const formatPeriodLabel = react.useCallback((periodKey) => {
338
+ if (!periodKey) return "\u2014";
339
+ return dateFns.format(dateFns.parseISO(periodKey), "MMM yy");
340
+ }, []);
341
+ const activeFilterCount = (selectedClass ? 1 : 0) + (selectedDepartment ? 1 : 0) + (comparisonMode !== "none" ? 1 : 0);
342
+ const periodChipLabel = granularity === "ltm" ? "LTM" : granularity === "ytd" ? "YTD" : granularity === "month" ? "Month" : granularity === "quarter" ? "Quarter" : granularity === "year" ? "Year" : "Custom";
343
+ const comparisonChipLabel = granularity === "ltm" ? "vs Previous 11" : comparisonMode === "none" ? "No comparison" : comparisonMode === "previous" ? `vs Previous ${comparisonPeriods}` : comparisonMode === "same-period-last-year" ? `vs Last year (${comparisonPeriods})` : "Custom comparison";
344
+ const resetFilters = react.useCallback(() => {
345
+ setSelectedClass("");
346
+ setSelectedDepartment("");
347
+ setComparisonMode("none");
348
+ setComparisonPeriods(1);
349
+ setComparisonCustomStart(void 0);
350
+ setComparisonCustomEnd(void 0);
351
+ }, []);
352
+ return {
353
+ granularity,
354
+ periodStart,
355
+ periodEnd,
356
+ timeUnit,
357
+ selectedClass,
358
+ selectedDepartment,
359
+ comparisonMode,
360
+ comparisonPeriods,
361
+ comparisonCustomStart,
362
+ comparisonCustomEnd,
363
+ mobileFiltersOpen,
364
+ hideZeroRows,
365
+ showRowTotals,
366
+ priorRange,
367
+ comparisonRanges,
368
+ periodChipLabel,
369
+ comparisonChipLabel,
370
+ activeFilterCount,
371
+ formatPeriodLabel,
372
+ setSelectedClass,
373
+ setSelectedDepartment,
374
+ setMobileFiltersOpen,
375
+ setHideZeroRows,
376
+ setShowRowTotals,
377
+ handlePeriodChange,
378
+ handleComparisonChange,
379
+ resetFilters
380
+ };
381
+ }
382
+ function matchesShortcut(event, shortcut) {
383
+ if (shortcut.enabled === false) return false;
384
+ const ctrlMatch = shortcut.ctrl ? event.ctrlKey : !event.ctrlKey;
385
+ const shiftMatch = shortcut.shift ? event.shiftKey : !event.shiftKey;
386
+ const altMatch = shortcut.alt ? event.altKey : !event.altKey;
387
+ const metaMatch = shortcut.meta ? event.metaKey : !event.metaKey;
388
+ const keyMatch = event.key === shortcut.key;
389
+ return ctrlMatch && shiftMatch && altMatch && metaMatch && keyMatch;
390
+ }
391
+ function useKeyboardShortcut(shortcut, callback, options = {}) {
392
+ const {
393
+ enabled = true,
394
+ target = typeof document !== "undefined" ? document : null,
395
+ capture = false,
396
+ preventDefault = false,
397
+ stopPropagation = false
398
+ } = options;
399
+ const callbackRef = react.useRef(callback);
400
+ react.useEffect(() => {
401
+ callbackRef.current = callback;
402
+ }, [callback]);
403
+ react.useEffect(() => {
404
+ if (typeof window === "undefined") {
405
+ return;
406
+ }
407
+ if (!enabled || !target) {
408
+ return;
409
+ }
410
+ const handler = (event) => {
411
+ const keyboardEvent = event;
412
+ const target2 = keyboardEvent.target;
413
+ if (target2.tagName === "INPUT" || target2.tagName === "TEXTAREA" || target2.isContentEditable) {
414
+ return;
415
+ }
416
+ if (matchesShortcut(keyboardEvent, shortcut)) {
417
+ if (preventDefault) {
418
+ keyboardEvent.preventDefault();
419
+ }
420
+ if (stopPropagation) {
421
+ keyboardEvent.stopPropagation();
422
+ }
423
+ callbackRef.current(keyboardEvent);
424
+ }
425
+ };
426
+ target.addEventListener("keydown", handler, capture);
427
+ return () => {
428
+ target.removeEventListener("keydown", handler, capture);
429
+ };
430
+ }, [shortcut, enabled, target, capture, preventDefault, stopPropagation]);
431
+ }
432
+ function formatShortcut(shortcut, usePlatformSymbols = false) {
433
+ const parts = [];
434
+ const isMac = typeof navigator !== "undefined" && /Mac|iPhone|iPad|iPod/.test(navigator.userAgent);
435
+ if (shortcut.ctrl) {
436
+ parts.push(usePlatformSymbols && isMac ? "\u2303" : "Ctrl");
437
+ }
438
+ if (shortcut.alt) {
439
+ parts.push(usePlatformSymbols && isMac ? "\u2325" : "Alt");
440
+ }
441
+ if (shortcut.shift) {
442
+ parts.push(usePlatformSymbols && isMac ? "\u21E7" : "Shift");
443
+ }
444
+ if (shortcut.meta) {
445
+ parts.push(usePlatformSymbols && isMac ? "\u2318" : "Meta");
446
+ }
447
+ const keyDisplay = shortcut.key.length === 1 ? shortcut.key.toUpperCase() : shortcut.key;
448
+ parts.push(keyDisplay);
449
+ return parts.join(usePlatformSymbols ? "" : "+");
450
+ }
451
+ function useLocalStorage(key, initialValue) {
452
+ const readValue = react.useCallback(() => {
453
+ if (typeof window === "undefined" || !key) {
454
+ return initialValue;
455
+ }
456
+ try {
457
+ const item = window.localStorage.getItem(key);
458
+ return item ? JSON.parse(item) : initialValue;
459
+ } catch (error) {
460
+ console.warn(`Error reading localStorage key "${key}":`, error);
461
+ return initialValue;
462
+ }
463
+ }, [initialValue, key]);
464
+ const [storedValue, setStoredValue] = react.useState(initialValue);
465
+ const [isLoaded, setIsLoaded] = react.useState(false);
466
+ react.useEffect(() => {
467
+ setStoredValue(readValue());
468
+ setIsLoaded(true);
469
+ }, [readValue]);
470
+ const setValue = react.useCallback(
471
+ (value) => {
472
+ try {
473
+ setStoredValue((prevStoredValue) => {
474
+ const valueToStore = value instanceof Function ? value(prevStoredValue) : value;
475
+ if (typeof window !== "undefined" && key) {
476
+ window.localStorage.setItem(key, JSON.stringify(valueToStore));
477
+ window.dispatchEvent(
478
+ new StorageEvent("storage", {
479
+ key,
480
+ newValue: JSON.stringify(valueToStore),
481
+ url: window.location.href
482
+ })
483
+ );
484
+ }
485
+ return valueToStore;
486
+ });
487
+ } catch (error) {
488
+ console.warn(`Error setting localStorage key "${key}":`, error);
489
+ }
490
+ },
491
+ [key]
492
+ );
493
+ const removeValue = react.useCallback(() => {
494
+ try {
495
+ if (typeof window !== "undefined" && key) {
496
+ window.localStorage.removeItem(key);
497
+ window.dispatchEvent(
498
+ new StorageEvent("storage", {
499
+ key,
500
+ newValue: null
501
+ })
502
+ );
503
+ }
504
+ setStoredValue(initialValue);
505
+ } catch (error) {
506
+ console.warn(`Error removing localStorage key "${key}":`, error);
507
+ }
508
+ }, [initialValue, key]);
509
+ react.useEffect(() => {
510
+ if (!key) return;
511
+ const handleStorageChange = (event) => {
512
+ if (event.key === key && event.newValue !== null) {
513
+ try {
514
+ setStoredValue(JSON.parse(event.newValue));
515
+ } catch {
516
+ }
517
+ } else if (event.key === key && event.newValue === null) {
518
+ setStoredValue(initialValue);
519
+ }
520
+ };
521
+ window.addEventListener("storage", handleStorageChange);
522
+ return () => window.removeEventListener("storage", handleStorageChange);
523
+ }, [initialValue, key]);
524
+ return [storedValue, setValue, removeValue, isLoaded];
525
+ }
526
+ function useMediaQuery(query) {
527
+ const [matches, setMatches] = react.useState(false);
528
+ react.useEffect(() => {
529
+ if (typeof window === "undefined") {
530
+ return;
531
+ }
532
+ const mediaQuery = window.matchMedia(query);
533
+ setMatches(mediaQuery.matches);
534
+ const handleChange = (event) => {
535
+ setMatches(event.matches);
536
+ };
537
+ mediaQuery.addEventListener("change", handleChange);
538
+ return () => {
539
+ mediaQuery.removeEventListener("change", handleChange);
540
+ };
541
+ }, [query]);
542
+ return matches;
543
+ }
544
+ var breakpoints = {
545
+ sm: "(min-width: 640px)",
546
+ md: "(min-width: 768px)",
547
+ lg: "(min-width: 1024px)",
548
+ xl: "(min-width: 1280px)",
549
+ "2xl": "(min-width: 1536px)"
550
+ };
551
+ function useBreakpoints() {
552
+ const isSm = useMediaQuery(breakpoints.sm);
553
+ const isMd = useMediaQuery(breakpoints.md);
554
+ const isLg = useMediaQuery(breakpoints.lg);
555
+ const isXl = useMediaQuery(breakpoints.xl);
556
+ const is2xl = useMediaQuery(breakpoints["2xl"]);
557
+ return {
558
+ /** Below 640px */
559
+ isMobile: !isSm,
560
+ /** 640px - 767px */
561
+ isSm: isSm && !isMd,
562
+ /** 768px - 1023px */
563
+ isTablet: isMd && !isLg,
564
+ /** 768px+ */
565
+ isMd,
566
+ /** 1024px+ */
567
+ isDesktop: isLg,
568
+ /** 1024px - 1279px */
569
+ isLg: isLg && !isXl,
570
+ /** 1280px+ */
571
+ isXl,
572
+ /** 1536px+ */
573
+ is2xl
574
+ };
575
+ }
576
+ function useStatementExport({
577
+ entries,
578
+ config,
579
+ timeUnit,
580
+ subtotalRules,
581
+ hideZeroRows,
582
+ periodStart,
583
+ periodEnd,
584
+ filenamePrefix,
585
+ worksheetName
586
+ }) {
587
+ return react.useCallback(
588
+ (format2) => {
589
+ const { rows: flat, periodKeys } = chunkUM7WMXIU_js.flattenStatementForExport(
590
+ entries,
591
+ config,
592
+ timeUnit,
593
+ subtotalRules,
594
+ hideZeroRows
595
+ );
596
+ const headers = ["Account", ...periodKeys, "Total"];
597
+ const dataRows = flat.map((row) => [
598
+ row.account,
599
+ ...periodKeys.map((periodKey) => String(row[periodKey] ?? 0)),
600
+ String(row.total ?? 0)
601
+ ]);
602
+ const filename = `${filenamePrefix}-${periodStart}-to-${periodEnd}`;
603
+ if (format2 === "csv") {
604
+ const escapeCsv = (value) => `"${value.replace(/"/g, '""')}"`;
605
+ const csv = [
606
+ headers.map(escapeCsv).join(","),
607
+ ...dataRows.map((row) => row.map(escapeCsv).join(","))
608
+ ].join("\n");
609
+ const blob = new Blob([csv], { type: "text/csv;charset=utf-8;" });
610
+ const url = URL.createObjectURL(blob);
611
+ const anchor = document.createElement("a");
612
+ anchor.href = url;
613
+ anchor.download = `${filename}.csv`;
614
+ anchor.click();
615
+ URL.revokeObjectURL(url);
616
+ return;
617
+ }
618
+ const rowStart = 2;
619
+ const firstValueColumn = 1;
620
+ const lastValueColumn = periodKeys.length;
621
+ const totalColumn = headers.length - 1;
622
+ const rows = [
623
+ headers.map((header, index) => ({
624
+ value: header,
625
+ style: index === totalColumn ? "totalLabel" : "header"
626
+ })),
627
+ ...flat.map((row, rowIndex) => {
628
+ const excelRow = rowStart + rowIndex;
629
+ const totalFormula = `SUM(${chunkUM7WMXIU_js.excelColumnName(firstValueColumn)}${excelRow}:${chunkUM7WMXIU_js.excelColumnName(lastValueColumn)}${excelRow})`;
630
+ const periodCells = periodKeys.map(
631
+ (periodKey) => ({
632
+ value: Number(row[periodKey] ?? 0),
633
+ style: "currency",
634
+ type: "Number"
635
+ })
636
+ );
637
+ return [
638
+ { value: row.account, style: "text" },
639
+ ...periodCells,
640
+ {
641
+ formula: totalFormula,
642
+ value: Number(row.total ?? 0),
643
+ style: "totalNumber",
644
+ type: "Number"
645
+ }
646
+ ];
647
+ })
648
+ ];
649
+ const xml = chunkUM7WMXIU_js.buildSpreadsheetWorkbookXml({
650
+ worksheetName,
651
+ rows
652
+ });
653
+ chunkUM7WMXIU_js.downloadExcelXml(xml, filename);
654
+ },
655
+ [
656
+ config,
657
+ entries,
658
+ filenamePrefix,
659
+ hideZeroRows,
660
+ periodEnd,
661
+ periodStart,
662
+ subtotalRules,
663
+ timeUnit,
664
+ worksheetName
665
+ ]
666
+ );
667
+ }
668
+ function useStatementMobileMode({
669
+ isMobile,
670
+ entries,
671
+ currentPeriodKeys,
672
+ comparisonMode
673
+ }) {
674
+ const normalizedPeriodKeys = react.useMemo(
675
+ () => Array.from(new Set(currentPeriodKeys)).sort((a, b) => b.localeCompare(a)),
676
+ [currentPeriodKeys]
677
+ );
678
+ const [activePeriodIndex, setActivePeriodIndex] = react.useState(0);
679
+ const [compareEnabled, setCompareEnabled] = react.useState(false);
680
+ react.useEffect(() => {
681
+ setActivePeriodIndex(
682
+ (index) => normalizedPeriodKeys.length === 0 ? 0 : Math.min(index, normalizedPeriodKeys.length - 1)
683
+ );
684
+ }, [normalizedPeriodKeys.length]);
685
+ const activePeriod = normalizedPeriodKeys[activePeriodIndex] ?? normalizedPeriodKeys[0];
686
+ const comparisonPeriodKeys = react.useMemo(
687
+ () => Array.from(new Set(entries.map((entry) => entry.period_first_day))).filter((period) => !normalizedPeriodKeys.includes(period)).sort((a, b) => b.localeCompare(a)),
688
+ [entries, normalizedPeriodKeys]
689
+ );
690
+ const hasComparisonCandidate = comparisonMode === "none" ? normalizedPeriodKeys.length > 1 : comparisonPeriodKeys.length > 0;
691
+ react.useEffect(() => {
692
+ if (!hasComparisonCandidate) setCompareEnabled(false);
693
+ }, [hasComparisonCandidate]);
694
+ const mobileComparisonPeriod = react.useMemo(() => {
695
+ if (!compareEnabled || !activePeriod) return void 0;
696
+ if (comparisonMode !== "none") return comparisonPeriodKeys[0];
697
+ const activeIndex = normalizedPeriodKeys.indexOf(activePeriod);
698
+ return activeIndex >= 0 ? normalizedPeriodKeys[activeIndex + 1] : void 0;
699
+ }, [
700
+ compareEnabled,
701
+ activePeriod,
702
+ comparisonMode,
703
+ comparisonPeriodKeys,
704
+ normalizedPeriodKeys
705
+ ]);
706
+ const mobileVisiblePeriods = react.useMemo(() => {
707
+ if (!isMobile || !activePeriod) return null;
708
+ return mobileComparisonPeriod ? [activePeriod, mobileComparisonPeriod] : [activePeriod];
709
+ }, [isMobile, activePeriod, mobileComparisonPeriod]);
710
+ const mobileEntries = react.useMemo(() => {
711
+ if (!mobileVisiblePeriods) return entries;
712
+ const visible = new Set(mobileVisiblePeriods);
713
+ return entries.filter((entry) => visible.has(entry.period_first_day));
714
+ }, [entries, mobileVisiblePeriods]);
715
+ return {
716
+ activePeriodIndex,
717
+ setActivePeriodIndex,
718
+ compareEnabled,
719
+ setCompareEnabled,
720
+ mobileEntries,
721
+ periodLabel: activePeriod ?? "",
722
+ compareLabel: mobileComparisonPeriod,
723
+ hasPrev: activePeriodIndex > 0,
724
+ hasNext: normalizedPeriodKeys.length > 0 && activePeriodIndex < normalizedPeriodKeys.length - 1,
725
+ hasComparisonCandidate,
726
+ activePeriod
727
+ };
728
+ }
729
+ function toast(options) {
730
+ const { title, description, variant, duration } = options;
731
+ const message = title || description || "";
732
+ const toastOptions = {
733
+ description: title ? description : void 0,
734
+ duration
735
+ };
736
+ if (variant === "destructive") {
737
+ return sonner.toast.error(message, toastOptions);
738
+ }
739
+ return sonner.toast(message, toastOptions);
740
+ }
741
+ function useToast() {
742
+ return { toast };
743
+ }
744
+ function createDataRestorationHandler(form, defaultValues, onComplete) {
745
+ return (data) => {
746
+ const dataWithPossibleValues = data;
747
+ const { values: _ignoredValues, ...cleanData } = dataWithPossibleValues;
748
+ const actualData = Object.keys(cleanData).length > 0 ? cleanData : data;
749
+ const newValues = { ...defaultValues };
750
+ const keys = Object.keys(defaultValues);
751
+ for (const key of keys) {
752
+ const restoredValue = actualData[key];
753
+ if (restoredValue !== void 0 && restoredValue !== null) {
754
+ newValues[key] = restoredValue;
755
+ }
756
+ }
757
+ requestAnimationFrame(() => {
758
+ for (const key of keys) {
759
+ form.setFieldValue(key, newValues[key]);
760
+ }
761
+ setTimeout(() => {
762
+ for (const key of keys) {
763
+ form.validateField(key, "change");
764
+ }
765
+ onComplete?.();
766
+ }, 100);
767
+ });
768
+ };
769
+ }
770
+ function extractZodErrors(zodResult, fieldFilter) {
771
+ if (zodResult.success || !zodResult.error) {
772
+ return [];
773
+ }
774
+ const issues = zodResult.error.issues;
775
+ if (!fieldFilter) {
776
+ return issues.map((issue) => issue.message);
777
+ }
778
+ return issues.filter((issue) => {
779
+ const fieldName = issue.path[0];
780
+ return typeof fieldName === "string" && fieldFilter.includes(fieldName);
781
+ }).map((issue) => issue.message);
782
+ }
783
+ function createStepHasFieldErrors(steps, formFieldMeta) {
784
+ return (stepIndex) => {
785
+ const fields = steps[stepIndex]?.fields ?? [];
786
+ for (const fieldName of fields) {
787
+ const meta = formFieldMeta[fieldName];
788
+ if (meta?.errors && meta.errors.length > 0) {
789
+ return true;
790
+ }
791
+ }
792
+ return false;
793
+ };
794
+ }
795
+ function createFormResetHandler(form, defaultValues, resetWizardState, clearSubmitError) {
796
+ return () => {
797
+ form.reset();
798
+ const keys = Object.keys(defaultValues);
799
+ for (const key of keys) {
800
+ form.setFieldValue(key, defaultValues[key]);
801
+ }
802
+ resetWizardState();
803
+ clearSubmitError?.();
804
+ };
805
+ }
806
+ function createFormSubmitHandler(form, markAsSubmitted, options) {
807
+ const {
808
+ validateStep,
809
+ totalSteps,
810
+ errorLogger,
811
+ componentName,
812
+ getStepStatuses,
813
+ showValidationToast
814
+ } = options;
815
+ return () => {
816
+ markAsSubmitted();
817
+ form.validateAllFields("change");
818
+ const allValid = Array.from({ length: totalSteps }, (_, i) => i).every(
819
+ (index) => validateStep(index)
820
+ );
821
+ if (!allValid) {
822
+ showValidationToast?.(
823
+ "Please fix the errors in the highlighted sections."
824
+ );
825
+ errorLogger?.logError(new Error(`${componentName} validation failed`), {
826
+ component: componentName,
827
+ action: "submit",
828
+ metadata: { stepStatuses: getStepStatuses?.() }
829
+ });
830
+ return;
831
+ }
832
+ return form.handleSubmit();
833
+ };
834
+ }
835
+ function useWizardForm(options, currentValues) {
836
+ const {
837
+ steps,
838
+ validateStep,
839
+ getStepErrors,
840
+ stepHasFieldErrors,
841
+ initialStep = 0
842
+ } = options;
843
+ const [currentStep, setCurrentStep] = react.useState(initialStep);
844
+ const [highestStepReached, setHighestStepReached] = react.useState(initialStep);
845
+ const [stepsWithErrorsShown, setStepsWithErrorsShown] = react.useState(
846
+ /* @__PURE__ */ new Set()
847
+ );
848
+ const [hasAttemptedFinalSubmit, setHasAttemptedFinalSubmit] = react.useState(false);
849
+ const totalSteps = steps.length;
850
+ const isFirstStep = currentStep === 0;
851
+ const isLastStep = currentStep === totalSteps - 1;
852
+ const stepStatuses = react.useMemo(() => {
853
+ return steps.map((step, index) => {
854
+ const isCurrentStepIndex = index === currentStep;
855
+ const isValid = validateStep(index, currentValues);
856
+ step.optional ?? false;
857
+ const shouldShowErrors = hasAttemptedFinalSubmit || stepsWithErrorsShown.has(index);
858
+ const hasFieldErrors = shouldShowErrors && stepHasFieldErrors?.(index);
859
+ const hasMovedPastThisStep = index < highestStepReached;
860
+ const isFutureStep = index > highestStepReached;
861
+ if (shouldShowErrors && (!isValid || hasFieldErrors)) {
862
+ return "error";
863
+ }
864
+ if (isFutureStep && !hasAttemptedFinalSubmit) {
865
+ return "not-started";
866
+ }
867
+ if (isValid) {
868
+ return "complete";
869
+ }
870
+ if (hasMovedPastThisStep && !isCurrentStepIndex) {
871
+ return "incomplete";
872
+ }
873
+ return "not-started";
874
+ });
875
+ }, [
876
+ steps,
877
+ currentStep,
878
+ highestStepReached,
879
+ hasAttemptedFinalSubmit,
880
+ stepsWithErrorsShown,
881
+ validateStep,
882
+ stepHasFieldErrors,
883
+ currentValues
884
+ ]);
885
+ const hasIncompleteOrErrorSteps = react.useMemo(() => {
886
+ return stepStatuses.some(
887
+ (status) => status === "incomplete" || status === "error"
888
+ );
889
+ }, [stepStatuses]);
890
+ const isCurrentStepValid = react.useMemo(() => {
891
+ return validateStep(currentStep, currentValues);
892
+ }, [validateStep, currentStep, currentValues]);
893
+ const handleNext = react.useCallback(() => {
894
+ setStepsWithErrorsShown((prev) => new Set(prev).add(currentStep));
895
+ const nextStep = currentStep + 1;
896
+ if (nextStep < totalSteps) {
897
+ setCurrentStep(nextStep);
898
+ setHighestStepReached((prev) => Math.max(prev, nextStep));
899
+ }
900
+ }, [currentStep, totalSteps]);
901
+ const handleBack = react.useCallback(() => {
902
+ if (!isFirstStep) {
903
+ const prevStep = currentStep - 1;
904
+ setCurrentStep(prevStep);
905
+ }
906
+ }, [currentStep, isFirstStep]);
907
+ const handleStepClick = react.useCallback(
908
+ (stepIndex) => {
909
+ if (stepIndex !== currentStep) {
910
+ setStepsWithErrorsShown((prev) => new Set(prev).add(currentStep));
911
+ }
912
+ setCurrentStep(stepIndex);
913
+ if (stepIndex > highestStepReached) {
914
+ setHighestStepReached(stepIndex);
915
+ }
916
+ },
917
+ [currentStep, highestStepReached]
918
+ );
919
+ const markAsSubmitted = react.useCallback(() => {
920
+ setHasAttemptedFinalSubmit(true);
921
+ }, []);
922
+ const resetWizardState = react.useCallback(() => {
923
+ setCurrentStep(initialStep);
924
+ setHighestStepReached(initialStep);
925
+ setStepsWithErrorsShown(/* @__PURE__ */ new Set());
926
+ setHasAttemptedFinalSubmit(false);
927
+ }, [initialStep]);
928
+ const shouldShowErrorsForStep = react.useCallback(
929
+ (stepIndex) => {
930
+ return hasAttemptedFinalSubmit || stepsWithErrorsShown.has(stepIndex);
931
+ },
932
+ [hasAttemptedFinalSubmit, stepsWithErrorsShown]
933
+ );
934
+ const getStepStatus = react.useCallback(
935
+ (stepIndex) => stepStatuses[stepIndex],
936
+ [stepStatuses]
937
+ );
938
+ const getStepTooltip = react.useCallback(
939
+ (stepIndex, status) => {
940
+ if (status !== "error" && status !== "incomplete") return null;
941
+ if (getStepErrors) {
942
+ const stepErrors = getStepErrors(stepIndex, currentValues);
943
+ if (stepErrors.length > 0) {
944
+ return `${stepErrors.length} issue${stepErrors.length > 1 ? "s" : ""}:
945
+ \u2022 ${stepErrors.join("\n\u2022 ")}`;
946
+ }
947
+ }
948
+ return null;
949
+ },
950
+ [getStepErrors, currentValues]
951
+ );
952
+ const getStepFields = react.useCallback(
953
+ (stepIndex) => {
954
+ return steps[stepIndex]?.fields ?? [];
955
+ },
956
+ [steps]
957
+ );
958
+ return {
959
+ // Navigation state
960
+ currentStep,
961
+ totalSteps,
962
+ isFirstStep,
963
+ isLastStep,
964
+ highestStepReached,
965
+ // Validation state
966
+ stepsWithErrorsShown,
967
+ hasAttemptedFinalSubmit,
968
+ stepStatuses,
969
+ hasIncompleteOrErrorSteps,
970
+ isCurrentStepValid,
971
+ // Navigation handlers
972
+ handleNext,
973
+ handleBack,
974
+ handleStepClick,
975
+ // Submit handlers
976
+ markAsSubmitted,
977
+ resetWizardState,
978
+ // Utility functions
979
+ shouldShowErrorsForStep,
980
+ getStepStatus,
981
+ getStepTooltip,
982
+ getStepFields
983
+ };
984
+ }
985
+
986
+ exports.breakpoints = breakpoints;
987
+ exports.createDataRestorationHandler = createDataRestorationHandler;
988
+ exports.createFormResetHandler = createFormResetHandler;
989
+ exports.createFormSubmitHandler = createFormSubmitHandler;
990
+ exports.createStepHasFieldErrors = createStepHasFieldErrors;
991
+ exports.extractZodErrors = extractZodErrors;
992
+ exports.formatShortcut = formatShortcut;
993
+ exports.getDefaultLtmRange = getDefaultLtmRange;
994
+ exports.matchesShortcut = matchesShortcut;
995
+ exports.useBreakpoints = useBreakpoints;
996
+ exports.useComparisonData = useComparisonData;
997
+ exports.useCopyToClipboard = useCopyToClipboard;
998
+ exports.useDebounce = useDebounce;
999
+ exports.useFinancialStatementState = useFinancialStatementState;
1000
+ exports.useKeyboardShortcut = useKeyboardShortcut;
1001
+ exports.useLocalStorage = useLocalStorage;
1002
+ exports.useMediaQuery = useMediaQuery;
1003
+ exports.useSessionErrors = useSessionErrors;
1004
+ exports.useStatementExport = useStatementExport;
1005
+ exports.useStatementMobileMode = useStatementMobileMode;
1006
+ exports.useToast = useToast;
1007
+ exports.useWizardForm = useWizardForm;