@oneuptime/common 12.0.5 → 12.0.6
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/Models/DatabaseModels/AIRun.ts +33 -0
- package/Models/DatabaseModels/DataSource.ts +744 -0
- package/Models/DatabaseModels/Index.ts +3 -0
- package/Models/DatabaseModels/ProjectCallSMSConfig.ts +10 -2
- package/Models/DatabaseModels/User.ts +2 -0
- package/Models/DatabaseModels/UserOnCallLog.ts +2 -0
- package/Models/DatabaseModels/UserOnCallLogTimeline.ts +2 -0
- package/Models/DatabaseModels/UserSession.ts +2 -0
- package/Models/DatabaseModels/UserTotpAuth.ts +6 -4
- package/Models/DatabaseModels/UserWebAuthn.ts +5 -3
- package/Server/API/AIInsightAPI.ts +47 -4
- package/Server/API/AIInvestigationAPI.ts +25 -0
- package/Server/API/DashboardAPI.ts +176 -492
- package/Server/API/DataSourceAPI.ts +268 -0
- package/Server/API/StatusPageAPI.ts +11 -1
- package/Server/API/UserAPI.ts +119 -0
- package/Server/Infrastructure/ClickhouseConfig.ts +59 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786303472848-AddDataSourceTable.ts +39 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786600000000-AddInvestigationAnalysisTldr.ts +24 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786700000000-DropProjectCallSMSConfigCredentialUniques.ts +76 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
- package/Server/Infrastructure/Queue.ts +26 -0
- package/Server/Infrastructure/QueueWorker.ts +17 -0
- package/Server/Middleware/TelemetryIngest.ts +8 -3
- package/Server/Services/AIInsightService.ts +132 -12
- package/Server/Services/AIRunService.ts +34 -0
- package/Server/Services/AIService.ts +17 -2
- package/Server/Services/AlertService.ts +38 -32
- package/Server/Services/AnalyticsDatabaseService.ts +8 -4
- package/Server/Services/DataSourceService.ts +200 -0
- package/Server/Services/HostService.ts +92 -0
- package/Server/Services/IncidentService.ts +45 -0
- package/Server/Services/Index.ts +2 -0
- package/Server/Services/MonitorService.ts +49 -0
- package/Server/Services/MonitorStatusService.ts +166 -0
- package/Server/Services/OpenTelemetryIngestService.ts +255 -184
- package/Server/Services/RumSessionPinService.ts +7 -21
- package/Server/Services/StatusPageSubscriberService.ts +13 -0
- package/Server/Services/UserService.ts +280 -9
- package/Server/Static/Vendor/README.md +62 -0
- package/Server/Static/Vendor/fonts/InterVariable.woff2 +0 -0
- package/Server/Static/Vendor/highlight/highlight.min.js +1244 -0
- package/Server/Static/Vendor/highlight/languages/apache.min.js +15 -0
- package/Server/Static/Vendor/highlight/languages/bash.min.js +21 -0
- package/Server/Static/Vendor/highlight/languages/c.min.js +41 -0
- package/Server/Static/Vendor/highlight/languages/cpp.min.js +47 -0
- package/Server/Static/Vendor/highlight/languages/csharp.min.js +49 -0
- package/Server/Static/Vendor/highlight/languages/css.min.js +31 -0
- package/Server/Static/Vendor/highlight/languages/diff.min.js +9 -0
- package/Server/Static/Vendor/highlight/languages/dns.min.js +11 -0
- package/Server/Static/Vendor/highlight/languages/dockerfile.min.js +8 -0
- package/Server/Static/Vendor/highlight/languages/go.min.js +20 -0
- package/Server/Static/Vendor/highlight/languages/graphql.min.js +12 -0
- package/Server/Static/Vendor/highlight/languages/http.min.js +14 -0
- package/Server/Static/Vendor/highlight/languages/ini.min.js +15 -0
- package/Server/Static/Vendor/highlight/languages/java.min.js +38 -0
- package/Server/Static/Vendor/highlight/languages/javascript.min.js +81 -0
- package/Server/Static/Vendor/highlight/languages/json.min.js +8 -0
- package/Server/Static/Vendor/highlight/languages/kotlin.min.js +46 -0
- package/Server/Static/Vendor/highlight/languages/lua.min.js +15 -0
- package/Server/Static/Vendor/highlight/languages/makefile.min.js +14 -0
- package/Server/Static/Vendor/highlight/languages/nginx.min.js +21 -0
- package/Server/Static/Vendor/highlight/languages/perl.min.js +41 -0
- package/Server/Static/Vendor/highlight/languages/php.min.js +59 -0
- package/Server/Static/Vendor/highlight/languages/powershell.min.js +39 -0
- package/Server/Static/Vendor/highlight/languages/python.min.js +42 -0
- package/Server/Static/Vendor/highlight/languages/r.min.js +26 -0
- package/Server/Static/Vendor/highlight/languages/ruby.min.js +54 -0
- package/Server/Static/Vendor/highlight/languages/rust.min.js +27 -0
- package/Server/Static/Vendor/highlight/languages/scala.min.js +28 -0
- package/Server/Static/Vendor/highlight/languages/sql.min.js +21 -0
- package/Server/Static/Vendor/highlight/languages/swift.min.js +68 -0
- package/Server/Static/Vendor/highlight/languages/typescript.min.js +99 -0
- package/Server/Static/Vendor/highlight/languages/xml.min.js +29 -0
- package/Server/Static/Vendor/highlight/languages/yaml.min.js +28 -0
- package/Server/Static/Vendor/highlight/styles/github-dark.min.css +10 -0
- package/Server/Static/Vendor/highlight/styles/vs2015.min.css +1 -0
- package/Server/Static/Vendor/tailwind/tailwind-3.4.5.js +21028 -0
- package/Server/Types/Database/Permissions/BasePermission.ts +7 -0
- package/Server/Types/Database/Permissions/DeletePermission.ts +2 -0
- package/Server/Types/Database/Permissions/ReadPermission.ts +3 -0
- package/Server/Types/Database/Permissions/TenantPermission.ts +101 -16
- package/Server/Utils/AI/CodeFix/FixRunBudget.ts +2 -2
- package/Server/Utils/AI/SRE/AIInvestigationEngine.ts +90 -11
- package/Server/Utils/AI/SRE/AlertInvestigationRunner.ts +1 -0
- package/Server/Utils/AI/SRE/IncidentInvestigationRunner.ts +1 -0
- package/Server/Utils/AI/SRE/Insights/Detectors/ExceptionIdentity.ts +125 -0
- package/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.ts +25 -15
- package/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.ts +256 -57
- package/Server/Utils/AI/SRE/Insights/InsightStore.ts +76 -18
- package/Server/Utils/AI/SRE/InvestigationTldr.ts +352 -0
- package/Server/Utils/AnalyticsDatabase/InsertDedupContext.ts +7 -2
- package/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.ts +1793 -0
- package/Server/Utils/Dashboard/PublicDashboardViewConfig.ts +65 -0
- package/Server/Utils/DataSource/ConnectorRegistry.ts +53 -0
- package/Server/Utils/DataSource/Connectors/ClickHouseConnector.ts +338 -0
- package/Server/Utils/DataSource/Connectors/ElasticsearchConnector.ts +717 -0
- package/Server/Utils/DataSource/Connectors/LokiConnector.ts +606 -0
- package/Server/Utils/DataSource/Connectors/MySqlConnector.ts +307 -0
- package/Server/Utils/DataSource/Connectors/PostgresConnector.ts +260 -0
- package/Server/Utils/DataSource/Connectors/PrometheusConnector.ts +555 -0
- package/Server/Utils/DataSource/Connectors/RestApiConnector.ts +597 -0
- package/Server/Utils/DataSource/Connectors/SqlServerConnector.ts +318 -0
- package/Server/Utils/DataSource/EgressGuard.ts +446 -0
- package/Server/Utils/DataSource/HttpFetch.ts +221 -0
- package/Server/Utils/DataSource/SqlQueryGuard.ts +383 -0
- package/Server/Utils/DataSource/SqlResultShaper.ts +372 -0
- package/Server/Utils/DataSource/Types.ts +93 -0
- package/Server/Utils/Database/PostgresErrorTranslator.ts +172 -17
- package/Server/Utils/InProcessMemo.ts +141 -0
- package/Server/Utils/InstanceHealth/TelemetryIngestion.ts +628 -0
- package/Server/Utils/Monitor/MonitorMetricUtil.ts +58 -0
- package/Server/Utils/Monitor/MonitorResource.ts +14 -0
- package/Server/Utils/Response.ts +12 -1
- package/Server/Utils/SSRFProtection.ts +237 -0
- package/Server/Utils/StartServer.ts +8 -0
- package/Server/Utils/StatusPageSubscriberWebhook.ts +30 -0
- package/Server/Utils/Telemetry/CaptureSpan.ts +30 -18
- package/Server/Utils/Telemetry/IngestionTimestamp.ts +75 -0
- package/Server/Utils/Telemetry/ResourceHeartbeat.ts +99 -7
- package/Server/Utils/Telemetry/Telemetry.ts +112 -1
- package/Server/Utils/Telemetry.ts +104 -3
- package/Server/Utils/VendorAssets.ts +165 -0
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +28 -5
- package/Server/Utils/Workspace/Slack/Slack.ts +5 -0
- package/Server/Views/Partials/Head.ejs +21 -7
- package/Tests/App/AdminDashboard/AdminProjectsIdFilter.test.tsx +207 -0
- package/Tests/App/AdminDashboard/AdminUsersIdFilter.test.tsx +216 -0
- package/Tests/App/Dashboard/AIInsightViewActions.test.tsx +422 -0
- package/Tests/App/Dashboard/AddWidgetModal.test.tsx +10 -3
- package/Tests/App/Dashboard/AlertsSideMenu.test.tsx +387 -0
- package/Tests/App/Dashboard/ChatActivityFeed.test.tsx +199 -0
- package/Tests/App/Dashboard/DataSourceChartSyntheticConfig.test.tsx +736 -0
- package/Tests/App/Dashboard/DataSourceQueryEditor.test.tsx +868 -0
- package/Tests/App/Dashboard/DataSourceWidgetCatalog.test.ts +440 -0
- package/Tests/App/Dashboard/DataSourceWidgetFetching.test.tsx +2109 -0
- package/Tests/App/Dashboard/DataSourceWidgetViews.test.tsx +726 -0
- package/Tests/App/Dashboard/IncidentsSideMenu.test.tsx +447 -0
- package/Tests/App/Dashboard/InvestigationPanel.test.tsx +514 -3
- package/Tests/App/Dashboard/ProductMenuBreadcrumbs.test.tsx +391 -0
- package/Tests/App/Dashboard/ScheduledMaintenanceSideMenu.test.tsx +326 -0
- package/Tests/App/Dashboard/SideMenuHarness.tsx +187 -0
- package/Tests/App/Dashboard/WidgetCatalog.test.ts +6 -1
- package/Tests/App/StatusPage/StatusPageResourceExplorer.test.tsx +1858 -0
- package/Tests/Models/DatabaseModels/DataSourceModelSecrets.test.ts +70 -0
- package/Tests/Server/API/AIInvestigationAPI.test.ts +187 -0
- package/Tests/Server/API/DashboardPublicDataSourceStrip.test.ts +686 -0
- package/Tests/Server/API/DashboardPublicResourceListAPI.test.ts +585 -823
- package/Tests/Server/API/DataSourceAPIRoutes.test.ts +486 -0
- package/Tests/Server/API/StatusPageSubscriberOwnership.test.ts +291 -0
- package/Tests/Server/API/UserAuthenticationAPI.test.ts +641 -0
- package/Tests/Server/Infrastructure/ClickhouseKeepAliveOptions.test.ts +441 -0
- package/Tests/Server/Middleware/TelemetryIngestTokenLog.test.ts +140 -0
- package/Tests/Server/Services/AIInsightService.test.ts +266 -11
- package/Tests/Server/Services/AIRunAnalysisTldrPersistence.test.ts +160 -0
- package/Tests/Server/Services/AIServiceDailyBudget.test.ts +4 -0
- package/Tests/Server/Services/AlertMetricResourceAttributes.test.ts +352 -0
- package/Tests/Server/Services/DataSourceServiceSettings.test.ts +244 -0
- package/Tests/Server/Services/HostServiceFindOrCreateMemo.test.ts +397 -0
- package/Tests/Server/Services/HostServiceUpdateLastSeen.test.ts +41 -2
- package/Tests/Server/Services/IncidentMetricResourceAttributes.test.ts +408 -0
- package/Tests/Server/Services/MonitorStatusServiceDeleteReferenceCleanup.test.ts +351 -0
- package/Tests/Server/Services/MonitorStatusServiceValidation.test.ts +171 -0
- package/Tests/Server/Services/OpenTelemetryResourceRetentionMemo.test.ts +398 -0
- package/Tests/Server/Services/OpenTelemetryServiceResolutionCache.test.ts +19 -0
- package/Tests/Server/Services/ProjectCallSMSConfigCredentialUniqueness.test.ts +305 -0
- package/Tests/Server/Services/ResourceUpdateLastSeenLivenessFallback.test.ts +36 -1
- package/Tests/Server/Services/RumSessionPinUniqueViolationRecovery.test.ts +163 -0
- package/Tests/Server/Services/UserAuthenticationService.test.ts +973 -0
- package/Tests/Server/Types/Database/ObjectIdColumnQuery.test.ts +262 -0
- package/Tests/Server/Types/Database/Permissions/TenantPermission.test.ts +358 -0
- package/Tests/Server/Utils/AI/FixRunBudget.test.ts +2 -2
- package/Tests/Server/Utils/AI/Insights/ExceptionSpikeDetector.test.ts +6 -1
- package/Tests/Server/Utils/AI/Insights/InsightStore.test.ts +121 -4
- package/Tests/Server/Utils/AI/Insights/NewExceptionDetector.test.ts +361 -10
- package/Tests/Server/Utils/AI/InvestigationSettlement.test.ts +292 -0
- package/Tests/Server/Utils/AI/InvestigationTldr.test.ts +623 -0
- package/Tests/Server/Utils/AI/InvestigationTldrWiring.test.ts +98 -0
- package/Tests/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.test.ts +857 -0
- package/Tests/Server/Utils/Dashboard/PublicDashboardViewConfig.test.ts +480 -0
- package/Tests/Server/Utils/DataSource/ClickHouseConnector.test.ts +759 -0
- package/Tests/Server/Utils/DataSource/ConnectorRegistry.test.ts +37 -0
- package/Tests/Server/Utils/DataSource/EgressGuard.test.ts +645 -0
- package/Tests/Server/Utils/DataSource/ElasticsearchConnector.test.ts +1206 -0
- package/Tests/Server/Utils/DataSource/HttpFetch.test.ts +616 -0
- package/Tests/Server/Utils/DataSource/LokiConnector.test.ts +970 -0
- package/Tests/Server/Utils/DataSource/MySqlConnector.test.ts +935 -0
- package/Tests/Server/Utils/DataSource/PostgresConnector.test.ts +854 -0
- package/Tests/Server/Utils/DataSource/PrometheusConnector.test.ts +881 -0
- package/Tests/Server/Utils/DataSource/RestApiConnector.test.ts +1020 -0
- package/Tests/Server/Utils/DataSource/SqlQueryGuard.test.ts +425 -0
- package/Tests/Server/Utils/DataSource/SqlResultShaper.test.ts +555 -0
- package/Tests/Server/Utils/DataSource/SqlServerConnector.test.ts +934 -0
- package/Tests/Server/Utils/Database/PostgresErrorTranslator.test.ts +228 -7
- package/Tests/Server/Utils/InProcessMemo.test.ts +292 -0
- package/Tests/Server/Utils/InstanceHealth/TelemetryIngestion.test.ts +960 -0
- package/Tests/Server/Utils/MicrosoftTeamsWebhookUrlValidation.test.ts +103 -0
- package/Tests/Server/Utils/Monitor/MonitorMetricResourceAttributes.test.ts +336 -0
- package/Tests/Server/Utils/OfflineAssetHygiene.test.ts +521 -0
- package/Tests/Server/Utils/ResponseRenderAnalytics.test.ts +143 -0
- package/Tests/Server/Utils/SSRFProtection.test.ts +193 -0
- package/Tests/Server/Utils/StatusPageSubscriberWebhook.test.ts +101 -0
- package/Tests/Server/Utils/TailwindBuildCopy.test.ts +225 -0
- package/Tests/Server/Utils/Telemetry/ResourceHeartbeatL1Memo.test.ts +355 -0
- package/Tests/Server/Utils/Telemetry/TelemetryFanInWriter.test.ts +128 -0
- package/Tests/Server/Utils/Telemetry/TelemetryUtilAttributeKeys.test.ts +381 -0
- package/Tests/Server/Utils/Telemetry.test.ts +87 -0
- package/Tests/Server/Utils/VendorAssetIntegrity.test.ts +343 -0
- package/Tests/Server/Utils/VendorAssets.test.ts +671 -0
- package/Tests/Server/Views/OfflineRender.test.ts +297 -0
- package/Tests/Types/Dashboard/DataSourceComponentTypes.test.ts +618 -0
- package/Tests/Types/DateClickhouseFormat.test.ts +192 -0
- package/Tests/Types/Password.test.ts +363 -0
- package/Tests/UI/Components/ConfirmModal.test.tsx +7 -0
- package/Tests/UI/Components/ErrorBoundary.test.tsx +53 -0
- package/Tests/UI/Components/Modal.test.tsx +281 -1
- package/Tests/UI/Components/ObjectIdFilterPipeline.test.tsx +396 -0
- package/Tests/UI/Components/StatusPage/ResourceGroupNavigator.test.tsx +1147 -0
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +116 -1
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +2 -0
- package/Tests/Utils/Analytics.test.ts +23 -0
- package/Tests/Utils/Dashboard/Components/DashboardDataSourceComponents.test.ts +640 -0
- package/Tests/Utils/DataSource/DataSourceQueryText.test.ts +138 -0
- package/Tests/Utils/DataSource/DataSourceValueReducer.test.ts +526 -0
- package/Tests/Utils/Metrics/MetricResourceAttributeUtil.test.ts +691 -0
- package/Tests/Utils/StatusPage/GroupHierarchyView.test.ts +1452 -0
- package/Tests/Utils/StatusPage/ResourceExplorer.test.ts +931 -0
- package/Tests/Utils/Telemetry/CaptureSpanExportGating.test.ts +288 -0
- package/Tests/Utils/Telemetry/IngestionTimestamp.test.ts +170 -0
- package/Types/AI/AIInsightEvidence.ts +6 -0
- package/Types/Analytics/RevenueEvent.ts +31 -0
- package/Types/Dashboard/DashboardComponentType.ts +31 -0
- package/Types/Dashboard/DashboardComponents/DashboardDataSourceChartComponent.ts +27 -0
- package/Types/Dashboard/DashboardComponents/DashboardDataSourceGaugeComponent.ts +32 -0
- package/Types/Dashboard/DashboardComponents/DashboardDataSourceTableComponent.ts +30 -0
- package/Types/Dashboard/DashboardComponents/DashboardDataSourceValueComponent.ts +55 -0
- package/Types/DataSource/DataSourceLimits.ts +62 -0
- package/Types/DataSource/DataSourceQueryConfig.ts +41 -0
- package/Types/DataSource/DataSourceTableResult.ts +38 -0
- package/Types/DataSource/DataSourceType.ts +213 -0
- package/Types/Date.ts +43 -3
- package/Types/Password.ts +64 -0
- package/Types/Permission.ts +46 -0
- package/Types/UserAuthenticationStatus.ts +34 -0
- package/UI/Components/Button/Button.tsx +1 -1
- package/UI/Components/ErrorBoundary.tsx +459 -108
- package/UI/Components/Icon/Icon.tsx +10 -9
- package/UI/Components/Modal/ConfirmModal.tsx +6 -1
- package/UI/Components/Modal/Modal.tsx +267 -35
- package/UI/Components/Modal/ModalFooter.tsx +6 -1
- package/UI/Components/MoreMenu/MoreMenu.tsx +19 -4
- package/UI/Components/MoreMenu/MoreMenuItem.tsx +6 -1
- package/UI/Components/StatusPage/ResourceGrid.tsx +314 -0
- package/UI/Components/StatusPage/ResourceGroupNavigator.tsx +808 -0
- package/UI/Components/StatusPage/ResourceList.tsx +570 -0
- package/UI/Styles/Theme.css +18 -0
- package/UI/Utils/API/RequestOptions.ts +7 -0
- package/UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI.ts +1 -0
- package/UI/Utils/ModelAPI/ModelAPI.ts +1 -0
- package/UI/Utils/TestDataSource.ts +61 -0
- package/UI/esbuild-config.js +45 -0
- package/Utils/Analytics.ts +15 -0
- package/Utils/Dashboard/Components/DashboardDataSourceChartComponent.ts +88 -0
- package/Utils/Dashboard/Components/DashboardDataSourceGaugeComponent.ts +123 -0
- package/Utils/Dashboard/Components/DashboardDataSourceShared.ts +16 -0
- package/Utils/Dashboard/Components/DashboardDataSourceTableComponent.ts +72 -0
- package/Utils/Dashboard/Components/DashboardDataSourceValueComponent.ts +126 -0
- package/Utils/Dashboard/Components/Index.ts +28 -0
- package/Utils/DataSource/DataSourceQueryText.ts +94 -0
- package/Utils/DataSource/DataSourceValueReducer.ts +156 -0
- package/Utils/Metrics/MetricResourceAttributeUtil.ts +380 -0
- package/Utils/NetworkDiscovery/ScanTargetUtil.ts +8 -6
- package/Utils/StatusPage/GroupHierarchyView.ts +931 -0
- package/Utils/StatusPage/ResourceExplorer.ts +853 -0
- package/build/dist/Models/DatabaseModels/AIRun.js +34 -0
- package/build/dist/Models/DatabaseModels/AIRun.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DataSource.js +774 -0
- package/build/dist/Models/DatabaseModels/DataSource.js.map +1 -0
- package/build/dist/Models/DatabaseModels/Index.js +2 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ProjectCallSMSConfig.js +14 -4
- package/build/dist/Models/DatabaseModels/ProjectCallSMSConfig.js.map +1 -1
- package/build/dist/Models/DatabaseModels/User.js +2 -0
- package/build/dist/Models/DatabaseModels/User.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserOnCallLog.js +2 -0
- package/build/dist/Models/DatabaseModels/UserOnCallLog.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserOnCallLogTimeline.js +2 -0
- package/build/dist/Models/DatabaseModels/UserOnCallLogTimeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserSession.js +2 -0
- package/build/dist/Models/DatabaseModels/UserSession.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserTotpAuth.js +6 -4
- package/build/dist/Models/DatabaseModels/UserTotpAuth.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserWebAuthn.js +5 -3
- package/build/dist/Models/DatabaseModels/UserWebAuthn.js.map +1 -1
- package/build/dist/Server/API/AIInsightAPI.js +34 -4
- package/build/dist/Server/API/AIInsightAPI.js.map +1 -1
- package/build/dist/Server/API/AIInvestigationAPI.js +23 -0
- package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -1
- package/build/dist/Server/API/DashboardAPI.js +119 -433
- package/build/dist/Server/API/DashboardAPI.js.map +1 -1
- package/build/dist/Server/API/DataSourceAPI.js +173 -0
- package/build/dist/Server/API/DataSourceAPI.js.map +1 -0
- package/build/dist/Server/API/StatusPageAPI.js +11 -1
- package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
- package/build/dist/Server/API/UserAPI.js +94 -2
- package/build/dist/Server/API/UserAPI.js.map +1 -1
- package/build/dist/Server/Infrastructure/ClickhouseConfig.js +49 -0
- package/build/dist/Server/Infrastructure/ClickhouseConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786303472848-AddDataSourceTable.js +20 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786303472848-AddDataSourceTable.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786600000000-AddInvestigationAnalysisTldr.js +19 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786600000000-AddInvestigationAnalysisTldr.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786700000000-DropProjectCallSMSConfigCredentialUniques.js +64 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786700000000-DropProjectCallSMSConfigCredentialUniques.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Infrastructure/Queue.js +27 -0
- package/build/dist/Server/Infrastructure/Queue.js.map +1 -1
- package/build/dist/Server/Infrastructure/QueueWorker.js +13 -0
- package/build/dist/Server/Infrastructure/QueueWorker.js.map +1 -1
- package/build/dist/Server/Middleware/TelemetryIngest.js +8 -3
- package/build/dist/Server/Middleware/TelemetryIngest.js.map +1 -1
- package/build/dist/Server/Services/AIInsightService.js +110 -10
- package/build/dist/Server/Services/AIInsightService.js.map +1 -1
- package/build/dist/Server/Services/AIRunService.js +34 -0
- package/build/dist/Server/Services/AIRunService.js.map +1 -1
- package/build/dist/Server/Services/AIService.js +16 -2
- package/build/dist/Server/Services/AIService.js.map +1 -1
- package/build/dist/Server/Services/AlertService.js +28 -35
- package/build/dist/Server/Services/AlertService.js.map +1 -1
- package/build/dist/Server/Services/AnalyticsDatabaseService.js +8 -4
- package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
- package/build/dist/Server/Services/DataSourceService.js +159 -0
- package/build/dist/Server/Services/DataSourceService.js.map +1 -0
- package/build/dist/Server/Services/HostService.js +74 -0
- package/build/dist/Server/Services/HostService.js.map +1 -1
- package/build/dist/Server/Services/IncidentService.js +35 -24
- package/build/dist/Server/Services/IncidentService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +2 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/MonitorService.js +45 -0
- package/build/dist/Server/Services/MonitorService.js.map +1 -1
- package/build/dist/Server/Services/MonitorStatusService.js +129 -0
- package/build/dist/Server/Services/MonitorStatusService.js.map +1 -1
- package/build/dist/Server/Services/OpenTelemetryIngestService.js +222 -159
- package/build/dist/Server/Services/OpenTelemetryIngestService.js.map +1 -1
- package/build/dist/Server/Services/RumSessionPinService.js +7 -15
- package/build/dist/Server/Services/RumSessionPinService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageSubscriberService.js +10 -0
- package/build/dist/Server/Services/StatusPageSubscriberService.js.map +1 -1
- package/build/dist/Server/Services/UserService.js +241 -10
- package/build/dist/Server/Services/UserService.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/BasePermission.js +6 -0
- package/build/dist/Server/Types/Database/Permissions/BasePermission.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/DeletePermission.js +1 -0
- package/build/dist/Server/Types/Database/Permissions/DeletePermission.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/ReadPermission.js +2 -0
- package/build/dist/Server/Types/Database/Permissions/ReadPermission.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/TenantPermission.js +68 -12
- package/build/dist/Server/Types/Database/Permissions/TenantPermission.js.map +1 -1
- package/build/dist/Server/Utils/AI/CodeFix/FixRunBudget.js +2 -2
- package/build/dist/Server/Utils/AI/CodeFix/FixRunBudget.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js +68 -8
- package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js +1 -0
- package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js +1 -0
- package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionIdentity.js +97 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionIdentity.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.js +17 -15
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.js +178 -54
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/Insights/InsightStore.js +65 -16
- package/build/dist/Server/Utils/AI/SRE/Insights/InsightStore.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/InvestigationTldr.js +303 -0
- package/build/dist/Server/Utils/AI/SRE/InvestigationTldr.js.map +1 -0
- package/build/dist/Server/Utils/AnalyticsDatabase/InsertDedupContext.js.map +1 -1
- package/build/dist/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.js +1261 -0
- package/build/dist/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.js.map +1 -0
- package/build/dist/Server/Utils/Dashboard/PublicDashboardViewConfig.js +47 -0
- package/build/dist/Server/Utils/Dashboard/PublicDashboardViewConfig.js.map +1 -0
- package/build/dist/Server/Utils/DataSource/ConnectorRegistry.js +42 -0
- package/build/dist/Server/Utils/DataSource/ConnectorRegistry.js.map +1 -0
- package/build/dist/Server/Utils/DataSource/Connectors/ClickHouseConnector.js +187 -0
- package/build/dist/Server/Utils/DataSource/Connectors/ClickHouseConnector.js.map +1 -0
- package/build/dist/Server/Utils/DataSource/Connectors/ElasticsearchConnector.js +493 -0
- package/build/dist/Server/Utils/DataSource/Connectors/ElasticsearchConnector.js.map +1 -0
- package/build/dist/Server/Utils/DataSource/Connectors/LokiConnector.js +399 -0
- package/build/dist/Server/Utils/DataSource/Connectors/LokiConnector.js.map +1 -0
- package/build/dist/Server/Utils/DataSource/Connectors/MySqlConnector.js +195 -0
- package/build/dist/Server/Utils/DataSource/Connectors/MySqlConnector.js.map +1 -0
- package/build/dist/Server/Utils/DataSource/Connectors/PostgresConnector.js +149 -0
- package/build/dist/Server/Utils/DataSource/Connectors/PostgresConnector.js.map +1 -0
- package/build/dist/Server/Utils/DataSource/Connectors/PrometheusConnector.js +362 -0
- package/build/dist/Server/Utils/DataSource/Connectors/PrometheusConnector.js.map +1 -0
- package/build/dist/Server/Utils/DataSource/Connectors/RestApiConnector.js +342 -0
- package/build/dist/Server/Utils/DataSource/Connectors/RestApiConnector.js.map +1 -0
- package/build/dist/Server/Utils/DataSource/Connectors/SqlServerConnector.js +186 -0
- package/build/dist/Server/Utils/DataSource/Connectors/SqlServerConnector.js.map +1 -0
- package/build/dist/Server/Utils/DataSource/EgressGuard.js +305 -0
- package/build/dist/Server/Utils/DataSource/EgressGuard.js.map +1 -0
- package/build/dist/Server/Utils/DataSource/HttpFetch.js +134 -0
- package/build/dist/Server/Utils/DataSource/HttpFetch.js.map +1 -0
- package/build/dist/Server/Utils/DataSource/SqlQueryGuard.js +331 -0
- package/build/dist/Server/Utils/DataSource/SqlQueryGuard.js.map +1 -0
- package/build/dist/Server/Utils/DataSource/SqlResultShaper.js +280 -0
- package/build/dist/Server/Utils/DataSource/SqlResultShaper.js.map +1 -0
- package/build/dist/Server/Utils/DataSource/Types.js +2 -0
- package/build/dist/Server/Utils/DataSource/Types.js.map +1 -0
- package/build/dist/Server/Utils/Database/PostgresErrorTranslator.js +103 -9
- package/build/dist/Server/Utils/Database/PostgresErrorTranslator.js.map +1 -1
- package/build/dist/Server/Utils/InProcessMemo.js +113 -0
- package/build/dist/Server/Utils/InProcessMemo.js.map +1 -0
- package/build/dist/Server/Utils/InstanceHealth/TelemetryIngestion.js +406 -0
- package/build/dist/Server/Utils/InstanceHealth/TelemetryIngestion.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js +34 -0
- package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorResource.js +14 -0
- package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
- package/build/dist/Server/Utils/Response.js +9 -1
- package/build/dist/Server/Utils/Response.js.map +1 -1
- package/build/dist/Server/Utils/SSRFProtection.js +192 -0
- package/build/dist/Server/Utils/SSRFProtection.js.map +1 -0
- package/build/dist/Server/Utils/StartServer.js +7 -0
- package/build/dist/Server/Utils/StartServer.js.map +1 -1
- package/build/dist/Server/Utils/StatusPageSubscriberWebhook.js +24 -0
- package/build/dist/Server/Utils/StatusPageSubscriberWebhook.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/CaptureSpan.js +25 -11
- package/build/dist/Server/Utils/Telemetry/CaptureSpan.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/IngestionTimestamp.js +32 -0
- package/build/dist/Server/Utils/Telemetry/IngestionTimestamp.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/ResourceHeartbeat.js +92 -5
- package/build/dist/Server/Utils/Telemetry/ResourceHeartbeat.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/Telemetry.js +92 -6
- package/build/dist/Server/Utils/Telemetry/Telemetry.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry.js +93 -6
- package/build/dist/Server/Utils/Telemetry.js.map +1 -1
- package/build/dist/Server/Utils/VendorAssets.js +121 -0
- package/build/dist/Server/Utils/VendorAssets.js.map +1 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +25 -4
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/Slack/Slack.js +5 -0
- package/build/dist/Server/Utils/Workspace/Slack/Slack.js.map +1 -1
- package/build/dist/Types/Analytics/RevenueEvent.js +26 -0
- package/build/dist/Types/Analytics/RevenueEvent.js.map +1 -0
- package/build/dist/Types/Dashboard/DashboardComponentType.js +27 -0
- package/build/dist/Types/Dashboard/DashboardComponentType.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardDataSourceChartComponent.js +2 -0
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardDataSourceChartComponent.js.map +1 -0
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardDataSourceGaugeComponent.js +2 -0
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardDataSourceGaugeComponent.js.map +1 -0
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardDataSourceTableComponent.js +2 -0
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardDataSourceTableComponent.js.map +1 -0
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardDataSourceValueComponent.js +16 -0
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardDataSourceValueComponent.js.map +1 -0
- package/build/dist/Types/DataSource/DataSourceLimits.js +47 -0
- package/build/dist/Types/DataSource/DataSourceLimits.js.map +1 -0
- package/build/dist/Types/DataSource/DataSourceQueryConfig.js +10 -0
- package/build/dist/Types/DataSource/DataSourceQueryConfig.js.map +1 -0
- package/build/dist/Types/DataSource/DataSourceTableResult.js +14 -0
- package/build/dist/Types/DataSource/DataSourceTableResult.js.map +1 -0
- package/build/dist/Types/DataSource/DataSourceType.js +183 -0
- package/build/dist/Types/DataSource/DataSourceType.js.map +1 -0
- package/build/dist/Types/Date.js +38 -3
- package/build/dist/Types/Date.js.map +1 -1
- package/build/dist/Types/Password.js +56 -0
- package/build/dist/Types/Password.js.map +1 -0
- package/build/dist/Types/Permission.js +42 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/UserAuthenticationStatus.js +2 -0
- package/build/dist/Types/UserAuthenticationStatus.js.map +1 -0
- package/build/dist/UI/Components/ErrorBoundary.js +388 -72
- package/build/dist/UI/Components/ErrorBoundary.js.map +1 -1
- package/build/dist/UI/Components/Icon/Icon.js +10 -4
- package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
- package/build/dist/UI/Components/Modal/ConfirmModal.js +1 -1
- package/build/dist/UI/Components/Modal/ConfirmModal.js.map +1 -1
- package/build/dist/UI/Components/Modal/Modal.js +178 -19
- package/build/dist/UI/Components/Modal/Modal.js.map +1 -1
- package/build/dist/UI/Components/Modal/ModalFooter.js +3 -1
- package/build/dist/UI/Components/Modal/ModalFooter.js.map +1 -1
- package/build/dist/UI/Components/MoreMenu/MoreMenu.js +9 -6
- package/build/dist/UI/Components/MoreMenu/MoreMenu.js.map +1 -1
- package/build/dist/UI/Components/MoreMenu/MoreMenuItem.js +7 -1
- package/build/dist/UI/Components/MoreMenu/MoreMenuItem.js.map +1 -1
- package/build/dist/UI/Components/StatusPage/ResourceGrid.js +119 -0
- package/build/dist/UI/Components/StatusPage/ResourceGrid.js.map +1 -0
- package/build/dist/UI/Components/StatusPage/ResourceGroupNavigator.js +354 -0
- package/build/dist/UI/Components/StatusPage/ResourceGroupNavigator.js.map +1 -0
- package/build/dist/UI/Components/StatusPage/ResourceList.js +203 -0
- package/build/dist/UI/Components/StatusPage/ResourceList.js.map +1 -0
- package/build/dist/UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI.js +1 -6
- package/build/dist/UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI.js.map +1 -1
- package/build/dist/UI/Utils/ModelAPI/ModelAPI.js +3 -8
- package/build/dist/UI/Utils/ModelAPI/ModelAPI.js.map +1 -1
- package/build/dist/UI/Utils/TestDataSource.js +39 -0
- package/build/dist/UI/Utils/TestDataSource.js.map +1 -0
- package/build/dist/Utils/Analytics.js +4 -0
- package/build/dist/Utils/Analytics.js.map +1 -1
- package/build/dist/Utils/Dashboard/Components/DashboardDataSourceChartComponent.js +79 -0
- package/build/dist/Utils/Dashboard/Components/DashboardDataSourceChartComponent.js.map +1 -0
- package/build/dist/Utils/Dashboard/Components/DashboardDataSourceGaugeComponent.js +111 -0
- package/build/dist/Utils/Dashboard/Components/DashboardDataSourceGaugeComponent.js.map +1 -0
- package/build/dist/Utils/Dashboard/Components/DashboardDataSourceShared.js +15 -0
- package/build/dist/Utils/Dashboard/Components/DashboardDataSourceShared.js.map +1 -0
- package/build/dist/Utils/Dashboard/Components/DashboardDataSourceTableComponent.js +62 -0
- package/build/dist/Utils/Dashboard/Components/DashboardDataSourceTableComponent.js.map +1 -0
- package/build/dist/Utils/Dashboard/Components/DashboardDataSourceValueComponent.js +112 -0
- package/build/dist/Utils/Dashboard/Components/DashboardDataSourceValueComponent.js.map +1 -0
- package/build/dist/Utils/Dashboard/Components/Index.js +16 -0
- package/build/dist/Utils/Dashboard/Components/Index.js.map +1 -1
- package/build/dist/Utils/DataSource/DataSourceQueryText.js +64 -0
- package/build/dist/Utils/DataSource/DataSourceQueryText.js.map +1 -0
- package/build/dist/Utils/DataSource/DataSourceValueReducer.js +124 -0
- package/build/dist/Utils/DataSource/DataSourceValueReducer.js.map +1 -0
- package/build/dist/Utils/Metrics/MetricResourceAttributeUtil.js +281 -0
- package/build/dist/Utils/Metrics/MetricResourceAttributeUtil.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/ScanTargetUtil.js +8 -6
- package/build/dist/Utils/NetworkDiscovery/ScanTargetUtil.js.map +1 -1
- package/build/dist/Utils/StatusPage/GroupHierarchyView.js +560 -0
- package/build/dist/Utils/StatusPage/GroupHierarchyView.js.map +1 -0
- package/build/dist/Utils/StatusPage/ResourceExplorer.js +519 -0
- package/build/dist/Utils/StatusPage/ResourceExplorer.js.map +1 -0
- package/jest.config.json +1 -0
- package/package.json +5 -1
- package/tsconfig.json +12 -10
|
@@ -10,9 +10,11 @@ import useTranslateValue from "../../Utils/Translation";
|
|
|
10
10
|
import React, {
|
|
11
11
|
FunctionComponent,
|
|
12
12
|
ReactElement,
|
|
13
|
+
useCallback,
|
|
13
14
|
useEffect,
|
|
14
15
|
useId,
|
|
15
16
|
useRef,
|
|
17
|
+
useState,
|
|
16
18
|
} from "react";
|
|
17
19
|
|
|
18
20
|
export enum ModalWidth {
|
|
@@ -21,6 +23,52 @@ export enum ModalWidth {
|
|
|
21
23
|
Large,
|
|
22
24
|
}
|
|
23
25
|
|
|
26
|
+
/*
|
|
27
|
+
* The page behind a modal must not scroll, and nested modals share a single
|
|
28
|
+
* lock: a counter, rather than a boolean, is what stops the inner modal from
|
|
29
|
+
* handing scrolling back while its parent is still open.
|
|
30
|
+
*/
|
|
31
|
+
let openModalCount: number = 0;
|
|
32
|
+
let bodyOverflowBeforeLock: string = "";
|
|
33
|
+
let bodyPaddingRightBeforeLock: string = "";
|
|
34
|
+
|
|
35
|
+
type PageScrollLockFunction = () => void;
|
|
36
|
+
|
|
37
|
+
const lockPageScroll: PageScrollLockFunction = (): void => {
|
|
38
|
+
openModalCount++;
|
|
39
|
+
|
|
40
|
+
if (openModalCount > 1 || typeof document === "undefined") {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
bodyOverflowBeforeLock = document.body.style.overflow;
|
|
45
|
+
bodyPaddingRightBeforeLock = document.body.style.paddingRight;
|
|
46
|
+
|
|
47
|
+
/*
|
|
48
|
+
* Hiding the scrollbar reclaims its width, so the page underneath would
|
|
49
|
+
* jump sideways by exactly that much. Pad it back to hold everything still.
|
|
50
|
+
*/
|
|
51
|
+
const scrollbarWidth: number =
|
|
52
|
+
window.innerWidth - document.documentElement.clientWidth;
|
|
53
|
+
|
|
54
|
+
if (scrollbarWidth > 0) {
|
|
55
|
+
document.body.style.paddingRight = `${scrollbarWidth}px`;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
document.body.style.overflow = "hidden";
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const unlockPageScroll: PageScrollLockFunction = (): void => {
|
|
62
|
+
openModalCount = Math.max(0, openModalCount - 1);
|
|
63
|
+
|
|
64
|
+
if (openModalCount > 0 || typeof document === "undefined") {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
document.body.style.overflow = bodyOverflowBeforeLock;
|
|
69
|
+
document.body.style.paddingRight = bodyPaddingRightBeforeLock;
|
|
70
|
+
};
|
|
71
|
+
|
|
24
72
|
export interface ComponentProps {
|
|
25
73
|
title: string;
|
|
26
74
|
description?: string | undefined;
|
|
@@ -39,6 +87,7 @@ export interface ComponentProps {
|
|
|
39
87
|
rightElement?: ReactElement | undefined;
|
|
40
88
|
closeButtonText?: string | undefined;
|
|
41
89
|
leftFooterElement?: ReactElement | undefined;
|
|
90
|
+
disableCloseOnBackdropClick?: boolean | undefined;
|
|
42
91
|
}
|
|
43
92
|
|
|
44
93
|
const Modal: FunctionComponent<ComponentProps> = (
|
|
@@ -58,6 +107,10 @@ const Modal: FunctionComponent<ComponentProps> = (
|
|
|
58
107
|
const translatedCloseLabel: string = translateString("Close") || "Close";
|
|
59
108
|
const modalRef: React.RefObject<HTMLDivElement> =
|
|
60
109
|
useRef<HTMLDivElement>(null);
|
|
110
|
+
const contentRef: React.RefObject<HTMLDivElement> =
|
|
111
|
+
useRef<HTMLDivElement>(null);
|
|
112
|
+
const contentInnerRef: React.RefObject<HTMLDivElement> =
|
|
113
|
+
useRef<HTMLDivElement>(null);
|
|
61
114
|
const previouslyFocusedElementRef: React.MutableRefObject<HTMLElement | null> =
|
|
62
115
|
useRef<HTMLElement | null>(
|
|
63
116
|
typeof document !== "undefined" &&
|
|
@@ -68,17 +121,126 @@ const Modal: FunctionComponent<ComponentProps> = (
|
|
|
68
121
|
const onCloseRef: React.MutableRefObject<(() => void) | undefined> = useRef<
|
|
69
122
|
(() => void) | undefined
|
|
70
123
|
>(props.onClose);
|
|
124
|
+
const backdropPressStartedOutsideRef: React.MutableRefObject<boolean> =
|
|
125
|
+
useRef<boolean>(false);
|
|
71
126
|
const titleId: string = useId();
|
|
72
127
|
const descriptionId: string = useId();
|
|
73
128
|
|
|
129
|
+
/*
|
|
130
|
+
* The modal is mounted in its closed state and flipped open one frame later
|
|
131
|
+
* so the browser has something to transition from. Without that first paint
|
|
132
|
+
* the panel would simply appear.
|
|
133
|
+
*/
|
|
134
|
+
const [hasEntered, setHasEntered] = useState<boolean>(false);
|
|
135
|
+
|
|
136
|
+
/*
|
|
137
|
+
* A body taller than the modal hides content above and below the fold. The
|
|
138
|
+
* header and footer grow a shadow in whichever direction that is true, which
|
|
139
|
+
* is the only cue that the body scrolls at all.
|
|
140
|
+
*/
|
|
141
|
+
const [isContentHiddenAbove, setIsContentHiddenAbove] =
|
|
142
|
+
useState<boolean>(false);
|
|
143
|
+
const [isContentHiddenBelow, setIsContentHiddenBelow] =
|
|
144
|
+
useState<boolean>(false);
|
|
145
|
+
|
|
74
146
|
useEffect(() => {
|
|
75
147
|
onCloseRef.current = props.onClose;
|
|
76
148
|
}, [props.onClose]);
|
|
77
149
|
|
|
150
|
+
useEffect(() => {
|
|
151
|
+
const open: () => void = (): void => {
|
|
152
|
+
setHasEntered(true);
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
const frame: number = requestAnimationFrame(open);
|
|
156
|
+
|
|
157
|
+
/*
|
|
158
|
+
* A hidden or throttled tab never runs an animation frame, and a modal that
|
|
159
|
+
* opened there would sit at zero opacity. The timer is the safety net: it
|
|
160
|
+
* skips the transition rather than the modal.
|
|
161
|
+
*/
|
|
162
|
+
const fallbackTimer: ReturnType<typeof setTimeout> = setTimeout(open, 80);
|
|
163
|
+
|
|
164
|
+
return () => {
|
|
165
|
+
cancelAnimationFrame(frame);
|
|
166
|
+
clearTimeout(fallbackTimer);
|
|
167
|
+
};
|
|
168
|
+
}, []);
|
|
169
|
+
|
|
170
|
+
useEffect(() => {
|
|
171
|
+
lockPageScroll();
|
|
172
|
+
|
|
173
|
+
return () => {
|
|
174
|
+
unlockPageScroll();
|
|
175
|
+
};
|
|
176
|
+
}, []);
|
|
177
|
+
|
|
178
|
+
useEffect(() => {
|
|
179
|
+
const content: HTMLDivElement | null = contentRef.current;
|
|
180
|
+
|
|
181
|
+
if (!content) {
|
|
182
|
+
return undefined;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const measure: () => void = (): void => {
|
|
186
|
+
/*
|
|
187
|
+
* A pixel of tolerance: fractional layout heights otherwise leave the
|
|
188
|
+
* bottom shadow up forever on a body that is already fully scrolled.
|
|
189
|
+
*/
|
|
190
|
+
setIsContentHiddenAbove(content.scrollTop > 1);
|
|
191
|
+
setIsContentHiddenBelow(
|
|
192
|
+
content.scrollHeight - content.scrollTop - content.clientHeight > 1,
|
|
193
|
+
);
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
measure();
|
|
197
|
+
content.addEventListener("scroll", measure, { passive: true });
|
|
198
|
+
|
|
199
|
+
/*
|
|
200
|
+
* ResizeObserver is missing in jsdom and in older browsers. Falling back to
|
|
201
|
+
* resize events keeps the shadows roughly right there; what it cannot catch
|
|
202
|
+
* is the body growing on its own, which only matters once the modal is up.
|
|
203
|
+
*/
|
|
204
|
+
if (typeof ResizeObserver === "undefined") {
|
|
205
|
+
window.addEventListener("resize", measure);
|
|
206
|
+
|
|
207
|
+
return () => {
|
|
208
|
+
content.removeEventListener("scroll", measure);
|
|
209
|
+
window.removeEventListener("resize", measure);
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
const observer: ResizeObserver = new ResizeObserver(measure);
|
|
214
|
+
observer.observe(content);
|
|
215
|
+
|
|
216
|
+
if (contentInnerRef.current) {
|
|
217
|
+
observer.observe(contentInnerRef.current);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return () => {
|
|
221
|
+
content.removeEventListener("scroll", measure);
|
|
222
|
+
observer.disconnect();
|
|
223
|
+
};
|
|
224
|
+
}, []);
|
|
225
|
+
|
|
226
|
+
const isTopmostDialog: () => boolean = useCallback((): boolean => {
|
|
227
|
+
const modal: HTMLDivElement | null = modalRef.current;
|
|
228
|
+
|
|
229
|
+
if (!modal) {
|
|
230
|
+
return false;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
const openDialogs: Array<Element> = Array.from(
|
|
234
|
+
document.querySelectorAll('[role="dialog"][aria-modal="true"]'),
|
|
235
|
+
);
|
|
236
|
+
|
|
237
|
+
return openDialogs[openDialogs.length - 1] === modal;
|
|
238
|
+
}, []);
|
|
239
|
+
|
|
78
240
|
useEffect(() => {
|
|
79
241
|
const modal: HTMLDivElement | null = modalRef.current;
|
|
80
242
|
if (!modal) {
|
|
81
|
-
return;
|
|
243
|
+
return undefined;
|
|
82
244
|
}
|
|
83
245
|
|
|
84
246
|
const getFocusableElements: () => Array<HTMLElement> =
|
|
@@ -88,21 +250,25 @@ const Modal: FunctionComponent<ComponentProps> = (
|
|
|
88
250
|
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])',
|
|
89
251
|
),
|
|
90
252
|
).filter((element: HTMLElement) => {
|
|
253
|
+
/*
|
|
254
|
+
* Collapsed sections and closed dropdowns leave focusable elements in
|
|
255
|
+
* the DOM with no box at all, and tabbing onto one of those looks
|
|
256
|
+
* exactly like focus escaping the modal. checkVisibility does not
|
|
257
|
+
* exist in jsdom, where nothing has a box to begin with, so the
|
|
258
|
+
* fallback keeps every element in the cycle there.
|
|
259
|
+
*/
|
|
260
|
+
const isRendered: boolean =
|
|
261
|
+
typeof element.checkVisibility !== "function" ||
|
|
262
|
+
element.checkVisibility();
|
|
263
|
+
|
|
91
264
|
return (
|
|
92
265
|
!element.hasAttribute("disabled") &&
|
|
93
|
-
element.getAttribute("aria-hidden") !== "true"
|
|
266
|
+
element.getAttribute("aria-hidden") !== "true" &&
|
|
267
|
+
isRendered
|
|
94
268
|
);
|
|
95
269
|
});
|
|
96
270
|
};
|
|
97
271
|
|
|
98
|
-
const isTopmostDialog: () => boolean = (): boolean => {
|
|
99
|
-
const openDialogs: Array<Element> = Array.from(
|
|
100
|
-
document.querySelectorAll('[role="dialog"][aria-modal="true"]'),
|
|
101
|
-
);
|
|
102
|
-
|
|
103
|
-
return openDialogs[openDialogs.length - 1] === modal;
|
|
104
|
-
};
|
|
105
|
-
|
|
106
272
|
const initialFocusElement: HTMLElement | undefined =
|
|
107
273
|
getFocusableElements().find((element: HTMLElement) => {
|
|
108
274
|
return element.getAttribute("data-testid") !== "close-button";
|
|
@@ -168,7 +334,51 @@ const Modal: FunctionComponent<ComponentProps> = (
|
|
|
168
334
|
previouslyFocusedElementRef.current.focus();
|
|
169
335
|
}
|
|
170
336
|
};
|
|
171
|
-
}, []);
|
|
337
|
+
}, [isTopmostDialog]);
|
|
338
|
+
|
|
339
|
+
type BackdropPressHandler = (event: React.MouseEvent<HTMLDivElement>) => void;
|
|
340
|
+
type IsEventOutsideModalFunction = (
|
|
341
|
+
event: React.MouseEvent<HTMLDivElement>,
|
|
342
|
+
) => boolean;
|
|
343
|
+
|
|
344
|
+
const isEventOutsideModal: IsEventOutsideModalFunction = (
|
|
345
|
+
event: React.MouseEvent<HTMLDivElement>,
|
|
346
|
+
): boolean => {
|
|
347
|
+
const modal: HTMLDivElement | null = modalRef.current;
|
|
348
|
+
|
|
349
|
+
return modal !== null && !modal.contains(event.target as Node);
|
|
350
|
+
};
|
|
351
|
+
|
|
352
|
+
const onBackdropMouseDown: BackdropPressHandler = (
|
|
353
|
+
event: React.MouseEvent<HTMLDivElement>,
|
|
354
|
+
): void => {
|
|
355
|
+
backdropPressStartedOutsideRef.current = isEventOutsideModal(event);
|
|
356
|
+
};
|
|
357
|
+
|
|
358
|
+
const onBackdropClick: BackdropPressHandler = (
|
|
359
|
+
event: React.MouseEvent<HTMLDivElement>,
|
|
360
|
+
): void => {
|
|
361
|
+
/*
|
|
362
|
+
* Both ends of the click have to land on the backdrop. Selecting text in
|
|
363
|
+
* the body and releasing the mouse past the edge of the panel is a drag,
|
|
364
|
+
* not a dismissal, and it used to be the fastest way to lose a filled-in
|
|
365
|
+
* form.
|
|
366
|
+
*/
|
|
367
|
+
const pressStartedOutside: boolean = backdropPressStartedOutsideRef.current;
|
|
368
|
+
backdropPressStartedOutsideRef.current = false;
|
|
369
|
+
|
|
370
|
+
if (
|
|
371
|
+
props.disableCloseOnBackdropClick ||
|
|
372
|
+
!props.onClose ||
|
|
373
|
+
!pressStartedOutside ||
|
|
374
|
+
!isEventOutsideModal(event) ||
|
|
375
|
+
!isTopmostDialog()
|
|
376
|
+
) {
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
props.onClose();
|
|
381
|
+
};
|
|
172
382
|
|
|
173
383
|
let modalWidthClassName: string = "sm:max-w-lg md:max-w-lg";
|
|
174
384
|
|
|
@@ -178,19 +388,35 @@ const Modal: FunctionComponent<ComponentProps> = (
|
|
|
178
388
|
modalWidthClassName = "sm:max-w-7xl md:max-w-7xl";
|
|
179
389
|
}
|
|
180
390
|
|
|
391
|
+
/*
|
|
392
|
+
* Once the panel has settled it carries no transform at all. A lingering
|
|
393
|
+
* `scale-100` would make it the containing block for `position: fixed`, and
|
|
394
|
+
* a modal opened from inside this one would be laid out against the panel
|
|
395
|
+
* instead of the viewport.
|
|
396
|
+
*/
|
|
397
|
+
const panelTransitionClassName: string = hasEntered
|
|
398
|
+
? "opacity-100"
|
|
399
|
+
: "translate-y-6 opacity-0 sm:translate-y-0 sm:scale-95";
|
|
400
|
+
|
|
181
401
|
return (
|
|
182
402
|
<div className="relative z-50">
|
|
183
403
|
<div
|
|
184
|
-
className=
|
|
404
|
+
className={`fixed inset-0 bg-gray-950/45 backdrop-blur-[2px] transition-opacity duration-200 ease-out motion-reduce:transition-none ${
|
|
405
|
+
hasEntered ? "opacity-100" : "opacity-0"
|
|
406
|
+
}`}
|
|
185
407
|
data-testid="modal-backdrop"
|
|
186
408
|
aria-hidden="true"
|
|
187
409
|
/>
|
|
188
410
|
|
|
189
|
-
<div
|
|
411
|
+
<div
|
|
412
|
+
className="fixed inset-0 z-50 overflow-y-auto"
|
|
413
|
+
onMouseDown={onBackdropMouseDown}
|
|
414
|
+
onClick={onBackdropClick}
|
|
415
|
+
>
|
|
190
416
|
<div className="flex min-h-full items-end justify-center p-0 text-center sm:items-center sm:p-6">
|
|
191
417
|
<div
|
|
192
418
|
ref={modalRef}
|
|
193
|
-
className={`relative flex max-h-[calc(
|
|
419
|
+
className={`relative flex max-h-[calc(100dvh-1rem)] w-full flex-col rounded-t-2xl border border-gray-200/80 bg-white text-left shadow-2xl ring-1 ring-black/5 transition duration-200 ease-out focus:outline-none motion-reduce:transition-none sm:my-8 sm:max-h-[calc(100dvh-4rem)] sm:rounded-xl ${modalWidthClassName} ${panelTransitionClassName}`}
|
|
194
420
|
data-testid="modal"
|
|
195
421
|
aria-labelledby={titleId}
|
|
196
422
|
aria-describedby={translatedDescription ? descriptionId : undefined}
|
|
@@ -198,12 +424,14 @@ const Modal: FunctionComponent<ComponentProps> = (
|
|
|
198
424
|
aria-modal="true"
|
|
199
425
|
tabIndex={-1}
|
|
200
426
|
>
|
|
201
|
-
<div
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
427
|
+
<div
|
|
428
|
+
className={`relative z-10 flex shrink-0 items-start gap-3 rounded-t-2xl border-b border-gray-100 bg-white px-5 py-4 transition-shadow duration-200 sm:gap-4 sm:rounded-t-xl sm:px-6 ${
|
|
429
|
+
isContentHiddenAbove
|
|
430
|
+
? "shadow-[0_6px_10px_-10px_var(--ou-modal-scroll-shadow,rgb(15_23_42_/_0.35))]"
|
|
431
|
+
: ""
|
|
432
|
+
}`}
|
|
433
|
+
>
|
|
434
|
+
<div className="min-w-0 flex-1">
|
|
207
435
|
<h3
|
|
208
436
|
data-testid="modal-title"
|
|
209
437
|
className="text-base font-semibold leading-6 tracking-tight text-gray-900"
|
|
@@ -224,7 +452,7 @@ const Modal: FunctionComponent<ComponentProps> = (
|
|
|
224
452
|
{props.rightElement && (
|
|
225
453
|
<div
|
|
226
454
|
data-testid="right-element"
|
|
227
|
-
className=
|
|
455
|
+
className="flex shrink-0 items-center"
|
|
228
456
|
>
|
|
229
457
|
{props.rightElement}
|
|
230
458
|
</div>
|
|
@@ -236,7 +464,7 @@ const Modal: FunctionComponent<ComponentProps> = (
|
|
|
236
464
|
aria-label={translatedCloseLabel}
|
|
237
465
|
data-testid="close-button"
|
|
238
466
|
onClick={props.onClose}
|
|
239
|
-
className="
|
|
467
|
+
className="-mr-1.5 -mt-0.5 inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-md text-gray-400 transition-colors hover:bg-gray-100 hover:text-gray-700 focus:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500 focus-visible:ring-offset-2"
|
|
240
468
|
>
|
|
241
469
|
<Icon icon={IconProp.Close} className="h-4 w-4" />
|
|
242
470
|
</button>
|
|
@@ -244,22 +472,25 @@ const Modal: FunctionComponent<ComponentProps> = (
|
|
|
244
472
|
</div>
|
|
245
473
|
|
|
246
474
|
<div
|
|
475
|
+
ref={contentRef}
|
|
247
476
|
className="min-h-0 flex-1 overflow-y-auto overscroll-contain px-5 py-5 sm:px-6"
|
|
248
477
|
data-testid="modal-content"
|
|
249
478
|
>
|
|
250
|
-
<
|
|
251
|
-
{
|
|
252
|
-
props.
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
<
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
479
|
+
<div ref={contentInnerRef}>
|
|
480
|
+
<ModalBody error={props.error}>
|
|
481
|
+
{!props.isBodyLoading ? (
|
|
482
|
+
props.children
|
|
483
|
+
) : (
|
|
484
|
+
<div className="modal-body flex justify-center py-16">
|
|
485
|
+
<Loader
|
|
486
|
+
loaderType={LoaderType.Bar}
|
|
487
|
+
color={VeryLightGray}
|
|
488
|
+
size={200}
|
|
489
|
+
/>
|
|
490
|
+
</div>
|
|
491
|
+
)}
|
|
492
|
+
</ModalBody>
|
|
493
|
+
</div>
|
|
263
494
|
</div>
|
|
264
495
|
<ModalFooter
|
|
265
496
|
submitButtonType={
|
|
@@ -294,6 +525,7 @@ const Modal: FunctionComponent<ComponentProps> = (
|
|
|
294
525
|
props.isBodyLoading || props.disableSubmitButton
|
|
295
526
|
}
|
|
296
527
|
leftFooterElement={props.leftFooterElement}
|
|
528
|
+
hasContentHiddenBelow={isContentHiddenBelow}
|
|
297
529
|
/>
|
|
298
530
|
</div>
|
|
299
531
|
</div>
|
|
@@ -13,6 +13,7 @@ export interface ComponentProps {
|
|
|
13
13
|
disableSubmitButton?: undefined | boolean;
|
|
14
14
|
closeButtonText?: undefined | string;
|
|
15
15
|
leftFooterElement?: ReactElement | undefined;
|
|
16
|
+
hasContentHiddenBelow?: boolean | undefined;
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
const ModalFooter: FunctionComponent<ComponentProps> = (
|
|
@@ -24,7 +25,11 @@ const ModalFooter: FunctionComponent<ComponentProps> = (
|
|
|
24
25
|
|
|
25
26
|
return (
|
|
26
27
|
<div
|
|
27
|
-
className=
|
|
28
|
+
className={`relative z-10 flex shrink-0 flex-col gap-3 rounded-b-2xl border-t border-gray-100 bg-gray-50/70 px-5 pb-[max(0.75rem,env(safe-area-inset-bottom))] pt-3 transition-shadow duration-200 sm:flex-row sm:items-center sm:justify-between sm:rounded-b-xl sm:px-6 sm:pb-3 ${
|
|
29
|
+
props.hasContentHiddenBelow
|
|
30
|
+
? "shadow-[0_-6px_10px_-10px_var(--ou-modal-scroll-shadow,rgb(15_23_42_/_0.35))]"
|
|
31
|
+
: ""
|
|
32
|
+
}`}
|
|
28
33
|
data-testid="modal-footer"
|
|
29
34
|
>
|
|
30
35
|
{props.leftFooterElement ? (
|
|
@@ -22,6 +22,15 @@ export interface ComponentProps {
|
|
|
22
22
|
triggerClassName?: string | undefined;
|
|
23
23
|
menuIcon?: IconProp | undefined;
|
|
24
24
|
text?: string | undefined;
|
|
25
|
+
/*
|
|
26
|
+
* The trigger's accessible name, separately from `text`. The default trigger
|
|
27
|
+
* renders `text` as a visible label beside the icon, so an icon-only overflow
|
|
28
|
+
* menu has to pass `text=""` — which would otherwise leave every one of them
|
|
29
|
+
* called "More options" and tell a screen reader user nothing about which
|
|
30
|
+
* thing the menu belongs to.
|
|
31
|
+
*/
|
|
32
|
+
ariaLabel?: string | undefined;
|
|
33
|
+
dataTestId?: string | undefined;
|
|
25
34
|
isDisabled?: boolean | undefined;
|
|
26
35
|
}
|
|
27
36
|
|
|
@@ -312,7 +321,10 @@ const MoreMenu: React.ForwardRefExoticComponent<
|
|
|
312
321
|
disabled: isTriggerDisabled,
|
|
313
322
|
"aria-disabled": isTriggerDisabled,
|
|
314
323
|
"aria-label":
|
|
315
|
-
trigger.props["aria-label"] ||
|
|
324
|
+
trigger.props["aria-label"] ||
|
|
325
|
+
props.ariaLabel ||
|
|
326
|
+
props.text ||
|
|
327
|
+
"More options",
|
|
316
328
|
"aria-haspopup": "menu",
|
|
317
329
|
"aria-expanded": isComponentVisible,
|
|
318
330
|
"aria-controls": isComponentVisible ? menuId : undefined,
|
|
@@ -338,10 +350,11 @@ const MoreMenu: React.ForwardRefExoticComponent<
|
|
|
338
350
|
title={props.text || ""}
|
|
339
351
|
buttonStyle={ButtonStyleType.OUTLINE}
|
|
340
352
|
disabled={props.isDisabled}
|
|
353
|
+
dataTestId={props.dataTestId}
|
|
341
354
|
onClick={() => {
|
|
342
355
|
setIsComponentVisible(!isDropdownVisible);
|
|
343
356
|
}}
|
|
344
|
-
ariaLabel={props.text || "More options"}
|
|
357
|
+
ariaLabel={props.ariaLabel || props.text || "More options"}
|
|
345
358
|
ariaExpanded={isComponentVisible}
|
|
346
359
|
ariaHaspopup="menu"
|
|
347
360
|
ariaControls={isComponentVisible ? menuId : undefined}
|
|
@@ -358,10 +371,11 @@ const MoreMenu: React.ForwardRefExoticComponent<
|
|
|
358
371
|
type="button"
|
|
359
372
|
className={props.triggerClassName}
|
|
360
373
|
disabled={props.isDisabled}
|
|
374
|
+
data-testid={props.dataTestId}
|
|
361
375
|
onClick={() => {
|
|
362
376
|
setIsComponentVisible(!isDropdownVisible);
|
|
363
377
|
}}
|
|
364
|
-
aria-label={props.text || "More options"}
|
|
378
|
+
aria-label={props.ariaLabel || props.text || "More options"}
|
|
365
379
|
aria-haspopup="menu"
|
|
366
380
|
aria-expanded={isComponentVisible}
|
|
367
381
|
aria-controls={isComponentVisible ? menuId : undefined}
|
|
@@ -383,7 +397,8 @@ const MoreMenu: React.ForwardRefExoticComponent<
|
|
|
383
397
|
id={buttonId}
|
|
384
398
|
role="button"
|
|
385
399
|
tabIndex={props.isDisabled ? -1 : 0}
|
|
386
|
-
|
|
400
|
+
data-testid={props.dataTestId}
|
|
401
|
+
aria-label={props.ariaLabel || props.text || undefined}
|
|
387
402
|
aria-haspopup="menu"
|
|
388
403
|
aria-expanded={isComponentVisible}
|
|
389
404
|
aria-controls={isComponentVisible ? menuId : undefined}
|
|
@@ -16,9 +16,14 @@ const MoreMenuItem: FunctionComponent<ComponentProps> = (
|
|
|
16
16
|
props: ComponentProps,
|
|
17
17
|
): ReactElement => {
|
|
18
18
|
return (
|
|
19
|
+
/*
|
|
20
|
+
* A button shrink-wraps its content whatever its display type, so the width
|
|
21
|
+
* has to be set explicitly or the hover background stops at the end of the
|
|
22
|
+
* label instead of spanning the menu. 100% less the mx-1 on either side.
|
|
23
|
+
*/
|
|
19
24
|
<button
|
|
20
25
|
type="button"
|
|
21
|
-
className={`group mx-1 flex items-center rounded-md px-3 py-2 text-left text-sm text-gray-700 transition-colors duration-100 enabled:cursor-pointer enabled:hover:bg-indigo-50 enabled:hover:text-gray-900 disabled:cursor-not-allowed disabled:opacity-50 ${props.className || ""}`}
|
|
26
|
+
className={`group mx-1 flex w-[calc(100%-0.5rem)] items-center rounded-md px-3 py-2 text-left text-sm text-gray-700 transition-colors duration-100 enabled:cursor-pointer enabled:hover:bg-indigo-50 enabled:hover:text-gray-900 disabled:cursor-not-allowed disabled:opacity-50 ${props.className || ""}`}
|
|
22
27
|
role="menuitem"
|
|
23
28
|
tabIndex={-1}
|
|
24
29
|
disabled={props.isDisabled}
|