@jmruthers/pace-core 0.5.193 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (191) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/README.md +7 -1
  3. package/cursor-rules/00-pace-core-compliance.mdc +372 -0
  4. package/cursor-rules/01-standards-compliance.mdc +275 -0
  5. package/cursor-rules/02-project-structure.mdc +200 -0
  6. package/cursor-rules/03-solid-principles.mdc +341 -0
  7. package/cursor-rules/04-testing-standards.mdc +315 -0
  8. package/cursor-rules/05-bug-reports-and-features.mdc +246 -0
  9. package/cursor-rules/06-code-quality.mdc +392 -0
  10. package/cursor-rules/07-tech-stack-compliance.mdc +309 -0
  11. package/cursor-rules/CHANGELOG.md +101 -0
  12. package/cursor-rules/README.md +191 -0
  13. package/dist/{DataTable-Be6dH_dR.d.ts → DataTable-CH1U5Tpy.d.ts} +1 -1
  14. package/dist/{DataTable-5FU7IESH.js → DataTable-DQ7RSOHE.js} +6 -6
  15. package/dist/{PublicPageProvider-C0Sm_e5k.d.ts → PublicPageProvider-ce4xlHYA.d.ts} +34 -155
  16. package/dist/{UnifiedAuthProvider-RGJTDE2C.js → UnifiedAuthProvider-ATAP5UTR.js} +2 -2
  17. package/dist/{chunk-6C4YBBJM 5.js → chunk-3QRJFVBR.js} +1 -1
  18. package/dist/chunk-3QRJFVBR.js.map +1 -0
  19. package/dist/{chunk-IIELH4DL.js → chunk-3XTALGJF.js} +2 -2
  20. package/dist/{chunk-IIELH4DL.js.map → chunk-3XTALGJF.js.map} +1 -1
  21. package/dist/{chunk-HWIIPPNI.js → chunk-4N5C5XZU.js} +20 -20
  22. package/dist/chunk-4N5C5XZU.js.map +1 -0
  23. package/dist/{chunk-7EQTDTTJ.js → chunk-4ZC4GX36.js} +5 -5
  24. package/dist/{chunk-7EQTDTTJ.js 2.map → chunk-4ZC4GX36.js.map} +1 -1
  25. package/dist/{chunk-7FLMSG37.js → chunk-BYFSK72L.js} +22 -22
  26. package/dist/chunk-BYFSK72L.js.map +1 -0
  27. package/dist/{chunk-LFNCN2SP.js → chunk-EXUD6RNJ.js} +46 -7
  28. package/dist/chunk-EXUD6RNJ.js.map +1 -0
  29. package/dist/{chunk-NOAYCWCX 5.js → chunk-GLK6VM3F.js} +167 -169
  30. package/dist/chunk-GLK6VM3F.js.map +1 -0
  31. package/dist/{chunk-HW3OVDUF.js → chunk-J36DSWQK.js} +1 -1
  32. package/dist/{chunk-HW3OVDUF.js.map → chunk-J36DSWQK.js.map} +1 -1
  33. package/dist/{chunk-BC4IJKSL.js → chunk-JBKQ3SAO.js} +2 -2
  34. package/dist/{chunk-QWWZ5CAQ.js → chunk-LXQLPRQ2.js} +2 -2
  35. package/dist/{chunk-E3SPN4VZ 5.js → chunk-T33XF5ZC.js} +119 -114
  36. package/dist/chunk-T33XF5ZC.js.map +1 -0
  37. package/dist/{chunk-XNXXZ43G.js → chunk-XM25TVIE.js} +27 -4
  38. package/dist/chunk-XM25TVIE.js.map +1 -0
  39. package/dist/components.d.ts +3 -3
  40. package/dist/components.js +8 -8
  41. package/dist/hooks.d.ts +6 -6
  42. package/dist/hooks.js +17 -22
  43. package/dist/hooks.js.map +1 -1
  44. package/dist/index.d.ts +7 -7
  45. package/dist/index.js +15 -16
  46. package/dist/index.js.map +1 -1
  47. package/dist/providers.js +1 -1
  48. package/dist/rbac/index.d.ts +1 -1
  49. package/dist/rbac/index.js +5 -5
  50. package/dist/{usePublicRouteParams-TZe0gy-4.d.ts → usePublicRouteParams-BJAlWfuJ.d.ts} +3 -3
  51. package/dist/{useToast-C8gR5ir4.d.ts → useToast-AyaT-x7p.d.ts} +2 -2
  52. package/dist/utils.d.ts +1 -1
  53. package/dist/utils.js +3 -3
  54. package/docs/getting-started/cursor-rules.md +262 -0
  55. package/docs/getting-started/installation-guide.md +6 -1
  56. package/docs/getting-started/quick-start.md +6 -1
  57. package/docs/migration/MIGRATION_GUIDE.md +4 -4
  58. package/docs/migration/REACT_19_MIGRATION.md +227 -0
  59. package/docs/standards/README.md +39 -0
  60. package/docs/troubleshooting/migration.md +4 -4
  61. package/examples/PublicPages/PublicEventPage.tsx +1 -1
  62. package/package.json +11 -6
  63. package/scripts/audit-consuming-app.cjs +961 -0
  64. package/scripts/check-pace-core-compliance.cjs +34 -15
  65. package/scripts/install-cursor-rules.cjs +236 -0
  66. package/src/__tests__/helpers/test-providers.tsx +1 -1
  67. package/src/__tests__/helpers/test-utils.tsx +1 -1
  68. package/src/components/Badge/Badge.tsx +2 -4
  69. package/src/components/Button/Button.tsx +5 -4
  70. package/src/components/Calendar/Calendar.tsx +1 -1
  71. package/src/components/DataTable/DataTable.test.tsx +57 -93
  72. package/src/components/DataTable/DataTable.tsx +2 -2
  73. package/src/components/DataTable/__tests__/pagination.modes.test.tsx +13 -5
  74. package/src/components/DataTable/__tests__/ssr.strict-mode.test.tsx +12 -12
  75. package/src/components/DataTable/components/AccessDeniedPage.tsx +1 -1
  76. package/src/components/DataTable/components/BulkOperationsDropdown.tsx +1 -1
  77. package/src/components/DataTable/components/DataTableCore.tsx +4 -7
  78. package/src/components/DataTable/components/DataTableModals.tsx +1 -1
  79. package/src/components/DataTable/components/EditableRow.tsx +1 -1
  80. package/src/components/DataTable/components/UnifiedTableBody.tsx +6 -8
  81. package/src/components/DataTable/components/__tests__/DataTableModals.test.tsx +23 -23
  82. package/src/components/DataTable/components/__tests__/EditableRow.test.tsx +11 -11
  83. package/src/components/DataTable/components/__tests__/ExpandButton.test.tsx +36 -36
  84. package/src/components/DataTable/components/__tests__/GroupHeader.test.tsx +27 -27
  85. package/src/components/DataTable/components/__tests__/ImportModal.test.tsx +39 -39
  86. package/src/components/DataTable/components/__tests__/UnifiedTableBody.test.tsx +33 -33
  87. package/src/components/DataTable/components/__tests__/ViewRowModal.test.tsx +29 -29
  88. package/src/components/DataTable/hooks/useColumnReordering.ts +2 -2
  89. package/src/components/DataTable/hooks/useKeyboardNavigation.ts +2 -2
  90. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +8 -14
  91. package/src/components/Dialog/Dialog.tsx +6 -5
  92. package/src/components/ErrorBoundary/ErrorBoundary.tsx +1 -1
  93. package/src/components/EventSelector/EventSelector.tsx +1 -1
  94. package/src/components/FileDisplay/FileDisplay.test.tsx +2 -2
  95. package/src/components/Footer/Footer.tsx +1 -1
  96. package/src/components/Form/Form.test.tsx +36 -15
  97. package/src/components/Form/Form.tsx +30 -26
  98. package/src/components/Header/Header.tsx +1 -1
  99. package/src/components/InactivityWarningModal/InactivityWarningModal.test.tsx +40 -40
  100. package/src/components/InactivityWarningModal/InactivityWarningModal.tsx +1 -1
  101. package/src/components/Input/Input.tsx +28 -30
  102. package/src/components/Label/Label.tsx +1 -1
  103. package/src/components/LoadingSpinner/LoadingSpinner.tsx +1 -1
  104. package/src/components/LoginForm/LoginForm.test.tsx +42 -42
  105. package/src/components/LoginForm/LoginForm.tsx +8 -8
  106. package/src/components/NavigationMenu/NavigationMenu.tsx +1 -1
  107. package/src/components/PaceAppLayout/PaceAppLayout.performance.test.tsx +1 -1
  108. package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +50 -50
  109. package/src/components/PaceAppLayout/PaceAppLayout.tsx +1 -1
  110. package/src/components/PaceAppLayout/README.md +1 -1
  111. package/src/components/PaceLoginPage/PaceLoginPage.tsx +1 -1
  112. package/src/components/PasswordChange/PasswordChangeForm.test.tsx +33 -33
  113. package/src/components/PasswordChange/PasswordChangeForm.tsx +1 -1
  114. package/src/components/Progress/Progress.tsx +1 -1
  115. package/src/components/PublicLayout/PublicPageLayout.tsx +1 -1
  116. package/src/components/Select/Select.tsx +33 -22
  117. package/src/components/SessionRestorationLoader/SessionRestorationLoader.tsx +1 -1
  118. package/src/components/Table/Table.tsx +1 -1
  119. package/src/components/Textarea/Textarea.tsx +27 -29
  120. package/src/components/Toast/Toast.tsx +1 -1
  121. package/src/components/Tooltip/Tooltip.tsx +1 -1
  122. package/src/components/UserMenu/UserMenu.tsx +1 -1
  123. package/src/hooks/__tests__/hooks.integration.test.tsx +80 -55
  124. package/src/hooks/__tests__/useStorage.unit.test.ts +36 -36
  125. package/src/hooks/public/usePublicEvent.ts +1 -1
  126. package/src/hooks/public/usePublicEventLogo.ts +1 -1
  127. package/src/hooks/public/usePublicRouteParams.ts +1 -1
  128. package/src/hooks/useDataTableState.ts +8 -18
  129. package/src/hooks/useFocusManagement.ts +2 -2
  130. package/src/hooks/useFocusTrap.ts +4 -4
  131. package/src/hooks/useFormDialog.ts +8 -7
  132. package/src/hooks/useInactivityTracker.ts +1 -1
  133. package/src/hooks/usePermissionCache.ts +1 -1
  134. package/src/hooks/useSecureDataAccess.ts +19 -4
  135. package/src/hooks/useToast.ts +2 -2
  136. package/src/providers/__tests__/OrganisationProvider.test.tsx +57 -13
  137. package/src/providers/__tests__/ProviderLifecycle.test.tsx +21 -6
  138. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +10 -10
  139. package/src/providers/services/UnifiedAuthProvider.tsx +22 -22
  140. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +13 -3
  141. package/src/rbac/__tests__/adapters.comprehensive.test.tsx +24 -24
  142. package/src/rbac/components/EnhancedNavigationMenu.tsx +1 -1
  143. package/src/rbac/components/NavigationGuard.tsx +1 -1
  144. package/src/rbac/components/NavigationProvider.tsx +1 -1
  145. package/src/rbac/components/PagePermissionGuard.tsx +1 -1
  146. package/src/rbac/components/PagePermissionProvider.tsx +1 -1
  147. package/src/rbac/components/PermissionEnforcer.tsx +1 -1
  148. package/src/rbac/components/RoleBasedRouter.tsx +1 -1
  149. package/src/rbac/components/SecureDataProvider.tsx +1 -1
  150. package/src/rbac/secureClient.ts +12 -0
  151. package/src/utils/security/secureDataAccess.test.ts +31 -20
  152. package/src/utils/security/secureDataAccess.ts +4 -3
  153. package/dist/chunk-6C4YBBJM.js +0 -628
  154. package/dist/chunk-6C4YBBJM.js.map +0 -1
  155. package/dist/chunk-7D4SUZUM.js 2.map +0 -1
  156. package/dist/chunk-7EQTDTTJ.js.map +0 -1
  157. package/dist/chunk-7FLMSG37.js 2.map +0 -1
  158. package/dist/chunk-7FLMSG37.js.map +0 -1
  159. package/dist/chunk-E3SPN4VZ.js +0 -12917
  160. package/dist/chunk-E3SPN4VZ.js.map +0 -1
  161. package/dist/chunk-E66EQZE6 5.js +0 -37
  162. package/dist/chunk-E66EQZE6.js 2.map +0 -1
  163. package/dist/chunk-HWIIPPNI.js.map +0 -1
  164. package/dist/chunk-I7PSE6JW 5.js +0 -191
  165. package/dist/chunk-I7PSE6JW.js 2.map +0 -1
  166. package/dist/chunk-KNC55RTG.js 5.map +0 -1
  167. package/dist/chunk-KQCRWDSA.js 5.map +0 -1
  168. package/dist/chunk-LFNCN2SP.js 2.map +0 -1
  169. package/dist/chunk-LFNCN2SP.js.map +0 -1
  170. package/dist/chunk-LMC26NLJ 2.js +0 -84
  171. package/dist/chunk-NOAYCWCX.js +0 -4993
  172. package/dist/chunk-NOAYCWCX.js.map +0 -1
  173. package/dist/chunk-QWWZ5CAQ.js.map +0 -1
  174. package/dist/chunk-QXHPKYJV 3.js +0 -113
  175. package/dist/chunk-R77UEZ4E 3.js +0 -68
  176. package/dist/chunk-VBXEHIUJ.js 6.map +0 -1
  177. package/dist/chunk-XNXXZ43G.js.map +0 -1
  178. package/dist/chunk-ZSAAAMVR 6.js +0 -25
  179. package/dist/components.js 5.map +0 -1
  180. package/dist/styles/index 2.js +0 -12
  181. package/dist/styles/index.js 5.map +0 -1
  182. package/dist/theming/runtime 5.js +0 -19
  183. package/dist/theming/runtime.js 5.map +0 -1
  184. /package/dist/{DataTable-5FU7IESH.js.map → DataTable-DQ7RSOHE.js.map} +0 -0
  185. /package/dist/{UnifiedAuthProvider-RGJTDE2C.js.map → UnifiedAuthProvider-ATAP5UTR.js.map} +0 -0
  186. /package/dist/{chunk-BC4IJKSL.js.map → chunk-JBKQ3SAO.js.map} +0 -0
  187. /package/dist/{chunk-QWWZ5CAQ.js 3.map → chunk-LXQLPRQ2.js.map} +0 -0
  188. /package/examples/{rbac → RBAC}/CompleteRBACExample.tsx +0 -0
  189. /package/examples/{rbac → RBAC}/EventBasedApp.tsx +0 -0
  190. /package/examples/{rbac → RBAC}/PermissionExample.tsx +0 -0
  191. /package/examples/{rbac → RBAC}/index.ts +0 -0
