@oneuptime/common 12.0.13 → 12.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (376) hide show
  1. package/Models/DatabaseModels/OnCallDutyPolicySchedule.ts +14 -0
  2. package/Models/DatabaseModels/UserCall.ts +94 -3
  3. package/Models/DatabaseModels/UserEmail.ts +94 -3
  4. package/Models/DatabaseModels/UserIncomingCallNumber.ts +94 -3
  5. package/Models/DatabaseModels/UserPush.ts +37 -0
  6. package/Models/DatabaseModels/UserSMS.ts +94 -3
  7. package/Models/DatabaseModels/UserWhatsApp.ts +93 -2
  8. package/Server/API/BaseAPI.ts +79 -14
  9. package/Server/API/UserCallAPI.ts +53 -45
  10. package/Server/API/UserEmailAPI.ts +53 -44
  11. package/Server/API/UserIncomingCallNumberAPI.ts +48 -38
  12. package/Server/API/UserNotificationMethodAdminAPI.ts +481 -0
  13. package/Server/API/UserPushAPI.ts +126 -2
  14. package/Server/API/UserSmsAPI.ts +53 -44
  15. package/Server/API/UserWhatsAppAPI.ts +53 -50
  16. package/Server/Infrastructure/Postgres/SchemaMigrations/1787142779538-MigrationName.ts +154 -0
  17. package/Server/Infrastructure/Postgres/SchemaMigrations/1787156982416-MigrationName.ts +17 -0
  18. package/Server/Infrastructure/Postgres/SchemaMigrations/1787700000000-FixTotpOtpUrlAlgorithm.ts +45 -0
  19. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
  20. package/Server/Middleware/VerificationCodeRateLimit.ts +586 -0
  21. package/Server/Services/AnalyticsDatabaseService.ts +169 -0
  22. package/Server/Services/DatabaseService.ts +101 -0
  23. package/Server/Services/LogAggregationService.ts +5 -0
  24. package/Server/Services/PushNotificationService.ts +127 -12
  25. package/Server/Services/TeamMemberService.ts +53 -13
  26. package/Server/Services/UserCallService.ts +55 -24
  27. package/Server/Services/UserEmailService.ts +83 -17
  28. package/Server/Services/UserIncomingCallNumberService.ts +49 -85
  29. package/Server/Services/UserNotificationMethodAdminService.ts +1527 -0
  30. package/Server/Services/UserNotificationRuleService.ts +26 -0
  31. package/Server/Services/UserPushService.ts +89 -0
  32. package/Server/Services/UserSmsService.ts +50 -17
  33. package/Server/Services/UserWhatsAppService.ts +48 -15
  34. package/Server/Types/Database/QueryHelper.ts +30 -0
  35. package/Server/Utils/AnalyticsDatabase/QuerySettingsHelper.ts +59 -0
  36. package/Server/Utils/ChannelVerification.ts +510 -0
  37. package/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.ts +13 -16
  38. package/Server/Utils/Monitor/MonitorAlert.ts +24 -21
  39. package/Server/Utils/Monitor/MonitorIncident.ts +21 -18
  40. package/Server/Utils/Monitor/MonitorResourceContext.ts +107 -0
  41. package/Server/Utils/Monitor/MonitorStepResourceIdentity.ts +442 -0
  42. package/Server/Utils/Monitor/SeriesResourceLabels.ts +3 -3
  43. package/Server/Utils/Monitor/SeriesResourceLinker.ts +96 -28
  44. package/Server/Utils/TotpAuth.ts +137 -9
  45. package/Server/Utils/UserRegistrationToken.ts +182 -0
  46. package/Server/Utils/VerificationCode.ts +134 -0
  47. package/Tests/App/Dashboard/AdminNotificationRulesPage.test.tsx +173 -94
  48. package/Tests/App/Dashboard/AdminUserNotificationMethodsPage.test.tsx +1151 -0
  49. package/Tests/App/Dashboard/AdminUserOnCallPages.test.tsx +905 -0
  50. package/Tests/App/Dashboard/DashboardCommandPalette.test.tsx +338 -0
  51. package/Tests/App/Dashboard/InvestigationPanel.test.tsx +1 -1
  52. package/Tests/App/Dashboard/MonitorTypePicker.test.tsx +28 -0
  53. package/Tests/Models/UserPushCriticalAlertColumn.test.ts +172 -0
  54. package/Tests/Server/API/BaseAPIGetListParallel.test.ts +519 -0
  55. package/Tests/Server/API/NotificationChannelVerificationAPI.test.ts +543 -0
  56. package/Tests/Server/API/UserIncomingCallNumberApi.test.ts +108 -18
  57. package/Tests/Server/API/UserNotificationMethodAdminAPI.test.ts +963 -0
  58. package/Tests/Server/API/UserPushCriticalAlertsApi.test.ts +114 -0
  59. package/Tests/Server/API/UserSmsApi.test.ts +107 -14
  60. package/Tests/Server/API/UserTotpAuthAPI.test.ts +427 -0
  61. package/Tests/Server/Infrastructure/Postgres/FixTotpOtpUrlAlgorithmMigration.test.ts +315 -0
  62. package/Tests/Server/Middleware/VerificationCodeRateLimit.test.ts +775 -0
  63. package/Tests/Server/Services/AddNetworkDeviceReachabilityColumnsMigration.test.ts +10 -62
  64. package/Tests/Server/Services/AnalyticsDatabasePaginationStability.test.ts +33 -13
  65. package/Tests/Server/Services/AnalyticsDatabaseSortKeyBoundary.test.ts +658 -0
  66. package/Tests/Server/Services/CriticalOnCallAlertDelivery.test.ts +458 -0
  67. package/Tests/Server/Services/CriticalPushAlertPayload.test.ts +301 -0
  68. package/Tests/Server/Services/DatabaseServiceAtomicIncrement.test.ts +143 -0
  69. package/Tests/Server/Services/DeliverNotificationForRuleExtraction.test.ts +1 -0
  70. package/Tests/Server/Services/LogAggregationScanMemory.test.ts +421 -0
  71. package/Tests/Server/Services/LogAggregationService.test.ts +2 -2
  72. package/Tests/Server/Services/NotificationChannelCodeIssuance.test.ts +401 -0
  73. package/Tests/Server/Services/PushNotificationDeliveryOptions.test.ts +204 -0
  74. package/Tests/Server/Services/TeamMemberAutoAcceptInvitation.test.ts +21 -1
  75. package/Tests/Server/Services/TeamMemberInviteRegistrationToken.test.ts +290 -0
  76. package/Tests/Server/Services/UserNotificationMethodAdminService.test.ts +948 -0
  77. package/Tests/Server/Services/UserNotificationRuleExecuteItem.test.ts +1 -0
  78. package/Tests/Server/Services/UserPushCriticalAlertToggle.test.ts +255 -0
  79. package/Tests/Server/Services/UserTotpAuthEnrolment.test.ts +218 -0
  80. package/Tests/Server/TestingUtils/AuthenticatorApp.ts +248 -0
  81. package/Tests/Server/Types/Database/Permissions/NotificationChannelVerificationColumns.test.ts +135 -0
  82. package/Tests/Server/Types/Database/Permissions/OnCallScheduleRelationSelect.test.ts +504 -0
  83. package/Tests/Server/Types/Database/QueryHelperFindWithSameTextAnyOf.test.ts +91 -0
  84. package/Tests/Server/Types/Workflow/Components/JsonToText.test.ts +384 -0
  85. package/Tests/Server/Types/Workflow/Components/MergeJson.test.ts +403 -0
  86. package/Tests/Server/Utils/Browser.test.ts +162 -0
  87. package/Tests/Server/Utils/ChannelVerification.test.ts +689 -0
  88. package/Tests/Server/Utils/Express.test.ts +371 -0
  89. package/Tests/Server/Utils/Monitor/Criteria/CustomCodeMonitorCriteria.test.ts +707 -0
  90. package/Tests/Server/Utils/Monitor/Criteria/DnsMonitorCriteria.test.ts +698 -0
  91. package/Tests/Server/Utils/Monitor/Criteria/IncomingEmailBodyCriteria.test.ts +243 -0
  92. package/Tests/Server/Utils/Monitor/Criteria/IncomingRequestBodyCriteria.test.ts +278 -0
  93. package/Tests/Server/Utils/Monitor/MonitorAlertResourceLinking.test.ts +160 -20
  94. package/Tests/Server/Utils/Monitor/MonitorDependencySuppressionCreatorSkip.test.ts +13 -8
  95. package/Tests/Server/Utils/Monitor/MonitorIncidentResourceLinking.test.ts +162 -18
  96. package/Tests/Server/Utils/Monitor/MonitorResourceContext.test.ts +349 -0
  97. package/Tests/Server/Utils/Monitor/MonitorStepResourceIdentity.test.ts +690 -0
  98. package/Tests/Server/Utils/Monitor/MonitorSummaryPersistence.test.ts +7 -2
  99. package/Tests/Server/Utils/Monitor/SeriesResourceLinker.test.ts +92 -18
  100. package/Tests/Server/Utils/PushNotificationUtilCreators.test.ts +267 -0
  101. package/Tests/Server/Utils/Telemetry/OneuptimeLabel.test.ts +439 -0
  102. package/Tests/Server/Utils/TotpAuth.test.ts +719 -0
  103. package/Tests/Server/Utils/UserRegistrationToken.test.ts +322 -0
  104. package/Tests/Server/Utils/VerificationCode.test.ts +296 -0
  105. package/Tests/Types/AutoRemediation/AutoRemediationSuggestionStatus.test.ts +192 -0
  106. package/Tests/Types/Call/CallRequest.test.ts +189 -0
  107. package/Tests/Types/Dashboard/DashboardSize.test.ts +226 -0
  108. package/Tests/Types/Incident/IncidentSlaStatus.test.ts +191 -0
  109. package/Tests/Types/Metrics/MetricDashboardMetricType.test.ts +278 -0
  110. package/Tests/Types/Metrics/MetricPipelineRuleType.test.ts +517 -0
  111. package/Tests/Types/Monitor/IncomingMonitorDefaultCriteria.test.ts +470 -0
  112. package/Tests/Types/Monitor/MonitorCriteriaInstance.test.ts +6 -4
  113. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCatalog.test.ts +262 -5
  114. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCoverage.test.ts +1 -1
  115. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationNotificationMode.test.ts +1 -1
  116. package/Tests/Types/Monitor/ServiceAlertTemplates.test.ts +905 -0
  117. package/Tests/Types/Service/ServiceLanguage.test.ts +255 -0
  118. package/Tests/Types/TextRandomGeneration.test.ts +211 -0
  119. package/Tests/UI/Components/Button.test.tsx +175 -1
  120. package/Tests/UI/Components/CodeBlockLanguages.test.tsx +236 -0
  121. package/Tests/UI/Components/CommandPalette/CommandPalette.test.tsx +568 -0
  122. package/Tests/UI/Components/CommandPalette/CommandPaletteKeyboard.test.tsx +239 -0
  123. package/Tests/UI/Components/CommandPalette/CommandPaletteProviders.test.tsx +400 -0
  124. package/Tests/UI/Components/CommandPalette/PaletteFilter.test.ts +234 -0
  125. package/Tests/UI/Components/CommandPalette/RecentCommands.test.ts +97 -0
  126. package/Tests/UI/Components/CountModelSideMenuItemGuard.test.tsx +198 -0
  127. package/Tests/UI/Components/FeedItemSafeMode.test.tsx +1 -1
  128. package/Tests/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.test.ts +267 -0
  129. package/Tests/UI/Components/List.test.tsx +9 -2
  130. package/Tests/UI/Components/ListLoadingStates.test.tsx +173 -0
  131. package/Tests/UI/Components/MarkdownLazy.test.tsx +113 -0
  132. package/Tests/UI/Components/MarkdownMermaidRetry.test.tsx +110 -0
  133. package/Tests/UI/Components/ModelTable/useCustomFieldColumns.test.tsx +8 -0
  134. package/Tests/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.test.ts +692 -0
  135. package/Tests/UI/Components/MoreMenuMotion.test.tsx +118 -0
  136. package/Tests/UI/Components/NavBarCommandKGating.test.tsx +178 -0
  137. package/Tests/UI/Components/OrderedStatesList.test.tsx +19 -2
  138. package/Tests/UI/Components/SideOverMotion.test.tsx +109 -0
  139. package/Tests/UI/Components/Skeleton.test.tsx +71 -0
  140. package/Tests/UI/Components/TableLoadingStates.test.tsx +279 -0
  141. package/Tests/UI/Components/Tabs.test.tsx +24 -0
  142. package/Tests/UI/Components/Toast.test.tsx +130 -7
  143. package/Tests/UI/Components/ToastStacking.test.tsx +198 -0
  144. package/Tests/UI/Utils/Dropdown.test.ts +423 -0
  145. package/Tests/UI/Utils/ModelAPITenantHeader.test.ts +122 -0
  146. package/Tests/UI/Utils/ModelListCache.test.ts +338 -0
  147. package/Tests/UI/Utils/ProjectListCacheInvalidation.test.ts +225 -0
  148. package/Tests/Utils/API.test.ts +16 -2
  149. package/Tests/Utils/Dashboard/Components/DashboardKubernetesResourceListShared.test.ts +347 -0
  150. package/Tests/Utils/Dashboard/Components/DashboardListSharedArgs.test.ts +259 -0
  151. package/Tests/Utils/Dashboard/Components/DashboardMonitorListComponent.test.ts +466 -0
  152. package/Tests/Utils/Rum/UrlScrubberSegments.test.ts +362 -0
  153. package/Types/Email/EmailTemplateType.ts +1 -0
  154. package/Types/Monitor/MonitorCriteriaInstance.ts +41 -20
  155. package/Types/Monitor/Recommendation/MonitorRecommendationCatalog.ts +131 -8
  156. package/Types/Monitor/Recommendation/MonitorRecommendationTypes.ts +48 -8
  157. package/Types/Monitor/ServiceAlertTemplates.ts +1352 -0
  158. package/Types/Permission.ts +35 -0
  159. package/Types/PushNotification/AndroidNotificationChannel.ts +26 -0
  160. package/Types/PushNotification/PushNotificationMessage.ts +15 -0
  161. package/Types/PushNotification/PushNotificationRequest.ts +8 -16
  162. package/Types/Service/ServiceLanguage.ts +144 -0
  163. package/Types/Text.ts +111 -19
  164. package/UI/Components/Button/Button.tsx +27 -14
  165. package/UI/Components/CodeBlock/CodeBlock.tsx +54 -7
  166. package/UI/Components/CodeBlock/LanguageRegistry.ts +103 -0
  167. package/UI/Components/CommandPalette/CommandPalette.tsx +790 -0
  168. package/UI/Components/CommandPalette/PaletteFilter.ts +196 -0
  169. package/UI/Components/CommandPalette/PaletteRow.tsx +173 -0
  170. package/UI/Components/CommandPalette/RecentCommands.ts +57 -0
  171. package/UI/Components/CommandPalette/Types.ts +49 -0
  172. package/UI/Components/CommandPalette/UseProviderSearch.ts +129 -0
  173. package/UI/Components/Dropdown/Dropdown.tsx +6 -1
  174. package/UI/Components/Feed/FeedItem.tsx +1 -1
  175. package/UI/Components/List/List.tsx +37 -5
  176. package/UI/Components/List/ListSkeleton.tsx +54 -0
  177. package/UI/Components/Markdown.tsx/LazyMarkdownViewer.tsx +6 -1
  178. package/UI/Components/Markdown.tsx/MarkdownViewer.tsx +71 -26
  179. package/UI/Components/Modal/Modal.tsx +2 -2
  180. package/UI/Components/ModelTable/BaseModelTable.tsx +1 -1
  181. package/UI/Components/ModelTable/useCustomFieldColumns.ts +11 -5
  182. package/UI/Components/MoreMenu/MoreMenu.tsx +39 -1
  183. package/UI/Components/Navbar/NavBar.tsx +14 -1
  184. package/UI/Components/OrderedStatesList/OrderedStatesList.tsx +50 -5
  185. package/UI/Components/SideMenu/CountModelSideMenuItem.tsx +40 -1
  186. package/UI/Components/SideOver/SideOver.tsx +37 -2
  187. package/UI/Components/Skeleton/Skeleton.tsx +53 -0
  188. package/UI/Components/Table/Table.tsx +74 -44
  189. package/UI/Components/Table/TableSkeletonRows.tsx +141 -0
  190. package/UI/Components/Tabs/Tab.tsx +1 -1
  191. package/UI/Components/Toast/Toast.tsx +118 -53
  192. package/UI/Components/Toast/ToastInit.tsx +82 -32
  193. package/UI/Styles/Theme.css +40 -0
  194. package/UI/Utils/ModelAPI/ModelAPI.ts +20 -10
  195. package/UI/Utils/ModelListCache.ts +188 -0
  196. package/UI/Utils/Project.ts +29 -0
  197. package/Utils/API.ts +6 -1
  198. package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js +14 -0
  199. package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js.map +1 -1
  200. package/build/dist/Models/DatabaseModels/UserCall.js +101 -3
  201. package/build/dist/Models/DatabaseModels/UserCall.js.map +1 -1
  202. package/build/dist/Models/DatabaseModels/UserEmail.js +101 -3
  203. package/build/dist/Models/DatabaseModels/UserEmail.js.map +1 -1
  204. package/build/dist/Models/DatabaseModels/UserIncomingCallNumber.js +101 -3
  205. package/build/dist/Models/DatabaseModels/UserIncomingCallNumber.js.map +1 -1
  206. package/build/dist/Models/DatabaseModels/UserPush.js +38 -0
  207. package/build/dist/Models/DatabaseModels/UserPush.js.map +1 -1
  208. package/build/dist/Models/DatabaseModels/UserSMS.js +101 -3
  209. package/build/dist/Models/DatabaseModels/UserSMS.js.map +1 -1
  210. package/build/dist/Models/DatabaseModels/UserWhatsApp.js +100 -2
  211. package/build/dist/Models/DatabaseModels/UserWhatsApp.js.map +1 -1
  212. package/build/dist/Server/API/BaseAPI.js +69 -13
  213. package/build/dist/Server/API/BaseAPI.js.map +1 -1
  214. package/build/dist/Server/API/UserCallAPI.js +42 -38
  215. package/build/dist/Server/API/UserCallAPI.js.map +1 -1
  216. package/build/dist/Server/API/UserEmailAPI.js +42 -38
  217. package/build/dist/Server/API/UserEmailAPI.js.map +1 -1
  218. package/build/dist/Server/API/UserIncomingCallNumberAPI.js +37 -32
  219. package/build/dist/Server/API/UserIncomingCallNumberAPI.js.map +1 -1
  220. package/build/dist/Server/API/UserNotificationMethodAdminAPI.js +341 -0
  221. package/build/dist/Server/API/UserNotificationMethodAdminAPI.js.map +1 -0
  222. package/build/dist/Server/API/UserPushAPI.js +95 -2
  223. package/build/dist/Server/API/UserPushAPI.js.map +1 -1
  224. package/build/dist/Server/API/UserSmsAPI.js +42 -38
  225. package/build/dist/Server/API/UserSmsAPI.js.map +1 -1
  226. package/build/dist/Server/API/UserWhatsAppAPI.js +42 -40
  227. package/build/dist/Server/API/UserWhatsAppAPI.js.map +1 -1
  228. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787142779538-MigrationName.js +89 -0
  229. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787142779538-MigrationName.js.map +1 -0
  230. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787156982416-MigrationName.js +12 -0
  231. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787156982416-MigrationName.js.map +1 -0
  232. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787700000000-FixTotpOtpUrlAlgorithm.js +40 -0
  233. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787700000000-FixTotpOtpUrlAlgorithm.js.map +1 -0
  234. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
  235. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  236. package/build/dist/Server/Middleware/VerificationCodeRateLimit.js +393 -0
  237. package/build/dist/Server/Middleware/VerificationCodeRateLimit.js.map +1 -0
  238. package/build/dist/Server/Services/AnalyticsDatabaseService.js +136 -0
  239. package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
  240. package/build/dist/Server/Services/DatabaseService.js +74 -0
  241. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  242. package/build/dist/Server/Services/LogAggregationService.js +5 -0
  243. package/build/dist/Server/Services/LogAggregationService.js.map +1 -1
  244. package/build/dist/Server/Services/PushNotificationService.js +69 -30
  245. package/build/dist/Server/Services/PushNotificationService.js.map +1 -1
  246. package/build/dist/Server/Services/TeamMemberService.js +43 -7
  247. package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
  248. package/build/dist/Server/Services/UserCallService.js +54 -22
  249. package/build/dist/Server/Services/UserCallService.js.map +1 -1
  250. package/build/dist/Server/Services/UserEmailService.js +78 -17
  251. package/build/dist/Server/Services/UserEmailService.js.map +1 -1
  252. package/build/dist/Server/Services/UserIncomingCallNumberService.js +45 -74
  253. package/build/dist/Server/Services/UserIncomingCallNumberService.js.map +1 -1
  254. package/build/dist/Server/Services/UserNotificationMethodAdminService.js +1117 -0
  255. package/build/dist/Server/Services/UserNotificationMethodAdminService.js.map +1 -0
  256. package/build/dist/Server/Services/UserNotificationRuleService.js +20 -0
  257. package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
  258. package/build/dist/Server/Services/UserPushService.js +77 -0
  259. package/build/dist/Server/Services/UserPushService.js.map +1 -1
  260. package/build/dist/Server/Services/UserSmsService.js +50 -17
  261. package/build/dist/Server/Services/UserSmsService.js.map +1 -1
  262. package/build/dist/Server/Services/UserWhatsAppService.js +48 -15
  263. package/build/dist/Server/Services/UserWhatsAppService.js.map +1 -1
  264. package/build/dist/Server/Types/Database/QueryHelper.js +27 -0
  265. package/build/dist/Server/Types/Database/QueryHelper.js.map +1 -1
  266. package/build/dist/Server/Utils/AnalyticsDatabase/QuerySettingsHelper.js +46 -0
  267. package/build/dist/Server/Utils/AnalyticsDatabase/QuerySettingsHelper.js.map +1 -1
  268. package/build/dist/Server/Utils/ChannelVerification.js +348 -0
  269. package/build/dist/Server/Utils/ChannelVerification.js.map +1 -0
  270. package/build/dist/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.js +13 -12
  271. package/build/dist/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.js.map +1 -1
  272. package/build/dist/Server/Utils/Monitor/MonitorAlert.js +20 -17
  273. package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
  274. package/build/dist/Server/Utils/Monitor/MonitorIncident.js +17 -14
  275. package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
  276. package/build/dist/Server/Utils/Monitor/MonitorResourceContext.js +95 -0
  277. package/build/dist/Server/Utils/Monitor/MonitorResourceContext.js.map +1 -0
  278. package/build/dist/Server/Utils/Monitor/MonitorStepResourceIdentity.js +313 -0
  279. package/build/dist/Server/Utils/Monitor/MonitorStepResourceIdentity.js.map +1 -0
  280. package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js +3 -3
  281. package/build/dist/Server/Utils/Monitor/SeriesResourceLinker.js +67 -26
  282. package/build/dist/Server/Utils/Monitor/SeriesResourceLinker.js.map +1 -1
  283. package/build/dist/Server/Utils/TotpAuth.js +127 -8
  284. package/build/dist/Server/Utils/TotpAuth.js.map +1 -1
  285. package/build/dist/Server/Utils/UserRegistrationToken.js +170 -0
  286. package/build/dist/Server/Utils/UserRegistrationToken.js.map +1 -0
  287. package/build/dist/Server/Utils/VerificationCode.js +120 -0
  288. package/build/dist/Server/Utils/VerificationCode.js.map +1 -0
  289. package/build/dist/Types/Email/EmailTemplateType.js +1 -0
  290. package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
  291. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +42 -21
  292. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
  293. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js +77 -5
  294. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js.map +1 -1
  295. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js +18 -6
  296. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js.map +1 -1
  297. package/build/dist/Types/Monitor/ServiceAlertTemplates.js +1028 -0
  298. package/build/dist/Types/Monitor/ServiceAlertTemplates.js.map +1 -0
  299. package/build/dist/Types/Permission.js +33 -0
  300. package/build/dist/Types/Permission.js.map +1 -1
  301. package/build/dist/Types/PushNotification/AndroidNotificationChannel.js +27 -0
  302. package/build/dist/Types/PushNotification/AndroidNotificationChannel.js.map +1 -0
  303. package/build/dist/Types/Service/ServiceLanguage.js +96 -0
  304. package/build/dist/Types/Service/ServiceLanguage.js.map +1 -0
  305. package/build/dist/Types/Text.js +82 -17
  306. package/build/dist/Types/Text.js.map +1 -1
  307. package/build/dist/UI/Components/Button/Button.js +22 -14
  308. package/build/dist/UI/Components/Button/Button.js.map +1 -1
  309. package/build/dist/UI/Components/CodeBlock/CodeBlock.js +35 -3
  310. package/build/dist/UI/Components/CodeBlock/CodeBlock.js.map +1 -1
  311. package/build/dist/UI/Components/CodeBlock/LanguageRegistry.js +57 -0
  312. package/build/dist/UI/Components/CodeBlock/LanguageRegistry.js.map +1 -0
  313. package/build/dist/UI/Components/CommandPalette/CommandPalette.js +439 -0
  314. package/build/dist/UI/Components/CommandPalette/CommandPalette.js.map +1 -0
  315. package/build/dist/UI/Components/CommandPalette/PaletteFilter.js +135 -0
  316. package/build/dist/UI/Components/CommandPalette/PaletteFilter.js.map +1 -0
  317. package/build/dist/UI/Components/CommandPalette/PaletteRow.js +83 -0
  318. package/build/dist/UI/Components/CommandPalette/PaletteRow.js.map +1 -0
  319. package/build/dist/UI/Components/CommandPalette/RecentCommands.js +47 -0
  320. package/build/dist/UI/Components/CommandPalette/RecentCommands.js.map +1 -0
  321. package/build/dist/UI/Components/CommandPalette/Types.js +2 -0
  322. package/build/dist/UI/Components/CommandPalette/Types.js.map +1 -0
  323. package/build/dist/UI/Components/CommandPalette/UseProviderSearch.js +88 -0
  324. package/build/dist/UI/Components/CommandPalette/UseProviderSearch.js.map +1 -0
  325. package/build/dist/UI/Components/Dropdown/Dropdown.js +6 -1
  326. package/build/dist/UI/Components/Dropdown/Dropdown.js.map +1 -1
  327. package/build/dist/UI/Components/Feed/FeedItem.js +1 -1
  328. package/build/dist/UI/Components/Feed/FeedItem.js.map +1 -1
  329. package/build/dist/UI/Components/List/List.js +19 -5
  330. package/build/dist/UI/Components/List/List.js.map +1 -1
  331. package/build/dist/UI/Components/List/ListSkeleton.js +21 -0
  332. package/build/dist/UI/Components/List/ListSkeleton.js.map +1 -0
  333. package/build/dist/UI/Components/Markdown.tsx/LazyMarkdownViewer.js.map +1 -1
  334. package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js +52 -25
  335. package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js.map +1 -1
  336. package/build/dist/UI/Components/Modal/Modal.js +2 -2
  337. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +1 -1
  338. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  339. package/build/dist/UI/Components/ModelTable/useCustomFieldColumns.js +9 -2
  340. package/build/dist/UI/Components/ModelTable/useCustomFieldColumns.js.map +1 -1
  341. package/build/dist/UI/Components/MoreMenu/MoreMenu.js +32 -1
  342. package/build/dist/UI/Components/MoreMenu/MoreMenu.js.map +1 -1
  343. package/build/dist/UI/Components/Navbar/NavBar.js +5 -1
  344. package/build/dist/UI/Components/Navbar/NavBar.js.map +1 -1
  345. package/build/dist/UI/Components/OrderedStatesList/OrderedStatesList.js +29 -5
  346. package/build/dist/UI/Components/OrderedStatesList/OrderedStatesList.js.map +1 -1
  347. package/build/dist/UI/Components/SideMenu/CountModelSideMenuItem.js +23 -1
  348. package/build/dist/UI/Components/SideMenu/CountModelSideMenuItem.js.map +1 -1
  349. package/build/dist/UI/Components/SideOver/SideOver.js +23 -2
  350. package/build/dist/UI/Components/SideOver/SideOver.js.map +1 -1
  351. package/build/dist/UI/Components/Skeleton/Skeleton.js +23 -0
  352. package/build/dist/UI/Components/Skeleton/Skeleton.js.map +1 -0
  353. package/build/dist/UI/Components/Table/Table.js +35 -24
  354. package/build/dist/UI/Components/Table/Table.js.map +1 -1
  355. package/build/dist/UI/Components/Table/TableSkeletonRows.js +52 -0
  356. package/build/dist/UI/Components/Table/TableSkeletonRows.js.map +1 -0
  357. package/build/dist/UI/Components/Tabs/Tab.js +1 -1
  358. package/build/dist/UI/Components/Tabs/Tab.js.map +1 -1
  359. package/build/dist/UI/Components/Toast/Toast.js +77 -23
  360. package/build/dist/UI/Components/Toast/Toast.js.map +1 -1
  361. package/build/dist/UI/Components/Toast/ToastInit.js +37 -15
  362. package/build/dist/UI/Components/Toast/ToastInit.js.map +1 -1
  363. package/build/dist/UI/Utils/ModelAPI/ModelAPI.js +18 -9
  364. package/build/dist/UI/Utils/ModelAPI/ModelAPI.js.map +1 -1
  365. package/build/dist/UI/Utils/ModelListCache.js +126 -0
  366. package/build/dist/UI/Utils/ModelListCache.js.map +1 -0
  367. package/build/dist/UI/Utils/Project.js +24 -1
  368. package/build/dist/UI/Utils/Project.js.map +1 -1
  369. package/build/dist/Utils/API.js +6 -1
  370. package/build/dist/Utils/API.js.map +1 -1
  371. package/jest.config.json +1 -1
  372. package/package.json +2 -3
  373. package/Server/Utils/Monitor/MonitorClusterContext.ts +0 -182
  374. package/Tests/__mocks__/otpauth.js +0 -30
  375. package/build/dist/Server/Utils/Monitor/MonitorClusterContext.js +0 -141
  376. package/build/dist/Server/Utils/Monitor/MonitorClusterContext.js.map +0 -1
