sanity 6.14.0 → 6.14.1

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 (163) hide show
  1. package/lib/{AddonDatasetProvider-0aiLWkZg.js → AddonDatasetProvider-C9tdum2G.js} +2 -2
  2. package/lib/{AddonDatasetProvider-0aiLWkZg.js.map → AddonDatasetProvider-C9tdum2G.js.map} +1 -1
  3. package/lib/{CalendarFilter-DVz369RP.js → CalendarFilter-C80uOkw-.js} +3 -3
  4. package/lib/{CalendarFilter-DVz369RP.js.map → CalendarFilter-C80uOkw-.js.map} +1 -1
  5. package/lib/{CommandList-CTDV_QZY.js → CommandList-duj-LVnd.js} +2 -2
  6. package/lib/{CommandList-CTDV_QZY.js.map → CommandList-duj-LVnd.js.map} +1 -1
  7. package/lib/{CommentInput-B5T1Iwnt.js → CommentInput-BXYQnGhq.js} +5 -5
  8. package/lib/{CommentInput-B5T1Iwnt.js.map → CommentInput-BXYQnGhq.js.map} +1 -1
  9. package/lib/{CommentsDocumentLayout-ByFwej_y.js → CommentsDocumentLayout-DAwAhx7q.js} +2 -2
  10. package/lib/{CommentsDocumentLayout-ByFwej_y.js.map → CommentsDocumentLayout-DAwAhx7q.js.map} +1 -1
  11. package/lib/{CommentsDocumentLayout-Czb6fC0_.js → CommentsDocumentLayout-pfM29WSy.js} +2 -2
  12. package/lib/{CommentsDocumentLayout-Czb6fC0_.js.map → CommentsDocumentLayout-pfM29WSy.js.map} +1 -1
  13. package/lib/{CommentsEnabledProvider-D2gutvsb.js → CommentsEnabledProvider-DN_oXwXM.js} +3 -3
  14. package/lib/{CommentsEnabledProvider-D2gutvsb.js.map → CommentsEnabledProvider-DN_oXwXM.js.map} +1 -1
  15. package/lib/{CommentsField-D2Fum0Jx.js → CommentsField-B7wTBRMB.js} +5 -5
  16. package/lib/{CommentsField-D2Fum0Jx.js.map → CommentsField-B7wTBRMB.js.map} +1 -1
  17. package/lib/{CommentsField-YM3cp3fA.js → CommentsField-BxoVuJOl.js} +4 -4
  18. package/lib/{CommentsField-YM3cp3fA.js.map → CommentsField-BxoVuJOl.js.map} +1 -1
  19. package/lib/{CommentsInput-Bx2t5AW_.js → CommentsInput-C3rEb5L8.js} +6 -6
  20. package/lib/{CommentsInput-Bx2t5AW_.js.map → CommentsInput-C3rEb5L8.js.map} +1 -1
  21. package/lib/{CommentsInput-BBBng3CJ.js → CommentsInput-CU-PFXmu.js} +7 -7
  22. package/lib/{CommentsInput-BBBng3CJ.js.map → CommentsInput-CU-PFXmu.js.map} +1 -1
  23. package/lib/{CommentsInspector-BnSG5Mq0.js → CommentsInspector-BJ1qwj6P.js} +6 -6
  24. package/lib/{CommentsInspector-BnSG5Mq0.js.map → CommentsInspector-BJ1qwj6P.js.map} +1 -1
  25. package/lib/{CommentsInspector-B5V_Bpz5.js → CommentsInspector-BQiMPjvm.js} +6 -6
  26. package/lib/{CommentsInspector-B5V_Bpz5.js.map → CommentsInspector-BQiMPjvm.js.map} +1 -1
  27. package/lib/{CommentsListItem-DnqAlN4p.js → CommentsListItem-QyYan1DB.js} +5 -5
  28. package/lib/{CommentsListItem-DnqAlN4p.js.map → CommentsListItem-QyYan1DB.js.map} +1 -1
  29. package/lib/{CommentsListItem-DVE4IMls.js → CommentsListItem-dvKmANi3.js} +4 -4
  30. package/lib/{CommentsListItem-DVE4IMls.js.map → CommentsListItem-dvKmANi3.js.map} +1 -1
  31. package/lib/{CommentsSelectedPathProvider-DRJ3Xqs4.js → CommentsSelectedPathProvider-COcPb3W3.js} +3 -3
  32. package/lib/{CommentsSelectedPathProvider-DRJ3Xqs4.js.map → CommentsSelectedPathProvider-COcPb3W3.js.map} +1 -1
  33. package/lib/{CommentsStudioLayout-Di510XhD.js → CommentsStudioLayout-BkX6o14w.js} +3 -3
  34. package/lib/{CommentsStudioLayout-Di510XhD.js.map → CommentsStudioLayout-BkX6o14w.js.map} +1 -1
  35. package/lib/{CommentsStudioLayout-Z09s50bM.js → CommentsStudioLayout-dIXEz52s.js} +3 -3
  36. package/lib/{CommentsStudioLayout-Z09s50bM.js.map → CommentsStudioLayout-dIXEz52s.js.map} +1 -1
  37. package/lib/{GlobalPerspectiveMenu-Cwur4_iD.js → GlobalPerspectiveMenu-0Hs276Z-.js} +15 -15
  38. package/lib/{GlobalPerspectiveMenu-Cwur4_iD.js.map → GlobalPerspectiveMenu-0Hs276Z-.js.map} +1 -1
  39. package/lib/{LoadingBlock-Ch_dBXfn.js → LoadingBlock-CElIdb7F.js} +3 -3
  40. package/lib/{LoadingBlock-Ch_dBXfn.js.map → LoadingBlock-CElIdb7F.js.map} +1 -1
  41. package/lib/{PerspectiveProvider-Yk7lgugx.js → PerspectiveProvider-D-6sweQH.js} +130 -97
  42. package/lib/PerspectiveProvider-D-6sweQH.js.map +1 -0
  43. package/lib/{ReleaseAvatar-C68bGuVQ.js → ReleaseAvatar-Bqp_Ci7r.js} +4 -4
  44. package/lib/{ReleaseAvatar-C68bGuVQ.js.map → ReleaseAvatar-Bqp_Ci7r.js.map} +1 -1
  45. package/lib/{ReleasesMetadataProvider-DabLuMD8.js → ReleasesMetadataProvider-BD6XRcpT.js} +2 -2
  46. package/lib/{ReleasesMetadataProvider-DabLuMD8.js.map → ReleasesMetadataProvider-BD6XRcpT.js.map} +1 -1
  47. package/lib/{ReleasesStudioLayout-DsygG30q.js → ReleasesStudioLayout-C6mmxoaY.js} +7 -7
  48. package/lib/{ReleasesStudioLayout-DsygG30q.js.map → ReleasesStudioLayout-C6mmxoaY.js.map} +1 -1
  49. package/lib/{ReleasesTool-CNXNODI_.js → ReleasesTool-DIDmkzic.js} +23 -23
  50. package/lib/{ReleasesTool-CNXNODI_.js.map → ReleasesTool-DIDmkzic.js.map} +1 -1
  51. package/lib/{SchedulePublishingStudioLayout-EsgEGZ7F.js → SchedulePublishingStudioLayout-DrZO-qbI.js} +3 -3
  52. package/lib/{SchedulePublishingStudioLayout-EsgEGZ7F.js.map → SchedulePublishingStudioLayout-DrZO-qbI.js.map} +1 -1
  53. package/lib/{SchedulePublishingUpsellProvider-CWxgqzFp.js → SchedulePublishingUpsellProvider-DeZ_jZIX.js} +2 -2
  54. package/lib/{SchedulePublishingUpsellProvider-CWxgqzFp.js.map → SchedulePublishingUpsellProvider-DeZ_jZIX.js.map} +1 -1
  55. package/lib/{ScheduledPublishingEnabledProvider-CQ-T1Y96.js → ScheduledPublishingEnabledProvider-B8C0_tc5.js} +3 -3
  56. package/lib/{ScheduledPublishingEnabledProvider-CQ-T1Y96.js.map → ScheduledPublishingEnabledProvider-B8C0_tc5.js.map} +1 -1
  57. package/lib/{SearchProvider-CEXmRg1N.js → SearchProvider-T8fsDJV5.js} +8 -8
  58. package/lib/{SearchProvider-CEXmRg1N.js.map → SearchProvider-T8fsDJV5.js.map} +1 -1
  59. package/lib/{SingleDocReleaseLayout-ByDXFS8N.js → SingleDocReleaseLayout-BpMXU9KY.js} +2 -2
  60. package/lib/{SingleDocReleaseLayout-ByDXFS8N.js.map → SingleDocReleaseLayout-BpMXU9KY.js.map} +1 -1
  61. package/lib/{SingleDocReleaseUpsellProvider-ByuDpBIG.js → SingleDocReleaseUpsellProvider-7_OXHySY.js} +3 -3
  62. package/lib/{SingleDocReleaseUpsellProvider-ByuDpBIG.js.map → SingleDocReleaseUpsellProvider-7_OXHySY.js.map} +1 -1
  63. package/lib/{TasksFooterOpenTasks-BSO8TgVF.js → TasksFooterOpenTasks-IFtOEGnB.js} +2 -2
  64. package/lib/{TasksFooterOpenTasks-BSO8TgVF.js.map → TasksFooterOpenTasks-IFtOEGnB.js.map} +1 -1
  65. package/lib/{TasksStudioActiveToolLayout-BXktrH08.js → TasksStudioActiveToolLayout-C99LQz4S.js} +20 -20
  66. package/lib/{TasksStudioActiveToolLayout-BXktrH08.js.map → TasksStudioActiveToolLayout-C99LQz4S.js.map} +1 -1
  67. package/lib/{TasksStudioLayout-BfN-M93c.js → TasksStudioLayout-CmFbUpnB.js} +4 -4
  68. package/lib/{TasksStudioLayout-BfN-M93c.js.map → TasksStudioLayout-CmFbUpnB.js.map} +1 -1
  69. package/lib/{TasksStudioNavbar-CfqloSfP.js → TasksStudioNavbar-DB7DJC4e.js} +2 -2
  70. package/lib/{TasksStudioNavbar-CfqloSfP.js.map → TasksStudioNavbar-DB7DJC4e.js.map} +1 -1
  71. package/lib/{TimeZoneButton-FCwCyJ1J.js → TimeZoneButton-B_ki5v8q.js} +7 -7
  72. package/lib/{TimeZoneButton-FCwCyJ1J.js.map → TimeZoneButton-B_ki5v8q.js.map} +1 -1
  73. package/lib/{Tool-PzN5dskE.js → Tool-DlkZrcrD.js} +15 -15
  74. package/lib/{Tool-PzN5dskE.js.map → Tool-DlkZrcrD.js.map} +1 -1
  75. package/lib/{UpsellPanel-T-5ZD_7k.js → UpsellPanel-ITWwjktp.js} +2 -2
  76. package/lib/{UpsellPanel-T-5ZD_7k.js.map → UpsellPanel-ITWwjktp.js.map} +1 -1
  77. package/lib/{VariantsStudioNavbar-D0XbvL1D.js → VariantsStudioNavbar-DwEV1roH.js} +9 -9
  78. package/lib/{VariantsStudioNavbar-D0XbvL1D.js.map → VariantsStudioNavbar-DwEV1roH.js.map} +1 -1
  79. package/lib/{VariantsTool-B3EEDrQT.js → VariantsTool-Dzhy3PST.js} +12 -12
  80. package/lib/{VariantsTool-B3EEDrQT.js.map → VariantsTool-Dzhy3PST.js.map} +1 -1
  81. package/lib/{WorkspaceLoader-BH_VDaY4.js → WorkspaceLoader-Ck4TMoR5.js} +31 -31
  82. package/lib/{WorkspaceLoader-BH_VDaY4.js.map → WorkspaceLoader-Ck4TMoR5.js.map} +1 -1
  83. package/lib/_createContext.js +1 -1
  84. package/lib/_unstable-embedded.js +5 -5
  85. package/lib/{buildRangeDecorationSelectionsFromComments-B1-tJPvG.js → buildRangeDecorationSelectionsFromComments-BnlhrvDK.js} +3 -3
  86. package/lib/{buildRangeDecorationSelectionsFromComments-B1-tJPvG.js.map → buildRangeDecorationSelectionsFromComments-BnlhrvDK.js.map} +1 -1
  87. package/lib/{buildTextSelectionFromFragment-BiLg851R.js → buildTextSelectionFromFragment-BXrYd9lr.js} +3 -3
  88. package/lib/{buildTextSelectionFromFragment-BiLg851R.js.map → buildTextSelectionFromFragment-BXrYd9lr.js.map} +1 -1
  89. package/lib/{constants-DdgHySkY.js → constants-BQItnHll.js} +2 -2
  90. package/lib/{constants-DdgHySkY.js.map → constants-BQItnHll.js.map} +1 -1
  91. package/lib/{datastores-D1tF4HQA.js → datastores-DNOJm1LF.js} +2 -2
  92. package/lib/{datastores-D1tF4HQA.js.map → datastores-DNOJm1LF.js.map} +1 -1
  93. package/lib/{i18n-Cl_y4bbR.js → i18n-JUYUb7y_.js} +2 -2
  94. package/lib/{i18n-Cl_y4bbR.js.map → i18n-JUYUb7y_.js.map} +1 -1
  95. package/lib/index.js +38 -38
  96. package/lib/{inputResolver-CUWPjdGU.js → inputResolver-Ce1lTBE-.js} +4 -4
  97. package/lib/{inputResolver-CUWPjdGU.js.map → inputResolver-Ce1lTBE-.js.map} +1 -1
  98. package/lib/{navigation.telemetry-rXclq03x.js → navigation.telemetry-BPxX2IEN.js} +10 -10
  99. package/lib/{navigation.telemetry-rXclq03x.js.map → navigation.telemetry-BPxX2IEN.js.map} +1 -1
  100. package/lib/{plugin-CSp8hwQE.js → plugin-Bvxhb5ko.js} +8 -8
  101. package/lib/{plugin-CSp8hwQE.js.map → plugin-Bvxhb5ko.js.map} +1 -1
  102. package/lib/{plugin-Daxe5hwG.js → plugin-Cv6TLYbE.js} +6 -6
  103. package/lib/{plugin-Daxe5hwG.js.map → plugin-Cv6TLYbE.js.map} +1 -1
  104. package/lib/{plugin-BFTpdKKH.js → plugin-D6-7jrXf.js} +3 -3
  105. package/lib/{plugin-BFTpdKKH.js.map → plugin-D6-7jrXf.js.map} +1 -1
  106. package/lib/{plugin-dtgDcBsL.js → plugin-D_GVPwTR.js} +6 -6
  107. package/lib/{plugin-dtgDcBsL.js.map → plugin-D_GVPwTR.js.map} +1 -1
  108. package/lib/{releases.telemetry-B6tRA9U2.js → releases.telemetry-BAO7xaO7.js} +6 -6
  109. package/lib/{releases.telemetry-B6tRA9U2.js.map → releases.telemetry-BAO7xaO7.js.map} +1 -1
  110. package/lib/{resources-BjljYbUa.js → resources-Bw1bpPhG.js} +2 -2
  111. package/lib/{resources-BjljYbUa.js.map → resources-Bw1bpPhG.js.map} +1 -1
  112. package/lib/{resources-DYxnNjS8.js → resources-CC1qBsSO.js} +2 -2
  113. package/lib/{resources-DYxnNjS8.js.map → resources-CC1qBsSO.js.map} +1 -1
  114. package/lib/{resources-D7Mp6N-8.js → resources-CH42UqhC.js} +2 -2
  115. package/lib/{resources-D7Mp6N-8.js.map → resources-CH42UqhC.js.map} +1 -1
  116. package/lib/{resources-GpX0LblP.js → resources-Cq1lXH8T.js} +2 -2
  117. package/lib/{resources-GpX0LblP.js.map → resources-Cq1lXH8T.js.map} +1 -1
  118. package/lib/{resources-B7mfG9Km.js → resources-D7XsFe7y.js} +2 -2
  119. package/lib/{resources-B7mfG9Km.js.map → resources-D7XsFe7y.js.map} +1 -1
  120. package/lib/{resources-CmmAynkL.js → resources-DYn0yzEW.js} +2 -2
  121. package/lib/{resources-CmmAynkL.js.map → resources-DYn0yzEW.js.map} +1 -1
  122. package/lib/{resources-C79qQva3.js → resources-TsgtFPi7.js} +2 -2
  123. package/lib/{resources-C79qQva3.js.map → resources-TsgtFPi7.js.map} +1 -1
  124. package/lib/{scheduleItem-Bdvl81Kb.js → scheduleItem-5fXCZgfo.js} +13 -13
  125. package/lib/{scheduleItem-Bdvl81Kb.js.map → scheduleItem-5fXCZgfo.js.map} +1 -1
  126. package/lib/{schedules-D7bPbTPm.js → schedules-BsE0_g47.js} +3 -3
  127. package/lib/{schedules-D7bPbTPm.js.map → schedules-BsE0_g47.js.map} +1 -1
  128. package/lib/{searchDocumentRelease-v1o9dMnE.js → searchDocumentRelease-Bang3A8l.js} +5 -5
  129. package/lib/{searchDocumentRelease-v1o9dMnE.js.map → searchDocumentRelease-Bang3A8l.js.map} +1 -1
  130. package/lib/{studioClient-EJDu6kOb.js → studioClient-C7B6Aobi.js} +2 -2
  131. package/lib/{studioClient-EJDu6kOb.js.map → studioClient-C7B6Aobi.js.map} +1 -1
  132. package/lib/{useActiveReleases-Bh_Q6f7G.js → useActiveReleases-DxYjyTB1.js} +5 -5
  133. package/lib/{useActiveReleases-Bh_Q6f7G.js.map → useActiveReleases-DxYjyTB1.js.map} +1 -1
  134. package/lib/{useBundleDocuments-zP6JiTzz.js → useBundleDocuments-2YaaN-2l.js} +3 -3
  135. package/lib/{useBundleDocuments-zP6JiTzz.js.map → useBundleDocuments-2YaaN-2l.js.map} +1 -1
  136. package/lib/{useComments-BGOJwUe0.js → useComments-DWh1k0kS.js} +5 -5
  137. package/lib/{useComments-BGOJwUe0.js.map → useComments-DWh1k0kS.js.map} +1 -1
  138. package/lib/{useCommentsTelemetry-BMkf6MTO.js → useCommentsTelemetry-BbJ8lTKN.js} +4 -4
  139. package/lib/{useCommentsTelemetry-BMkf6MTO.js.map → useCommentsTelemetry-BbJ8lTKN.js.map} +1 -1
  140. package/lib/{useDocumentPreviewValues-CryTvfKc.js → useDocumentPreviewValues-CK5VteK3.js} +4 -4
  141. package/lib/{useDocumentPreviewValues-CryTvfKc.js.map → useDocumentPreviewValues-CK5VteK3.js.map} +1 -1
  142. package/lib/{useFieldActions-BTj7VsW5.js → useFieldActions-BmY1Kh3s.js} +2 -2
  143. package/lib/{useFieldActions-BTj7VsW5.js.map → useFieldActions-BmY1Kh3s.js.map} +1 -1
  144. package/lib/{useProjectId-BN6GCdwS.js → useProjectId-C8pZxybz.js} +2 -2
  145. package/lib/{useProjectId-BN6GCdwS.js.map → useProjectId-C8pZxybz.js.map} +1 -1
  146. package/lib/{useReleasesToolAvailable-CQ9-I8Tt.js → useReleasesToolAvailable-DjaSujLo.js} +3 -3
  147. package/lib/{useReleasesToolAvailable-CQ9-I8Tt.js.map → useReleasesToolAvailable-DjaSujLo.js.map} +1 -1
  148. package/lib/{useScheduledDraftMenuActions-OSkdxONo.js → useScheduledDraftMenuActions-DSJU6xQa.js} +9 -9
  149. package/lib/{useScheduledDraftMenuActions-OSkdxONo.js.map → useScheduledDraftMenuActions-DSJU6xQa.js.map} +1 -1
  150. package/lib/{useStudioUrl-DUBI_S4K.js → useStudioUrl-DcTGV00c.js} +5 -5
  151. package/lib/{useStudioUrl-DUBI_S4K.js.map → useStudioUrl-DcTGV00c.js.map} +1 -1
  152. package/lib/{useTasksNavigation-fohCXW6l.js → useTasksNavigation-tAXFJd2V.js} +2 -2
  153. package/lib/{useTasksNavigation-fohCXW6l.js.map → useTasksNavigation-tAXFJd2V.js.map} +1 -1
  154. package/lib/{useTimeZone-DM8ZmUO2.js → useTimeZone-Dj7C8tfZ.js} +2 -2
  155. package/lib/{useTimeZone-DM8ZmUO2.js.map → useTimeZone-Dj7C8tfZ.js.map} +1 -1
  156. package/lib/{utils-D-4rueJZ.js → utils-CT034e4q.js} +3 -3
  157. package/lib/{utils-D-4rueJZ.js.map → utils-CT034e4q.js.map} +1 -1
  158. package/lib/{validationUtils-jTd1rxfY.js → validationUtils-BZPoHEYN.js} +4 -4
  159. package/lib/{validationUtils-jTd1rxfY.js.map → validationUtils-BZPoHEYN.js.map} +1 -1
  160. package/lib/{version-D0Vx4cX1.js → version-BDSMcNU7.js} +2 -2
  161. package/lib/{version-D0Vx4cX1.js.map → version-BDSMcNU7.js.map} +1 -1
  162. package/package.json +17 -17
  163. package/lib/PerspectiveProvider-Yk7lgugx.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"CommentsInspector-BnSG5Mq0.js","names":["getEmptyStateMessages(t)","t('list-status.error')","<Flex alignItems=\"center\" justifyContent=\"center\" flexBasis=\"0%\" flexGrow={1} padding={4}>\n <Flex alignItems=\"center\">\n <Text size={1} muted as=\"div\" trim={true}>\n {t('list-status.error')}\n </Text>\n </Flex>\n </Flex>","t('list-status.loading')","<LoadingBlock showText title={t('list-status.loading')} />","<Text align=\"center\" size={1} muted weight=\"medium\" as=\"div\" trim={true}>\n {emptyStateMessages[status].title}\n </Text>","title","emptyStateMessages[status]","<Text align=\"center\" size={1} muted as=\"div\" trim={true}>\n {emptyStateMessages[status].message}\n </Text>","message","<Flex alignItems=\"center\" justifyContent=\"center\" flexBasis=\"0%\" flexGrow={1}>\n <Container size={0} padding={4}>\n <VStack gap={3}>\n <Text align=\"center\" size={1} muted weight=\"medium\" as=\"div\" trim={true}>\n {emptyStateMessages[status].title}\n </Text>\n\n <Text align=\"center\" size={1} muted as=\"div\" trim={true}>\n {emptyStateMessages[status].message}\n </Text>\n </VStack>\n </Container>\n </Flex>","useMemo(() => {\n const len = titlePath.length\n const beforeLength = Math.ceil(maxLength / 2)\n const afterLength = Math.floor(maxLength / 2)\n\n if (maxLength && len > maxLength) {\n return [\n ...titlePath.slice(0, beforeLength - 1),\n titlePath.slice(beforeLength - 1, len - afterLength),\n ...titlePath.slice(len - afterLength),\n ]\n }\n\n return titlePath\n }, [maxLength, titlePath])","[\n ...titlePath.slice(0, beforeLength - 1),\n titlePath.slice(beforeLength - 1, len - afterLength),\n ...titlePath.slice(len - afterLength),\n ]","items.map((item, index) => {\n const key = `${item}-${index}`\n const showSeparator = index < items.length - 1\n\n if (Array.isArray(item)) {\n return (\n <Fragment key={key}>\n <Tooltip\n content={\n <Flex gap={2} padding={2} flexDirection=\"column\">\n {item.map(renderItem)}\n </Flex>\n }\n >\n <Box>{renderItem('...', index)}</Box>\n </Tooltip>\n\n {showSeparator && separator}\n </Fragment>\n )\n }\n\n return (\n <Fragment key={key}>\n {renderItem(item, index)}\n\n {showSeparator && separator}\n </Fragment>\n )\n })","items.length","(item, index) => {\n const key = `${item}-${index}`\n const showSeparator = index < items.length - 1\n\n if (Array.isArray(item)) {\n return (\n <Fragment key={key}>\n <Tooltip\n content={\n <Flex gap={2} padding={2} flexDirection=\"column\">\n {item.map(renderItem)}\n </Flex>\n }\n >\n <Box>{renderItem('...', index)}</Box>\n </Tooltip>\n\n {showSeparator && separator}\n </Fragment>\n )\n }\n\n return (\n <Fragment key={key}>\n {renderItem(item, index)}\n\n {showSeparator && separator}\n </Fragment>\n )\n }","length","useMemo(() => {\n return items.map((item, index) => {\n const key = `${item}-${index}`\n const showSeparator = index < items.length - 1\n\n if (Array.isArray(item)) {\n return (\n <Fragment key={key}>\n <Tooltip\n content={\n <Flex gap={2} padding={2} flexDirection=\"column\">\n {item.map(renderItem)}\n </Flex>\n }\n >\n <Box>{renderItem('...', index)}</Box>\n </Tooltip>\n\n {showSeparator && separator}\n </Fragment>\n )\n }\n\n return (\n <Fragment key={key}>\n {renderItem(item, index)}\n\n {showSeparator && separator}\n </Fragment>\n )\n })\n }, [items])","<Flex alignItems=\"center\" as=\"ol\" gap={2}>\n {nodes}\n </Flex>","(nextValue: CommentMessage) => {\n onNewThreadCreate?.(nextValue)\n setValue(EMPTY_PT_ARRAY)\n }","useCallback(\n (nextValue: CommentMessage) => {\n onNewThreadCreate?.(nextValue)\n setValue(EMPTY_PT_ARRAY)\n },\n [onNewThreadCreate],\n )","hasCommentMessageValue(value)","useMemo(() => hasCommentMessageValue(value), [value])","() => {\n if (!hasValue) {\n return\n }\n commentInputHandle.current?.discardDialogController.open()\n }","useCallback(() => {\n if (!hasValue) {\n return\n }\n commentInputHandle.current?.discardDialogController.open()\n }, [hasValue])","(event: React.KeyboardEvent) => {\n // Don't act if the input already prevented this event\n if (event.isDefaultPrevented()) {\n return\n }\n // Discard the input text\n if (event.key === 'Escape') {\n event.preventDefault()\n event.stopPropagation()\n startDiscard()\n }\n // Call parent handler\n if (onKeyDown) onKeyDown(event)\n }","useCallback(\n (event: React.KeyboardEvent) => {\n // Don't act if the input already prevented this event\n if (event.isDefaultPrevented()) {\n return\n }\n // Discard the input text\n if (event.key === 'Escape') {\n event.preventDefault()\n event.stopPropagation()\n startDiscard()\n }\n // Call parent handler\n if (onKeyDown) onKeyDown(event)\n },\n [onKeyDown, startDiscard],\n )","() => {\n setValue(EMPTY_PT_ARRAY)\n commentInputHandle.current?.discardDialogController.close()\n commentInputHandle.current?.focus()\n }","useCallback(() => {\n setValue(EMPTY_PT_ARRAY)\n commentInputHandle.current?.discardDialogController.close()\n commentInputHandle.current?.focus()\n }, [])","() => {\n commentInputHandle.current?.discardDialogController.close()\n }","useCallback(() => {\n commentInputHandle.current?.discardDialogController.close()\n }, [])","mode === 'upsell' ? (\n t('compose.add-comment-input-placeholder-upsell')\n ) : (\n <Translate\n t={t}\n i18nKey=\"compose.add-comment-input-placeholder\"\n values={{field: fieldTitle}}\n />\n )","<CommentInput\n currentUser={currentUser}\n expandOnFocus\n mentionOptions={mentionOptions}\n onBlur={onBlur}\n onChange={setValue}\n onDiscardCancel={cancelDiscard}\n onDiscardConfirm={confirmDiscard}\n onKeyDown={handleInputKeyDown}\n onFocus={onFocus}\n onSubmit={handleSubmit}\n placeholder={placeholder}\n readOnly={readOnly || mode === 'upsell'}\n ref={commentInputHandle}\n value={value}\n />","readOnly || mode === 'upsell'","(payload: CommentMessage) => {\n const nextComment: CommentBaseCreatePayload = {\n message: payload,\n parentCommentId: undefined,\n status: 'open',\n // Since this is a new comment, we generate a new thread ID\n threadId: uuid(),\n // New comments have no reactions\n reactions: [],\n\n payload: {\n fieldPath,\n },\n }\n\n onNewThreadCreate?.(nextComment)\n }","useCallback(\n (payload: CommentMessage) => {\n const nextComment: CommentBaseCreatePayload = {\n message: payload,\n parentCommentId: undefined,\n status: 'open',\n // Since this is a new comment, we generate a new thread ID\n threadId: uuid(),\n // New comments have no reactions\n reactions: [],\n\n payload: {\n fieldPath,\n },\n }\n\n onNewThreadCreate?.(nextComment)\n },\n [onNewThreadCreate, fieldPath],\n )","(e: MouseEvent<HTMLButtonElement>) => {\n e.stopPropagation()\n\n onPathSelect?.({\n fieldPath,\n origin: 'inspector',\n threadId: null,\n })\n }","useCallback(\n (e: MouseEvent<HTMLButtonElement>) => {\n e.stopPropagation()\n\n onPathSelect?.({\n fieldPath,\n origin: 'inspector',\n threadId: null,\n })\n },\n [fieldPath, onPathSelect],\n )","(e: MouseEvent<HTMLDivElement>) => {\n e.stopPropagation()\n // Skip if the click was triggered from \"Enter\" keydown.\n // This because we don't want to trigger `onPathSelect` when\n // submitting the new thread form.\n if (e.detail === 0) return\n\n onPathSelect?.({\n fieldPath,\n origin: 'inspector',\n threadId: null,\n })\n }","e","useCallback(\n (e: MouseEvent<HTMLDivElement>) => {\n e.stopPropagation()\n // Skip if the click was triggered from \"Enter\" keydown.\n // This because we don't want to trigger `onPathSelect` when\n // submitting the new thread form.\n if (e.detail === 0) return\n\n onPathSelect?.({\n fieldPath,\n origin: 'inspector',\n threadId: null,\n })\n },\n [fieldPath, onPathSelect],\n )","breadcrumbs?.map((p) => p.title) || []","(p) => p.title","breadcrumbs?.map","useMemo(() => breadcrumbs?.map((p) => p.title) || [], [breadcrumbs])","t('list-item.breadcrumb-button-go-to-field-aria-label', {\n field: lastCrumb,\n })","<CommentBreadcrumbs maxLength={3} titlePath={crumbsTitlePath} />","<HeaderFlex alignItems=\"center\" gap={2} paddingRight={1}>\n <Flex flexBasis=\"0%\" flexGrow={1} flexDirection=\"column\">\n <Flex alignItems=\"center\">\n <BreadcrumbsButton\n aria-label={t('list-item.breadcrumb-button-go-to-field-aria-label', {\n field: lastCrumb,\n })}\n mode=\"bleed\"\n onClick={handleBreadcrumbsClick}\n padding={2}\n gap={2}\n >\n <CommentBreadcrumbs maxLength={3} titlePath={crumbsTitlePath} />\n </BreadcrumbsButton>\n </Flex>\n </Flex>\n </HeaderFlex>","canCreateNewThread && (\n <ThreadCard onClick={handleNewThreadClick} data-active={isSelected}>\n <CreateNewThreadInput\n currentUser={currentUser}\n fieldTitle={lastCrumb}\n mentionOptions={mentionOptions}\n mode={mode}\n onNewThreadCreate={handleNewThreadCreate}\n readOnly={readOnly}\n />\n </ThreadCard>\n )","<VStack gap={2}>{children}</VStack>","<VStack gap={2}>\n <HeaderFlex alignItems=\"center\" gap={2} paddingRight={1}>\n <Flex flexBasis=\"0%\" flexGrow={1} flexDirection=\"column\">\n <Flex alignItems=\"center\">\n <BreadcrumbsButton\n aria-label={t('list-item.breadcrumb-button-go-to-field-aria-label', {\n field: lastCrumb,\n })}\n mode=\"bleed\"\n onClick={handleBreadcrumbsClick}\n padding={2}\n gap={2}\n >\n <CommentBreadcrumbs maxLength={3} titlePath={crumbsTitlePath} />\n </BreadcrumbsButton>\n </Flex>\n </Flex>\n </HeaderFlex>\n\n {canCreateNewThread && (\n <ThreadCard onClick={handleNewThreadClick} data-active={isSelected}>\n <CreateNewThreadInput\n currentUser={currentUser}\n fieldTitle={lastCrumb}\n mentionOptions={mentionOptions}\n mode={mode}\n onNewThreadCreate={handleNewThreadCreate}\n readOnly={readOnly}\n />\n </ThreadCard>\n )}\n\n <VStack gap={2}>{children}</VStack>\n </VStack>","Object.entries(groupThreads(comments))","useMemo(() => Object.entries(groupThreads(comments)), [comments])","mode !== 'upsell' && (\n <CommentsListStatus\n error={error}\n hasNoComments={groupedThreads.length === 0}\n loading={loading}\n status={status}\n />\n )","groupedThreads.length","(showComments || beforeListNode) && (\n <Flex\n as=\"ul\"\n flexBasis=\"0%\"\n flexGrow={1}\n overflow=\"auto\"\n padding={3}\n paddingTop={1}\n paddingBottom={6}\n gap={1}\n ref={ref}\n flexDirection=\"column\"\n >\n {beforeListNode}\n\n <BoundaryElementProvider element={boundaryElement}>\n {groupedThreads?.map(([fieldPath, group]) => {\n // Since all threads in the group point to the same field, the breadcrumbs will be\n // the same for all of them. Therefore, we can just pick the first one.\n const breadcrumbs = group[0].breadcrumbs\n\n // The thread ID is used to scroll to the thread.\n // We pick the first thread id in the group so that we scroll to the first thread\n // in the group.\n const firstThreadId = group[0].threadId\n\n // The new thread is selected if the field path matches the selected path and\n // there is no thread ID selected.\n const newThreadSelected =\n selectedPath?.fieldPath === fieldPath && !selectedPath.threadId\n\n return (\n <Flex\n key={fieldPath}\n as=\"li\"\n paddingTop={3}\n {...applyCommentsGroupAttr(firstThreadId)}\n flexDirection=\"column\"\n flexShrink={0}\n >\n <CommentThreadLayout\n key={fieldPath}\n breadcrumbs={breadcrumbs}\n canCreateNewThread={status === 'open'}\n currentUser={currentUser}\n fieldPath={fieldPath}\n isSelected={newThreadSelected}\n mentionOptions={mentionOptions}\n mode={mode}\n onNewThreadCreate={onNewThreadCreate}\n onPathSelect={onPathSelect}\n readOnly={readOnly}\n >\n {group.map((item) => {\n // The default sort order is by date, descending (newest first).\n // However, inside a thread, we want the order to be ascending (oldest first).\n // So we reverse the array here.\n // We use slice() to avoid mutating the original array.\n const replies = item.replies.slice().reverse()\n\n const canReply =\n status === 'open' &&\n item.parentComment._state?.type !== 'createError' &&\n item.parentComment._state?.type !== 'createRetrying'\n\n // The thread is selected if the thread ID and field path matches the\n // selected path.\n const threadIsSelected =\n selectedPath?.threadId === item.parentComment.threadId &&\n selectedPath?.fieldPath === item.parentComment.target.path?.field\n\n return (\n <CommentsListItem\n key={item.parentComment._id}\n canReply={canReply}\n currentUser={currentUser}\n hasReferencedValue={item.hasReferencedValue}\n isSelected={threadIsSelected}\n mentionOptions={mentionOptions}\n mode={mode}\n onCopyLink={onCopyLink}\n onCreateRetry={onCreateRetry}\n onDelete={onDelete}\n onEdit={onEdit}\n onPathSelect={onPathSelect}\n onReactionSelect={onReactionSelect}\n onReply={onReply}\n onStatusChange={onStatusChange}\n parentComment={item.parentComment}\n readOnly={readOnly}\n replies={replies}\n />\n )\n })}\n </CommentThreadLayout>\n </Flex>\n )\n })}\n </BoundaryElementProvider>\n </Flex>\n )","groupedThreads?.map","selectedPath?.fieldPath","[fieldPath, group]","<Flex\n data-testid=\"comments-list\"\n flexDirection=\"column\"\n flexBasis=\"0%\"\n flexGrow={1}\n height=\"100%\"\n overflow=\"hidden\"\n ref={setBoundaryElement}\n >\n {mode !== 'upsell' && (\n <CommentsListStatus\n error={error}\n hasNoComments={groupedThreads.length === 0}\n loading={loading}\n status={status}\n />\n )}\n\n {(showComments || beforeListNode) && (\n <Flex\n as=\"ul\"\n flexBasis=\"0%\"\n flexGrow={1}\n overflow=\"auto\"\n padding={3}\n paddingTop={1}\n paddingBottom={6}\n gap={1}\n ref={ref}\n flexDirection=\"column\"\n >\n {beforeListNode}\n\n <BoundaryElementProvider element={boundaryElement}>\n {groupedThreads?.map(([fieldPath, group]) => {\n // Since all threads in the group point to the same field, the breadcrumbs will be\n // the same for all of them. Therefore, we can just pick the first one.\n const breadcrumbs = group[0].breadcrumbs\n\n // The thread ID is used to scroll to the thread.\n // We pick the first thread id in the group so that we scroll to the first thread\n // in the group.\n const firstThreadId = group[0].threadId\n\n // The new thread is selected if the field path matches the selected path and\n // there is no thread ID selected.\n const newThreadSelected =\n selectedPath?.fieldPath === fieldPath && !selectedPath.threadId\n\n return (\n <Flex\n key={fieldPath}\n as=\"li\"\n paddingTop={3}\n {...applyCommentsGroupAttr(firstThreadId)}\n flexDirection=\"column\"\n flexShrink={0}\n >\n <CommentThreadLayout\n key={fieldPath}\n breadcrumbs={breadcrumbs}\n canCreateNewThread={status === 'open'}\n currentUser={currentUser}\n fieldPath={fieldPath}\n isSelected={newThreadSelected}\n mentionOptions={mentionOptions}\n mode={mode}\n onNewThreadCreate={onNewThreadCreate}\n onPathSelect={onPathSelect}\n readOnly={readOnly}\n >\n {group.map((item) => {\n // The default sort order is by date, descending (newest first).\n // However, inside a thread, we want the order to be ascending (oldest first).\n // So we reverse the array here.\n // We use slice() to avoid mutating the original array.\n const replies = item.replies.slice().reverse()\n\n const canReply =\n status === 'open' &&\n item.parentComment._state?.type !== 'createError' &&\n item.parentComment._state?.type !== 'createRetrying'\n\n // The thread is selected if the thread ID and field path matches the\n // selected path.\n const threadIsSelected =\n selectedPath?.threadId === item.parentComment.threadId &&\n selectedPath?.fieldPath === item.parentComment.target.path?.field\n\n return (\n <CommentsListItem\n key={item.parentComment._id}\n canReply={canReply}\n currentUser={currentUser}\n hasReferencedValue={item.hasReferencedValue}\n isSelected={threadIsSelected}\n mentionOptions={mentionOptions}\n mode={mode}\n onCopyLink={onCopyLink}\n onCreateRetry={onCreateRetry}\n onDelete={onDelete}\n onEdit={onEdit}\n onPathSelect={onPathSelect}\n onReactionSelect={onReactionSelect}\n onReply={onReply}\n onStatusChange={onStatusChange}\n parentComment={item.parentComment}\n readOnly={readOnly}\n replies={replies}\n />\n )\n })}\n </CommentThreadLayout>\n </Flex>\n )\n })}\n </BoundaryElementProvider>\n </Flex>\n )}\n </Flex>","t('onboarding.header')","<Text weight=\"medium\" size={1} as=\"div\" trim={true}>\n {t('onboarding.header')}\n </Text>","t('onboarding.body')","<Text size={1} as=\"div\" trim={true}>\n {t('onboarding.body')}\n </Text>","t('onboarding.dismiss')","<Flex justifyContent=\"flex-end\" marginTop={2}>\n <Button text={t('onboarding.dismiss')} tone=\"primary\" onClick={onDismiss} />\n </Flex>","<Root padding={4}>\n <VStack gap={3}>\n <Text weight=\"medium\" size={1} as=\"div\" trim={true}>\n {t('onboarding.header')}\n </Text>\n\n <Text size={1} as=\"div\" trim={true}>\n {t('onboarding.body')}\n </Text>\n\n <Flex justifyContent=\"flex-end\" marginTop={2}>\n <Button text={t('onboarding.dismiss')} tone=\"primary\" onClick={onDismiss} />\n </Flex>\n </VStack>\n </Root>","<StyledPopover\n content={\n <Root padding={4}>\n <VStack gap={3}>\n <Text weight=\"medium\" size={1} as=\"div\" trim={true}>\n {t('onboarding.header')}\n </Text>\n\n <Text size={1} as=\"div\" trim={true}>\n {t('onboarding.body')}\n </Text>\n\n <Flex justifyContent=\"flex-end\" marginTop={2}>\n <Button text={t('onboarding.dismiss')} tone=\"primary\" onClick={onDismiss} />\n </Flex>\n </VStack>\n </Root>\n }\n open\n portal\n {...rest}\n />","<Container size={1}>\n <Box marginBottom={6}>\n <UpsellPanel\n data={data}\n onPrimaryClick={onPrimaryClick}\n onSecondaryClick={onSecondaryClick}\n />\n </Box>\n </Container>","() => {\n telemetry.log(CommentLinkCopied)\n }","useCallback(() => {\n telemetry.log(CommentLinkCopied)\n }, [telemetry])","() => {\n telemetry.log(CommentViewedFromLink)\n }","useCallback(() => {\n telemetry.log(CommentViewedFromLink)\n }, [telemetry])","(view: CommentStatus) => {\n telemetry.log(CommentListViewChanged, {view})\n }","useCallback(\n (view: CommentStatus) => {\n telemetry.log(CommentListViewChanged, {view})\n },\n [telemetry],\n )","{\n commentLinkCopied,\n commentListViewChanged,\n commentViewedFromLink,\n }","useMemo(\n (): CommentsTelemetryHookValue => ({\n commentLinkCopied,\n commentListViewChanged,\n commentViewedFromLink,\n }),\n [commentLinkCopied, commentListViewChanged, commentViewedFromLink],\n )","() => onViewChange('open')","useCallback(() => onViewChange('open'), [onViewChange])","() => onViewChange('resolved')","useCallback(() => onViewChange('resolved'), [onViewChange])","t('feature-name')","<Flex alignItems=\"center\" flexBasis=\"0%\" flexGrow={1} gap={2} paddingY={2} padding={3}>\n <Text as=\"h1\" size={1} weight=\"medium\" trim={true}>\n {t('feature-name')}\n </Text>\n </Flex>","view === 'open'\n ? t('status-filter.status-open')\n : t('status-filter.status-resolved')","<Button\n text={\n view === 'open'\n ? t('status-filter.status-open')\n : t('status-filter.status-resolved')\n }\n mode=\"bleed\"\n iconRight={ChevronDownIcon}\n />","{width: '180px'}","t('status-filter.status-open-full')","<MenuItem\n iconRight={view === 'open' ? CheckmarkIcon : undefined}\n onClick={handleSetOpenView}\n text={t('status-filter.status-open-full')}\n />","view === 'open' ? CheckmarkIcon : undefined","t('status-filter.status-resolved-full')","mode === 'upsell'\n ? {content: t('status-filter.status-resolved-full-upsell')}\n : undefined","<MenuItem\n iconRight={view === 'resolved' ? CheckmarkIcon : undefined}\n onClick={handleSetResolvedView}\n text={t('status-filter.status-resolved-full')}\n tooltipProps={\n mode === 'upsell'\n ? {content: t('status-filter.status-resolved-full-upsell')}\n : undefined\n }\n disabled={mode === 'upsell'}\n />","view === 'resolved' ? CheckmarkIcon : undefined","mode === 'upsell'","<Menu style={{width: '180px'}}>\n <MenuItem\n iconRight={view === 'open' ? CheckmarkIcon : undefined}\n onClick={handleSetOpenView}\n text={t('status-filter.status-open-full')}\n />\n <MenuItem\n iconRight={view === 'resolved' ? CheckmarkIcon : undefined}\n onClick={handleSetResolvedView}\n text={t('status-filter.status-resolved-full')}\n tooltipProps={\n mode === 'upsell'\n ? {content: t('status-filter.status-resolved-full-upsell')}\n : undefined\n }\n disabled={mode === 'upsell'}\n />\n </Menu>","{placement: 'bottom-end'}","<MenuButton\n id=\"comment-status-menu-button\"\n button={\n <Button\n text={\n view === 'open'\n ? t('status-filter.status-open')\n : t('status-filter.status-resolved')\n }\n mode=\"bleed\"\n iconRight={ChevronDownIcon}\n />\n }\n menu={\n <Menu style={{width: '180px'}}>\n <MenuItem\n iconRight={view === 'open' ? CheckmarkIcon : undefined}\n onClick={handleSetOpenView}\n text={t('status-filter.status-open-full')}\n />\n <MenuItem\n iconRight={view === 'resolved' ? CheckmarkIcon : undefined}\n onClick={handleSetResolvedView}\n text={t('status-filter.status-resolved-full')}\n tooltipProps={\n mode === 'upsell'\n ? {content: t('status-filter.status-resolved-full-upsell')}\n : undefined\n }\n disabled={mode === 'upsell'}\n />\n </Menu>\n }\n popover={{placement: 'bottom-end'}}\n />","t('close-pane-button-text-aria-label')","t('close-pane-button-text')","{content: t('close-pane-button-text')}","<Button\n aria-label={t('close-pane-button-text-aria-label')}\n icon={CloseIcon}\n mode=\"bleed\"\n onClick={onClose}\n tooltipProps={{content: t('close-pane-button-text')}}\n />","<Flex flexBasis=\"auto\" flexGrow={0} flexShrink={0} padding={1} gap={2}>\n <MenuButton\n id=\"comment-status-menu-button\"\n button={\n <Button\n text={\n view === 'open'\n ? t('status-filter.status-open')\n : t('status-filter.status-resolved')\n }\n mode=\"bleed\"\n iconRight={ChevronDownIcon}\n />\n }\n menu={\n <Menu style={{width: '180px'}}>\n <MenuItem\n iconRight={view === 'open' ? CheckmarkIcon : undefined}\n onClick={handleSetOpenView}\n text={t('status-filter.status-open-full')}\n />\n <MenuItem\n iconRight={view === 'resolved' ? CheckmarkIcon : undefined}\n onClick={handleSetResolvedView}\n text={t('status-filter.status-resolved-full')}\n tooltipProps={\n mode === 'upsell'\n ? {content: t('status-filter.status-resolved-full-upsell')}\n : undefined\n }\n disabled={mode === 'upsell'}\n />\n </Menu>\n }\n popover={{placement: 'bottom-end'}}\n />\n\n <Button\n aria-label={t('close-pane-button-text-aria-label')}\n icon={CloseIcon}\n mode=\"bleed\"\n onClick={onClose}\n tooltipProps={{content: t('close-pane-button-text')}}\n />\n </Flex>","<Flex padding={2}>\n <Flex alignItems=\"center\" flexBasis=\"0%\" flexGrow={1} gap={2} paddingY={2} padding={3}>\n <Text as=\"h1\" size={1} weight=\"medium\" trim={true}>\n {t('feature-name')}\n </Text>\n </Flex>\n\n <Flex flexBasis=\"auto\" flexGrow={0} flexShrink={0} padding={1} gap={2}>\n <MenuButton\n id=\"comment-status-menu-button\"\n button={\n <Button\n text={\n view === 'open'\n ? t('status-filter.status-open')\n : t('status-filter.status-resolved')\n }\n mode=\"bleed\"\n iconRight={ChevronDownIcon}\n />\n }\n menu={\n <Menu style={{width: '180px'}}>\n <MenuItem\n iconRight={view === 'open' ? CheckmarkIcon : undefined}\n onClick={handleSetOpenView}\n text={t('status-filter.status-open-full')}\n />\n <MenuItem\n iconRight={view === 'resolved' ? CheckmarkIcon : undefined}\n onClick={handleSetResolvedView}\n text={t('status-filter.status-resolved-full')}\n tooltipProps={\n mode === 'upsell'\n ? {content: t('status-filter.status-resolved-full-upsell')}\n : undefined\n }\n disabled={mode === 'upsell'}\n />\n </Menu>\n }\n popover={{placement: 'bottom-end'}}\n />\n\n <Button\n aria-label={t('close-pane-button-text-aria-label')}\n icon={CloseIcon}\n mode=\"bleed\"\n onClick={onClose}\n tooltipProps={{content: t('close-pane-button-text')}}\n />\n </Flex>\n </Flex>","<Root ref={ref}>\n <Flex padding={2}>\n <Flex alignItems=\"center\" flexBasis=\"0%\" flexGrow={1} gap={2} paddingY={2} padding={3}>\n <Text as=\"h1\" size={1} weight=\"medium\" trim={true}>\n {t('feature-name')}\n </Text>\n </Flex>\n\n <Flex flexBasis=\"auto\" flexGrow={0} flexShrink={0} padding={1} gap={2}>\n <MenuButton\n id=\"comment-status-menu-button\"\n button={\n <Button\n text={\n view === 'open'\n ? t('status-filter.status-open')\n : t('status-filter.status-resolved')\n }\n mode=\"bleed\"\n iconRight={ChevronDownIcon}\n />\n }\n menu={\n <Menu style={{width: '180px'}}>\n <MenuItem\n iconRight={view === 'open' ? CheckmarkIcon : undefined}\n onClick={handleSetOpenView}\n text={t('status-filter.status-open-full')}\n />\n <MenuItem\n iconRight={view === 'resolved' ? CheckmarkIcon : undefined}\n onClick={handleSetResolvedView}\n text={t('status-filter.status-resolved-full')}\n tooltipProps={\n mode === 'upsell'\n ? {content: t('status-filter.status-resolved-full-upsell')}\n : undefined\n }\n disabled={mode === 'upsell'}\n />\n </Menu>\n }\n popover={{placement: 'bottom-end'}}\n />\n\n <Button\n aria-label={t('close-pane-button-text-aria-label')}\n icon={CloseIcon}\n mode=\"bleed\"\n onClick={onClose}\n tooltipProps={{content: t('close-pane-button-text')}}\n />\n </Flex>\n </Flex>\n </Root>","<RootLayer>\n <CommentsInspectorInner {...props} mode={mode} />\n </RootLayer>","{\n boundaryElement: rootElement,\n }","(nextView: CommentStatus) => {\n setStatus(nextView)\n setSelectedPath(null)\n\n telemetry.commentListViewChanged(nextView)\n }","useCallback(\n (nextView: CommentStatus) => {\n setStatus(nextView)\n setSelectedPath(null)\n\n telemetry.commentListViewChanged(nextView)\n },\n [setSelectedPath, setStatus, telemetry],\n )","() => {\n onClose()\n setSelectedPath(null)\n }","useCallback(() => {\n onClose()\n setSelectedPath(null)\n }, [onClose, setSelectedPath])","useMemo(() => {\n if (!getCommentLink) return undefined\n\n const copyLink = (id: string) => {\n navigator.clipboard.writeText(getCommentLink(id)).catch(() => {\n pushToast({\n closable: true,\n status: 'error',\n title: t('copy-link-error-message'),\n })\n })\n\n telemetry.commentLinkCopied()\n }\n\n return copyLink\n }, [getCommentLink, pushToast, t, telemetry])","(id: string) => {\n navigator.clipboard.writeText(getCommentLink(id)).catch(() => {\n pushToast({\n closable: true,\n status: 'error',\n title: t('copy-link-error-message'),\n })\n })\n\n telemetry.commentLinkCopied()\n }","(id: string) => {\n const comment = getComment(id)\n if (!comment) return\n\n void operation.create({\n type: 'field',\n fieldPath: comment.target.path?.field || '',\n id: comment._id,\n message: comment.message,\n parentCommentId: comment.parentCommentId,\n reactions: comment.reactions || [],\n status: comment.status,\n threadId: comment.threadId,\n })\n }","id","useCallback(\n (id: string) => {\n const comment = getComment(id)\n if (!comment) return\n\n void operation.create({\n type: 'field',\n fieldPath: comment.target.path?.field || '',\n id: comment._id,\n message: comment.message,\n parentCommentId: comment.parentCommentId,\n reactions: comment.reactions || [],\n status: comment.status,\n threadId: comment.threadId,\n })\n },\n [getComment, operation],\n )","() => {\n if (deleteLoading) return\n setShowDeleteDialog(false)\n setCommentToDelete(null)\n }","useCallback(() => {\n if (deleteLoading) return\n setShowDeleteDialog(false)\n setCommentToDelete(null)\n }, [deleteLoading])","(nextPath: CommentsSelectedPath) => {\n setSelectedPath(nextPath)\n\n if (nextPath?.fieldPath) {\n const path = PathUtils.fromString(nextPath.fieldPath)\n onPathOpen?.(path)\n\n scrollToField(nextPath.fieldPath)\n\n const isInlineComment = comments.data.open\n .filter((c) => c.threadId === nextPath?.threadId)\n .some((x) => isTextSelectionComment(x.parentComment))\n\n if (isInlineComment && nextPath.threadId) {\n scrollToInlineComment(nextPath.threadId)\n }\n }\n }","open","(x) => isTextSelectionComment(x.parentComment)","useCallback(\n (nextPath: CommentsSelectedPath) => {\n setSelectedPath(nextPath)\n\n if (nextPath?.fieldPath) {\n const path = PathUtils.fromString(nextPath.fieldPath)\n onPathOpen?.(path)\n\n scrollToField(nextPath.fieldPath)\n\n const isInlineComment = comments.data.open\n .filter((c) => c.threadId === nextPath?.threadId)\n .some((x) => isTextSelectionComment(x.parentComment))\n\n if (isInlineComment && nextPath.threadId) {\n scrollToInlineComment(nextPath.threadId)\n }\n }\n },\n [comments.data.open, onPathOpen, scrollToField, scrollToInlineComment, setSelectedPath],\n )","(nextComment: CommentBaseCreatePayload) => {\n const fieldPath = nextComment?.payload?.fieldPath || ''\n\n void operation.create({\n type: 'field',\n fieldPath,\n message: nextComment.message,\n parentCommentId: nextComment.parentCommentId,\n reactions: nextComment.reactions,\n status: nextComment.status,\n threadId: nextComment.threadId,\n })\n\n setSelectedPath({\n fieldPath,\n origin: 'inspector',\n threadId: nextComment.threadId,\n })\n }","useCallback(\n (nextComment: CommentBaseCreatePayload) => {\n const fieldPath = nextComment?.payload?.fieldPath || ''\n\n void operation.create({\n type: 'field',\n fieldPath,\n message: nextComment.message,\n parentCommentId: nextComment.parentCommentId,\n reactions: nextComment.reactions,\n status: nextComment.status,\n threadId: nextComment.threadId,\n })\n\n setSelectedPath({\n fieldPath,\n origin: 'inspector',\n threadId: nextComment.threadId,\n })\n },\n [operation, setSelectedPath],\n )","(nextComment: CommentBaseCreatePayload) => {\n void operation.create({\n ...nextComment,\n type: 'field',\n fieldPath: nextComment?.payload?.fieldPath || '',\n })\n }","nextComment","useCallback(\n (nextComment: CommentBaseCreatePayload) => {\n void operation.create({\n ...nextComment,\n type: 'field',\n fieldPath: nextComment?.payload?.fieldPath || '',\n })\n },\n [operation],\n )","(id: string, nextComment: CommentUpdatePayload) => {\n void operation.update(id, nextComment)\n }","useCallback(\n (id: string, nextComment: CommentUpdatePayload) => {\n void operation.update(id, nextComment)\n },\n [operation],\n )","(id: string) => {\n const parent = currentComments.find((c) => c.parentComment?._id === id)\n const isParent = Boolean(parent && parent?.replies?.length > 0)\n\n setShowDeleteDialog(true)\n setCommentToDelete({\n commentId: id,\n isParent,\n })\n }","c","useCallback(\n (id: string) => {\n const parent = currentComments.find((c) => c.parentComment?._id === id)\n const isParent = Boolean(parent && parent?.replies?.length > 0)\n\n setShowDeleteDialog(true)\n setCommentToDelete({\n commentId: id,\n isParent,\n })\n },\n\n [currentComments],\n )","async (id: string) => {\n try {\n setDeleteLoading(true)\n await operation.remove(id)\n closeDeleteDialog()\n } catch (err) {\n setDeleteError(err)\n }\n setDeleteLoading(false)\n }","err","useCallback(\n async (id: string) => {\n try {\n setDeleteLoading(true)\n await operation.remove(id)\n closeDeleteDialog()\n } catch (err) {\n setDeleteError(err)\n }\n setDeleteLoading(false)\n },\n [closeDeleteDialog, operation],\n )","(id: string, nextStatus: CommentStatus) => {\n void operation.update(id, {\n status: nextStatus,\n })\n\n // If the comment is being opened, we want to change to the \"open\" view\n // and scroll to the comment\n if (nextStatus === 'open') {\n setStatus('open')\n\n const comment = getComment(id)\n\n if (!comment) return\n\n setSelectedPath({\n fieldPath: comment.target.path?.field || null,\n origin: 'inspector',\n threadId: comment.threadId || null,\n })\n\n scrollToComment(id)\n }\n }","comment","useCallback(\n (id: string, nextStatus: CommentStatus) => {\n void operation.update(id, {\n status: nextStatus,\n })\n\n // If the comment is being opened, we want to change to the \"open\" view\n // and scroll to the comment\n if (nextStatus === 'open') {\n setStatus('open')\n\n const comment = getComment(id)\n\n if (!comment) return\n\n setSelectedPath({\n fieldPath: comment.target.path?.field || null,\n origin: 'inspector',\n threadId: comment.threadId || null,\n })\n\n scrollToComment(id)\n }\n },\n [getComment, operation, scrollToComment, setSelectedPath, setStatus],\n )","(id: string, reaction: CommentReactionOption) => {\n void operation.react(id, reaction)\n }","useCallback(\n (id: string, reaction: CommentReactionOption) => {\n void operation.react(id, reaction)\n },\n [operation],\n )","() => {\n // Clear the selected path when:\n // - Clicking outside the inspector when it's the top layer\n // - The target is not a slate editor string. This is needed because we do not want to\n // frequently deselect the selected path when clicking inside the editor.\n if (selectedPath && isTopLayer) {\n setSelectedPath(null)\n }\n }","useCallback(() => {\n // Clear the selected path when:\n // - Clicking outside the inspector when it's the top layer\n // - The target is not a slate editor string. This is needed because we do not want to\n // frequently deselect the selected path when clicking inside the editor.\n if (selectedPath && isTopLayer) {\n setSelectedPath(null)\n }\n }, [isTopLayer, selectedPath, setSelectedPath])","(element: HTMLDivElement | null) => {\n rootRef.current = element\n setRootElement(element)\n }","useCallback((element: HTMLDivElement | null) => {\n rootRef.current = element\n setRootElement(element)\n }, [])","(event) => {\n // Clear the selected path when clicking outside the comments inspector.\n // We do this only when the comments inspector is the top layer.\n const isPTETarget =\n event.target instanceof HTMLElement && event.target?.hasAttribute('data-pt-text')\n\n if (!isPTETarget) {\n handleDeselectPath()\n }\n }","() => [rootRef.current]","() => {\n if (loggedTelemetry || mode !== 'upsell') return undefined\n // oxlint-disable-next-line react/set-state-in-effect -- pre-existing violation, to be fixed in a follow-up\n setLoggedTelemetry(true)\n if (selectedPath?.origin === 'form') {\n upsellTelemetryLogs.panelViewed('field_action')\n } else if (commentIdParamRef.current) {\n upsellTelemetryLogs.panelViewed('link')\n } else {\n upsellTelemetryLogs.panelViewed('document_action')\n }\n return () => {\n upsellTelemetryLogs.panelDismissed()\n }\n }","origin","[loggedTelemetry, mode, selectedPath?.origin, upsellTelemetryLogs]","selectedPath?.origin","() => {\n // Make sure that the comment exists before we try to scroll to it.\n // We can't solely rely on the comment id from the url since the comment might not be loaded yet.\n const commentToScrollTo = getComment(commentIdParamRef.current || '')\n\n if (!loading && commentToScrollTo && !didScrollToCommentFromParam.current) {\n // Make sure we have the correct status set before we scroll to the comment\n setStatus(commentToScrollTo.status || 'open')\n\n handlePathSelect({\n fieldPath: commentToScrollTo.target.path?.field || null,\n origin: 'url',\n threadId: commentToScrollTo.threadId || null,\n })\n\n // Defer the comment scroll to prevent React batching from overwriting the field scroll\n requestAnimationFrame(() => {\n scrollToComment(commentToScrollTo._id)\n })\n\n didScrollToCommentFromParam.current = true\n commentIdParamRef.current = undefined\n\n onClearSelectedComment?.()\n\n telemetry.commentViewedFromLink()\n }\n }","[\n getComment,\n handlePathSelect,\n loading,\n onClearSelectedComment,\n scrollToComment,\n setStatus,\n telemetry,\n ]","useMemo(() => {\n if (mode === 'upsell' && upsellData) {\n return (\n <CommentsUpsellPanel\n data={upsellData}\n onPrimaryClick={upsellTelemetryLogs.panelPrimaryClicked}\n onSecondaryClick={upsellTelemetryLogs.panelSecondaryClicked}\n />\n )\n }\n\n return null\n }, [\n mode,\n upsellTelemetryLogs.panelPrimaryClicked,\n upsellTelemetryLogs.panelSecondaryClicked,\n upsellData,\n ])","<CommentsUpsellPanel\n data={upsellData}\n onPrimaryClick={upsellTelemetryLogs.panelPrimaryClicked}\n onSecondaryClick={upsellTelemetryLogs.panelSecondaryClicked}\n />","panelPrimaryClicked","panelSecondaryClicked","commentToDelete && showDeleteDialog && (\n <CommentDeleteDialog\n {...commentToDelete}\n error={deleteError}\n loading={deleteLoading}\n onClose={closeDeleteDialog}\n onConfirm={handleDeleteConfirm}\n />\n )","<CommentsInspectorHeader\n onClose={handleCloseInspector}\n onViewChange={handleChangeView}\n view={status}\n mode={mode}\n />","<CommentsOnboardingPopover\n onDismiss={setDismissed}\n open={!isDismissed}\n placement=\"left-start\"\n >\n <CommentsInspectorHeader\n onClose={handleCloseInspector}\n onViewChange={handleChangeView}\n view={status}\n mode={mode}\n />\n </CommentsOnboardingPopover>","!isDismissed","currentUser && (\n <CommentsList\n beforeListNode={beforeListNode}\n comments={currentComments}\n currentUser={currentUser}\n error={comments.error}\n loading={loading}\n mentionOptions={mentionOptions}\n mode={mode}\n onCopyLink={handleCopyLink}\n onCreateRetry={handleCreateRetry}\n onDelete={onDeleteStart}\n onEdit={handleEdit}\n onNewThreadCreate={handleNewThreadCreate}\n onPathSelect={handlePathSelect}\n onReactionSelect={handleReactionSelect}\n onReply={handleReply}\n onStatusChange={handleStatusChange}\n readOnly={readOnly}\n selectedPath={selectedPath}\n status={status}\n />\n )","error","<Flex\n flexDirection=\"column\"\n flexBasis=\"0%\"\n flexGrow={1}\n height=\"100%\"\n onClick={handleDeselectPath}\n overflow=\"hidden\"\n ref={setRootRef}\n >\n <CommentsOnboardingPopover\n onDismiss={setDismissed}\n open={!isDismissed}\n placement=\"left-start\"\n >\n <CommentsInspectorHeader\n onClose={handleCloseInspector}\n onViewChange={handleChangeView}\n view={status}\n mode={mode}\n />\n </CommentsOnboardingPopover>\n {currentUser && (\n <CommentsList\n beforeListNode={beforeListNode}\n comments={currentComments}\n currentUser={currentUser}\n error={comments.error}\n loading={loading}\n mentionOptions={mentionOptions}\n mode={mode}\n onCopyLink={handleCopyLink}\n onCreateRetry={handleCreateRetry}\n onDelete={onDeleteStart}\n onEdit={handleEdit}\n onNewThreadCreate={handleNewThreadCreate}\n onPathSelect={handlePathSelect}\n onReactionSelect={handleReactionSelect}\n onReply={handleReply}\n onStatusChange={handleStatusChange}\n readOnly={readOnly}\n selectedPath={selectedPath}\n status={status}\n />\n )}\n </Flex>","<Fragment>\n {commentToDelete && showDeleteDialog && (\n <CommentDeleteDialog\n {...commentToDelete}\n error={deleteError}\n loading={deleteLoading}\n onClose={closeDeleteDialog}\n onConfirm={handleDeleteConfirm}\n />\n )}\n\n <Flex\n flexDirection=\"column\"\n flexBasis=\"0%\"\n flexGrow={1}\n height=\"100%\"\n onClick={handleDeselectPath}\n overflow=\"hidden\"\n ref={setRootRef}\n >\n <CommentsOnboardingPopover\n onDismiss={setDismissed}\n open={!isDismissed}\n placement=\"left-start\"\n >\n <CommentsInspectorHeader\n onClose={handleCloseInspector}\n onViewChange={handleChangeView}\n view={status}\n mode={mode}\n />\n </CommentsOnboardingPopover>\n {currentUser && (\n <CommentsList\n beforeListNode={beforeListNode}\n comments={currentComments}\n currentUser={currentUser}\n error={comments.error}\n loading={loading}\n mentionOptions={mentionOptions}\n mode={mode}\n onCopyLink={handleCopyLink}\n onCreateRetry={handleCreateRetry}\n onDelete={onDeleteStart}\n onEdit={handleEdit}\n onNewThreadCreate={handleNewThreadCreate}\n onPathSelect={handlePathSelect}\n onReactionSelect={handleReactionSelect}\n onReply={handleReply}\n onStatusChange={handleStatusChange}\n readOnly={readOnly}\n selectedPath={selectedPath}\n status={status}\n />\n )}\n </Flex>\n </Fragment>"],"sources":["../src/core/comments-v2/components/list/CommentsListStatus.tsx","../src/core/comments-v2/components/CommentBreadcrumbs.tsx","../src/core/comments-v2/components/list/CreateNewThreadInput.tsx","../src/core/comments-v2/components/list/CommentThreadLayout.tsx","../src/core/comments-v2/components/list/CommentsList.tsx","../src/core/comments-v2/components/onboarding/CommentsOnboardingPopover.tsx","../src/core/comments-v2/components/upsell/CommentsUpsellPanel.tsx","../src/core/comments-v2/hooks/useCommentsOnboarding.ts","../src/core/comments-v2/__telemetry__/comments.telemetry.ts","../src/core/comments-v2/hooks/useCommentsTelemetry.ts","../src/core/comments-v2/plugin/inspector/CommentsInspectorHeader.tsx","../src/core/comments-v2/plugin/inspector/CommentsInspector.tsx"],"sourcesContent":["import {Text, Container, Flex, VStack} from 'ui5'\n\nimport {LoadingBlock} from '../../../components/loadingBlock/LoadingBlock'\nimport {useTranslation} from '../../../i18n/hooks/useTranslation'\nimport {type TFunction} from '../../../i18n/types'\nimport {commentsLocaleNamespace} from '../../i18n'\nimport {type CommentStatus} from '../../types'\n\ninterface EmptyStateMessage {\n title: string\n message: React.ReactNode\n}\n\nfunction getEmptyStateMessages(t: TFunction): Record<CommentStatus, EmptyStateMessage> {\n return {\n open: {\n title: t('list-status.empty-state-open-title'),\n message: t('list-status.empty-state-open-text'),\n },\n resolved: {\n title: t('list-status.empty-state-resolved-title'),\n message: t('list-status.empty-state-resolved-text'),\n },\n }\n}\n\ninterface CommentsListStatusProps {\n error: Error | null\n hasNoComments: boolean\n loading: boolean\n status: CommentStatus\n}\n\nexport function CommentsListStatus(props: CommentsListStatusProps) {\n const {status, error, loading, hasNoComments} = props\n const {t} = useTranslation(commentsLocaleNamespace)\n const emptyStateMessages = getEmptyStateMessages(t)\n\n if (error) {\n return (\n <Flex alignItems=\"center\" justifyContent=\"center\" flexBasis=\"0%\" flexGrow={1} padding={4}>\n <Flex alignItems=\"center\">\n <Text size={1} muted as=\"div\" trim={true}>\n {t('list-status.error')}\n </Text>\n </Flex>\n </Flex>\n )\n }\n\n if (loading) {\n return <LoadingBlock showText title={t('list-status.loading')} />\n }\n\n if (hasNoComments) {\n return (\n <Flex alignItems=\"center\" justifyContent=\"center\" flexBasis=\"0%\" flexGrow={1}>\n <Container size={0} padding={4}>\n <VStack gap={3}>\n <Text align=\"center\" size={1} muted weight=\"medium\" as=\"div\" trim={true}>\n {emptyStateMessages[status].title}\n </Text>\n\n <Text align=\"center\" size={1} muted as=\"div\" trim={true}>\n {emptyStateMessages[status].message}\n </Text>\n </VStack>\n </Container>\n </Flex>\n )\n }\n\n return null\n}\n","import {ChevronRightIcon} from '@sanity/icons/ChevronRight'\nimport {Fragment, useMemo} from 'react'\nimport {Text, Box, Flex, Icon} from 'ui5'\n\nimport {Tooltip} from '../../../ui-components/tooltip/Tooltip'\n\nexport interface CommentBreadcrumbsProps {\n titlePath: string[]\n maxLength: number\n}\n\ntype Item = string | string[]\n\nconst separator = <Icon muted icon={ChevronRightIcon} style={{margin: '-0.4375rem'}} />\n\nconst renderItem = (item: string, index: number) => {\n return (\n <Box key={`${item}-${index}`} as=\"li\">\n <Text truncate={1} size={1} weight=\"medium\" as=\"div\" trim={true}>\n {item}\n </Text>\n </Box>\n )\n}\n\nexport function CommentBreadcrumbs(props: CommentBreadcrumbsProps) {\n const {titlePath, maxLength} = props\n\n const items: Item[] = useMemo(() => {\n const len = titlePath.length\n const beforeLength = Math.ceil(maxLength / 2)\n const afterLength = Math.floor(maxLength / 2)\n\n if (maxLength && len > maxLength) {\n return [\n ...titlePath.slice(0, beforeLength - 1),\n titlePath.slice(beforeLength - 1, len - afterLength),\n ...titlePath.slice(len - afterLength),\n ]\n }\n\n return titlePath\n }, [maxLength, titlePath])\n\n const nodes = useMemo(() => {\n return items.map((item, index) => {\n const key = `${item}-${index}`\n const showSeparator = index < items.length - 1\n\n if (Array.isArray(item)) {\n return (\n <Fragment key={key}>\n <Tooltip\n content={\n <Flex gap={2} padding={2} flexDirection=\"column\">\n {item.map(renderItem)}\n </Flex>\n }\n >\n <Box>{renderItem('...', index)}</Box>\n </Tooltip>\n\n {showSeparator && separator}\n </Fragment>\n )\n }\n\n return (\n <Fragment key={key}>\n {renderItem(item, index)}\n\n {showSeparator && separator}\n </Fragment>\n )\n })\n }, [items])\n\n return (\n <Flex alignItems=\"center\" as=\"ol\" gap={2}>\n {nodes}\n </Flex>\n )\n}\n","import {type CurrentUser, type PortableTextBlock} from '@sanity/types'\nimport {useCallback, useMemo, useRef, useState} from 'react'\n\nimport {type UserListWithPermissionsHookValue} from '../../../hooks/useUserListWithPermissions'\nimport {useTranslation} from '../../../i18n/hooks/useTranslation'\nimport {Translate} from '../../../i18n/Translate'\nimport {hasCommentMessageValue} from '../../helpers'\nimport {commentsLocaleNamespace} from '../../i18n'\nimport {type CommentMessage, type CommentsUIMode} from '../../types'\nimport {\n CommentInput,\n type CommentInputHandle,\n type CommentInputProps,\n} from '../pte/comment-input/CommentInput'\n\nconst EMPTY_PT_ARRAY: PortableTextBlock[] = []\n\ninterface CreateNewThreadInputProps {\n currentUser: CurrentUser\n fieldTitle: string\n mentionOptions: UserListWithPermissionsHookValue\n mode: CommentsUIMode\n onBlur?: CommentInputProps['onBlur']\n onFocus?: CommentInputProps['onFocus']\n onKeyDown?: (event: React.KeyboardEvent) => void\n onNewThreadCreate: (payload: CommentMessage) => void\n readOnly?: boolean\n}\n\nexport function CreateNewThreadInput(props: CreateNewThreadInputProps) {\n const {\n currentUser,\n fieldTitle,\n mentionOptions,\n mode,\n onBlur,\n onFocus,\n onKeyDown,\n onNewThreadCreate,\n readOnly,\n } = props\n const {t} = useTranslation(commentsLocaleNamespace)\n\n const [value, setValue] = useState<CommentMessage>(EMPTY_PT_ARRAY)\n const commentInputHandle = useRef<CommentInputHandle | null>(null)\n\n const handleSubmit = useCallback(\n (nextValue: CommentMessage) => {\n onNewThreadCreate?.(nextValue)\n setValue(EMPTY_PT_ARRAY)\n },\n [onNewThreadCreate],\n )\n\n const hasValue = useMemo(() => hasCommentMessageValue(value), [value])\n\n const startDiscard = useCallback(() => {\n if (!hasValue) {\n return\n }\n commentInputHandle.current?.discardDialogController.open()\n }, [hasValue])\n\n const handleInputKeyDown = useCallback(\n (event: React.KeyboardEvent) => {\n // Don't act if the input already prevented this event\n if (event.isDefaultPrevented()) {\n return\n }\n // Discard the input text\n if (event.key === 'Escape') {\n event.preventDefault()\n event.stopPropagation()\n startDiscard()\n }\n // Call parent handler\n if (onKeyDown) onKeyDown(event)\n },\n [onKeyDown, startDiscard],\n )\n\n const confirmDiscard = useCallback(() => {\n setValue(EMPTY_PT_ARRAY)\n commentInputHandle.current?.discardDialogController.close()\n commentInputHandle.current?.focus()\n }, [])\n\n const cancelDiscard = useCallback(() => {\n commentInputHandle.current?.discardDialogController.close()\n }, [])\n\n const placeholder =\n mode === 'upsell' ? (\n t('compose.add-comment-input-placeholder-upsell')\n ) : (\n <Translate\n t={t}\n i18nKey=\"compose.add-comment-input-placeholder\"\n values={{field: fieldTitle}}\n />\n )\n\n return (\n <CommentInput\n currentUser={currentUser}\n expandOnFocus\n mentionOptions={mentionOptions}\n onBlur={onBlur}\n onChange={setValue}\n onDiscardCancel={cancelDiscard}\n onDiscardConfirm={confirmDiscard}\n onKeyDown={handleInputKeyDown}\n onFocus={onFocus}\n onSubmit={handleSubmit}\n placeholder={placeholder}\n readOnly={readOnly || mode === 'upsell'}\n ref={commentInputHandle}\n value={value}\n />\n )\n}\n","import {type CurrentUser} from '@sanity/types'\nimport {\n // oxlint-disable-next-line no-restricted-imports\n Button, // Button with specific styling and children behavior.\n} from '@sanity/ui'\nimport {uuid} from '@sanity/uuid'\nimport {type MouseEvent, type ReactNode, useCallback, useMemo} from 'react'\nimport {css, styled} from 'styled-components'\nimport {Flex, VStack} from 'ui5'\n\nimport {type UserListWithPermissionsHookValue} from '../../../hooks/useUserListWithPermissions'\nimport {useTranslation} from '../../../i18n/hooks/useTranslation'\nimport {type CommentsSelectedPath} from '../../context/selected-path/types'\nimport {commentsLocaleNamespace} from '../../i18n'\nimport {\n type CommentBaseCreatePayload,\n type CommentListBreadcrumbs,\n type CommentMessage,\n type CommentsUIMode,\n} from '../../types'\nimport {CommentBreadcrumbs} from '../CommentBreadcrumbs'\nimport {CreateNewThreadInput} from './CreateNewThreadInput'\nimport {ThreadCard} from './styles'\n\nconst HeaderFlex = styled(Flex)`\n min-height: 25px;\n`\n\nconst BreadcrumbsButton = styled(Button)(({theme}) => {\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n const fg = theme.sanity.color.base.fg\n return css`\n --card-fg-color: ${fg};\n\n // The width is needed to make the text ellipsis work\n // in the breadcrumbs component\n max-width: 100%;\n `\n})\n\ninterface CommentThreadLayoutProps {\n breadcrumbs?: CommentListBreadcrumbs\n canCreateNewThread: boolean\n children: ReactNode\n currentUser: CurrentUser\n fieldPath: string\n isSelected: boolean\n mentionOptions: UserListWithPermissionsHookValue\n mode: CommentsUIMode\n onNewThreadCreate: (payload: CommentBaseCreatePayload) => void\n onPathSelect?: (nextPath: CommentsSelectedPath) => void\n readOnly?: boolean\n}\n\nexport function CommentThreadLayout(props: CommentThreadLayoutProps) {\n const {\n breadcrumbs,\n canCreateNewThread,\n children,\n currentUser,\n fieldPath,\n isSelected,\n mentionOptions,\n mode,\n onNewThreadCreate,\n onPathSelect,\n readOnly,\n } = props\n\n const {t} = useTranslation(commentsLocaleNamespace)\n\n const handleNewThreadCreate = useCallback(\n (payload: CommentMessage) => {\n const nextComment: CommentBaseCreatePayload = {\n message: payload,\n parentCommentId: undefined,\n status: 'open',\n // Since this is a new comment, we generate a new thread ID\n threadId: uuid(),\n // New comments have no reactions\n reactions: [],\n\n payload: {\n fieldPath,\n },\n }\n\n onNewThreadCreate?.(nextComment)\n },\n [onNewThreadCreate, fieldPath],\n )\n\n const handleBreadcrumbsClick = useCallback(\n (e: MouseEvent<HTMLButtonElement>) => {\n e.stopPropagation()\n\n onPathSelect?.({\n fieldPath,\n origin: 'inspector',\n threadId: null,\n })\n },\n [fieldPath, onPathSelect],\n )\n\n const handleNewThreadClick = useCallback(\n (e: MouseEvent<HTMLDivElement>) => {\n e.stopPropagation()\n // Skip if the click was triggered from \"Enter\" keydown.\n // This because we don't want to trigger `onPathSelect` when\n // submitting the new thread form.\n if (e.detail === 0) return\n\n onPathSelect?.({\n fieldPath,\n origin: 'inspector',\n threadId: null,\n })\n },\n [fieldPath, onPathSelect],\n )\n\n const crumbsTitlePath = useMemo(() => breadcrumbs?.map((p) => p.title) || [], [breadcrumbs])\n const lastCrumb = crumbsTitlePath[crumbsTitlePath.length - 1]\n\n return (\n <VStack gap={2}>\n <HeaderFlex alignItems=\"center\" gap={2} paddingRight={1}>\n <Flex flexBasis=\"0%\" flexGrow={1} flexDirection=\"column\">\n <Flex alignItems=\"center\">\n <BreadcrumbsButton\n aria-label={t('list-item.breadcrumb-button-go-to-field-aria-label', {\n field: lastCrumb,\n })}\n mode=\"bleed\"\n onClick={handleBreadcrumbsClick}\n padding={2}\n gap={2}\n >\n <CommentBreadcrumbs maxLength={3} titlePath={crumbsTitlePath} />\n </BreadcrumbsButton>\n </Flex>\n </Flex>\n </HeaderFlex>\n\n {canCreateNewThread && (\n <ThreadCard onClick={handleNewThreadClick} data-active={isSelected}>\n <CreateNewThreadInput\n currentUser={currentUser}\n fieldTitle={lastCrumb}\n mentionOptions={mentionOptions}\n mode={mode}\n onNewThreadCreate={handleNewThreadCreate}\n readOnly={readOnly}\n />\n </ThreadCard>\n )}\n\n <VStack gap={2}>{children}</VStack>\n </VStack>\n )\n}\n","import {type CurrentUser} from '@sanity/types'\nimport {BoundaryElementProvider} from '@sanity/ui'\nimport {memo, useMemo, useState, type RefAttributes} from 'react'\nimport {Flex} from 'ui5'\n\nimport {type UserListWithPermissionsHookValue} from '../../../hooks/useUserListWithPermissions'\nimport {type CommentsSelectedPath} from '../../context/selected-path/types'\nimport {applyCommentsGroupAttr} from '../../hooks/useCommentsScroll'\nimport {\n type CommentBaseCreatePayload,\n type CommentReactionOption,\n type CommentStatus,\n type CommentsUIMode,\n type CommentThreadItem,\n type CommentUpdatePayload,\n} from '../../types'\nimport {CommentsListItem} from './CommentsListItem'\nimport {CommentsListStatus} from './CommentsListStatus'\nimport {CommentThreadLayout} from './CommentThreadLayout'\n\ninterface GroupedComments {\n [field: string]: CommentThreadItem[]\n}\n\nfunction groupThreads(comments: CommentThreadItem[]) {\n return comments.reduce((acc, comment) => {\n const field = comment.fieldPath\n\n if (!acc[field]) {\n acc[field] = []\n }\n\n acc[field].push(comment)\n\n return acc\n }, {} as GroupedComments)\n}\n\n/**\n * @beta\n * @hidden\n */\nexport interface CommentsListProps {\n beforeListNode?: React.ReactNode\n comments: CommentThreadItem[]\n currentUser: CurrentUser\n error: Error | null\n loading: boolean\n mentionOptions: UserListWithPermissionsHookValue\n mode: CommentsUIMode\n onCopyLink?: (id: string) => void\n onCreateRetry: (id: string) => void\n onDelete: (id: string) => void\n onEdit: (id: string, payload: CommentUpdatePayload) => void\n onNewThreadCreate: (payload: CommentBaseCreatePayload) => void\n /**\n * @internal\n */\n onPathSelect?: (nextPath: CommentsSelectedPath) => void\n onReactionSelect?: (id: string, reaction: CommentReactionOption) => void\n onReply: (payload: CommentBaseCreatePayload) => void\n onStatusChange?: (id: string, status: CommentStatus) => void\n readOnly?: boolean\n /**\n * @internal\n */\n selectedPath: CommentsSelectedPath | null\n status: CommentStatus\n}\n\n/**\n * @beta\n * @hidden\n */\nexport interface CommentsListHandle {\n scrollToComment: (id: string) => void\n}\n\nfunction CommentsListInner(props: CommentsListProps & RefAttributes<HTMLUListElement>) {\n const {\n ref,\n beforeListNode,\n comments,\n currentUser,\n error,\n loading,\n mentionOptions,\n mode,\n onCopyLink,\n onCreateRetry,\n onDelete,\n onEdit,\n onNewThreadCreate,\n onPathSelect,\n onReactionSelect,\n onReply,\n onStatusChange,\n readOnly,\n selectedPath,\n status,\n } = props\n const [boundaryElement, setBoundaryElement] = useState<HTMLDivElement | null>(null)\n\n const groupedThreads = useMemo(() => Object.entries(groupThreads(comments)), [comments])\n\n const showComments = !loading && !error && groupedThreads.length > 0\n\n return (\n <Flex\n data-testid=\"comments-list\"\n flexDirection=\"column\"\n flexBasis=\"0%\"\n flexGrow={1}\n height=\"100%\"\n overflow=\"hidden\"\n ref={setBoundaryElement}\n >\n {mode !== 'upsell' && (\n <CommentsListStatus\n error={error}\n hasNoComments={groupedThreads.length === 0}\n loading={loading}\n status={status}\n />\n )}\n\n {(showComments || beforeListNode) && (\n <Flex\n as=\"ul\"\n flexBasis=\"0%\"\n flexGrow={1}\n overflow=\"auto\"\n padding={3}\n paddingTop={1}\n paddingBottom={6}\n gap={1}\n ref={ref}\n flexDirection=\"column\"\n >\n {beforeListNode}\n\n <BoundaryElementProvider element={boundaryElement}>\n {groupedThreads?.map(([fieldPath, group]) => {\n // Since all threads in the group point to the same field, the breadcrumbs will be\n // the same for all of them. Therefore, we can just pick the first one.\n const breadcrumbs = group[0].breadcrumbs\n\n // The thread ID is used to scroll to the thread.\n // We pick the first thread id in the group so that we scroll to the first thread\n // in the group.\n const firstThreadId = group[0].threadId\n\n // The new thread is selected if the field path matches the selected path and\n // there is no thread ID selected.\n const newThreadSelected =\n selectedPath?.fieldPath === fieldPath && !selectedPath.threadId\n\n return (\n <Flex\n key={fieldPath}\n as=\"li\"\n paddingTop={3}\n {...applyCommentsGroupAttr(firstThreadId)}\n flexDirection=\"column\"\n flexShrink={0}\n >\n <CommentThreadLayout\n key={fieldPath}\n breadcrumbs={breadcrumbs}\n canCreateNewThread={status === 'open'}\n currentUser={currentUser}\n fieldPath={fieldPath}\n isSelected={newThreadSelected}\n mentionOptions={mentionOptions}\n mode={mode}\n onNewThreadCreate={onNewThreadCreate}\n onPathSelect={onPathSelect}\n readOnly={readOnly}\n >\n {group.map((item) => {\n // The default sort order is by date, descending (newest first).\n // However, inside a thread, we want the order to be ascending (oldest first).\n // So we reverse the array here.\n // We use slice() to avoid mutating the original array.\n const replies = item.replies.slice().reverse()\n\n const canReply =\n status === 'open' &&\n item.parentComment._state?.type !== 'createError' &&\n item.parentComment._state?.type !== 'createRetrying'\n\n // The thread is selected if the thread ID and field path matches the\n // selected path.\n const threadIsSelected =\n selectedPath?.threadId === item.parentComment.threadId &&\n selectedPath?.fieldPath === item.parentComment.target.path?.field\n\n return (\n <CommentsListItem\n key={item.parentComment._id}\n canReply={canReply}\n currentUser={currentUser}\n hasReferencedValue={item.hasReferencedValue}\n isSelected={threadIsSelected}\n mentionOptions={mentionOptions}\n mode={mode}\n onCopyLink={onCopyLink}\n onCreateRetry={onCreateRetry}\n onDelete={onDelete}\n onEdit={onEdit}\n onPathSelect={onPathSelect}\n onReactionSelect={onReactionSelect}\n onReply={onReply}\n onStatusChange={onStatusChange}\n parentComment={item.parentComment}\n readOnly={readOnly}\n replies={replies}\n />\n )\n })}\n </CommentThreadLayout>\n </Flex>\n )\n })}\n </BoundaryElementProvider>\n </Flex>\n )}\n </Flex>\n )\n}\n\n/**\n * @beta\n * @hidden\n */\nexport const CommentsList = memo(CommentsListInner)\n","import {keyframes, styled} from 'styled-components'\nimport {Text, Box, Flex, VStack} from 'ui5'\n\nimport {Button} from '../../../../ui-components/button/Button'\nimport {Popover, type PopoverProps} from '../../../../ui-components/popover/Popover'\nimport {useTranslation} from '../../../i18n/hooks/useTranslation'\nimport {commentsLocaleNamespace} from '../../i18n'\n\nconst Root = styled(Box)`\n max-width: 280px;\n`\n\nconst fadeInKeyFrame = keyframes`\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n`\n\nconst StyledPopover = styled(Popover)`\n opacity: 0;\n // Fade in the popover after 500ms\n animation: ${fadeInKeyFrame} 200ms 500ms forwards;\n`\n\ninterface CommentsOnboardingPopoverProps extends Omit<PopoverProps, 'content'> {\n // ...\n onDismiss: () => void\n}\n\nexport function CommentsOnboardingPopover(props: CommentsOnboardingPopoverProps) {\n const {onDismiss, ...rest} = props\n const {t} = useTranslation(commentsLocaleNamespace)\n\n return (\n <StyledPopover\n content={\n <Root padding={4}>\n <VStack gap={3}>\n <Text weight=\"medium\" size={1} as=\"div\" trim={true}>\n {t('onboarding.header')}\n </Text>\n\n <Text size={1} as=\"div\" trim={true}>\n {t('onboarding.body')}\n </Text>\n\n <Flex justifyContent=\"flex-end\" marginTop={2}>\n <Button text={t('onboarding.dismiss')} tone=\"primary\" onClick={onDismiss} />\n </Flex>\n </VStack>\n </Root>\n }\n open\n portal\n {...rest}\n />\n )\n}\n","import {Container, Box} from 'ui5'\n\nimport {type UpsellData} from '../../../studio/upsell/types'\nimport {UpsellPanel} from '../../../studio/upsell/UpsellPanel'\n\ninterface CommentsUpsellPanelProps {\n data: UpsellData\n onPrimaryClick: () => void\n onSecondaryClick: () => void\n}\n\nexport function CommentsUpsellPanel(props: CommentsUpsellPanelProps) {\n const {data, onPrimaryClick, onSecondaryClick} = props\n return (\n <Container size={1}>\n <Box marginBottom={6}>\n <UpsellPanel\n data={data}\n onPrimaryClick={onPrimaryClick}\n onSecondaryClick={onSecondaryClick}\n />\n </Box>\n </Container>\n )\n}\n","import {useContext} from 'react'\nimport {CommentsOnboardingContextV2} from 'sanity/_singletons'\n\nimport {type CommentsOnboardingContextValue} from '../context/onboarding/types'\n\nexport function useCommentsOnboarding(): CommentsOnboardingContextValue {\n const ctx = useContext(CommentsOnboardingContextV2)\n\n if (!ctx) {\n throw new Error('useCommentsOnboarding: missing context value')\n }\n\n return ctx\n}\n","import {defineEvent} from '@sanity/telemetry'\n\nimport {type CommentStatus} from '../types'\n\nexport const CommentLinkCopied = defineEvent({\n name: 'Comment Link Copied',\n version: 1,\n description: 'The link to a comment is copied',\n})\n\nexport const CommentViewedFromLink = defineEvent({\n name: 'Comment Viewed From Link',\n version: 1,\n description: 'A comment is viewed from a link',\n})\n\nexport const CommentListViewChanged = defineEvent<{view: CommentStatus}>({\n name: 'Comment List View Changed',\n version: 1,\n description: 'The view of the comment list is changed',\n})\n","import {useTelemetry} from '@sanity/telemetry/react'\nimport {useCallback, useMemo} from 'react'\n\nimport {\n CommentLinkCopied,\n CommentListViewChanged,\n CommentViewedFromLink,\n} from '../__telemetry__/comments.telemetry'\nimport {type CommentStatus} from '../types'\n\ninterface CommentsTelemetryHookValue {\n commentLinkCopied: () => void\n commentListViewChanged: (view: CommentStatus) => void\n commentViewedFromLink: () => void\n}\n\n/** @internal */\nexport function useCommentsTelemetry(): CommentsTelemetryHookValue {\n const telemetry = useTelemetry()\n\n const commentLinkCopied = useCallback(() => {\n telemetry.log(CommentLinkCopied)\n }, [telemetry])\n\n const commentViewedFromLink = useCallback(() => {\n telemetry.log(CommentViewedFromLink)\n }, [telemetry])\n\n const commentListViewChanged = useCallback(\n (view: CommentStatus) => {\n telemetry.log(CommentListViewChanged, {view})\n },\n [telemetry],\n )\n\n return useMemo(\n (): CommentsTelemetryHookValue => ({\n commentLinkCopied,\n commentListViewChanged,\n commentViewedFromLink,\n }),\n [commentLinkCopied, commentListViewChanged, commentViewedFromLink],\n )\n}\n","import {CheckmarkIcon} from '@sanity/icons/Checkmark'\nimport {ChevronDownIcon} from '@sanity/icons/ChevronDown'\nimport {CloseIcon} from '@sanity/icons/Close'\nimport {Card} from '@sanity/ui'\nimport {Menu} from '@sanity/ui/menu'\nimport {useCallback, type RefAttributes} from 'react'\nimport {styled} from 'styled-components'\nimport {Text, Flex} from 'ui5'\n\nimport {Button} from '../../../../ui-components/button/Button'\nimport {MenuButton} from '../../../../ui-components/menuButton/MenuButton'\nimport {MenuItem} from '../../../../ui-components/menuItem/MenuItem'\nimport {useTranslation} from '../../../i18n/hooks/useTranslation'\nimport {commentsLocaleNamespace} from '../../i18n'\nimport {type CommentStatus, type CommentsUIMode} from '../../types'\n\nconst Root = styled(Card)({\n position: 'relative',\n zIndex: '1',\n lineHeight: '0',\n})\n\ninterface CommentsInspectorHeaderProps {\n onClose: () => void\n onViewChange: (view: CommentStatus) => void\n view: CommentStatus\n mode: CommentsUIMode\n}\n\nexport function CommentsInspectorHeader(\n props: CommentsInspectorHeaderProps & RefAttributes<HTMLDivElement>,\n) {\n const {t} = useTranslation(commentsLocaleNamespace)\n const {ref, onClose, onViewChange, view, mode} = props\n\n const handleSetOpenView = useCallback(() => onViewChange('open'), [onViewChange])\n const handleSetResolvedView = useCallback(() => onViewChange('resolved'), [onViewChange])\n\n return (\n <Root ref={ref}>\n <Flex padding={2}>\n <Flex alignItems=\"center\" flexBasis=\"0%\" flexGrow={1} gap={2} paddingY={2} padding={3}>\n <Text as=\"h1\" size={1} weight=\"medium\" trim={true}>\n {t('feature-name')}\n </Text>\n </Flex>\n\n <Flex flexBasis=\"auto\" flexGrow={0} flexShrink={0} padding={1} gap={2}>\n <MenuButton\n id=\"comment-status-menu-button\"\n button={\n <Button\n text={\n view === 'open'\n ? t('status-filter.status-open')\n : t('status-filter.status-resolved')\n }\n mode=\"bleed\"\n iconRight={ChevronDownIcon}\n />\n }\n menu={\n <Menu style={{width: '180px'}}>\n <MenuItem\n iconRight={view === 'open' ? CheckmarkIcon : undefined}\n onClick={handleSetOpenView}\n text={t('status-filter.status-open-full')}\n />\n <MenuItem\n iconRight={view === 'resolved' ? CheckmarkIcon : undefined}\n onClick={handleSetResolvedView}\n text={t('status-filter.status-resolved-full')}\n tooltipProps={\n mode === 'upsell'\n ? {content: t('status-filter.status-resolved-full-upsell')}\n : undefined\n }\n disabled={mode === 'upsell'}\n />\n </Menu>\n }\n popover={{placement: 'bottom-end'}}\n />\n\n <Button\n aria-label={t('close-pane-button-text-aria-label')}\n icon={CloseIcon}\n mode=\"bleed\"\n onClick={onClose}\n tooltipProps={{content: t('close-pane-button-text')}}\n />\n </Flex>\n </Flex>\n </Root>\n )\n}\n","import {Layer, useClickOutsideEvent, useLayer} from '@sanity/ui'\nimport {useToast} from '@sanity/ui/toast'\nimport * as PathUtils from '@sanity/util/paths'\nimport {Fragment, useCallback, useEffect, useMemo, useRef, useState} from 'react'\nimport {styled} from 'styled-components'\nimport {Flex} from 'ui5'\n\nimport {type DocumentInspectorProps} from '../../../config/document/inspector'\nimport {useTranslation} from '../../../i18n/hooks/useTranslation'\nimport {useCurrentUser} from '../../../store/user/hooks'\nimport {CommentDeleteDialog} from '../../components/CommentDeleteDialog'\nimport {CommentsList} from '../../components/list/CommentsList'\nimport {CommentsOnboardingPopover} from '../../components/onboarding/CommentsOnboardingPopover'\nimport {CommentsUpsellPanel} from '../../components/upsell/CommentsUpsellPanel'\nimport {type CommentsSelectedPath} from '../../context/selected-path/types'\nimport {isTextSelectionComment} from '../../helpers'\nimport {useComments} from '../../hooks/useComments'\nimport {useCommentsEnabled} from '../../hooks/useCommentsEnabled'\nimport {useCommentsOnboarding} from '../../hooks/useCommentsOnboarding'\nimport {useCommentsScroll} from '../../hooks/useCommentsScroll'\nimport {useCommentsSelectedPath} from '../../hooks/useCommentsSelectedPath'\nimport {useCommentsTelemetry} from '../../hooks/useCommentsTelemetry'\nimport {useCommentsUpsell} from '../../hooks/useCommentsUpsell'\nimport {commentsLocaleNamespace} from '../../i18n'\nimport {\n type CommentBaseCreatePayload,\n type CommentReactionOption,\n type CommentStatus,\n type CommentsUIMode,\n type CommentUpdatePayload,\n} from '../../types'\nimport {CommentsInspectorHeader} from './CommentsInspectorHeader'\n\ninterface CommentToDelete {\n commentId: string\n isParent: boolean\n}\n\nconst RootLayer = styled(Layer)`\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n`\n\nexport function CommentsInspector(props: DocumentInspectorProps) {\n const {enabled, mode} = useCommentsEnabled()\n\n if (!enabled) return null\n\n // We wrap the comments inspector in a Layer in order to know when the comments inspector\n // is the top layer (that is, if there is e.g. a popover open). This is used to determine\n // if we should deselect the selected path when clicking outside the comments inspector.\n return (\n <RootLayer>\n <CommentsInspectorInner {...props} mode={mode} />\n </RootLayer>\n )\n}\n\nfunction CommentsInspectorInner(\n props: DocumentInspectorProps & {\n mode: CommentsUIMode\n },\n) {\n const {t} = useTranslation(commentsLocaleNamespace)\n const {onClose, mode} = props\n const [showDeleteDialog, setShowDeleteDialog] = useState<boolean>(false)\n const [commentToDelete, setCommentToDelete] = useState<CommentToDelete | null>(null)\n const [deleteLoading, setDeleteLoading] = useState<boolean>(false)\n const [deleteError, setDeleteError] = useState<Error | null>(null)\n\n const rootRef = useRef<HTMLDivElement | null>(null)\n const [rootElement, setRootElement] = useState<HTMLDivElement | null>(null)\n\n const currentUser = useCurrentUser()\n const {\n comments,\n getComment,\n mentionOptions,\n readOnly,\n setStatus,\n status,\n operation,\n selectedCommentId,\n getCommentLink,\n onClearSelectedComment,\n onPathOpen,\n } = useComments()\n const commentIdParamRef = useRef<string | undefined>(selectedCommentId)\n const didScrollToCommentFromParam = useRef<boolean>(false)\n\n const pushToast = useToast().push\n const {isTopLayer} = useLayer()\n\n const {scrollToComment, scrollToField, scrollToInlineComment} = useCommentsScroll({\n boundaryElement: rootElement,\n })\n const {selectedPath, setSelectedPath} = useCommentsSelectedPath()\n const {isDismissed, setDismissed} = useCommentsOnboarding()\n const telemetry = useCommentsTelemetry()\n\n const {upsellData, telemetryLogs: upsellTelemetryLogs} = useCommentsUpsell()\n\n const currentComments = useMemo(() => comments.data[status], [comments, status])\n\n const {loading} = comments\n\n const handleChangeView = useCallback(\n (nextView: CommentStatus) => {\n setStatus(nextView)\n setSelectedPath(null)\n\n telemetry.commentListViewChanged(nextView)\n },\n [setSelectedPath, setStatus, telemetry],\n )\n\n const handleCloseInspector = useCallback(() => {\n onClose()\n setSelectedPath(null)\n }, [onClose, setSelectedPath])\n\n const handleCopyLink = useMemo(() => {\n if (!getCommentLink) return undefined\n\n const copyLink = (id: string) => {\n navigator.clipboard.writeText(getCommentLink(id)).catch(() => {\n pushToast({\n closable: true,\n status: 'error',\n title: t('copy-link-error-message'),\n })\n })\n\n telemetry.commentLinkCopied()\n }\n\n return copyLink\n }, [getCommentLink, pushToast, t, telemetry])\n\n const handleCreateRetry = useCallback(\n (id: string) => {\n const comment = getComment(id)\n if (!comment) return\n\n void operation.create({\n type: 'field',\n fieldPath: comment.target.path?.field || '',\n id: comment._id,\n message: comment.message,\n parentCommentId: comment.parentCommentId,\n reactions: comment.reactions || [],\n status: comment.status,\n threadId: comment.threadId,\n })\n },\n [getComment, operation],\n )\n\n const closeDeleteDialog = useCallback(() => {\n if (deleteLoading) return\n setShowDeleteDialog(false)\n setCommentToDelete(null)\n }, [deleteLoading])\n\n const handlePathSelect = useCallback(\n (nextPath: CommentsSelectedPath) => {\n setSelectedPath(nextPath)\n\n if (nextPath?.fieldPath) {\n const path = PathUtils.fromString(nextPath.fieldPath)\n onPathOpen?.(path)\n\n scrollToField(nextPath.fieldPath)\n\n const isInlineComment = comments.data.open\n .filter((c) => c.threadId === nextPath?.threadId)\n .some((x) => isTextSelectionComment(x.parentComment))\n\n if (isInlineComment && nextPath.threadId) {\n scrollToInlineComment(nextPath.threadId)\n }\n }\n },\n [comments.data.open, onPathOpen, scrollToField, scrollToInlineComment, setSelectedPath],\n )\n\n const handleNewThreadCreate = useCallback(\n (nextComment: CommentBaseCreatePayload) => {\n const fieldPath = nextComment?.payload?.fieldPath || ''\n\n void operation.create({\n type: 'field',\n fieldPath,\n message: nextComment.message,\n parentCommentId: nextComment.parentCommentId,\n reactions: nextComment.reactions,\n status: nextComment.status,\n threadId: nextComment.threadId,\n })\n\n setSelectedPath({\n fieldPath,\n origin: 'inspector',\n threadId: nextComment.threadId,\n })\n },\n [operation, setSelectedPath],\n )\n\n const handleReply = useCallback(\n (nextComment: CommentBaseCreatePayload) => {\n void operation.create({\n ...nextComment,\n type: 'field',\n fieldPath: nextComment?.payload?.fieldPath || '',\n })\n },\n [operation],\n )\n\n const handleEdit = useCallback(\n (id: string, nextComment: CommentUpdatePayload) => {\n void operation.update(id, nextComment)\n },\n [operation],\n )\n\n const onDeleteStart = useCallback(\n (id: string) => {\n const parent = currentComments.find((c) => c.parentComment?._id === id)\n const isParent = Boolean(parent && parent?.replies?.length > 0)\n\n setShowDeleteDialog(true)\n setCommentToDelete({\n commentId: id,\n isParent,\n })\n },\n\n [currentComments],\n )\n\n const handleDeleteConfirm = useCallback(\n async (id: string) => {\n try {\n setDeleteLoading(true)\n await operation.remove(id)\n closeDeleteDialog()\n } catch (err) {\n setDeleteError(err)\n }\n setDeleteLoading(false)\n },\n [closeDeleteDialog, operation],\n )\n\n const handleStatusChange = useCallback(\n (id: string, nextStatus: CommentStatus) => {\n void operation.update(id, {\n status: nextStatus,\n })\n\n // If the comment is being opened, we want to change to the \"open\" view\n // and scroll to the comment\n if (nextStatus === 'open') {\n setStatus('open')\n\n const comment = getComment(id)\n\n if (!comment) return\n\n setSelectedPath({\n fieldPath: comment.target.path?.field || null,\n origin: 'inspector',\n threadId: comment.threadId || null,\n })\n\n scrollToComment(id)\n }\n },\n [getComment, operation, scrollToComment, setSelectedPath, setStatus],\n )\n\n const handleReactionSelect = useCallback(\n (id: string, reaction: CommentReactionOption) => {\n void operation.react(id, reaction)\n },\n [operation],\n )\n\n const handleDeselectPath = useCallback(() => {\n // Clear the selected path when:\n // - Clicking outside the inspector when it's the top layer\n // - The target is not a slate editor string. This is needed because we do not want to\n // frequently deselect the selected path when clicking inside the editor.\n if (selectedPath && isTopLayer) {\n setSelectedPath(null)\n }\n }, [isTopLayer, selectedPath, setSelectedPath])\n\n const setRootRef = useCallback((element: HTMLDivElement | null) => {\n rootRef.current = element\n setRootElement(element)\n }, [])\n\n useClickOutsideEvent(\n (event) => {\n // Clear the selected path when clicking outside the comments inspector.\n // We do this only when the comments inspector is the top layer.\n const isPTETarget =\n event.target instanceof HTMLElement && event.target?.hasAttribute('data-pt-text')\n\n if (!isPTETarget) {\n handleDeselectPath()\n }\n },\n () => [rootRef.current],\n )\n\n const [loggedTelemetry, setLoggedTelemetry] = useState(false)\n useEffect(() => {\n if (loggedTelemetry || mode !== 'upsell') return undefined\n // oxlint-disable-next-line react/set-state-in-effect -- pre-existing violation, to be fixed in a follow-up\n setLoggedTelemetry(true)\n if (selectedPath?.origin === 'form') {\n upsellTelemetryLogs.panelViewed('field_action')\n } else if (commentIdParamRef.current) {\n upsellTelemetryLogs.panelViewed('link')\n } else {\n upsellTelemetryLogs.panelViewed('document_action')\n }\n return () => {\n upsellTelemetryLogs.panelDismissed()\n }\n }, [loggedTelemetry, mode, selectedPath?.origin, upsellTelemetryLogs])\n\n // Handle scroll to comment from URL param\n useEffect(() => {\n // Make sure that the comment exists before we try to scroll to it.\n // We can't solely rely on the comment id from the url since the comment might not be loaded yet.\n const commentToScrollTo = getComment(commentIdParamRef.current || '')\n\n if (!loading && commentToScrollTo && !didScrollToCommentFromParam.current) {\n // Make sure we have the correct status set before we scroll to the comment\n setStatus(commentToScrollTo.status || 'open')\n\n handlePathSelect({\n fieldPath: commentToScrollTo.target.path?.field || null,\n origin: 'url',\n threadId: commentToScrollTo.threadId || null,\n })\n\n // Defer the comment scroll to prevent React batching from overwriting the field scroll\n requestAnimationFrame(() => {\n scrollToComment(commentToScrollTo._id)\n })\n\n didScrollToCommentFromParam.current = true\n commentIdParamRef.current = undefined\n\n onClearSelectedComment?.()\n\n telemetry.commentViewedFromLink()\n }\n }, [\n getComment,\n handlePathSelect,\n loading,\n onClearSelectedComment,\n scrollToComment,\n setStatus,\n telemetry,\n ])\n\n const beforeListNode = useMemo(() => {\n if (mode === 'upsell' && upsellData) {\n return (\n <CommentsUpsellPanel\n data={upsellData}\n onPrimaryClick={upsellTelemetryLogs.panelPrimaryClicked}\n onSecondaryClick={upsellTelemetryLogs.panelSecondaryClicked}\n />\n )\n }\n\n return null\n }, [\n mode,\n upsellTelemetryLogs.panelPrimaryClicked,\n upsellTelemetryLogs.panelSecondaryClicked,\n upsellData,\n ])\n\n return (\n <Fragment>\n {commentToDelete && showDeleteDialog && (\n <CommentDeleteDialog\n {...commentToDelete}\n error={deleteError}\n loading={deleteLoading}\n onClose={closeDeleteDialog}\n onConfirm={handleDeleteConfirm}\n />\n )}\n\n <Flex\n flexDirection=\"column\"\n flexBasis=\"0%\"\n flexGrow={1}\n height=\"100%\"\n onClick={handleDeselectPath}\n overflow=\"hidden\"\n ref={setRootRef}\n >\n <CommentsOnboardingPopover\n onDismiss={setDismissed}\n open={!isDismissed}\n placement=\"left-start\"\n >\n <CommentsInspectorHeader\n onClose={handleCloseInspector}\n onViewChange={handleChangeView}\n view={status}\n mode={mode}\n />\n </CommentsOnboardingPopover>\n {currentUser && (\n <CommentsList\n beforeListNode={beforeListNode}\n comments={currentComments}\n currentUser={currentUser}\n error={comments.error}\n loading={loading}\n mentionOptions={mentionOptions}\n mode={mode}\n onCopyLink={handleCopyLink}\n onCreateRetry={handleCreateRetry}\n onDelete={onDeleteStart}\n onEdit={handleEdit}\n onNewThreadCreate={handleNewThreadCreate}\n onPathSelect={handlePathSelect}\n onReactionSelect={handleReactionSelect}\n onReply={handleReply}\n onStatusChange={handleStatusChange}\n readOnly={readOnly}\n selectedPath={selectedPath}\n status={status}\n />\n )}\n </Flex>\n </Fragment>\n )\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"CommentsInspector-BJ1qwj6P.js","names":["getEmptyStateMessages(t)","t('list-status.error')","<Flex alignItems=\"center\" justifyContent=\"center\" flexBasis=\"0%\" flexGrow={1} padding={4}>\n <Flex alignItems=\"center\">\n <Text size={1} muted as=\"div\" trim={true}>\n {t('list-status.error')}\n </Text>\n </Flex>\n </Flex>","t('list-status.loading')","<LoadingBlock showText title={t('list-status.loading')} />","<Text align=\"center\" size={1} muted weight=\"medium\" as=\"div\" trim={true}>\n {emptyStateMessages[status].title}\n </Text>","title","emptyStateMessages[status]","<Text align=\"center\" size={1} muted as=\"div\" trim={true}>\n {emptyStateMessages[status].message}\n </Text>","message","<Flex alignItems=\"center\" justifyContent=\"center\" flexBasis=\"0%\" flexGrow={1}>\n <Container size={0} padding={4}>\n <VStack gap={3}>\n <Text align=\"center\" size={1} muted weight=\"medium\" as=\"div\" trim={true}>\n {emptyStateMessages[status].title}\n </Text>\n\n <Text align=\"center\" size={1} muted as=\"div\" trim={true}>\n {emptyStateMessages[status].message}\n </Text>\n </VStack>\n </Container>\n </Flex>","useMemo(() => {\n const len = titlePath.length\n const beforeLength = Math.ceil(maxLength / 2)\n const afterLength = Math.floor(maxLength / 2)\n\n if (maxLength && len > maxLength) {\n return [\n ...titlePath.slice(0, beforeLength - 1),\n titlePath.slice(beforeLength - 1, len - afterLength),\n ...titlePath.slice(len - afterLength),\n ]\n }\n\n return titlePath\n }, [maxLength, titlePath])","[\n ...titlePath.slice(0, beforeLength - 1),\n titlePath.slice(beforeLength - 1, len - afterLength),\n ...titlePath.slice(len - afterLength),\n ]","items.map((item, index) => {\n const key = `${item}-${index}`\n const showSeparator = index < items.length - 1\n\n if (Array.isArray(item)) {\n return (\n <Fragment key={key}>\n <Tooltip\n content={\n <Flex gap={2} padding={2} flexDirection=\"column\">\n {item.map(renderItem)}\n </Flex>\n }\n >\n <Box>{renderItem('...', index)}</Box>\n </Tooltip>\n\n {showSeparator && separator}\n </Fragment>\n )\n }\n\n return (\n <Fragment key={key}>\n {renderItem(item, index)}\n\n {showSeparator && separator}\n </Fragment>\n )\n })","items.length","(item, index) => {\n const key = `${item}-${index}`\n const showSeparator = index < items.length - 1\n\n if (Array.isArray(item)) {\n return (\n <Fragment key={key}>\n <Tooltip\n content={\n <Flex gap={2} padding={2} flexDirection=\"column\">\n {item.map(renderItem)}\n </Flex>\n }\n >\n <Box>{renderItem('...', index)}</Box>\n </Tooltip>\n\n {showSeparator && separator}\n </Fragment>\n )\n }\n\n return (\n <Fragment key={key}>\n {renderItem(item, index)}\n\n {showSeparator && separator}\n </Fragment>\n )\n }","length","useMemo(() => {\n return items.map((item, index) => {\n const key = `${item}-${index}`\n const showSeparator = index < items.length - 1\n\n if (Array.isArray(item)) {\n return (\n <Fragment key={key}>\n <Tooltip\n content={\n <Flex gap={2} padding={2} flexDirection=\"column\">\n {item.map(renderItem)}\n </Flex>\n }\n >\n <Box>{renderItem('...', index)}</Box>\n </Tooltip>\n\n {showSeparator && separator}\n </Fragment>\n )\n }\n\n return (\n <Fragment key={key}>\n {renderItem(item, index)}\n\n {showSeparator && separator}\n </Fragment>\n )\n })\n }, [items])","<Flex alignItems=\"center\" as=\"ol\" gap={2}>\n {nodes}\n </Flex>","(nextValue: CommentMessage) => {\n onNewThreadCreate?.(nextValue)\n setValue(EMPTY_PT_ARRAY)\n }","useCallback(\n (nextValue: CommentMessage) => {\n onNewThreadCreate?.(nextValue)\n setValue(EMPTY_PT_ARRAY)\n },\n [onNewThreadCreate],\n )","hasCommentMessageValue(value)","useMemo(() => hasCommentMessageValue(value), [value])","() => {\n if (!hasValue) {\n return\n }\n commentInputHandle.current?.discardDialogController.open()\n }","useCallback(() => {\n if (!hasValue) {\n return\n }\n commentInputHandle.current?.discardDialogController.open()\n }, [hasValue])","(event: React.KeyboardEvent) => {\n // Don't act if the input already prevented this event\n if (event.isDefaultPrevented()) {\n return\n }\n // Discard the input text\n if (event.key === 'Escape') {\n event.preventDefault()\n event.stopPropagation()\n startDiscard()\n }\n // Call parent handler\n if (onKeyDown) onKeyDown(event)\n }","useCallback(\n (event: React.KeyboardEvent) => {\n // Don't act if the input already prevented this event\n if (event.isDefaultPrevented()) {\n return\n }\n // Discard the input text\n if (event.key === 'Escape') {\n event.preventDefault()\n event.stopPropagation()\n startDiscard()\n }\n // Call parent handler\n if (onKeyDown) onKeyDown(event)\n },\n [onKeyDown, startDiscard],\n )","() => {\n setValue(EMPTY_PT_ARRAY)\n commentInputHandle.current?.discardDialogController.close()\n commentInputHandle.current?.focus()\n }","useCallback(() => {\n setValue(EMPTY_PT_ARRAY)\n commentInputHandle.current?.discardDialogController.close()\n commentInputHandle.current?.focus()\n }, [])","() => {\n commentInputHandle.current?.discardDialogController.close()\n }","useCallback(() => {\n commentInputHandle.current?.discardDialogController.close()\n }, [])","mode === 'upsell' ? (\n t('compose.add-comment-input-placeholder-upsell')\n ) : (\n <Translate\n t={t}\n i18nKey=\"compose.add-comment-input-placeholder\"\n values={{field: fieldTitle}}\n />\n )","<CommentInput\n currentUser={currentUser}\n expandOnFocus\n mentionOptions={mentionOptions}\n onBlur={onBlur}\n onChange={setValue}\n onDiscardCancel={cancelDiscard}\n onDiscardConfirm={confirmDiscard}\n onKeyDown={handleInputKeyDown}\n onFocus={onFocus}\n onSubmit={handleSubmit}\n placeholder={placeholder}\n readOnly={readOnly || mode === 'upsell'}\n ref={commentInputHandle}\n value={value}\n />","readOnly || mode === 'upsell'","(payload: CommentMessage) => {\n const nextComment: CommentBaseCreatePayload = {\n message: payload,\n parentCommentId: undefined,\n status: 'open',\n // Since this is a new comment, we generate a new thread ID\n threadId: uuid(),\n // New comments have no reactions\n reactions: [],\n\n payload: {\n fieldPath,\n },\n }\n\n onNewThreadCreate?.(nextComment)\n }","useCallback(\n (payload: CommentMessage) => {\n const nextComment: CommentBaseCreatePayload = {\n message: payload,\n parentCommentId: undefined,\n status: 'open',\n // Since this is a new comment, we generate a new thread ID\n threadId: uuid(),\n // New comments have no reactions\n reactions: [],\n\n payload: {\n fieldPath,\n },\n }\n\n onNewThreadCreate?.(nextComment)\n },\n [onNewThreadCreate, fieldPath],\n )","(e: MouseEvent<HTMLButtonElement>) => {\n e.stopPropagation()\n\n onPathSelect?.({\n fieldPath,\n origin: 'inspector',\n threadId: null,\n })\n }","useCallback(\n (e: MouseEvent<HTMLButtonElement>) => {\n e.stopPropagation()\n\n onPathSelect?.({\n fieldPath,\n origin: 'inspector',\n threadId: null,\n })\n },\n [fieldPath, onPathSelect],\n )","(e: MouseEvent<HTMLDivElement>) => {\n e.stopPropagation()\n // Skip if the click was triggered from \"Enter\" keydown.\n // This because we don't want to trigger `onPathSelect` when\n // submitting the new thread form.\n if (e.detail === 0) return\n\n onPathSelect?.({\n fieldPath,\n origin: 'inspector',\n threadId: null,\n })\n }","e","useCallback(\n (e: MouseEvent<HTMLDivElement>) => {\n e.stopPropagation()\n // Skip if the click was triggered from \"Enter\" keydown.\n // This because we don't want to trigger `onPathSelect` when\n // submitting the new thread form.\n if (e.detail === 0) return\n\n onPathSelect?.({\n fieldPath,\n origin: 'inspector',\n threadId: null,\n })\n },\n [fieldPath, onPathSelect],\n )","breadcrumbs?.map((p) => p.title) || []","(p) => p.title","breadcrumbs?.map","useMemo(() => breadcrumbs?.map((p) => p.title) || [], [breadcrumbs])","t('list-item.breadcrumb-button-go-to-field-aria-label', {\n field: lastCrumb,\n })","<CommentBreadcrumbs maxLength={3} titlePath={crumbsTitlePath} />","<HeaderFlex alignItems=\"center\" gap={2} paddingRight={1}>\n <Flex flexBasis=\"0%\" flexGrow={1} flexDirection=\"column\">\n <Flex alignItems=\"center\">\n <BreadcrumbsButton\n aria-label={t('list-item.breadcrumb-button-go-to-field-aria-label', {\n field: lastCrumb,\n })}\n mode=\"bleed\"\n onClick={handleBreadcrumbsClick}\n padding={2}\n gap={2}\n >\n <CommentBreadcrumbs maxLength={3} titlePath={crumbsTitlePath} />\n </BreadcrumbsButton>\n </Flex>\n </Flex>\n </HeaderFlex>","canCreateNewThread && (\n <ThreadCard onClick={handleNewThreadClick} data-active={isSelected}>\n <CreateNewThreadInput\n currentUser={currentUser}\n fieldTitle={lastCrumb}\n mentionOptions={mentionOptions}\n mode={mode}\n onNewThreadCreate={handleNewThreadCreate}\n readOnly={readOnly}\n />\n </ThreadCard>\n )","<VStack gap={2}>{children}</VStack>","<VStack gap={2}>\n <HeaderFlex alignItems=\"center\" gap={2} paddingRight={1}>\n <Flex flexBasis=\"0%\" flexGrow={1} flexDirection=\"column\">\n <Flex alignItems=\"center\">\n <BreadcrumbsButton\n aria-label={t('list-item.breadcrumb-button-go-to-field-aria-label', {\n field: lastCrumb,\n })}\n mode=\"bleed\"\n onClick={handleBreadcrumbsClick}\n padding={2}\n gap={2}\n >\n <CommentBreadcrumbs maxLength={3} titlePath={crumbsTitlePath} />\n </BreadcrumbsButton>\n </Flex>\n </Flex>\n </HeaderFlex>\n\n {canCreateNewThread && (\n <ThreadCard onClick={handleNewThreadClick} data-active={isSelected}>\n <CreateNewThreadInput\n currentUser={currentUser}\n fieldTitle={lastCrumb}\n mentionOptions={mentionOptions}\n mode={mode}\n onNewThreadCreate={handleNewThreadCreate}\n readOnly={readOnly}\n />\n </ThreadCard>\n )}\n\n <VStack gap={2}>{children}</VStack>\n </VStack>","Object.entries(groupThreads(comments))","useMemo(() => Object.entries(groupThreads(comments)), [comments])","mode !== 'upsell' && (\n <CommentsListStatus\n error={error}\n hasNoComments={groupedThreads.length === 0}\n loading={loading}\n status={status}\n />\n )","groupedThreads.length","(showComments || beforeListNode) && (\n <Flex\n as=\"ul\"\n flexBasis=\"0%\"\n flexGrow={1}\n overflow=\"auto\"\n padding={3}\n paddingTop={1}\n paddingBottom={6}\n gap={1}\n ref={ref}\n flexDirection=\"column\"\n >\n {beforeListNode}\n\n <BoundaryElementProvider element={boundaryElement}>\n {groupedThreads?.map(([fieldPath, group]) => {\n // Since all threads in the group point to the same field, the breadcrumbs will be\n // the same for all of them. Therefore, we can just pick the first one.\n const breadcrumbs = group[0].breadcrumbs\n\n // The thread ID is used to scroll to the thread.\n // We pick the first thread id in the group so that we scroll to the first thread\n // in the group.\n const firstThreadId = group[0].threadId\n\n // The new thread is selected if the field path matches the selected path and\n // there is no thread ID selected.\n const newThreadSelected =\n selectedPath?.fieldPath === fieldPath && !selectedPath.threadId\n\n return (\n <Flex\n key={fieldPath}\n as=\"li\"\n paddingTop={3}\n {...applyCommentsGroupAttr(firstThreadId)}\n flexDirection=\"column\"\n flexShrink={0}\n >\n <CommentThreadLayout\n key={fieldPath}\n breadcrumbs={breadcrumbs}\n canCreateNewThread={status === 'open'}\n currentUser={currentUser}\n fieldPath={fieldPath}\n isSelected={newThreadSelected}\n mentionOptions={mentionOptions}\n mode={mode}\n onNewThreadCreate={onNewThreadCreate}\n onPathSelect={onPathSelect}\n readOnly={readOnly}\n >\n {group.map((item) => {\n // The default sort order is by date, descending (newest first).\n // However, inside a thread, we want the order to be ascending (oldest first).\n // So we reverse the array here.\n // We use slice() to avoid mutating the original array.\n const replies = item.replies.slice().reverse()\n\n const canReply =\n status === 'open' &&\n item.parentComment._state?.type !== 'createError' &&\n item.parentComment._state?.type !== 'createRetrying'\n\n // The thread is selected if the thread ID and field path matches the\n // selected path.\n const threadIsSelected =\n selectedPath?.threadId === item.parentComment.threadId &&\n selectedPath?.fieldPath === item.parentComment.target.path?.field\n\n return (\n <CommentsListItem\n key={item.parentComment._id}\n canReply={canReply}\n currentUser={currentUser}\n hasReferencedValue={item.hasReferencedValue}\n isSelected={threadIsSelected}\n mentionOptions={mentionOptions}\n mode={mode}\n onCopyLink={onCopyLink}\n onCreateRetry={onCreateRetry}\n onDelete={onDelete}\n onEdit={onEdit}\n onPathSelect={onPathSelect}\n onReactionSelect={onReactionSelect}\n onReply={onReply}\n onStatusChange={onStatusChange}\n parentComment={item.parentComment}\n readOnly={readOnly}\n replies={replies}\n />\n )\n })}\n </CommentThreadLayout>\n </Flex>\n )\n })}\n </BoundaryElementProvider>\n </Flex>\n )","groupedThreads?.map","selectedPath?.fieldPath","[fieldPath, group]","<Flex\n data-testid=\"comments-list\"\n flexDirection=\"column\"\n flexBasis=\"0%\"\n flexGrow={1}\n height=\"100%\"\n overflow=\"hidden\"\n ref={setBoundaryElement}\n >\n {mode !== 'upsell' && (\n <CommentsListStatus\n error={error}\n hasNoComments={groupedThreads.length === 0}\n loading={loading}\n status={status}\n />\n )}\n\n {(showComments || beforeListNode) && (\n <Flex\n as=\"ul\"\n flexBasis=\"0%\"\n flexGrow={1}\n overflow=\"auto\"\n padding={3}\n paddingTop={1}\n paddingBottom={6}\n gap={1}\n ref={ref}\n flexDirection=\"column\"\n >\n {beforeListNode}\n\n <BoundaryElementProvider element={boundaryElement}>\n {groupedThreads?.map(([fieldPath, group]) => {\n // Since all threads in the group point to the same field, the breadcrumbs will be\n // the same for all of them. Therefore, we can just pick the first one.\n const breadcrumbs = group[0].breadcrumbs\n\n // The thread ID is used to scroll to the thread.\n // We pick the first thread id in the group so that we scroll to the first thread\n // in the group.\n const firstThreadId = group[0].threadId\n\n // The new thread is selected if the field path matches the selected path and\n // there is no thread ID selected.\n const newThreadSelected =\n selectedPath?.fieldPath === fieldPath && !selectedPath.threadId\n\n return (\n <Flex\n key={fieldPath}\n as=\"li\"\n paddingTop={3}\n {...applyCommentsGroupAttr(firstThreadId)}\n flexDirection=\"column\"\n flexShrink={0}\n >\n <CommentThreadLayout\n key={fieldPath}\n breadcrumbs={breadcrumbs}\n canCreateNewThread={status === 'open'}\n currentUser={currentUser}\n fieldPath={fieldPath}\n isSelected={newThreadSelected}\n mentionOptions={mentionOptions}\n mode={mode}\n onNewThreadCreate={onNewThreadCreate}\n onPathSelect={onPathSelect}\n readOnly={readOnly}\n >\n {group.map((item) => {\n // The default sort order is by date, descending (newest first).\n // However, inside a thread, we want the order to be ascending (oldest first).\n // So we reverse the array here.\n // We use slice() to avoid mutating the original array.\n const replies = item.replies.slice().reverse()\n\n const canReply =\n status === 'open' &&\n item.parentComment._state?.type !== 'createError' &&\n item.parentComment._state?.type !== 'createRetrying'\n\n // The thread is selected if the thread ID and field path matches the\n // selected path.\n const threadIsSelected =\n selectedPath?.threadId === item.parentComment.threadId &&\n selectedPath?.fieldPath === item.parentComment.target.path?.field\n\n return (\n <CommentsListItem\n key={item.parentComment._id}\n canReply={canReply}\n currentUser={currentUser}\n hasReferencedValue={item.hasReferencedValue}\n isSelected={threadIsSelected}\n mentionOptions={mentionOptions}\n mode={mode}\n onCopyLink={onCopyLink}\n onCreateRetry={onCreateRetry}\n onDelete={onDelete}\n onEdit={onEdit}\n onPathSelect={onPathSelect}\n onReactionSelect={onReactionSelect}\n onReply={onReply}\n onStatusChange={onStatusChange}\n parentComment={item.parentComment}\n readOnly={readOnly}\n replies={replies}\n />\n )\n })}\n </CommentThreadLayout>\n </Flex>\n )\n })}\n </BoundaryElementProvider>\n </Flex>\n )}\n </Flex>","t('onboarding.header')","<Text weight=\"medium\" size={1} as=\"div\" trim={true}>\n {t('onboarding.header')}\n </Text>","t('onboarding.body')","<Text size={1} as=\"div\" trim={true}>\n {t('onboarding.body')}\n </Text>","t('onboarding.dismiss')","<Flex justifyContent=\"flex-end\" marginTop={2}>\n <Button text={t('onboarding.dismiss')} tone=\"primary\" onClick={onDismiss} />\n </Flex>","<Root padding={4}>\n <VStack gap={3}>\n <Text weight=\"medium\" size={1} as=\"div\" trim={true}>\n {t('onboarding.header')}\n </Text>\n\n <Text size={1} as=\"div\" trim={true}>\n {t('onboarding.body')}\n </Text>\n\n <Flex justifyContent=\"flex-end\" marginTop={2}>\n <Button text={t('onboarding.dismiss')} tone=\"primary\" onClick={onDismiss} />\n </Flex>\n </VStack>\n </Root>","<StyledPopover\n content={\n <Root padding={4}>\n <VStack gap={3}>\n <Text weight=\"medium\" size={1} as=\"div\" trim={true}>\n {t('onboarding.header')}\n </Text>\n\n <Text size={1} as=\"div\" trim={true}>\n {t('onboarding.body')}\n </Text>\n\n <Flex justifyContent=\"flex-end\" marginTop={2}>\n <Button text={t('onboarding.dismiss')} tone=\"primary\" onClick={onDismiss} />\n </Flex>\n </VStack>\n </Root>\n }\n open\n portal\n {...rest}\n />","<Container size={1}>\n <Box marginBottom={6}>\n <UpsellPanel\n data={data}\n onPrimaryClick={onPrimaryClick}\n onSecondaryClick={onSecondaryClick}\n />\n </Box>\n </Container>","() => {\n telemetry.log(CommentLinkCopied)\n }","useCallback(() => {\n telemetry.log(CommentLinkCopied)\n }, [telemetry])","() => {\n telemetry.log(CommentViewedFromLink)\n }","useCallback(() => {\n telemetry.log(CommentViewedFromLink)\n }, [telemetry])","(view: CommentStatus) => {\n telemetry.log(CommentListViewChanged, {view})\n }","useCallback(\n (view: CommentStatus) => {\n telemetry.log(CommentListViewChanged, {view})\n },\n [telemetry],\n )","{\n commentLinkCopied,\n commentListViewChanged,\n commentViewedFromLink,\n }","useMemo(\n (): CommentsTelemetryHookValue => ({\n commentLinkCopied,\n commentListViewChanged,\n commentViewedFromLink,\n }),\n [commentLinkCopied, commentListViewChanged, commentViewedFromLink],\n )","() => onViewChange('open')","useCallback(() => onViewChange('open'), [onViewChange])","() => onViewChange('resolved')","useCallback(() => onViewChange('resolved'), [onViewChange])","t('feature-name')","<Flex alignItems=\"center\" flexBasis=\"0%\" flexGrow={1} gap={2} paddingY={2} padding={3}>\n <Text as=\"h1\" size={1} weight=\"medium\" trim={true}>\n {t('feature-name')}\n </Text>\n </Flex>","view === 'open'\n ? t('status-filter.status-open')\n : t('status-filter.status-resolved')","<Button\n text={\n view === 'open'\n ? t('status-filter.status-open')\n : t('status-filter.status-resolved')\n }\n mode=\"bleed\"\n iconRight={ChevronDownIcon}\n />","{width: '180px'}","t('status-filter.status-open-full')","<MenuItem\n iconRight={view === 'open' ? CheckmarkIcon : undefined}\n onClick={handleSetOpenView}\n text={t('status-filter.status-open-full')}\n />","view === 'open' ? CheckmarkIcon : undefined","t('status-filter.status-resolved-full')","mode === 'upsell'\n ? {content: t('status-filter.status-resolved-full-upsell')}\n : undefined","<MenuItem\n iconRight={view === 'resolved' ? CheckmarkIcon : undefined}\n onClick={handleSetResolvedView}\n text={t('status-filter.status-resolved-full')}\n tooltipProps={\n mode === 'upsell'\n ? {content: t('status-filter.status-resolved-full-upsell')}\n : undefined\n }\n disabled={mode === 'upsell'}\n />","view === 'resolved' ? CheckmarkIcon : undefined","mode === 'upsell'","<Menu style={{width: '180px'}}>\n <MenuItem\n iconRight={view === 'open' ? CheckmarkIcon : undefined}\n onClick={handleSetOpenView}\n text={t('status-filter.status-open-full')}\n />\n <MenuItem\n iconRight={view === 'resolved' ? CheckmarkIcon : undefined}\n onClick={handleSetResolvedView}\n text={t('status-filter.status-resolved-full')}\n tooltipProps={\n mode === 'upsell'\n ? {content: t('status-filter.status-resolved-full-upsell')}\n : undefined\n }\n disabled={mode === 'upsell'}\n />\n </Menu>","{placement: 'bottom-end'}","<MenuButton\n id=\"comment-status-menu-button\"\n button={\n <Button\n text={\n view === 'open'\n ? t('status-filter.status-open')\n : t('status-filter.status-resolved')\n }\n mode=\"bleed\"\n iconRight={ChevronDownIcon}\n />\n }\n menu={\n <Menu style={{width: '180px'}}>\n <MenuItem\n iconRight={view === 'open' ? CheckmarkIcon : undefined}\n onClick={handleSetOpenView}\n text={t('status-filter.status-open-full')}\n />\n <MenuItem\n iconRight={view === 'resolved' ? CheckmarkIcon : undefined}\n onClick={handleSetResolvedView}\n text={t('status-filter.status-resolved-full')}\n tooltipProps={\n mode === 'upsell'\n ? {content: t('status-filter.status-resolved-full-upsell')}\n : undefined\n }\n disabled={mode === 'upsell'}\n />\n </Menu>\n }\n popover={{placement: 'bottom-end'}}\n />","t('close-pane-button-text-aria-label')","t('close-pane-button-text')","{content: t('close-pane-button-text')}","<Button\n aria-label={t('close-pane-button-text-aria-label')}\n icon={CloseIcon}\n mode=\"bleed\"\n onClick={onClose}\n tooltipProps={{content: t('close-pane-button-text')}}\n />","<Flex flexBasis=\"auto\" flexGrow={0} flexShrink={0} padding={1} gap={2}>\n <MenuButton\n id=\"comment-status-menu-button\"\n button={\n <Button\n text={\n view === 'open'\n ? t('status-filter.status-open')\n : t('status-filter.status-resolved')\n }\n mode=\"bleed\"\n iconRight={ChevronDownIcon}\n />\n }\n menu={\n <Menu style={{width: '180px'}}>\n <MenuItem\n iconRight={view === 'open' ? CheckmarkIcon : undefined}\n onClick={handleSetOpenView}\n text={t('status-filter.status-open-full')}\n />\n <MenuItem\n iconRight={view === 'resolved' ? CheckmarkIcon : undefined}\n onClick={handleSetResolvedView}\n text={t('status-filter.status-resolved-full')}\n tooltipProps={\n mode === 'upsell'\n ? {content: t('status-filter.status-resolved-full-upsell')}\n : undefined\n }\n disabled={mode === 'upsell'}\n />\n </Menu>\n }\n popover={{placement: 'bottom-end'}}\n />\n\n <Button\n aria-label={t('close-pane-button-text-aria-label')}\n icon={CloseIcon}\n mode=\"bleed\"\n onClick={onClose}\n tooltipProps={{content: t('close-pane-button-text')}}\n />\n </Flex>","<Flex padding={2}>\n <Flex alignItems=\"center\" flexBasis=\"0%\" flexGrow={1} gap={2} paddingY={2} padding={3}>\n <Text as=\"h1\" size={1} weight=\"medium\" trim={true}>\n {t('feature-name')}\n </Text>\n </Flex>\n\n <Flex flexBasis=\"auto\" flexGrow={0} flexShrink={0} padding={1} gap={2}>\n <MenuButton\n id=\"comment-status-menu-button\"\n button={\n <Button\n text={\n view === 'open'\n ? t('status-filter.status-open')\n : t('status-filter.status-resolved')\n }\n mode=\"bleed\"\n iconRight={ChevronDownIcon}\n />\n }\n menu={\n <Menu style={{width: '180px'}}>\n <MenuItem\n iconRight={view === 'open' ? CheckmarkIcon : undefined}\n onClick={handleSetOpenView}\n text={t('status-filter.status-open-full')}\n />\n <MenuItem\n iconRight={view === 'resolved' ? CheckmarkIcon : undefined}\n onClick={handleSetResolvedView}\n text={t('status-filter.status-resolved-full')}\n tooltipProps={\n mode === 'upsell'\n ? {content: t('status-filter.status-resolved-full-upsell')}\n : undefined\n }\n disabled={mode === 'upsell'}\n />\n </Menu>\n }\n popover={{placement: 'bottom-end'}}\n />\n\n <Button\n aria-label={t('close-pane-button-text-aria-label')}\n icon={CloseIcon}\n mode=\"bleed\"\n onClick={onClose}\n tooltipProps={{content: t('close-pane-button-text')}}\n />\n </Flex>\n </Flex>","<Root ref={ref}>\n <Flex padding={2}>\n <Flex alignItems=\"center\" flexBasis=\"0%\" flexGrow={1} gap={2} paddingY={2} padding={3}>\n <Text as=\"h1\" size={1} weight=\"medium\" trim={true}>\n {t('feature-name')}\n </Text>\n </Flex>\n\n <Flex flexBasis=\"auto\" flexGrow={0} flexShrink={0} padding={1} gap={2}>\n <MenuButton\n id=\"comment-status-menu-button\"\n button={\n <Button\n text={\n view === 'open'\n ? t('status-filter.status-open')\n : t('status-filter.status-resolved')\n }\n mode=\"bleed\"\n iconRight={ChevronDownIcon}\n />\n }\n menu={\n <Menu style={{width: '180px'}}>\n <MenuItem\n iconRight={view === 'open' ? CheckmarkIcon : undefined}\n onClick={handleSetOpenView}\n text={t('status-filter.status-open-full')}\n />\n <MenuItem\n iconRight={view === 'resolved' ? CheckmarkIcon : undefined}\n onClick={handleSetResolvedView}\n text={t('status-filter.status-resolved-full')}\n tooltipProps={\n mode === 'upsell'\n ? {content: t('status-filter.status-resolved-full-upsell')}\n : undefined\n }\n disabled={mode === 'upsell'}\n />\n </Menu>\n }\n popover={{placement: 'bottom-end'}}\n />\n\n <Button\n aria-label={t('close-pane-button-text-aria-label')}\n icon={CloseIcon}\n mode=\"bleed\"\n onClick={onClose}\n tooltipProps={{content: t('close-pane-button-text')}}\n />\n </Flex>\n </Flex>\n </Root>","<RootLayer>\n <CommentsInspectorInner {...props} mode={mode} />\n </RootLayer>","{\n boundaryElement: rootElement,\n }","(nextView: CommentStatus) => {\n setStatus(nextView)\n setSelectedPath(null)\n\n telemetry.commentListViewChanged(nextView)\n }","useCallback(\n (nextView: CommentStatus) => {\n setStatus(nextView)\n setSelectedPath(null)\n\n telemetry.commentListViewChanged(nextView)\n },\n [setSelectedPath, setStatus, telemetry],\n )","() => {\n onClose()\n setSelectedPath(null)\n }","useCallback(() => {\n onClose()\n setSelectedPath(null)\n }, [onClose, setSelectedPath])","useMemo(() => {\n if (!getCommentLink) return undefined\n\n const copyLink = (id: string) => {\n navigator.clipboard.writeText(getCommentLink(id)).catch(() => {\n pushToast({\n closable: true,\n status: 'error',\n title: t('copy-link-error-message'),\n })\n })\n\n telemetry.commentLinkCopied()\n }\n\n return copyLink\n }, [getCommentLink, pushToast, t, telemetry])","(id: string) => {\n navigator.clipboard.writeText(getCommentLink(id)).catch(() => {\n pushToast({\n closable: true,\n status: 'error',\n title: t('copy-link-error-message'),\n })\n })\n\n telemetry.commentLinkCopied()\n }","(id: string) => {\n const comment = getComment(id)\n if (!comment) return\n\n void operation.create({\n type: 'field',\n fieldPath: comment.target.path?.field || '',\n id: comment._id,\n message: comment.message,\n parentCommentId: comment.parentCommentId,\n reactions: comment.reactions || [],\n status: comment.status,\n threadId: comment.threadId,\n })\n }","id","useCallback(\n (id: string) => {\n const comment = getComment(id)\n if (!comment) return\n\n void operation.create({\n type: 'field',\n fieldPath: comment.target.path?.field || '',\n id: comment._id,\n message: comment.message,\n parentCommentId: comment.parentCommentId,\n reactions: comment.reactions || [],\n status: comment.status,\n threadId: comment.threadId,\n })\n },\n [getComment, operation],\n )","() => {\n if (deleteLoading) return\n setShowDeleteDialog(false)\n setCommentToDelete(null)\n }","useCallback(() => {\n if (deleteLoading) return\n setShowDeleteDialog(false)\n setCommentToDelete(null)\n }, [deleteLoading])","(nextPath: CommentsSelectedPath) => {\n setSelectedPath(nextPath)\n\n if (nextPath?.fieldPath) {\n const path = PathUtils.fromString(nextPath.fieldPath)\n onPathOpen?.(path)\n\n scrollToField(nextPath.fieldPath)\n\n const isInlineComment = comments.data.open\n .filter((c) => c.threadId === nextPath?.threadId)\n .some((x) => isTextSelectionComment(x.parentComment))\n\n if (isInlineComment && nextPath.threadId) {\n scrollToInlineComment(nextPath.threadId)\n }\n }\n }","open","(x) => isTextSelectionComment(x.parentComment)","useCallback(\n (nextPath: CommentsSelectedPath) => {\n setSelectedPath(nextPath)\n\n if (nextPath?.fieldPath) {\n const path = PathUtils.fromString(nextPath.fieldPath)\n onPathOpen?.(path)\n\n scrollToField(nextPath.fieldPath)\n\n const isInlineComment = comments.data.open\n .filter((c) => c.threadId === nextPath?.threadId)\n .some((x) => isTextSelectionComment(x.parentComment))\n\n if (isInlineComment && nextPath.threadId) {\n scrollToInlineComment(nextPath.threadId)\n }\n }\n },\n [comments.data.open, onPathOpen, scrollToField, scrollToInlineComment, setSelectedPath],\n )","(nextComment: CommentBaseCreatePayload) => {\n const fieldPath = nextComment?.payload?.fieldPath || ''\n\n void operation.create({\n type: 'field',\n fieldPath,\n message: nextComment.message,\n parentCommentId: nextComment.parentCommentId,\n reactions: nextComment.reactions,\n status: nextComment.status,\n threadId: nextComment.threadId,\n })\n\n setSelectedPath({\n fieldPath,\n origin: 'inspector',\n threadId: nextComment.threadId,\n })\n }","useCallback(\n (nextComment: CommentBaseCreatePayload) => {\n const fieldPath = nextComment?.payload?.fieldPath || ''\n\n void operation.create({\n type: 'field',\n fieldPath,\n message: nextComment.message,\n parentCommentId: nextComment.parentCommentId,\n reactions: nextComment.reactions,\n status: nextComment.status,\n threadId: nextComment.threadId,\n })\n\n setSelectedPath({\n fieldPath,\n origin: 'inspector',\n threadId: nextComment.threadId,\n })\n },\n [operation, setSelectedPath],\n )","(nextComment: CommentBaseCreatePayload) => {\n void operation.create({\n ...nextComment,\n type: 'field',\n fieldPath: nextComment?.payload?.fieldPath || '',\n })\n }","nextComment","useCallback(\n (nextComment: CommentBaseCreatePayload) => {\n void operation.create({\n ...nextComment,\n type: 'field',\n fieldPath: nextComment?.payload?.fieldPath || '',\n })\n },\n [operation],\n )","(id: string, nextComment: CommentUpdatePayload) => {\n void operation.update(id, nextComment)\n }","useCallback(\n (id: string, nextComment: CommentUpdatePayload) => {\n void operation.update(id, nextComment)\n },\n [operation],\n )","(id: string) => {\n const parent = currentComments.find((c) => c.parentComment?._id === id)\n const isParent = Boolean(parent && parent?.replies?.length > 0)\n\n setShowDeleteDialog(true)\n setCommentToDelete({\n commentId: id,\n isParent,\n })\n }","c","useCallback(\n (id: string) => {\n const parent = currentComments.find((c) => c.parentComment?._id === id)\n const isParent = Boolean(parent && parent?.replies?.length > 0)\n\n setShowDeleteDialog(true)\n setCommentToDelete({\n commentId: id,\n isParent,\n })\n },\n\n [currentComments],\n )","async (id: string) => {\n try {\n setDeleteLoading(true)\n await operation.remove(id)\n closeDeleteDialog()\n } catch (err) {\n setDeleteError(err)\n }\n setDeleteLoading(false)\n }","err","useCallback(\n async (id: string) => {\n try {\n setDeleteLoading(true)\n await operation.remove(id)\n closeDeleteDialog()\n } catch (err) {\n setDeleteError(err)\n }\n setDeleteLoading(false)\n },\n [closeDeleteDialog, operation],\n )","(id: string, nextStatus: CommentStatus) => {\n void operation.update(id, {\n status: nextStatus,\n })\n\n // If the comment is being opened, we want to change to the \"open\" view\n // and scroll to the comment\n if (nextStatus === 'open') {\n setStatus('open')\n\n const comment = getComment(id)\n\n if (!comment) return\n\n setSelectedPath({\n fieldPath: comment.target.path?.field || null,\n origin: 'inspector',\n threadId: comment.threadId || null,\n })\n\n scrollToComment(id)\n }\n }","comment","useCallback(\n (id: string, nextStatus: CommentStatus) => {\n void operation.update(id, {\n status: nextStatus,\n })\n\n // If the comment is being opened, we want to change to the \"open\" view\n // and scroll to the comment\n if (nextStatus === 'open') {\n setStatus('open')\n\n const comment = getComment(id)\n\n if (!comment) return\n\n setSelectedPath({\n fieldPath: comment.target.path?.field || null,\n origin: 'inspector',\n threadId: comment.threadId || null,\n })\n\n scrollToComment(id)\n }\n },\n [getComment, operation, scrollToComment, setSelectedPath, setStatus],\n )","(id: string, reaction: CommentReactionOption) => {\n void operation.react(id, reaction)\n }","useCallback(\n (id: string, reaction: CommentReactionOption) => {\n void operation.react(id, reaction)\n },\n [operation],\n )","() => {\n // Clear the selected path when:\n // - Clicking outside the inspector when it's the top layer\n // - The target is not a slate editor string. This is needed because we do not want to\n // frequently deselect the selected path when clicking inside the editor.\n if (selectedPath && isTopLayer) {\n setSelectedPath(null)\n }\n }","useCallback(() => {\n // Clear the selected path when:\n // - Clicking outside the inspector when it's the top layer\n // - The target is not a slate editor string. This is needed because we do not want to\n // frequently deselect the selected path when clicking inside the editor.\n if (selectedPath && isTopLayer) {\n setSelectedPath(null)\n }\n }, [isTopLayer, selectedPath, setSelectedPath])","(element: HTMLDivElement | null) => {\n rootRef.current = element\n setRootElement(element)\n }","useCallback((element: HTMLDivElement | null) => {\n rootRef.current = element\n setRootElement(element)\n }, [])","(event) => {\n // Clear the selected path when clicking outside the comments inspector.\n // We do this only when the comments inspector is the top layer.\n const isPTETarget =\n event.target instanceof HTMLElement && event.target?.hasAttribute('data-pt-text')\n\n if (!isPTETarget) {\n handleDeselectPath()\n }\n }","() => [rootRef.current]","() => {\n if (loggedTelemetry || mode !== 'upsell') return undefined\n // oxlint-disable-next-line react/set-state-in-effect -- pre-existing violation, to be fixed in a follow-up\n setLoggedTelemetry(true)\n if (selectedPath?.origin === 'form') {\n upsellTelemetryLogs.panelViewed('field_action')\n } else if (commentIdParamRef.current) {\n upsellTelemetryLogs.panelViewed('link')\n } else {\n upsellTelemetryLogs.panelViewed('document_action')\n }\n return () => {\n upsellTelemetryLogs.panelDismissed()\n }\n }","origin","[loggedTelemetry, mode, selectedPath?.origin, upsellTelemetryLogs]","selectedPath?.origin","() => {\n // Make sure that the comment exists before we try to scroll to it.\n // We can't solely rely on the comment id from the url since the comment might not be loaded yet.\n const commentToScrollTo = getComment(commentIdParamRef.current || '')\n\n if (!loading && commentToScrollTo && !didScrollToCommentFromParam.current) {\n // Make sure we have the correct status set before we scroll to the comment\n setStatus(commentToScrollTo.status || 'open')\n\n handlePathSelect({\n fieldPath: commentToScrollTo.target.path?.field || null,\n origin: 'url',\n threadId: commentToScrollTo.threadId || null,\n })\n\n // Defer the comment scroll to prevent React batching from overwriting the field scroll\n requestAnimationFrame(() => {\n scrollToComment(commentToScrollTo._id)\n })\n\n didScrollToCommentFromParam.current = true\n commentIdParamRef.current = undefined\n\n onClearSelectedComment?.()\n\n telemetry.commentViewedFromLink()\n }\n }","[\n getComment,\n handlePathSelect,\n loading,\n onClearSelectedComment,\n scrollToComment,\n setStatus,\n telemetry,\n ]","useMemo(() => {\n if (mode === 'upsell' && upsellData) {\n return (\n <CommentsUpsellPanel\n data={upsellData}\n onPrimaryClick={upsellTelemetryLogs.panelPrimaryClicked}\n onSecondaryClick={upsellTelemetryLogs.panelSecondaryClicked}\n />\n )\n }\n\n return null\n }, [\n mode,\n upsellTelemetryLogs.panelPrimaryClicked,\n upsellTelemetryLogs.panelSecondaryClicked,\n upsellData,\n ])","<CommentsUpsellPanel\n data={upsellData}\n onPrimaryClick={upsellTelemetryLogs.panelPrimaryClicked}\n onSecondaryClick={upsellTelemetryLogs.panelSecondaryClicked}\n />","panelPrimaryClicked","panelSecondaryClicked","commentToDelete && showDeleteDialog && (\n <CommentDeleteDialog\n {...commentToDelete}\n error={deleteError}\n loading={deleteLoading}\n onClose={closeDeleteDialog}\n onConfirm={handleDeleteConfirm}\n />\n )","<CommentsInspectorHeader\n onClose={handleCloseInspector}\n onViewChange={handleChangeView}\n view={status}\n mode={mode}\n />","<CommentsOnboardingPopover\n onDismiss={setDismissed}\n open={!isDismissed}\n placement=\"left-start\"\n >\n <CommentsInspectorHeader\n onClose={handleCloseInspector}\n onViewChange={handleChangeView}\n view={status}\n mode={mode}\n />\n </CommentsOnboardingPopover>","!isDismissed","currentUser && (\n <CommentsList\n beforeListNode={beforeListNode}\n comments={currentComments}\n currentUser={currentUser}\n error={comments.error}\n loading={loading}\n mentionOptions={mentionOptions}\n mode={mode}\n onCopyLink={handleCopyLink}\n onCreateRetry={handleCreateRetry}\n onDelete={onDeleteStart}\n onEdit={handleEdit}\n onNewThreadCreate={handleNewThreadCreate}\n onPathSelect={handlePathSelect}\n onReactionSelect={handleReactionSelect}\n onReply={handleReply}\n onStatusChange={handleStatusChange}\n readOnly={readOnly}\n selectedPath={selectedPath}\n status={status}\n />\n )","error","<Flex\n flexDirection=\"column\"\n flexBasis=\"0%\"\n flexGrow={1}\n height=\"100%\"\n onClick={handleDeselectPath}\n overflow=\"hidden\"\n ref={setRootRef}\n >\n <CommentsOnboardingPopover\n onDismiss={setDismissed}\n open={!isDismissed}\n placement=\"left-start\"\n >\n <CommentsInspectorHeader\n onClose={handleCloseInspector}\n onViewChange={handleChangeView}\n view={status}\n mode={mode}\n />\n </CommentsOnboardingPopover>\n {currentUser && (\n <CommentsList\n beforeListNode={beforeListNode}\n comments={currentComments}\n currentUser={currentUser}\n error={comments.error}\n loading={loading}\n mentionOptions={mentionOptions}\n mode={mode}\n onCopyLink={handleCopyLink}\n onCreateRetry={handleCreateRetry}\n onDelete={onDeleteStart}\n onEdit={handleEdit}\n onNewThreadCreate={handleNewThreadCreate}\n onPathSelect={handlePathSelect}\n onReactionSelect={handleReactionSelect}\n onReply={handleReply}\n onStatusChange={handleStatusChange}\n readOnly={readOnly}\n selectedPath={selectedPath}\n status={status}\n />\n )}\n </Flex>","<Fragment>\n {commentToDelete && showDeleteDialog && (\n <CommentDeleteDialog\n {...commentToDelete}\n error={deleteError}\n loading={deleteLoading}\n onClose={closeDeleteDialog}\n onConfirm={handleDeleteConfirm}\n />\n )}\n\n <Flex\n flexDirection=\"column\"\n flexBasis=\"0%\"\n flexGrow={1}\n height=\"100%\"\n onClick={handleDeselectPath}\n overflow=\"hidden\"\n ref={setRootRef}\n >\n <CommentsOnboardingPopover\n onDismiss={setDismissed}\n open={!isDismissed}\n placement=\"left-start\"\n >\n <CommentsInspectorHeader\n onClose={handleCloseInspector}\n onViewChange={handleChangeView}\n view={status}\n mode={mode}\n />\n </CommentsOnboardingPopover>\n {currentUser && (\n <CommentsList\n beforeListNode={beforeListNode}\n comments={currentComments}\n currentUser={currentUser}\n error={comments.error}\n loading={loading}\n mentionOptions={mentionOptions}\n mode={mode}\n onCopyLink={handleCopyLink}\n onCreateRetry={handleCreateRetry}\n onDelete={onDeleteStart}\n onEdit={handleEdit}\n onNewThreadCreate={handleNewThreadCreate}\n onPathSelect={handlePathSelect}\n onReactionSelect={handleReactionSelect}\n onReply={handleReply}\n onStatusChange={handleStatusChange}\n readOnly={readOnly}\n selectedPath={selectedPath}\n status={status}\n />\n )}\n </Flex>\n </Fragment>"],"sources":["../src/core/comments-v2/components/list/CommentsListStatus.tsx","../src/core/comments-v2/components/CommentBreadcrumbs.tsx","../src/core/comments-v2/components/list/CreateNewThreadInput.tsx","../src/core/comments-v2/components/list/CommentThreadLayout.tsx","../src/core/comments-v2/components/list/CommentsList.tsx","../src/core/comments-v2/components/onboarding/CommentsOnboardingPopover.tsx","../src/core/comments-v2/components/upsell/CommentsUpsellPanel.tsx","../src/core/comments-v2/hooks/useCommentsOnboarding.ts","../src/core/comments-v2/__telemetry__/comments.telemetry.ts","../src/core/comments-v2/hooks/useCommentsTelemetry.ts","../src/core/comments-v2/plugin/inspector/CommentsInspectorHeader.tsx","../src/core/comments-v2/plugin/inspector/CommentsInspector.tsx"],"sourcesContent":["import {Text, Container, Flex, VStack} from 'ui5'\n\nimport {LoadingBlock} from '../../../components/loadingBlock/LoadingBlock'\nimport {useTranslation} from '../../../i18n/hooks/useTranslation'\nimport {type TFunction} from '../../../i18n/types'\nimport {commentsLocaleNamespace} from '../../i18n'\nimport {type CommentStatus} from '../../types'\n\ninterface EmptyStateMessage {\n title: string\n message: React.ReactNode\n}\n\nfunction getEmptyStateMessages(t: TFunction): Record<CommentStatus, EmptyStateMessage> {\n return {\n open: {\n title: t('list-status.empty-state-open-title'),\n message: t('list-status.empty-state-open-text'),\n },\n resolved: {\n title: t('list-status.empty-state-resolved-title'),\n message: t('list-status.empty-state-resolved-text'),\n },\n }\n}\n\ninterface CommentsListStatusProps {\n error: Error | null\n hasNoComments: boolean\n loading: boolean\n status: CommentStatus\n}\n\nexport function CommentsListStatus(props: CommentsListStatusProps) {\n const {status, error, loading, hasNoComments} = props\n const {t} = useTranslation(commentsLocaleNamespace)\n const emptyStateMessages = getEmptyStateMessages(t)\n\n if (error) {\n return (\n <Flex alignItems=\"center\" justifyContent=\"center\" flexBasis=\"0%\" flexGrow={1} padding={4}>\n <Flex alignItems=\"center\">\n <Text size={1} muted as=\"div\" trim={true}>\n {t('list-status.error')}\n </Text>\n </Flex>\n </Flex>\n )\n }\n\n if (loading) {\n return <LoadingBlock showText title={t('list-status.loading')} />\n }\n\n if (hasNoComments) {\n return (\n <Flex alignItems=\"center\" justifyContent=\"center\" flexBasis=\"0%\" flexGrow={1}>\n <Container size={0} padding={4}>\n <VStack gap={3}>\n <Text align=\"center\" size={1} muted weight=\"medium\" as=\"div\" trim={true}>\n {emptyStateMessages[status].title}\n </Text>\n\n <Text align=\"center\" size={1} muted as=\"div\" trim={true}>\n {emptyStateMessages[status].message}\n </Text>\n </VStack>\n </Container>\n </Flex>\n )\n }\n\n return null\n}\n","import {ChevronRightIcon} from '@sanity/icons/ChevronRight'\nimport {Fragment, useMemo} from 'react'\nimport {Text, Box, Flex, Icon} from 'ui5'\n\nimport {Tooltip} from '../../../ui-components/tooltip/Tooltip'\n\nexport interface CommentBreadcrumbsProps {\n titlePath: string[]\n maxLength: number\n}\n\ntype Item = string | string[]\n\nconst separator = <Icon muted icon={ChevronRightIcon} style={{margin: '-0.4375rem'}} />\n\nconst renderItem = (item: string, index: number) => {\n return (\n <Box key={`${item}-${index}`} as=\"li\">\n <Text truncate={1} size={1} weight=\"medium\" as=\"div\" trim={true}>\n {item}\n </Text>\n </Box>\n )\n}\n\nexport function CommentBreadcrumbs(props: CommentBreadcrumbsProps) {\n const {titlePath, maxLength} = props\n\n const items: Item[] = useMemo(() => {\n const len = titlePath.length\n const beforeLength = Math.ceil(maxLength / 2)\n const afterLength = Math.floor(maxLength / 2)\n\n if (maxLength && len > maxLength) {\n return [\n ...titlePath.slice(0, beforeLength - 1),\n titlePath.slice(beforeLength - 1, len - afterLength),\n ...titlePath.slice(len - afterLength),\n ]\n }\n\n return titlePath\n }, [maxLength, titlePath])\n\n const nodes = useMemo(() => {\n return items.map((item, index) => {\n const key = `${item}-${index}`\n const showSeparator = index < items.length - 1\n\n if (Array.isArray(item)) {\n return (\n <Fragment key={key}>\n <Tooltip\n content={\n <Flex gap={2} padding={2} flexDirection=\"column\">\n {item.map(renderItem)}\n </Flex>\n }\n >\n <Box>{renderItem('...', index)}</Box>\n </Tooltip>\n\n {showSeparator && separator}\n </Fragment>\n )\n }\n\n return (\n <Fragment key={key}>\n {renderItem(item, index)}\n\n {showSeparator && separator}\n </Fragment>\n )\n })\n }, [items])\n\n return (\n <Flex alignItems=\"center\" as=\"ol\" gap={2}>\n {nodes}\n </Flex>\n )\n}\n","import {type CurrentUser, type PortableTextBlock} from '@sanity/types'\nimport {useCallback, useMemo, useRef, useState} from 'react'\n\nimport {type UserListWithPermissionsHookValue} from '../../../hooks/useUserListWithPermissions'\nimport {useTranslation} from '../../../i18n/hooks/useTranslation'\nimport {Translate} from '../../../i18n/Translate'\nimport {hasCommentMessageValue} from '../../helpers'\nimport {commentsLocaleNamespace} from '../../i18n'\nimport {type CommentMessage, type CommentsUIMode} from '../../types'\nimport {\n CommentInput,\n type CommentInputHandle,\n type CommentInputProps,\n} from '../pte/comment-input/CommentInput'\n\nconst EMPTY_PT_ARRAY: PortableTextBlock[] = []\n\ninterface CreateNewThreadInputProps {\n currentUser: CurrentUser\n fieldTitle: string\n mentionOptions: UserListWithPermissionsHookValue\n mode: CommentsUIMode\n onBlur?: CommentInputProps['onBlur']\n onFocus?: CommentInputProps['onFocus']\n onKeyDown?: (event: React.KeyboardEvent) => void\n onNewThreadCreate: (payload: CommentMessage) => void\n readOnly?: boolean\n}\n\nexport function CreateNewThreadInput(props: CreateNewThreadInputProps) {\n const {\n currentUser,\n fieldTitle,\n mentionOptions,\n mode,\n onBlur,\n onFocus,\n onKeyDown,\n onNewThreadCreate,\n readOnly,\n } = props\n const {t} = useTranslation(commentsLocaleNamespace)\n\n const [value, setValue] = useState<CommentMessage>(EMPTY_PT_ARRAY)\n const commentInputHandle = useRef<CommentInputHandle | null>(null)\n\n const handleSubmit = useCallback(\n (nextValue: CommentMessage) => {\n onNewThreadCreate?.(nextValue)\n setValue(EMPTY_PT_ARRAY)\n },\n [onNewThreadCreate],\n )\n\n const hasValue = useMemo(() => hasCommentMessageValue(value), [value])\n\n const startDiscard = useCallback(() => {\n if (!hasValue) {\n return\n }\n commentInputHandle.current?.discardDialogController.open()\n }, [hasValue])\n\n const handleInputKeyDown = useCallback(\n (event: React.KeyboardEvent) => {\n // Don't act if the input already prevented this event\n if (event.isDefaultPrevented()) {\n return\n }\n // Discard the input text\n if (event.key === 'Escape') {\n event.preventDefault()\n event.stopPropagation()\n startDiscard()\n }\n // Call parent handler\n if (onKeyDown) onKeyDown(event)\n },\n [onKeyDown, startDiscard],\n )\n\n const confirmDiscard = useCallback(() => {\n setValue(EMPTY_PT_ARRAY)\n commentInputHandle.current?.discardDialogController.close()\n commentInputHandle.current?.focus()\n }, [])\n\n const cancelDiscard = useCallback(() => {\n commentInputHandle.current?.discardDialogController.close()\n }, [])\n\n const placeholder =\n mode === 'upsell' ? (\n t('compose.add-comment-input-placeholder-upsell')\n ) : (\n <Translate\n t={t}\n i18nKey=\"compose.add-comment-input-placeholder\"\n values={{field: fieldTitle}}\n />\n )\n\n return (\n <CommentInput\n currentUser={currentUser}\n expandOnFocus\n mentionOptions={mentionOptions}\n onBlur={onBlur}\n onChange={setValue}\n onDiscardCancel={cancelDiscard}\n onDiscardConfirm={confirmDiscard}\n onKeyDown={handleInputKeyDown}\n onFocus={onFocus}\n onSubmit={handleSubmit}\n placeholder={placeholder}\n readOnly={readOnly || mode === 'upsell'}\n ref={commentInputHandle}\n value={value}\n />\n )\n}\n","import {type CurrentUser} from '@sanity/types'\nimport {\n // oxlint-disable-next-line no-restricted-imports\n Button, // Button with specific styling and children behavior.\n} from '@sanity/ui'\nimport {uuid} from '@sanity/uuid'\nimport {type MouseEvent, type ReactNode, useCallback, useMemo} from 'react'\nimport {css, styled} from 'styled-components'\nimport {Flex, VStack} from 'ui5'\n\nimport {type UserListWithPermissionsHookValue} from '../../../hooks/useUserListWithPermissions'\nimport {useTranslation} from '../../../i18n/hooks/useTranslation'\nimport {type CommentsSelectedPath} from '../../context/selected-path/types'\nimport {commentsLocaleNamespace} from '../../i18n'\nimport {\n type CommentBaseCreatePayload,\n type CommentListBreadcrumbs,\n type CommentMessage,\n type CommentsUIMode,\n} from '../../types'\nimport {CommentBreadcrumbs} from '../CommentBreadcrumbs'\nimport {CreateNewThreadInput} from './CreateNewThreadInput'\nimport {ThreadCard} from './styles'\n\nconst HeaderFlex = styled(Flex)`\n min-height: 25px;\n`\n\nconst BreadcrumbsButton = styled(Button)(({theme}) => {\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n const fg = theme.sanity.color.base.fg\n return css`\n --card-fg-color: ${fg};\n\n // The width is needed to make the text ellipsis work\n // in the breadcrumbs component\n max-width: 100%;\n `\n})\n\ninterface CommentThreadLayoutProps {\n breadcrumbs?: CommentListBreadcrumbs\n canCreateNewThread: boolean\n children: ReactNode\n currentUser: CurrentUser\n fieldPath: string\n isSelected: boolean\n mentionOptions: UserListWithPermissionsHookValue\n mode: CommentsUIMode\n onNewThreadCreate: (payload: CommentBaseCreatePayload) => void\n onPathSelect?: (nextPath: CommentsSelectedPath) => void\n readOnly?: boolean\n}\n\nexport function CommentThreadLayout(props: CommentThreadLayoutProps) {\n const {\n breadcrumbs,\n canCreateNewThread,\n children,\n currentUser,\n fieldPath,\n isSelected,\n mentionOptions,\n mode,\n onNewThreadCreate,\n onPathSelect,\n readOnly,\n } = props\n\n const {t} = useTranslation(commentsLocaleNamespace)\n\n const handleNewThreadCreate = useCallback(\n (payload: CommentMessage) => {\n const nextComment: CommentBaseCreatePayload = {\n message: payload,\n parentCommentId: undefined,\n status: 'open',\n // Since this is a new comment, we generate a new thread ID\n threadId: uuid(),\n // New comments have no reactions\n reactions: [],\n\n payload: {\n fieldPath,\n },\n }\n\n onNewThreadCreate?.(nextComment)\n },\n [onNewThreadCreate, fieldPath],\n )\n\n const handleBreadcrumbsClick = useCallback(\n (e: MouseEvent<HTMLButtonElement>) => {\n e.stopPropagation()\n\n onPathSelect?.({\n fieldPath,\n origin: 'inspector',\n threadId: null,\n })\n },\n [fieldPath, onPathSelect],\n )\n\n const handleNewThreadClick = useCallback(\n (e: MouseEvent<HTMLDivElement>) => {\n e.stopPropagation()\n // Skip if the click was triggered from \"Enter\" keydown.\n // This because we don't want to trigger `onPathSelect` when\n // submitting the new thread form.\n if (e.detail === 0) return\n\n onPathSelect?.({\n fieldPath,\n origin: 'inspector',\n threadId: null,\n })\n },\n [fieldPath, onPathSelect],\n )\n\n const crumbsTitlePath = useMemo(() => breadcrumbs?.map((p) => p.title) || [], [breadcrumbs])\n const lastCrumb = crumbsTitlePath[crumbsTitlePath.length - 1]\n\n return (\n <VStack gap={2}>\n <HeaderFlex alignItems=\"center\" gap={2} paddingRight={1}>\n <Flex flexBasis=\"0%\" flexGrow={1} flexDirection=\"column\">\n <Flex alignItems=\"center\">\n <BreadcrumbsButton\n aria-label={t('list-item.breadcrumb-button-go-to-field-aria-label', {\n field: lastCrumb,\n })}\n mode=\"bleed\"\n onClick={handleBreadcrumbsClick}\n padding={2}\n gap={2}\n >\n <CommentBreadcrumbs maxLength={3} titlePath={crumbsTitlePath} />\n </BreadcrumbsButton>\n </Flex>\n </Flex>\n </HeaderFlex>\n\n {canCreateNewThread && (\n <ThreadCard onClick={handleNewThreadClick} data-active={isSelected}>\n <CreateNewThreadInput\n currentUser={currentUser}\n fieldTitle={lastCrumb}\n mentionOptions={mentionOptions}\n mode={mode}\n onNewThreadCreate={handleNewThreadCreate}\n readOnly={readOnly}\n />\n </ThreadCard>\n )}\n\n <VStack gap={2}>{children}</VStack>\n </VStack>\n )\n}\n","import {type CurrentUser} from '@sanity/types'\nimport {BoundaryElementProvider} from '@sanity/ui'\nimport {memo, useMemo, useState, type RefAttributes} from 'react'\nimport {Flex} from 'ui5'\n\nimport {type UserListWithPermissionsHookValue} from '../../../hooks/useUserListWithPermissions'\nimport {type CommentsSelectedPath} from '../../context/selected-path/types'\nimport {applyCommentsGroupAttr} from '../../hooks/useCommentsScroll'\nimport {\n type CommentBaseCreatePayload,\n type CommentReactionOption,\n type CommentStatus,\n type CommentsUIMode,\n type CommentThreadItem,\n type CommentUpdatePayload,\n} from '../../types'\nimport {CommentsListItem} from './CommentsListItem'\nimport {CommentsListStatus} from './CommentsListStatus'\nimport {CommentThreadLayout} from './CommentThreadLayout'\n\ninterface GroupedComments {\n [field: string]: CommentThreadItem[]\n}\n\nfunction groupThreads(comments: CommentThreadItem[]) {\n return comments.reduce((acc, comment) => {\n const field = comment.fieldPath\n\n if (!acc[field]) {\n acc[field] = []\n }\n\n acc[field].push(comment)\n\n return acc\n }, {} as GroupedComments)\n}\n\n/**\n * @beta\n * @hidden\n */\nexport interface CommentsListProps {\n beforeListNode?: React.ReactNode\n comments: CommentThreadItem[]\n currentUser: CurrentUser\n error: Error | null\n loading: boolean\n mentionOptions: UserListWithPermissionsHookValue\n mode: CommentsUIMode\n onCopyLink?: (id: string) => void\n onCreateRetry: (id: string) => void\n onDelete: (id: string) => void\n onEdit: (id: string, payload: CommentUpdatePayload) => void\n onNewThreadCreate: (payload: CommentBaseCreatePayload) => void\n /**\n * @internal\n */\n onPathSelect?: (nextPath: CommentsSelectedPath) => void\n onReactionSelect?: (id: string, reaction: CommentReactionOption) => void\n onReply: (payload: CommentBaseCreatePayload) => void\n onStatusChange?: (id: string, status: CommentStatus) => void\n readOnly?: boolean\n /**\n * @internal\n */\n selectedPath: CommentsSelectedPath | null\n status: CommentStatus\n}\n\n/**\n * @beta\n * @hidden\n */\nexport interface CommentsListHandle {\n scrollToComment: (id: string) => void\n}\n\nfunction CommentsListInner(props: CommentsListProps & RefAttributes<HTMLUListElement>) {\n const {\n ref,\n beforeListNode,\n comments,\n currentUser,\n error,\n loading,\n mentionOptions,\n mode,\n onCopyLink,\n onCreateRetry,\n onDelete,\n onEdit,\n onNewThreadCreate,\n onPathSelect,\n onReactionSelect,\n onReply,\n onStatusChange,\n readOnly,\n selectedPath,\n status,\n } = props\n const [boundaryElement, setBoundaryElement] = useState<HTMLDivElement | null>(null)\n\n const groupedThreads = useMemo(() => Object.entries(groupThreads(comments)), [comments])\n\n const showComments = !loading && !error && groupedThreads.length > 0\n\n return (\n <Flex\n data-testid=\"comments-list\"\n flexDirection=\"column\"\n flexBasis=\"0%\"\n flexGrow={1}\n height=\"100%\"\n overflow=\"hidden\"\n ref={setBoundaryElement}\n >\n {mode !== 'upsell' && (\n <CommentsListStatus\n error={error}\n hasNoComments={groupedThreads.length === 0}\n loading={loading}\n status={status}\n />\n )}\n\n {(showComments || beforeListNode) && (\n <Flex\n as=\"ul\"\n flexBasis=\"0%\"\n flexGrow={1}\n overflow=\"auto\"\n padding={3}\n paddingTop={1}\n paddingBottom={6}\n gap={1}\n ref={ref}\n flexDirection=\"column\"\n >\n {beforeListNode}\n\n <BoundaryElementProvider element={boundaryElement}>\n {groupedThreads?.map(([fieldPath, group]) => {\n // Since all threads in the group point to the same field, the breadcrumbs will be\n // the same for all of them. Therefore, we can just pick the first one.\n const breadcrumbs = group[0].breadcrumbs\n\n // The thread ID is used to scroll to the thread.\n // We pick the first thread id in the group so that we scroll to the first thread\n // in the group.\n const firstThreadId = group[0].threadId\n\n // The new thread is selected if the field path matches the selected path and\n // there is no thread ID selected.\n const newThreadSelected =\n selectedPath?.fieldPath === fieldPath && !selectedPath.threadId\n\n return (\n <Flex\n key={fieldPath}\n as=\"li\"\n paddingTop={3}\n {...applyCommentsGroupAttr(firstThreadId)}\n flexDirection=\"column\"\n flexShrink={0}\n >\n <CommentThreadLayout\n key={fieldPath}\n breadcrumbs={breadcrumbs}\n canCreateNewThread={status === 'open'}\n currentUser={currentUser}\n fieldPath={fieldPath}\n isSelected={newThreadSelected}\n mentionOptions={mentionOptions}\n mode={mode}\n onNewThreadCreate={onNewThreadCreate}\n onPathSelect={onPathSelect}\n readOnly={readOnly}\n >\n {group.map((item) => {\n // The default sort order is by date, descending (newest first).\n // However, inside a thread, we want the order to be ascending (oldest first).\n // So we reverse the array here.\n // We use slice() to avoid mutating the original array.\n const replies = item.replies.slice().reverse()\n\n const canReply =\n status === 'open' &&\n item.parentComment._state?.type !== 'createError' &&\n item.parentComment._state?.type !== 'createRetrying'\n\n // The thread is selected if the thread ID and field path matches the\n // selected path.\n const threadIsSelected =\n selectedPath?.threadId === item.parentComment.threadId &&\n selectedPath?.fieldPath === item.parentComment.target.path?.field\n\n return (\n <CommentsListItem\n key={item.parentComment._id}\n canReply={canReply}\n currentUser={currentUser}\n hasReferencedValue={item.hasReferencedValue}\n isSelected={threadIsSelected}\n mentionOptions={mentionOptions}\n mode={mode}\n onCopyLink={onCopyLink}\n onCreateRetry={onCreateRetry}\n onDelete={onDelete}\n onEdit={onEdit}\n onPathSelect={onPathSelect}\n onReactionSelect={onReactionSelect}\n onReply={onReply}\n onStatusChange={onStatusChange}\n parentComment={item.parentComment}\n readOnly={readOnly}\n replies={replies}\n />\n )\n })}\n </CommentThreadLayout>\n </Flex>\n )\n })}\n </BoundaryElementProvider>\n </Flex>\n )}\n </Flex>\n )\n}\n\n/**\n * @beta\n * @hidden\n */\nexport const CommentsList = memo(CommentsListInner)\n","import {keyframes, styled} from 'styled-components'\nimport {Text, Box, Flex, VStack} from 'ui5'\n\nimport {Button} from '../../../../ui-components/button/Button'\nimport {Popover, type PopoverProps} from '../../../../ui-components/popover/Popover'\nimport {useTranslation} from '../../../i18n/hooks/useTranslation'\nimport {commentsLocaleNamespace} from '../../i18n'\n\nconst Root = styled(Box)`\n max-width: 280px;\n`\n\nconst fadeInKeyFrame = keyframes`\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n`\n\nconst StyledPopover = styled(Popover)`\n opacity: 0;\n // Fade in the popover after 500ms\n animation: ${fadeInKeyFrame} 200ms 500ms forwards;\n`\n\ninterface CommentsOnboardingPopoverProps extends Omit<PopoverProps, 'content'> {\n // ...\n onDismiss: () => void\n}\n\nexport function CommentsOnboardingPopover(props: CommentsOnboardingPopoverProps) {\n const {onDismiss, ...rest} = props\n const {t} = useTranslation(commentsLocaleNamespace)\n\n return (\n <StyledPopover\n content={\n <Root padding={4}>\n <VStack gap={3}>\n <Text weight=\"medium\" size={1} as=\"div\" trim={true}>\n {t('onboarding.header')}\n </Text>\n\n <Text size={1} as=\"div\" trim={true}>\n {t('onboarding.body')}\n </Text>\n\n <Flex justifyContent=\"flex-end\" marginTop={2}>\n <Button text={t('onboarding.dismiss')} tone=\"primary\" onClick={onDismiss} />\n </Flex>\n </VStack>\n </Root>\n }\n open\n portal\n {...rest}\n />\n )\n}\n","import {Container, Box} from 'ui5'\n\nimport {type UpsellData} from '../../../studio/upsell/types'\nimport {UpsellPanel} from '../../../studio/upsell/UpsellPanel'\n\ninterface CommentsUpsellPanelProps {\n data: UpsellData\n onPrimaryClick: () => void\n onSecondaryClick: () => void\n}\n\nexport function CommentsUpsellPanel(props: CommentsUpsellPanelProps) {\n const {data, onPrimaryClick, onSecondaryClick} = props\n return (\n <Container size={1}>\n <Box marginBottom={6}>\n <UpsellPanel\n data={data}\n onPrimaryClick={onPrimaryClick}\n onSecondaryClick={onSecondaryClick}\n />\n </Box>\n </Container>\n )\n}\n","import {useContext} from 'react'\nimport {CommentsOnboardingContextV2} from 'sanity/_singletons'\n\nimport {type CommentsOnboardingContextValue} from '../context/onboarding/types'\n\nexport function useCommentsOnboarding(): CommentsOnboardingContextValue {\n const ctx = useContext(CommentsOnboardingContextV2)\n\n if (!ctx) {\n throw new Error('useCommentsOnboarding: missing context value')\n }\n\n return ctx\n}\n","import {defineEvent} from '@sanity/telemetry'\n\nimport {type CommentStatus} from '../types'\n\nexport const CommentLinkCopied = defineEvent({\n name: 'Comment Link Copied',\n version: 1,\n description: 'The link to a comment is copied',\n})\n\nexport const CommentViewedFromLink = defineEvent({\n name: 'Comment Viewed From Link',\n version: 1,\n description: 'A comment is viewed from a link',\n})\n\nexport const CommentListViewChanged = defineEvent<{view: CommentStatus}>({\n name: 'Comment List View Changed',\n version: 1,\n description: 'The view of the comment list is changed',\n})\n","import {useTelemetry} from '@sanity/telemetry/react'\nimport {useCallback, useMemo} from 'react'\n\nimport {\n CommentLinkCopied,\n CommentListViewChanged,\n CommentViewedFromLink,\n} from '../__telemetry__/comments.telemetry'\nimport {type CommentStatus} from '../types'\n\ninterface CommentsTelemetryHookValue {\n commentLinkCopied: () => void\n commentListViewChanged: (view: CommentStatus) => void\n commentViewedFromLink: () => void\n}\n\n/** @internal */\nexport function useCommentsTelemetry(): CommentsTelemetryHookValue {\n const telemetry = useTelemetry()\n\n const commentLinkCopied = useCallback(() => {\n telemetry.log(CommentLinkCopied)\n }, [telemetry])\n\n const commentViewedFromLink = useCallback(() => {\n telemetry.log(CommentViewedFromLink)\n }, [telemetry])\n\n const commentListViewChanged = useCallback(\n (view: CommentStatus) => {\n telemetry.log(CommentListViewChanged, {view})\n },\n [telemetry],\n )\n\n return useMemo(\n (): CommentsTelemetryHookValue => ({\n commentLinkCopied,\n commentListViewChanged,\n commentViewedFromLink,\n }),\n [commentLinkCopied, commentListViewChanged, commentViewedFromLink],\n )\n}\n","import {CheckmarkIcon} from '@sanity/icons/Checkmark'\nimport {ChevronDownIcon} from '@sanity/icons/ChevronDown'\nimport {CloseIcon} from '@sanity/icons/Close'\nimport {Card} from '@sanity/ui'\nimport {Menu} from '@sanity/ui/menu'\nimport {useCallback, type RefAttributes} from 'react'\nimport {styled} from 'styled-components'\nimport {Text, Flex} from 'ui5'\n\nimport {Button} from '../../../../ui-components/button/Button'\nimport {MenuButton} from '../../../../ui-components/menuButton/MenuButton'\nimport {MenuItem} from '../../../../ui-components/menuItem/MenuItem'\nimport {useTranslation} from '../../../i18n/hooks/useTranslation'\nimport {commentsLocaleNamespace} from '../../i18n'\nimport {type CommentStatus, type CommentsUIMode} from '../../types'\n\nconst Root = styled(Card)({\n position: 'relative',\n zIndex: '1',\n lineHeight: '0',\n})\n\ninterface CommentsInspectorHeaderProps {\n onClose: () => void\n onViewChange: (view: CommentStatus) => void\n view: CommentStatus\n mode: CommentsUIMode\n}\n\nexport function CommentsInspectorHeader(\n props: CommentsInspectorHeaderProps & RefAttributes<HTMLDivElement>,\n) {\n const {t} = useTranslation(commentsLocaleNamespace)\n const {ref, onClose, onViewChange, view, mode} = props\n\n const handleSetOpenView = useCallback(() => onViewChange('open'), [onViewChange])\n const handleSetResolvedView = useCallback(() => onViewChange('resolved'), [onViewChange])\n\n return (\n <Root ref={ref}>\n <Flex padding={2}>\n <Flex alignItems=\"center\" flexBasis=\"0%\" flexGrow={1} gap={2} paddingY={2} padding={3}>\n <Text as=\"h1\" size={1} weight=\"medium\" trim={true}>\n {t('feature-name')}\n </Text>\n </Flex>\n\n <Flex flexBasis=\"auto\" flexGrow={0} flexShrink={0} padding={1} gap={2}>\n <MenuButton\n id=\"comment-status-menu-button\"\n button={\n <Button\n text={\n view === 'open'\n ? t('status-filter.status-open')\n : t('status-filter.status-resolved')\n }\n mode=\"bleed\"\n iconRight={ChevronDownIcon}\n />\n }\n menu={\n <Menu style={{width: '180px'}}>\n <MenuItem\n iconRight={view === 'open' ? CheckmarkIcon : undefined}\n onClick={handleSetOpenView}\n text={t('status-filter.status-open-full')}\n />\n <MenuItem\n iconRight={view === 'resolved' ? CheckmarkIcon : undefined}\n onClick={handleSetResolvedView}\n text={t('status-filter.status-resolved-full')}\n tooltipProps={\n mode === 'upsell'\n ? {content: t('status-filter.status-resolved-full-upsell')}\n : undefined\n }\n disabled={mode === 'upsell'}\n />\n </Menu>\n }\n popover={{placement: 'bottom-end'}}\n />\n\n <Button\n aria-label={t('close-pane-button-text-aria-label')}\n icon={CloseIcon}\n mode=\"bleed\"\n onClick={onClose}\n tooltipProps={{content: t('close-pane-button-text')}}\n />\n </Flex>\n </Flex>\n </Root>\n )\n}\n","import {Layer, useClickOutsideEvent, useLayer} from '@sanity/ui'\nimport {useToast} from '@sanity/ui/toast'\nimport * as PathUtils from '@sanity/util/paths'\nimport {Fragment, useCallback, useEffect, useMemo, useRef, useState} from 'react'\nimport {styled} from 'styled-components'\nimport {Flex} from 'ui5'\n\nimport {type DocumentInspectorProps} from '../../../config/document/inspector'\nimport {useTranslation} from '../../../i18n/hooks/useTranslation'\nimport {useCurrentUser} from '../../../store/user/hooks'\nimport {CommentDeleteDialog} from '../../components/CommentDeleteDialog'\nimport {CommentsList} from '../../components/list/CommentsList'\nimport {CommentsOnboardingPopover} from '../../components/onboarding/CommentsOnboardingPopover'\nimport {CommentsUpsellPanel} from '../../components/upsell/CommentsUpsellPanel'\nimport {type CommentsSelectedPath} from '../../context/selected-path/types'\nimport {isTextSelectionComment} from '../../helpers'\nimport {useComments} from '../../hooks/useComments'\nimport {useCommentsEnabled} from '../../hooks/useCommentsEnabled'\nimport {useCommentsOnboarding} from '../../hooks/useCommentsOnboarding'\nimport {useCommentsScroll} from '../../hooks/useCommentsScroll'\nimport {useCommentsSelectedPath} from '../../hooks/useCommentsSelectedPath'\nimport {useCommentsTelemetry} from '../../hooks/useCommentsTelemetry'\nimport {useCommentsUpsell} from '../../hooks/useCommentsUpsell'\nimport {commentsLocaleNamespace} from '../../i18n'\nimport {\n type CommentBaseCreatePayload,\n type CommentReactionOption,\n type CommentStatus,\n type CommentsUIMode,\n type CommentUpdatePayload,\n} from '../../types'\nimport {CommentsInspectorHeader} from './CommentsInspectorHeader'\n\ninterface CommentToDelete {\n commentId: string\n isParent: boolean\n}\n\nconst RootLayer = styled(Layer)`\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n`\n\nexport function CommentsInspector(props: DocumentInspectorProps) {\n const {enabled, mode} = useCommentsEnabled()\n\n if (!enabled) return null\n\n // We wrap the comments inspector in a Layer in order to know when the comments inspector\n // is the top layer (that is, if there is e.g. a popover open). This is used to determine\n // if we should deselect the selected path when clicking outside the comments inspector.\n return (\n <RootLayer>\n <CommentsInspectorInner {...props} mode={mode} />\n </RootLayer>\n )\n}\n\nfunction CommentsInspectorInner(\n props: DocumentInspectorProps & {\n mode: CommentsUIMode\n },\n) {\n const {t} = useTranslation(commentsLocaleNamespace)\n const {onClose, mode} = props\n const [showDeleteDialog, setShowDeleteDialog] = useState<boolean>(false)\n const [commentToDelete, setCommentToDelete] = useState<CommentToDelete | null>(null)\n const [deleteLoading, setDeleteLoading] = useState<boolean>(false)\n const [deleteError, setDeleteError] = useState<Error | null>(null)\n\n const rootRef = useRef<HTMLDivElement | null>(null)\n const [rootElement, setRootElement] = useState<HTMLDivElement | null>(null)\n\n const currentUser = useCurrentUser()\n const {\n comments,\n getComment,\n mentionOptions,\n readOnly,\n setStatus,\n status,\n operation,\n selectedCommentId,\n getCommentLink,\n onClearSelectedComment,\n onPathOpen,\n } = useComments()\n const commentIdParamRef = useRef<string | undefined>(selectedCommentId)\n const didScrollToCommentFromParam = useRef<boolean>(false)\n\n const pushToast = useToast().push\n const {isTopLayer} = useLayer()\n\n const {scrollToComment, scrollToField, scrollToInlineComment} = useCommentsScroll({\n boundaryElement: rootElement,\n })\n const {selectedPath, setSelectedPath} = useCommentsSelectedPath()\n const {isDismissed, setDismissed} = useCommentsOnboarding()\n const telemetry = useCommentsTelemetry()\n\n const {upsellData, telemetryLogs: upsellTelemetryLogs} = useCommentsUpsell()\n\n const currentComments = useMemo(() => comments.data[status], [comments, status])\n\n const {loading} = comments\n\n const handleChangeView = useCallback(\n (nextView: CommentStatus) => {\n setStatus(nextView)\n setSelectedPath(null)\n\n telemetry.commentListViewChanged(nextView)\n },\n [setSelectedPath, setStatus, telemetry],\n )\n\n const handleCloseInspector = useCallback(() => {\n onClose()\n setSelectedPath(null)\n }, [onClose, setSelectedPath])\n\n const handleCopyLink = useMemo(() => {\n if (!getCommentLink) return undefined\n\n const copyLink = (id: string) => {\n navigator.clipboard.writeText(getCommentLink(id)).catch(() => {\n pushToast({\n closable: true,\n status: 'error',\n title: t('copy-link-error-message'),\n })\n })\n\n telemetry.commentLinkCopied()\n }\n\n return copyLink\n }, [getCommentLink, pushToast, t, telemetry])\n\n const handleCreateRetry = useCallback(\n (id: string) => {\n const comment = getComment(id)\n if (!comment) return\n\n void operation.create({\n type: 'field',\n fieldPath: comment.target.path?.field || '',\n id: comment._id,\n message: comment.message,\n parentCommentId: comment.parentCommentId,\n reactions: comment.reactions || [],\n status: comment.status,\n threadId: comment.threadId,\n })\n },\n [getComment, operation],\n )\n\n const closeDeleteDialog = useCallback(() => {\n if (deleteLoading) return\n setShowDeleteDialog(false)\n setCommentToDelete(null)\n }, [deleteLoading])\n\n const handlePathSelect = useCallback(\n (nextPath: CommentsSelectedPath) => {\n setSelectedPath(nextPath)\n\n if (nextPath?.fieldPath) {\n const path = PathUtils.fromString(nextPath.fieldPath)\n onPathOpen?.(path)\n\n scrollToField(nextPath.fieldPath)\n\n const isInlineComment = comments.data.open\n .filter((c) => c.threadId === nextPath?.threadId)\n .some((x) => isTextSelectionComment(x.parentComment))\n\n if (isInlineComment && nextPath.threadId) {\n scrollToInlineComment(nextPath.threadId)\n }\n }\n },\n [comments.data.open, onPathOpen, scrollToField, scrollToInlineComment, setSelectedPath],\n )\n\n const handleNewThreadCreate = useCallback(\n (nextComment: CommentBaseCreatePayload) => {\n const fieldPath = nextComment?.payload?.fieldPath || ''\n\n void operation.create({\n type: 'field',\n fieldPath,\n message: nextComment.message,\n parentCommentId: nextComment.parentCommentId,\n reactions: nextComment.reactions,\n status: nextComment.status,\n threadId: nextComment.threadId,\n })\n\n setSelectedPath({\n fieldPath,\n origin: 'inspector',\n threadId: nextComment.threadId,\n })\n },\n [operation, setSelectedPath],\n )\n\n const handleReply = useCallback(\n (nextComment: CommentBaseCreatePayload) => {\n void operation.create({\n ...nextComment,\n type: 'field',\n fieldPath: nextComment?.payload?.fieldPath || '',\n })\n },\n [operation],\n )\n\n const handleEdit = useCallback(\n (id: string, nextComment: CommentUpdatePayload) => {\n void operation.update(id, nextComment)\n },\n [operation],\n )\n\n const onDeleteStart = useCallback(\n (id: string) => {\n const parent = currentComments.find((c) => c.parentComment?._id === id)\n const isParent = Boolean(parent && parent?.replies?.length > 0)\n\n setShowDeleteDialog(true)\n setCommentToDelete({\n commentId: id,\n isParent,\n })\n },\n\n [currentComments],\n )\n\n const handleDeleteConfirm = useCallback(\n async (id: string) => {\n try {\n setDeleteLoading(true)\n await operation.remove(id)\n closeDeleteDialog()\n } catch (err) {\n setDeleteError(err)\n }\n setDeleteLoading(false)\n },\n [closeDeleteDialog, operation],\n )\n\n const handleStatusChange = useCallback(\n (id: string, nextStatus: CommentStatus) => {\n void operation.update(id, {\n status: nextStatus,\n })\n\n // If the comment is being opened, we want to change to the \"open\" view\n // and scroll to the comment\n if (nextStatus === 'open') {\n setStatus('open')\n\n const comment = getComment(id)\n\n if (!comment) return\n\n setSelectedPath({\n fieldPath: comment.target.path?.field || null,\n origin: 'inspector',\n threadId: comment.threadId || null,\n })\n\n scrollToComment(id)\n }\n },\n [getComment, operation, scrollToComment, setSelectedPath, setStatus],\n )\n\n const handleReactionSelect = useCallback(\n (id: string, reaction: CommentReactionOption) => {\n void operation.react(id, reaction)\n },\n [operation],\n )\n\n const handleDeselectPath = useCallback(() => {\n // Clear the selected path when:\n // - Clicking outside the inspector when it's the top layer\n // - The target is not a slate editor string. This is needed because we do not want to\n // frequently deselect the selected path when clicking inside the editor.\n if (selectedPath && isTopLayer) {\n setSelectedPath(null)\n }\n }, [isTopLayer, selectedPath, setSelectedPath])\n\n const setRootRef = useCallback((element: HTMLDivElement | null) => {\n rootRef.current = element\n setRootElement(element)\n }, [])\n\n useClickOutsideEvent(\n (event) => {\n // Clear the selected path when clicking outside the comments inspector.\n // We do this only when the comments inspector is the top layer.\n const isPTETarget =\n event.target instanceof HTMLElement && event.target?.hasAttribute('data-pt-text')\n\n if (!isPTETarget) {\n handleDeselectPath()\n }\n },\n () => [rootRef.current],\n )\n\n const [loggedTelemetry, setLoggedTelemetry] = useState(false)\n useEffect(() => {\n if (loggedTelemetry || mode !== 'upsell') return undefined\n // oxlint-disable-next-line react/set-state-in-effect -- pre-existing violation, to be fixed in a follow-up\n setLoggedTelemetry(true)\n if (selectedPath?.origin === 'form') {\n upsellTelemetryLogs.panelViewed('field_action')\n } else if (commentIdParamRef.current) {\n upsellTelemetryLogs.panelViewed('link')\n } else {\n upsellTelemetryLogs.panelViewed('document_action')\n }\n return () => {\n upsellTelemetryLogs.panelDismissed()\n }\n }, [loggedTelemetry, mode, selectedPath?.origin, upsellTelemetryLogs])\n\n // Handle scroll to comment from URL param\n useEffect(() => {\n // Make sure that the comment exists before we try to scroll to it.\n // We can't solely rely on the comment id from the url since the comment might not be loaded yet.\n const commentToScrollTo = getComment(commentIdParamRef.current || '')\n\n if (!loading && commentToScrollTo && !didScrollToCommentFromParam.current) {\n // Make sure we have the correct status set before we scroll to the comment\n setStatus(commentToScrollTo.status || 'open')\n\n handlePathSelect({\n fieldPath: commentToScrollTo.target.path?.field || null,\n origin: 'url',\n threadId: commentToScrollTo.threadId || null,\n })\n\n // Defer the comment scroll to prevent React batching from overwriting the field scroll\n requestAnimationFrame(() => {\n scrollToComment(commentToScrollTo._id)\n })\n\n didScrollToCommentFromParam.current = true\n commentIdParamRef.current = undefined\n\n onClearSelectedComment?.()\n\n telemetry.commentViewedFromLink()\n }\n }, [\n getComment,\n handlePathSelect,\n loading,\n onClearSelectedComment,\n scrollToComment,\n setStatus,\n telemetry,\n ])\n\n const beforeListNode = useMemo(() => {\n if (mode === 'upsell' && upsellData) {\n return (\n <CommentsUpsellPanel\n data={upsellData}\n onPrimaryClick={upsellTelemetryLogs.panelPrimaryClicked}\n onSecondaryClick={upsellTelemetryLogs.panelSecondaryClicked}\n />\n )\n }\n\n return null\n }, [\n mode,\n upsellTelemetryLogs.panelPrimaryClicked,\n upsellTelemetryLogs.panelSecondaryClicked,\n upsellData,\n ])\n\n return (\n <Fragment>\n {commentToDelete && showDeleteDialog && (\n <CommentDeleteDialog\n {...commentToDelete}\n error={deleteError}\n loading={deleteLoading}\n onClose={closeDeleteDialog}\n onConfirm={handleDeleteConfirm}\n />\n )}\n\n <Flex\n flexDirection=\"column\"\n flexBasis=\"0%\"\n flexGrow={1}\n height=\"100%\"\n onClick={handleDeselectPath}\n overflow=\"hidden\"\n ref={setRootRef}\n >\n <CommentsOnboardingPopover\n onDismiss={setDismissed}\n open={!isDismissed}\n placement=\"left-start\"\n >\n <CommentsInspectorHeader\n onClose={handleCloseInspector}\n onViewChange={handleChangeView}\n view={status}\n mode={mode}\n />\n </CommentsOnboardingPopover>\n {currentUser && (\n <CommentsList\n beforeListNode={beforeListNode}\n comments={currentComments}\n currentUser={currentUser}\n error={comments.error}\n loading={loading}\n mentionOptions={mentionOptions}\n mode={mode}\n onCopyLink={handleCopyLink}\n onCreateRetry={handleCreateRetry}\n onDelete={onDeleteStart}\n onEdit={handleEdit}\n onNewThreadCreate={handleNewThreadCreate}\n onPathSelect={handlePathSelect}\n onReactionSelect={handleReactionSelect}\n onReply={handleReply}\n onStatusChange={handleStatusChange}\n readOnly={readOnly}\n selectedPath={selectedPath}\n status={status}\n />\n )}\n </Flex>\n </Fragment>\n )\n}\n"],"mappings":"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"}