@@ -1,628 +0,0 @@
1
- import {
2
- logger
3
- } from "./chunk-PWLANIRT.js";
4
-
5
- // src/hooks/useToast.ts
6
- import * as React from "react";
7
- var TOAST_LIMIT = 5;
8
- var TOAST_REMOVE_DELAY = 1e3;
9
- var DEFAULT_TOAST_DURATION = 5e3;
10
- var toastTimeouts = /* @__PURE__ */ new Map();
11
- var memoryState = {
12
- toasts: []
13
- };
14
- var listeners = [];
15
- function dispatch(action) {
16
- memoryState = reducer(memoryState, action);
17
- listeners.forEach((listener) => {
18
- listener(memoryState);
19
- });
20
- }
21
- function genId() {
22
- return Math.random().toString(36).substring(2, 9);
23
- }
24
- var addToRemoveQueue = (toastId) => {
25
- if (toastTimeouts.has(toastId)) {
26
- return;
27
- }
28
- const timeout = setTimeout(() => {
29
- toastTimeouts.delete(toastId);
30
- dispatch({
31
- type: "REMOVE_TOAST",
32
- toastId
33
- });
34
- }, TOAST_REMOVE_DELAY);
35
- toastTimeouts.set(toastId, timeout);
36
- };
37
- function reducer(state, action) {
38
- switch (action.type) {
39
- case "ADD_TOAST":
40
- return {
41
- ...state,
42
- toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT)
43
- };
44
- case "UPDATE_TOAST":
45
- return {
46
- ...state,
47
- toasts: state.toasts.map(
48
- (t) => t.id === action.toast?.id ? { ...t, ...action.toast } : t
49
- )
50
- };
51
- case "DISMISS_TOAST": {
52
- const { toastId } = action;
53
- if (toastId) {
54
- addToRemoveQueue(toastId);
55
- }
56
- return {
57
- ...state,
58
- toasts: state.toasts.map(
59
- (t) => t.id === toastId || toastId === void 0 ? {
60
- ...t,
61
- open: false
62
- } : t
63
- )
64
- };
65
- }
66
- case "REMOVE_TOAST":
67
- if (action.toastId === void 0) {
68
- return {
69
- ...state,
70
- toasts: []
71
- };
72
- }
73
- return {
74
- ...state,
75
- toasts: state.toasts.filter((t) => t.id !== action.toastId)
76
- };
77
- }
78
- }
79
- function toast(props) {
80
- const id = genId();
81
- const update = (props2) => dispatch({
82
- type: "UPDATE_TOAST",
83
- toast: { ...props2, duration: DEFAULT_TOAST_DURATION, id }
84
- });
85
- const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id });
86
- dispatch({
87
- type: "ADD_TOAST",
88
- toast: {
89
- ...props,
90
- duration: DEFAULT_TOAST_DURATION,
91
- id,
92
- open: true,
93
- dismiss,
94
- onOpenChange: (open) => {
95
- if (!open) dismiss();
96
- }
97
- }
98
- });
99
- return {
100
- id,
101
- dismiss,
102
- update
103
- };
104
- }
105
- function useToast() {
106
- const [state, setState] = React.useState(memoryState);
107
- React.useEffect(() => {
108
- listeners.push(setState);
109
- return () => {
110
- const index = listeners.indexOf(setState);
111
- if (index > -1) {
112
- listeners.splice(index, 1);
113
- }
114
- };
115
- }, [state]);
116
- return {
117
- ...state,
118
- toast,
119
- dismiss: (toastId) => dispatch({ type: "DISMISS_TOAST", toastId })
120
- };
121
- }
122
-
123
- // src/components/DataTable/utils/performanceUtils.ts
124
- function determinePaginationMode(dataLength, serverSideThreshold = 1e4) {
125
- if (dataLength <= 1e3) return "client";
126
- return "hybrid";
127
- }
128
- function getOptimalPageSizeOptions(mode, dataLength) {
129
- switch (mode) {
130
- case "client":
131
- return dataLength <= 100 ? [10, 25, 50] : [10, 25, 50, 100];
132
- case "hybrid":
133
- return [50, 100, 250, 500];
134
- case "server":
135
- return [25, 50, 100, 250];
136
- default:
137
- return [10, 25, 50, 100];
138
- }
139
- }
140
- function chunkData(data, chunkSize) {
141
- const chunks = [];
142
- for (let i = 0; i < data.length; i += chunkSize) {
143
- chunks.push(data.slice(i, i + chunkSize));
144
- }
145
- return chunks;
146
- }
147
- var DataChunkManager = class {
148
- constructor(config) {
149
- this.chunks = /* @__PURE__ */ new Map();
150
- this.accessOrder = [];
151
- this.maxChunks = config.maxChunksInMemory;
152
- this.chunkSize = config.chunkSize;
153
- }
154
- getChunk(chunkIndex, allData) {
155
- if (this.chunks.has(chunkIndex)) {
156
- this.updateAccessOrder(chunkIndex);
157
- return this.chunks.get(chunkIndex);
158
- }
159
- const startIndex = chunkIndex * this.chunkSize;
160
- const endIndex = Math.min(startIndex + this.chunkSize, allData.length);
161
- const chunk = allData.slice(startIndex, endIndex);
162
- this.addChunk(chunkIndex, chunk);
163
- return chunk;
164
- }
165
- addChunk(chunkIndex, chunk) {
166
- if (this.chunks.size >= this.maxChunks && !this.chunks.has(chunkIndex)) {
167
- const oldestChunk = this.accessOrder.shift();
168
- if (oldestChunk !== void 0) {
169
- this.chunks.delete(oldestChunk);
170
- }
171
- }
172
- this.chunks.set(chunkIndex, chunk);
173
- this.updateAccessOrder(chunkIndex);
174
- }
175
- updateAccessOrder(chunkIndex) {
176
- const existingIndex = this.accessOrder.indexOf(chunkIndex);
177
- if (existingIndex > -1) {
178
- this.accessOrder.splice(existingIndex, 1);
179
- }
180
- this.accessOrder.push(chunkIndex);
181
- }
182
- clear() {
183
- this.chunks.clear();
184
- this.accessOrder = [];
185
- }
186
- getMemoryUsage() {
187
- let totalSize = 0;
188
- for (const chunk of this.chunks.values()) {
189
- totalSize += JSON.stringify(chunk).length;
190
- }
191
- return totalSize / (1024 * 1024);
192
- }
193
- };
194
- var SearchIndex = class {
195
- constructor(config) {
196
- this.index = /* @__PURE__ */ new Map();
197
- this.data = [];
198
- this.indexedFields = config.indexedFields;
199
- this.fuzzySearch = config.fuzzySearch ?? false;
200
- this.fuzzyThreshold = config.fuzzyThreshold ?? 0.6;
201
- }
202
- buildIndex(data) {
203
- this.data = data;
204
- this.index.clear();
205
- data.forEach((row, rowIndex) => {
206
- this.indexedFields.forEach((field) => {
207
- const value = this.getNestedValue(row, field);
208
- if (value != null) {
209
- const searchableText = String(value).toLowerCase();
210
- const words = this.tokenize(searchableText);
211
- words.forEach((word) => {
212
- if (!this.index.has(word)) {
213
- this.index.set(word, /* @__PURE__ */ new Set());
214
- }
215
- this.index.get(word).add(rowIndex);
216
- });
217
- }
218
- });
219
- });
220
- }
221
- search(query) {
222
- if (!query.trim()) return [];
223
- const searchTerms = this.tokenize(query.toLowerCase());
224
- const matchingSets = [];
225
- searchTerms.forEach((term) => {
226
- const matches = /* @__PURE__ */ new Set();
227
- if (this.index.has(term)) {
228
- this.index.get(term).forEach((index) => matches.add(index));
229
- }
230
- if (this.fuzzySearch) {
231
- for (const [indexedTerm, indices] of this.index.entries()) {
232
- if (this.calculateSimilarity(term, indexedTerm) >= this.fuzzyThreshold) {
233
- indices.forEach((index) => matches.add(index));
234
- }
235
- }
236
- }
237
- matchingSets.push(matches);
238
- });
239
- if (matchingSets.length === 0) return [];
240
- let result = matchingSets[0];
241
- for (let i = 1; i < matchingSets.length; i++) {
242
- result = new Set([...result].filter((x) => matchingSets[i].has(x)));
243
- }
244
- return Array.from(result);
245
- }
246
- getNestedValue(obj, path) {
247
- return path.split(".").reduce((current, key) => {
248
- if (current && typeof current === "object" && key in current) {
249
- return current[key];
250
- }
251
- return void 0;
252
- }, obj);
253
- }
254
- tokenize(text) {
255
- return text.replace(/[^\w\s]/g, " ").split(/\s+/).filter((word) => word.length > 0);
256
- }
257
- calculateSimilarity(str1, str2) {
258
- const longer = str1.length > str2.length ? str1 : str2;
259
- const shorter = str1.length > str2.length ? str2 : str1;
260
- if (longer.length === 0) return 1;
261
- const editDistance = this.levenshteinDistance(longer, shorter);
262
- return (longer.length - editDistance) / longer.length;
263
- }
264
- levenshteinDistance(str1, str2) {
265
- const matrix = Array(str2.length + 1).fill(null).map(
266
- () => Array(str1.length + 1).fill(null)
267
- );
268
- for (let i = 0; i <= str1.length; i++) matrix[0][i] = i;
269
- for (let j = 0; j <= str2.length; j++) matrix[j][0] = j;
270
- for (let j = 1; j <= str2.length; j++) {
271
- for (let i = 1; i <= str1.length; i++) {
272
- const substitutionCost = str1[i - 1] === str2[j - 1] ? 0 : 1;
273
- matrix[j][i] = Math.min(
274
- matrix[j][i - 1] + 1,
275
- // insertion
276
- matrix[j - 1][i] + 1,
277
- // deletion
278
- matrix[j - 1][i - 1] + substitutionCost
279
- // substitution
280
- );
281
- }
282
- }
283
- return matrix[str2.length][str1.length];
284
- }
285
- };
286
- function debounce(func, delay) {
287
- let timeoutId;
288
- return (...args) => {
289
- clearTimeout(timeoutId);
290
- timeoutId = setTimeout(() => func(...args), delay);
291
- };
292
- }
293
- function throttle(func, delay) {
294
- let lastCall = 0;
295
- return (...args) => {
296
- const now = Date.now();
297
- if (now - lastCall >= delay) {
298
- lastCall = now;
299
- func(...args);
300
- }
301
- };
302
- }
303
- var VisibilityTracker = class {
304
- constructor() {
305
- this.observer = null;
306
- this.visibleElements = /* @__PURE__ */ new Set();
307
- this.callbacks = /* @__PURE__ */ new Set();
308
- if (typeof IntersectionObserver !== "undefined") {
309
- this.observer = new IntersectionObserver(
310
- (entries) => {
311
- entries.forEach((entry) => {
312
- if (entry.isIntersecting) {
313
- this.visibleElements.add(entry.target);
314
- } else {
315
- this.visibleElements.delete(entry.target);
316
- }
317
- });
318
- this.callbacks.forEach((callback) => {
319
- callback(this.visibleElements.size);
320
- });
321
- },
322
- { threshold: 0.1 }
323
- );
324
- }
325
- }
326
- observe(element) {
327
- this.observer?.observe(element);
328
- }
329
- unobserve(element) {
330
- this.observer?.unobserve(element);
331
- this.visibleElements.delete(element);
332
- }
333
- onVisibilityChange(callback) {
334
- this.callbacks.add(callback);
335
- return () => this.callbacks.delete(callback);
336
- }
337
- getVisibleCount() {
338
- return this.visibleElements.size;
339
- }
340
- destroy() {
341
- this.observer?.disconnect();
342
- this.visibleElements.clear();
343
- this.callbacks.clear();
344
- }
345
- };
346
-
347
- // src/components/DataTable/utils/errorHandling.ts
348
- var DEFAULT_FALLBACK_CONFIG = {
349
- enabled: false
350
- };
351
- var DataTableErrorType = /* @__PURE__ */ ((DataTableErrorType3) => {
352
- DataTableErrorType3["VIRTUALIZATION"] = "virtualization";
353
- DataTableErrorType3["SEARCH_INDEX"] = "search_index";
354
- DataTableErrorType3["DATA_CHUNK"] = "data_chunk";
355
- DataTableErrorType3["SERVER_FETCH"] = "server_fetch";
356
- DataTableErrorType3["MEMORY"] = "memory";
357
- return DataTableErrorType3;
358
- })(DataTableErrorType || {});
359
- var DataTableError = class extends Error {
360
- constructor(message, type, recoverable = true) {
361
- super(message);
362
- this.type = type;
363
- this.recoverable = recoverable;
364
- this.name = "DataTableError";
365
- }
366
- };
367
- var ErrorRecoveryManager = class {
368
- constructor(config) {
369
- this.config = config;
370
- }
371
- async handleError(error) {
372
- return { recovered: false, strategy: null };
373
- }
374
- clearErrorLog() {
375
- }
376
- };
377
- var MemoryMonitor = class {
378
- constructor(threshold = 100) {
379
- this.threshold = threshold;
380
- }
381
- getCurrentUsage() {
382
- return 0;
383
- }
384
- checkThreshold() {
385
- return true;
386
- }
387
- stopMonitoring() {
388
- }
389
- };
390
- var CircuitBreaker = class {
391
- constructor() {
392
- }
393
- isOpen() {
394
- return false;
395
- }
396
- recordSuccess() {
397
- }
398
- recordFailure() {
399
- }
400
- reset() {
401
- }
402
- };
403
- function safeExecute(fn, fallback) {
404
- try {
405
- return fn();
406
- } catch {
407
- return fallback;
408
- }
409
- }
410
-
411
- // src/hooks/useDataTablePerformance.ts
412
- import { useState as useState2, useEffect as useEffect2, useCallback, useMemo, useRef } from "react";
413
- function useDataTablePerformance({
414
- data,
415
- performance = {},
416
- serverSide,
417
- chunking,
418
- searchIndex,
419
- fallbackConfig = DEFAULT_FALLBACK_CONFIG,
420
- onError,
421
- enableErrorRecovery = true
422
- }) {
423
- const [isLoading, setIsLoading] = useState2(false);
424
- const [searchQuery, setSearchQuery] = useState2("");
425
- const [searchResults, setSearchResults] = useState2([]);
426
- const [serverData, setServerData] = useState2(null);
427
- const [memoryUsage, setMemoryUsage] = useState2(0);
428
- const [errorState, setErrorState] = useState2({
429
- hasErrors: false,
430
- errorCount: 0,
431
- lastError: null,
432
- fallbacksActive: []
433
- });
434
- const [lastFailedOperation, setLastFailedOperation] = useState2(null);
435
- const chunkManagerRef = useRef(null);
436
- const searchIndexRef = useRef(null);
437
- const visibilityTrackerRef = useRef(null);
438
- const errorRecoveryManagerRef = useRef(new ErrorRecoveryManager(fallbackConfig));
439
- const memoryMonitorRef = useRef(null);
440
- const circuitBreakerRef = useRef(new CircuitBreaker());
441
- const paginationMode = useMemo(() => {
442
- if (serverSide) return "server";
443
- return determinePaginationMode(data?.length || 0, performance.serverSideThreshold);
444
- }, [data?.length, performance.serverSideThreshold, serverSide]);
445
- const isVirtualized = false;
446
- const pageSizeOptions = useMemo(() => {
447
- return getOptimalPageSizeOptions(paginationMode, data?.length || 0);
448
- }, [paginationMode, data?.length]);
449
- const processedData = useMemo(() => {
450
- if (serverSide && serverData) {
451
- return serverData.data;
452
- }
453
- let filteredData = data;
454
- if (searchQuery && searchResults.length > 0) {
455
- filteredData = searchResults.map((index) => data[index]);
456
- }
457
- return filteredData;
458
- }, [data, serverData, searchQuery, searchResults, serverSide]);
459
- const totalCount = useMemo(() => {
460
- if (serverSide && serverData) {
461
- return serverData.totalCount;
462
- }
463
- return processedData?.length || 0;
464
- }, [serverData, processedData?.length, serverSide]);
465
- useEffect2(() => {
466
- if (chunking && !chunkManagerRef.current) {
467
- chunkManagerRef.current = new DataChunkManager(chunking);
468
- }
469
- }, [chunking]);
470
- useEffect2(() => {
471
- if (searchIndex && !searchIndexRef.current) {
472
- searchIndexRef.current = new SearchIndex(searchIndex);
473
- }
474
- if (searchIndexRef.current && data.length > 0) {
475
- searchIndexRef.current.buildIndex(data);
476
- }
477
- }, [searchIndex, data]);
478
- const debouncedSearch = useCallback(
479
- debounce(((query) => {
480
- if (!searchIndexRef.current) return;
481
- if (!query.trim()) {
482
- setSearchResults([]);
483
- return;
484
- }
485
- const results = searchIndexRef.current.search(query);
486
- setSearchResults(results);
487
- }), performance.debounceSearch ?? 300),
488
- [performance.debounceSearch]
489
- );
490
- useEffect2(() => {
491
- debouncedSearch(searchQuery);
492
- }, [searchQuery, debouncedSearch]);
493
- const fetchServerData = useCallback(async (params) => {
494
- if (!serverSide) return;
495
- setIsLoading(true);
496
- try {
497
- const response = await serverSide.fetchData(params);
498
- setServerData(response);
499
- } catch (error) {
500
- logger.error("useDataTablePerformance", "Failed to fetch server data:", error);
501
- } finally {
502
- setIsLoading(false);
503
- }
504
- }, [serverSide]);
505
- useEffect2(() => {
506
- if (!visibilityTrackerRef.current) {
507
- visibilityTrackerRef.current = new VisibilityTracker();
508
- }
509
- const tracker = visibilityTrackerRef.current;
510
- const unsubscribe = tracker.onVisibilityChange((visibleCount) => {
511
- });
512
- return unsubscribe;
513
- }, [totalCount, isVirtualized, paginationMode]);
514
- useEffect2(() => {
515
- const updateMemoryUsage = () => {
516
- let usage = 0;
517
- if (chunkManagerRef.current) {
518
- usage += chunkManagerRef.current.getMemoryUsage();
519
- }
520
- usage += JSON.stringify(processedData || []).length / (1024 * 1024);
521
- setMemoryUsage(usage);
522
- };
523
- updateMemoryUsage();
524
- const interval = import.meta.env.MODE !== "test" ? setInterval(updateMemoryUsage, 5e3) : null;
525
- return () => {
526
- if (interval) {
527
- clearInterval(interval);
528
- }
529
- };
530
- }, [processedData]);
531
- const handleError = useCallback(async (error, operation) => {
532
- if (enableErrorRecovery) {
533
- try {
534
- const recovery = await errorRecoveryManagerRef.current.handleError(error);
535
- setErrorState((prev) => ({
536
- hasErrors: true,
537
- errorCount: prev.errorCount + 1,
538
- lastError: error,
539
- fallbacksActive: [...prev.fallbacksActive, error.type]
540
- }));
541
- if (operation) {
542
- setLastFailedOperation(() => operation);
543
- }
544
- onError?.(error);
545
- return recovery;
546
- } catch (recoveryError) {
547
- logger.error("useDataTablePerformance", "Error recovery failed:", recoveryError);
548
- }
549
- }
550
- throw error;
551
- }, [enableErrorRecovery, onError]);
552
- const retryLastOperation = useCallback(async () => {
553
- if (lastFailedOperation) {
554
- try {
555
- await lastFailedOperation();
556
- setLastFailedOperation(null);
557
- setErrorState((prev) => ({ ...prev, hasErrors: false }));
558
- } catch (error) {
559
- logger.error("useDataTablePerformance", "Retry failed:", error);
560
- }
561
- }
562
- }, [lastFailedOperation]);
563
- const clearErrors = useCallback(() => {
564
- setErrorState({
565
- hasErrors: false,
566
- errorCount: 0,
567
- lastError: null,
568
- fallbacksActive: []
569
- });
570
- setLastFailedOperation(null);
571
- errorRecoveryManagerRef.current.clearErrorLog();
572
- }, []);
573
- const cleanup = useCallback(() => {
574
- chunkManagerRef.current?.clear();
575
- visibilityTrackerRef.current?.destroy();
576
- memoryMonitorRef.current?.stopMonitoring();
577
- }, []);
578
- useEffect2(() => {
579
- return cleanup;
580
- }, [cleanup]);
581
- return {
582
- // Performance state
583
- paginationMode,
584
- isVirtualized,
585
- pageSizeOptions,
586
- // Data management
587
- processedData,
588
- totalCount,
589
- isLoading,
590
- // Search functionality
591
- searchQuery,
592
- setSearchQuery,
593
- searchResults,
594
- // Server-side functionality
595
- fetchServerData,
596
- serverData,
597
- // Performance monitoring
598
- memoryUsage,
599
- // Error handling and recovery
600
- errorState,
601
- retryLastOperation,
602
- clearErrors,
603
- // Cleanup
604
- cleanup
605
- };
606
- }
607
-
608
- export {
609
- toast,
610
- useToast,
611
- determinePaginationMode,
612
- getOptimalPageSizeOptions,
613
- chunkData,
614
- DataChunkManager,
615
- SearchIndex,
616
- debounce,
617
- throttle,
618
- VisibilityTracker,
619
- DEFAULT_FALLBACK_CONFIG,
620
- DataTableErrorType,
621
- DataTableError,
622
- ErrorRecoveryManager,
623
- MemoryMonitor,
624
- CircuitBreaker,
625
- safeExecute,
626
- useDataTablePerformance
627
- };
628
- //# sourceMappingURL=chunk-6C4YBBJM.js.map