@jmruthers/pace-core 0.6.10 → 0.6.12
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.
- package/CHANGELOG.md +21 -0
- package/audit-tool/00-dependencies.cjs +46 -13
- package/audit-tool/audits/01-pace-core-compliance.cjs +96 -21
- package/audit-tool/audits/02-project-structure.cjs +13 -3
- package/audit-tool/audits/03-architecture.cjs +78 -4
- package/audit-tool/audits/04-code-quality.cjs +9 -2
- package/audit-tool/audits/05-styling.cjs +19 -7
- package/audit-tool/audits/06-security-rbac.cjs +105 -14
- package/audit-tool/audits/07-api-tech-stack.cjs +31 -15
- package/audit-tool/audits/08-testing-documentation.cjs +11 -3
- package/audit-tool/audits/09-operations.cjs +19 -7
- package/audit-tool/index.cjs +22 -11
- package/audit-tool/utils/report-utils.cjs +4 -0
- package/cursor-rules/01-pace-core-compliance.mdc +1 -0
- package/cursor-rules/02-project-structure.mdc +1 -0
- package/cursor-rules/03-architecture.mdc +3 -1
- package/cursor-rules/04-code-quality.mdc +1 -0
- package/cursor-rules/05-styling.mdc +41 -7
- package/cursor-rules/06-security-rbac.mdc +2 -1
- package/cursor-rules/07-api-tech-stack.mdc +1 -0
- package/cursor-rules/08-testing-documentation.mdc +1 -0
- package/cursor-rules/09-operations.mdc +1 -0
- package/dist/DataTable-AQAHSFLM.js +17 -0
- package/dist/InactivityServiceProvider-BbxwwDz1.d.ts +308 -0
- package/dist/UnifiedAuthProvider-Bkt_tzdS.d.ts +183 -0
- package/dist/api-6OQXYT67.js +6 -0
- package/dist/api-result-USV1Czr-.d.ts +51 -0
- package/dist/audit-HI2DHUVU.js +4 -0
- package/dist/auth-JvdRVaud.d.ts +49 -0
- package/dist/chunk-2DL2WSOE.js +327 -0
- package/dist/chunk-2GBDPPUC.js +61 -0
- package/dist/chunk-44CNXN4P.js +15 -0
- package/dist/chunk-AP5FG7W4.js +2159 -0
- package/dist/chunk-CU2BU2MQ.js +2 -0
- package/dist/chunk-D6BMFMQZ.js +200 -0
- package/dist/chunk-ENLXB7GP.js +721 -0
- package/dist/chunk-GHCUP64P.js +105 -0
- package/dist/chunk-H6RTU4DZ.js +1098 -0
- package/dist/chunk-HQTYP6BX.js +6468 -0
- package/dist/chunk-M7QE7XOA.js +529 -0
- package/dist/chunk-MVVWZ7JV.js +1329 -0
- package/dist/chunk-NJ7FGQWB.js +811 -0
- package/dist/chunk-QRYSEPHB.js +429 -0
- package/dist/chunk-QWIG36BZ.js +264 -0
- package/dist/chunk-S57OLCLO.js +2946 -0
- package/dist/chunk-VFLR5K2H.js +23 -0
- package/dist/chunk-XOJME5T7.js +407 -0
- package/dist/chunk-XPFVT3GN.js +492 -0
- package/dist/chunk-Y2LWSLLB.js +9614 -0
- package/dist/chunk-YFGNMB67.js +2390 -0
- package/dist/components.d.ts +10 -9
- package/dist/components.js +20 -17
- package/dist/database.generated-qkdoiVrJ.d.ts +9441 -0
- package/dist/eslint-rules/index.cjs +3 -0
- package/dist/eslint-rules/rules/03-architecture.cjs +74 -0
- package/dist/eslint-rules/rules/06-security-rbac.cjs +74 -0
- package/dist/event-BfCox3N2.d.ts +265 -0
- package/dist/file-reference-DU1hcawx.d.ts +164 -0
- package/dist/functions-hF5ImHCr.d.ts +208 -0
- package/dist/hooks.d.ts +22 -9
- package/dist/hooks.js +35 -25
- package/dist/icons/index.d.ts +1 -0
- package/dist/icons/index.js +1 -0
- package/dist/index.d.ts +69 -180
- package/dist/index.js +319 -342
- package/dist/pagination-BW1mqywp.d.ts +201 -0
- package/dist/providers.d.ts +6 -5
- package/dist/providers.js +6 -3
- package/dist/rbac/index.d.ts +133 -148
- package/dist/rbac/index.js +12 -9
- package/dist/theming/runtime.d.ts +19 -2
- package/dist/theming/runtime.js +1 -1
- package/dist/timezone-BTWWXKVY.d.ts +696 -0
- package/dist/types-Besvoyzb.d.ts +55 -0
- package/dist/types-CGHrxfqc.d.ts +114 -0
- package/dist/types.d.ts +19 -12
- package/dist/types.js +1 -0
- package/dist/usePublicPageContext-BQrHf95t.d.ts +4367 -0
- package/dist/usePublicRouteParams-BgV6VhMi.d.ts +946 -0
- package/dist/utils.d.ts +163 -145
- package/dist/utils.js +45 -27
- package/docs/api/@jmruthers/namespaces/DialogPortal/README.md +14 -0
- package/docs/api/@jmruthers/namespaces/DialogPortal/variables/displayName.md +11 -0
- package/docs/api/README.md +6 -2
- package/docs/api/_media/README.md +186 -0
- package/docs/api/classes/ColumnFactory.md +225 -0
- package/docs/api/classes/Logger.md +246 -0
- package/docs/api/classes/RBACAuditManager.md +299 -0
- package/docs/api/classes/RBACCache.md +389 -0
- package/docs/api/classes/RBACEngine.md +181 -0
- package/docs/api/classes/SecureSupabaseClient.md +168 -0
- package/docs/api/classes/StorageUtils.md +324 -0
- package/docs/api/enumerations/FileCategory.md +137 -0
- package/docs/api/enumerations/LogLevel.md +43 -0
- package/docs/api/enumerations/RBACErrorCode.md +169 -0
- package/docs/api/enumerations/RPCFunction.md +89 -0
- package/docs/api/functions/AccessDenied.md +30 -0
- package/docs/api/functions/AppSwitcher.md +21 -0
- package/docs/api/functions/Badge.md +42 -0
- package/docs/api/functions/ContextSelector.md +43 -0
- package/docs/api/functions/DataTable.md +36 -0
- package/docs/api/functions/DatePickerWithTimezone.md +28 -0
- package/docs/api/functions/DialogBody.md +24 -0
- package/docs/api/functions/DialogFooter.md +24 -0
- package/docs/api/functions/DialogHeader.md +24 -0
- package/docs/api/functions/ErrorBoundaryProvider.md +28 -0
- package/docs/api/functions/EventServiceProvider.md +28 -0
- package/docs/api/functions/FileDisplay.md +25 -0
- package/docs/api/functions/FileUpload.md +21 -0
- package/docs/api/functions/Form.md +50 -0
- package/docs/api/functions/FormField.md +102 -0
- package/docs/api/functions/Header.md +21 -0
- package/docs/api/functions/InactivityServiceProvider.md +28 -0
- package/docs/api/functions/InactivityWarningModal.md +21 -0
- package/docs/api/functions/Input.md +49 -0
- package/docs/api/functions/NavigationGuard.md +31 -0
- package/docs/api/functions/OrganisationServiceProvider.md +28 -0
- package/docs/api/functions/PaceAppLayout.md +169 -0
- package/docs/api/functions/PasswordChangeForm.md +21 -0
- package/docs/api/functions/ProtectedRoute.md +37 -0
- package/docs/api/functions/PublicPageFooter.md +21 -0
- package/docs/api/functions/PublicPageHeader.md +21 -0
- package/docs/api/functions/PublicPageLayout.md +33 -0
- package/docs/api/functions/PublicPageProvider.md +30 -0
- package/docs/api/functions/Textarea.md +49 -0
- package/docs/api/functions/Toaster.md +34 -0
- package/docs/api/functions/UnifiedAuthProvider.md +28 -0
- package/docs/api/functions/applyPalette.md +33 -0
- package/docs/api/functions/archiveFile.md +47 -0
- package/docs/api/functions/average.md +63 -0
- package/docs/api/functions/buildAppUrl.md +46 -0
- package/docs/api/functions/clearInFlightRequests.md +17 -0
- package/docs/api/functions/clearPalette.md +18 -0
- package/docs/api/functions/clearPublicEventCache.md +18 -0
- package/docs/api/functions/clearPublicFileDisplayCache.md +18 -0
- package/docs/api/functions/clearPublicLogoCache.md +18 -0
- package/docs/api/functions/cn.md +21 -0
- package/docs/api/functions/count.md +56 -0
- package/docs/api/functions/createAuditManager.md +45 -0
- package/docs/api/functions/createBaseClient.md +75 -0
- package/docs/api/functions/createLogger.md +95 -0
- package/docs/api/functions/createRBACConfig.md +21 -0
- package/docs/api/functions/createRBACEngine.md +33 -0
- package/docs/api/functions/createRBACExpressMiddleware.md +84 -0
- package/docs/api/functions/createRBACMiddleware.md +88 -0
- package/docs/api/functions/createSecureClient.md +80 -0
- package/docs/api/functions/createSecureDataAccess.md +39 -0
- package/docs/api/functions/deleteFile.md +33 -0
- package/docs/api/functions/disablePerformanceMonitoring.md +17 -0
- package/docs/api/functions/downloadFile.md +33 -0
- package/docs/api/functions/emitAuditEvent.md +27 -0
- package/docs/api/functions/enablePerformanceMonitoring.md +17 -0
- package/docs/api/functions/err.md +23 -0
- package/docs/api/functions/exportToCSV.md +56 -0
- package/docs/api/functions/exportToCSVWithTableRows.md +46 -0
- package/docs/api/functions/extractEventCodeFromPath.md +24 -0
- package/docs/api/functions/extractFileMetadata.md +33 -0
- package/docs/api/functions/formatCompactNumber.md +27 -0
- package/docs/api/functions/formatCurrency.md +31 -0
- package/docs/api/functions/formatDate.md +23 -0
- package/docs/api/functions/formatDateTime.md +24 -0
- package/docs/api/functions/formatFileSize.md +23 -0
- package/docs/api/functions/formatInTimeZone.md +46 -0
- package/docs/api/functions/formatNumber.md +31 -0
- package/docs/api/functions/formatPercent.md +64 -0
- package/docs/api/functions/formatTime.md +24 -0
- package/docs/api/functions/formatTimeInTimeZone.md +40 -0
- package/docs/api/functions/fromSupabaseClient.md +49 -0
- package/docs/api/functions/fromZonedTime.md +41 -0
- package/docs/api/functions/generateCSVContent.md +55 -0
- package/docs/api/functions/generateFilePath.md +29 -0
- package/docs/api/functions/generateFileUrlsBatch.md +33 -0
- package/docs/api/functions/generatePublicRoutePath.md +27 -0
- package/docs/api/functions/generateUniqueFileName.md +24 -0
- package/docs/api/functions/getAccessLevel.md +48 -0
- package/docs/api/functions/getAllAppPorts.md +19 -0
- package/docs/api/functions/getAllStylePaths.md +15 -0
- package/docs/api/functions/getAppConfig.md +17 -0
- package/docs/api/functions/getAppPort.md +34 -0
- package/docs/api/functions/getBucketName.md +27 -0
- package/docs/api/functions/getCurrentAppId.md +17 -0
- package/docs/api/functions/getCurrentAppName.md +17 -0
- package/docs/api/functions/getFileSizeLimit.md +23 -0
- package/docs/api/functions/getGlobalAuditManager.md +19 -0
- package/docs/api/functions/getInFlightRequestCount.md +19 -0
- package/docs/api/functions/getPerformanceMetrics.md +17 -0
- package/docs/api/functions/getPerformanceSummary.md +17 -0
- package/docs/api/functions/getPermissionMap.md +52 -0
- package/docs/api/functions/getPublicEventCacheStats.md +25 -0
- package/docs/api/functions/getPublicFileDisplayCacheStats.md +25 -0
- package/docs/api/functions/getPublicLogoCacheStats.md +25 -0
- package/docs/api/functions/getPublicUrl.md +39 -0
- package/docs/api/functions/getRBACConfig.md +15 -0
- package/docs/api/functions/getRBACLogger.md +15 -0
- package/docs/api/functions/getRoleContext.md +31 -0
- package/docs/api/functions/getSignedUrl.md +34 -0
- package/docs/api/functions/getStylePath.md +21 -0
- package/docs/api/functions/getTimeZoneDifference.md +40 -0
- package/docs/api/functions/getTimezoneAbbreviation.md +40 -0
- package/docs/api/functions/getUserTimeZone.md +26 -0
- package/docs/api/functions/hasAllPermissions.md +41 -0
- package/docs/api/functions/hasAnyPermission.md +41 -0
- package/docs/api/functions/isDebugMode.md +15 -0
- package/docs/api/functions/isDevelopmentMode.md +15 -0
- package/docs/api/functions/isErr.md +29 -0
- package/docs/api/functions/isOk.md +29 -0
- package/docs/api/functions/isPerformanceMonitoringEnabled.md +17 -0
- package/docs/api/functions/isPermitted.md +58 -0
- package/docs/api/functions/isPermittedCached.md +36 -0
- package/docs/api/functions/isRBACInitialized.md +19 -0
- package/docs/api/functions/isSecureClient.md +38 -0
- package/docs/api/functions/isValidPermission.md +27 -0
- package/docs/api/functions/listFiles.md +29 -0
- package/docs/api/functions/max.md +63 -0
- package/docs/api/functions/min.md +63 -0
- package/docs/api/functions/ok.md +29 -0
- package/docs/api/functions/parseAndNormalizeEventColours.md +105 -0
- package/docs/api/functions/recordAuditEvent.md +23 -0
- package/docs/api/functions/recordPermissionCheck.md +31 -0
- package/docs/api/functions/resetPerformanceMetrics.md +17 -0
- package/docs/api/functions/resolveAppContext.md +27 -0
- package/docs/api/functions/roundToNearestMinutes.md +41 -0
- package/docs/api/functions/sanitizeFormData.md +49 -0
- package/docs/api/functions/sanitizeHtml.md +39 -0
- package/docs/api/functions/sanitizeUserInput.md +27 -0
- package/docs/api/functions/setAppConfig.md +23 -0
- package/docs/api/functions/setGlobalAuditManager.md +25 -0
- package/docs/api/functions/setupRBAC.md +31 -0
- package/docs/api/functions/sum.md +63 -0
- package/docs/api/functions/toZonedTime.md +41 -0
- package/docs/api/functions/uploadFile.md +32 -0
- package/docs/api/functions/useAccessLevel.md +71 -0
- package/docs/api/functions/useAccessibleApps.md +55 -0
- package/docs/api/functions/useAppConfig.md +20 -0
- package/docs/api/functions/useAuthService.md +15 -0
- package/docs/api/functions/useCan.md +99 -0
- package/docs/api/functions/useEventService.md +15 -0
- package/docs/api/functions/useEventTheme.md +26 -0
- package/docs/api/functions/useEvents.md +45 -0
- package/docs/api/functions/useFileReference.md +264 -0
- package/docs/api/functions/useFileReferenceById.md +63 -0
- package/docs/api/functions/useFileReferenceForRecord.md +129 -0
- package/docs/api/functions/useFilesByCategory.md +80 -0
- package/docs/api/functions/useFormDialog.md +62 -0
- package/docs/api/functions/useInactivityService.md +15 -0
- package/docs/api/functions/useInactivityTracker.md +21 -0
- package/docs/api/functions/useIsPublicPage.md +19 -0
- package/docs/api/functions/useMultiplePermissions.md +88 -0
- package/docs/api/functions/useOptionalEvents.md +31 -0
- package/docs/api/functions/useOrganisationPermissions.md +27 -0
- package/docs/api/functions/useOrganisationSecurity.md +15 -0
- package/docs/api/functions/useOrganisationService.md +15 -0
- package/docs/api/functions/useOrganisations.md +48 -0
- package/docs/api/functions/usePermissions.md +130 -0
- package/docs/api/functions/usePublicEvent.md +36 -0
- package/docs/api/functions/usePublicEventCode.md +32 -0
- package/docs/api/functions/usePublicEventLogo.md +48 -0
- package/docs/api/functions/usePublicFileDisplay.md +54 -0
- package/docs/api/functions/usePublicPageContext.md +19 -0
- package/docs/api/functions/usePublicRouteParams.md +31 -0
- package/docs/api/functions/useRBAC.md +21 -0
- package/docs/api/functions/useResolvedScope.md +46 -0
- package/docs/api/functions/useResourcePermissions.md +25 -0
- package/docs/api/functions/useRoleManagement.md +121 -0
- package/docs/api/functions/useSecureSupabase.md +51 -0
- package/docs/api/functions/useSessionRestoration.md +15 -0
- package/docs/api/functions/useSessionTracking.md +62 -0
- package/docs/api/functions/useToast.md +83 -0
- package/docs/api/functions/useUnifiedAuth.md +24 -0
- package/docs/api/functions/useZodForm.md +27 -0
- package/docs/api/functions/validateFileSize.md +31 -0
- package/docs/api/functions/warnIfInsecureClient.md +40 -0
- package/docs/api/functions/withAccessLevelGuard.md +67 -0
- package/docs/api/functions/withPermissionGuard.md +73 -0
- package/docs/api/functions/withRoleGuard.md +86 -0
- package/docs/api/globals.md +502 -0
- package/docs/api/interfaces/AccessDeniedProps.md +87 -0
- package/docs/api/interfaces/AccessibleApp.md +41 -0
- package/docs/api/interfaces/AddressFieldProps.md +195 -0
- package/docs/api/interfaces/AddressFieldRef.md +67 -0
- package/docs/api/interfaces/AggregateConfig.md +35 -0
- package/docs/api/interfaces/AppSwitcherProps.md +51 -0
- package/docs/api/interfaces/AuthSessionData.md +27 -0
- package/docs/api/interfaces/AutocompleteOptions.md +61 -0
- package/docs/api/interfaces/AvatarProps.md +97 -0
- package/docs/api/interfaces/BadgeProps.md +30 -0
- package/docs/api/interfaces/BuildAppUrlOptions.md +41 -0
- package/docs/api/interfaces/ButtonProps.md +46 -0
- package/docs/api/interfaces/CalendarProps.md +60 -0
- package/docs/api/interfaces/CardProps.md +56 -0
- package/docs/api/interfaces/ColorPalette.md +13 -0
- package/docs/api/interfaces/ColorShade.md +58 -0
- package/docs/api/interfaces/ContextSelectorProps.md +131 -0
- package/docs/api/interfaces/DataRecord.md +16 -0
- package/docs/api/interfaces/DataTableAction.md +198 -0
- package/docs/api/interfaces/DataTableColumn.md +422 -0
- package/docs/api/interfaces/DataTableProps.md +511 -0
- package/docs/api/interfaces/DataTableToolbarButton.md +75 -0
- package/docs/api/interfaces/DatePickerWithTimezoneProps.md +75 -0
- package/docs/api/interfaces/DialogBodyProps.md +55 -0
- package/docs/api/interfaces/DialogCloseProps.md +25 -0
- package/docs/api/interfaces/DialogContentProps.md +160 -0
- package/docs/api/interfaces/DialogFooterProps.md +25 -0
- package/docs/api/interfaces/DialogHeaderProps.md +25 -0
- package/docs/api/interfaces/DialogPortalProps.md +19 -0
- package/docs/api/interfaces/DialogProps.md +53 -0
- package/docs/api/interfaces/DialogTriggerProps.md +53 -0
- package/docs/api/interfaces/EmptyStateConfig.md +55 -0
- package/docs/api/interfaces/ErrorBoundaryProps.md +131 -0
- package/docs/api/interfaces/ErrorBoundaryProviderProps.md +31 -0
- package/docs/api/interfaces/ErrorBoundaryState.md +61 -0
- package/docs/api/interfaces/EventAppRoleData.md +54 -0
- package/docs/api/interfaces/ExportColumn.md +69 -0
- package/docs/api/interfaces/ExportOptions.md +109 -0
- package/docs/api/interfaces/FileDisplayProps.md +192 -0
- package/docs/api/interfaces/FileMetadata.md +97 -0
- package/docs/api/interfaces/FileReference.md +89 -0
- package/docs/api/interfaces/FileSizeLimits.md +13 -0
- package/docs/api/interfaces/FileUploadOptions.md +107 -0
- package/docs/api/interfaces/FooterProps.md +37 -0
- package/docs/api/interfaces/FormFieldProps.md +171 -0
- package/docs/api/interfaces/FormProps.md +93 -0
- package/docs/api/interfaces/GrantEventAppRoleParams.md +97 -0
- package/docs/api/interfaces/ImportSummary.md +49 -0
- package/docs/api/interfaces/InactivityWarningModalProps.md +87 -0
- package/docs/api/interfaces/InputProps.md +46 -0
- package/docs/api/interfaces/InvalidScopeError.md +37 -0
- package/docs/api/interfaces/LabelProps.md +85 -0
- package/docs/api/interfaces/LoggerConfig.md +51 -0
- package/docs/api/interfaces/LoginFormProps.md +146 -0
- package/docs/api/interfaces/MissingUserContextError.md +37 -0
- package/docs/api/interfaces/NavigationGuardProps.md +109 -0
- package/docs/api/interfaces/NavigationItem.md +91 -0
- package/docs/api/interfaces/NavigationMenuProps.md +169 -0
- package/docs/api/interfaces/Organisation.md +105 -0
- package/docs/api/interfaces/OrganisationContextRequiredError.md +37 -0
- package/docs/api/interfaces/OrganisationMembership.md +105 -0
- package/docs/api/interfaces/OrganisationSecurityError.md +49 -0
- package/docs/api/interfaces/PaceAppLayoutPermissionConfig.md +127 -0
- package/docs/api/interfaces/PaceAppLayoutRouteConfigItem.md +91 -0
- package/docs/api/interfaces/PaceAppLayoutRoutingConfig.md +79 -0
- package/docs/api/interfaces/PaceLoginPageProps.md +41 -0
- package/docs/api/interfaces/PagePermissionGuardProps.md +143 -0
- package/docs/api/interfaces/PaletteData.md +33 -0
- package/docs/api/interfaces/ParsedAddress.md +91 -0
- package/docs/api/interfaces/PermissionDeniedError.md +37 -0
- package/docs/api/interfaces/ProgressProps.md +35 -0
- package/docs/api/interfaces/ProtectedRouteProps.md +67 -0
- package/docs/api/interfaces/PublicPageFooterProps.md +97 -0
- package/docs/api/interfaces/PublicPageHeaderProps.md +99 -0
- package/docs/api/interfaces/PublicPageLayoutProps.md +153 -0
- package/docs/api/interfaces/RBACAccessValidateParams.md +41 -0
- package/docs/api/interfaces/RBACAccessValidateResult.md +33 -0
- package/docs/api/interfaces/RBACAuditLogParams.md +65 -0
- package/docs/api/interfaces/RBACAuditLogResult.md +41 -0
- package/docs/api/interfaces/RBACContext.md +41 -0
- package/docs/api/interfaces/RBACError.md +37 -0
- package/docs/api/interfaces/RBACLogger.md +97 -0
- package/docs/api/interfaces/RBACNotInitializedError.md +37 -0
- package/docs/api/interfaces/RBACPageAccessCheckParams.md +57 -0
- package/docs/api/interfaces/RBACPerformanceMetrics.md +109 -0
- package/docs/api/interfaces/RBACPermissionCheckParams.md +57 -0
- package/docs/api/interfaces/RBACPermissionCheckResult.md +41 -0
- package/docs/api/interfaces/RBACPermissionsGetParams.md +49 -0
- package/docs/api/interfaces/RBACPermissionsGetResult.md +49 -0
- package/docs/api/interfaces/RBACResult.md +47 -0
- package/docs/api/interfaces/RBACRoleGrantParams.md +49 -0
- package/docs/api/interfaces/RBACRoleGrantResult.md +41 -0
- package/docs/api/interfaces/RBACRoleRevokeParams.md +49 -0
- package/docs/api/interfaces/RBACRoleRevokeResult.md +41 -0
- package/docs/api/interfaces/RBACRoleValidateParams.md +41 -0
- package/docs/api/interfaces/RBACRoleValidateResult.md +49 -0
- package/docs/api/interfaces/RBACRolesListParams.md +41 -0
- package/docs/api/interfaces/RBACRolesListResult.md +57 -0
- package/docs/api/interfaces/RBACSessionTrackParams.md +57 -0
- package/docs/api/interfaces/RBACSessionTrackResult.md +41 -0
- package/docs/api/interfaces/ResourcePermissions.md +119 -0
- package/docs/api/interfaces/RevokeEventAppRoleParams.md +81 -0
- package/docs/api/interfaces/RoleManagementResult.md +41 -0
- package/docs/api/interfaces/SessionRestorationLoaderProps.md +29 -0
- package/docs/api/interfaces/StorageConfig.md +33 -0
- package/docs/api/interfaces/StorageFileInfo.md +57 -0
- package/docs/api/interfaces/StorageFileMetadata.md +113 -0
- package/docs/api/interfaces/StorageListOptions.md +79 -0
- package/docs/api/interfaces/StorageListResult.md +33 -0
- package/docs/api/interfaces/StorageUploadOptions.md +81 -0
- package/docs/api/interfaces/StorageUploadResult.md +49 -0
- package/docs/api/interfaces/StorageUploadSuccess.md +35 -0
- package/docs/api/interfaces/StorageUrlOptions.md +49 -0
- package/docs/api/interfaces/StyleImport.md +17 -0
- package/docs/api/interfaces/SwitchProps.md +30 -0
- package/docs/api/interfaces/TabsContentProps.md +13 -0
- package/docs/api/interfaces/TabsListProps.md +13 -0
- package/docs/api/interfaces/TabsProps.md +13 -0
- package/docs/api/interfaces/TabsTriggerProps.md +41 -0
- package/docs/api/interfaces/TextareaProps.md +43 -0
- package/docs/api/interfaces/ToastActionElement.md +16 -0
- package/docs/api/interfaces/ToastProps.md +13 -0
- package/docs/api/interfaces/UnifiedAuthProviderProps.md +129 -0
- package/docs/api/interfaces/UseAccessibleAppsReturn.md +55 -0
- package/docs/api/interfaces/UseFormDialogOptions.md +49 -0
- package/docs/api/interfaces/UseFormDialogReturn.md +95 -0
- package/docs/api/interfaces/UseInactivityTrackerOptions.md +103 -0
- package/docs/api/interfaces/UseInactivityTrackerReturn.md +91 -0
- package/docs/api/interfaces/UsePublicEventLogoOptions.md +69 -0
- package/docs/api/interfaces/UsePublicEventLogoReturn.md +66 -0
- package/docs/api/interfaces/UsePublicEventOptions.md +29 -0
- package/docs/api/interfaces/UsePublicEventReturn.md +56 -0
- package/docs/api/interfaces/UsePublicFileDisplayOptions.md +39 -0
- package/docs/api/interfaces/UsePublicFileDisplayReturn.md +96 -0
- package/docs/api/interfaces/UsePublicRouteParamsReturn.md +76 -0
- package/docs/api/interfaces/UseResolvedScopeOptions.md +49 -0
- package/docs/api/interfaces/UseResolvedScopeReturn.md +39 -0
- package/docs/api/interfaces/UseResourcePermissionsOptions.md +29 -0
- package/docs/api/interfaces/UserEventAccess.md +92 -0
- package/docs/api/interfaces/UserMenuProps.md +69 -0
- package/docs/api/interfaces/UserProfile.md +49 -0
- package/docs/api/type-aliases/AccessLevel.md +11 -0
- package/docs/api/type-aliases/AccessLevelContext.md +14 -0
- package/docs/api/type-aliases/AllPermissions.md +11 -0
- package/docs/api/type-aliases/ApiError.md +37 -0
- package/docs/api/type-aliases/ApiResult.md +19 -0
- package/docs/api/type-aliases/AuditEventType.md +11 -0
- package/docs/api/type-aliases/BadgeVariant.md +18 -0
- package/docs/api/type-aliases/DataTableFeatureConfig.md +14 -0
- package/docs/api/type-aliases/DialogSize.md +13 -0
- package/docs/api/type-aliases/EventAppRole.md +11 -0
- package/docs/api/type-aliases/FileUploadProps.md +15 -0
- package/docs/api/type-aliases/GetRowId.md +33 -0
- package/docs/api/type-aliases/GlobalErrorHandler.md +35 -0
- package/docs/api/type-aliases/GlobalRole.md +11 -0
- package/docs/api/type-aliases/ImportHandlerResult.md +13 -0
- package/docs/api/type-aliases/NavigationMode.md +13 -0
- package/docs/api/type-aliases/Operation.md +11 -0
- package/docs/api/type-aliases/OrganisationContextType.md +13 -0
- package/docs/api/type-aliases/OrganisationRole.md +11 -0
- package/docs/api/type-aliases/PaceAppLayoutProps.md +14 -0
- package/docs/api/type-aliases/Permission.md +11 -0
- package/docs/api/type-aliases/PermissionCheck.md +46 -0
- package/docs/api/type-aliases/PermissionMap.md +11 -0
- package/docs/api/type-aliases/PermissionSource.md +13 -0
- package/docs/api/type-aliases/RBACConfig.md +13 -0
- package/docs/api/type-aliases/RBACFunctionResponse.md +57 -0
- package/docs/api/type-aliases/Scope.md +41 -0
- package/docs/api/type-aliases/SessionType.md +11 -0
- package/docs/api/type-aliases/UUID.md +11 -0
- package/docs/api/type-aliases/UnifiedAuthContextType.md +13 -0
- package/docs/api/type-aliases/UseFileReferenceForRecordReturn.md +161 -0
- package/docs/api/type-aliases/UseFileReferenceOptions.md +35 -0
- package/docs/api/type-aliases/UseFileReferenceReturn.md +13 -0
- package/docs/api/variables/ALL_PERMISSIONS.md +281 -0
- package/docs/api/variables/APP_PATH_MAPPING.md +14 -0
- package/docs/api/variables/AddressField.md +41 -0
- package/docs/api/variables/Alert.md +11 -0
- package/docs/api/variables/AlertDescription.md +11 -0
- package/docs/api/variables/AlertTitle.md +11 -0
- package/docs/api/variables/Avatar.md +13 -0
- package/docs/api/variables/Button.md +31 -0
- package/docs/api/variables/CACHE_PATTERNS.md +89 -0
- package/docs/api/variables/Calendar.md +74 -0
- package/docs/api/variables/Card.md +11 -0
- package/docs/api/variables/CardActions.md +11 -0
- package/docs/api/variables/CardContent.md +11 -0
- package/docs/api/variables/CardDescription.md +11 -0
- package/docs/api/variables/CardFooter.md +11 -0
- package/docs/api/variables/CardHeader.md +11 -0
- package/docs/api/variables/CardTitle.md +11 -0
- package/docs/api/variables/Checkbox.md +11 -0
- package/docs/api/variables/DEFAULT_APP_PORT_MAP.md +14 -0
- package/docs/api/variables/DEFAULT_FILE_SIZE_LIMIT.md +13 -0
- package/docs/api/variables/Dialog.md +14 -0
- package/docs/api/variables/DialogClose.md +14 -0
- package/docs/api/variables/DialogContent.md +28 -0
- package/docs/api/variables/DialogDescription.md +14 -0
- package/docs/api/variables/DialogPortal.md +14 -0
- package/docs/api/variables/DialogTitle.md +14 -0
- package/docs/api/variables/DialogTrigger.md +14 -0
- package/docs/api/variables/EVENT_APP_PERMISSIONS.md +109 -0
- package/docs/api/variables/ErrorBoundary.md +15 -0
- package/docs/api/variables/FILE_SIZE_LIMITS.md +13 -0
- package/docs/api/variables/Footer.md +11 -0
- package/docs/api/variables/GLOBAL_PERMISSIONS.md +29 -0
- package/docs/api/variables/Label.md +34 -0
- package/docs/api/variables/LoadingSpinner.md +28 -0
- package/docs/api/variables/LoginForm.md +34 -0
- package/docs/api/variables/NavigationMenu.md +203 -0
- package/docs/api/variables/ORGANISATION_PERMISSIONS.md +89 -0
- package/docs/api/variables/PAGE_PERMISSIONS.md +93 -0
- package/docs/api/variables/PaceLoginPage.md +40 -0
- package/docs/api/variables/PagePermissionGuard.md +11 -0
- package/docs/api/variables/Progress.md +32 -0
- package/docs/api/variables/SECURE_CLIENT_SYMBOL.md +14 -0
- package/docs/api/variables/STORAGE_CONFIG.md +13 -0
- package/docs/api/variables/Select.md +26 -0
- package/docs/api/variables/SelectContent.md +26 -0
- package/docs/api/variables/SelectGroup.md +26 -0
- package/docs/api/variables/SelectItem.md +26 -0
- package/docs/api/variables/SelectLabel.md +26 -0
- package/docs/api/variables/SelectSeparator.md +26 -0
- package/docs/api/variables/SelectTrigger.md +26 -0
- package/docs/api/variables/SelectValue.md +26 -0
- package/docs/api/variables/SessionRestorationLoader.md +11 -0
- package/docs/api/variables/Switch.md +23 -0
- package/docs/api/variables/Table.md +35 -0
- package/docs/api/variables/TableBody.md +11 -0
- package/docs/api/variables/TableCaption.md +11 -0
- package/docs/api/variables/TableCell.md +11 -0
- package/docs/api/variables/TableFooter.md +11 -0
- package/docs/api/variables/TableHead.md +11 -0
- package/docs/api/variables/TableHeader.md +11 -0
- package/docs/api/variables/TableRow.md +11 -0
- package/docs/api/variables/Tabs.md +25 -0
- package/docs/api/variables/TabsContent.md +24 -0
- package/docs/api/variables/TabsList.md +25 -0
- package/docs/api/variables/TabsTrigger.md +34 -0
- package/docs/api/variables/Toast.md +36 -0
- package/docs/api/variables/ToastAction.md +32 -0
- package/docs/api/variables/ToastClose.md +32 -0
- package/docs/api/variables/ToastDescription.md +32 -0
- package/docs/api/variables/ToastProvider.md +11 -0
- package/docs/api/variables/ToastTitle.md +32 -0
- package/docs/api/variables/ToastViewport.md +26 -0
- package/docs/api/variables/Tooltip.md +34 -0
- package/docs/api/variables/TooltipContent.md +34 -0
- package/docs/api/variables/TooltipProvider.md +11 -0
- package/docs/api/variables/TooltipRoot.md +11 -0
- package/docs/api/variables/TooltipTrigger.md +11 -0
- package/docs/api/variables/UserMenu.md +11 -0
- package/docs/api/variables/emailSchema.md +13 -0
- package/docs/api/variables/logger.md +203 -0
- package/docs/api/variables/nameSchema.md +13 -0
- package/docs/api/variables/passwordSchema.md +13 -0
- package/docs/api/variables/phoneSchema.md +13 -0
- package/docs/api/variables/rbacCache.md +16 -0
- package/docs/api/variables/styleConfig.md +25 -0
- package/docs/api/variables/urlSchema.md +13 -0
- package/docs/api-reference/hooks.md +2 -0
- package/docs/api-reference/rpc-functions.md +12 -3
- package/docs/core-concepts/rbac-system.md +8 -0
- package/docs/getting-started/cursor-rules.md +17 -20
- package/docs/getting-started/dependencies.md +1 -1
- package/docs/getting-started/setup.md +235 -0
- package/docs/implementation-guides/authentication.md +27 -0
- package/docs/implementation-guides/data-tables.md +184 -3
- package/docs/migration/ApiResult-migration.md +25 -0
- package/docs/rbac/api-reference.md +33 -31
- package/docs/rbac/getting-started.md +7 -0
- package/docs/rbac/troubleshooting.md +5 -1
- package/docs/standards/0-standards-overview.md +50 -15
- package/docs/standards/1-pace-core-compliance-standards.md +62 -57
- package/docs/standards/2-project-structure-standards.md +33 -16
- package/docs/standards/3-architecture-standards.md +41 -1
- package/docs/standards/4-code-quality-standards.md +26 -6
- package/docs/standards/5-styling-standards.md +35 -1
- package/docs/standards/6-security-rbac-standards.md +66 -0
- package/docs/standards/7-api-tech-stack-standards.md +25 -14
- package/docs/standards/8-testing-documentation-standards.md +31 -0
- package/docs/standards/9-operations-standards.md +19 -0
- package/docs/standards/README.md +20 -201
- package/docs/testing/test-setup-for-consumers.md +2 -0
- package/docs/troubleshooting/common-issues.md +17 -1
- package/docs/troubleshooting/organisation-context-setup.md +8 -0
- package/docs/troubleshooting/print-event-name-css-variable-analysis.md +217 -0
- package/eslint-config-pace-core.cjs +20 -0
- package/package.json +16 -22
- package/scripts/build-docs.js +180 -0
- package/scripts/setup.cjs +536 -0
- package/scripts/validate.cjs +480 -0
- package/src/__tests__/helpers/component-test-utils.test.tsx +260 -0
- package/src/__tests__/helpers/optimized-test-setup.test.ts +224 -0
- package/src/__tests__/helpers/supabaseMock.test.ts +273 -0
- package/src/__tests__/helpers/test-providers.test.tsx +99 -0
- package/src/__tests__/helpers/test-providers.tsx +37 -39
- package/src/__tests__/helpers/test-utils.test.tsx +447 -0
- package/src/__tests__/helpers/timer-utils.test.ts +371 -0
- package/src/assets/app-icons/index.test.ts +304 -0
- package/src/components/AddressField/AddressField.test.tsx +1 -1
- package/src/components/AddressField/AddressField.tsx +238 -212
- package/src/components/Button/Button.tsx +1 -1
- package/src/components/Card/Card.test.tsx +172 -17
- package/src/components/Card/Card.tsx +19 -10
- package/src/components/ContextSelector/ContextSelector.internals.tsx +204 -0
- package/src/components/ContextSelector/ContextSelector.test.tsx +360 -0
- package/src/components/ContextSelector/ContextSelector.tsx +66 -280
- package/src/components/ContextSelector/ContextSelector.types.ts +35 -0
- package/src/components/ContextSelector/useContextSelectorState.tsx +195 -0
- package/src/components/DataTable/AUDIT_REPORT.md +59 -44
- package/src/components/DataTable/DataTable.comprehensive.test.tsx +759 -0
- package/src/components/DataTable/DataTable.default-state.test.tsx +524 -0
- package/src/components/DataTable/DataTable.export.test.tsx +705 -0
- package/src/components/DataTable/DataTable.grouping-aggregation.test.tsx +658 -0
- package/src/components/DataTable/DataTable.hooks.test.tsx +192 -0
- package/src/components/DataTable/DataTable.select-label-display.test.tsx +485 -0
- package/src/components/DataTable/DataTable.test.tsx +787 -416
- package/src/components/DataTable/DataTable.tsx +12 -12
- package/src/components/DataTable/DataTableCore.integration.test.tsx +458 -0
- package/src/components/DataTable/DataTableCore.test-setup.ts +221 -0
- package/src/components/DataTable/DataTableCore.test.tsx +970 -0
- package/src/components/DataTable/README.md +155 -0
- package/src/components/DataTable/TESTING.md +101 -0
- package/src/components/DataTable/a11y.basic.test.tsx +788 -0
- package/src/components/DataTable/components/DataTableCore.tsx +104 -864
- package/src/components/DataTable/components/GroupingDropdown.test.tsx +621 -0
- package/src/components/DataTable/components/GroupingDropdown.tsx +2 -2
- package/src/components/DataTable/components/ImportModal.tsx +61 -559
- package/src/components/DataTable/components/ImportModalFileSection.tsx +148 -0
- package/src/components/DataTable/context/DataTableContext.test.tsx +328 -0
- package/src/components/DataTable/context/DataTableContext.tsx +7 -6
- package/src/components/DataTable/core/ColumnFactory.test.ts +403 -0
- package/src/components/DataTable/hooks/useColumnOrderPersistence.test.ts +516 -0
- package/src/components/DataTable/hooks/useColumnVisibilityPersistence.test.ts +256 -0
- package/src/components/DataTable/hooks/useDataTableConfiguration.test.ts +297 -0
- package/src/components/DataTable/hooks/useDataTableConfiguration.ts +14 -2
- package/src/components/DataTable/hooks/useDataTableDataPipeline.test.ts +270 -0
- package/src/components/DataTable/hooks/useDataTableDeletionBatching.test.ts +127 -0
- package/src/components/DataTable/hooks/useDataTableDeletionBatching.ts +106 -0
- package/src/components/DataTable/hooks/useDataTableEffectiveActions.test.ts +461 -0
- package/src/components/DataTable/hooks/useDataTableEffectiveActions.ts +248 -0
- package/src/components/DataTable/hooks/useDataTableLayoutHandlers.test.ts +296 -0
- package/src/components/DataTable/hooks/useDataTableLayoutHandlers.ts +175 -0
- package/src/components/DataTable/hooks/useDataTablePaginationSync.test.ts +203 -0
- package/src/components/DataTable/hooks/useDataTablePaginationSync.ts +109 -0
- package/src/components/DataTable/hooks/useDataTablePermissions.test.ts +280 -0
- package/src/components/DataTable/hooks/useDataTablePermissions.ts +79 -247
- package/src/components/DataTable/hooks/useDataTablePipeline.test.tsx +219 -0
- package/src/components/DataTable/hooks/useDataTablePipeline.tsx +239 -0
- package/src/components/DataTable/hooks/useDataTableRenderGuard.test.tsx +316 -0
- package/src/components/DataTable/hooks/useDataTableRenderGuard.tsx +195 -0
- package/src/components/DataTable/hooks/useDataTableScope.test.ts +102 -0
- package/src/components/DataTable/hooks/useDataTableScope.ts +125 -0
- package/src/components/DataTable/hooks/useDataTableState.test.ts +733 -0
- package/src/components/DataTable/hooks/useDataTableState.ts +145 -94
- package/src/components/DataTable/hooks/useDataTableStateAndPersistence.test.ts +277 -0
- package/src/components/DataTable/hooks/useDataTableStateAndPersistence.ts +222 -0
- package/src/components/DataTable/hooks/useDataTableSuperAdmin.test.ts +93 -0
- package/src/components/DataTable/hooks/useDataTableSuperAdmin.ts +86 -0
- package/src/components/DataTable/hooks/useDataTableTableInstance.test.ts +185 -0
- package/src/components/DataTable/hooks/useDataTableTableInstance.ts +178 -0
- package/src/components/DataTable/hooks/useEffectiveColumnOrder.test.ts +183 -0
- package/src/components/DataTable/hooks/useHierarchicalState.test.ts +294 -0
- package/src/components/DataTable/hooks/useImportModalFocus.test.ts +184 -0
- package/src/components/DataTable/hooks/useImportModalFocus.ts +53 -0
- package/src/components/DataTable/hooks/useImportModalState.test.ts +390 -0
- package/src/components/DataTable/hooks/useImportModalState.ts +345 -0
- package/src/components/DataTable/hooks/useKeyboardNavigation.test.ts +787 -0
- package/src/components/DataTable/hooks/useKeyboardNavigation.ts +309 -269
- package/src/components/DataTable/hooks/usePermissionTracking.test.ts +381 -0
- package/src/components/DataTable/hooks/usePermissionTracking.ts +122 -0
- package/src/components/DataTable/hooks/useServerSideDataEffect.test.ts +258 -0
- package/src/components/DataTable/hooks/useServerSideDataEffect.ts +14 -3
- package/src/components/DataTable/hooks/useTableColumns.test.ts +499 -0
- package/src/components/DataTable/hooks/useTableHandlers.test.ts +461 -0
- package/src/components/DataTable/hooks/useTableHandlers.ts +5 -2
- package/src/components/DataTable/index.ts +18 -17
- package/src/components/DataTable/keyboard.test.tsx +734 -0
- package/src/components/DataTable/mocks/MockRBACProvider.tsx +66 -0
- package/src/components/DataTable/pagination.modes.test.tsx +728 -0
- package/src/components/DataTable/ssr.strict-mode.test.tsx +319 -0
- package/src/components/DataTable/styles.test.ts +379 -0
- package/src/components/DataTable/styles.ts +0 -1
- package/src/components/DataTable/test-utils/MockDataTableComponents.tsx +55 -0
- package/src/components/DataTable/test-utils/dataFactories.ts +103 -0
- package/src/components/DataTable/test-utils/featureConfig.ts +10 -0
- package/src/components/DataTable/test-utils/sharedTestUtils.ts +419 -0
- package/src/components/DataTable/test-utils.ts +94 -0
- package/src/components/DataTable/types/actions.ts +71 -0
- package/src/components/DataTable/types/base.ts +39 -0
- package/src/components/DataTable/types/columns.ts +125 -0
- package/src/components/DataTable/types/export.ts +32 -0
- package/src/components/DataTable/types/features.ts +81 -0
- package/src/components/DataTable/types/hierarchical.ts +44 -0
- package/src/components/DataTable/types/index.ts +43 -0
- package/src/components/DataTable/types/pagination.ts +85 -0
- package/src/components/DataTable/types/performance.ts +47 -0
- package/src/components/DataTable/types/props.ts +62 -0
- package/src/components/DataTable/types/rbac.ts +45 -0
- package/src/components/DataTable/ui/layout/DataTableCore.test.tsx +1194 -0
- package/src/components/DataTable/ui/layout/DataTableCore.tsx +345 -0
- package/src/components/DataTable/ui/layout/DataTableErrorBoundary.test.tsx +438 -0
- package/src/components/DataTable/ui/layout/DataTableErrorBoundary.tsx +225 -0
- package/src/components/DataTable/ui/layout/DataTableLayout.test.tsx +1352 -0
- package/src/components/DataTable/ui/layout/DataTableLayout.tsx +661 -0
- package/src/components/DataTable/ui/modals/BulkDeleteConfirmDialog.test.tsx +91 -0
- package/src/components/DataTable/ui/modals/BulkDeleteConfirmDialog.tsx +43 -0
- package/src/components/DataTable/ui/modals/DataTableModals.test.tsx +749 -0
- package/src/components/DataTable/ui/modals/DataTableModals.tsx +341 -0
- package/src/components/DataTable/ui/modals/ImportModal.test.tsx +1834 -0
- package/src/components/DataTable/ui/modals/ImportModal.tsx +197 -0
- package/src/components/DataTable/ui/modals/ImportModalFailedRowsSection.tsx +60 -0
- package/src/components/DataTable/ui/modals/ImportModalFileSection.tsx +148 -0
- package/src/components/DataTable/ui/modals/ImportModalPreviewSection.tsx +60 -0
- package/src/components/DataTable/ui/modals/ImportModalSummarySection.tsx +59 -0
- package/src/components/DataTable/ui/modals/importModalPersistence.ts +73 -0
- package/src/components/DataTable/ui/shared/AccessDeniedPage.test.tsx +245 -0
- package/src/components/DataTable/ui/shared/AccessDeniedPage.tsx +159 -0
- package/src/components/DataTable/ui/shared/ActionButtons.test.tsx +921 -0
- package/src/components/DataTable/ui/shared/ActionButtons.tsx +195 -0
- package/src/components/DataTable/ui/shared/ColumnFilter.test.tsx +497 -0
- package/src/components/DataTable/ui/shared/ColumnFilter.tsx +113 -0
- package/src/components/DataTable/ui/shared/PaginationControls.test.tsx +451 -0
- package/src/components/DataTable/ui/shared/PaginationControls.tsx +291 -0
- package/src/components/DataTable/ui/shared/SortIndicator.test.tsx +135 -0
- package/src/components/DataTable/ui/shared/SortIndicator.tsx +50 -0
- package/src/components/DataTable/ui/table/EditFields.test.tsx +526 -0
- package/src/components/DataTable/ui/table/EditFields.tsx +355 -0
- package/src/components/DataTable/ui/table/EditableRow.test.tsx +1003 -0
- package/src/components/DataTable/ui/table/EditableRow.tsx +444 -0
- package/src/components/DataTable/ui/table/EmptyState.test.tsx +360 -0
- package/src/components/DataTable/ui/table/EmptyState.tsx +74 -0
- package/src/components/DataTable/ui/table/FilterRow.test.tsx +416 -0
- package/src/components/DataTable/ui/table/FilterRow.tsx +148 -0
- package/src/components/DataTable/ui/table/LoadingState.test.tsx +77 -0
- package/src/components/DataTable/ui/table/LoadingState.tsx +17 -0
- package/src/components/DataTable/ui/table/RowComponent.test.tsx +1024 -0
- package/src/components/DataTable/ui/table/RowComponent.tsx +429 -0
- package/src/components/DataTable/ui/table/UnifiedTableBody.test.tsx +1273 -0
- package/src/components/DataTable/ui/table/UnifiedTableBody.tsx +440 -0
- package/src/components/DataTable/ui/table/cellValueUtils.test.ts +453 -0
- package/src/components/DataTable/ui/table/cellValueUtils.ts +40 -0
- package/src/components/DataTable/ui/toolbar/BulkOperationsDropdown.test.tsx +551 -0
- package/src/components/DataTable/ui/toolbar/BulkOperationsDropdown.tsx +160 -0
- package/src/components/DataTable/ui/toolbar/ColumnVisibilityDropdown.test.tsx +751 -0
- package/src/components/DataTable/ui/toolbar/ColumnVisibilityDropdown.tsx +114 -0
- package/src/components/DataTable/ui/toolbar/DataTableToolbar.test.tsx +629 -0
- package/src/components/DataTable/ui/toolbar/DataTableToolbar.tsx +271 -0
- package/src/components/DataTable/ui/toolbar/GroupingDropdown.test.tsx +621 -0
- package/src/components/DataTable/ui/toolbar/GroupingDropdown.tsx +107 -0
- package/src/components/DataTable/utils/a11yUtils.test.ts +548 -0
- package/src/components/DataTable/utils/aggregationUtils.test.ts +288 -0
- package/src/components/DataTable/utils/columnUtils.test.ts +94 -0
- package/src/components/DataTable/utils/csvParse.test.ts +74 -0
- package/src/components/DataTable/utils/csvParse.ts +65 -0
- package/src/components/DataTable/utils/errorHandling.test.ts +209 -0
- package/src/components/DataTable/utils/exportUtils.test.ts +954 -0
- package/src/components/DataTable/utils/flexibleImport.test.ts +573 -0
- package/src/components/DataTable/utils/flexibleImport.ts +3 -186
- package/src/components/DataTable/utils/hierarchicalSorting.test.ts +235 -0
- package/src/components/DataTable/utils/hierarchicalUtils.test.ts +586 -0
- package/src/components/DataTable/utils/importDateParser.test.ts +162 -0
- package/src/components/DataTable/utils/importDateParser.ts +114 -0
- package/src/components/DataTable/utils/importValueParser.test.ts +138 -0
- package/src/components/DataTable/utils/importValueParser.ts +91 -0
- package/src/components/DataTable/utils/paginationUtils.test.ts +593 -0
- package/src/components/DataTable/utils/paginationUtils.ts +6 -3
- package/src/components/DataTable/utils/performanceUtils.test.ts +470 -0
- package/src/components/DataTable/utils/rowUtils.test.ts +235 -0
- package/src/components/DataTable/utils/selectFieldUtils.test.ts +271 -0
- package/src/components/DataTable/utils/selectFieldUtils.ts +97 -60
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +1 -1
- package/src/components/DateTimeField/DateTimeField.test.tsx +1 -1
- package/src/components/Dialog/Dialog.test-utils.ts +49 -0
- package/src/components/Dialog/Dialog.test.tsx +896 -89
- package/src/components/Dialog/Dialog.tsx +174 -882
- package/src/components/Dialog/dialogLock.test.ts +238 -0
- package/src/components/Dialog/dialogLock.ts +98 -0
- package/src/components/Dialog/index.ts +2 -0
- package/src/components/Dialog/useDialogDimensions.test.ts +163 -0
- package/src/components/Dialog/useDialogDimensions.ts +140 -0
- package/src/components/Dialog/useDialogLifecycle.test.ts +361 -0
- package/src/components/Dialog/useDialogLifecycle.ts +135 -0
- package/src/components/Dialog/useDialogPersistence.test.ts +381 -0
- package/src/components/Dialog/useDialogPersistence.ts +357 -0
- package/src/components/FileDisplay/FileDisplay.test.tsx +40 -40
- package/src/components/FileDisplay/FileDisplay.tsx +24 -656
- package/src/components/FileDisplay/FileDisplayContent.test.tsx +395 -0
- package/src/components/FileDisplay/FileDisplayContent.tsx +242 -0
- package/src/components/FileDisplay/FileDisplayDeleteConfirmDialog.test.tsx +74 -0
- package/src/components/FileDisplay/FileDisplayDeleteConfirmDialog.tsx +38 -0
- package/src/components/FileDisplay/FileDisplayEmptyView.test.tsx +33 -0
- package/src/components/FileDisplay/FileDisplayEmptyView.tsx +33 -0
- package/src/components/FileDisplay/FileDisplayErrorView.test.tsx +71 -0
- package/src/components/FileDisplay/FileDisplayErrorView.tsx +50 -0
- package/src/components/FileDisplay/FileDisplayLoadingFallbackView.test.tsx +22 -0
- package/src/components/FileDisplay/FileDisplayLoadingFallbackView.tsx +22 -0
- package/src/components/FileDisplay/FileDisplayLoadingView.test.tsx +21 -0
- package/src/components/FileDisplay/FileDisplayLoadingView.tsx +23 -0
- package/src/components/FileDisplay/FileDisplayMultipleFilesView.test.tsx +101 -0
- package/src/components/FileDisplay/FileDisplayMultipleFilesView.tsx +109 -0
- package/src/components/FileDisplay/FileDisplaySingleDocumentLinkView.test.tsx +58 -0
- package/src/components/FileDisplay/FileDisplaySingleDocumentLinkView.tsx +48 -0
- package/src/components/FileDisplay/FileDisplaySingleFileWithActionsView.test.tsx +111 -0
- package/src/components/FileDisplay/FileDisplaySingleFileWithActionsView.tsx +270 -0
- package/src/components/FileDisplay/FileDisplaySingleImageView.test.tsx +78 -0
- package/src/components/FileDisplay/FileDisplaySingleImageView.tsx +67 -0
- package/src/components/FileDisplay/fallbackUtils.test.ts +50 -0
- package/src/components/FileDisplay/fallbackUtils.ts +44 -0
- package/src/components/FileDisplay/fetchFileDisplayData.ts +24 -0
- package/src/components/FileDisplay/fetchFileDisplayData.unit.test.ts +183 -0
- package/src/components/FileDisplay/fileDisplayUtils.test.ts +58 -0
- package/src/components/FileDisplay/fileDisplayUtils.ts +24 -0
- package/src/components/FileDisplay/useFileDisplay.test.ts +538 -0
- package/src/components/FileDisplay/useFileDisplay.ts +515 -0
- package/src/components/FileDisplay/useFileDisplay.unit.test.ts +1442 -0
- package/src/components/FileDisplay/useFileDisplayData.ts +126 -0
- package/src/components/FileDisplay/usePublicFileDisplay.test.ts +729 -0
- package/src/components/FileDisplay/usePublicFileDisplay.ts +579 -0
- package/src/components/FileUpload/FileUpload.test.tsx +16 -10
- package/src/components/FileUpload/FileUpload.tsx +107 -525
- package/src/components/FileUpload/FileUploadDropZone.tsx +112 -0
- package/src/components/FileUpload/FileUploadProgressItem.tsx +86 -0
- package/src/components/FileUpload/FileUploadProgressList.tsx +40 -0
- package/src/components/FileUpload/useFileUploadManager.test.ts +308 -0
- package/src/components/FileUpload/useFileUploadManager.ts +454 -0
- package/src/components/FileUpload/useResolvedAppId.test.ts +102 -0
- package/src/components/FileUpload/useResolvedAppId.ts +77 -0
- package/src/components/Footer/Footer.test.tsx +6 -292
- package/src/components/Footer/Footer.tsx +8 -125
- package/src/components/Form/Form.test.tsx +44 -27
- package/src/components/Form/Form.tsx +64 -287
- package/src/components/Form/useFormPersistence.ts +257 -0
- package/src/components/Header/Header.test.tsx +17 -18
- package/src/components/Header/Header.tsx +10 -1
- package/src/components/Input/Input.tsx +1 -1
- package/src/components/Label/Label.test.tsx +1 -1
- package/src/components/LoadingSpinner/LoadingSpinner.test.tsx +1 -1
- package/src/components/NavigationMenu/HierarchicalNavItem.tsx +104 -0
- package/src/components/NavigationMenu/NavigationMenu.test.tsx +1029 -26
- package/src/components/NavigationMenu/NavigationMenu.tsx +61 -361
- package/src/components/NavigationMenu/index.ts +6 -1
- package/src/components/NavigationMenu/navigationPermissionHelper.ts +188 -0
- package/src/components/NavigationMenu/useNavigationFiltering.test.ts +1949 -0
- package/src/components/NavigationMenu/useNavigationFiltering.ts +197 -296
- package/src/components/NavigationMenu/useNavigationScope.ts +125 -0
- package/src/components/PaceAppLayout/PaceAppLayout.edge-cases.test.tsx +109 -70
- package/src/components/PaceAppLayout/PaceAppLayout.integration.test.tsx +3 -3
- package/src/components/PaceAppLayout/PaceAppLayout.security.test.tsx +16 -19
- package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +529 -5
- package/src/components/PaceAppLayout/PaceAppLayout.tsx +280 -756
- package/src/components/PaceAppLayout/useFilteredNavItems.ts +319 -0
- package/src/components/PaceAppLayout/usePaceAppLayoutConfig.ts +163 -0
- package/src/components/PaceAppLayout/usePaceAppLayoutGate.tsx +150 -0
- package/src/components/PaceAppLayout/usePaceAppLayoutPermissions.ts +162 -0
- package/src/components/PaceAppLayout/usePaceAppLayoutScope.ts +81 -0
- package/src/components/PaceAppLayout/useRoleBasedRouteAccess.ts +157 -0
- package/src/components/PaceAppLayout/useSuperAdminFallback.ts +58 -0
- package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +31 -25
- package/src/components/PaceLoginPage/PaceLoginPage.tsx +31 -122
- package/src/components/PaceLoginPage/useLoginAppAccess.ts +153 -0
- package/src/components/Progress/Progress.tsx +1 -2
- package/src/components/ProtectedRoute/ProtectedRoute.tsx +29 -235
- package/src/components/ProtectedRoute/useProtectedRouteState.ts +128 -0
- package/src/components/ProtectedRoute/useVisibilityRedirectGrace.ts +89 -0
- package/src/components/PublicLayout/PublicLayout.test.tsx +217 -36
- package/src/components/PublicLayout/PublicPageLayout.tsx +132 -73
- package/src/components/PublicLayout/PublicPageProvider.tsx +5 -1
- package/src/components/Select/Select.test.tsx +1 -1
- package/src/components/Select/Select.tsx +28 -18
- package/src/components/Select/context.test.tsx +56 -0
- package/src/components/Select/text.test.tsx +104 -0
- package/src/components/Select/text.ts +26 -0
- package/src/components/Select/useSelectEvents.test.ts +279 -0
- package/src/components/Select/useSelectEvents.ts +87 -0
- package/src/components/Select/useSelectSearch.test.tsx +295 -0
- package/src/components/Select/useSelectSearch.ts +91 -0
- package/src/components/Select/useSelectState.test.ts +268 -0
- package/src/components/Select/useSelectState.ts +104 -0
- package/src/components/Table/Table.test.tsx +348 -0
- package/src/components/Tabs/Tabs.test.tsx +270 -0
- package/src/components/Tabs/Tabs.tsx +1 -1
- package/src/components/Toast/Toast.test.tsx +420 -0
- package/src/components/index.test.ts +346 -0
- package/src/constants/performance.test.ts +91 -0
- package/src/hooks/ServiceHooks.test.tsx +725 -0
- package/src/hooks/hooks.integration.test.tsx +608 -0
- package/src/hooks/index.ts +7 -4
- package/src/hooks/index.unit.test.ts +220 -0
- package/src/hooks/public/usePublicEvent.test.ts +1 -1
- package/src/hooks/public/usePublicEventLogo.test.ts +1 -1
- package/src/hooks/public/usePublicRouteParams.test.ts +1 -1
- package/src/hooks/services/useAuth.ts +9 -7
- package/src/hooks/useAddressAutocomplete.test.ts +22 -22
- package/src/hooks/useAddressAutocomplete.ts +90 -75
- package/src/hooks/useAppConfig.unit.test.ts +720 -0
- package/src/hooks/useComponentPerformance.unit.test.tsx +316 -0
- package/src/hooks/useDataTablePerformance.ts +100 -120
- package/src/hooks/useDataTablePerformance.unit.test.ts +720 -0
- package/src/hooks/useDataTableState.test.ts +170 -0
- package/src/hooks/useDebounce.unit.test.ts +157 -0
- package/src/hooks/useEventTheme.test.ts +4 -1
- package/src/hooks/useEventTheme.ts +49 -21
- package/src/hooks/useEvents.ts +41 -1
- package/src/hooks/useEvents.unit.test.ts +227 -0
- package/src/hooks/useFileReference.test.ts +44 -41
- package/src/hooks/useFileReference.ts +182 -173
- package/src/hooks/useFileUrl.ts +1 -1
- package/src/hooks/useFileUrl.unit.test.ts +684 -0
- package/src/hooks/useFileUrlCache.test.ts +319 -0
- package/src/hooks/useFileUrlCache.ts +1 -1
- package/src/hooks/useFocusManagement.unit.test.ts +604 -0
- package/src/hooks/useFocusTrap.unit.test.tsx +613 -0
- package/src/hooks/useFormDialog.test.ts +307 -0
- package/src/hooks/useInactivityTracker.ts +138 -131
- package/src/hooks/useInactivityTracker.unit.test.ts +450 -0
- package/src/hooks/useIsMobile.unit.test.ts +317 -0
- package/src/hooks/useIsPrint.ts +62 -0
- package/src/hooks/useIsPrint.unit.test.ts +545 -0
- package/src/hooks/useKeyboardShortcuts.unit.test.ts +907 -0
- package/src/hooks/useOrganisationPermissions.unit.test.tsx +293 -0
- package/src/hooks/useOrganisationSecurity.test.ts +3 -3
- package/src/hooks/useOrganisationSecurity.ts +190 -201
- package/src/hooks/useOrganisationSecurity.unit.test.tsx +959 -0
- package/src/hooks/useOrganisations.unit.test.ts +369 -0
- package/src/hooks/usePerformanceMonitor.unit.test.ts +683 -0
- package/src/hooks/usePermissionCache.test.ts +505 -0
- package/src/hooks/usePermissionCache.ts +276 -271
- package/src/hooks/usePreventTabReload.test.ts +307 -0
- package/src/hooks/usePublicEvent.simple.test.ts +779 -0
- package/src/hooks/usePublicEvent.test.ts +664 -0
- package/src/hooks/usePublicEvent.unit.test.ts +638 -0
- package/src/hooks/usePublicFileDisplay.test.ts +948 -0
- package/src/hooks/usePublicRouteParams.unit.test.ts +442 -0
- package/src/hooks/useQueryCache.test.ts +391 -0
- package/src/hooks/useQueryCache.ts +0 -2
- package/src/hooks/useRBAC.unit.test.ts +253 -0
- package/src/hooks/useSessionDraft.test.ts +556 -0
- package/src/hooks/useSessionRestoration.unit.test.tsx +381 -0
- package/src/hooks/useStorage.ts +21 -16
- package/src/hooks/useStorage.unit.test.ts +684 -0
- package/src/hooks/useToast.test.ts +413 -0
- package/src/hooks/useToast.unit.test.tsx +481 -0
- package/src/hooks/useZodForm.unit.test.tsx +191 -0
- package/src/icons/index.test.ts +133 -0
- package/src/icons/index.ts +2 -0
- package/src/index.test.ts +528 -0
- package/src/index.ts +15 -7
- package/src/providers/AuthProvider.test.tsx +218 -0
- package/src/providers/EventProvider.test.tsx +487 -0
- package/src/providers/InactivityProvider.test-helper.tsx +40 -0
- package/src/providers/InactivityProvider.test.tsx +421 -0
- package/src/providers/ProviderLifecycle.test.tsx +308 -0
- package/src/providers/UnifiedAuthProvider.test.tsx +503 -0
- package/src/providers/index.test.ts +138 -0
- package/src/providers/services/AuthServiceProvider.integration.test.tsx +229 -0
- package/src/providers/services/AuthServiceProvider.test.tsx +643 -0
- package/src/providers/services/EventServiceProvider.test.tsx +844 -0
- package/src/providers/services/InactivityServiceProvider.test.tsx +667 -0
- package/src/providers/services/OrganisationServiceProvider.test.tsx +445 -0
- package/src/providers/services/UnifiedAuthContext.ts +30 -27
- package/src/providers/services/UnifiedAuthProvider.advanced.test.tsx +434 -0
- package/src/providers/services/UnifiedAuthProvider.appId.test.tsx +408 -0
- package/src/providers/services/UnifiedAuthProvider.integration.test.tsx +304 -0
- package/src/providers/services/UnifiedAuthProvider.tsx +115 -360
- package/src/providers/services/contexts.test.tsx +281 -0
- package/src/providers/services/useUnifiedAuth.test.tsx +251 -0
- package/src/providers/services/useUnifiedAuthContextValue.ts +279 -0
- package/src/providers/useInactivity.test-helper.ts +27 -0
- package/src/rbac/README.md +7 -5
- package/src/rbac/adapters.comprehensive.test.tsx +429 -0
- package/src/rbac/adapters.test.tsx +22 -22
- package/src/rbac/adapters.tsx +29 -29
- package/src/rbac/api.test.ts +1075 -87
- package/src/rbac/api.ts +300 -255
- package/src/rbac/audit-batched.test.ts +550 -0
- package/src/rbac/audit.ts +4 -1
- package/src/rbac/auth-rbac-security.integration.test.tsx +300 -0
- package/src/rbac/auth-rbac.e2e.test.tsx +510 -0
- package/src/rbac/cache-invalidation.test.ts +715 -0
- package/src/rbac/components/AccessDenied.test.tsx +324 -0
- package/src/rbac/components/NavigationGuard.test.tsx +1148 -0
- package/src/rbac/components/NavigationGuard.tsx +2 -1
- package/src/rbac/components/PagePermissionGuard.guard.test.tsx +236 -0
- package/src/rbac/components/PagePermissionGuard.performance.test.tsx +252 -0
- package/src/rbac/components/PagePermissionGuard.race-condition.test.tsx +243 -0
- package/src/rbac/components/PagePermissionGuard.test.tsx +1443 -0
- package/src/rbac/components/PagePermissionGuard.tsx +177 -372
- package/src/rbac/components/PagePermissionGuard.verification.test.tsx +185 -0
- package/src/rbac/config.ts +58 -18
- package/src/rbac/engine.comprehensive.test.ts +808 -0
- package/src/rbac/engine.test.ts +494 -0
- package/src/rbac/engine.ts +23 -1
- package/src/rbac/errors.ts +89 -55
- package/src/rbac/hooks/permissions/runPermissionCheck.ts +91 -0
- package/src/rbac/hooks/permissions/useAccessLevel.test.ts +622 -0
- package/src/rbac/hooks/permissions/useAccessLevel.ts +16 -6
- package/src/rbac/hooks/permissions/useCan.test.ts +837 -0
- package/src/rbac/hooks/permissions/useCan.ts +177 -255
- package/src/rbac/hooks/permissions/useMultiplePermissions.test.ts +843 -0
- package/src/rbac/hooks/permissions/useMultiplePermissions.ts +24 -11
- package/src/rbac/hooks/permissions/usePermissions.test.ts +543 -0
- package/src/rbac/hooks/permissions/usePermissions.ts +36 -65
- package/src/rbac/hooks/useCan.test.ts +44 -45
- package/src/rbac/hooks/usePageAccessLogging.ts +160 -0
- package/src/rbac/hooks/usePageGuardScope.ts +119 -0
- package/src/rbac/hooks/usePagePermissionCheck.ts +67 -0
- package/src/rbac/hooks/usePermissions.integration.test.ts +427 -0
- package/src/rbac/hooks/usePermissions.stability.test.ts +268 -0
- package/src/rbac/hooks/usePermissions.test.ts +54 -54
- package/src/rbac/hooks/useRBAC.test.ts +313 -217
- package/src/rbac/hooks/useRBAC.ts +145 -81
- package/src/rbac/hooks/useResolvedScope.ts +16 -10
- package/src/rbac/hooks/useResourcePermissions.test.ts +73 -83
- package/src/rbac/hooks/useResourcePermissions.ts +77 -152
- package/src/rbac/hooks/useResourcePermissionsSuperAdmin.ts +67 -0
- package/src/rbac/hooks/useRoleManagement.test.ts +27 -112
- package/src/rbac/hooks/useRoleManagement.ts +153 -585
- package/src/rbac/hooks/useSecureSupabase.test.ts +1179 -0
- package/src/rbac/hooks/useSecureSupabase.ts +10 -2
- package/src/rbac/hooks/useSuperAdminCheck.ts +80 -0
- package/src/rbac/performance.test.ts +451 -0
- package/src/rbac/rbac-core.test.tsx +276 -0
- package/src/rbac/rbac-engine-core-logic.test.ts +387 -0
- package/src/rbac/rbac-engine-simplified.test.ts +252 -0
- package/src/rbac/rbac-functions.test.ts +703 -0
- package/src/rbac/rbac-role-isolation.test.ts +456 -0
- package/src/rbac/request-deduplication.test.ts +14 -9
- package/src/rbac/request-deduplication.ts +5 -4
- package/src/rbac/scenarios.user-role.test.tsx +271 -0
- package/src/rbac/secureClient.test.ts +514 -83
- package/src/rbac/secureClient.ts +8 -2
- package/src/rbac/security.test.ts +323 -0
- package/src/rbac/types/roleManagement.ts +66 -0
- package/src/rbac/types.ts +3 -0
- package/src/rbac/utils/clientSecurity.test.ts +192 -0
- package/src/rbac/utils/contextValidator.test.ts +126 -0
- package/src/rbac/utils/contextValidator.ts +5 -1
- package/src/rbac/utils/deep-equal.test.ts +76 -0
- package/src/rbac/utils/eventContext.test.ts +401 -0
- package/src/rbac/utils/eventContext.ts +37 -33
- package/src/rbac/utils/fetchPermissionMap.ts +13 -0
- package/src/rbac/utils/permissionMapHelpers.ts +34 -0
- package/src/rbac/utils/roleManagementRpc.ts +303 -0
- package/src/services/AuthService.edge-cases.test.ts +746 -0
- package/src/services/AuthService.restoreSession.test.ts +59 -0
- package/src/services/AuthService.test.ts +1362 -0
- package/src/services/AuthService.ts +184 -205
- package/src/services/BaseService.edge-cases.test.ts +506 -0
- package/src/services/BaseService.test.ts +363 -0
- package/src/services/EventService.edge-cases.test.ts +636 -0
- package/src/services/EventService.eventColours.test.ts +64 -0
- package/src/services/EventService.test.ts +1250 -0
- package/src/services/EventService.ts +251 -316
- package/src/services/InactivityService.edge-cases.test.ts +492 -0
- package/src/services/InactivityService.lifecycle.test.ts +406 -0
- package/src/services/InactivityService.test.ts +829 -0
- package/src/services/InactivityService.ts +172 -213
- package/src/services/OrganisationService.edge-cases.test.ts +633 -0
- package/src/services/OrganisationService.pagination.test.ts +409 -0
- package/src/services/OrganisationService.test.ts +1579 -0
- package/src/services/OrganisationService.ts +184 -238
- package/src/services/base/BaseService.test.ts +1 -1
- package/src/services/interfaces/IAuthService.test.ts +184 -0
- package/src/services/interfaces/IAuthService.ts +10 -9
- package/src/services/interfaces/IEventService.test.ts +176 -0
- package/src/services/interfaces/IInactivityService.test.ts +183 -0
- package/src/services/interfaces/IOrganisationService.test.ts +207 -0
- package/src/styles/core.css +243 -12
- package/src/theming/parseEventColours.test.ts +321 -0
- package/src/theming/runtime.test.ts +495 -0
- package/src/theming/runtime.ts +71 -2
- package/src/types/api-result.ts +53 -0
- package/src/types/core.test.ts +397 -0
- package/src/types/database-generated.test.ts +78 -0
- package/src/types/database.generated.ts +45 -10
- package/src/types/event.ts +38 -18
- package/src/types/file-reference.test.ts +351 -0
- package/src/types/file-reference.ts +37 -12
- package/src/types/guards.test.ts +246 -0
- package/src/types/index.test.ts +265 -0
- package/src/types/index.ts +3 -0
- package/src/types/organisation.roles.test.ts +55 -0
- package/src/types/organisation.test.ts +1105 -0
- package/src/types/organisation.ts +15 -15
- package/src/types/supabase.ts +13 -4
- package/src/types/theme.test.ts +830 -0
- package/src/types/type-validation.test.ts +526 -0
- package/src/types/validation.test.ts +729 -0
- package/src/utils/app/appIdResolver.test.ts +98 -71
- package/src/utils/app/appIdResolver.ts +31 -20
- package/src/utils/appConfig.unit.test.ts +55 -0
- package/src/utils/audit.unit.test.ts +69 -0
- package/src/utils/auth-utils.unit.test.ts +69 -0
- package/src/utils/bundleAnalysis.unit.test.ts +326 -0
- package/src/utils/cn.unit.test.ts +34 -0
- package/src/utils/context/organisationContext.test.ts +105 -91
- package/src/utils/context/organisationContext.ts +29 -40
- package/src/utils/core/cn.test.ts +66 -0
- package/src/utils/core/debugLogger.test.ts +113 -0
- package/src/utils/core/logger.test.ts +217 -0
- package/src/utils/core/mergeRefs.ts +24 -0
- package/src/utils/debugLogger.test.ts +417 -0
- package/src/utils/deviceFingerprint.unit.test.ts +818 -0
- package/src/utils/dynamic/createLazyComponent.tsx +9 -1
- package/src/utils/dynamic/dynamicUtils.test.ts +185 -0
- package/src/utils/dynamic/lazyLoad.test.tsx +156 -0
- package/src/utils/dynamicUtils.unit.test.ts +331 -0
- package/src/utils/file-reference/file-reference.test.ts +1249 -0
- package/src/utils/file-reference/index.ts +330 -347
- package/src/utils/formatDate.unit.test.ts +109 -0
- package/src/utils/formatting/formatDateTimeTimezone.test.ts +1 -1
- package/src/utils/formatting/formatNumber.test.ts +1 -1
- package/src/utils/formatting.unit.test.ts +99 -0
- package/src/utils/google-places/googlePlacesUtils.test.ts +70 -48
- package/src/utils/google-places/googlePlacesUtils.ts +67 -99
- package/src/utils/google-places/loadGoogleMapsScript.test.ts +25 -22
- package/src/utils/google-places/loadGoogleMapsScript.ts +138 -117
- package/src/utils/index.unit.test.ts +251 -0
- package/src/utils/lazyLoad.unit.test.tsx +319 -0
- package/src/utils/location/location.test.ts +1 -1
- package/src/utils/logger.unit.test.ts +398 -0
- package/src/utils/organisationContext.unit.test.ts +180 -0
- package/src/utils/performance/bundleAnalysis.test.ts +148 -0
- package/src/utils/performance/performanceBenchmark.test.ts +251 -0
- package/src/utils/performance/performanceBudgets.test.ts +241 -0
- package/src/utils/performanceBenchmark.test.ts +174 -0
- package/src/utils/performanceBudgets.unit.test.ts +288 -0
- package/src/utils/permissionTypes.unit.test.ts +250 -0
- package/src/utils/permissionUtils.unit.test.ts +362 -0
- package/src/utils/permissions/permissionTypes.test.ts +149 -0
- package/src/utils/persistence/keyDerivation.test.ts +306 -0
- package/src/utils/persistence/sensitiveFieldDetection.test.ts +271 -0
- package/src/utils/request-deduplication.test.ts +349 -0
- package/src/utils/sanitization.unit.test.ts +346 -0
- package/src/utils/schemaUtils.unit.test.ts +441 -0
- package/src/utils/secureDataAccess.unit.test.ts +334 -0
- package/src/utils/secureErrors.unit.test.ts +390 -0
- package/src/utils/secureStorage.unit.test.ts +289 -0
- package/src/utils/security/auth-utils.ts +34 -23
- package/src/utils/security/secureDataAccess.ts +241 -281
- package/src/utils/security/secureErrors.test.ts +1 -1
- package/src/utils/security/secureStorage.test.ts +1 -1
- package/src/utils/security/security.test.ts +25 -17
- package/src/utils/security/security.ts +15 -18
- package/src/utils/security/securityMonitor.test.ts +1 -1
- package/src/utils/security.unit.test.ts +155 -0
- package/src/utils/securityMonitor.unit.test.ts +276 -0
- package/src/utils/sessionTracking.unit.test.ts +218 -0
- package/src/utils/storage/config.unit.test.ts +239 -0
- package/src/utils/storage/helpers.test.ts +88 -102
- package/src/utils/storage/helpers.ts +173 -251
- package/src/utils/storage/index.unit.test.ts +68 -0
- package/src/utils/storage/types.ts +7 -0
- package/src/utils/supabase/createBaseClient.test.ts +31 -14
- package/src/utils/timezone/timezone.test.ts +1 -1
- package/src/utils/timezone.test.ts +345 -0
- package/src/utils/validation/common.test.ts +115 -0
- package/src/utils/validation/csrf.test.ts +198 -0
- package/src/utils/validation/csrf.ts +42 -41
- package/src/utils/validation/htmlSanitization.unit.test.ts +618 -0
- package/src/utils/validation/passwordSchema.test.ts +164 -0
- package/src/utils/validation/schema.test.ts +127 -0
- package/src/utils/validation/sqlInjectionProtection.test.ts +165 -0
- package/src/utils/validation/user.test.ts +173 -0
- package/src/utils/validation/validation.test.ts +197 -0
- package/src/utils/validation/validationUtils.test.ts +294 -0
- package/src/utils/validation.unit.test.ts +307 -0
- package/src/utils/validationUtils.unit.test.ts +558 -0
- package/dist/DataTable-SAXFG4XI.js +0 -13
- package/dist/InactivityServiceProvider-DHryoh6K.d.ts +0 -299
- package/dist/UnifiedAuthProvider-BBD2PS3Q.js +0 -7
- package/dist/UnifiedAuthProvider-CiBAl9-s.d.ts +0 -151
- package/dist/api-F47QJ7FX.js +0 -4
- package/dist/audit-Z6ZZBWLU.js +0 -3
- package/dist/auth-BZOJqrdd.d.ts +0 -49
- package/dist/chunk-3GWSPISD.js +0 -61
- package/dist/chunk-66R6RLUZ.js +0 -529
- package/dist/chunk-7YDC7LMU.js +0 -487
- package/dist/chunk-BCTXBU6U.js +0 -704
- package/dist/chunk-FBZ7U3ID.js +0 -2209
- package/dist/chunk-FN52B75D.js +0 -246
- package/dist/chunk-JJEYZ3DX.js +0 -165
- package/dist/chunk-KPYQWGFQ.js +0 -183
- package/dist/chunk-KSNLMI7N.js +0 -481
- package/dist/chunk-KYURMOQM.js +0 -977
- package/dist/chunk-LNHFAF4X.js +0 -2279
- package/dist/chunk-MPY44PWB.js +0 -8510
- package/dist/chunk-NIU6DPQV.js +0 -427
- package/dist/chunk-TFIPNIPE.js +0 -5379
- package/dist/chunk-UZNAFKGW.js +0 -125
- package/dist/chunk-W46INAVW.js +0 -1216
- package/dist/chunk-X5EAU5G7.js +0 -793
- package/dist/chunk-Y4PF6HIM.js +0 -2862
- package/dist/database.generated-DT8JTZiP.d.ts +0 -9406
- package/dist/event-WTAQuGcq.d.ts +0 -239
- package/dist/file-reference-BavO2eQj.d.ts +0 -148
- package/dist/functions-DH45k8ec.d.ts +0 -208
- package/dist/timezone-K-ptz3HO.d.ts +0 -696
- package/dist/types-BE2sEHKd.d.ts +0 -55
- package/dist/types-CvOPXWWZ.d.ts +0 -111
- package/dist/types-D05dCGma.d.ts +0 -521
- package/dist/usePublicPageContext-vxBlEHO9.d.ts +0 -4290
- package/dist/usePublicRouteParams-G3Ks53mk.d.ts +0 -877
- package/docs/api/modules.md +0 -9889
- package/scripts/build-docs-incremental.js +0 -179
- package/scripts/eslint-audit.cjs +0 -222
- package/scripts/generate-docs.js +0 -157
- package/scripts/install-cursor-rules.cjs +0 -255
- package/scripts/install-eslint-config.cjs +0 -349
- package/scripts/setup-build-cache.js +0 -73
- package/scripts/validate-pre-publish.js +0 -145
- package/src/__tests__/helpers/__tests__/component-test-utils.test.tsx +0 -260
- package/src/__tests__/helpers/__tests__/optimized-test-setup.test.ts +0 -224
- package/src/__tests__/helpers/__tests__/supabaseMock.test.ts +0 -273
- package/src/__tests__/helpers/__tests__/test-providers.test.tsx +0 -99
- package/src/__tests__/helpers/__tests__/test-utils.test.tsx +0 -446
- package/src/__tests__/helpers/__tests__/timer-utils.test.ts +0 -371
- package/src/__tests__/hooks/usePermissions.test.ts +0 -268
- package/src/__tests__/index.test.ts +0 -532
- package/src/__tests__/integration/UserProfile.test.tsx +0 -124
- package/src/__tests__/public-recipe-view.test.ts +0 -228
- package/src/__tests__/rbac/PagePermissionGuard.test.tsx +0 -222
- package/src/__tests__/rls-policies.test.ts +0 -472
- package/src/components/ContextSelector/__tests__/ContextSelector.test.tsx +0 -360
- package/src/components/DataTable/__tests__/DataTable.comprehensive.test.tsx +0 -759
- package/src/components/DataTable/__tests__/DataTable.default-state.test.tsx +0 -524
- package/src/components/DataTable/__tests__/DataTable.export.test.tsx +0 -705
- package/src/components/DataTable/__tests__/DataTable.grouping-aggregation.test.tsx +0 -658
- package/src/components/DataTable/__tests__/DataTable.hooks.test.tsx +0 -192
- package/src/components/DataTable/__tests__/DataTable.select-label-display.test.tsx +0 -485
- package/src/components/DataTable/__tests__/DataTable.test.tsx +0 -876
- package/src/components/DataTable/__tests__/DataTableCore.test-setup.ts +0 -220
- package/src/components/DataTable/__tests__/DataTableCore.test.tsx +0 -970
- package/src/components/DataTable/__tests__/README.md +0 -145
- package/src/components/DataTable/__tests__/a11y.basic.test.tsx +0 -788
- package/src/components/DataTable/__tests__/keyboard.test.tsx +0 -756
- package/src/components/DataTable/__tests__/mocks/MockRBACProvider.tsx +0 -66
- package/src/components/DataTable/__tests__/pagination.modes.test.tsx +0 -728
- package/src/components/DataTable/__tests__/ssr.strict-mode.test.tsx +0 -319
- package/src/components/DataTable/__tests__/styles.test.ts +0 -382
- package/src/components/DataTable/__tests__/test-utils/dataFactories.ts +0 -103
- package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +0 -388
- package/src/components/DataTable/__tests__/test-utils.ts +0 -94
- package/src/components/DataTable/components/AccessDeniedPage.tsx +0 -159
- package/src/components/DataTable/components/ActionButtons.tsx +0 -195
- package/src/components/DataTable/components/BulkOperationsDropdown.tsx +0 -160
- package/src/components/DataTable/components/ColumnFilter.tsx +0 -113
- package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +0 -114
- package/src/components/DataTable/components/DataTableErrorBoundary.tsx +0 -225
- package/src/components/DataTable/components/DataTableLayout.tsx +0 -584
- package/src/components/DataTable/components/DataTableModals.tsx +0 -333
- package/src/components/DataTable/components/DataTableToolbar.tsx +0 -271
- package/src/components/DataTable/components/EditFields.tsx +0 -286
- package/src/components/DataTable/components/EditableRow.tsx +0 -462
- package/src/components/DataTable/components/EmptyState.tsx +0 -82
- package/src/components/DataTable/components/FilterRow.tsx +0 -148
- package/src/components/DataTable/components/LoadingState.tsx +0 -17
- package/src/components/DataTable/components/PaginationControls.tsx +0 -285
- package/src/components/DataTable/components/RowComponent.tsx +0 -423
- package/src/components/DataTable/components/SortIndicator.tsx +0 -50
- package/src/components/DataTable/components/UnifiedTableBody.tsx +0 -395
- package/src/components/DataTable/components/__tests__/AccessDeniedPage.test.tsx +0 -245
- package/src/components/DataTable/components/__tests__/ActionButtons.test.tsx +0 -919
- package/src/components/DataTable/components/__tests__/BulkOperationsDropdown.test.tsx +0 -544
- package/src/components/DataTable/components/__tests__/ColumnFilter.test.tsx +0 -484
- package/src/components/DataTable/components/__tests__/ColumnVisibilityDropdown.test.tsx +0 -748
- package/src/components/DataTable/components/__tests__/DataTableCore.test.tsx +0 -792
- package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.test.tsx +0 -438
- package/src/components/DataTable/components/__tests__/DataTableLayout.test.tsx +0 -467
- package/src/components/DataTable/components/__tests__/DataTableModals.test.tsx +0 -358
- package/src/components/DataTable/components/__tests__/DataTableToolbar.test.tsx +0 -629
- package/src/components/DataTable/components/__tests__/EditFields.test.tsx +0 -526
- package/src/components/DataTable/components/__tests__/EditableRow.test.tsx +0 -994
- package/src/components/DataTable/components/__tests__/EmptyState.test.tsx +0 -420
- package/src/components/DataTable/components/__tests__/FilterRow.test.tsx +0 -415
- package/src/components/DataTable/components/__tests__/GroupingDropdown.test.tsx +0 -612
- package/src/components/DataTable/components/__tests__/ImportModal.test.tsx +0 -957
- package/src/components/DataTable/components/__tests__/LoadingState.test.tsx +0 -81
- package/src/components/DataTable/components/__tests__/PaginationControls.test.tsx +0 -429
- package/src/components/DataTable/components/__tests__/RowComponent.test.tsx +0 -629
- package/src/components/DataTable/components/__tests__/SortIndicator.test.tsx +0 -135
- package/src/components/DataTable/components/__tests__/UnifiedTableBody.test.tsx +0 -864
- package/src/components/DataTable/components/__tests__/cellValueUtils.test.ts +0 -453
- package/src/components/DataTable/components/cellValueUtils.ts +0 -40
- package/src/components/DataTable/components/hooks/useImportModalFocus.test.ts +0 -184
- package/src/components/DataTable/components/hooks/useImportModalFocus.ts +0 -53
- package/src/components/DataTable/components/hooks/usePermissionTracking.test.ts +0 -381
- package/src/components/DataTable/components/hooks/usePermissionTracking.ts +0 -122
- package/src/components/DataTable/context/__tests__/DataTableContext.test.tsx +0 -328
- package/src/components/DataTable/core/ActionManager.ts +0 -235
- package/src/components/DataTable/core/ColumnManager.ts +0 -204
- package/src/components/DataTable/core/DataManager.ts +0 -190
- package/src/components/DataTable/core/LocalDataAdapter.ts +0 -274
- package/src/components/DataTable/core/PluginRegistry.ts +0 -229
- package/src/components/DataTable/core/StateManager.ts +0 -312
- package/src/components/DataTable/core/__tests__/ActionManager.test.ts +0 -235
- package/src/components/DataTable/core/__tests__/ColumnFactory.test.ts +0 -403
- package/src/components/DataTable/core/__tests__/ColumnManager.test.ts +0 -141
- package/src/components/DataTable/core/__tests__/DataManager.test.ts +0 -178
- package/src/components/DataTable/core/__tests__/LocalDataAdapter.test.ts +0 -133
- package/src/components/DataTable/core/__tests__/PluginRegistry.test.ts +0 -142
- package/src/components/DataTable/core/__tests__/StateManager.test.ts +0 -158
- package/src/components/DataTable/core/interfaces.ts +0 -338
- package/src/components/DataTable/hooks/__tests__/useColumnOrderPersistence.test.ts +0 -516
- package/src/components/DataTable/hooks/__tests__/useColumnVisibilityPersistence.test.ts +0 -256
- package/src/components/DataTable/hooks/__tests__/useDataTableConfiguration.test.ts +0 -297
- package/src/components/DataTable/hooks/__tests__/useDataTableDataPipeline.test.ts +0 -270
- package/src/components/DataTable/hooks/__tests__/useDataTablePermissions.test.ts +0 -280
- package/src/components/DataTable/hooks/__tests__/useDataTableState.test.ts +0 -691
- package/src/components/DataTable/hooks/__tests__/useEffectiveColumnOrder.test.ts +0 -183
- package/src/components/DataTable/hooks/__tests__/useHierarchicalState.test.ts +0 -294
- package/src/components/DataTable/hooks/__tests__/useKeyboardNavigation.test.ts +0 -787
- package/src/components/DataTable/hooks/__tests__/useServerSideDataEffect.test.ts +0 -258
- package/src/components/DataTable/hooks/__tests__/useTableColumns.test.ts +0 -499
- package/src/components/DataTable/hooks/__tests__/useTableHandlers.test.ts +0 -440
- package/src/components/DataTable/types.ts +0 -764
- package/src/components/DataTable/utils/__tests__/a11yUtils.test.ts +0 -548
- package/src/components/DataTable/utils/__tests__/aggregationUtils.test.ts +0 -288
- package/src/components/DataTable/utils/__tests__/columnUtils.test.ts +0 -94
- package/src/components/DataTable/utils/__tests__/errorHandling.test.ts +0 -209
- package/src/components/DataTable/utils/__tests__/exportUtils.test.ts +0 -954
- package/src/components/DataTable/utils/__tests__/flexibleImport.test.ts +0 -573
- package/src/components/DataTable/utils/__tests__/hierarchicalSorting.test.ts +0 -235
- package/src/components/DataTable/utils/__tests__/hierarchicalUtils.test.ts +0 -586
- package/src/components/DataTable/utils/__tests__/paginationUtils.test.ts +0 -593
- package/src/components/DataTable/utils/__tests__/performanceUtils.test.ts +0 -470
- package/src/components/DataTable/utils/__tests__/rowUtils.test.ts +0 -235
- package/src/components/DataTable/utils/__tests__/selectFieldUtils.test.ts +0 -208
- package/src/components/NavigationMenu/__tests__/useNavigationFiltering.test.ts +0 -1934
- package/src/components/Select/__tests__/context.test.tsx +0 -56
- package/src/components/Select/hooks/__tests__/useSelectEvents.test.ts +0 -279
- package/src/components/Select/hooks/__tests__/useSelectSearch.test.tsx +0 -295
- package/src/components/Select/hooks/__tests__/useSelectState.test.ts +0 -254
- package/src/components/Select/hooks/useSelectEvents.ts +0 -87
- package/src/components/Select/hooks/useSelectSearch.ts +0 -91
- package/src/components/Select/hooks/useSelectState.ts +0 -104
- package/src/components/Select/utils/__tests__/text.test.tsx +0 -104
- package/src/components/Select/utils/text.ts +0 -26
- package/src/components/__tests__/index.test.ts +0 -346
- package/src/constants/__tests__/performance.test.ts +0 -91
- package/src/hooks/__tests__/ServiceHooks.test.tsx +0 -725
- package/src/hooks/__tests__/hooks.integration.test.tsx +0 -608
- package/src/hooks/__tests__/index.unit.test.ts +0 -220
- package/src/hooks/__tests__/useAppConfig.unit.test.ts +0 -406
- package/src/hooks/__tests__/useComponentPerformance.unit.test.tsx +0 -328
- package/src/hooks/__tests__/useDataTablePerformance.unit.test.ts +0 -720
- package/src/hooks/__tests__/useDataTableState.test.ts +0 -170
- package/src/hooks/__tests__/useDebounce.unit.test.ts +0 -157
- package/src/hooks/__tests__/useEvents.unit.test.ts +0 -227
- package/src/hooks/__tests__/useFileDisplay.test.ts +0 -540
- package/src/hooks/__tests__/useFileDisplay.unit.test.ts +0 -1109
- package/src/hooks/__tests__/useFileUrl.unit.test.ts +0 -696
- package/src/hooks/__tests__/useFileUrlCache.test.ts +0 -319
- package/src/hooks/__tests__/useFocusManagement.unit.test.ts +0 -604
- package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +0 -613
- package/src/hooks/__tests__/useFormDialog.test.ts +0 -307
- package/src/hooks/__tests__/useInactivityTracker.unit.test.ts +0 -446
- package/src/hooks/__tests__/useIsMobile.unit.test.ts +0 -317
- package/src/hooks/__tests__/useKeyboardShortcuts.unit.test.ts +0 -907
- package/src/hooks/__tests__/useOrganisationPermissions.unit.test.tsx +0 -293
- package/src/hooks/__tests__/useOrganisationSecurity.unit.test.tsx +0 -961
- package/src/hooks/__tests__/useOrganisations.unit.test.ts +0 -369
- package/src/hooks/__tests__/usePerformanceMonitor.unit.test.ts +0 -694
- package/src/hooks/__tests__/usePermissionCache.test.ts +0 -506
- package/src/hooks/__tests__/usePreventTabReload.test.ts +0 -307
- package/src/hooks/__tests__/usePublicEvent.simple.test.ts +0 -794
- package/src/hooks/__tests__/usePublicEvent.test.ts +0 -670
- package/src/hooks/__tests__/usePublicEvent.unit.test.ts +0 -638
- package/src/hooks/__tests__/usePublicFileDisplay.test.ts +0 -948
- package/src/hooks/__tests__/usePublicRouteParams.unit.test.ts +0 -442
- package/src/hooks/__tests__/useQueryCache.test.ts +0 -391
- package/src/hooks/__tests__/useRBAC.unit.test.ts +0 -236
- package/src/hooks/__tests__/useSessionDraft.test.ts +0 -556
- package/src/hooks/__tests__/useSessionRestoration.unit.test.tsx +0 -390
- package/src/hooks/__tests__/useStorage.unit.test.ts +0 -721
- package/src/hooks/__tests__/useToast.test.ts +0 -413
- package/src/hooks/__tests__/useToast.unit.test.tsx +0 -481
- package/src/hooks/__tests__/useZodForm.unit.test.tsx +0 -191
- package/src/hooks/public/usePublicFileDisplay.test.ts +0 -723
- package/src/hooks/public/usePublicFileDisplay.ts +0 -534
- package/src/hooks/useFileDisplay.ts +0 -748
- package/src/icons/__tests__/index.test.ts +0 -133
- package/src/providers/OrganisationProvider.test.tsx +0 -40
- package/src/providers/OrganisationProvider.tsx +0 -92
- package/src/providers/__tests__/AuthProvider.test.tsx +0 -218
- package/src/providers/__tests__/EventProvider.test.tsx +0 -487
- package/src/providers/__tests__/InactivityProvider.test-helper.tsx +0 -65
- package/src/providers/__tests__/InactivityProvider.test.tsx +0 -428
- package/src/providers/__tests__/OrganisationProvider.test.tsx +0 -616
- package/src/providers/__tests__/OrganisationProvider.wrapper.test.tsx +0 -591
- package/src/providers/__tests__/ProviderLifecycle.test.tsx +0 -308
- package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +0 -503
- package/src/providers/__tests__/index.test.ts +0 -138
- package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +0 -229
- package/src/providers/services/__tests__/AuthServiceProvider.test.tsx +0 -638
- package/src/providers/services/__tests__/EventServiceProvider.test.tsx +0 -839
- package/src/providers/services/__tests__/InactivityServiceProvider.test.tsx +0 -662
- package/src/providers/services/__tests__/OrganisationServiceProvider.test.tsx +0 -440
- package/src/providers/services/__tests__/UnifiedAuthProvider.advanced.test.tsx +0 -435
- package/src/providers/services/__tests__/UnifiedAuthProvider.appId.test.tsx +0 -408
- package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +0 -301
- package/src/providers/services/__tests__/contexts.test.tsx +0 -281
- package/src/providers/services/__tests__/useUnifiedAuth.test.tsx +0 -251
- package/src/rbac/__tests__/adapters.comprehensive.test.tsx +0 -429
- package/src/rbac/__tests__/audit-batched.test.ts +0 -550
- package/src/rbac/__tests__/auth-rbac-security.integration.test.tsx +0 -300
- package/src/rbac/__tests__/auth-rbac.e2e.test.tsx +0 -517
- package/src/rbac/__tests__/cache-invalidation.test.ts +0 -393
- package/src/rbac/__tests__/engine.comprehensive.test.ts +0 -808
- package/src/rbac/__tests__/performance.test.ts +0 -451
- package/src/rbac/__tests__/rbac-core.test.tsx +0 -276
- package/src/rbac/__tests__/rbac-engine-core-logic.test.ts +0 -387
- package/src/rbac/__tests__/rbac-engine-simplified.test.ts +0 -252
- package/src/rbac/__tests__/rbac-functions.test.ts +0 -646
- package/src/rbac/__tests__/rbac-role-isolation.test.ts +0 -456
- package/src/rbac/__tests__/scenarios.user-role.test.tsx +0 -271
- package/src/rbac/components/__tests__/AccessDenied.test.tsx +0 -324
- package/src/rbac/components/__tests__/NavigationGuard.test.tsx +0 -1146
- package/src/rbac/components/__tests__/PagePermissionGuard.performance.test.tsx +0 -231
- package/src/rbac/components/__tests__/PagePermissionGuard.race-condition.test.tsx +0 -243
- package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +0 -1430
- package/src/rbac/components/__tests__/PagePermissionGuard.verification.test.tsx +0 -185
- package/src/rbac/hooks/__tests__/usePermissions.integration.test.ts +0 -427
- package/src/rbac/hooks/__tests__/useSecureSupabase.test.ts +0 -1179
- package/src/rbac/hooks/permissions/__tests__/useAccessLevel.test.ts +0 -622
- package/src/rbac/hooks/permissions/__tests__/useCan.test.ts +0 -798
- package/src/rbac/hooks/permissions/__tests__/useMultiplePermissions.test.ts +0 -843
- package/src/rbac/hooks/permissions/__tests__/usePermissions.test.ts +0 -545
- package/src/rbac/utils/__tests__/clientSecurity.test.ts +0 -192
- package/src/rbac/utils/__tests__/contextValidator.test.ts +0 -126
- package/src/rbac/utils/__tests__/deep-equal.test.ts +0 -76
- package/src/rbac/utils/__tests__/eventContext.test.ts +0 -386
- package/src/services/__tests__/AuthService.edge-cases.test.ts +0 -746
- package/src/services/__tests__/AuthService.restoreSession.test.ts +0 -59
- package/src/services/__tests__/AuthService.test.ts +0 -1328
- package/src/services/__tests__/BaseService.edge-cases.test.ts +0 -506
- package/src/services/__tests__/BaseService.test.ts +0 -363
- package/src/services/__tests__/EventService.edge-cases.test.ts +0 -633
- package/src/services/__tests__/EventService.eventColours.test.ts +0 -64
- package/src/services/__tests__/EventService.test.ts +0 -1018
- package/src/services/__tests__/InactivityService.edge-cases.test.ts +0 -492
- package/src/services/__tests__/InactivityService.lifecycle.test.ts +0 -406
- package/src/services/__tests__/InactivityService.test.ts +0 -654
- package/src/services/__tests__/OrganisationService.edge-cases.test.ts +0 -633
- package/src/services/__tests__/OrganisationService.pagination.test.ts +0 -409
- package/src/services/__tests__/OrganisationService.test.ts +0 -1176
- package/src/services/interfaces/__tests__/IAuthService.test.ts +0 -190
- package/src/services/interfaces/__tests__/IEventService.test.ts +0 -176
- package/src/services/interfaces/__tests__/IInactivityService.test.ts +0 -183
- package/src/services/interfaces/__tests__/IOrganisationService.test.ts +0 -207
- package/src/theming/__tests__/parseEventColours.test.ts +0 -321
- package/src/theming/__tests__/runtime.test.ts +0 -504
- package/src/types/__tests__/core.test.ts +0 -397
- package/src/types/__tests__/database-generated.test.ts +0 -78
- package/src/types/__tests__/file-reference.test.ts +0 -351
- package/src/types/__tests__/guards.test.ts +0 -246
- package/src/types/__tests__/index.test.ts +0 -265
- package/src/types/__tests__/organisation.roles.test.ts +0 -55
- package/src/types/__tests__/organisation.test.ts +0 -1133
- package/src/types/__tests__/theme.test.ts +0 -830
- package/src/types/__tests__/type-validation.test.ts +0 -526
- package/src/types/__tests__/validation.test.ts +0 -729
- package/src/utils/__tests__/appConfig.unit.test.ts +0 -55
- package/src/utils/__tests__/audit.unit.test.ts +0 -69
- package/src/utils/__tests__/auth-utils.unit.test.ts +0 -70
- package/src/utils/__tests__/bundleAnalysis.unit.test.ts +0 -326
- package/src/utils/__tests__/cn.unit.test.ts +0 -34
- package/src/utils/__tests__/debugLogger.test.ts +0 -417
- package/src/utils/__tests__/deviceFingerprint.unit.test.ts +0 -818
- package/src/utils/__tests__/dynamicUtils.unit.test.ts +0 -331
- package/src/utils/__tests__/formatDate.unit.test.ts +0 -109
- package/src/utils/__tests__/formatting.unit.test.ts +0 -99
- package/src/utils/__tests__/index.unit.test.ts +0 -251
- package/src/utils/__tests__/lazyLoad.unit.test.tsx +0 -320
- package/src/utils/__tests__/logger.unit.test.ts +0 -398
- package/src/utils/__tests__/organisationContext.unit.test.ts +0 -191
- package/src/utils/__tests__/performanceBenchmark.test.ts +0 -174
- package/src/utils/__tests__/performanceBudgets.unit.test.ts +0 -288
- package/src/utils/__tests__/permissionTypes.unit.test.ts +0 -250
- package/src/utils/__tests__/permissionUtils.unit.test.ts +0 -362
- package/src/utils/__tests__/request-deduplication.test.ts +0 -349
- package/src/utils/__tests__/sanitization.unit.test.ts +0 -346
- package/src/utils/__tests__/schemaUtils.unit.test.ts +0 -441
- package/src/utils/__tests__/secureDataAccess.unit.test.ts +0 -334
- package/src/utils/__tests__/secureErrors.unit.test.ts +0 -390
- package/src/utils/__tests__/secureStorage.unit.test.ts +0 -289
- package/src/utils/__tests__/security.unit.test.ts +0 -149
- package/src/utils/__tests__/securityMonitor.unit.test.ts +0 -276
- package/src/utils/__tests__/sessionTracking.unit.test.ts +0 -218
- package/src/utils/__tests__/timezone.test.ts +0 -345
- package/src/utils/__tests__/validation.unit.test.ts +0 -307
- package/src/utils/__tests__/validationUtils.unit.test.ts +0 -555
- package/src/utils/core/__tests__/cn.test.ts +0 -66
- package/src/utils/core/__tests__/debugLogger.test.ts +0 -113
- package/src/utils/core/__tests__/logger.test.ts +0 -217
- package/src/utils/dynamic/__tests__/dynamicUtils.test.ts +0 -185
- package/src/utils/dynamic/__tests__/lazyLoad.test.tsx +0 -156
- package/src/utils/file-reference/__tests__/file-reference.test.ts +0 -1313
- package/src/utils/performance/__tests__/bundleAnalysis.test.ts +0 -148
- package/src/utils/performance/__tests__/performanceBenchmark.test.ts +0 -251
- package/src/utils/performance/__tests__/performanceBudgets.test.ts +0 -241
- package/src/utils/permissions/__tests__/permissionTypes.test.ts +0 -149
- package/src/utils/persistence/__tests__/keyDerivation.test.ts +0 -306
- package/src/utils/persistence/__tests__/sensitiveFieldDetection.test.ts +0 -271
- package/src/utils/storage/__tests__/config.unit.test.ts +0 -239
- package/src/utils/storage/__tests__/index.unit.test.ts +0 -68
- package/src/utils/validation/__tests__/common.test.ts +0 -115
- package/src/utils/validation/__tests__/csrf.test.ts +0 -170
- package/src/utils/validation/__tests__/htmlSanitization.unit.test.ts +0 -618
- package/src/utils/validation/__tests__/passwordSchema.test.ts +0 -164
- package/src/utils/validation/__tests__/schema.test.ts +0 -127
- package/src/utils/validation/__tests__/sqlInjectionProtection.test.ts +0 -165
- package/src/utils/validation/__tests__/user.test.ts +0 -173
- package/src/utils/validation/__tests__/validation.test.ts +0 -197
- package/src/utils/validation/__tests__/validationUtils.test.ts +0 -294
- /package/src/components/DataTable/{components/__tests__ → ui}/COVERAGE_NOTE.md +0 -0
- /package/src/components/DataTable/utils/{__tests__/COVERAGE_NOTE.md → COVERAGE_NOTE.md} +0 -0
- /package/src/hooks/{__tests__/useApiFetch.unit.test.ts → useApiFetch.unit.test.ts} +0 -0
- /package/src/providers/{__tests__/README.md → README.md} +0 -0
- /package/src/rbac/{__tests__/index.test.ts → index.test.ts} +0 -0
- /package/src/rbac/{__tests__/rbac-integration.test.ts → rbac-integration.test.ts} +0 -0
- /package/src/types/{__tests__/README.md → README.md} +0 -0
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
* <DialogBody>
|
|
43
43
|
* <section className="space-y-4">
|
|
44
44
|
* <fieldset className="grid grid-cols-4 items-center gap-4">
|
|
45
|
-
* <Label htmlFor="name"
|
|
45
|
+
* <Label htmlFor="name">Name</Label>
|
|
46
46
|
* <Input id="name" defaultValue="John Doe" className="col-span-3" />
|
|
47
47
|
* </fieldset>
|
|
48
48
|
* </section>
|
|
@@ -89,16 +89,20 @@
|
|
|
89
89
|
|
|
90
90
|
import * as React from 'react';
|
|
91
91
|
import { createPortal } from 'react-dom';
|
|
92
|
-
import { X } from 'lucide-react';
|
|
93
92
|
import { useLocation } from 'react-router-dom';
|
|
93
|
+
import { Button, IconButton } from '../Button';
|
|
94
|
+
import { X } from '../../icons';
|
|
94
95
|
import { useUnifiedAuth } from '../../providers/services/UnifiedAuthProvider';
|
|
95
96
|
import { cn } from '../../utils/core/cn';
|
|
97
|
+
import { mergeRefs } from '../../utils/core/mergeRefs';
|
|
96
98
|
import { renderSafeHtml } from '../../utils/validation/htmlSanitization';
|
|
97
99
|
import { useState, useEffect, useRef, useCallback, useId, useMemo } from 'react';
|
|
98
100
|
import { useFocusTrap } from '../../hooks/useFocusTrap';
|
|
99
|
-
import { useSessionDraft } from '../../hooks/useSessionDraft';
|
|
100
101
|
import { deriveDialogKey } from '../../utils/persistence/keyDerivation';
|
|
101
102
|
import { createLogger } from '../../utils/core/logger';
|
|
103
|
+
import { useDialogPersistence } from './useDialogPersistence';
|
|
104
|
+
import { useDialogDimensions } from './useDialogDimensions';
|
|
105
|
+
import { useDialogLifecycle } from './useDialogLifecycle';
|
|
102
106
|
|
|
103
107
|
/**
|
|
104
108
|
* Dialog size variants
|
|
@@ -115,7 +119,6 @@ interface DialogContextValue {
|
|
|
115
119
|
dialogRef: React.RefObject<HTMLDialogElement | null>;
|
|
116
120
|
titleId: string;
|
|
117
121
|
descriptionId: string;
|
|
118
|
-
dialogTitle?: string; // For persistence key derivation
|
|
119
122
|
markClosedByUser?: () => void; // Callback to mark dialog as closed by user (for Cancel buttons, etc.)
|
|
120
123
|
}
|
|
121
124
|
|
|
@@ -190,12 +193,6 @@ export interface DialogContentProps extends React.HTMLAttributes<HTMLDialogEleme
|
|
|
190
193
|
persistOpenState?: boolean;
|
|
191
194
|
}
|
|
192
195
|
|
|
193
|
-
/**
|
|
194
|
-
* Props for the DialogOverlay component
|
|
195
|
-
* @public
|
|
196
|
-
*/
|
|
197
|
-
export interface DialogOverlayProps extends React.HTMLAttributes<HTMLDivElement> {}
|
|
198
|
-
|
|
199
196
|
/**
|
|
200
197
|
* Props for the DialogPortal component
|
|
201
198
|
* @public
|
|
@@ -259,16 +256,6 @@ export interface DialogDescriptionProps extends React.HTMLAttributes<HTMLParagra
|
|
|
259
256
|
allowHtml?: boolean;
|
|
260
257
|
}
|
|
261
258
|
|
|
262
|
-
// Size mapping for dialog variants
|
|
263
|
-
const sizeClasses = {
|
|
264
|
-
sm: 'max-w-sm',
|
|
265
|
-
md: 'max-w-md',
|
|
266
|
-
lg: 'max-w-lg',
|
|
267
|
-
xl: 'max-w-xl',
|
|
268
|
-
full: 'max-w-full size-full',
|
|
269
|
-
auto: 'max-w-none w-auto min-w-0'
|
|
270
|
-
};
|
|
271
|
-
|
|
272
259
|
/**
|
|
273
260
|
* Dialog root component
|
|
274
261
|
* Provides context for dialog state management
|
|
@@ -283,7 +270,6 @@ const Dialog = React.memo<DialogProps>(function Dialog({
|
|
|
283
270
|
const dialogRef = useRef<HTMLDialogElement | null>(null);
|
|
284
271
|
const titleId = useId();
|
|
285
272
|
const descriptionId = useId();
|
|
286
|
-
const dialogTitleRef = useRef<string | undefined>(undefined);
|
|
287
273
|
const [markClosedByUser, setMarkClosedByUserState] = useState<(() => void) | undefined>(undefined);
|
|
288
274
|
|
|
289
275
|
const isControlled = controlledOpen !== undefined;
|
|
@@ -302,15 +288,9 @@ const Dialog = React.memo<DialogProps>(function Dialog({
|
|
|
302
288
|
dialogRef,
|
|
303
289
|
titleId,
|
|
304
290
|
descriptionId,
|
|
305
|
-
dialogTitle: dialogTitleRef.current,
|
|
306
291
|
markClosedByUser, // Set by DialogContent
|
|
307
292
|
}), [open, handleOpenChange, titleId, descriptionId, markClosedByUser]);
|
|
308
293
|
|
|
309
|
-
// Expose function to set dialog title (called by DialogContent)
|
|
310
|
-
const setDialogTitle = useCallback((title: string | undefined) => {
|
|
311
|
-
dialogTitleRef.current = title;
|
|
312
|
-
}, []);
|
|
313
|
-
|
|
314
294
|
// Expose function to set markClosedByUser callback (called by DialogContent)
|
|
315
295
|
const setMarkClosedByUser = useCallback((callback: (() => void) | undefined) => {
|
|
316
296
|
setMarkClosedByUserState(callback);
|
|
@@ -318,22 +298,17 @@ const Dialog = React.memo<DialogProps>(function Dialog({
|
|
|
318
298
|
|
|
319
299
|
return (
|
|
320
300
|
<DialogContext.Provider value={contextValue}>
|
|
321
|
-
<
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
</DialogMarkClosedContext.Provider>
|
|
325
|
-
</DialogTitleContext.Provider>
|
|
301
|
+
<DialogMarkClosedContext.Provider value={setMarkClosedByUser}>
|
|
302
|
+
{children}
|
|
303
|
+
</DialogMarkClosedContext.Provider>
|
|
326
304
|
</DialogContext.Provider>
|
|
327
305
|
);
|
|
328
306
|
});
|
|
329
307
|
|
|
330
|
-
// Context for setting dialog title from DialogContent
|
|
331
|
-
const DialogTitleContext = React.createContext<((title: string | undefined) => void) | null>(null);
|
|
332
|
-
|
|
333
308
|
// Context for setting markClosedByUser callback from DialogContent
|
|
334
309
|
const DialogMarkClosedContext = React.createContext<((callback: (() => void) | undefined) => void) | null>(null);
|
|
335
310
|
|
|
336
|
-
// Context for
|
|
311
|
+
// Context for passing markClosedByUser to DialogClose in the same render (DialogContext.markClosedByUser is set async)
|
|
337
312
|
const DialogCloseContext = React.createContext<(() => void) | null>(null);
|
|
338
313
|
Dialog.displayName = 'Dialog';
|
|
339
314
|
|
|
@@ -341,7 +316,7 @@ Dialog.displayName = 'Dialog';
|
|
|
341
316
|
* DialogTrigger component
|
|
342
317
|
* Opens the dialog when clicked
|
|
343
318
|
*/
|
|
344
|
-
const DialogTrigger = React.forwardRef<
|
|
319
|
+
const DialogTrigger = React.forwardRef<HTMLButtonElement, DialogTriggerProps>(
|
|
345
320
|
({ children, asChild = false, className, onClick, ...props }, ref) => {
|
|
346
321
|
const { onOpenChange } = useDialogContext();
|
|
347
322
|
|
|
@@ -357,19 +332,19 @@ const DialogTrigger = React.forwardRef<HTMLElement, DialogTriggerProps>(
|
|
|
357
332
|
onClick: handleClick,
|
|
358
333
|
className: cn(className, childElement.props?.className),
|
|
359
334
|
...props,
|
|
360
|
-
} as
|
|
335
|
+
} as React.HTMLAttributes<HTMLElement> & React.RefAttributes<HTMLElement>);
|
|
361
336
|
}
|
|
362
337
|
|
|
363
338
|
return (
|
|
364
|
-
<
|
|
365
|
-
ref={ref
|
|
339
|
+
<Button
|
|
340
|
+
ref={ref}
|
|
366
341
|
type="button"
|
|
367
342
|
onClick={handleClick}
|
|
368
343
|
className={className}
|
|
369
344
|
{...props}
|
|
370
345
|
>
|
|
371
346
|
{children}
|
|
372
|
-
</
|
|
347
|
+
</Button>
|
|
373
348
|
);
|
|
374
349
|
}
|
|
375
350
|
);
|
|
@@ -393,172 +368,28 @@ const DialogPortal: React.FC<DialogPortalProps> = ({ children }) => {
|
|
|
393
368
|
};
|
|
394
369
|
DialogPortal.displayName = 'DialogPortal';
|
|
395
370
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
DialogOverlay.displayName = 'DialogOverlay';
|
|
411
|
-
|
|
412
|
-
/**
|
|
413
|
-
* Custom hook for managing smart dialog dimensions
|
|
414
|
-
* Handles responsive sizing and viewport-based constraints
|
|
415
|
-
* Dimensions are calculated synchronously based on props - no resize listener needed
|
|
416
|
-
*/
|
|
417
|
-
const useSmartDimensions = ({
|
|
418
|
-
maxHeightPercent,
|
|
419
|
-
maxWidthPercent,
|
|
420
|
-
maxHeight,
|
|
421
|
-
maxWidth,
|
|
422
|
-
minHeight,
|
|
423
|
-
minWidth,
|
|
424
|
-
}: {
|
|
425
|
-
maxHeightPercent?: number;
|
|
426
|
-
maxWidthPercent?: number;
|
|
427
|
-
maxHeight?: string;
|
|
428
|
-
maxWidth?: string;
|
|
429
|
-
minHeight?: string;
|
|
430
|
-
minWidth?: string;
|
|
431
|
-
}) => {
|
|
432
|
-
// Calculate dimensions synchronously - no need for resize listener
|
|
433
|
-
// CSS viewport units (vh/vw) handle responsiveness automatically
|
|
434
|
-
return React.useMemo<React.CSSProperties>(() => {
|
|
435
|
-
const result: React.CSSProperties = {};
|
|
436
|
-
|
|
437
|
-
// Handle height constraints
|
|
438
|
-
if (maxHeightPercent && typeof maxHeightPercent === 'number') {
|
|
439
|
-
const constrainedHeight = Math.min(maxHeightPercent, 95);
|
|
440
|
-
result.maxHeight = `${constrainedHeight}vh`;
|
|
441
|
-
} else if (maxHeight) {
|
|
442
|
-
result.maxHeight = maxHeight;
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
// Handle width constraints
|
|
446
|
-
if (maxWidthPercent && typeof maxWidthPercent === 'number') {
|
|
447
|
-
const constrainedWidth = Math.min(maxWidthPercent, 95);
|
|
448
|
-
result.maxWidth = `${constrainedWidth}vw`;
|
|
449
|
-
} else if (maxWidth) {
|
|
450
|
-
result.maxWidth = maxWidth;
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
// Include minHeight/minWidth if provided
|
|
454
|
-
if (minHeight) {
|
|
455
|
-
result.minHeight = minHeight;
|
|
456
|
-
}
|
|
457
|
-
if (minWidth) {
|
|
458
|
-
result.minWidth = minWidth;
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
return result;
|
|
462
|
-
}, [maxHeightPercent, maxWidthPercent, maxHeight, maxWidth, minHeight, minWidth]);
|
|
463
|
-
};
|
|
464
|
-
|
|
465
|
-
/**
|
|
466
|
-
* Global lock to ensure only one dialog is open at a time
|
|
467
|
-
* Uses sessionStorage for persistence across page reloads
|
|
468
|
-
*/
|
|
469
|
-
const DIALOG_LOCK_KEY = 'pace-core:dialog:lock';
|
|
470
|
-
|
|
471
|
-
function acquireDialogLock(persistenceKey: string | null): boolean {
|
|
472
|
-
if (!persistenceKey) {
|
|
473
|
-
return true; // Non-persisted dialogs can always open
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
try {
|
|
477
|
-
const lock = sessionStorage.getItem(DIALOG_LOCK_KEY);
|
|
478
|
-
if (lock) {
|
|
479
|
-
const lockData = JSON.parse(lock);
|
|
480
|
-
// If lock is held by this dialog, allow it
|
|
481
|
-
if (lockData.key === persistenceKey) {
|
|
482
|
-
return true;
|
|
483
|
-
}
|
|
484
|
-
// If lock is held by another dialog, check if that dialog is still open
|
|
485
|
-
const lockDialog = document.querySelector(`dialog[data-persistence-key="${lockData.key}"]`) as HTMLDialogElement;
|
|
486
|
-
if (lockDialog && lockDialog.open) {
|
|
487
|
-
return false; // Another dialog is still open
|
|
488
|
-
}
|
|
489
|
-
// Lock is stale, clear it
|
|
490
|
-
sessionStorage.removeItem(DIALOG_LOCK_KEY);
|
|
491
|
-
}
|
|
492
|
-
// Acquire the lock
|
|
493
|
-
sessionStorage.setItem(DIALOG_LOCK_KEY, JSON.stringify({
|
|
494
|
-
key: persistenceKey,
|
|
495
|
-
timestamp: Date.now(),
|
|
496
|
-
}));
|
|
497
|
-
return true;
|
|
498
|
-
} catch {
|
|
499
|
-
// If sessionStorage fails, allow opening (graceful degradation)
|
|
500
|
-
return true;
|
|
501
|
-
}
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
function releaseDialogLock(persistenceKey: string | null): void {
|
|
505
|
-
if (!persistenceKey) {
|
|
506
|
-
return;
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
try {
|
|
510
|
-
const lock = sessionStorage.getItem(DIALOG_LOCK_KEY);
|
|
511
|
-
if (lock) {
|
|
512
|
-
const lockData = JSON.parse(lock);
|
|
513
|
-
if (lockData.key === persistenceKey) {
|
|
514
|
-
sessionStorage.removeItem(DIALOG_LOCK_KEY);
|
|
515
|
-
}
|
|
516
|
-
}
|
|
517
|
-
} catch {
|
|
518
|
-
// Ignore errors
|
|
519
|
-
}
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
/**
|
|
523
|
-
* Check if any other dialog (besides the current one) has persisted open state
|
|
524
|
-
* This helps determine if another dialog should be allowed to auto-open
|
|
525
|
-
*/
|
|
526
|
-
function checkOtherDialogsHavePersistedState(currentPersistenceKey: string | null): boolean {
|
|
527
|
-
if (!currentPersistenceKey) {
|
|
528
|
-
return false;
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
try {
|
|
532
|
-
const lock = sessionStorage.getItem(DIALOG_LOCK_KEY);
|
|
533
|
-
if (lock) {
|
|
534
|
-
const lockData = JSON.parse(lock);
|
|
535
|
-
if (lockData.key !== currentPersistenceKey) {
|
|
536
|
-
// Another dialog holds the lock
|
|
537
|
-
return true;
|
|
538
|
-
}
|
|
539
|
-
}
|
|
540
|
-
} catch {
|
|
541
|
-
// Error accessing sessionStorage - assume no other dialogs
|
|
542
|
-
return false;
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
return false;
|
|
371
|
+
export interface UseDialogContentStateReturn {
|
|
372
|
+
mergedRef: (node: HTMLDialogElement | null) => void;
|
|
373
|
+
canRender: boolean;
|
|
374
|
+
markClosedByUser: () => void;
|
|
375
|
+
sizeClass: string;
|
|
376
|
+
mergedStyle: React.CSSProperties;
|
|
377
|
+
hasHeightConstraint: boolean;
|
|
378
|
+
persistenceKey: string | null;
|
|
379
|
+
persistOpenState: boolean;
|
|
380
|
+
titleId: string;
|
|
381
|
+
descriptionId: string;
|
|
382
|
+
open: boolean;
|
|
383
|
+
title: string | undefined;
|
|
384
|
+
description: string | undefined;
|
|
546
385
|
}
|
|
547
386
|
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
* @param ref - Forwarded ref to the dialog element
|
|
554
|
-
* @returns JSX.Element - The semantic dialog content with overlay and optional close button
|
|
555
|
-
*/
|
|
556
|
-
const DialogContent = React.forwardRef<HTMLDialogElement, DialogContentProps>(
|
|
557
|
-
({
|
|
558
|
-
className,
|
|
559
|
-
children,
|
|
387
|
+
function useDialogContentState(
|
|
388
|
+
props: DialogContentProps,
|
|
389
|
+
ref: React.ForwardedRef<HTMLDialogElement>
|
|
390
|
+
): UseDialogContentStateReturn {
|
|
391
|
+
const {
|
|
560
392
|
size = 'md',
|
|
561
|
-
showCloseButton = true,
|
|
562
393
|
preventCloseOnEscape = false,
|
|
563
394
|
preventCloseOnOutsideClick = false,
|
|
564
395
|
maxHeightPercent,
|
|
@@ -572,427 +403,47 @@ const DialogContent = React.forwardRef<HTMLDialogElement, DialogContentProps>(
|
|
|
572
403
|
description,
|
|
573
404
|
style,
|
|
574
405
|
persistOpenState = true,
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
return null;
|
|
606
|
-
}
|
|
607
|
-
// Don't create persistence key if userId is not available
|
|
608
|
-
// This prevents unscoped persistence that could leak between users
|
|
609
|
-
if (!userId) {
|
|
610
|
-
return null;
|
|
611
|
-
}
|
|
612
|
-
return deriveDialogKey(
|
|
613
|
-
{
|
|
614
|
-
title,
|
|
615
|
-
description,
|
|
616
|
-
},
|
|
617
|
-
location,
|
|
618
|
-
userId
|
|
619
|
-
);
|
|
620
|
-
}, [title, description, location, userId, persistOpenState]);
|
|
621
|
-
|
|
622
|
-
// Use session draft for open state persistence
|
|
623
|
-
// Only enabled when we have a valid persistenceKey (which requires userId)
|
|
624
|
-
const { state: persistedOpen, setState: setPersistedOpen, clearDraft, wasRestored } = useSessionDraft<boolean>(
|
|
625
|
-
persistenceKey ? `${persistenceKey}:open` : 'dialog:no-key:open',
|
|
626
|
-
false,
|
|
627
|
-
{
|
|
628
|
-
enabled: Boolean(persistenceKey && persistOpenState && userId),
|
|
629
|
-
debounceMs: 300,
|
|
630
|
-
}
|
|
631
|
-
);
|
|
632
|
-
|
|
633
|
-
// Track if we've attempted auto-open to prevent multiple attempts
|
|
634
|
-
const hasAutoOpenedRef = useRef(false);
|
|
635
|
-
const hasInitializedRef = useRef(false);
|
|
636
|
-
// Track if dialog was closed by user action (to clear persistence)
|
|
637
|
-
const wasClosedByUserRef = useRef(false);
|
|
638
|
-
// Track if dialog was manually opened (to prevent auto-open from interfering)
|
|
639
|
-
const wasManuallyOpenedRef = useRef(false);
|
|
640
|
-
|
|
641
|
-
// Callback to mark dialog as closed by user (exposed via context for DialogClose and Cancel buttons)
|
|
642
|
-
const markClosedByUser = useCallback(() => {
|
|
643
|
-
if (hasInitializedRef.current) {
|
|
644
|
-
wasClosedByUserRef.current = true;
|
|
645
|
-
}
|
|
646
|
-
}, []);
|
|
647
|
-
|
|
648
|
-
// Register markClosedByUser with parent Dialog component so it's available via DialogContext
|
|
649
|
-
useEffect(() => {
|
|
650
|
-
if (setMarkClosedByUser) {
|
|
651
|
-
setMarkClosedByUser(markClosedByUser);
|
|
652
|
-
}
|
|
653
|
-
return () => {
|
|
654
|
-
// Cleanup: unregister when DialogContent unmounts
|
|
655
|
-
if (setMarkClosedByUser) {
|
|
656
|
-
setMarkClosedByUser(undefined);
|
|
657
|
-
}
|
|
658
|
-
};
|
|
659
|
-
}, [setMarkClosedByUser, markClosedByUser]);
|
|
660
|
-
// Track if we've cleaned up other dialog states (to prevent multiple cleanup runs)
|
|
661
|
-
const hasCleanedUpOtherDialogsRef = useRef(false);
|
|
662
|
-
|
|
663
|
-
// Auto-open on mount if dialog was open when tab closed
|
|
664
|
-
useEffect(() => {
|
|
665
|
-
if (!persistenceKey || !persistOpenState) {
|
|
666
|
-
hasInitializedRef.current = true;
|
|
667
|
-
return;
|
|
668
|
-
}
|
|
669
|
-
|
|
670
|
-
// Only attempt auto-open once
|
|
671
|
-
// This prevents auto-open from running after manual opens
|
|
672
|
-
if (hasAutoOpenedRef.current) {
|
|
673
|
-
return;
|
|
674
|
-
}
|
|
675
|
-
|
|
676
|
-
// CRITICAL: Don't auto-open if dialog was manually opened
|
|
677
|
-
// This prevents auto-open from interfering with manual opens
|
|
678
|
-
if (wasManuallyOpenedRef.current) {
|
|
679
|
-
logger.debug('[Dialog Persistence] ⏭️ Skipping auto-open - dialog was manually opened', {
|
|
680
|
-
persistenceKey,
|
|
681
|
-
currentOpen: open,
|
|
682
|
-
});
|
|
683
|
-
return;
|
|
684
|
-
}
|
|
685
|
-
|
|
686
|
-
// Mark as initialized after first check
|
|
687
|
-
if (!hasInitializedRef.current) {
|
|
688
|
-
hasInitializedRef.current = true;
|
|
689
|
-
}
|
|
690
|
-
|
|
691
|
-
// Auto-open check (logging removed for performance)
|
|
692
|
-
|
|
693
|
-
// CRITICAL: Don't auto-open if dialog is already open (user-initiated)
|
|
694
|
-
if (open === true) {
|
|
695
|
-
hasAutoOpenedRef.current = true;
|
|
696
|
-
return;
|
|
697
|
-
}
|
|
698
|
-
|
|
699
|
-
// CRITICAL: Don't auto-open if userId is not available (prevents unscoped persistence from being restored)
|
|
700
|
-
if (!userId) {
|
|
701
|
-
hasAutoOpenedRef.current = true;
|
|
702
|
-
return;
|
|
703
|
-
}
|
|
704
|
-
|
|
705
|
-
// Only auto-open if conditions are met
|
|
706
|
-
if (persistedOpen === true && open === false && wasRestored && !hasAutoOpenedRef.current && !wasManuallyOpenedRef.current) {
|
|
707
|
-
const AUTO_OPEN_LOCK_KEY = 'pace-core:dialog:auto-open-lock';
|
|
708
|
-
const lockTimestamp = sessionStorage.getItem(AUTO_OPEN_LOCK_KEY);
|
|
709
|
-
const now = Date.now();
|
|
710
|
-
|
|
711
|
-
// Check if another dialog is already auto-opening (lock exists and is recent)
|
|
712
|
-
if (lockTimestamp) {
|
|
713
|
-
const lockAge = now - parseInt(lockTimestamp, 10);
|
|
714
|
-
if (lockAge < 1000) {
|
|
715
|
-
// Lock is recent - another dialog is auto-opening
|
|
716
|
-
// Check if there's already an open dialog with this persistence key
|
|
717
|
-
const existingOpenDialog = document.querySelector(`dialog[data-persistence-key="${persistenceKey}"][open]`);
|
|
718
|
-
if (existingOpenDialog) {
|
|
719
|
-
// Another instance is already open - skip
|
|
720
|
-
hasAutoOpenedRef.current = true;
|
|
721
|
-
return;
|
|
722
|
-
}
|
|
723
|
-
// Check if other dialog has persisted state
|
|
724
|
-
const otherDialogHasPersistedState = checkOtherDialogsHavePersistedState(persistenceKey);
|
|
725
|
-
if (otherDialogHasPersistedState) {
|
|
726
|
-
// Another dialog with persisted state is auto-opening - skip this one
|
|
727
|
-
clearDraft();
|
|
728
|
-
hasAutoOpenedRef.current = true;
|
|
729
|
-
return;
|
|
730
|
-
}
|
|
731
|
-
}
|
|
732
|
-
// Clear stale locks
|
|
733
|
-
if (lockAge > 2000) {
|
|
734
|
-
sessionStorage.removeItem(AUTO_OPEN_LOCK_KEY);
|
|
735
|
-
}
|
|
736
|
-
}
|
|
737
|
-
|
|
738
|
-
// Check if dialog with same key is already open in DOM (synchronous check)
|
|
739
|
-
const existingDialog = document.querySelector(`dialog[data-persistence-key="${persistenceKey}"][open]`);
|
|
740
|
-
if (existingDialog && existingDialog !== dialogRef.current && existingDialog !== internalRef.current) {
|
|
741
|
-
hasAutoOpenedRef.current = true;
|
|
742
|
-
return;
|
|
743
|
-
}
|
|
744
|
-
|
|
745
|
-
// Set lock and mark as auto-opened BEFORE calling onOpenChange
|
|
746
|
-
sessionStorage.setItem(AUTO_OPEN_LOCK_KEY, String(now));
|
|
747
|
-
hasAutoOpenedRef.current = true;
|
|
748
|
-
wasManuallyOpenedRef.current = false;
|
|
749
|
-
|
|
750
|
-
logger.debug('[Dialog] 🔄 AUTO-OPEN', { persistenceKey });
|
|
751
|
-
|
|
752
|
-
// Use small delay to prevent visual flash
|
|
753
|
-
const timeoutId = setTimeout(() => {
|
|
754
|
-
// Double-check: if dialog is still closed and no other instance opened it
|
|
755
|
-
const stillClosed = !open;
|
|
756
|
-
const noOtherInstance = !document.querySelector(`dialog[data-persistence-key="${persistenceKey}"][open]`);
|
|
757
|
-
|
|
758
|
-
if (stillClosed && noOtherInstance) {
|
|
759
|
-
sessionStorage.removeItem(AUTO_OPEN_LOCK_KEY);
|
|
760
|
-
onOpenChange(true);
|
|
761
|
-
} else {
|
|
762
|
-
sessionStorage.removeItem(AUTO_OPEN_LOCK_KEY);
|
|
763
|
-
}
|
|
764
|
-
}, 75);
|
|
765
|
-
|
|
766
|
-
return () => {
|
|
767
|
-
clearTimeout(timeoutId);
|
|
768
|
-
sessionStorage.removeItem(AUTO_OPEN_LOCK_KEY);
|
|
769
|
-
};
|
|
770
|
-
}
|
|
771
|
-
}, [persistenceKey, persistOpenState, persistedOpen, open, onOpenChange, wasRestored, clearDraft, dialogRef, userId, logger]);
|
|
772
|
-
|
|
773
|
-
// When this dialog auto-opens, clear persisted state of all other dialogs
|
|
774
|
-
// This prevents multiple dialogs from being restored simultaneously
|
|
775
|
-
useEffect(() => {
|
|
776
|
-
if (!persistenceKey || !persistOpenState || !open || !hasAutoOpenedRef.current) {
|
|
777
|
-
return;
|
|
778
|
-
}
|
|
779
|
-
|
|
780
|
-
// Only run once when dialog first auto-opens
|
|
781
|
-
if (hasCleanedUpOtherDialogsRef.current) {
|
|
782
|
-
return;
|
|
783
|
-
}
|
|
784
|
-
|
|
785
|
-
// Clear all other dialog persisted states from sessionStorage
|
|
786
|
-
// AND close any other dialogs that are currently open in the DOM
|
|
787
|
-
// This ensures only the first auto-opened dialog remains open
|
|
788
|
-
try {
|
|
789
|
-
const keysToRemove: string[] = [];
|
|
790
|
-
for (let i = 0; i < sessionStorage.length; i++) {
|
|
791
|
-
const key = sessionStorage.key(i);
|
|
792
|
-
if (key && key.startsWith('pace-core:draft:dialog:') && key.endsWith(':open')) {
|
|
793
|
-
// Don't clear this dialog's own state
|
|
794
|
-
if (key !== `pace-core:draft:${persistenceKey}:open`) {
|
|
795
|
-
keysToRemove.push(key);
|
|
796
|
-
}
|
|
797
|
-
}
|
|
798
|
-
}
|
|
799
|
-
|
|
800
|
-
if (keysToRemove.length > 0) {
|
|
801
|
-
logger.debug('[Dialog Persistence] Clearing other dialog persisted states:', keysToRemove);
|
|
802
|
-
keysToRemove.forEach(key => sessionStorage.removeItem(key));
|
|
803
|
-
}
|
|
804
|
-
|
|
805
|
-
// Also close any other dialogs that are currently open in the DOM AND have persisted state
|
|
806
|
-
// This prevents dialogs with persisted state from being hidden behind this one
|
|
807
|
-
// We only close dialogs that have persisted state, not dialogs opened by app code
|
|
808
|
-
// We identify dialogs with persistence using a data attribute
|
|
809
|
-
const timeoutId = setTimeout(() => {
|
|
810
|
-
// Guard against test environment teardown
|
|
811
|
-
if (typeof document === 'undefined' || typeof sessionStorage === 'undefined') {
|
|
812
|
-
return;
|
|
813
|
-
}
|
|
814
|
-
|
|
815
|
-
const otherOpenDialogs = document.querySelectorAll('dialog[open][role="dialog"]');
|
|
816
|
-
const currentDialog = dialogRef.current || internalRef.current;
|
|
817
|
-
if (otherOpenDialogs.length > 0 && currentDialog) {
|
|
818
|
-
let closedCount = 0;
|
|
819
|
-
otherOpenDialogs.forEach((dialog) => {
|
|
820
|
-
// Don't close this dialog
|
|
821
|
-
const dialogElement = dialog as HTMLDialogElement;
|
|
822
|
-
if (dialogElement !== currentDialog) {
|
|
823
|
-
// Check if this dialog has a data-persistence-key attribute
|
|
824
|
-
// This indicates it was auto-opened from persistence
|
|
825
|
-
const dialogPersistenceKey = dialogElement.getAttribute('data-persistence-key');
|
|
826
|
-
if (dialogPersistenceKey && dialogPersistenceKey !== persistenceKey) {
|
|
827
|
-
// Check if this dialog's persisted state is true
|
|
828
|
-
let hasPersistedState = false;
|
|
829
|
-
try {
|
|
830
|
-
const key = `pace-core:draft:${dialogPersistenceKey}:open`;
|
|
831
|
-
const stored = sessionStorage.getItem(key);
|
|
832
|
-
if (stored) {
|
|
833
|
-
const parsed = JSON.parse(stored);
|
|
834
|
-
if (parsed && parsed.data === true) {
|
|
835
|
-
hasPersistedState = true;
|
|
836
|
-
}
|
|
837
|
-
}
|
|
838
|
-
} catch {
|
|
839
|
-
// Invalid data - skip
|
|
840
|
-
}
|
|
841
|
-
|
|
842
|
-
// Only close if this dialog has persisted state (was auto-opened)
|
|
843
|
-
if (hasPersistedState) {
|
|
844
|
-
logger.debug('[Dialog Persistence] Closing other dialog with persisted state:', dialogPersistenceKey);
|
|
845
|
-
dialogElement.close();
|
|
846
|
-
closedCount++;
|
|
847
|
-
}
|
|
848
|
-
}
|
|
849
|
-
// If dialog doesn't have data-persistence-key, it was opened by app code - don't close it
|
|
850
|
-
}
|
|
851
|
-
});
|
|
852
|
-
if (closedCount > 0) {
|
|
853
|
-
logger.debug('[Dialog Persistence] Closed', closedCount, 'other dialog(s) with persisted state');
|
|
854
|
-
}
|
|
855
|
-
}
|
|
856
|
-
}, 100);
|
|
857
|
-
|
|
858
|
-
hasCleanedUpOtherDialogsRef.current = true;
|
|
859
|
-
|
|
860
|
-
// Also clear the auto-open lock
|
|
861
|
-
if (typeof sessionStorage !== 'undefined') {
|
|
862
|
-
sessionStorage.removeItem('pace-core:dialog:auto-open-lock');
|
|
863
|
-
}
|
|
864
|
-
|
|
865
|
-
// Cleanup timeout on unmount or dependency change
|
|
866
|
-
return () => {
|
|
867
|
-
clearTimeout(timeoutId);
|
|
868
|
-
};
|
|
869
|
-
} catch (error) {
|
|
870
|
-
logger.warn('[Dialog Persistence] Failed to clear other dialog states:', error);
|
|
871
|
-
}
|
|
872
|
-
}, [open, persistenceKey, persistOpenState, dialogRef, logger]);
|
|
873
|
-
|
|
874
|
-
// When dialog closes (user action), immediately clear persisted state
|
|
875
|
-
// This prevents the dialog from auto-opening again after user explicitly closed it
|
|
876
|
-
useEffect(() => {
|
|
877
|
-
if (!persistenceKey || !persistOpenState) {
|
|
878
|
-
return;
|
|
879
|
-
}
|
|
880
|
-
|
|
881
|
-
if (!hasInitializedRef.current) {
|
|
882
|
-
return;
|
|
883
|
-
}
|
|
884
|
-
|
|
885
|
-
// If dialog is closed and user closed it, clear persisted state immediately
|
|
886
|
-
if (!open && wasClosedByUserRef.current) {
|
|
887
|
-
clearDraft();
|
|
888
|
-
wasClosedByUserRef.current = false;
|
|
889
|
-
}
|
|
890
|
-
}, [open, persistenceKey, persistOpenState, clearDraft]);
|
|
891
|
-
|
|
892
|
-
// Check lock BEFORE allowing dialog to open (synchronous check)
|
|
893
|
-
// This prevents React from even trying to open if another dialog is open
|
|
894
|
-
// Track lock acquisition state for rendering decision
|
|
895
|
-
const [lockAcquired, setLockAcquired] = React.useState(false);
|
|
896
|
-
|
|
897
|
-
useEffect(() => {
|
|
898
|
-
if (!open) {
|
|
899
|
-
setLockAcquired(false);
|
|
900
|
-
return;
|
|
901
|
-
}
|
|
902
|
-
|
|
903
|
-
// Synchronously check if we can acquire the lock
|
|
904
|
-
const acquired = acquireDialogLock(persistenceKey);
|
|
905
|
-
setLockAcquired(acquired);
|
|
906
|
-
|
|
907
|
-
if (!acquired) {
|
|
908
|
-
// Another dialog is open - prevent this one from opening
|
|
909
|
-
logger.warn('[Dialog] ⚠️ Cannot open - another dialog holds the lock', {
|
|
910
|
-
persistenceKey,
|
|
911
|
-
});
|
|
912
|
-
// Immediately close this dialog's React state
|
|
913
|
-
onOpenChange?.(false);
|
|
914
|
-
return;
|
|
915
|
-
}
|
|
916
|
-
|
|
917
|
-
// Lock acquired successfully - dialog can proceed to open
|
|
918
|
-
}, [open, persistenceKey, onOpenChange, logger]);
|
|
919
|
-
|
|
920
|
-
// Track when dialog closes via onOpenChange to mark as closed by user
|
|
921
|
-
// This handles Cancel buttons and other programmatic closes
|
|
922
|
-
const previousOpenRef = useRef(open);
|
|
923
|
-
useEffect(() => {
|
|
924
|
-
// If dialog was open and is now closed, and it wasn't auto-opened, mark as closed by user
|
|
925
|
-
if (previousOpenRef.current === true && open === false && hasInitializedRef.current) {
|
|
926
|
-
// Only mark as closed by user if it wasn't an auto-open scenario
|
|
927
|
-
// Auto-open sets hasAutoOpenedRef before calling onOpenChange, so we can detect it
|
|
928
|
-
if (!hasAutoOpenedRef.current || wasManuallyOpenedRef.current) {
|
|
929
|
-
// Dialog was manually opened and then closed - mark as closed by user
|
|
930
|
-
wasClosedByUserRef.current = true;
|
|
931
|
-
}
|
|
932
|
-
}
|
|
933
|
-
previousOpenRef.current = open;
|
|
934
|
-
}, [open]);
|
|
935
|
-
|
|
936
|
-
// Persist open state changes
|
|
937
|
-
useEffect(() => {
|
|
938
|
-
if (!persistenceKey || !persistOpenState) {
|
|
939
|
-
return;
|
|
940
|
-
}
|
|
941
|
-
|
|
942
|
-
// Only persist after initial mount check is complete
|
|
943
|
-
// This prevents overwriting the persisted state before auto-open can read it
|
|
944
|
-
if (!hasInitializedRef.current) {
|
|
945
|
-
return;
|
|
946
|
-
}
|
|
406
|
+
} = props;
|
|
407
|
+
|
|
408
|
+
const { open, onOpenChange, dialogRef, titleId, descriptionId } = useDialogContext();
|
|
409
|
+
const setMarkClosedByUser = React.useContext(DialogMarkClosedContext);
|
|
410
|
+
|
|
411
|
+
const location = useLocation();
|
|
412
|
+
const auth = useUnifiedAuth();
|
|
413
|
+
const userId = auth.user?.id || null;
|
|
414
|
+
|
|
415
|
+
const logger = createLogger('Dialog');
|
|
416
|
+
|
|
417
|
+
const persistenceKey = useMemo(() => {
|
|
418
|
+
if (!persistOpenState) return null;
|
|
419
|
+
if (!userId) return null;
|
|
420
|
+
return deriveDialogKey({ title, description }, location, userId);
|
|
421
|
+
}, [title, description, location, userId, persistOpenState]);
|
|
422
|
+
|
|
423
|
+
const internalRef = useRef<HTMLDialogElement>(null);
|
|
424
|
+
|
|
425
|
+
const { lockAcquired, markClosedByUser, clearDraft } = useDialogPersistence({
|
|
426
|
+
open,
|
|
427
|
+
onOpenChange,
|
|
428
|
+
persistenceKey,
|
|
429
|
+
persistOpenState,
|
|
430
|
+
userId,
|
|
431
|
+
dialogRef,
|
|
432
|
+
internalRef,
|
|
433
|
+
setMarkClosedByUser,
|
|
434
|
+
logger,
|
|
435
|
+
});
|
|
947
436
|
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
wasClosedByUserRef.current = false;
|
|
952
|
-
// If dialog is manually opened (not via auto-open), mark it so auto-open doesn't interfere
|
|
953
|
-
// This prevents auto-open from trying to open an already-open dialog
|
|
954
|
-
// We check if hasAutoOpenedRef is false to determine if this is a manual open
|
|
955
|
-
// (auto-open sets hasAutoOpenedRef to true before calling onOpenChange)
|
|
956
|
-
if (!hasAutoOpenedRef.current) {
|
|
957
|
-
// Mark as manually opened to prevent auto-open from interfering
|
|
958
|
-
wasManuallyOpenedRef.current = true;
|
|
959
|
-
// Also mark as "opened" to prevent auto-open from trying to open it again
|
|
960
|
-
hasAutoOpenedRef.current = true;
|
|
961
|
-
}
|
|
962
|
-
setPersistedOpen(true);
|
|
963
|
-
} else {
|
|
964
|
-
// Only clear draft if user explicitly closed (not if it was never opened or auto-opened then closed)
|
|
965
|
-
if (wasClosedByUserRef.current) {
|
|
966
|
-
clearDraft();
|
|
967
|
-
wasClosedByUserRef.current = false;
|
|
968
|
-
// Reset manual open flag when dialog is closed
|
|
969
|
-
wasManuallyOpenedRef.current = false;
|
|
970
|
-
}
|
|
971
|
-
}
|
|
972
|
-
}, [open, persistenceKey, persistOpenState, setPersistedOpen, clearDraft]);
|
|
973
|
-
|
|
974
|
-
// Note: We do NOT automatically clear the draft when dialog closes
|
|
975
|
-
// The draft should only be cleared on explicit user actions (e.g., form submit success)
|
|
976
|
-
// This allows the dialog to restore its state after tab switches
|
|
977
|
-
const internalRef = useRef<HTMLDialogElement>(null);
|
|
978
|
-
|
|
979
|
-
// Use the dialogRef from context, or fall back to internal ref or forwarded ref
|
|
980
|
-
const actualDialogRef = dialogRef.current ? dialogRef : (ref ? (ref as React.RefObject<HTMLDialogElement>) : internalRef);
|
|
981
|
-
|
|
982
|
-
// Default to 80% viewport height if no height constraint is provided
|
|
983
|
-
// This allows the dialog to grow to 80% before enabling scrolling
|
|
984
|
-
const effectiveMaxHeightPercent = maxHeightPercent ?? (maxHeight ? undefined : 80);
|
|
985
|
-
|
|
986
|
-
// Determine if we have a height constraint that requires flex layout
|
|
987
|
-
const hasHeightConstraint = Boolean(effectiveMaxHeightPercent || maxHeight);
|
|
988
|
-
|
|
989
|
-
const smartDimensions = useSmartDimensions({
|
|
990
|
-
maxHeightPercent: effectiveMaxHeightPercent,
|
|
437
|
+
const { sizeClass, mergedStyle, hasHeightConstraint } = useDialogDimensions({
|
|
438
|
+
size,
|
|
439
|
+
maxHeightPercent,
|
|
991
440
|
maxWidthPercent,
|
|
992
|
-
maxHeight,
|
|
441
|
+
maxHeight,
|
|
993
442
|
maxWidth,
|
|
994
443
|
minHeight,
|
|
995
|
-
minWidth
|
|
444
|
+
minWidth,
|
|
445
|
+
enableScrolling,
|
|
446
|
+
style,
|
|
996
447
|
});
|
|
997
448
|
|
|
998
449
|
// Focus trap
|
|
@@ -1003,255 +454,114 @@ const DialogContent = React.forwardRef<HTMLDialogElement, DialogContentProps>(
|
|
|
1003
454
|
onEscape: preventCloseOnEscape ? undefined : () => onOpenChange(false),
|
|
1004
455
|
});
|
|
1005
456
|
|
|
1006
|
-
// Merge refs
|
|
1007
|
-
const mergedRef =
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
}
|
|
1012
|
-
// Set internal ref
|
|
1013
|
-
if (internalRef && 'current' in internalRef) {
|
|
1014
|
-
internalRef.current = node;
|
|
1015
|
-
}
|
|
1016
|
-
// Set focus trap container ref
|
|
1017
|
-
if (containerRef && 'current' in containerRef) {
|
|
1018
|
-
(containerRef as React.MutableRefObject<HTMLElement | null>).current = node;
|
|
1019
|
-
}
|
|
1020
|
-
// Handle forwarded ref
|
|
1021
|
-
if (typeof ref === 'function') {
|
|
1022
|
-
ref(node);
|
|
1023
|
-
} else if (ref && 'current' in ref) {
|
|
1024
|
-
(ref as React.MutableRefObject<HTMLDialogElement | null>).current = node;
|
|
1025
|
-
}
|
|
1026
|
-
}, [dialogRef, containerRef, ref]);
|
|
1027
|
-
|
|
1028
|
-
// Handle dialog open/close
|
|
1029
|
-
useEffect(() => {
|
|
1030
|
-
const dialog = dialogRef.current || internalRef.current;
|
|
1031
|
-
if (!dialog) return;
|
|
1032
|
-
|
|
1033
|
-
if (open) {
|
|
1034
|
-
// Log all dialogs in DOM before opening
|
|
1035
|
-
const allDialogsBefore = document.querySelectorAll('dialog[role="dialog"]');
|
|
1036
|
-
const dialogsBefore = Array.from(allDialogsBefore).map((d) => {
|
|
1037
|
-
const dialogEl = d as HTMLDialogElement;
|
|
1038
|
-
return {
|
|
1039
|
-
persistenceKey: dialogEl.getAttribute('data-persistence-key') || 'NO-KEY',
|
|
1040
|
-
open: dialogEl.open,
|
|
1041
|
-
isCurrent: d === dialog,
|
|
1042
|
-
};
|
|
1043
|
-
});
|
|
1044
|
-
logger.debug('[Dialog] 🟢 OPENING', {
|
|
1045
|
-
persistenceKey,
|
|
1046
|
-
dialogsInDOM: dialogsBefore,
|
|
1047
|
-
totalDialogs: allDialogsBefore.length,
|
|
1048
|
-
});
|
|
1049
|
-
|
|
1050
|
-
// Use requestAnimationFrame to ensure DOM is ready
|
|
1051
|
-
// Lock was already checked in the earlier useEffect, so we can proceed
|
|
1052
|
-
requestAnimationFrame(() => {
|
|
1053
|
-
if (dialog && open) {
|
|
1054
|
-
// Check if dialog is connected to DOM before attempting to open
|
|
1055
|
-
if (!dialog.isConnected) {
|
|
1056
|
-
logger.warn('[Dialog] ⚠️ Dialog not connected to DOM, skipping showModal()', { persistenceKey });
|
|
1057
|
-
return;
|
|
1058
|
-
}
|
|
1059
|
-
|
|
1060
|
-
// Check if dialog is already open - if so, skip showModal() call
|
|
1061
|
-
// This prevents "Cannot call showModal() on an open non-modal dialog" error
|
|
1062
|
-
if (dialog.open) {
|
|
1063
|
-
logger.debug('[Dialog] ⏭️ Dialog already open, skipping showModal()', { persistenceKey });
|
|
1064
|
-
return;
|
|
1065
|
-
}
|
|
1066
|
-
|
|
1067
|
-
// Before opening, close any other open dialogs (safety check)
|
|
1068
|
-
const allDialogs = document.querySelectorAll('dialog[role="dialog"]');
|
|
1069
|
-
allDialogs.forEach((d) => {
|
|
1070
|
-
const dialogEl = d as HTMLDialogElement;
|
|
1071
|
-
if (dialogEl !== dialog && dialogEl.open) {
|
|
1072
|
-
dialogEl.setAttribute('data-duplicate-cleanup', 'true');
|
|
1073
|
-
dialogEl.close();
|
|
1074
|
-
}
|
|
1075
|
-
});
|
|
1076
|
-
|
|
1077
|
-
logger.debug('[Dialog] ✅ showModal() called', { persistenceKey });
|
|
1078
|
-
dialog.showModal();
|
|
1079
|
-
}
|
|
1080
|
-
});
|
|
1081
|
-
} else {
|
|
1082
|
-
// Close dialog before it's removed from DOM
|
|
1083
|
-
if (dialog.open) {
|
|
1084
|
-
logger.debug('[Dialog] 🔴 CLOSING', { persistenceKey });
|
|
1085
|
-
dialog.close();
|
|
1086
|
-
// Release the lock
|
|
1087
|
-
releaseDialogLock(persistenceKey);
|
|
1088
|
-
|
|
1089
|
-
// After closing, check if any other dialogs with persistence are trying to open
|
|
1090
|
-
// Only close dialogs that have persistence (data-persistence-key attribute)
|
|
1091
|
-
// Non-persistent dialogs should be left alone
|
|
1092
|
-
setTimeout(() => {
|
|
1093
|
-
const allDialogs = document.querySelectorAll('dialog[role="dialog"]');
|
|
1094
|
-
allDialogs.forEach((d) => {
|
|
1095
|
-
const dialogEl = d as HTMLDialogElement;
|
|
1096
|
-
if (dialogEl !== dialog && dialogEl.open) {
|
|
1097
|
-
const otherPersistenceKey = dialogEl.getAttribute('data-persistence-key');
|
|
1098
|
-
// Only close dialogs that have persistence (they might auto-open)
|
|
1099
|
-
// Non-persistent dialogs are user-controlled and shouldn't be closed
|
|
1100
|
-
if (otherPersistenceKey) {
|
|
1101
|
-
logger.warn('[Dialog] 🗑️ Closing other persisted dialog after lock release:', {
|
|
1102
|
-
persistenceKey,
|
|
1103
|
-
otherPersistenceKey,
|
|
1104
|
-
});
|
|
1105
|
-
dialogEl.setAttribute('data-duplicate-cleanup', 'true');
|
|
1106
|
-
dialogEl.close();
|
|
1107
|
-
}
|
|
1108
|
-
}
|
|
1109
|
-
});
|
|
1110
|
-
}, 50);
|
|
1111
|
-
}
|
|
1112
|
-
}
|
|
1113
|
-
}, [open, persistenceKey, dialogRef, logger]);
|
|
1114
|
-
|
|
1115
|
-
// Handle close event - sync state when dialog is closed externally
|
|
1116
|
-
// Also track when dialog is closed by user action (for persistence clearing)
|
|
1117
|
-
useEffect(() => {
|
|
1118
|
-
const dialog = dialogRef.current || internalRef.current;
|
|
1119
|
-
if (!dialog) return;
|
|
1120
|
-
|
|
1121
|
-
const handleClose = () => {
|
|
1122
|
-
// Check if this close was initiated by the user (via close button)
|
|
1123
|
-
const wasUserClosed = dialog.hasAttribute('data-user-closed');
|
|
1124
|
-
if (wasUserClosed) {
|
|
1125
|
-
dialog.removeAttribute('data-user-closed');
|
|
1126
|
-
if (hasInitializedRef.current) {
|
|
1127
|
-
wasClosedByUserRef.current = true;
|
|
1128
|
-
}
|
|
1129
|
-
}
|
|
1130
|
-
|
|
1131
|
-
// Ignore duplicate cleanup closes
|
|
1132
|
-
const isDuplicateCleanup = dialog.hasAttribute('data-duplicate-cleanup');
|
|
1133
|
-
if (isDuplicateCleanup) {
|
|
1134
|
-
dialog.removeAttribute('data-duplicate-cleanup');
|
|
1135
|
-
return;
|
|
1136
|
-
}
|
|
1137
|
-
|
|
1138
|
-
if (!dialog.open && open) {
|
|
1139
|
-
// Mark as closed by user if this wasn't an auto-open scenario
|
|
1140
|
-
if (hasInitializedRef.current && !wasUserClosed) {
|
|
1141
|
-
wasClosedByUserRef.current = true;
|
|
1142
|
-
}
|
|
1143
|
-
onOpenChange(false);
|
|
1144
|
-
} else if (!dialog.open && !open && hasInitializedRef.current && wasUserClosed) {
|
|
1145
|
-
wasClosedByUserRef.current = true;
|
|
1146
|
-
}
|
|
1147
|
-
};
|
|
1148
|
-
|
|
1149
|
-
dialog.addEventListener('close', handleClose);
|
|
1150
|
-
return () => {
|
|
1151
|
-
dialog.removeEventListener('close', handleClose);
|
|
1152
|
-
};
|
|
1153
|
-
}, [open, onOpenChange, dialogRef]);
|
|
1154
|
-
|
|
1155
|
-
// Handle cancel event (Escape or backdrop click)
|
|
1156
|
-
useEffect(() => {
|
|
1157
|
-
const dialog = dialogRef.current || internalRef.current;
|
|
1158
|
-
if (!dialog) return;
|
|
1159
|
-
|
|
1160
|
-
const handleCancel = (e: Event) => {
|
|
1161
|
-
if (preventCloseOnEscape || preventCloseOnOutsideClick) {
|
|
1162
|
-
e.preventDefault();
|
|
1163
|
-
return;
|
|
1164
|
-
}
|
|
1165
|
-
// Mark as closed by user and clear persisted state
|
|
1166
|
-
wasClosedByUserRef.current = true;
|
|
1167
|
-
if (persistenceKey && persistOpenState && clearDraft) {
|
|
1168
|
-
clearDraft();
|
|
1169
|
-
}
|
|
1170
|
-
onOpenChange(false);
|
|
1171
|
-
};
|
|
1172
|
-
|
|
1173
|
-
dialog.addEventListener('cancel', handleCancel);
|
|
1174
|
-
return () => {
|
|
1175
|
-
dialog.removeEventListener('cancel', handleCancel);
|
|
1176
|
-
};
|
|
1177
|
-
}, [preventCloseOnEscape, preventCloseOnOutsideClick, onOpenChange, dialogRef, persistenceKey, persistOpenState, clearDraft]);
|
|
1178
|
-
|
|
1179
|
-
// Merge smart dimensions with provided style
|
|
1180
|
-
const mergedStyle = React.useMemo(() => {
|
|
1181
|
-
if (Object.keys(smartDimensions).length === 0) {
|
|
1182
|
-
return style;
|
|
1183
|
-
}
|
|
457
|
+
// Merge refs (avoids type assertions; mergeRefs handles RefObject and callback refs)
|
|
458
|
+
const mergedRef = useMemo(
|
|
459
|
+
() => mergeRefs(dialogRef, internalRef, containerRef, ref),
|
|
460
|
+
[dialogRef, containerRef, ref]
|
|
461
|
+
);
|
|
1184
462
|
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
return finalStyle;
|
|
1200
|
-
}, [smartDimensions, style, maxWidth, maxWidthPercent, enableScrolling, maxHeight, maxHeightPercent]);
|
|
463
|
+
useDialogLifecycle({
|
|
464
|
+
dialogRef,
|
|
465
|
+
internalRef,
|
|
466
|
+
open,
|
|
467
|
+
persistenceKey,
|
|
468
|
+
logger,
|
|
469
|
+
onOpenChange,
|
|
470
|
+
markClosedByUser,
|
|
471
|
+
preventCloseOnEscape,
|
|
472
|
+
preventCloseOnOutsideClick,
|
|
473
|
+
persistOpenState,
|
|
474
|
+
clearDraft,
|
|
475
|
+
});
|
|
1201
476
|
|
|
1202
|
-
// Synchronously check if we can render (must hold lock if open)
|
|
1203
477
|
const canRender = React.useMemo(() => {
|
|
1204
|
-
if (!open)
|
|
1205
|
-
|
|
1206
|
-
}
|
|
1207
|
-
if (!persistenceKey) {
|
|
1208
|
-
return true; // Non-persisted dialogs can always render
|
|
1209
|
-
}
|
|
1210
|
-
// Use the lockAcquired state which is set by the effect
|
|
478
|
+
if (!open) return true;
|
|
479
|
+
if (!persistenceKey) return true;
|
|
1211
480
|
return lockAcquired;
|
|
1212
481
|
}, [open, persistenceKey, lockAcquired]);
|
|
1213
482
|
|
|
483
|
+
return {
|
|
484
|
+
mergedRef,
|
|
485
|
+
canRender,
|
|
486
|
+
markClosedByUser,
|
|
487
|
+
sizeClass,
|
|
488
|
+
mergedStyle: mergedStyle ?? {},
|
|
489
|
+
hasHeightConstraint,
|
|
490
|
+
persistenceKey,
|
|
491
|
+
persistOpenState,
|
|
492
|
+
titleId,
|
|
493
|
+
descriptionId,
|
|
494
|
+
open,
|
|
495
|
+
title,
|
|
496
|
+
description,
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/**
|
|
501
|
+
* DialogContent component
|
|
502
|
+
* The main content container using semantic HTML <dialog> element with enhanced features.
|
|
503
|
+
* Inline style exception (5-styling): viewport-based max/min dimensions from props are applied
|
|
504
|
+
* via the style prop; they cannot be expressed with static Tailwind and are merged with optional consumer style.
|
|
505
|
+
*
|
|
506
|
+
* @param props - Content configuration and styling
|
|
507
|
+
* @param ref - Forwarded ref to the dialog element
|
|
508
|
+
* @returns JSX.Element - The semantic dialog content with overlay and optional close button
|
|
509
|
+
*/
|
|
510
|
+
const DialogContent = (React.forwardRef<HTMLDialogElement, DialogContentProps>)(
|
|
511
|
+
function DialogContentInner(props, ref) {
|
|
512
|
+
const {
|
|
513
|
+
className,
|
|
514
|
+
children,
|
|
515
|
+
size = 'md',
|
|
516
|
+
showCloseButton = true,
|
|
517
|
+
maxHeightPercent,
|
|
518
|
+
maxWidthPercent,
|
|
519
|
+
enableScrolling = false,
|
|
520
|
+
maxHeight,
|
|
521
|
+
maxWidth,
|
|
522
|
+
minHeight,
|
|
523
|
+
minWidth,
|
|
524
|
+
style: _styleProp,
|
|
525
|
+
title: _titleProp,
|
|
526
|
+
description: _descriptionProp,
|
|
527
|
+
persistOpenState: _persistOpenStateProp,
|
|
528
|
+
preventCloseOnEscape: _preventCloseOnEscape,
|
|
529
|
+
preventCloseOnOutsideClick: _preventCloseOnOutsideClick,
|
|
530
|
+
...restProps
|
|
531
|
+
} = props;
|
|
532
|
+
|
|
533
|
+
const state = useDialogContentState(props, ref);
|
|
534
|
+
|
|
1214
535
|
return (
|
|
1215
536
|
<DialogPortal>
|
|
1216
|
-
{open && canRender && (
|
|
537
|
+
{state.open && state.canRender && (
|
|
1217
538
|
<dialog
|
|
1218
|
-
ref={mergedRef}
|
|
539
|
+
ref={state.mergedRef}
|
|
1219
540
|
className={cn(
|
|
1220
541
|
'fixed left-[50%] top-[50%] z-[51] w-full translate-x-[-50%] translate-y-[-50%] border bg-background shadow-lg duration-200',
|
|
1221
542
|
'animate-in fade-in-0 zoom-in-95 slide-in-from-left-1/2 slide-in-from-top-[48%]',
|
|
1222
543
|
'sm:rounded-lg',
|
|
1223
|
-
// Reset native dialog styles
|
|
1224
544
|
'm-0 p-0 max-w-none max-h-none border-0 bg-transparent outline-none',
|
|
1225
|
-
// When maxWidthPercent is set, use w-full to expand to the constraint (not w-auto)
|
|
1226
|
-
// When maxWidthPercent is not set, use w-auto to size to content
|
|
1227
545
|
(maxWidth || maxWidthPercent) ? 'w-full' : 'w-auto h-auto',
|
|
1228
|
-
// Apply our custom styling
|
|
1229
546
|
'border bg-background shadow-lg',
|
|
1230
|
-
|
|
1231
|
-
// Only apply size classes if not using smart width
|
|
1232
|
-
!maxWidth && !maxWidthPercent && sizeClasses[size],
|
|
1233
|
-
// Auto size gets special handling
|
|
547
|
+
!maxWidth && !maxWidthPercent && state.sizeClass,
|
|
1234
548
|
size === 'auto' && 'w-fit max-w-[90vw] sm:max-w-[80vw]',
|
|
1235
|
-
|
|
1236
|
-
// Flex layout is needed for proper scrolling when height is constrained
|
|
1237
|
-
(enableScrolling || hasHeightConstraint) ? 'flex flex-col p-6' : 'grid p-6',
|
|
1238
|
-
// Full screen handling
|
|
549
|
+
(enableScrolling || state.hasHeightConstraint) ? 'flex flex-col p-6' : 'grid p-6',
|
|
1239
550
|
size === 'full' && 'sm:left-[50%] sm:top-[50%] sm:translate-x-[-50%] sm:translate-y-[-50%] left-0 top-0 translate-x-0 translate-y-0 h-full rounded-none sm:h-auto sm:rounded-lg',
|
|
1240
|
-
|
|
1241
|
-
(enableScrolling || hasHeightConstraint) && 'overflow-hidden',
|
|
551
|
+
(enableScrolling || state.hasHeightConstraint) && 'overflow-hidden',
|
|
1242
552
|
className
|
|
1243
553
|
)}
|
|
1244
|
-
style={mergedStyle}
|
|
554
|
+
style={state.mergedStyle}
|
|
1245
555
|
role="dialog"
|
|
1246
556
|
aria-modal="true"
|
|
1247
|
-
aria-labelledby={titleId}
|
|
1248
|
-
aria-describedby={descriptionId}
|
|
1249
|
-
title={title}
|
|
1250
|
-
aria-description={description}
|
|
1251
|
-
data-persistence-key={persistenceKey && persistOpenState ? persistenceKey : undefined}
|
|
1252
|
-
{...
|
|
557
|
+
aria-labelledby={state.titleId}
|
|
558
|
+
aria-describedby={state.descriptionId}
|
|
559
|
+
title={state.title}
|
|
560
|
+
aria-description={state.description}
|
|
561
|
+
data-persistence-key={state.persistenceKey && state.persistOpenState ? state.persistenceKey : undefined}
|
|
562
|
+
{...restProps}
|
|
1253
563
|
>
|
|
1254
|
-
<DialogCloseContext.Provider value={markClosedByUser}>
|
|
564
|
+
<DialogCloseContext.Provider value={state.markClosedByUser}>
|
|
1255
565
|
{children}
|
|
1256
566
|
{showCloseButton && (
|
|
1257
567
|
<DialogClose />
|
|
@@ -1280,48 +590,38 @@ export interface DialogCloseProps extends React.ButtonHTMLAttributes<HTMLButtonE
|
|
|
1280
590
|
*/
|
|
1281
591
|
const DialogClose = React.forwardRef<HTMLButtonElement, DialogCloseProps>(
|
|
1282
592
|
({ className, asChild = false, children, onClick, ...props }, ref) => {
|
|
1283
|
-
// Call all hooks unconditionally at the top level
|
|
1284
|
-
// Hooks must be called in the same order on every render
|
|
1285
593
|
const { onOpenChange, markClosedByUser: contextMarkClosedByUser } = useDialogContext();
|
|
1286
|
-
// Prefer DialogContext markClosedByUser (available to all components), fallback to DialogCloseContext (for backwards compatibility)
|
|
1287
594
|
const dialogCloseContextValue = React.useContext(DialogCloseContext);
|
|
1288
|
-
const markClosedByUser = contextMarkClosedByUser
|
|
1289
|
-
|
|
1290
|
-
const handleClick = useCallback((e: React.MouseEvent<
|
|
1291
|
-
// Mark dialog as closed by user before calling onOpenChange
|
|
1292
|
-
// This ensures the persisted state is cleared when user clicks close button
|
|
595
|
+
const markClosedByUser = contextMarkClosedByUser ?? dialogCloseContextValue;
|
|
596
|
+
|
|
597
|
+
const handleClick = useCallback((e: React.MouseEvent<HTMLButtonElement>) => {
|
|
1293
598
|
if (markClosedByUser) {
|
|
1294
599
|
markClosedByUser();
|
|
1295
600
|
}
|
|
1296
|
-
|
|
1297
|
-
onClick?.(e as React.MouseEvent<HTMLButtonElement>);
|
|
601
|
+
onClick?.(e);
|
|
1298
602
|
onOpenChange(false);
|
|
1299
603
|
}, [onOpenChange, markClosedByUser, onClick]);
|
|
1300
604
|
|
|
1301
605
|
if (asChild && React.isValidElement(children)) {
|
|
1302
|
-
const childElement = children as React.ReactElement<React.HTMLAttributes<
|
|
606
|
+
const childElement = children as React.ReactElement<React.HTMLAttributes<HTMLButtonElement>>;
|
|
1303
607
|
return React.cloneElement(childElement, {
|
|
1304
608
|
ref,
|
|
1305
609
|
onClick: handleClick,
|
|
1306
610
|
className: cn(className, childElement.props?.className),
|
|
1307
611
|
...props,
|
|
1308
|
-
} as
|
|
612
|
+
} as React.HTMLAttributes<HTMLButtonElement> & React.RefAttributes<HTMLButtonElement>);
|
|
1309
613
|
}
|
|
1310
614
|
|
|
1311
615
|
return (
|
|
1312
|
-
<
|
|
616
|
+
<IconButton
|
|
1313
617
|
ref={ref}
|
|
618
|
+
icon={<X className="size-4" />}
|
|
619
|
+
aria-label="Close"
|
|
1314
620
|
type="button"
|
|
1315
621
|
onClick={handleClick}
|
|
1316
|
-
className={cn(
|
|
1317
|
-
'absolute right-4 top-4 z-10 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none',
|
|
1318
|
-
className
|
|
1319
|
-
)}
|
|
622
|
+
className={cn('absolute right-4 top-4 z-10', className)}
|
|
1320
623
|
{...props}
|
|
1321
|
-
|
|
1322
|
-
<X className="size-4" />
|
|
1323
|
-
<span className="sr-only">Close</span>
|
|
1324
|
-
</button>
|
|
624
|
+
/>
|
|
1325
625
|
);
|
|
1326
626
|
}
|
|
1327
627
|
);
|
|
@@ -1337,11 +637,7 @@ const DialogHeader = ({
|
|
|
1337
637
|
...props
|
|
1338
638
|
}: DialogHeaderProps) => (
|
|
1339
639
|
<header
|
|
1340
|
-
className={cn(
|
|
1341
|
-
'flex flex-col space-y-1.5 text-center sm:text-left mb-4',
|
|
1342
|
-
sticky && 'sticky top-0 z-10 bg-background',
|
|
1343
|
-
className
|
|
1344
|
-
)}
|
|
640
|
+
className={cn('dialog-header', sticky && 'sticky top-0 z-10 bg-background', className)}
|
|
1345
641
|
{...props}
|
|
1346
642
|
/>
|
|
1347
643
|
);
|
|
@@ -1361,6 +657,7 @@ const DialogBody = ({
|
|
|
1361
657
|
children,
|
|
1362
658
|
...props
|
|
1363
659
|
}: DialogBodyProps) => {
|
|
660
|
+
// Inline style exception (5-styling): maxHeight and style from props; no fixed token set.
|
|
1364
661
|
const mergedStyle = React.useMemo(() => {
|
|
1365
662
|
return {
|
|
1366
663
|
...(maxHeight && { maxHeight }),
|
|
@@ -1428,14 +725,14 @@ const DialogBody = ({
|
|
|
1428
725
|
{...props}
|
|
1429
726
|
>
|
|
1430
727
|
{processedHtmlContent ? (
|
|
1431
|
-
<p
|
|
728
|
+
<p
|
|
1432
729
|
dangerouslySetInnerHTML={{ __html: processedHtmlContent }}
|
|
1433
|
-
className="
|
|
730
|
+
className="dialog-body-html-content"
|
|
1434
731
|
/>
|
|
1435
732
|
) : (
|
|
1436
733
|
<>
|
|
1437
734
|
{hasHtmlContent && !processedHtmlContent && (
|
|
1438
|
-
<p className="
|
|
735
|
+
<p className="dialog-body-fallback">
|
|
1439
736
|
No HTML content processed. Showing children instead.
|
|
1440
737
|
</p>
|
|
1441
738
|
)}
|
|
@@ -1457,12 +754,7 @@ const DialogFooter = ({
|
|
|
1457
754
|
...props
|
|
1458
755
|
}: DialogFooterProps) => (
|
|
1459
756
|
<footer
|
|
1460
|
-
className={cn(
|
|
1461
|
-
!className && 'flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2',
|
|
1462
|
-
'mt-4',
|
|
1463
|
-
sticky && 'sticky bottom-0 z-10 bg-background',
|
|
1464
|
-
className
|
|
1465
|
-
)}
|
|
757
|
+
className={cn('dialog-footer', sticky && 'sticky bottom-0 z-10 bg-background', className)}
|
|
1466
758
|
{...props}
|
|
1467
759
|
/>
|
|
1468
760
|
);
|