@jmruthers/pace-core 0.5.185 → 0.5.187

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 (300) hide show
  1. package/dist/{DataTable-Z9NLVJh0.d.ts → DataTable-IVYljGJ6.d.ts} +1 -1
  2. package/dist/{DataTable-IX2NBUTP.js → DataTable-K3RJRSOX.js} +7 -7
  3. package/dist/{PublicPageProvider-BABf6JCh.d.ts → PublicPageProvider-DrLDztHt.d.ts} +214 -107
  4. package/dist/{UnifiedAuthProvider-A4BCQRJY.js → UnifiedAuthProvider-B76OWOAT.js} +2 -2
  5. package/dist/{api-BMFCXVQX.js → api-YP7XD5L6.js} +3 -3
  6. package/dist/{audit-WRS3KJKI.js → audit-B5P6FFIR.js} +2 -2
  7. package/dist/{chunk-445GEP27.js → chunk-3IC5WCMO.js} +33 -8
  8. package/dist/chunk-3IC5WCMO.js.map +1 -0
  9. package/dist/{chunk-OKI34GZD.js → chunk-3NFNJOO7.js} +8 -8
  10. package/dist/chunk-3NFNJOO7.js.map +1 -0
  11. package/dist/{chunk-FSFQFJCU.js → chunk-63FOKYGO.js} +174 -6
  12. package/dist/chunk-63FOKYGO.js.map +1 -0
  13. package/dist/{chunk-MX3EIJGQ.js → chunk-C4OYJOV4.js} +631 -97
  14. package/dist/chunk-C4OYJOV4.js.map +1 -0
  15. package/dist/{chunk-HGPQUCBC.js → chunk-FMTK4XNN.js} +3 -3
  16. package/dist/{chunk-U6WNSFX5.js → chunk-HEHYGYOX.js} +279 -44
  17. package/dist/chunk-HEHYGYOX.js.map +1 -0
  18. package/dist/{chunk-XAUHJD3L.js → chunk-K2JGDXGU.js} +2 -2
  19. package/dist/{chunk-HC67NW5K.js → chunk-LBBUPSSC.js} +863 -552
  20. package/dist/chunk-LBBUPSSC.js.map +1 -0
  21. package/dist/{chunk-IXSNYUCT.js → chunk-SAUPYVLF.js} +1 -1
  22. package/dist/chunk-SAUPYVLF.js.map +1 -0
  23. package/dist/{chunk-AISXLWGZ.js → chunk-T6ZJVI3A.js} +27 -23
  24. package/dist/chunk-T6ZJVI3A.js.map +1 -0
  25. package/dist/{chunk-STTZQK2I.js → chunk-ULX5FYEM.js} +9 -7
  26. package/dist/chunk-ULX5FYEM.js.map +1 -0
  27. package/dist/{chunk-FXFJRTKI.js → chunk-WK2Y6TGA.js} +3 -3
  28. package/dist/chunk-WK2Y6TGA.js.map +1 -0
  29. package/dist/chunk-YHCN776L.js +447 -0
  30. package/dist/chunk-YHCN776L.js.map +1 -0
  31. package/dist/components.d.ts +4 -4
  32. package/dist/components.js +12 -10
  33. package/dist/components.js.map +1 -1
  34. package/dist/{database.generated-CBmg2950.d.ts → database.generated-DI89OQeI.d.ts} +63 -9
  35. package/dist/{file-reference-BjR39ktt.d.ts → file-reference-D037xOFK.d.ts} +3 -1
  36. package/dist/hooks.d.ts +265 -6
  37. package/dist/hooks.js +148 -49
  38. package/dist/hooks.js.map +1 -1
  39. package/dist/index.d.ts +25 -10
  40. package/dist/index.js +65 -30
  41. package/dist/index.js.map +1 -1
  42. package/dist/providers.js +1 -1
  43. package/dist/rbac/index.d.ts +125 -8
  44. package/dist/rbac/index.js +27 -7
  45. package/dist/{types-DUyCRSTj.d.ts → types-Bwgl--Xo.d.ts} +162 -1
  46. package/dist/types.d.ts +2 -2
  47. package/dist/types.js +1 -1
  48. package/dist/{usePublicRouteParams-CvnC3d-e.d.ts → usePublicRouteParams-CTDELQ7H.d.ts} +3 -3
  49. package/dist/utils.d.ts +214 -4
  50. package/dist/utils.js +22 -2
  51. package/dist/utils.js.map +1 -1
  52. package/docs/api/classes/ColumnFactory.md +1 -1
  53. package/docs/api/classes/ErrorBoundary.md +1 -1
  54. package/docs/api/classes/InvalidScopeError.md +1 -1
  55. package/docs/api/classes/Logger.md +1 -1
  56. package/docs/api/classes/MissingUserContextError.md +1 -1
  57. package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
  58. package/docs/api/classes/PermissionDeniedError.md +1 -1
  59. package/docs/api/classes/RBACAuditManager.md +21 -17
  60. package/docs/api/classes/RBACCache.md +31 -23
  61. package/docs/api/classes/RBACEngine.md +6 -6
  62. package/docs/api/classes/RBACError.md +1 -1
  63. package/docs/api/classes/RBACNotInitializedError.md +1 -1
  64. package/docs/api/classes/SecureSupabaseClient.md +5 -5
  65. package/docs/api/classes/StorageUtils.md +1 -1
  66. package/docs/api/enums/FileCategory.md +1 -1
  67. package/docs/api/enums/LogLevel.md +1 -1
  68. package/docs/api/enums/RBACErrorCode.md +1 -1
  69. package/docs/api/enums/RPCFunction.md +1 -1
  70. package/docs/api/interfaces/AddressFieldProps.md +241 -0
  71. package/docs/api/interfaces/AddressFieldRef.md +94 -0
  72. package/docs/api/interfaces/AggregateConfig.md +1 -1
  73. package/docs/api/interfaces/AutocompleteOptions.md +75 -0
  74. package/docs/api/interfaces/BadgeProps.md +1 -1
  75. package/docs/api/interfaces/ButtonProps.md +1 -1
  76. package/docs/api/interfaces/CalendarProps.md +1 -1
  77. package/docs/api/interfaces/CardProps.md +1 -1
  78. package/docs/api/interfaces/ColorPalette.md +1 -1
  79. package/docs/api/interfaces/ColorShade.md +1 -1
  80. package/docs/api/interfaces/ComplianceResult.md +1 -1
  81. package/docs/api/interfaces/DataAccessRecord.md +1 -1
  82. package/docs/api/interfaces/DataRecord.md +1 -1
  83. package/docs/api/interfaces/DataTableAction.md +1 -1
  84. package/docs/api/interfaces/DataTableColumn.md +1 -1
  85. package/docs/api/interfaces/DataTableProps.md +1 -1
  86. package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
  87. package/docs/api/interfaces/DatabaseComplianceResult.md +1 -1
  88. package/docs/api/interfaces/DatabaseIssue.md +1 -1
  89. package/docs/api/interfaces/EmptyStateConfig.md +1 -1
  90. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  91. package/docs/api/interfaces/EventAppRoleData.md +1 -1
  92. package/docs/api/interfaces/ExportColumn.md +1 -1
  93. package/docs/api/interfaces/ExportOptions.md +1 -1
  94. package/docs/api/interfaces/FileDisplayProps.md +15 -15
  95. package/docs/api/interfaces/FileMetadata.md +1 -1
  96. package/docs/api/interfaces/FileReference.md +1 -1
  97. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  98. package/docs/api/interfaces/FileUploadOptions.md +33 -9
  99. package/docs/api/interfaces/FileUploadProps.md +36 -14
  100. package/docs/api/interfaces/FooterProps.md +1 -1
  101. package/docs/api/interfaces/FormFieldProps.md +1 -1
  102. package/docs/api/interfaces/FormProps.md +1 -1
  103. package/docs/api/interfaces/GrantEventAppRoleParams.md +1 -1
  104. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  105. package/docs/api/interfaces/InputProps.md +1 -1
  106. package/docs/api/interfaces/LabelProps.md +1 -1
  107. package/docs/api/interfaces/LoggerConfig.md +1 -1
  108. package/docs/api/interfaces/LoginFormProps.md +1 -1
  109. package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
  110. package/docs/api/interfaces/NavigationContextType.md +1 -1
  111. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  112. package/docs/api/interfaces/NavigationItem.md +1 -1
  113. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  114. package/docs/api/interfaces/NavigationProviderProps.md +1 -1
  115. package/docs/api/interfaces/Organisation.md +1 -1
  116. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  117. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  118. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  119. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  120. package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
  121. package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
  122. package/docs/api/interfaces/PageAccessRecord.md +1 -1
  123. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  124. package/docs/api/interfaces/PagePermissionGuardProps.md +11 -11
  125. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  126. package/docs/api/interfaces/PaletteData.md +1 -1
  127. package/docs/api/interfaces/ParsedAddress.md +120 -0
  128. package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
  129. package/docs/api/interfaces/ProgressProps.md +1 -1
  130. package/docs/api/interfaces/ProtectedRouteProps.md +6 -6
  131. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  132. package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
  133. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  134. package/docs/api/interfaces/QuickFix.md +1 -1
  135. package/docs/api/interfaces/RBACAccessValidateParams.md +1 -1
  136. package/docs/api/interfaces/RBACAccessValidateResult.md +1 -1
  137. package/docs/api/interfaces/RBACAuditLogParams.md +1 -1
  138. package/docs/api/interfaces/RBACAuditLogResult.md +1 -1
  139. package/docs/api/interfaces/RBACConfig.md +27 -4
  140. package/docs/api/interfaces/RBACContext.md +1 -1
  141. package/docs/api/interfaces/RBACLogger.md +5 -5
  142. package/docs/api/interfaces/RBACPageAccessCheckParams.md +1 -1
  143. package/docs/api/interfaces/RBACPerformanceMetrics.md +138 -0
  144. package/docs/api/interfaces/RBACPermissionCheckParams.md +1 -1
  145. package/docs/api/interfaces/RBACPermissionCheckResult.md +1 -1
  146. package/docs/api/interfaces/RBACPermissionsGetParams.md +1 -1
  147. package/docs/api/interfaces/RBACPermissionsGetResult.md +1 -1
  148. package/docs/api/interfaces/RBACResult.md +1 -1
  149. package/docs/api/interfaces/RBACRoleGrantParams.md +1 -1
  150. package/docs/api/interfaces/RBACRoleGrantResult.md +1 -1
  151. package/docs/api/interfaces/RBACRoleRevokeParams.md +1 -1
  152. package/docs/api/interfaces/RBACRoleRevokeResult.md +1 -1
  153. package/docs/api/interfaces/RBACRoleValidateParams.md +1 -1
  154. package/docs/api/interfaces/RBACRoleValidateResult.md +1 -1
  155. package/docs/api/interfaces/RBACRolesListParams.md +1 -1
  156. package/docs/api/interfaces/RBACRolesListResult.md +1 -1
  157. package/docs/api/interfaces/RBACSessionTrackParams.md +1 -1
  158. package/docs/api/interfaces/RBACSessionTrackResult.md +1 -1
  159. package/docs/api/interfaces/ResourcePermissions.md +1 -1
  160. package/docs/api/interfaces/RevokeEventAppRoleParams.md +1 -1
  161. package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
  162. package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
  163. package/docs/api/interfaces/RoleManagementResult.md +1 -1
  164. package/docs/api/interfaces/RouteAccessRecord.md +1 -1
  165. package/docs/api/interfaces/RouteConfig.md +1 -1
  166. package/docs/api/interfaces/RuntimeComplianceResult.md +1 -1
  167. package/docs/api/interfaces/SecureDataContextType.md +1 -1
  168. package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
  169. package/docs/api/interfaces/SessionRestorationLoaderProps.md +1 -1
  170. package/docs/api/interfaces/SetupIssue.md +1 -1
  171. package/docs/api/interfaces/StorageConfig.md +1 -1
  172. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  173. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  174. package/docs/api/interfaces/StorageListOptions.md +1 -1
  175. package/docs/api/interfaces/StorageListResult.md +1 -1
  176. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  177. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  178. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  179. package/docs/api/interfaces/StyleImport.md +1 -1
  180. package/docs/api/interfaces/SwitchProps.md +1 -1
  181. package/docs/api/interfaces/TabsContentProps.md +1 -1
  182. package/docs/api/interfaces/TabsListProps.md +1 -1
  183. package/docs/api/interfaces/TabsProps.md +1 -1
  184. package/docs/api/interfaces/TabsTriggerProps.md +1 -1
  185. package/docs/api/interfaces/TextareaProps.md +1 -1
  186. package/docs/api/interfaces/ToastActionElement.md +1 -1
  187. package/docs/api/interfaces/ToastProps.md +1 -1
  188. package/docs/api/interfaces/UnifiedAuthContextType.md +1 -1
  189. package/docs/api/interfaces/UnifiedAuthProviderProps.md +1 -1
  190. package/docs/api/interfaces/UseFormDialogOptions.md +1 -1
  191. package/docs/api/interfaces/UseFormDialogReturn.md +1 -1
  192. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  193. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  194. package/docs/api/interfaces/UsePublicEventLogoOptions.md +2 -2
  195. package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
  196. package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
  197. package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
  198. package/docs/api/interfaces/UsePublicFileDisplayOptions.md +2 -2
  199. package/docs/api/interfaces/UsePublicFileDisplayReturn.md +1 -1
  200. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  201. package/docs/api/interfaces/UseResolvedScopeOptions.md +2 -2
  202. package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
  203. package/docs/api/interfaces/UseResourcePermissionsOptions.md +1 -1
  204. package/docs/api/interfaces/UserEventAccess.md +1 -1
  205. package/docs/api/interfaces/UserMenuProps.md +1 -1
  206. package/docs/api/interfaces/UserProfile.md +1 -1
  207. package/docs/api/modules.md +328 -69
  208. package/docs/api-reference/components.md +26 -12
  209. package/docs/best-practices/performance.md +11 -0
  210. package/docs/implementation-guides/file-reference-system.md +24 -2
  211. package/docs/implementation-guides/file-upload-storage.md +38 -1
  212. package/docs/rbac/README.md +2 -1
  213. package/docs/rbac/api-reference.md +11 -0
  214. package/docs/rbac/performance.md +320 -0
  215. package/docs/standards/01-architecture-standard.md +5 -0
  216. package/docs/standards/05-security-standard.md +12 -0
  217. package/package.json +1 -1
  218. package/scripts/check-pace-core-compliance.js +512 -0
  219. package/src/components/AddressField/AddressField.test.tsx +411 -0
  220. package/src/components/AddressField/AddressField.tsx +323 -0
  221. package/src/components/AddressField/README.md +336 -0
  222. package/src/components/AddressField/index.ts +10 -0
  223. package/src/components/AddressField/types.ts +65 -0
  224. package/src/components/FileDisplay/FileDisplay.test.tsx +454 -0
  225. package/src/components/FileDisplay/FileDisplay.tsx +28 -1
  226. package/src/components/FileUpload/FileUpload.test.tsx +2 -0
  227. package/src/components/FileUpload/FileUpload.tsx +7 -1
  228. package/src/components/Header/Header.tsx +2 -5
  229. package/src/components/ProtectedRoute/ProtectedRoute.tsx +134 -1
  230. package/src/components/index.ts +2 -0
  231. package/src/hooks/__tests__/useFileDisplay.unit.test.ts +30 -5
  232. package/src/hooks/__tests__/useOrganisationSecurity.unit.test.tsx +11 -10
  233. package/src/hooks/__tests__/usePublicFileDisplay.test.ts +31 -6
  234. package/src/hooks/index.ts +9 -0
  235. package/src/hooks/public/usePublicFileDisplay.ts +8 -10
  236. package/src/hooks/useAddressAutocomplete.test.ts +318 -0
  237. package/src/hooks/useAddressAutocomplete.ts +268 -0
  238. package/src/hooks/useFileDisplay.ts +3 -15
  239. package/src/hooks/useFileReference.test.ts +21 -3
  240. package/src/hooks/useFileReference.ts +3 -24
  241. package/src/hooks/useFileUrlCache.ts +246 -0
  242. package/src/hooks/useInactivityTracker.ts +31 -20
  243. package/src/hooks/useOrganisationSecurity.test.ts +10 -7
  244. package/src/hooks/useOrganisationSecurity.ts +3 -3
  245. package/src/hooks/usePreventTabReload.ts +106 -0
  246. package/src/hooks/useQueryCache.ts +315 -0
  247. package/src/hooks/useSecureDataAccess.ts +2 -2
  248. package/src/index.ts +2 -0
  249. package/src/providers/services/EventServiceProvider.tsx +4 -1
  250. package/src/rbac/__tests__/rbac-role-isolation.test.ts +456 -0
  251. package/src/rbac/api.test.ts +21 -6
  252. package/src/rbac/api.ts +32 -11
  253. package/src/rbac/audit-batched.ts +223 -0
  254. package/src/rbac/audit-enhanced.ts +2 -2
  255. package/src/rbac/audit.test.ts +6 -5
  256. package/src/rbac/audit.ts +34 -6
  257. package/src/rbac/cache-invalidation.ts +63 -12
  258. package/src/rbac/cache.test.ts +2 -2
  259. package/src/rbac/cache.ts +61 -14
  260. package/src/rbac/components/PagePermissionGuard.tsx +19 -10
  261. package/src/rbac/components/__tests__/PagePermissionGuard.performance.test.tsx +248 -0
  262. package/src/rbac/config.ts +9 -0
  263. package/src/rbac/engine.ts +2 -21
  264. package/src/rbac/hooks/usePermissions.ts +21 -5
  265. package/src/rbac/index.ts +19 -0
  266. package/src/rbac/performance.ts +210 -0
  267. package/src/rbac/request-deduplication.ts +87 -0
  268. package/src/rbac/utils/deep-equal.ts +93 -0
  269. package/src/styles/core.css +5 -5
  270. package/src/types/database.generated.ts +63 -9
  271. package/src/types/file-reference.ts +3 -1
  272. package/src/utils/file-reference/__tests__/file-reference.test.ts +89 -8
  273. package/src/utils/file-reference/index.ts +56 -17
  274. package/src/utils/google-places/googlePlacesUtils.test.ts +403 -0
  275. package/src/utils/google-places/googlePlacesUtils.ts +475 -0
  276. package/src/utils/google-places/index.ts +26 -0
  277. package/src/utils/google-places/loadGoogleMapsScript.ts +207 -0
  278. package/src/utils/google-places/types.ts +94 -0
  279. package/src/utils/index.ts +23 -0
  280. package/src/utils/request-deduplication.ts +165 -0
  281. package/src/utils/security/secureDataAccess.ts +1 -1
  282. package/src/utils/storage/helpers.ts +211 -4
  283. package/dist/chunk-445GEP27.js.map +0 -1
  284. package/dist/chunk-AISXLWGZ.js.map +0 -1
  285. package/dist/chunk-FMUCXFII.js +0 -76
  286. package/dist/chunk-FMUCXFII.js.map +0 -1
  287. package/dist/chunk-FSFQFJCU.js.map +0 -1
  288. package/dist/chunk-FXFJRTKI.js.map +0 -1
  289. package/dist/chunk-HC67NW5K.js.map +0 -1
  290. package/dist/chunk-IXSNYUCT.js.map +0 -1
  291. package/dist/chunk-MX3EIJGQ.js.map +0 -1
  292. package/dist/chunk-OKI34GZD.js.map +0 -1
  293. package/dist/chunk-STTZQK2I.js.map +0 -1
  294. package/dist/chunk-U6WNSFX5.js.map +0 -1
  295. /package/dist/{DataTable-IX2NBUTP.js.map → DataTable-K3RJRSOX.js.map} +0 -0
  296. /package/dist/{UnifiedAuthProvider-A4BCQRJY.js.map → UnifiedAuthProvider-B76OWOAT.js.map} +0 -0
  297. /package/dist/{api-BMFCXVQX.js.map → api-YP7XD5L6.js.map} +0 -0
  298. /package/dist/{audit-WRS3KJKI.js.map → audit-B5P6FFIR.js.map} +0 -0
  299. /package/dist/{chunk-HGPQUCBC.js.map → chunk-FMTK4XNN.js.map} +0 -0
  300. /package/dist/{chunk-XAUHJD3L.js.map → chunk-K2JGDXGU.js.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/DateTimeField/DateTimeField.tsx","../src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx"],"sourcesContent":["/**\n * @file DateTimeField Component\n * @package @jmruthers/pace-core\n * @module Components/DateTimeField\n * @since 0.1.0\n *\n * Form input component for datetime values with timezone support.\n * Handles UTC ↔ timezone conversion automatically.\n *\n * Features:\n * - Automatic UTC ↔ timezone conversion\n * - Prevents unwanted conversions during user editing\n * - Shows timezone information when not UTC\n * - Supports both ISO string and Date object values\n * - Uses native datetime-local input type\n * - Accessible form field with proper labels\n *\n * @example\n * ```tsx\n * import { DateTimeField } from '@jmruthers/pace-core/components';\n * import { useState } from 'react';\n *\n * function EventForm() {\n * const [startTime, setStartTime] = useState<string>();\n *\n * return (\n * <DateTimeField\n * label=\"Start Time\"\n * value={startTime}\n * onChange={setStartTime}\n * timezone=\"America/New_York\"\n * required\n * />\n * );\n * }\n * ```\n *\n * @accessibility\n * - Proper label association with htmlFor\n * - Required field indicators\n * - Screen reader friendly\n * - Keyboard navigation support\n * - Focus management\n */\n\nimport * as React from 'react';\nimport { format, parse } from 'date-fns';\nimport { Label } from '../Label';\nimport { Input } from '../Input';\nimport { cn } from '../../utils/core/cn';\nimport { toZonedTime, fromZonedTime, getUserTimeZone } from '../../utils/timezone';\n\n/**\n * Props for the DateTimeField component\n */\nexport interface DateTimeFieldProps {\n /**\n * Field label\n */\n label: string;\n /**\n * UTC date value (ISO string, Date object, or undefined)\n */\n value: string | Date | undefined;\n /**\n * Change handler that receives UTC value (ISO string or Date object)\n */\n onChange: (value: string | Date | undefined) => void;\n /**\n * Target timezone for display (default: 'UTC')\n */\n timezone?: string;\n /**\n * Whether the field is required\n */\n required?: boolean;\n /**\n * Additional CSS classes\n */\n className?: string;\n /**\n * If true, onChange returns Date object instead of ISO string\n */\n returnAsDate?: boolean;\n /**\n * Input id (auto-generated if not provided)\n */\n id?: string;\n /**\n * Helper text to display below the label\n */\n helperText?: string;\n /**\n * Error message to display\n */\n error?: string;\n}\n\n/**\n * DateTimeField component\n * Form input for datetime values with automatic timezone conversion\n *\n * @param props - DateTimeField configuration\n * @returns JSX.Element - The rendered datetime field\n */\nexport function DateTimeField({\n label,\n value,\n onChange,\n timezone = 'UTC',\n required = false,\n className,\n returnAsDate = false,\n id,\n helperText,\n error\n}: DateTimeFieldProps) {\n const [isEditing, setIsEditing] = React.useState(false);\n const inputRef = React.useRef<HTMLInputElement>(null);\n const fieldId = id || `datetime-field-${React.useId()}`;\n\n // Convert UTC value to timezone for display\n const getDisplayValue = React.useCallback((): string => {\n if (!value) {\n return '';\n }\n\n try {\n let dateObj: Date;\n if (typeof value === 'string') {\n dateObj = new Date(value);\n } else {\n dateObj = value;\n }\n\n if (!dateObj || isNaN(dateObj.getTime())) {\n return '';\n }\n\n // Convert UTC to timezone\n const zonedDate = toZonedTime(dateObj, timezone);\n\n // Format for datetime-local input (YYYY-MM-DDTHH:mm)\n return format(zonedDate, \"yyyy-MM-dd'T'HH:mm\");\n } catch {\n return '';\n }\n }, [value, timezone]);\n\n const displayValue = isEditing ? undefined : getDisplayValue();\n\n // Handle input change\n const handleChange = React.useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\n setIsEditing(true);\n const inputValue = e.target.value;\n\n if (!inputValue) {\n onChange(undefined);\n return;\n }\n\n try {\n // Parse the datetime-local value (in timezone)\n const localDate = parse(inputValue, \"yyyy-MM-dd'T'HH:mm\", new Date());\n\n if (isNaN(localDate.getTime())) {\n onChange(undefined);\n return;\n }\n\n // Convert from timezone to UTC\n const utcDate = fromZonedTime(localDate, timezone);\n\n // Return as ISO string or Date object\n if (returnAsDate) {\n onChange(utcDate);\n } else {\n onChange(utcDate.toISOString());\n }\n } catch {\n onChange(undefined);\n }\n }, [timezone, returnAsDate, onChange]);\n\n // Handle blur to stop editing mode\n const handleBlur = React.useCallback(() => {\n setIsEditing(false);\n }, []);\n\n // Get timezone display text\n const getTimezoneDisplay = React.useCallback((): string => {\n if (timezone === 'UTC') {\n return '';\n }\n\n const userTz = getUserTimeZone();\n if (timezone === userTz) {\n return 'Local';\n }\n\n return timezone;\n }, [timezone]);\n\n const timezoneDisplay = getTimezoneDisplay();\n\n return (\n <div className={cn('space-y-2', className)}>\n <Label htmlFor={fieldId} required={required} helperText={helperText} error={error}>\n {label}\n </Label>\n <div className=\"relative\">\n <Input\n ref={inputRef}\n id={fieldId}\n type=\"datetime-local\"\n value={displayValue}\n onChange={handleChange}\n onBlur={handleBlur}\n required={required}\n error={!!error}\n className=\"w-full\"\n />\n {timezoneDisplay && (\n <span className=\"absolute right-3 top-1/2 -translate-y-1/2 text-sm text-muted-foreground pointer-events-none\">\n {timezoneDisplay}\n </span>\n )}\n </div>\n </div>\n );\n}\n\n","/**\n * @file DatePickerWithTimezone Component\n * @package @jmruthers/pace-core\n * @module Components/DatePickerWithTimezone\n * @since 0.1.0\n *\n * Date picker component that displays timezone information alongside the calendar.\n * Provides a calendar interface with timezone context for date selection.\n *\n * Features:\n * - Calendar date selection\n * - Timezone display (shows \"Local\" when matches user timezone)\n * - Optional \"Done\" button\n * - Accessible date selection\n * - Keyboard navigation support\n *\n * @example\n * ```tsx\n * import { DatePickerWithTimezone } from '@jmruthers/pace-core/components';\n * import { useState } from 'react';\n *\n * function DateSelector() {\n * const [date, setDate] = useState<Date>();\n *\n * return (\n * <DatePickerWithTimezone\n * selected={date}\n * onSelect={setDate}\n * timezone=\"America/New_York\"\n * onDone={() => console.log('Date selected')}\n * />\n * );\n * }\n * ```\n *\n * @accessibility\n * - WCAG 2.1 AA compliant\n * - Keyboard navigation support\n * - Screen reader friendly\n * - Focus management\n * - Proper ARIA attributes\n */\n\nimport * as React from 'react';\nimport { Calendar } from '../Calendar';\nimport { Button } from '../Button';\nimport { Clock } from 'lucide-react';\nimport { getUserTimeZone } from '../../utils/timezone';\nimport { cn } from '../../utils/core/cn';\n\n/**\n * Props for the DatePickerWithTimezone component\n */\nexport interface DatePickerWithTimezoneProps {\n /**\n * Currently selected date\n */\n selected?: Date;\n /**\n * Date selection handler\n */\n onSelect: (date: Date | undefined) => void;\n /**\n * Optional callback when \"Done\" button is clicked\n */\n onDone?: () => void;\n /**\n * Timezone to display (defaults to user's timezone)\n */\n timezone?: string;\n /**\n * Additional CSS classes\n */\n className?: string;\n}\n\n/**\n * DatePickerWithTimezone component\n * Date picker with timezone information display\n *\n * @param props - DatePickerWithTimezone configuration\n * @returns JSX.Element - The rendered date picker with timezone\n */\nexport function DatePickerWithTimezone({\n selected,\n onSelect,\n onDone,\n timezone,\n className\n}: DatePickerWithTimezoneProps) {\n const userTimezone = getUserTimeZone();\n const displayTimezone = timezone || userTimezone;\n const timezoneDisplay = displayTimezone === userTimezone ? 'Local' : displayTimezone;\n\n return (\n <div className={cn('flex flex-col', className)}>\n <div className=\"p-3\">\n <Calendar\n mode=\"single\"\n selected={selected}\n onSelect={onSelect}\n initialFocus\n captionLayout=\"dropdown-buttons\"\n fromYear={1900}\n toYear={2100}\n className=\"p-0\"\n />\n </div>\n\n <div className=\"flex items-center justify-between border-t border-border px-3 py-2\">\n <div className=\"flex items-center gap-2 text-sm text-muted-foreground\">\n <Clock className=\"h-4 w-4\" aria-hidden=\"true\" />\n <span>\n Timezone: <span aria-label={`Timezone ${timezoneDisplay}`}>{timezoneDisplay}</span>\n </span>\n </div>\n {onDone && (\n <Button onClick={onDone} size=\"sm\" className=\"h-8\">\n Done\n </Button>\n )}\n </div>\n </div>\n );\n}\n\n"],"mappings":"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","names":["jsx","jsxs"]}
1
+ {"version":3,"sources":["../src/components/DateTimeField/DateTimeField.tsx","../src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx"],"sourcesContent":["/**\n * @file DateTimeField Component\n * @package @jmruthers/pace-core\n * @module Components/DateTimeField\n * @since 0.1.0\n *\n * Form input component for datetime values with timezone support.\n * Handles UTC ↔ timezone conversion automatically.\n *\n * Features:\n * - Automatic UTC ↔ timezone conversion\n * - Prevents unwanted conversions during user editing\n * - Shows timezone information when not UTC\n * - Supports both ISO string and Date object values\n * - Uses native datetime-local input type\n * - Accessible form field with proper labels\n *\n * @example\n * ```tsx\n * import { DateTimeField } from '@jmruthers/pace-core/components';\n * import { useState } from 'react';\n *\n * function EventForm() {\n * const [startTime, setStartTime] = useState<string>();\n *\n * return (\n * <DateTimeField\n * label=\"Start Time\"\n * value={startTime}\n * onChange={setStartTime}\n * timezone=\"America/New_York\"\n * required\n * />\n * );\n * }\n * ```\n *\n * @accessibility\n * - Proper label association with htmlFor\n * - Required field indicators\n * - Screen reader friendly\n * - Keyboard navigation support\n * - Focus management\n */\n\nimport * as React from 'react';\nimport { format, parse } from 'date-fns';\nimport { Label } from '../Label';\nimport { Input } from '../Input';\nimport { cn } from '../../utils/core/cn';\nimport { toZonedTime, fromZonedTime, getUserTimeZone } from '../../utils/timezone';\n\n/**\n * Props for the DateTimeField component\n */\nexport interface DateTimeFieldProps {\n /**\n * Field label\n */\n label: string;\n /**\n * UTC date value (ISO string, Date object, or undefined)\n */\n value: string | Date | undefined;\n /**\n * Change handler that receives UTC value (ISO string or Date object)\n */\n onChange: (value: string | Date | undefined) => void;\n /**\n * Target timezone for display (default: 'UTC')\n */\n timezone?: string;\n /**\n * Whether the field is required\n */\n required?: boolean;\n /**\n * Additional CSS classes\n */\n className?: string;\n /**\n * If true, onChange returns Date object instead of ISO string\n */\n returnAsDate?: boolean;\n /**\n * Input id (auto-generated if not provided)\n */\n id?: string;\n /**\n * Helper text to display below the label\n */\n helperText?: string;\n /**\n * Error message to display\n */\n error?: string;\n}\n\n/**\n * DateTimeField component\n * Form input for datetime values with automatic timezone conversion\n *\n * @param props - DateTimeField configuration\n * @returns JSX.Element - The rendered datetime field\n */\nexport function DateTimeField({\n label,\n value,\n onChange,\n timezone = 'UTC',\n required = false,\n className,\n returnAsDate = false,\n id,\n helperText,\n error\n}: DateTimeFieldProps) {\n const [isEditing, setIsEditing] = React.useState(false);\n const inputRef = React.useRef<HTMLInputElement>(null);\n const fieldId = id || `datetime-field-${React.useId()}`;\n\n // Convert UTC value to timezone for display\n const getDisplayValue = React.useCallback((): string => {\n if (!value) {\n return '';\n }\n\n try {\n let dateObj: Date;\n if (typeof value === 'string') {\n dateObj = new Date(value);\n } else {\n dateObj = value;\n }\n\n if (!dateObj || isNaN(dateObj.getTime())) {\n return '';\n }\n\n // Convert UTC to timezone\n const zonedDate = toZonedTime(dateObj, timezone);\n\n // Format for datetime-local input (YYYY-MM-DDTHH:mm)\n return format(zonedDate, \"yyyy-MM-dd'T'HH:mm\");\n } catch {\n return '';\n }\n }, [value, timezone]);\n\n const displayValue = isEditing ? undefined : getDisplayValue();\n\n // Handle input change\n const handleChange = React.useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\n setIsEditing(true);\n const inputValue = e.target.value;\n\n if (!inputValue) {\n onChange(undefined);\n return;\n }\n\n try {\n // Parse the datetime-local value (in timezone)\n const localDate = parse(inputValue, \"yyyy-MM-dd'T'HH:mm\", new Date());\n\n if (isNaN(localDate.getTime())) {\n onChange(undefined);\n return;\n }\n\n // Convert from timezone to UTC\n const utcDate = fromZonedTime(localDate, timezone);\n\n // Return as ISO string or Date object\n if (returnAsDate) {\n onChange(utcDate);\n } else {\n onChange(utcDate.toISOString());\n }\n } catch {\n onChange(undefined);\n }\n }, [timezone, returnAsDate, onChange]);\n\n // Handle blur to stop editing mode\n const handleBlur = React.useCallback(() => {\n setIsEditing(false);\n }, []);\n\n // Get timezone display text\n const getTimezoneDisplay = React.useCallback((): string => {\n if (timezone === 'UTC') {\n return '';\n }\n\n const userTz = getUserTimeZone();\n if (timezone === userTz) {\n return 'Local';\n }\n\n return timezone;\n }, [timezone]);\n\n const timezoneDisplay = getTimezoneDisplay();\n\n return (\n <div className={cn('space-y-2', className)}>\n <Label htmlFor={fieldId} required={required} helperText={helperText} error={error}>\n {label}\n </Label>\n <div className=\"relative\">\n <Input\n ref={inputRef}\n id={fieldId}\n type=\"datetime-local\"\n value={displayValue}\n onChange={handleChange}\n onBlur={handleBlur}\n required={required}\n error={!!error}\n className=\"w-full\"\n />\n {timezoneDisplay && (\n <span className=\"absolute right-3 top-1/2 -translate-y-1/2 text-sm text-muted-foreground pointer-events-none\">\n {timezoneDisplay}\n </span>\n )}\n </div>\n </div>\n );\n}\n\n","/**\n * @file DatePickerWithTimezone Component\n * @package @jmruthers/pace-core\n * @module Components/DatePickerWithTimezone\n * @since 0.1.0\n *\n * Date picker component that displays timezone information alongside the calendar.\n * Provides a calendar interface with timezone context for date selection.\n *\n * Features:\n * - Calendar date selection\n * - Timezone display (shows \"Local\" when matches user timezone)\n * - Optional \"Done\" button\n * - Accessible date selection\n * - Keyboard navigation support\n *\n * @example\n * ```tsx\n * import { DatePickerWithTimezone } from '@jmruthers/pace-core/components';\n * import { useState } from 'react';\n *\n * function DateSelector() {\n * const [date, setDate] = useState<Date>();\n *\n * return (\n * <DatePickerWithTimezone\n * selected={date}\n * onSelect={setDate}\n * timezone=\"America/New_York\"\n * onDone={() => console.log('Date selected')}\n * />\n * );\n * }\n * ```\n *\n * @accessibility\n * - WCAG 2.1 AA compliant\n * - Keyboard navigation support\n * - Screen reader friendly\n * - Focus management\n * - Proper ARIA attributes\n */\n\nimport * as React from 'react';\nimport { Calendar } from '../Calendar';\nimport { Button } from '../Button';\nimport { Clock } from 'lucide-react';\nimport { getUserTimeZone } from '../../utils/timezone';\nimport { cn } from '../../utils/core/cn';\n\n/**\n * Props for the DatePickerWithTimezone component\n */\nexport interface DatePickerWithTimezoneProps {\n /**\n * Currently selected date\n */\n selected?: Date;\n /**\n * Date selection handler\n */\n onSelect: (date: Date | undefined) => void;\n /**\n * Optional callback when \"Done\" button is clicked\n */\n onDone?: () => void;\n /**\n * Timezone to display (defaults to user's timezone)\n */\n timezone?: string;\n /**\n * Additional CSS classes\n */\n className?: string;\n}\n\n/**\n * DatePickerWithTimezone component\n * Date picker with timezone information display\n *\n * @param props - DatePickerWithTimezone configuration\n * @returns JSX.Element - The rendered date picker with timezone\n */\nexport function DatePickerWithTimezone({\n selected,\n onSelect,\n onDone,\n timezone,\n className\n}: DatePickerWithTimezoneProps) {\n const userTimezone = getUserTimeZone();\n const displayTimezone = timezone || userTimezone;\n const timezoneDisplay = displayTimezone === userTimezone ? 'Local' : displayTimezone;\n\n return (\n <div className={cn('flex flex-col', className)}>\n <div className=\"p-3\">\n <Calendar\n mode=\"single\"\n selected={selected}\n onSelect={onSelect}\n initialFocus\n captionLayout=\"dropdown-buttons\"\n fromYear={1900}\n toYear={2100}\n className=\"p-0\"\n />\n </div>\n\n <div className=\"flex items-center justify-between border-t border-border px-3 py-2\">\n <div className=\"flex items-center gap-2 text-sm text-muted-foreground\">\n <Clock className=\"h-4 w-4\" aria-hidden=\"true\" />\n <span>\n Timezone: <span aria-label={`Timezone ${timezoneDisplay}`}>{timezoneDisplay}</span>\n </span>\n </div>\n {onDone && (\n <Button onClick={onDone} size=\"sm\" className=\"h-8\">\n Done\n </Button>\n )}\n </div>\n </div>\n );\n}\n\n"],"mappings":"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","names":["jsx","jsxs"]}
@@ -3307,13 +3307,13 @@ type Database = {
3307
3307
  }
3308
3308
  ];
3309
3309
  };