@@ -0,0 +1,53 @@
1
+ import React, { FunctionComponent, ReactElement } from "react";
2
+
3
+ /*
4
+ * Width variants for skeleton lines. Cycled by index (never Math.random) so
5
+ * the shimmer is stable across re-renders - random widths re-roll on every
6
+ * render, which reads as flicker - and so tests can assert exact widths.
7
+ */
8
+ const WIDTH_VARIANTS: Array<string> = ["w-3/4", "w-1/2", "w-2/3"];
9
+
10
+ export type GetSkeletonWidthClassFunction = (index: number) => string;
11
+
12
+ export const getSkeletonWidthClass: GetSkeletonWidthClassFunction = (
13
+ index: number,
14
+ ): string => {
15
+ return WIDTH_VARIANTS[Math.abs(index) % WIDTH_VARIANTS.length] as string;
16
+ };
17
+
18
+ export interface ComponentProps {
19
+ className?: string | undefined;
20
+ /*
21
+ * When set, a deterministic width variant (w-3/4 / w-1/2 / w-2/3, cycling)
22
+ * is appended so a stack of lines looks like ragged text instead of a
23
+ * uniform block. Leave undefined when className already sizes the block.
24
+ */
25
+ widthVariantIndex?: number | undefined;
26
+ dataTestId?: string | undefined;
27
+ }
28
+
29
+ /*
30
+ * A single pulsing placeholder block. Purely decorative - the wrapper that
31
+ * composes skeletons into a loading state owns the role="status" / sr-only
32
+ * announcement, so each block hides itself from the accessibility tree.
33
+ */
34
+ const Skeleton: FunctionComponent<ComponentProps> = (
35
+ props: ComponentProps,
36
+ ): ReactElement => {
37
+ const widthClass: string =
38
+ props.widthVariantIndex === undefined
39
+ ? ""
40
+ : ` ${getSkeletonWidthClass(props.widthVariantIndex)}`;
41
+
42
+ return (
43
+ <div
44
+ data-testid={props.dataTestId || "skeleton"}
45
+ aria-hidden={true}
46
+ className={`animate-pulse rounded bg-gray-200${
47
+ props.className ? ` ${props.className}` : ""
48
+ }${widthClass}`}
49
+ ></div>
50
+ );
51
+ };
52
+
53
+ export default Skeleton;
@@ -7,7 +7,6 @@ import BulkUpdateForm, {
7
7
  BulkActionButtonSchema,
8
8
  BulkActionOnClickProps,
9
9
  } from "../BulkUpdate/BulkUpdateForm";
