@jmruthers/pace-core 0.5.120 → 0.5.121

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 (124) hide show
  1. package/dist/chunk-BDZUMRBD.js 3.map +1 -0
  2. package/dist/chunk-CGURJ27Z.js 2.map +1 -0
  3. package/dist/chunk-GKHF54DI 2.js +619 -0
  4. package/dist/chunk-GKHF54DI.js 2.map +1 -0
  5. package/dist/chunk-NZ32EONV.js 2.map +1 -0
  6. package/dist/chunk-O3NWNXDY 2.js +76 -0
  7. package/dist/chunk-TDNI6ZWL.js 2.map +1 -0
  8. package/dist/chunk-VKOCWWVY.js 3.map +1 -0
  9. package/dist/chunk-WP5I5GLN 2.js +1564 -0
  10. package/dist/index 3.js +856 -0
  11. package/dist/providers 3.js +38 -0
  12. package/dist/providers.js 3.map +1 -0
  13. package/dist/types 3.js +128 -0
  14. package/dist/types.js 3.map +1 -0
  15. package/dist/useInactivityTracker-MRUU55XI.js 3.map +1 -0
  16. package/dist/utils.js 3.map +1 -0
  17. package/dist/validation 3.js +479 -0
  18. package/docs/api/classes/ColumnFactory.md +1 -1
  19. package/docs/api/classes/ErrorBoundary.md +1 -1
  20. package/docs/api/classes/InvalidScopeError.md +1 -1
  21. package/docs/api/classes/MissingUserContextError.md +1 -1
  22. package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
  23. package/docs/api/classes/PermissionDeniedError.md +1 -1
  24. package/docs/api/classes/PublicErrorBoundary.md +1 -1
  25. package/docs/api/classes/RBACAuditManager.md +1 -1
  26. package/docs/api/classes/RBACCache.md +1 -1
  27. package/docs/api/classes/RBACEngine.md +1 -1
  28. package/docs/api/classes/RBACError.md +1 -1
  29. package/docs/api/classes/RBACNotInitializedError.md +1 -1
  30. package/docs/api/classes/SecureSupabaseClient.md +1 -1
  31. package/docs/api/classes/StorageUtils.md +1 -1
  32. package/docs/api/enums/FileCategory.md +1 -1
  33. package/docs/api/interfaces/AggregateConfig.md +1 -1
  34. package/docs/api/interfaces/ButtonProps.md +1 -1
  35. package/docs/api/interfaces/CardProps.md +1 -1
  36. package/docs/api/interfaces/ColorPalette.md +1 -1
  37. package/docs/api/interfaces/ColorShade.md +1 -1
  38. package/docs/api/interfaces/DataAccessRecord.md +1 -1
  39. package/docs/api/interfaces/DataRecord.md +1 -1
  40. package/docs/api/interfaces/DataTableAction.md +1 -1
  41. package/docs/api/interfaces/DataTableColumn.md +1 -1
  42. package/docs/api/interfaces/DataTableProps.md +1 -1
  43. package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
  44. package/docs/api/interfaces/EmptyStateConfig.md +1 -1
  45. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  46. package/docs/api/interfaces/EventAppRoleData.md +1 -1
  47. package/docs/api/interfaces/FileDisplayProps.md +1 -1
  48. package/docs/api/interfaces/FileMetadata.md +1 -1
  49. package/docs/api/interfaces/FileReference.md +1 -1
  50. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  51. package/docs/api/interfaces/FileUploadOptions.md +1 -1
  52. package/docs/api/interfaces/FileUploadProps.md +1 -1
  53. package/docs/api/interfaces/FooterProps.md +1 -1
  54. package/docs/api/interfaces/GrantEventAppRoleParams.md +1 -1
  55. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  56. package/docs/api/interfaces/InputProps.md +1 -1
  57. package/docs/api/interfaces/LabelProps.md +1 -1
  58. package/docs/api/interfaces/LoginFormProps.md +1 -1
  59. package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
  60. package/docs/api/interfaces/NavigationContextType.md +1 -1
  61. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  62. package/docs/api/interfaces/NavigationItem.md +1 -1
  63. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  64. package/docs/api/interfaces/NavigationProviderProps.md +1 -1
  65. package/docs/api/interfaces/Organisation.md +1 -1
  66. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  67. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  68. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  69. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  70. package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
  71. package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
  72. package/docs/api/interfaces/PageAccessRecord.md +1 -1
  73. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  74. package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
  75. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  76. package/docs/api/interfaces/PaletteData.md +1 -1
  77. package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
  78. package/docs/api/interfaces/ProtectedRouteProps.md +1 -1
  79. package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
  80. package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
  81. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
  82. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  83. package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
  84. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  85. package/docs/api/interfaces/RBACConfig.md +1 -1
  86. package/docs/api/interfaces/RBACLogger.md +1 -1
  87. package/docs/api/interfaces/RevokeEventAppRoleParams.md +1 -1
  88. package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
  89. package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
  90. package/docs/api/interfaces/RoleManagementResult.md +1 -1
  91. package/docs/api/interfaces/RouteAccessRecord.md +1 -1
  92. package/docs/api/interfaces/RouteConfig.md +1 -1
  93. package/docs/api/interfaces/SecureDataContextType.md +1 -1
  94. package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
  95. package/docs/api/interfaces/StorageConfig.md +1 -1
  96. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  97. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  98. package/docs/api/interfaces/StorageListOptions.md +1 -1
  99. package/docs/api/interfaces/StorageListResult.md +1 -1
  100. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  101. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  102. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  103. package/docs/api/interfaces/StyleImport.md +1 -1
  104. package/docs/api/interfaces/SwitchProps.md +1 -1
  105. package/docs/api/interfaces/ToastActionElement.md +1 -1
  106. package/docs/api/interfaces/ToastProps.md +1 -1
  107. package/docs/api/interfaces/UnifiedAuthContextType.md +1 -1
  108. package/docs/api/interfaces/UnifiedAuthProviderProps.md +1 -1
  109. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  110. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  111. package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
  112. package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
  113. package/docs/api/interfaces/UsePublicFileDisplayOptions.md +1 -1
  114. package/docs/api/interfaces/UsePublicFileDisplayReturn.md +1 -1
  115. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  116. package/docs/api/interfaces/UseResolvedScopeOptions.md +1 -1
  117. package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
  118. package/docs/api/interfaces/UserEventAccess.md +1 -1
  119. package/docs/api/interfaces/UserMenuProps.md +1 -1
  120. package/docs/api/interfaces/UserProfile.md +1 -1
  121. package/docs/api/modules.md +2 -2
  122. package/package.json +1 -1
  123. package/src/components/DataTable/utils/flexibleImport.ts +27 -6
  124. package/src/types/database.generated.ts +1515 -424
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/organisationContext.ts"],"sourcesContent":["/**\n * @file Organisation Context Utility\n * @package @jmruthers/pace-core\n * @module Utils/OrganisationContext\n * @since 0.4.0\n *\n * Utility functions for managing organisation context in database sessions.\n * Provides fallback mechanisms for when database functions are not available.\n */\n\nimport type { SupabaseClient } from '@supabase/supabase-js';\n\n/**\n * Set organisation context in the database session\n * \n * This function attempts to set the organisation context using a database function.\n * If the function is not available, it falls back gracefully without throwing errors.\n * \n * @param supabase - Supabase client instance\n * @param organisationId - The organisation ID to set as context\n * @returns Promise that resolves when context is set (or falls back gracefully)\n */\nexport async function setOrganisationContext(\n supabase: SupabaseClient,\n organisationId: string\n): Promise<void> {\n if (!supabase || !organisationId) {\n // TODO: Replace with proper logging service integration\n return;\n }\n\n try {\n // Add timeout to prevent hanging RPC calls\n const timeoutPromise = new Promise((_, reject) => {\n setTimeout(() => reject(new Error('RPC timeout after 3 seconds')), 3000);\n });\n \n // Call the database function to set organisation context\n const rpcPromise = supabase.rpc('set_organisation_context', {\n org_id: organisationId\n });\n\n const { error } = await Promise.race([rpcPromise, timeoutPromise]) as any;\n\n if (error) {\n // Function might not exist yet - this is expected during migration\n // Silent fail - will fall back to client-side filtering\n console.log('[organisationContext] RPC function not available or failed, continuing without database context');\n } else {\n console.log('[organisationContext] Organisation context set in database successfully');\n }\n } catch (error) {\n // Handle any other errors gracefully\n // Silent fail - will fall back to client-side filtering\n console.log('[organisationContext] Failed to set database context, continuing without it:', error);\n }\n}\n\n/**\n * Clear organisation context from the database session\n * \n * @param supabase - Supabase client instance\n * @returns Promise that resolves when context is cleared\n */\nexport async function clearOrganisationContext(\n supabase: SupabaseClient\n): Promise<void> {\n if (!supabase) {\n // TODO: Replace with proper logging service integration\n return;\n }\n\n try {\n const { error } = await supabase.rpc('rbac_audit_log', {\n p_event_type: 'organisation_switched',\n p_metadata: { action: 'clear_context' }\n });\n \n if (error) {\n // Silent fail - function not available\n // TODO: Replace with proper logging service integration\n } else {\n // TODO: Replace with proper logging service integration\n }\n } catch (error) {\n // Silent fail - error occurred\n // TODO: Replace with proper logging service integration\n }\n}\n\n/**\n * Get current organisation context from the database session\n * \n * @param supabase - Supabase client instance\n * @returns Promise that resolves to the current organisation ID or null\n */\nexport async function getOrganisationContext(\n supabase: SupabaseClient\n): Promise<string | null> {\n if (!supabase) {\n // TODO: Replace with proper logging service integration\n return null;\n }\n\n try {\n // For now, return null since we're not using database context\n // This will be replaced with proper context management\n const data = null;\n const error = null;\n \n if (error) {\n // TODO: Replace with proper logging service integration\n return null;\n }\n \n // Validate that data is a string (allow empty strings)\n if (typeof data === 'string') {\n return data;\n }\n \n // Return null for invalid data formats\n return null;\n } catch (error) {\n // TODO: Replace with proper logging service integration\n return null;\n }\n}\n\n/**\n * Check if organisation context functions are available in the database\n * \n * @param supabase - Supabase client instance\n * @returns Promise that resolves to true if functions are available\n */\nexport async function isOrganisationContextAvailable(\n supabase: SupabaseClient\n): Promise<boolean> {\n if (!supabase) {\n return false;\n }\n\n try {\n const { error } = await supabase.rpc('get_organisation_context');\n \n if (error) {\n return false;\n }\n \n return true;\n } catch (error) {\n return false;\n }\n} "],"mappings":";;;;;AAsBA,eAAsB,uBACpB,UACA,gBACe;AACf,MAAI,CAAC,YAAY,CAAC,gBAAgB;AAEhC;AAAA,EACF;AAEA,MAAI;AAEF,UAAM,iBAAiB,IAAI,QAAQ,CAAC,GAAG,WAAW;AAChD,iBAAW,MAAM,OAAO,IAAI,MAAM,6BAA6B,CAAC,GAAG,GAAI;AAAA,IACzE,CAAC;AAGD,UAAM,aAAa,SAAS,IAAI,4BAA4B;AAAA,MAC1D,QAAQ;AAAA,IACV,CAAC;AAED,UAAM,EAAE,MAAM,IAAI,MAAM,QAAQ,KAAK,CAAC,YAAY,cAAc,CAAC;AAEjE,QAAI,OAAO;AAGT,cAAQ,IAAI,iGAAiG;AAAA,IAC/G,OAAO;AACL,cAAQ,IAAI,yEAAyE;AAAA,IACvF;AAAA,EACF,SAAS,OAAO;AAGd,YAAQ,IAAI,gFAAgF,KAAK;AAAA,EACnG;AACF;AAQA,eAAsB,yBACpB,UACe;AACf,MAAI,CAAC,UAAU;AAEb;AAAA,EACF;AAEA,MAAI;AACF,UAAM,EAAE,MAAM,IAAI,MAAM,SAAS,IAAI,kBAAkB;AAAA,MACrD,cAAc;AAAA,MACd,YAAY,EAAE,QAAQ,gBAAgB;AAAA,IACxC,CAAC;AAED,QAAI,OAAO;AAAA,IAGX,OAAO;AAAA,IAEP;AAAA,EACF,SAAS,OAAO;AAAA,EAGhB;AACF;AAQA,eAAsB,uBACpB,UACwB;AACxB,MAAI,CAAC,UAAU;AAEb,WAAO;AAAA,EACT;AAEA,MAAI;AAGF,UAAM,OAAO;AACb,UAAM,QAAQ;AAEd,QAAI,OAAO;AAET,aAAO;AAAA,IACT;AAGA,QAAI,OAAO,SAAS,UAAU;AAC5B,aAAO;AAAA,IACT;AAGA,WAAO;AAAA,EACT,SAAS,OAAO;AAEd,WAAO;AAAA,EACT;AACF;AAQA,eAAsB,+BACpB,UACkB;AAClB,MAAI,CAAC,UAAU;AACb,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,EAAE,MAAM,IAAI,MAAM,SAAS,IAAI,0BAA0B;AAE/D,QAAI,OAAO;AACT,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT,SAAS,OAAO;AACd,WAAO;AAAA,EACT;AACF;AAxJA;AAAA;AAAA;AAAA;AAAA;","names":[]}
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/hooks/useOrganisations.ts","../src/hooks/useEvents.ts"],"sourcesContent":["/**\n * @file Organisation Hook\n * @package @jmruthers/pace-core\n * @module Hooks\n * @since 0.1.0\n *\n * Convenience hook for accessing organisation context.\n * This hook provides a simple interface for working with organisations.\n * \n * Note: This is a convenience wrapper around the OrganisationService.\n * For better performance, consider using useOrganisationService directly.\n */\n\nimport { useOrganisationService } from './services/useOrganisationService';\nimport { Organisation, OrganisationMembership, OrganisationContextType } from '../types/organisation';\n\n/**\n * Hook to access organisation context\n * \n * @returns Organisation context with selected organisation, organisations list, and helper methods\n * @throws {Error} If used outside OrganisationServiceProvider\n * \n * @example\n * ```tsx\n * function MyComponent() {\n * const { selectedOrganisation, organisations, switchOrganisation } = useOrganisations();\n * \n * return (\n * <div>\n * <h1>Current Organisation: {selectedOrganisation.display_name}</h1>\n * {organisations.map(org => (\n * <button key={org.id} onClick={() => switchOrganisation(org.id)}>\n * {org.display_name}\n * </button>\n * ))}\n * </div>\n * );\n * }\n * ```\n */\nexport function useOrganisations(): OrganisationContextType {\n const organisationService = useOrganisationService();\n\n const selectedOrg = organisationService.getSelectedOrganisation();\n \n return {\n selectedOrganisation: selectedOrg as Organisation | null,\n organisations: organisationService.getOrganisations(),\n userMemberships: organisationService.getUserMemberships(),\n isLoading: organisationService.isLoading(),\n error: organisationService.getError(),\n hasValidOrganisationContext: organisationService.hasValidOrganisationContext(),\n isContextReady: organisationService.isContextReady(),\n setSelectedOrganisation: (org: Organisation | null) => organisationService.setSelectedOrganisation(org),\n switchOrganisation: (orgId: string) => organisationService.switchOrganisation(orgId),\n getUserRole: (orgId?: string) => organisationService.getUserRole(orgId),\n validateOrganisationAccess: (orgId: string) => organisationService.validateOrganisationAccess(orgId),\n refreshOrganisations: () => organisationService.refreshOrganisations(),\n ensureOrganisationContext: () => organisationService.ensureOrganisationContext(),\n isOrganisationSecure: () => organisationService.isOrganisationSecure(),\n getPrimaryOrganisation: () => organisationService.getPrimaryOrganisation(),\n };\n}\n\n","/**\n * @file Event Hook\n * @package @jmruthers/pace-core\n * @module Hooks\n * @since 0.1.0\n *\n * Convenience hook for accessing event context.\n * This hook provides a simple interface for working with events.\n * \n * Note: This is a convenience wrapper around the EventService.\n * For better performance, consider using useEventService directly.\n */\n\nimport { useEventService } from './services/useEventService';\nimport { Event } from '../types/unified';\n\nexport interface EventContextType {\n events: Event[];\n selectedEvent: Event | null;\n isLoading: boolean;\n error: Error | null;\n setSelectedEvent: (event: Event | null) => void;\n refreshEvents: () => Promise<void>;\n}\n\n/**\n * Hook to access event context\n * \n * @returns Event context with events, selected event, and helper methods\n * @throws {Error} If used outside EventServiceProvider\n * \n * @example\n * ```tsx\n * function MyComponent() {\n * const { events, selectedEvent, setSelectedEvent } = useEvents();\n * \n * return (\n * <div>\n * {events.map(event => (\n * <button key={event.id} onClick={() => setSelectedEvent(event)}>\n * {event.event_name}\n * </button>\n * ))}\n * </div>\n * );\n * }\n * ```\n */\nexport function useEvents(): EventContextType {\n const eventService = useEventService();\n\n const events = eventService.getEvents();\n\n return {\n events,\n selectedEvent: eventService.getSelectedEvent(),\n isLoading: eventService.isLoading(),\n error: eventService.getError(),\n setSelectedEvent: (event: Event | null) => eventService.setSelectedEvent(event),\n refreshEvents: () => eventService.refreshEvents(),\n };\n}\n\n"],"mappings":";;;;;;;;;;;AAwCO,SAAS,mBAA4C;AAC1D,QAAM,sBAAsB,uBAAuB;AAEnD,QAAM,cAAc,oBAAoB,wBAAwB;AAEhE,SAAO;AAAA,IACL,sBAAsB;AAAA,IACtB,eAAe,oBAAoB,iBAAiB;AAAA,IACpD,iBAAiB,oBAAoB,mBAAmB;AAAA,IACxD,WAAW,oBAAoB,UAAU;AAAA,IACzC,OAAO,oBAAoB,SAAS;AAAA,IACpC,6BAA6B,oBAAoB,4BAA4B;AAAA,IAC7E,gBAAgB,oBAAoB,eAAe;AAAA,IACnD,yBAAyB,CAAC,QAA6B,oBAAoB,wBAAwB,GAAG;AAAA,IACtG,oBAAoB,CAAC,UAAkB,oBAAoB,mBAAmB,KAAK;AAAA,IACnF,aAAa,CAAC,UAAmB,oBAAoB,YAAY,KAAK;AAAA,IACtE,4BAA4B,CAAC,UAAkB,oBAAoB,2BAA2B,KAAK;AAAA,IACnG,sBAAsB,MAAM,oBAAoB,qBAAqB;AAAA,IACrE,2BAA2B,MAAM,oBAAoB,0BAA0B;AAAA,IAC/E,sBAAsB,MAAM,oBAAoB,qBAAqB;AAAA,IACrE,wBAAwB,MAAM,oBAAoB,uBAAuB;AAAA,EAC3E;AACF;AA9DA;AAAA;AAAA;AAaA;AAAA;AAAA;;;ACAA;AAmCO,SAAS,YAA8B;AAC5C,QAAM,eAAe,gBAAgB;AAErC,QAAM,SAAS,aAAa,UAAU;AAEtC,SAAO;AAAA,IACL;AAAA,IACA,eAAe,aAAa,iBAAiB;AAAA,IAC7C,WAAW,aAAa,UAAU;AAAA,IAClC,OAAO,aAAa,SAAS;AAAA,IAC7B,kBAAkB,CAAC,UAAwB,aAAa,iBAAiB,KAAK;AAAA,IAC9E,eAAe,MAAM,aAAa,cAAc;AAAA,EAClD;AACF;","names":[]}
@@ -0,0 +1,619 @@
1
+ // src/hooks/useToast.ts
2
+ import * as React from "react";
3
+ var TOAST_LIMIT = 5;
4
+ var TOAST_REMOVE_DELAY = 1e3;
5
+ var DEFAULT_TOAST_DURATION = 5e3;
6
+ var toastTimeouts = /* @__PURE__ */ new Map();
7
+ var memoryState = {
8
+ toasts: []
9
+ };
10
+ var listeners = [];
11
+ function dispatch(action) {
12
+ memoryState = reducer(memoryState, action);
13
+ listeners.forEach((listener) => {
14
+ listener(memoryState);
15
+ });
16
+ }
17
+ function genId() {
18
+ return Math.random().toString(36).substring(2, 9);
19
+ }
20
+ var addToRemoveQueue = (toastId) => {
21
+ if (toastTimeouts.has(toastId)) {
22
+ return;
23
+ }
24
+ const timeout = setTimeout(() => {
25
+ toastTimeouts.delete(toastId);
26
+ dispatch({
27
+ type: "REMOVE_TOAST",
28
+ toastId
29
+ });
30
+ }, TOAST_REMOVE_DELAY);
31
+ toastTimeouts.set(toastId, timeout);
32
+ };
33
+ function reducer(state, action) {
34
+ switch (action.type) {
35
+ case "ADD_TOAST":
36
+ return {
37
+ ...state,
38
+ toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT)
39
+ };
40
+ case "UPDATE_TOAST":
41
+ return {
42
+ ...state,
43
+ toasts: state.toasts.map(
44
+ (t) => t.id === action.toast?.id ? { ...t, ...action.toast } : t
45
+ )
46
+ };
47
+ case "DISMISS_TOAST": {
48
+ const { toastId } = action;
49
+ if (toastId) {
50
+ addToRemoveQueue(toastId);
51
+ }
52
+ return {
53
+ ...state,
54
+ toasts: state.toasts.map(
55
+ (t) => t.id === toastId || toastId === void 0 ? {
56
+ ...t,
57
+ open: false
58
+ } : t
59
+ )
60
+ };
61
+ }
62
+ case "REMOVE_TOAST":
63
+ if (action.toastId === void 0) {
64
+ return {
65
+ ...state,
66
+ toasts: []
67
+ };
68
+ }
69
+ return {
70
+ ...state,
71
+ toasts: state.toasts.filter((t) => t.id !== action.toastId)
72
+ };
73
+ }
74
+ }
75
+ function toast(props) {
76
+ const id = genId();
77
+ const update = (props2) => dispatch({
78
+ type: "UPDATE_TOAST",
79
+ toast: { ...props2, duration: DEFAULT_TOAST_DURATION, id }
80
+ });
81
+ const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id });
82
+ dispatch({
83
+ type: "ADD_TOAST",
84
+ toast: {
85
+ ...props,
86
+ duration: DEFAULT_TOAST_DURATION,
87
+ id,
88
+ open: true,
89
+ dismiss,
90
+ onOpenChange: (open) => {
91
+ if (!open) dismiss();
92
+ }
93
+ }
94
+ });
95
+ return {
96
+ id,
97
+ dismiss,
98
+ update
99
+ };
100
+ }
101
+ function useToast() {
102
+ const [state, setState] = React.useState(memoryState);
103
+ React.useEffect(() => {
104
+ listeners.push(setState);
105
+ return () => {
106
+ const index = listeners.indexOf(setState);
107
+ if (index > -1) {
108
+ listeners.splice(index, 1);
109
+ }
110
+ };
111
+ }, [state]);
112
+ return {
113
+ ...state,
114
+ toast,
115
+ dismiss: (toastId) => dispatch({ type: "DISMISS_TOAST", toastId })
116
+ };
117
+ }
118
+
119
+ // src/components/DataTable/utils/performanceUtils.ts
120
+ function determinePaginationMode(dataLength, serverSideThreshold = 1e4) {
121
+ if (dataLength <= 1e3) return "client";
122
+ return "hybrid";
123
+ }
124
+ function getOptimalPageSizeOptions(mode, dataLength) {
125
+ switch (mode) {
126
+ case "client":
127
+ return dataLength <= 100 ? [10, 25, 50] : [10, 25, 50, 100];
128
+ case "hybrid":
129
+ return [50, 100, 250, 500];
130
+ case "server":
131
+ return [25, 50, 100, 250];
132
+ default:
133
+ return [10, 25, 50, 100];
134
+ }
135
+ }
136
+ function chunkData(data, chunkSize) {
137
+ const chunks = [];
138
+ for (let i = 0; i < data.length; i += chunkSize) {
139
+ chunks.push(data.slice(i, i + chunkSize));
140
+ }
141
+ return chunks;
142
+ }
143
+ var DataChunkManager = class {
144
+ constructor(config) {
145
+ this.chunks = /* @__PURE__ */ new Map();
146
+ this.accessOrder = [];
147
+ this.maxChunks = config.maxChunksInMemory;
148
+ this.chunkSize = config.chunkSize;
149
+ }
150
+ getChunk(chunkIndex, allData) {
151
+ if (this.chunks.has(chunkIndex)) {
152
+ this.updateAccessOrder(chunkIndex);
153
+ return this.chunks.get(chunkIndex);
154
+ }
155
+ const startIndex = chunkIndex * this.chunkSize;
156
+ const endIndex = Math.min(startIndex + this.chunkSize, allData.length);
157
+ const chunk = allData.slice(startIndex, endIndex);
158
+ this.addChunk(chunkIndex, chunk);
159
+ return chunk;
160
+ }
161
+ addChunk(chunkIndex, chunk) {
162
+ if (this.chunks.size >= this.maxChunks && !this.chunks.has(chunkIndex)) {
163
+ const oldestChunk = this.accessOrder.shift();
164
+ if (oldestChunk !== void 0) {
165
+ this.chunks.delete(oldestChunk);
166
+ }
167
+ }
168
+ this.chunks.set(chunkIndex, chunk);
169
+ this.updateAccessOrder(chunkIndex);
170
+ }
171
+ updateAccessOrder(chunkIndex) {
172
+ const existingIndex = this.accessOrder.indexOf(chunkIndex);
173
+ if (existingIndex > -1) {
174
+ this.accessOrder.splice(existingIndex, 1);
175
+ }
176
+ this.accessOrder.push(chunkIndex);
177
+ }
178
+ clear() {
179
+ this.chunks.clear();
180
+ this.accessOrder = [];
181
+ }
182
+ getMemoryUsage() {
183
+ let totalSize = 0;
184
+ for (const chunk of this.chunks.values()) {
185
+ totalSize += JSON.stringify(chunk).length;
186
+ }
187
+ return totalSize / (1024 * 1024);
188
+ }
189
+ };
190
+ var SearchIndex = class {
191
+ constructor(config) {
192
+ this.index = /* @__PURE__ */ new Map();
193
+ this.data = [];
194
+ this.indexedFields = config.indexedFields;
195
+ this.fuzzySearch = config.fuzzySearch ?? false;
196
+ this.fuzzyThreshold = config.fuzzyThreshold ?? 0.6;
197
+ }
198
+ buildIndex(data) {
199
+ this.data = data;
200
+ this.index.clear();
201
+ data.forEach((row, rowIndex) => {
202
+ this.indexedFields.forEach((field) => {
203
+ const value = this.getNestedValue(row, field);
204
+ if (value != null) {
205
+ const searchableText = String(value).toLowerCase();
206
+ const words = this.tokenize(searchableText);
207
+ words.forEach((word) => {
208
+ if (!this.index.has(word)) {
209
+ this.index.set(word, /* @__PURE__ */ new Set());
210
+ }
211
+ this.index.get(word).add(rowIndex);
212
+ });
213
+ }
214
+ });
215
+ });
216
+ }
217
+ search(query) {
218
+ if (!query.trim()) return [];
219
+ const searchTerms = this.tokenize(query.toLowerCase());
220
+ const matchingSets = [];
221
+ searchTerms.forEach((term) => {
222
+ const matches = /* @__PURE__ */ new Set();
223
+ if (this.index.has(term)) {
224
+ this.index.get(term).forEach((index) => matches.add(index));
225
+ }
226
+ if (this.fuzzySearch) {
227
+ for (const [indexedTerm, indices] of this.index.entries()) {
228
+ if (this.calculateSimilarity(term, indexedTerm) >= this.fuzzyThreshold) {
229
+ indices.forEach((index) => matches.add(index));
230
+ }
231
+ }
232
+ }
233
+ matchingSets.push(matches);
234
+ });
235
+ if (matchingSets.length === 0) return [];
236
+ let result = matchingSets[0];
237
+ for (let i = 1; i < matchingSets.length; i++) {
238
+ result = new Set([...result].filter((x) => matchingSets[i].has(x)));
239
+ }
240
+ return Array.from(result);
241
+ }
242
+ getNestedValue(obj, path) {
243
+ return path.split(".").reduce((current, key) => current?.[key], obj);
244
+ }
245
+ tokenize(text) {
246
+ return text.replace(/[^\w\s]/g, " ").split(/\s+/).filter((word) => word.length > 0);
247
+ }
248
+ calculateSimilarity(str1, str2) {
249
+ const longer = str1.length > str2.length ? str1 : str2;
250
+ const shorter = str1.length > str2.length ? str2 : str1;
251
+ if (longer.length === 0) return 1;
252
+ const editDistance = this.levenshteinDistance(longer, shorter);
253
+ return (longer.length - editDistance) / longer.length;
254
+ }
255
+ levenshteinDistance(str1, str2) {
256
+ const matrix = Array(str2.length + 1).fill(null).map(
257
+ () => Array(str1.length + 1).fill(null)
258
+ );
259
+ for (let i = 0; i <= str1.length; i++) matrix[0][i] = i;
260
+ for (let j = 0; j <= str2.length; j++) matrix[j][0] = j;
261
+ for (let j = 1; j <= str2.length; j++) {
262
+ for (let i = 1; i <= str1.length; i++) {
263
+ const substitutionCost = str1[i - 1] === str2[j - 1] ? 0 : 1;
264
+ matrix[j][i] = Math.min(
265
+ matrix[j][i - 1] + 1,
266
+ // insertion
267
+ matrix[j - 1][i] + 1,
268
+ // deletion
269
+ matrix[j - 1][i - 1] + substitutionCost
270
+ // substitution
271
+ );
272
+ }
273
+ }
274
+ return matrix[str2.length][str1.length];
275
+ }
276
+ };
277
+ function debounce(func, delay) {
278
+ let timeoutId;
279
+ return (...args) => {
280
+ clearTimeout(timeoutId);
281
+ timeoutId = setTimeout(() => func(...args), delay);
282
+ };
283
+ }
284
+ function throttle(func, delay) {
285
+ let lastCall = 0;
286
+ return (...args) => {
287
+ const now = Date.now();
288
+ if (now - lastCall >= delay) {
289
+ lastCall = now;
290
+ func(...args);
291
+ }
292
+ };
293
+ }
294
+ var VisibilityTracker = class {
295
+ constructor() {
296
+ this.observer = null;
297
+ this.visibleElements = /* @__PURE__ */ new Set();
298
+ this.callbacks = /* @__PURE__ */ new Set();
299
+ if (typeof IntersectionObserver !== "undefined") {
300
+ this.observer = new IntersectionObserver(
301
+ (entries) => {
302
+ entries.forEach((entry) => {
303
+ if (entry.isIntersecting) {
304
+ this.visibleElements.add(entry.target);
305
+ } else {
306
+ this.visibleElements.delete(entry.target);
307
+ }
308
+ });
309
+ this.callbacks.forEach((callback) => {
310
+ callback(this.visibleElements.size);
311
+ });
312
+ },
313
+ { threshold: 0.1 }
314
+ );
315
+ }
316
+ }
317
+ observe(element) {
318
+ this.observer?.observe(element);
319
+ }
320
+ unobserve(element) {
321
+ this.observer?.unobserve(element);
322
+ this.visibleElements.delete(element);
323
+ }
324
+ onVisibilityChange(callback) {
325
+ this.callbacks.add(callback);
326
+ return () => this.callbacks.delete(callback);
327
+ }
328
+ getVisibleCount() {
329
+ return this.visibleElements.size;
330
+ }
331
+ destroy() {
332
+ this.observer?.disconnect();
333
+ this.visibleElements.clear();
334
+ this.callbacks.clear();
335
+ }
336
+ };
337
+
338
+ // src/components/DataTable/utils/errorHandling.ts
339
+ var DEFAULT_FALLBACK_CONFIG = {
340
+ enabled: false
341
+ };
342
+ var DataTableErrorType = /* @__PURE__ */ ((DataTableErrorType3) => {
343
+ DataTableErrorType3["VIRTUALIZATION"] = "virtualization";
344
+ DataTableErrorType3["SEARCH_INDEX"] = "search_index";
345
+ DataTableErrorType3["DATA_CHUNK"] = "data_chunk";
346
+ DataTableErrorType3["SERVER_FETCH"] = "server_fetch";
347
+ DataTableErrorType3["MEMORY"] = "memory";
348
+ return DataTableErrorType3;
349
+ })(DataTableErrorType || {});
350
+ var DataTableError = class extends Error {
351
+ constructor(message, type, recoverable = true) {
352
+ super(message);
353
+ this.type = type;
354
+ this.recoverable = recoverable;
355
+ this.name = "DataTableError";
356
+ }
357
+ };
358
+ var ErrorRecoveryManager = class {
359
+ constructor(config) {
360
+ this.config = config;
361
+ }
362
+ async handleError(error) {
363
+ return { recovered: false, strategy: null };
364
+ }
365
+ clearErrorLog() {
366
+ }
367
+ };
368
+ var MemoryMonitor = class {
369
+ constructor(threshold = 100) {
370
+ this.threshold = threshold;
371
+ }
372
+ getCurrentUsage() {
373
+ return 0;
374
+ }
375
+ checkThreshold() {
376
+ return true;
377
+ }
378
+ stopMonitoring() {
379
+ }
380
+ };
381
+ var CircuitBreaker = class {
382
+ constructor() {
383
+ }
384
+ isOpen() {
385
+ return false;
386
+ }
387
+ recordSuccess() {
388
+ }
389
+ recordFailure() {
390
+ }
391
+ reset() {
392
+ }
393
+ };
394
+ function safeExecute(fn, fallback) {
395
+ try {
396
+ return fn();
397
+ } catch {
398
+ return fallback;
399
+ }
400
+ }
401
+
402
+ // src/hooks/useDataTablePerformance.ts
403
+ import { useState as useState2, useEffect as useEffect2, useCallback, useMemo, useRef } from "react";
404
+ function useDataTablePerformance({
405
+ data,
406
+ performance = {},
407
+ serverSide,
408
+ chunking,
409
+ searchIndex,
410
+ fallbackConfig = DEFAULT_FALLBACK_CONFIG,
411
+ onError,
412
+ enableErrorRecovery = true
413
+ }) {
414
+ const [isLoading, setIsLoading] = useState2(false);
415
+ const [searchQuery, setSearchQuery] = useState2("");
416
+ const [searchResults, setSearchResults] = useState2([]);
417
+ const [serverData, setServerData] = useState2(null);
418
+ const [memoryUsage, setMemoryUsage] = useState2(0);
419
+ const [errorState, setErrorState] = useState2({
420
+ hasErrors: false,
421
+ errorCount: 0,
422
+ lastError: null,
423
+ fallbacksActive: []
424
+ });
425
+ const [lastFailedOperation, setLastFailedOperation] = useState2(null);
426
+ const chunkManagerRef = useRef(null);
427
+ const searchIndexRef = useRef(null);
428
+ const visibilityTrackerRef = useRef(null);
429
+ const errorRecoveryManagerRef = useRef(new ErrorRecoveryManager(fallbackConfig));
430
+ const memoryMonitorRef = useRef(null);
431
+ const circuitBreakerRef = useRef(new CircuitBreaker());
432
+ const paginationMode = useMemo(() => {
433
+ if (serverSide) return "server";
434
+ return determinePaginationMode(data?.length || 0, performance.serverSideThreshold);
435
+ }, [data?.length, performance.serverSideThreshold, serverSide]);
436
+ const isVirtualized = false;
437
+ const pageSizeOptions = useMemo(() => {
438
+ return getOptimalPageSizeOptions(paginationMode, data?.length || 0);
439
+ }, [paginationMode, data?.length]);
440
+ const processedData = useMemo(() => {
441
+ if (serverSide && serverData) {
442
+ return serverData.data;
443
+ }
444
+ let filteredData = data;
445
+ if (searchQuery && searchResults.length > 0) {
446
+ filteredData = searchResults.map((index) => data[index]);
447
+ }
448
+ return filteredData;
449
+ }, [data, serverData, searchQuery, searchResults, serverSide]);
450
+ const totalCount = useMemo(() => {
451
+ if (serverSide && serverData) {
452
+ return serverData.totalCount;
453
+ }
454
+ return processedData?.length || 0;
455
+ }, [serverData, processedData?.length, serverSide]);
456
+ useEffect2(() => {
457
+ if (chunking && !chunkManagerRef.current) {
458
+ chunkManagerRef.current = new DataChunkManager(chunking);
459
+ }
460
+ }, [chunking]);
461
+ useEffect2(() => {
462
+ if (searchIndex && !searchIndexRef.current) {
463
+ searchIndexRef.current = new SearchIndex(searchIndex);
464
+ }
465
+ if (searchIndexRef.current && data.length > 0) {
466
+ searchIndexRef.current.buildIndex(data);
467
+ }
468
+ }, [searchIndex, data]);
469
+ const debouncedSearch = useCallback(
470
+ debounce((query) => {
471
+ if (!searchIndexRef.current) return;
472
+ if (!query.trim()) {
473
+ setSearchResults([]);
474
+ return;
475
+ }
476
+ const results = searchIndexRef.current.search(query);
477
+ setSearchResults(results);
478
+ }, performance.debounceSearch ?? 300),
479
+ [performance.debounceSearch]
480
+ );
481
+ useEffect2(() => {
482
+ debouncedSearch(searchQuery);
483
+ }, [searchQuery, debouncedSearch]);
484
+ const fetchServerData = useCallback(async (params) => {
485
+ if (!serverSide) return;
486
+ setIsLoading(true);
487
+ try {
488
+ const response = await serverSide.fetchData(params);
489
+ setServerData(response);
490
+ } catch (error) {
491
+ console.error("Failed to fetch server data:", error);
492
+ } finally {
493
+ setIsLoading(false);
494
+ }
495
+ }, [serverSide]);
496
+ useEffect2(() => {
497
+ if (!visibilityTrackerRef.current) {
498
+ visibilityTrackerRef.current = new VisibilityTracker();
499
+ }
500
+ const tracker = visibilityTrackerRef.current;
501
+ const unsubscribe = tracker.onVisibilityChange((visibleCount) => {
502
+ });
503
+ return unsubscribe;
504
+ }, [totalCount, isVirtualized, paginationMode]);
505
+ useEffect2(() => {
506
+ const updateMemoryUsage = () => {
507
+ let usage = 0;
508
+ if (chunkManagerRef.current) {
509
+ usage += chunkManagerRef.current.getMemoryUsage();
510
+ }
511
+ usage += JSON.stringify(processedData || []).length / (1024 * 1024);
512
+ setMemoryUsage(usage);
513
+ };
514
+ updateMemoryUsage();
515
+ const interval = import.meta.env.MODE !== "test" ? setInterval(updateMemoryUsage, 5e3) : null;
516
+ return () => {
517
+ if (interval) {
518
+ clearInterval(interval);
519
+ }
520
+ };
521
+ }, [processedData]);
522
+ const handleError = useCallback(async (error, operation) => {
523
+ if (enableErrorRecovery) {
524
+ try {
525
+ const recovery = await errorRecoveryManagerRef.current.handleError(error);
526
+ setErrorState((prev) => ({
527
+ hasErrors: true,
528
+ errorCount: prev.errorCount + 1,
529
+ lastError: error,
530
+ fallbacksActive: [...prev.fallbacksActive, error.type]
531
+ }));
532
+ if (operation) {
533
+ setLastFailedOperation(() => operation);
534
+ }
535
+ onError?.(error);
536
+ return recovery;
537
+ } catch (recoveryError) {
538
+ console.error("Error recovery failed:", recoveryError);
539
+ }
540
+ }
541
+ throw error;
542
+ }, [enableErrorRecovery, onError]);
543
+ const retryLastOperation = useCallback(async () => {
544
+ if (lastFailedOperation) {
545
+ try {
546
+ await lastFailedOperation();
547
+ setLastFailedOperation(null);
548
+ setErrorState((prev) => ({ ...prev, hasErrors: false }));
549
+ } catch (error) {
550
+ console.error("Retry failed:", error);
551
+ }
552
+ }
553
+ }, [lastFailedOperation]);
554
+ const clearErrors = useCallback(() => {
555
+ setErrorState({
556
+ hasErrors: false,
557
+ errorCount: 0,
558
+ lastError: null,
559
+ fallbacksActive: []
560
+ });
561
+ setLastFailedOperation(null);
562
+ errorRecoveryManagerRef.current.clearErrorLog();
563
+ }, []);
564
+ const cleanup = useCallback(() => {
565
+ chunkManagerRef.current?.clear();
566
+ visibilityTrackerRef.current?.destroy();
567
+ memoryMonitorRef.current?.stopMonitoring();
568
+ }, []);
569
+ useEffect2(() => {
570
+ return cleanup;
571
+ }, [cleanup]);
572
+ return {
573
+ // Performance state
574
+ paginationMode,
575
+ isVirtualized,
576
+ pageSizeOptions,
577
+ // Data management
578
+ processedData,
579
+ totalCount,
580
+ isLoading,
581
+ // Search functionality
582
+ searchQuery,
583
+ setSearchQuery,
584
+ searchResults,
585
+ // Server-side functionality
586
+ fetchServerData,
587
+ serverData,
588
+ // Performance monitoring
589
+ memoryUsage,
590
+ // Error handling and recovery
591
+ errorState,
592
+ retryLastOperation,
593
+ clearErrors,
594
+ // Cleanup
595
+ cleanup
596
+ };
597
+ }
598
+
599
+ export {
600
+ toast,
601
+ useToast,
602
+ determinePaginationMode,
603
+ getOptimalPageSizeOptions,
604
+ chunkData,
605
+ DataChunkManager,
606
+ SearchIndex,
607
+ debounce,
608
+ throttle,
609
+ VisibilityTracker,
610
+ DEFAULT_FALLBACK_CONFIG,
611
+ DataTableErrorType,
612
+ DataTableError,
613
+ ErrorRecoveryManager,
614
+ MemoryMonitor,
615
+ CircuitBreaker,
616
+ safeExecute,
617
+ useDataTablePerformance
618
+ };
619
+ //# sourceMappingURL=chunk-GKHF54DI.js.map