3310
- pace_id_documents: {
3310
+ pace_identification: {
3311
3311
  Row: {
3312
3312
  created_at: string | null;
3313
3313
  document_number: string | null;
3314
- document_type: string;
3315
3314
  expiry_date: string | null;
3316
3315
  id: string;
3316
+ identification_type_id: number | null;
3317
3317
  issue_city: string | null;
3318
3318
  issue_country: string | null;
3319
3319
  issue_date: string | null;
@@ -3326,9 +3326,9 @@ type Database = {
3326
3326
  Insert: {
3327
3327
  created_at?: string | null;
3328
3328
  document_number?: string | null;
3329
- document_type: string;
3330
3329
  expiry_date?: string | null;
3331
3330
  id?: string;
3331
+ identification_type_id?: number | null;
3332
3332
  issue_city?: string | null;
3333
3333
  issue_country?: string | null;
3334
3334
  issue_date?: string | null;
@@ -3341,9 +3341,9 @@ type Database = {
3341
3341
  Update: {
3342
3342
  created_at?: string | null;
3343
3343
  document_number?: string | null;
3344
- document_type?: string;
3345
3344
  expiry_date?: string | null;
3346
3345
  id?: string;
3346
+ identification_type_id?: number | null;
3347
3347
  issue_city?: string | null;
3348
3348
  issue_country?: string | null;
3349
3349
  issue_date?: string | null;
@@ -3355,14 +3355,21 @@ type Database = {
3355
3355
  };
3356
3356
  Relationships: [
3357
3357
  {
3358
- foreignKeyName: "fk_pace_id_documents_organisation_id";
3358
+ foreignKeyName: "fk_pace_identification_organisation_id";
3359
3359
  columns: ["organisation_id"];
3360
3360
  isOneToOne: false;
3361
3361
  referencedRelation: "organisations";
3362
3362
  referencedColumns: ["id"];
3363
3363
  },
3364
3364
  {
3365
- foreignKeyName: "identification_documents_member_id_fkey";
3365
+ foreignKeyName: "fk_pace_identification_type_id";
3366
+ columns: ["identification_type_id"];
3367
+ isOneToOne: false;
3368
+ referencedRelation: "pace_identification_type";
3369
+ referencedColumns: ["id"];
3370
+ },
3371
+ {
3372
+ foreignKeyName: "pace_identification_member_id_fkey";
3366
3373
  columns: ["member_id"];
3367
3374
  isOneToOne: false;
3368
3375
  referencedRelation: "pace_member";
@@ -3370,6 +3377,53 @@ type Database = {
3370
3377
  }
3371
3378
  ];
3372
3379
  };
3380
+ pace_identification_type: {
3381
+ Row: {
3382
+ created_at: string | null;
3383
+ created_by: string | null;
3384
+ description: string | null;
3385
+ id: number;
3386
+ is_active: boolean | null;
3387
+ name: string;
3388
+ organisation_id: string;
3389
+ sort_order: number | null;
3390
+ updated_at: string | null;
3391
+ updated_by: string | null;
3392
+ };
3393
+ Insert: {
3394
+ created_at?: string | null;
3395
+ created_by?: string | null;
3396
+ description?: string | null;
3397
+ id?: never;
3398
+ is_active?: boolean | null;
3399
+ name: string;
3400
+ organisation_id: string;
3401
+ sort_order?: number | null;
3402
+ updated_at?: string | null;
3403
+ updated_by?: string | null;
3404
+ };
3405
+ Update: {
3406
+ created_at?: string | null;
3407
+ created_by?: string | null;
3408
+ description?: string | null;
3409
+ id?: never;
3410
+ is_active?: boolean | null;
3411
+ name?: string;
3412
+ organisation_id?: string;
3413
+ sort_order?: number | null;
3414
+ updated_at?: string | null;
3415
+ updated_by?: string | null;
3416
+ };
3417
+ Relationships: [
3418
+ {
3419
+ foreignKeyName: "pace_identification_type_organisation_id_fkey";
3420
+ columns: ["organisation_id"];
3421
+ isOneToOne: false;
3422
+ referencedRelation: "organisations";
3423
+ referencedColumns: ["id"];
3424
+ }
3425
+ ];
3426
+ };
3373
3427
  pace_member: {
3374
3428
  Row: {
3375
3429
  address_id: string | null;
@@ -3839,7 +3893,7 @@ type Database = {
3839
3893
  }
3840
3894
  ];
3841
3895
  };
3842
- pace_qualifications: {
3896
+ pace_qualification: {
3843
3897
  Row: {
3844
3898
  created_at: string | null;
3845
3899
  credential_id: string | null;
@@ -3881,14 +3935,14 @@ type Database = {
3881
3935
  };
3882
3936
  Relationships: [
3883
3937
  {
3884
- foreignKeyName: "fk_pace_qualifications_organisation_id";
3938
+ foreignKeyName: "fk_pace_qualification_organisation_id";
3885
3939
  columns: ["organisation_id"];
3886
3940
  isOneToOne: false;
3887
3941
  referencedRelation: "organisations";
3888
3942
  referencedColumns: ["id"];
3889
3943
  },
3890
3944
  {
3891
- foreignKeyName: "qualifications_member_id_fkey";
3945
+ foreignKeyName: "pace_qualification_member_id_fkey";
3892
3946
  columns: ["member_id"];
3893
3947
  isOneToOne: false;
3894
3948
  referencedRelation: "pace_member";
@@ -47,6 +47,7 @@ declare enum FileCategory {
47
47
  * Options for uploading a file with a file reference
48
48
  * @property pageContext - The page context where the file upload occurs (e.g., 'configuration', 'forms', 'applications')
49
49
  * Used for context-aware permission checks. Required to check appropriate page-level permissions.
50
+ * @property event_id - Optional event ID for event-scoped permission checks. Required for event-based apps.
50
51
  */
51
52
  interface FileUploadOptions {
52
53
  table_name: string;
@@ -54,7 +55,9 @@ interface FileUploadOptions {
54
55
  organisation_id: string;
55
56
  app_id: AppId;
56
57
  category: FileCategory;
58
+ folder: string;
57
59
  pageContext: string;
60
+ event_id?: string;
58
61
  is_public?: boolean;
59
62
  custom_metadata?: Record<string, unknown>;
60
63
  }
@@ -73,7 +76,6 @@ interface FileReferenceService {
73
76
  }
74
77
  interface StorageUploadOptions {
75
78
  orgId: string;
76
- category: FileCategory;
77
79
  isPublic?: boolean;
78
80
  customPath?: string;
79
81
  }
package/dist/hooks.d.ts CHANGED
@@ -1,17 +1,17 @@
1
1
  export { u as useToast } from './useToast-C8gR5ir4.js';
2
- import { S as StorageUploadOptions, a as StorageUploadResult, b as StorageListOptions, c as StorageListResult, d as StorageFileInfo } from './usePublicRouteParams-CvnC3d-e.js';
3
- export { O as OrganisationSecurityHook, l as UseAppConfigReturn, i as UseFormDialogOptions, j as UseFormDialogReturn, U as UseOrganisationPermissionsReturn, F as UsePublicEventLogoOptions, E as UsePublicEventLogoReturn, B as UsePublicEventOptions, A as UsePublicEventReturn, D as UsePublicFileDisplayOptions, C as UsePublicFileDisplayReturn, G as UsePublicRouteParamsReturn, n as clearPublicEventCache, q as clearPublicFileDisplayCache, t as clearPublicLogoCache, z as extractEventCodeFromPath, y as generatePublicRoutePath, o as getPublicEventCacheStats, r as getPublicFileDisplayCacheStats, v as getPublicLogoCacheStats, k as useAppConfig, u as useEventTheme, h as useFormDialog, e as useOrganisationPermissions, f as useOrganisationSecurity, m as usePublicEvent, x as usePublicEventCode, s as usePublicEventLogo, p as usePublicFileDisplay, w as usePublicRouteParams, g as useZodForm } from './usePublicRouteParams-CvnC3d-e.js';
2
+ import { a as StorageUploadOptions, c as StorageUploadResult, e as StorageListOptions, f as StorageListResult, m as StorageFileInfo } from './usePublicRouteParams-CTDELQ7H.js';
3
+ export { O as OrganisationSecurityHook, K as UseAppConfigReturn, U as UseFormDialogOptions, h as UseFormDialogReturn, J as UseOrganisationPermissionsReturn, H as UsePublicEventLogoOptions, G as UsePublicEventLogoReturn, C as UsePublicEventOptions, B as UsePublicEventReturn, E as UsePublicFileDisplayOptions, D as UsePublicFileDisplayReturn, I as UsePublicRouteParamsReturn, o as clearPublicEventCache, r as clearPublicFileDisplayCache, v as clearPublicLogoCache, A as extractEventCodeFromPath, z as generatePublicRoutePath, p as getPublicEventCacheStats, s as getPublicFileDisplayCacheStats, w as getPublicLogoCacheStats, k as useAppConfig, l as useEventTheme, g as useFormDialog, i as useOrganisationPermissions, j as useOrganisationSecurity, n as usePublicEvent, y as usePublicEventCode, t as usePublicEventLogo, q as usePublicFileDisplay, x as usePublicRouteParams, u as useZodForm } from './usePublicRouteParams-CTDELQ7H.js';
4
4
  import * as React$1 from 'react';
5
5
  import { SortingState, ColumnFiltersState, ExpandedState } from '@tanstack/react-table';
6
+ import { d as DataRecord, g as PerformanceConfig, S as ServerSideConfig, C as ChunkingConfig, i as SearchIndexConfig, h as PaginationMode, k as ServerSideParams, l as ServerSideResponse, A as AutocompleteOptions, m as GooglePlaceAutocompletePrediction, P as ParsedAddress } from './types-Bwgl--Xo.js';
6
7
  export { u as useComponentPerformance } from './useComponentPerformance-DE9l5RkL.js';
7
- import { c as DataRecord, P as PerformanceConfig, S as ServerSideConfig, C as ChunkingConfig, g as SearchIndexConfig, f as PaginationMode, i as ServerSideParams, j as ServerSideResponse } from './types-DUyCRSTj.js';
8
8
  import { SupabaseClient } from '@supabase/supabase-js';
9
- import { F as FileCategory, a as FileReference } from './file-reference-BjR39ktt.js';
9
+ import { D as Database } from './database.generated-DI89OQeI.js';
10
+ import { F as FileCategory, a as FileReference } from './file-reference-D037xOFK.js';
10
11
  import 'react-hook-form';
11
12
  import 'zod';
12
13
  import './event-CW5YB_2p.js';
13
14
  import './core-CUElvH_C.js';
14
- import './database.generated-CBmg2950.js';
15
15
 
16
16
  /**
17
17
  * @file Error Handling Stubs
@@ -227,6 +227,64 @@ declare function useDataTableState(options: UseDataTableStateOptions): {
227
227
  };
228
228
  };
229
229
 
230
+ /**
231
+ * @file Address Autocomplete Hook
232
+ * @package @jmruthers/pace-core
233
+ * @module Hooks/AddressAutocomplete
234
+ * @since 0.1.0
235
+ *
236
+ * Hook for managing Google Places API autocomplete functionality.
237
+ * Provides debounced input, caching, and address selection.
238
+ */
239
+
240
+ interface UseAddressAutocompleteOptions {
241
+ /** Google Places API options */
242
+ autocompleteOptions?: AutocompleteOptions;
243
+ /** Debounce delay in milliseconds (default: 300) */
244
+ debounceDelay?: number;
245
+ /** Enable caching (default: true) */
246
+ cacheEnabled?: boolean;
247
+ /** Cache TTL configuration */
248
+ cacheTTL?: {
249
+ /** Autocomplete cache TTL in seconds (default: 3600 = 1 hour) */
250
+ autocomplete?: number;
251
+ /** Place details cache TTL in seconds (default: 86400 = 24 hours) */
252
+ placeDetails?: number;
253
+ };
254
+ }
255
+ interface UseAddressAutocompleteReturn {
256
+ /** Array of autocomplete suggestions */
257
+ suggestions: GooglePlaceAutocompletePrediction[];
258
+ /** Loading state */
259
+ isLoading: boolean;
260
+ /** Error state */
261
+ error: Error | null;
262
+ /** Select an address by place_id */
263
+ selectAddress: (placeId: string) => Promise<ParsedAddress | null>;
264
+ /** Get address by place_id (uses cache) */
265
+ getAddressByPlaceId: (placeId: string) => Promise<ParsedAddress | null>;
266
+ /** Clear suggestions */
267
+ clearSuggestions: () => void;
268
+ }
269
+ /**
270
+ * Hook for Google Places API autocomplete with caching
271
+ *
272
+ * @param apiKey - Google Places API key
273
+ * @param inputValue - Current input value
274
+ * @param options - Hook configuration options
275
+ * @returns Autocomplete state and functions
276
+ *
277
+ * @example
278
+ * ```tsx
279
+ * const { suggestions, isLoading, selectAddress } = useAddressAutocomplete(
280
+ * apiKey,
281
+ * inputValue,
282
+ * { debounceDelay: 300, cacheEnabled: true }
283
+ * );
284
+ * ```
285
+ */
286
+ declare function useAddressAutocomplete(apiKey: string, inputValue: string, options?: UseAddressAutocompleteOptions): UseAddressAutocompleteReturn;
287
+
230
288
  /**
231
289
  * @file useSecureDataAccess Hook
232
290
  * @package @jmruthers/pace-core
@@ -359,6 +417,86 @@ declare function usePerformanceMonitor(componentName: string, enabled?: boolean,
359
417
  endMeasurement: () => void;
360
418
  };
361
419
 
420
+ /**
421
+ * Query Result Caching Hook
422
+ * @package @jmruthers/pace-core
423
+ * @module Hooks/QueryCache
424
+ * @since 2.0.0
425
+ *
426
+ * Provides in-memory caching for frequently accessed data to eliminate duplicate queries.
427
+ * Useful for caching user profiles, app pages, and other relatively static data.
428
+ */
429
+
430
+ interface UseQueryCacheOptions {
431
+ /** Time to live in seconds (default: 300 = 5 minutes) */
432
+ ttl?: number;
433
+ /** Whether to enable caching (default: true) */
434
+ enabled?: boolean;
435
+ }
436
+ interface UseQueryCacheReturn {
437
+ /** Get cached query result or fetch if not cached */
438
+ getCachedQuery: <T>(table: string, filterKey: string, filterValue: string, fetchFn: () => Promise<T>, options?: UseQueryCacheOptions) => Promise<T>;
439
+ /** Invalidate a specific cached query */
440
+ invalidateQuery: (table: string, filterKey: string, filterValue: string) => void;
441
+ /** Clear all cached queries */
442
+ clearCache: () => void;
443
+ /** Get cache statistics */
444
+ getCacheStats: () => {
445
+ size: number;
446
+ keys: string[];
447
+ };
448
+ }
449
+ /**
450
+ * Hook for query result caching
451
+ *
452
+ * Provides caching for frequently accessed data to eliminate duplicate queries.
453
+ * Automatically handles cache expiration and cleanup.
454
+ *
455
+ * @param supabase - Supabase client (optional, can be passed in fetchFn)
456
+ * @returns Query cache utilities
457
+ *
458
+ * @example
459
+ * ```tsx
460
+ * const { getCachedQuery } = useQueryCache(supabase);
461
+ *
462
+ * const person = await getCachedQuery(
463
+ * 'pace_person',
464
+ * 'user_id',
465
+ * userId,
466
+ * async () => {
467
+ * const { data } = await supabase
468
+ * .from('pace_person')
469
+ * .select('id, first_name, last_name, email')
470
+ * .eq('user_id', userId)
471
+ * .single();
472
+ * return data;
473
+ * },
474
+ * { ttl: 300 } // 5 minutes
475
+ * );
476
+ * ```
477
+ */
478
+ declare function useQueryCache(supabase?: SupabaseClient<Database>): UseQueryCacheReturn;
479
+ /**
480
+ * Pre-configured cache helpers for common queries
481
+ */
482
+ declare const queryCacheHelpers: {
483
+ /**
484
+ * Cache pace_person queries by user_id
485
+ * TTL: 5 minutes
486
+ */
487
+ pacePersonByUserId: <T>(supabase: SupabaseClient<Database>, userId: string, fetchFn: () => Promise<T>) => Promise<T>;
488
+ /**
489
+ * Cache pace_member queries by person_id
490
+ * TTL: 5 minutes
491
+ */
492
+ paceMemberByPersonId: <T>(supabase: SupabaseClient<Database>, personId: string, fetchFn: () => Promise<T>) => Promise<T>;
493
+ /**
494
+ * Cache rbac_app_pages queries by app_id
495
+ * TTL: 15 minutes (app pages are relatively static)
496
+ */
497
+ rbacAppPagesByAppId: <T>(supabase: SupabaseClient<Database>, appId: string, fetchFn: () => Promise<T>) => Promise<T>;
498
+ };
499
+
362
500
  /**
363
501
  * @file File Display Hook (Authenticated)
364
502
  * @package @jmruthers/pace-core
@@ -459,6 +597,83 @@ declare function getFileDisplayCacheStats(): {
459
597
  */
460
598
  declare function invalidateFileDisplayCache(table_name: string, record_id: string, organisation_id: string, category?: FileCategory): void;
461
599
 
600
+ /**
601
+ * @file File URL Cache Hook
602
+ * @package @jmruthers/pace-core
603
+ * @module Hooks
604
+ *
605
+ * Centralized caching hook for file URLs to prevent duplicate requests
606
+ * and improve performance across components.
607
+ *
608
+ * Features:
609
+ * - TTL-based caching matching signed URL expiration (3600s)
610
+ * - Automatic cache cleanup
611
+ * - Supports both public and signed URLs
612
+ * - Thread-safe cache operations
613
+ *
614
+ * @example
615
+ * ```tsx
616
+ * import { useFileUrlCache } from '@jmruthers/pace-core';
617
+ *
618
+ * function MyComponent() {
619
+ * const { getUrl, setUrl, clearCache } = useFileUrlCache();
620
+ *
621
+ * const url = await getUrl(fileReference, supabase, organisationId);
622
+ * return <img src={url} alt="File" />;
623
+ * }
624
+ * ```
625
+ */
626
+
627
+ interface UseFileUrlCacheReturn {
628
+ /**
629
+ * Get URL for a file reference, using cache if available
630
+ * @param fileReference - File reference to get URL for
631
+ * @param supabase - Supabase client instance
632
+ * @param organisationId - Organisation ID for signed URLs
633
+ * @param ttl - Time to live in milliseconds (default: 3600000 = 1 hour)
634
+ * @returns Promise resolving to URL string or null
635
+ */
636
+ getUrl: (fileReference: FileReference, supabase: SupabaseClient, organisationId: string, ttl?: number) => Promise<string | null>;
637
+ /**
638
+ * Set URL in cache
639
+ * @param fileReference - File reference
640
+ * @param url - URL to cache
641
+ * @param ttl - Time to live in milliseconds (default: 3600000 = 1 hour)
642
+ */
643
+ setUrl: (fileReference: FileReference, url: string, ttl?: number) => void;
644
+ /**
645
+ * Get URL from cache without generating if missing
646
+ * @param fileReference - File reference
647
+ * @returns Cached URL or null if not in cache or expired
648
+ */
649
+ getCachedUrl: (fileReference: FileReference) => string | null;
650
+ /**
651
+ * Clear cache for a specific file reference
652
+ * @param fileReference - File reference to clear
653
+ */
654
+ clearFile: (fileReference: FileReference) => void;
655
+ /**
656
+ * Clear all cached URLs
657
+ */
658
+ clearCache: () => void;
659
+ /**
660
+ * Get cache statistics
661
+ */
662
+ getCacheStats: () => {
663
+ size: number;
664
+ maxSize: number;
665
+ };
666
+ }
667
+ /**
668
+ * Hook for centralized file URL caching
669
+ *
670
+ * This hook provides a shared cache for file URLs across all components,
671
+ * preventing duplicate requests for the same file.
672
+ *
673
+ * @returns Cache operations and utilities
674
+ */
675
+ declare function useFileUrlCache(): UseFileUrlCacheReturn;
676
+
462
677
  /**
463
678
  * React hook for storage operations
464
679
  */
@@ -505,4 +720,48 @@ declare function useFileUpload({ supabase, appName, orgId }: UseStorageOptions):
505
720
  uploadError: string | null;
506
721
  };
507
722
 
508
- export { type SecureDataAccessReturn, type UseDataTablePerformanceOptions, type UseDataTablePerformanceReturn, type UseFileDisplayOptions, type UseFileDisplayReturn, type UseStorageOptions, type UseStorageReturn, clearFileDisplayCache, getFileDisplayCacheStats, invalidateFileDisplayCache, useDataTablePerformance, useDataTableState, useDebounce, useFileDisplay, useFileUpload, useFocusManagement, useFocusTrap, useIsMobile, useKeyboardShortcuts, usePerformanceMonitor, useSecureDataAccess, useStorage };
723
+ /**
724
+ * @file usePreventTabReload Hook
725
+ * @package @jmruthers/pace-core
726
+ * @module Hooks
727
+ * @since 0.6.0
728
+ *
729
+ * Prevents full page reloads when switching browser tabs.
730
+ * Handles browser back-forward cache (bfcache) restoration and tab visibility changes.
731
+ */
732
+ interface UsePreventTabReloadOptions {
733
+ /**
734
+ * Whether to enable the prevention logic
735
+ * @default true
736
+ */
737
+ enabled?: boolean;
738
+ /**
739
+ * Grace period in milliseconds to wait after tab becomes visible
740
+ * before allowing any potential reloads
741
+ * @default 2000
742
+ */
743
+ gracePeriodMs?: number;
744
+ }
745
+ /**
746
+ * Hook to prevent full page reloads when switching browser tabs.
747
+ *
748
+ * This hook handles:
749
+ * - Browser back-forward cache (bfcache) restoration
750
+ * - Tab visibility changes
751
+ * - Prevents unwanted page reloads when returning to a tab
752
+ *
753
+ * @param options - Configuration options
754
+ *
755
+ * @example
756
+ * ```tsx
757
+ * import { usePreventTabReload } from '@jmruthers/pace-core';
758
+ *
759
+ * function MyComponent() {
760
+ * usePreventTabReload();
761
+ * // Component code...
762
+ * }
763
+ * ```
764
+ */
765
+ declare function usePreventTabReload(options?: UsePreventTabReloadOptions): void;
766
+
767
+ export { type SecureDataAccessReturn, type UseAddressAutocompleteOptions, type UseAddressAutocompleteReturn, type UseDataTablePerformanceOptions, type UseDataTablePerformanceReturn, type UseFileDisplayOptions, type UseFileDisplayReturn, type UseFileUrlCacheReturn, type UsePreventTabReloadOptions, type UseQueryCacheOptions, type UseQueryCacheReturn, type UseStorageOptions, type UseStorageReturn, clearFileDisplayCache, getFileDisplayCacheStats, invalidateFileDisplayCache, queryCacheHelpers, useAddressAutocomplete, useDataTablePerformance, useDataTableState, useDebounce, useFileDisplay, useFileUpload, useFileUrlCache, useFocusManagement, useFocusTrap, useIsMobile, useKeyboardShortcuts, usePerformanceMonitor, usePreventTabReload, useQueryCache, useSecureDataAccess, useStorage };