10
- import ComponentLoader from "../ComponentLoader/ComponentLoader";
11
10
  import ErrorMessage from "../ErrorMessage/ErrorMessage";
12
11
  import FilterViewer from "../Filters/FilterViewer";
13
12
  import Filter from "../Filters/Types/Filter";
@@ -15,6 +14,7 @@ import FilterData from "../Filters/Types/FilterData";
15
14
  import Pagination from "../Pagination/Pagination";
16
15
  import TableBody from "./TableBody";
17
16
  import TableHeader from "./TableHeader";
17
+ import TableSkeletonRows from "./TableSkeletonRows";
18
18
  import Columns from "./Types/Columns";
19
19
  import SortOrder from "../../../Types/BaseDatabase/SortOrder";
20
20
  import GenericObject from "../../../Types/GenericObject";
@@ -211,22 +211,34 @@ const Table: TableFunction = <T extends GenericObject>(
211
211
  colspan = 1;
212
212
  }
213
213
 
214
+ /*
215
+ * A refetch with rows already on screen (pagination, sort, refresh - the
216
+ * parent never clears `data` while fetching) keeps those rows visible and
217
+ * dims them instead of tearing the layout down to placeholders. Skeletons
218
+ * are only for a load with nothing to show yet.
219
+ */
220
+ const isRefetchingWithData: boolean =
221
+ props.isLoading && props.data.length > 0;
222
+
214
223
  const getTablebody: GetReactElementFunction = (): ReactElement => {
215
- if (props.isLoading) {
224
+ if (props.isLoading && props.data.length === 0) {
216
225
  return (
217
- <tbody>
218
- <tr>
219
- <td colSpan={colspan}>
220
- <div className="flex justify-center w-full">
221
- <ComponentLoader />
222
- </div>
223
- </td>
224
- </tr>
225
- </tbody>
226
+ <TableSkeletonRows
227
+ columns={props.columns}
228
+ enableDragAndDrop={props.enableDragAndDrop}
229
+ isBulkActionsEnabled={isBulkActionsEnabled}
230
+ itemsOnPage={props.itemsOnPage}
231
+ isMobile={isMobile}
232
+ />
226
233
  );
227
234
  }
228
235
 
229
- if (props.error) {
236
+ /*
237
+ * Loading still wins over error and empty (same priority as before the
238
+ * skeletons): while a refetch is in flight the stale rows render, never a
239
+ * stale error or a premature "no items".
240
+ */
241
+ if (!props.isLoading && props.error) {
230
242
  return (
231
243
  <tbody>
232
244
  <tr>
@@ -260,7 +272,7 @@ const Table: TableFunction = <T extends GenericObject>(
260
272
  );
261
273
  }
262
274
 
263
- if (props.filterError) {
275
+ if (!props.isLoading && props.filterError) {
264
276
  return <></>;
265
277
  }
266
278
 
@@ -418,38 +430,56 @@ const Table: TableFunction = <T extends GenericObject>(
418
430
  : "overflow-hidden border-t border-gray-200"
419
431
  }
420
432
  >
421
- {isMobile ? (
422
- // Mobile view: render as list
423
- <div className="min-w-full divide-y divide-gray-200">
424
- {getTablebody()}
425
- </div>
426
- ) : (
427
- // Desktop view: render as table
428
- <table className="min-w-full divide-y divide-gray-200">
429
- <TableHeader
430
- id={`${props.id}-header`}
431
- columns={props.columns}
432
- onSortChanged={props.onSortChanged}
433
- enableDragAndDrop={props.enableDragAndDrop}
434
- sortBy={props.sortBy}
435
- sortOrder={props.sortOrder}
436
- isBulkActionsEnabled={isBulkActionsEnabled}
437
- onAllItemsDeselected={() => {
438
- setIsAllItemsSelected(false);
439
- props.onBulkClearAllItems?.();
440
- }}
441
- onAllItemsOnThePageSelected={() => {
442
- if (props.onBulkSelectItemsOnCurrentPage) {
443
- props.onBulkSelectItemsOnCurrentPage();
433
+ {/*
434
+ * Dims the stale rows (header included) while a refetch is in
435
+ * flight and blocks clicks on them - a sort or row action
436
+ * against data about to be replaced is a race. The wrapper
437
+ * sits OUTSIDE the <table> because a <div> cannot legally wrap
438
+ * a <tbody> inside one.
439
+ */}
440
+ <div
441
+ data-testid="table-content"
442
+ className={
443
+ isRefetchingWithData
444
+ ? "opacity-60 pointer-events-none transition-opacity duration-150"
445
+ : "transition-opacity duration-150"
446
+ }
447
+ >
448
+ {isMobile ? (
449
+ // Mobile view: render as list
450
+ <div className="min-w-full divide-y divide-gray-200">
451
+ {getTablebody()}
452
+ </div>
453
+ ) : (
454
+ // Desktop view: render as table
455
+ <table className="min-w-full divide-y divide-gray-200">
456
+ <TableHeader
457
+ id={`${props.id}-header`}
458
+ columns={props.columns}
459
+ onSortChanged={props.onSortChanged}
460
+ enableDragAndDrop={props.enableDragAndDrop}
461
+ sortBy={props.sortBy}
462
+ sortOrder={props.sortOrder}
463
+ isBulkActionsEnabled={isBulkActionsEnabled}
464
+ onAllItemsDeselected={() => {
465
+ setIsAllItemsSelected(false);
466
+ props.onBulkClearAllItems?.();
467
+ }}
468
+ onAllItemsOnThePageSelected={() => {
469
+ if (props.onBulkSelectItemsOnCurrentPage) {
470
+ props.onBulkSelectItemsOnCurrentPage();
471
+ }
472
+ }}
473
+ isAllItemsOnThePageSelected={isAllItemsOnThePageSelected}
474
+ isSomeItemsOnThePageSelected={
475
+ isSomeItemsOnThePageSelected
444
476
  }
445
- }}
446
- isAllItemsOnThePageSelected={isAllItemsOnThePageSelected}
447
- isSomeItemsOnThePageSelected={isSomeItemsOnThePageSelected}
448
- hasTableItems={selectableRowsOnThePage.length > 0}
449
- />
450
- {getTablebody()}
451
- </table>
452
- )}
477
+ hasTableItems={selectableRowsOnThePage.length > 0}
478
+ />
479
+ {getTablebody()}
480
+ </table>
481
+ )}
482
+ </div>
453
483
  </div>
454
484
  </div>
455
485
  </div>
@@ -0,0 +1,141 @@
1
+ import Skeleton from "../Skeleton/Skeleton";
2
+ import Column from "./Types/Column";
3
+ import Columns from "./Types/Columns";
4
+ import GenericObject from "../../../Types/GenericObject";
5
+ import React, { ReactElement } from "react";
6
+
7
+ export interface ComponentProps<T extends GenericObject> {
8
+ columns: Columns<T>;
9
+ /*
10
+ * The same feature flags TableHeader renders leading cells for. The
11
+ * skeleton must mirror them exactly or its cells sit misaligned under the
12
+ * header while loading.
13
+ */
14
+ enableDragAndDrop?: undefined | boolean;
15
+ isBulkActionsEnabled?: undefined | boolean;
16
+ itemsOnPage: number;
17
+ /*
18
+ * Mobile renders card-shaped placeholders inside the table's mobile <div>
19
+ * wrapper - <tbody> markup is invalid there - and drops hideOnMobile
20
+ * columns, same as TableHeader and TableRow do.
21
+ */
22
+ isMobile: boolean;
23
+ }
24
+
25
+ type TableSkeletonRowsFunction = <T extends GenericObject>(
26
+ props: ComponentProps<T>,
27
+ ) => ReactElement;
28
+
29
+ /*
30
+ * Layout-preserving placeholder rows for the table's first load: one pulsing
31
+ * cell per visible column (plus the drag-handle / bulk-select extras) so the
32
+ * page keeps the table's shape instead of collapsing to a centered spinner.
33
+ */
34
+ const TableSkeletonRows: TableSkeletonRowsFunction = <T extends GenericObject>(
35
+ props: ComponentProps<T>,
36
+ ): ReactElement => {
37
+ // Enough rows to look like a page of data without painting offscreen ones.
38
+ const rowCount: number = Math.max(1, Math.min(props.itemsOnPage || 0, 10));
39
+ const rowIndexes: Array<number> = Array.from(Array(rowCount).keys());
40
+
41
+ // Same filter as TableHeader / TableRow so cell counts always agree.
42
+ const visibleColumns: Columns<T> = props.columns.filter(
43
+ (column: Column<T>) => {
44
+ return !(column.hideOnMobile && props.isMobile);
45
+ },
46
+ );
47
+
48
+ if (props.isMobile) {
49
+ return (
50
+ <div
51
+ data-testid="table-skeleton-loader"
52
+ role="status"
53
+ aria-live="polite"
54
+ className="divide-y divide-gray-200 bg-white"
55
+ >
56
+ <span className="sr-only">Loading...</span>
57
+ {rowIndexes.map((rowIndex: number) => {
58
+ return (
59
+ <div
60
+ key={rowIndex}
61
+ className="p-4 bg-white border-b border-gray-200"
62
+ >
63
+ <div className="space-y-3">
64
+ {visibleColumns.map(
65
+ (_column: Column<T>, columnIndex: number) => {
66
+ return (
67
+ <div
68
+ key={columnIndex}
69
+ className="flex flex-col space-y-1"
70
+ >
71
+ <Skeleton className="h-3 w-24" />
72
+ <Skeleton
73
+ className="h-4"
74
+ widthVariantIndex={rowIndex + columnIndex}
75
+ />
76
+ </div>
77
+ );
78
+ },
79
+ )}
80
+ </div>
81
+ </div>
82
+ );
83
+ })}
84
+ </div>
85
+ );
86
+ }
87
+
88
+ return (
89
+ <tbody
90
+ data-testid="table-skeleton-loader"
91
+ role="status"
92
+ aria-live="polite"
93
+ className="divide-y divide-gray-200 bg-white"
94
+ >
95
+ {rowIndexes.map((rowIndex: number) => {
96
+ return (
97
+ <tr key={rowIndex}>
98
+ {props.enableDragAndDrop && (
99
+ <td className="ml-5 py-4 w-10 align-top">
100
+ <Skeleton className="ml-6 h-5 w-5" />
101
+ </td>
102
+ )}
103
+ {props.isBulkActionsEnabled && (
104
+ <td className="w-10 py-3.5 align-top">
105
+ <div className="ml-5">
106
+ <Skeleton className="h-4 w-4" />
107
+ </div>
108
+ </td>
109
+ )}
110
+ {visibleColumns.map((_column: Column<T>, columnIndex: number) => {
111
+ /*
112
+ * Cell classes copied from TableRow's real cells so the
113
+ * skeleton's rhythm and padding match the rows that replace it.
114
+ */
115
+ let className: string =
116
+ "whitespace-nowrap py-4 pl-4 pr-3 text-sm font-medium text-gray-500 sm:pl-6 align-top";
117
+ if (columnIndex === visibleColumns.length - 1) {
118
+ className =
119
+ "whitespace-nowrap py-4 pl-4 pr-6 text-sm font-medium text-gray-500 sm:pl-6 align-top";
120
+ }
121
+
122
+ return (
123
+ <td key={columnIndex} className={className}>
124
+ {rowIndex === 0 && columnIndex === 0 && (
125
+ <span className="sr-only">Loading...</span>
126
+ )}
127
+ <Skeleton
128
+ className="h-4"
129
+ widthVariantIndex={rowIndex + columnIndex}
130
+ />
131
+ </td>
132
+ );
133
+ })}
134
+ </tr>
135
+ );
136
+ })}
137
+ </tbody>
138
+ );
139
+ };
140
+
141
+ export default TableSkeletonRows;
@@ -31,7 +31,7 @@ const TabElement: FunctionComponent<ComponentProps> = (
31
31
  const backgroundColor: string = "bg-gray-100";
32
32
 
33
33
  const baseClasses: string =
34
- "rounded-md px-3 py-2 text-sm font-medium cursor-pointer inline-flex whitespace-nowrap flex-shrink-0";
34
+ "rounded-md px-3 py-2 text-sm font-medium cursor-pointer inline-flex whitespace-nowrap flex-shrink-0 transition-colors duration-150 focus:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500 focus-visible:ring-offset-2";
35
35
  const stateClasses: string = props.isSelected
36
36
  ? `${backgroundColor} text-gray-700`
37
37
  : "text-gray-500 hover:text-gray-700";
@@ -1,4 +1,10 @@
1
- import React, { FunctionComponent, ReactElement, useState } from "react";
1
+ import React, {
2
+ FunctionComponent,
3
+ ReactElement,
4
+ useEffect,
5
+ useRef,
6
+ useState,
7
+ } from "react";
2
8
  import Icon from "../Icon/Icon";
3
9
  import IconProp from "../../../Types/Icon/IconProp";
4
10
  import useTranslateValue from "../../Utils/Translation";
@@ -17,14 +23,78 @@ export interface ComponentProps {
17
23
  onClose?: undefined | (() => void);
18
24
  type?: undefined | ToastType;
19
25
  icon?: IconProp | undefined;
20
- index?: undefined | number;
21
26
  }
22
27
 
28
+ /* How long the exit fade runs before the toast actually unmounts. */
29
+ const EXIT_DURATION_IN_MS: number = 150;
30
+
23
31
  const Component: FunctionComponent<ComponentProps> = (
24
32
  props: ComponentProps,
25
33
  ): ReactElement => {
26
34
  const { translateString } = useTranslateValue();
27
35
  const [show, setShow] = useState<boolean>(true);
36
+
37
+ /*
38
+ * The toast is mounted in its closed state (faded, nudged down) and flipped
39
+ * open one frame later so the browser has something to transition from —
40
+ * the same pattern Modal uses for its entrance.
41
+ */
42
+ const [hasEntered, setHasEntered] = useState<boolean>(false);
43
+
44
+ /*
45
+ * Dismissal fades the card out first and only unmounts (and notifies the
46
+ * owner) once the fade has finished, so the toast never blinks away.
47
+ */
48
+ const [isLeaving, setIsLeaving] = useState<boolean>(false);
49
+
50
+ useEffect(() => {
51
+ const open: () => void = (): void => {
52
+ setHasEntered(true);
53
+ };
54
+
55
+ const frame: number = requestAnimationFrame(open);
56
+
57
+ /*
58
+ * A hidden or throttled tab never runs an animation frame; the timer
59
+ * skips the transition rather than leaving the toast at zero opacity.
60
+ */
61
+ const fallbackTimer: ReturnType<typeof setTimeout> = setTimeout(open, 80);
62
+
63
+ return () => {
64
+ cancelAnimationFrame(frame);
65
+ clearTimeout(fallbackTimer);
66
+ };
67
+ }, []);
68
+
69
+ /*
70
+ * The latest onClose lives in a ref so the exit effect can depend on
71
+ * isLeaving alone. Owners may recreate onClose every render, and a dep on
72
+ * it would restart the unmount timer whenever a sibling toast re-renders
73
+ * the stack mid-exit — leaving an invisible pointer-events-auto card
74
+ * intercepting clicks past its original deadline.
75
+ */
76
+ const onCloseRef: React.MutableRefObject<(() => void) | undefined> = useRef<
77
+ (() => void) | undefined
78
+ >(props.onClose);
79
+ onCloseRef.current = props.onClose;
80
+
81
+ useEffect(() => {
82
+ if (!isLeaving) {
83
+ return undefined;
84
+ }
85
+
86
+ const exitTimer: ReturnType<typeof setTimeout> = setTimeout(() => {
87
+ setShow(false);
88
+ if (onCloseRef.current) {
89
+ onCloseRef.current();
90
+ }
91
+ }, EXIT_DURATION_IN_MS);
92
+
93
+ return () => {
94
+ clearTimeout(exitTimer);
95
+ };
96
+ }, [isLeaving]);
97
+
28
98
  let typeCssClass: string = "text-gray-400";
29
99
  let iconType: IconProp = IconProp.Info;
30
100
 
@@ -53,65 +123,60 @@ const Component: FunctionComponent<ComponentProps> = (
53
123
  iconType = props.icon;
54
124
  }
55
125
 
56
- let top: number = 0;
126
+ /*
127
+ * Settled state carries no transform class at all — leaving a translate on
128
+ * the card would make it the containing block for position:fixed
129
+ * descendants (the Modal invariant).
130
+ */
131
+ let motionClassName: string = "translate-y-2 opacity-0";
57
132
 
58
- if (props.index) {
59
- top = props.index * 16; // move the second item lower than the first one. 16 is the height of the toast.
133
+ if (isLeaving) {
134
+ motionClassName = "opacity-0";
135
+ } else if (hasEntered) {
136
+ motionClassName = "opacity-100";
60
137
  }
61
138
 
62
139
  if (show) {
63
140
  return (
64
141
  <div
65
142
  data-testid="toast"
66
- aria-live="assertive"
67
- className={`pointer-events-none fixed z-40 top-${top} left-0 right-0 flex items-end px-4 py-6 sm:items-start sm:p-6`}
143
+ className={`pointer-events-auto w-full max-w-sm overflow-hidden rounded-lg bg-white shadow-lg ring-1 ring-black ring-opacity-5 transition duration-150 ease-out motion-reduce:transition-none ${motionClassName}`}
68
144
  >
69
- <div className="flex w-full flex-col items-center space-y-4 sm:items-end">
70
- <div className="pointer-events-auto w-full max-w-sm overflow-hidden rounded-lg bg-white shadow-lg ring-1 ring-black ring-opacity-5">
71
- <div className="p-4">
72
- <div className="flex items-start">
73
- <div className="flex-shrink-0">
74
- <Icon
75
- className={`h-6 w-6 ${typeCssClass}`}
76
- data-testid="toast-icon"
77
- icon={iconType}
78
- />
79
- </div>
80
- <div className="ml-3 w-0 flex-1 pt-0.5">
81
- <p
82
- data-testid="title"
83
- className="text-sm font-medium text-gray-900"
84
- >
85
- {translateString(props.title)}
86
- </p>
87
- <p
88
- data-testid="description"
89
- className="mt-1 text-sm text-gray-500"
90
- >
91
- {translateString(props.description)}
92
- </p>
93
- {/* <div className="mt-3 flex space-x-7">
94
- <button type="button" className="rounded-md bg-white text-sm font-medium text-indigo-600 hover:text-indigo-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">Undo</button>
95
- <button type="button" className="rounded-md bg-white text-sm font-medium text-gray-700 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">Dismiss</button>
96
- </div> */}
97
- </div>
98
- <div className="ml-4 flex flex-shrink-0">
99
- <button
100
- onClick={() => {
101
- setShow(false);
102
- if (props.onClose) {
103
- props.onClose();
104
- }
105
- }}
106
- data-testid="close-button"
107
- type="button"
108
- className="inline-flex rounded-md bg-white text-gray-400 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
109
- >
110
- <span className="sr-only">Close</span>
111
- <Icon className={`h-5 w-5`} icon={IconProp.Close} />
112
- </button>
113
- </div>
114
- </div>
145
+ <div className="p-4">
146
+ <div className="flex items-start">
147
+ <div className="flex-shrink-0">
148
+ <Icon
149
+ className={`h-6 w-6 ${typeCssClass}`}
150
+ data-testid="toast-icon"
151
+ icon={iconType}
152
+ />
153
+ </div>
154
+ <div className="ml-3 w-0 flex-1 pt-0.5">
155
+ <p
156
+ data-testid="title"
157
+ className="text-sm font-medium text-gray-900"
158
+ >
159
+ {translateString(props.title)}
160
+ </p>
161
+ <p
162
+ data-testid="description"
163
+ className="mt-1 text-sm text-gray-500"
164
+ >
165
+ {translateString(props.description)}
166
+ </p>
167
+ </div>
168
+ <div className="ml-4 flex flex-shrink-0">
169
+ <button
170
+ onClick={() => {
171
+ setIsLeaving(true);
172
+ }}
173
+ data-testid="close-button"
174
+ type="button"
175
+ className="inline-flex rounded-md bg-white text-gray-400 transition-colors duration-150 ease-out hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
176
+ >
177
+ <span className="sr-only">Close</span>
178
+ <Icon className={`h-5 w-5`} icon={IconProp.Close} />
179
+ </button>
115
180
  </div>
116
181
  </div>
117
182
  </div>