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.
- package/lib/{AddonDatasetProvider-0aiLWkZg.js → AddonDatasetProvider-C9tdum2G.js} +2 -2
- package/lib/{AddonDatasetProvider-0aiLWkZg.js.map → AddonDatasetProvider-C9tdum2G.js.map} +1 -1
- package/lib/{CalendarFilter-DVz369RP.js → CalendarFilter-C80uOkw-.js} +3 -3
- package/lib/{CalendarFilter-DVz369RP.js.map → CalendarFilter-C80uOkw-.js.map} +1 -1
- package/lib/{CommandList-CTDV_QZY.js → CommandList-duj-LVnd.js} +2 -2
- package/lib/{CommandList-CTDV_QZY.js.map → CommandList-duj-LVnd.js.map} +1 -1
- package/lib/{CommentInput-B5T1Iwnt.js → CommentInput-BXYQnGhq.js} +5 -5
- package/lib/{CommentInput-B5T1Iwnt.js.map → CommentInput-BXYQnGhq.js.map} +1 -1
- package/lib/{CommentsDocumentLayout-ByFwej_y.js → CommentsDocumentLayout-DAwAhx7q.js} +2 -2
- package/lib/{CommentsDocumentLayout-ByFwej_y.js.map → CommentsDocumentLayout-DAwAhx7q.js.map} +1 -1
- package/lib/{CommentsDocumentLayout-Czb6fC0_.js → CommentsDocumentLayout-pfM29WSy.js} +2 -2
- package/lib/{CommentsDocumentLayout-Czb6fC0_.js.map → CommentsDocumentLayout-pfM29WSy.js.map} +1 -1
- package/lib/{CommentsEnabledProvider-D2gutvsb.js → CommentsEnabledProvider-DN_oXwXM.js} +3 -3
- package/lib/{CommentsEnabledProvider-D2gutvsb.js.map → CommentsEnabledProvider-DN_oXwXM.js.map} +1 -1
- package/lib/{CommentsField-D2Fum0Jx.js → CommentsField-B7wTBRMB.js} +5 -5
- package/lib/{CommentsField-D2Fum0Jx.js.map → CommentsField-B7wTBRMB.js.map} +1 -1
- package/lib/{CommentsField-YM3cp3fA.js → CommentsField-BxoVuJOl.js} +4 -4
- package/lib/{CommentsField-YM3cp3fA.js.map → CommentsField-BxoVuJOl.js.map} +1 -1
- package/lib/{CommentsInput-Bx2t5AW_.js → CommentsInput-C3rEb5L8.js} +6 -6
- package/lib/{CommentsInput-Bx2t5AW_.js.map → CommentsInput-C3rEb5L8.js.map} +1 -1
- package/lib/{CommentsInput-BBBng3CJ.js → CommentsInput-CU-PFXmu.js} +7 -7
- package/lib/{CommentsInput-BBBng3CJ.js.map → CommentsInput-CU-PFXmu.js.map} +1 -1
- package/lib/{CommentsInspector-BnSG5Mq0.js → CommentsInspector-BJ1qwj6P.js} +6 -6
- package/lib/{CommentsInspector-BnSG5Mq0.js.map → CommentsInspector-BJ1qwj6P.js.map} +1 -1
- package/lib/{CommentsInspector-B5V_Bpz5.js → CommentsInspector-BQiMPjvm.js} +6 -6
- package/lib/{CommentsInspector-B5V_Bpz5.js.map → CommentsInspector-BQiMPjvm.js.map} +1 -1
- package/lib/{CommentsListItem-DnqAlN4p.js → CommentsListItem-QyYan1DB.js} +5 -5
- package/lib/{CommentsListItem-DnqAlN4p.js.map → CommentsListItem-QyYan1DB.js.map} +1 -1
- package/lib/{CommentsListItem-DVE4IMls.js → CommentsListItem-dvKmANi3.js} +4 -4
- package/lib/{CommentsListItem-DVE4IMls.js.map → CommentsListItem-dvKmANi3.js.map} +1 -1
- package/lib/{CommentsSelectedPathProvider-DRJ3Xqs4.js → CommentsSelectedPathProvider-COcPb3W3.js} +3 -3
- package/lib/{CommentsSelectedPathProvider-DRJ3Xqs4.js.map → CommentsSelectedPathProvider-COcPb3W3.js.map} +1 -1
- package/lib/{CommentsStudioLayout-Di510XhD.js → CommentsStudioLayout-BkX6o14w.js} +3 -3
- package/lib/{CommentsStudioLayout-Di510XhD.js.map → CommentsStudioLayout-BkX6o14w.js.map} +1 -1
- package/lib/{CommentsStudioLayout-Z09s50bM.js → CommentsStudioLayout-dIXEz52s.js} +3 -3
- package/lib/{CommentsStudioLayout-Z09s50bM.js.map → CommentsStudioLayout-dIXEz52s.js.map} +1 -1
- package/lib/{GlobalPerspectiveMenu-Cwur4_iD.js → GlobalPerspectiveMenu-0Hs276Z-.js} +15 -15
- package/lib/{GlobalPerspectiveMenu-Cwur4_iD.js.map → GlobalPerspectiveMenu-0Hs276Z-.js.map} +1 -1
- package/lib/{LoadingBlock-Ch_dBXfn.js → LoadingBlock-CElIdb7F.js} +3 -3
- package/lib/{LoadingBlock-Ch_dBXfn.js.map → LoadingBlock-CElIdb7F.js.map} +1 -1
- package/lib/{PerspectiveProvider-Yk7lgugx.js → PerspectiveProvider-D-6sweQH.js} +130 -97
- package/lib/PerspectiveProvider-D-6sweQH.js.map +1 -0
- package/lib/{ReleaseAvatar-C68bGuVQ.js → ReleaseAvatar-Bqp_Ci7r.js} +4 -4
- package/lib/{ReleaseAvatar-C68bGuVQ.js.map → ReleaseAvatar-Bqp_Ci7r.js.map} +1 -1
- package/lib/{ReleasesMetadataProvider-DabLuMD8.js → ReleasesMetadataProvider-BD6XRcpT.js} +2 -2
- package/lib/{ReleasesMetadataProvider-DabLuMD8.js.map → ReleasesMetadataProvider-BD6XRcpT.js.map} +1 -1
- package/lib/{ReleasesStudioLayout-DsygG30q.js → ReleasesStudioLayout-C6mmxoaY.js} +7 -7
- package/lib/{ReleasesStudioLayout-DsygG30q.js.map → ReleasesStudioLayout-C6mmxoaY.js.map} +1 -1
- package/lib/{ReleasesTool-CNXNODI_.js → ReleasesTool-DIDmkzic.js} +23 -23
- package/lib/{ReleasesTool-CNXNODI_.js.map → ReleasesTool-DIDmkzic.js.map} +1 -1
- package/lib/{SchedulePublishingStudioLayout-EsgEGZ7F.js → SchedulePublishingStudioLayout-DrZO-qbI.js} +3 -3
- package/lib/{SchedulePublishingStudioLayout-EsgEGZ7F.js.map → SchedulePublishingStudioLayout-DrZO-qbI.js.map} +1 -1
- package/lib/{SchedulePublishingUpsellProvider-CWxgqzFp.js → SchedulePublishingUpsellProvider-DeZ_jZIX.js} +2 -2
- package/lib/{SchedulePublishingUpsellProvider-CWxgqzFp.js.map → SchedulePublishingUpsellProvider-DeZ_jZIX.js.map} +1 -1
- package/lib/{ScheduledPublishingEnabledProvider-CQ-T1Y96.js → ScheduledPublishingEnabledProvider-B8C0_tc5.js} +3 -3
- package/lib/{ScheduledPublishingEnabledProvider-CQ-T1Y96.js.map → ScheduledPublishingEnabledProvider-B8C0_tc5.js.map} +1 -1
- package/lib/{SearchProvider-CEXmRg1N.js → SearchProvider-T8fsDJV5.js} +8 -8
- package/lib/{SearchProvider-CEXmRg1N.js.map → SearchProvider-T8fsDJV5.js.map} +1 -1
- package/lib/{SingleDocReleaseLayout-ByDXFS8N.js → SingleDocReleaseLayout-BpMXU9KY.js} +2 -2
- package/lib/{SingleDocReleaseLayout-ByDXFS8N.js.map → SingleDocReleaseLayout-BpMXU9KY.js.map} +1 -1
- package/lib/{SingleDocReleaseUpsellProvider-ByuDpBIG.js → SingleDocReleaseUpsellProvider-7_OXHySY.js} +3 -3
- package/lib/{SingleDocReleaseUpsellProvider-ByuDpBIG.js.map → SingleDocReleaseUpsellProvider-7_OXHySY.js.map} +1 -1
- package/lib/{TasksFooterOpenTasks-BSO8TgVF.js → TasksFooterOpenTasks-IFtOEGnB.js} +2 -2
- package/lib/{TasksFooterOpenTasks-BSO8TgVF.js.map → TasksFooterOpenTasks-IFtOEGnB.js.map} +1 -1
- package/lib/{TasksStudioActiveToolLayout-BXktrH08.js → TasksStudioActiveToolLayout-C99LQz4S.js} +20 -20
- package/lib/{TasksStudioActiveToolLayout-BXktrH08.js.map → TasksStudioActiveToolLayout-C99LQz4S.js.map} +1 -1
- package/lib/{TasksStudioLayout-BfN-M93c.js → TasksStudioLayout-CmFbUpnB.js} +4 -4
- package/lib/{TasksStudioLayout-BfN-M93c.js.map → TasksStudioLayout-CmFbUpnB.js.map} +1 -1
- package/lib/{TasksStudioNavbar-CfqloSfP.js → TasksStudioNavbar-DB7DJC4e.js} +2 -2
- package/lib/{TasksStudioNavbar-CfqloSfP.js.map → TasksStudioNavbar-DB7DJC4e.js.map} +1 -1
- package/lib/{TimeZoneButton-FCwCyJ1J.js → TimeZoneButton-B_ki5v8q.js} +7 -7
- package/lib/{TimeZoneButton-FCwCyJ1J.js.map → TimeZoneButton-B_ki5v8q.js.map} +1 -1
- package/lib/{Tool-PzN5dskE.js → Tool-DlkZrcrD.js} +15 -15
- package/lib/{Tool-PzN5dskE.js.map → Tool-DlkZrcrD.js.map} +1 -1
- package/lib/{UpsellPanel-T-5ZD_7k.js → UpsellPanel-ITWwjktp.js} +2 -2
- package/lib/{UpsellPanel-T-5ZD_7k.js.map → UpsellPanel-ITWwjktp.js.map} +1 -1
- package/lib/{VariantsStudioNavbar-D0XbvL1D.js → VariantsStudioNavbar-DwEV1roH.js} +9 -9
- package/lib/{VariantsStudioNavbar-D0XbvL1D.js.map → VariantsStudioNavbar-DwEV1roH.js.map} +1 -1
- package/lib/{VariantsTool-B3EEDrQT.js → VariantsTool-Dzhy3PST.js} +12 -12
- package/lib/{VariantsTool-B3EEDrQT.js.map → VariantsTool-Dzhy3PST.js.map} +1 -1
- package/lib/{WorkspaceLoader-BH_VDaY4.js → WorkspaceLoader-Ck4TMoR5.js} +31 -31
- package/lib/{WorkspaceLoader-BH_VDaY4.js.map → WorkspaceLoader-Ck4TMoR5.js.map} +1 -1
- package/lib/_createContext.js +1 -1
- package/lib/_unstable-embedded.js +5 -5
- package/lib/{buildRangeDecorationSelectionsFromComments-B1-tJPvG.js → buildRangeDecorationSelectionsFromComments-BnlhrvDK.js} +3 -3
- package/lib/{buildRangeDecorationSelectionsFromComments-B1-tJPvG.js.map → buildRangeDecorationSelectionsFromComments-BnlhrvDK.js.map} +1 -1
- package/lib/{buildTextSelectionFromFragment-BiLg851R.js → buildTextSelectionFromFragment-BXrYd9lr.js} +3 -3
- package/lib/{buildTextSelectionFromFragment-BiLg851R.js.map → buildTextSelectionFromFragment-BXrYd9lr.js.map} +1 -1
- package/lib/{constants-DdgHySkY.js → constants-BQItnHll.js} +2 -2
- package/lib/{constants-DdgHySkY.js.map → constants-BQItnHll.js.map} +1 -1
- package/lib/{datastores-D1tF4HQA.js → datastores-DNOJm1LF.js} +2 -2
- package/lib/{datastores-D1tF4HQA.js.map → datastores-DNOJm1LF.js.map} +1 -1
- package/lib/{i18n-Cl_y4bbR.js → i18n-JUYUb7y_.js} +2 -2
- package/lib/{i18n-Cl_y4bbR.js.map → i18n-JUYUb7y_.js.map} +1 -1
- package/lib/index.js +38 -38
- package/lib/{inputResolver-CUWPjdGU.js → inputResolver-Ce1lTBE-.js} +4 -4
- package/lib/{inputResolver-CUWPjdGU.js.map → inputResolver-Ce1lTBE-.js.map} +1 -1
- package/lib/{navigation.telemetry-rXclq03x.js → navigation.telemetry-BPxX2IEN.js} +10 -10
- package/lib/{navigation.telemetry-rXclq03x.js.map → navigation.telemetry-BPxX2IEN.js.map} +1 -1
- package/lib/{plugin-CSp8hwQE.js → plugin-Bvxhb5ko.js} +8 -8
- package/lib/{plugin-CSp8hwQE.js.map → plugin-Bvxhb5ko.js.map} +1 -1
- package/lib/{plugin-Daxe5hwG.js → plugin-Cv6TLYbE.js} +6 -6
- package/lib/{plugin-Daxe5hwG.js.map → plugin-Cv6TLYbE.js.map} +1 -1
- package/lib/{plugin-BFTpdKKH.js → plugin-D6-7jrXf.js} +3 -3
- package/lib/{plugin-BFTpdKKH.js.map → plugin-D6-7jrXf.js.map} +1 -1
- package/lib/{plugin-dtgDcBsL.js → plugin-D_GVPwTR.js} +6 -6
- package/lib/{plugin-dtgDcBsL.js.map → plugin-D_GVPwTR.js.map} +1 -1
- package/lib/{releases.telemetry-B6tRA9U2.js → releases.telemetry-BAO7xaO7.js} +6 -6
- package/lib/{releases.telemetry-B6tRA9U2.js.map → releases.telemetry-BAO7xaO7.js.map} +1 -1
- package/lib/{resources-BjljYbUa.js → resources-Bw1bpPhG.js} +2 -2
- package/lib/{resources-BjljYbUa.js.map → resources-Bw1bpPhG.js.map} +1 -1
- package/lib/{resources-DYxnNjS8.js → resources-CC1qBsSO.js} +2 -2
- package/lib/{resources-DYxnNjS8.js.map → resources-CC1qBsSO.js.map} +1 -1
- package/lib/{resources-D7Mp6N-8.js → resources-CH42UqhC.js} +2 -2
- package/lib/{resources-D7Mp6N-8.js.map → resources-CH42UqhC.js.map} +1 -1
- package/lib/{resources-GpX0LblP.js → resources-Cq1lXH8T.js} +2 -2
- package/lib/{resources-GpX0LblP.js.map → resources-Cq1lXH8T.js.map} +1 -1
- package/lib/{resources-B7mfG9Km.js → resources-D7XsFe7y.js} +2 -2
- package/lib/{resources-B7mfG9Km.js.map → resources-D7XsFe7y.js.map} +1 -1
- package/lib/{resources-CmmAynkL.js → resources-DYn0yzEW.js} +2 -2
- package/lib/{resources-CmmAynkL.js.map → resources-DYn0yzEW.js.map} +1 -1
- package/lib/{resources-C79qQva3.js → resources-TsgtFPi7.js} +2 -2
- package/lib/{resources-C79qQva3.js.map → resources-TsgtFPi7.js.map} +1 -1
- package/lib/{scheduleItem-Bdvl81Kb.js → scheduleItem-5fXCZgfo.js} +13 -13
- package/lib/{scheduleItem-Bdvl81Kb.js.map → scheduleItem-5fXCZgfo.js.map} +1 -1
- package/lib/{schedules-D7bPbTPm.js → schedules-BsE0_g47.js} +3 -3
- package/lib/{schedules-D7bPbTPm.js.map → schedules-BsE0_g47.js.map} +1 -1
- package/lib/{searchDocumentRelease-v1o9dMnE.js → searchDocumentRelease-Bang3A8l.js} +5 -5
- package/lib/{searchDocumentRelease-v1o9dMnE.js.map → searchDocumentRelease-Bang3A8l.js.map} +1 -1
- package/lib/{studioClient-EJDu6kOb.js → studioClient-C7B6Aobi.js} +2 -2
- package/lib/{studioClient-EJDu6kOb.js.map → studioClient-C7B6Aobi.js.map} +1 -1
- package/lib/{useActiveReleases-Bh_Q6f7G.js → useActiveReleases-DxYjyTB1.js} +5 -5
- package/lib/{useActiveReleases-Bh_Q6f7G.js.map → useActiveReleases-DxYjyTB1.js.map} +1 -1
- package/lib/{useBundleDocuments-zP6JiTzz.js → useBundleDocuments-2YaaN-2l.js} +3 -3
- package/lib/{useBundleDocuments-zP6JiTzz.js.map → useBundleDocuments-2YaaN-2l.js.map} +1 -1
- package/lib/{useComments-BGOJwUe0.js → useComments-DWh1k0kS.js} +5 -5
- package/lib/{useComments-BGOJwUe0.js.map → useComments-DWh1k0kS.js.map} +1 -1
- package/lib/{useCommentsTelemetry-BMkf6MTO.js → useCommentsTelemetry-BbJ8lTKN.js} +4 -4
- package/lib/{useCommentsTelemetry-BMkf6MTO.js.map → useCommentsTelemetry-BbJ8lTKN.js.map} +1 -1
- package/lib/{useDocumentPreviewValues-CryTvfKc.js → useDocumentPreviewValues-CK5VteK3.js} +4 -4
- package/lib/{useDocumentPreviewValues-CryTvfKc.js.map → useDocumentPreviewValues-CK5VteK3.js.map} +1 -1
- package/lib/{useFieldActions-BTj7VsW5.js → useFieldActions-BmY1Kh3s.js} +2 -2
- package/lib/{useFieldActions-BTj7VsW5.js.map → useFieldActions-BmY1Kh3s.js.map} +1 -1
- package/lib/{useProjectId-BN6GCdwS.js → useProjectId-C8pZxybz.js} +2 -2
- package/lib/{useProjectId-BN6GCdwS.js.map → useProjectId-C8pZxybz.js.map} +1 -1
- package/lib/{useReleasesToolAvailable-CQ9-I8Tt.js → useReleasesToolAvailable-DjaSujLo.js} +3 -3
- package/lib/{useReleasesToolAvailable-CQ9-I8Tt.js.map → useReleasesToolAvailable-DjaSujLo.js.map} +1 -1
- package/lib/{useScheduledDraftMenuActions-OSkdxONo.js → useScheduledDraftMenuActions-DSJU6xQa.js} +9 -9
- package/lib/{useScheduledDraftMenuActions-OSkdxONo.js.map → useScheduledDraftMenuActions-DSJU6xQa.js.map} +1 -1
- package/lib/{useStudioUrl-DUBI_S4K.js → useStudioUrl-DcTGV00c.js} +5 -5
- package/lib/{useStudioUrl-DUBI_S4K.js.map → useStudioUrl-DcTGV00c.js.map} +1 -1
- package/lib/{useTasksNavigation-fohCXW6l.js → useTasksNavigation-tAXFJd2V.js} +2 -2
- package/lib/{useTasksNavigation-fohCXW6l.js.map → useTasksNavigation-tAXFJd2V.js.map} +1 -1
- package/lib/{useTimeZone-DM8ZmUO2.js → useTimeZone-Dj7C8tfZ.js} +2 -2
- package/lib/{useTimeZone-DM8ZmUO2.js.map → useTimeZone-Dj7C8tfZ.js.map} +1 -1
- package/lib/{utils-D-4rueJZ.js → utils-CT034e4q.js} +3 -3
- package/lib/{utils-D-4rueJZ.js.map → utils-CT034e4q.js.map} +1 -1
- package/lib/{validationUtils-jTd1rxfY.js → validationUtils-BZPoHEYN.js} +4 -4
- package/lib/{validationUtils-jTd1rxfY.js.map → validationUtils-BZPoHEYN.js.map} +1 -1
- package/lib/{version-D0Vx4cX1.js → version-BDSMcNU7.js} +2 -2
- package/lib/{version-D0Vx4cX1.js.map → version-BDSMcNU7.js.map} +1 -1
- package/package.json +17 -17
- package/lib/PerspectiveProvider-Yk7lgugx.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CommentInput-B5T1Iwnt.js","names":["opts || {}","{\n ...options,\n boundary: shouldApplyBoundary ? boundaryElement : undefined,\n }","shouldApplyBoundary ? boundaryElement : undefined","useMemo(() => {\n const options = SCROLL_OPTIONS_BY_TYPE[scrollTarget?.type || 'comment']\n\n // Only apply boundary for 'comment' type scrolls (scrolling within inspector panel)\n // Field, group, and inline-comment scrolls target the document pane and shouldn't be bounded\n const shouldApplyBoundary = scrollTarget?.type === 'comment'\n\n return {\n ...options,\n boundary: shouldApplyBoundary ? boundaryElement : undefined,\n }\n }, [boundaryElement, scrollTarget?.type])","(commentId: string) => {\n setScrollTarget({type: 'comment', id: commentId})\n }","useCallback((commentId: string) => {\n setScrollTarget({type: 'comment', id: commentId})\n }, [])","(threadId: string) => {\n setScrollTarget({type: 'group', id: threadId})\n }","useCallback((threadId: string) => {\n setScrollTarget({type: 'group', id: threadId})\n }, [])","(fieldPath: string) => {\n setScrollTarget({type: 'field', id: fieldPath})\n }","useCallback((fieldPath: string) => {\n setScrollTarget({type: 'field', id: fieldPath})\n }, [])","(commentId: string) => {\n setScrollTarget({type: 'inline-comment', id: commentId})\n }","commentId","useCallback((commentId: string) => {\n setScrollTarget({type: 'inline-comment', id: commentId})\n }, [])","() => {\n const raf = requestAnimationFrame(() => {\n if (!scrollTarget) return\n\n const {type, id} = scrollTarget\n\n const element = document?.querySelector(\n `[data-comments-${type}-id=\"${generateValidAttrValue(id)}\"]`,\n )\n\n if (element) {\n scrollIntoViewIfNeeded(element, scrollOpts)\n }\n })\n\n return () => {\n cancelAnimationFrame(raf)\n }\n }","[scrollOpts, scrollTarget]","{\n scrollToComment: handleScrollToComment,\n scrollToField: handleScrollToField,\n scrollToGroup: handleScrollToGroup,\n scrollToInlineComment: handleScrollToInlineComment,\n }","useMemo(\n (): CommentsScrollHookValue => ({\n scrollToComment: handleScrollToComment,\n scrollToField: handleScrollToField,\n scrollToGroup: handleScrollToGroup,\n scrollToInlineComment: handleScrollToInlineComment,\n }),\n [handleScrollToComment, handleScrollToField, handleScrollToGroup, handleScrollToInlineComment],\n )","<NormalText size={1} forwardedAs=\"div\" trim={true}>\n {children}\n </NormalText>","(e: MouseEvent<HTMLButtonElement>) => {\n e.stopPropagation()\n onClose()\n }","useCallback(\n (e: MouseEvent<HTMLButtonElement>) => {\n e.stopPropagation()\n onClose()\n },\n [onClose],\n )","(e: MouseEvent<HTMLButtonElement>) => {\n e.stopPropagation()\n onConfirm()\n }","useCallback(\n (e: MouseEvent<HTMLButtonElement>) => {\n e.stopPropagation()\n onConfirm()\n },\n [onConfirm],\n )","t('discard.header')","{\n onClick: handleCancelClick,\n }","t('discard.button-confirm')","{\n onClick: handleConfirmClick,\n text: t('discard.button-confirm'),\n tone: 'critical',\n }","{\n cancelButton: {\n onClick: handleCancelClick,\n },\n confirmButton: {\n onClick: handleConfirmClick,\n text: t('discard.button-confirm'),\n tone: 'critical',\n },\n }","t('discard.text')","<Text size={1} as=\"div\" trim={true}>\n {t('discard.text')}\n </Text>","<ThemeColorProvider tone=\"default\">\n <DialogProvider zOffset={Z_OFFSET}>\n <Dialog\n header={t('discard.header')}\n id=\"discard-comment-dialog\"\n onClose={onClose}\n width={0}\n onClickOutside={onClose}\n footer={{\n cancelButton: {\n onClick: handleCancelClick,\n },\n confirmButton: {\n onClick: handleConfirmClick,\n text: t('discard.button-confirm'),\n tone: 'critical',\n },\n }}\n >\n <Text size={1} as=\"div\" trim={true}>\n {t('discard.text')}\n </Text>\n </Dialog>\n </DialogProvider>\n </ThemeColorProvider>","nameToInitials(user?.displayName || '')","user?.displayName || ''","useMemo(() => nameToInitials(user?.displayName || ''), [user?.displayName])","<StyledAvatar {...restProps} />","<StyledAvatar\n initials={initials}\n src={user?.imageUrl}\n title={user?.displayName}\n {...restProps}\n />","user?.imageUrl","user?.displayName","<path\n d=\"M16.6633 18.9383C15.539 19.6562 14.2034 20.0723 12.7705 20.0723C8.77022 20.0723 5.52734 16.8294 5.52734 12.8291C5.52734 8.82881 8.77022 5.58594 12.7705 5.58594C16.7708 5.58594 20.0137 8.82881 20.0137 12.8291C20.0137 13.6623 19.8249 14.7093 19.6141 15.2077C19.5578 15.3408 19.479 15.4845 19.3936 15.6238C19.0955 16.1106 18.5507 16.3721 17.9807 16.4018V16.4018C16.8271 16.462 15.8588 15.5428 15.8588 14.3877V9.27302\"\n stroke=\"currentColor\"\n strokeWidth={1.2}\n strokeLinejoin=\"round\"\n />","<circle cx=\"12.5732\" cy=\"12.8291\" r=\"3.08691\" stroke=\"currentColor\" strokeWidth={1.2} />","<svg\n data-sanity-icon=\"mention\"\n fill=\"none\"\n height=\"1em\"\n ref={ref}\n viewBox=\"0 0 25 25\"\n width=\"1em\"\n xmlns=\"http://www.w3.org/2000/svg\"\n {...rest}\n >\n <path\n d=\"M16.6633 18.9383C15.539 19.6562 14.2034 20.0723 12.7705 20.0723C8.77022 20.0723 5.52734 16.8294 5.52734 12.8291C5.52734 8.82881 8.77022 5.58594 12.7705 5.58594C16.7708 5.58594 20.0137 8.82881 20.0137 12.8291C20.0137 13.6623 19.8249 14.7093 19.6141 15.2077C19.5578 15.3408 19.479 15.4845 19.3936 15.6238C19.0955 16.1106 18.5507 16.3721 17.9807 16.4018V16.4018C16.8271 16.462 15.8588 15.5428 15.8588 14.3877V9.27302\"\n stroke=\"currentColor\"\n strokeWidth={1.2}\n strokeLinejoin=\"round\"\n />\n <circle cx=\"12.5732\" cy=\"12.8291\" r=\"3.08691\" stroke=\"currentColor\" strokeWidth={1.2} />\n </svg>","<path\n clipRule=\"evenodd\"\n d=\"M21.1602 12.5L7.16016 19.5V14.8765L13.6656 12.4989L7.16016 9.97149L7.16016 5.5L21.1602 12.5Z\"\n stroke=\"currentColor\"\n strokeWidth={1.2}\n strokeLinejoin=\"round\"\n />","<svg\n data-sanity-icon=\"send\"\n fill=\"none\"\n height=\"1em\"\n ref={ref}\n viewBox=\"0 0 25 25\"\n width=\"1em\"\n xmlns=\"http://www.w3.org/2000/svg\"\n {...rest}\n >\n <path\n clipRule=\"evenodd\"\n d=\"M21.1602 12.5L7.16016 19.5V14.8765L13.6656 12.4989L7.16016 9.97149L7.16016 5.5L21.1602 12.5Z\"\n stroke=\"currentColor\"\n strokeWidth={1.2}\n strokeLinejoin=\"round\"\n />\n </svg>","<CommentsAvatar user={loadedUser} status={user.granted ? undefined : 'inactive'} />","user.granted ? undefined : 'inactive'","loadedUser ? (\n <Text size={1} truncate={1} title={loadedUser.displayName} as=\"div\" trim={true}>\n {loadedUser.displayName}\n </Text>\n ) : (\n <TextSkeleton size={1} style={SKELETON_INLINE_STYLE} />\n )","() => {\n onSelect(user.id)\n }","id","useCallback(() => {\n onSelect(user.id)\n }, [onSelect, user.id])","<Box>{text}</Box>","<InnerFlex alignItems=\"center\" gap={2} flexBasis=\"0%\" flexGrow={1}>\n {avatar}\n <Box>{text}</Box>\n </InnerFlex>","!user.granted && <Badge fontSize={1}>{t('mentions.unauthorized-user')}</Badge>","granted","<Flex alignItems=\"center\" gap={3}>\n <InnerFlex alignItems=\"center\" gap={2} flexBasis=\"0%\" flexGrow={1}>\n {avatar}\n <Box>{text}</Box>\n </InnerFlex>\n\n {!user.granted && <Badge fontSize={1}>{t('mentions.unauthorized-user')}</Badge>}\n </Flex>","<Card as=\"button\" disabled={!user.granted} onClick={handleSelect} padding={2} radius={2}>\n <Flex alignItems=\"center\" gap={3}>\n <InnerFlex alignItems=\"center\" gap={2} flexBasis=\"0%\" flexGrow={1}>\n {avatar}\n <Box>{text}</Box>\n </InnerFlex>\n\n {!user.granted && <Badge fontSize={1}>{t('mentions.unauthorized-user')}</Badge>}\n </Flex>\n </Card>","!user.granted","options = []","() => {\n return {\n setSearchTerm(term: string) {\n setSearchTerm(term)\n },\n }\n }","[]","(itemProps: UserWithPermission) => {\n return <MentionsMenuItem user={itemProps} onSelect={onSelect} />\n }","useCallback(\n (itemProps: UserWithPermission) => {\n return <MentionsMenuItem user={itemProps} onSelect={onSelect} />\n },\n [onSelect],\n )","(index: number) => {\n return !options?.[index]?.granted\n }","useCallback(\n (index: number) => {\n return !options?.[index]?.granted\n },\n [options],\n )","useMemo(() => {\n if (!searchTerm) return options || EMPTY_ARRAY\n\n // We deburr the search term and the display names so that when searching\n // for e.g \"bjorge\" we also get results for \"bjørge\"\n const deburredSearchTerm = deburr(searchTerm).toLocaleLowerCase()\n\n const deburredOptions = options?.map((option) => ({\n ...option,\n displayName: deburr(option.displayName || '').toLocaleLowerCase(),\n }))\n\n const filtered = deburredOptions\n ?.filter((option) => {\n return option?.displayName?.includes(deburredSearchTerm)\n })\n // Sort by whether the displayName starts with the search term to get more relevant results first\n ?.sort((a, b) => {\n const matchA = a.displayName?.startsWith(deburredSearchTerm)\n const matchB = b.displayName?.startsWith(deburredSearchTerm)\n\n if (matchA && !matchB) return -1\n if (!matchA && matchB) return 1\n\n return 0\n })\n\n return filtered || EMPTY_ARRAY\n }, [options, searchTerm])","deburredOptions\n ?.filter((option) => {\n return option?.displayName?.includes(deburredSearchTerm)\n })\n // Sort by whether the displayName starts with the search term to get more relevant results first\n ?.sort((a, b) => {\n const matchA = a.displayName?.startsWith(deburredSearchTerm)\n const matchB = b.displayName?.startsWith(deburredSearchTerm)\n\n if (matchA && !matchB) return -1\n if (!matchA && matchB) return 1\n\n return 0\n })","options?.map","(option) => ({\n ...option,\n displayName: deburr(option.displayName || '').toLocaleLowerCase(),\n })","option","<Root>\n <LoadingBlock showText />\n </Root>","filteredOptions.length === 0 && (\n <Box padding={5}>\n <Text align=\"center\" size={1} muted as=\"div\" trim={true}>\n {t('mentions.no-users-found')}\n </Text>\n </Box>\n )","length","filteredOptions.length > 0 && (\n <FlexWrap flexDirection=\"column\" flexBasis=\"0%\" flexGrow={1} overflow=\"hidden\">\n <CommandList\n activeItemDataAttr=\"data-hovered\"\n ariaLabel={t('mentions.user-list-aria-label')}\n fixedHeight\n getItemDisabled={getItemDisabled}\n inputElement={_inputElement}\n itemHeight={41}\n items={filteredOptions}\n padding={1}\n ref={commandListRef}\n renderItem={renderItem}\n />\n </FlexWrap>\n )","filteredOptions.length","<Flex flexDirection=\"column\" height=\"100%\" data-testid=\"comments-mentions-menu\">\n {filteredOptions.length === 0 && (\n <Box padding={5}>\n <Text align=\"center\" size={1} muted as=\"div\" trim={true}>\n {t('mentions.no-users-found')}\n </Text>\n </Box>\n )}\n\n {filteredOptions.length > 0 && (\n <FlexWrap flexDirection=\"column\" flexBasis=\"0%\" flexGrow={1} overflow=\"hidden\">\n <CommandList\n activeItemDataAttr=\"data-hovered\"\n ariaLabel={t('mentions.user-list-aria-label')}\n fixedHeight\n getItemDisabled={getItemDisabled}\n inputElement={_inputElement}\n itemHeight={41}\n items={filteredOptions}\n padding={1}\n ref={commandListRef}\n renderItem={renderItem}\n />\n </FlexWrap>\n )}\n </Flex>","<TextSkeleton\n data-testid=\"comment-mentions-loading-skeleton\"\n style={{width: '10ch'}}\n size={0}\n muted\n radius={1}\n animated\n />","<Flex>\n <CommentsAvatar user={user} />\n </Flex>","<Text size={1} as=\"div\" trim={true}>\n {user.displayName}\n </Text>","displayName","<Flex alignItems=\"center\" gap={2}>\n <Flex>\n <CommentsAvatar user={user} />\n </Flex>\n\n <Text size={1} as=\"div\" trim={true}>\n {user.displayName}\n </Text>\n </Flex>","<Span data-selected={selected} data-active={currentUser?.sanityUserId === userId}>\n @{user.displayName}\n </Span>","currentUser?.sanityUserId === userId","<Tooltip\n portal\n content={\n <Flex alignItems=\"center\" gap={2}>\n <Flex>\n <CommentsAvatar user={user} />\n </Flex>\n\n <Text size={1} as=\"div\" trim={true}>\n {user.displayName}\n </Text>\n </Flex>\n }\n >\n <Span data-selected={selected} data-active={currentUser?.sanityUserId === userId}>\n @{user.displayName}\n </Span>\n </Tooltip>","useMemo(() => {\n if (!cursorRect) {\n return null\n }\n return {\n getBoundingClientRect: () => {\n return cursorRect\n },\n } as HTMLElement\n }, [cursorRect])","{\n getBoundingClientRect: () => {\n return cursorRect\n },\n }","() => {\n if (disabled) {\n setCursorRect(null)\n return\n }\n\n const sel = window.getSelection()\n\n if (!sel || !sel.isCollapsed || sel.rangeCount === 0) return\n\n const range = sel.getRangeAt(0)\n const isWithinRoot = rootElement?.contains(range.commonAncestorContainer)\n\n if (!isWithinRoot) {\n setCursorRect(null)\n return\n }\n const rect = range?.getBoundingClientRect()\n if (rect) {\n setCursorRect(rect)\n }\n }","rootElement?.contains","useCallback(() => {\n if (disabled) {\n setCursorRect(null)\n return\n }\n\n const sel = window.getSelection()\n\n if (!sel || !sel.isCollapsed || sel.rangeCount === 0) return\n\n const range = sel.getRangeAt(0)\n const isWithinRoot = rootElement?.contains(range.commonAncestorContainer)\n\n if (!isWithinRoot) {\n setCursorRect(null)\n return\n }\n const rect = range?.getBoundingClientRect()\n if (rect) {\n setCursorRect(rect)\n }\n }, [disabled, rootElement])","() => {\n document.addEventListener('selectionchange', handleSelectionChange, EVENT_LISTENER_OPTIONS)\n\n return () => {\n document.removeEventListener('selectionchange', handleSelectionChange)\n }\n }","[handleSelectionChange]","placeholder = t('compose.create-comment-placeholder')","{\n disabled: !mentionsMenuOpen,\n rootElement: rootElement,\n }","!mentionsMenuOpen","() => <PlaceholderWrapper>{placeholder}</PlaceholderWrapper>","useCallback(\n () => <PlaceholderWrapper>{placeholder}</PlaceholderWrapper>,\n [placeholder],\n )","defineTextBlock({\n type: 'block',\n render: (blockProps) => (\n <div {...blockProps.attributes}>{renderBlock({children: blockProps.children})}</div>\n ),\n })","defineInlineObject({\n type: 'mention',\n render: (mentionProps) =>\n mentionProps.node.userId ? (\n <span {...mentionProps.attributes}>\n {/* Carries the engine's caret spacer; dropping this loses cursor placement around the mention. */}\n {mentionProps.children}\n {/* `draggable` makes the mention movable and keeps its text\n unselectable (a draggable element starts a drag instead of a\n text selection), matching the legacy pipeline's wrapper. */}\n <span draggable={!mentionProps.readOnly} style={{display: 'inline-block'}}>\n <MentionInlineBlock\n selected={mentionProps.selected}\n userId={mentionProps.node.userId as string}\n />\n </span>\n </span>\n ) : (\n mentionProps.renderDefault(mentionProps)\n ),\n })","(mentionProps) =>\n mentionProps.node.userId ? (\n <span {...mentionProps.attributes}>\n {/* Carries the engine's caret spacer; dropping this loses cursor placement around the mention. */}\n {mentionProps.children}\n {/* `draggable` makes the mention movable and keeps its text\n unselectable (a draggable element starts a drag instead of a\n text selection), matching the legacy pipeline's wrapper. */}\n <span draggable={!mentionProps.readOnly} style={{display: 'inline-block'}}>\n <MentionInlineBlock\n selected={mentionProps.selected}\n userId={mentionProps.node.userId as string}\n />\n </span>\n </span>\n ) : (\n mentionProps.renderDefault(mentionProps)\n )","[\n defineTextBlock({\n type: 'block',\n render: (blockProps) => (\n <div {...blockProps.attributes}>{renderBlock({children: blockProps.children})}</div>\n ),\n }),\n defineInlineObject({\n type: 'mention',\n render: (mentionProps) =>\n mentionProps.node.userId ? (\n <span {...mentionProps.attributes}>\n {/* Carries the engine's caret spacer; dropping this loses cursor placement around the mention. */}\n {mentionProps.children}\n {/* `draggable` makes the mention movable and keeps its text\n unselectable (a draggable element starts a drag instead of a\n text selection), matching the legacy pipeline's wrapper. */}\n <span draggable={!mentionProps.readOnly} style={{display: 'inline-block'}}>\n <MentionInlineBlock\n selected={mentionProps.selected}\n userId={mentionProps.node.userId as string}\n />\n </span>\n </span>\n ) : (\n mentionProps.renderDefault(mentionProps)\n ),\n }),\n ]","useMemo(\n () => [\n defineTextBlock({\n type: 'block',\n render: (blockProps) => (\n <div {...blockProps.attributes}>{renderBlock({children: blockProps.children})}</div>\n ),\n }),\n defineInlineObject({\n type: 'mention',\n render: (mentionProps) =>\n mentionProps.node.userId ? (\n <span {...mentionProps.attributes}>\n {/* Carries the engine's caret spacer; dropping this loses cursor placement around the mention. */}\n {mentionProps.children}\n {/* `draggable` makes the mention movable and keeps its text\n unselectable (a draggable element starts a drag instead of a\n text selection), matching the legacy pipeline's wrapper. */}\n <span draggable={!mentionProps.readOnly} style={{display: 'inline-block'}}>\n <MentionInlineBlock\n selected={mentionProps.selected}\n userId={mentionProps.node.userId as string}\n />\n </span>\n </span>\n ) : (\n mentionProps.renderDefault(mentionProps)\n ),\n }),\n ],\n [renderBlock],\n )","() => [popoverRef.current]","(event: KeyboardEvent) => {\n switch (event.key) {\n case 'Enter':\n // Shift enter is used to insert a new line,\n // keep the default behavior\n if (event.shiftKey) {\n break\n }\n\n // If the mention menu is open close it, but don't submit.\n if (mentionsMenuOpen) {\n // Enter is being used both to select something from the mentionsMenu, prevent the default behavior.\n event.preventDefault()\n event.stopPropagation()\n closeMentions()\n break\n }\n\n // Submit the comment if eligible for submission\n if (onSubmit && canSubmit) {\n // Enter is being used to submit the comment, prevent the default behavior.\n event.preventDefault()\n event.stopPropagation()\n onSubmit()\n }\n break\n\n case 'Escape':\n case 'ArrowLeft':\n case 'ArrowRight':\n if (mentionsMenuOpen) {\n // stop these events if the menu is open\n event.preventDefault()\n event.stopPropagation()\n closeMentions()\n }\n break\n default:\n }\n // Call parent key handler\n if (onKeyDown) onKeyDown(event)\n }","useCallback(\n (event: KeyboardEvent) => {\n switch (event.key) {\n case 'Enter':\n // Shift enter is used to insert a new line,\n // keep the default behavior\n if (event.shiftKey) {\n break\n }\n\n // If the mention menu is open close it, but don't submit.\n if (mentionsMenuOpen) {\n // Enter is being used both to select something from the mentionsMenu, prevent the default behavior.\n event.preventDefault()\n event.stopPropagation()\n closeMentions()\n break\n }\n\n // Submit the comment if eligible for submission\n if (onSubmit && canSubmit) {\n // Enter is being used to submit the comment, prevent the default behavior.\n event.preventDefault()\n event.stopPropagation()\n onSubmit()\n }\n break\n\n case 'Escape':\n case 'ArrowLeft':\n case 'ArrowRight':\n if (mentionsMenuOpen) {\n // stop these events if the menu is open\n event.preventDefault()\n event.stopPropagation()\n closeMentions()\n }\n break\n default:\n }\n // Call parent key handler\n if (onKeyDown) onKeyDown(event)\n },\n [canSubmit, closeMentions, mentionsMenuOpen, onKeyDown, onSubmit],\n )","useMemo(() => {\n if (selection) {\n return undefined\n }\n const lastBlock = (value || EMPTY_ARRAY).slice(-1)[0]\n const lastChild = isPortableTextTextBlock(lastBlock)\n ? lastBlock.children.slice(-1)[0]\n : undefined\n if (!lastChild) {\n return undefined\n }\n const point = {\n path: [{_key: lastBlock._key}, 'children', {_key: lastChild._key}],\n offset: isPortableTextSpan(lastChild) ? lastChild.text.length : 0,\n }\n return {\n focus: point,\n anchor: point,\n }\n }, [value, selection])","{\n focus: point,\n anchor: point,\n }","() => {\n mentionsMenuRef.current?.setSearchTerm(mentionsSearchTerm)\n }","[mentionsSearchTerm]","() => {\n if (mentionsMenuOpen && selection && !isEqual(selection.anchor, selection.focus)) {\n closeMentions()\n }\n }","[mentionsMenuOpen, closeMentions, selection]","<MentionsMenu\n inputElement={inputElement}\n loading={mentionOptions.loading}\n onSelect={insertMention}\n options={mentionOptions.data || EMPTY_ARRAY}\n ref={mentionsMenuRef}\n />","loading","mentionOptions.data || EMPTY_ARRAY","<StyledPopover\n arrow={false}\n constrainSize\n content={popoverContent}\n disabled={!mentionsMenuOpen}\n fallbackPlacements={POPOVER_FALLBACK_PLACEMENTS}\n open={mentionsMenuOpen}\n placement=\"bottom\"\n ref={popoverRef}\n referenceElement={cursorElement}\n />","<NodePlugin nodes={nodes} />","<PortableTextEditable\n data-testid=\"comment-input-editable\"\n data-ui=\"EditableElement\"\n onBeforeInput={onBeforeInput}\n onBlur={onBlur}\n onFocus={onFocus}\n onKeyDown={handleKeyDown}\n ref={setInputElement}\n renderPlaceholder={renderPlaceholder}\n selection={initialSelectionAtEndOfContent}\n style={INLINE_STYLE}\n tabIndex={focusLock ? 0 : undefined}\n />","focusLock ? 0 : undefined","<div ref={setRootElement}>\n <StyledPopover\n arrow={false}\n constrainSize\n content={popoverContent}\n disabled={!mentionsMenuOpen}\n fallbackPlacements={POPOVER_FALLBACK_PLACEMENTS}\n open={mentionsMenuOpen}\n placement=\"bottom\"\n ref={popoverRef}\n referenceElement={cursorElement}\n />\n <NodePlugin nodes={nodes} />\n <PortableTextEditable\n data-testid=\"comment-input-editable\"\n data-ui=\"EditableElement\"\n onBeforeInput={onBeforeInput}\n onBlur={onBlur}\n onFocus={onFocus}\n onKeyDown={handleKeyDown}\n ref={setInputElement}\n renderPlaceholder={renderPlaceholder}\n selection={initialSelectionAtEndOfContent}\n style={INLINE_STYLE}\n tabIndex={focusLock ? 0 : undefined}\n />\n </div>","avatarSize = 1","withAvatar ? (\n <AvatarContainer>\n <CommentsAvatar user={user} size={avatarSize} />\n </AvatarContainer>\n ) : null","(e: React.MouseEvent<HTMLButtonElement>) => {\n e.stopPropagation()\n insertAtChar()\n openMentions()\n }","useCallback(\n (e: React.MouseEvent<HTMLButtonElement>) => {\n e.stopPropagation()\n insertAtChar()\n openMentions()\n },\n [insertAtChar, openMentions],\n )","<EditableWrap data-ui=\"CommentInputEditableWrap\" paddingX={1} paddingY={2}>\n <Editable\n focusLock={focusLock}\n onBlur={onBlur}\n onFocus={onFocus}\n onKeyDown={onKeyDown}\n onSubmit={onSubmit}\n placeholder={placeholder}\n renderBlock={renderBlock}\n />\n </EditableWrap>","!mentionOptions.disabled && (\n <Button\n aria-label={t('compose.mention-user-aria-label')}\n data-testid=\"comment-input-mention-button\"\n disabled={readOnly}\n icon={MentionIcon}\n mode=\"bleed\"\n type=\"button\"\n onClick={handleMentionButtonClicked}\n tooltipProps={{content: t('compose.mention-user-tooltip')}}\n />\n )","disabled","onSubmit && (\n <>\n {!mentionOptions.disabled && <ButtonDivider />}\n\n <Button\n aria-label={t('compose.send-comment-aria-label')}\n data-testid=\"comment-input-send-button\"\n disabled={!canSubmit || !hasChanges || readOnly}\n icon={SendIcon}\n mode={hasChanges && canSubmit ? 'default' : 'bleed'}\n onClick={onSubmit}\n tone={hasChanges && canSubmit ? 'primary' : 'default'}\n tooltipProps={{content: t('compose.send-comment-tooltip')}}\n />\n </>\n )","<Flex\n alignItems=\"center\"\n data-ui=\"CommentInputActions\"\n gap={1}\n justifyContent=\"flex-end\"\n padding={1}\n >\n <TooltipDelayGroupProvider>\n {!mentionOptions.disabled && (\n <Button\n aria-label={t('compose.mention-user-aria-label')}\n data-testid=\"comment-input-mention-button\"\n disabled={readOnly}\n icon={MentionIcon}\n mode=\"bleed\"\n type=\"button\"\n onClick={handleMentionButtonClicked}\n tooltipProps={{content: t('compose.mention-user-tooltip')}}\n />\n )}\n {onSubmit && (\n <>\n {!mentionOptions.disabled && <ButtonDivider />}\n\n <Button\n aria-label={t('compose.send-comment-aria-label')}\n data-testid=\"comment-input-send-button\"\n disabled={!canSubmit || !hasChanges || readOnly}\n icon={SendIcon}\n mode={hasChanges && canSubmit ? 'default' : 'bleed'}\n onClick={onSubmit}\n tone={hasChanges && canSubmit ? 'primary' : 'default'}\n tooltipProps={{content: t('compose.send-comment-tooltip')}}\n />\n </>\n )}\n </TooltipDelayGroupProvider>\n </Flex>","<VStack>\n <EditableWrap data-ui=\"CommentInputEditableWrap\" paddingX={1} paddingY={2}>\n <Editable\n focusLock={focusLock}\n onBlur={onBlur}\n onFocus={onFocus}\n onKeyDown={onKeyDown}\n onSubmit={onSubmit}\n placeholder={placeholder}\n renderBlock={renderBlock}\n />\n </EditableWrap>\n\n <Flex\n alignItems=\"center\"\n data-ui=\"CommentInputActions\"\n gap={1}\n justifyContent=\"flex-end\"\n padding={1}\n >\n <TooltipDelayGroupProvider>\n {!mentionOptions.disabled && (\n <Button\n aria-label={t('compose.mention-user-aria-label')}\n data-testid=\"comment-input-mention-button\"\n disabled={readOnly}\n icon={MentionIcon}\n mode=\"bleed\"\n type=\"button\"\n onClick={handleMentionButtonClicked}\n tooltipProps={{content: t('compose.mention-user-tooltip')}}\n />\n )}\n {onSubmit && (\n <>\n {!mentionOptions.disabled && <ButtonDivider />}\n\n <Button\n aria-label={t('compose.send-comment-aria-label')}\n data-testid=\"comment-input-send-button\"\n disabled={!canSubmit || !hasChanges || readOnly}\n icon={SendIcon}\n mode={hasChanges && canSubmit ? 'default' : 'bleed'}\n onClick={onSubmit}\n tone={hasChanges && canSubmit ? 'primary' : 'default'}\n tooltipProps={{content: t('compose.send-comment-tooltip')}}\n />\n </>\n )}\n </TooltipDelayGroupProvider>\n </Flex>\n </VStack>","<RootCard\n id=\"comment-input-root\"\n data-expand-on-focus={expandOnFocus && !canSubmit ? 'true' : 'false'}\n data-focused={focused ? 'true' : 'false'}\n flex={1}\n sizing=\"border\"\n tone={readOnly ? 'transparent' : 'default'}\n >\n <VStack>\n <EditableWrap data-ui=\"CommentInputEditableWrap\" paddingX={1} paddingY={2}>\n <Editable\n focusLock={focusLock}\n onBlur={onBlur}\n onFocus={onFocus}\n onKeyDown={onKeyDown}\n onSubmit={onSubmit}\n placeholder={placeholder}\n renderBlock={renderBlock}\n />\n </EditableWrap>\n\n <Flex\n alignItems=\"center\"\n data-ui=\"CommentInputActions\"\n gap={1}\n justifyContent=\"flex-end\"\n padding={1}\n >\n <TooltipDelayGroupProvider>\n {!mentionOptions.disabled && (\n <Button\n aria-label={t('compose.mention-user-aria-label')}\n data-testid=\"comment-input-mention-button\"\n disabled={readOnly}\n icon={MentionIcon}\n mode=\"bleed\"\n type=\"button\"\n onClick={handleMentionButtonClicked}\n tooltipProps={{content: t('compose.mention-user-tooltip')}}\n />\n )}\n {onSubmit && (\n <>\n {!mentionOptions.disabled && <ButtonDivider />}\n\n <Button\n aria-label={t('compose.send-comment-aria-label')}\n data-testid=\"comment-input-send-button\"\n disabled={!canSubmit || !hasChanges || readOnly}\n icon={SendIcon}\n mode={hasChanges && canSubmit ? 'default' : 'bleed'}\n onClick={onSubmit}\n tone={hasChanges && canSubmit ? 'primary' : 'default'}\n tooltipProps={{content: t('compose.send-comment-tooltip')}}\n />\n </>\n )}\n </TooltipDelayGroupProvider>\n </Flex>\n </VStack>\n </RootCard>","expandOnFocus && !canSubmit ? 'true' : 'false'","focused ? 'true' : 'false'","readOnly ? 'transparent' : 'default'","<Flex alignItems=\"flex-start\" gap={2}>\n {avatar}\n\n <RootCard\n id=\"comment-input-root\"\n data-expand-on-focus={expandOnFocus && !canSubmit ? 'true' : 'false'}\n data-focused={focused ? 'true' : 'false'}\n flex={1}\n sizing=\"border\"\n tone={readOnly ? 'transparent' : 'default'}\n >\n <VStack>\n <EditableWrap data-ui=\"CommentInputEditableWrap\" paddingX={1} paddingY={2}>\n <Editable\n focusLock={focusLock}\n onBlur={onBlur}\n onFocus={onFocus}\n onKeyDown={onKeyDown}\n onSubmit={onSubmit}\n placeholder={placeholder}\n renderBlock={renderBlock}\n />\n </EditableWrap>\n\n <Flex\n alignItems=\"center\"\n data-ui=\"CommentInputActions\"\n gap={1}\n justifyContent=\"flex-end\"\n padding={1}\n >\n <TooltipDelayGroupProvider>\n {!mentionOptions.disabled && (\n <Button\n aria-label={t('compose.mention-user-aria-label')}\n data-testid=\"comment-input-mention-button\"\n disabled={readOnly}\n icon={MentionIcon}\n mode=\"bleed\"\n type=\"button\"\n onClick={handleMentionButtonClicked}\n tooltipProps={{content: t('compose.mention-user-tooltip')}}\n />\n )}\n {onSubmit && (\n <>\n {!mentionOptions.disabled && <ButtonDivider />}\n\n <Button\n aria-label={t('compose.send-comment-aria-label')}\n data-testid=\"comment-input-send-button\"\n disabled={!canSubmit || !hasChanges || readOnly}\n icon={SendIcon}\n mode={hasChanges && canSubmit ? 'default' : 'bleed'}\n onClick={onSubmit}\n tone={hasChanges && canSubmit ? 'primary' : 'default'}\n tooltipProps={{content: t('compose.send-comment-tooltip')}}\n />\n </>\n )}\n </TooltipDelayGroupProvider>\n </Flex>\n </VStack>\n </RootCard>\n </Flex>","expandOnFocus = false","focusOnMount = false","hasCommentMessageValue(value)","useMemo(() => hasCommentMessageValue(value), [value])","() => {\n if (readOnly) return\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n PortableTextEditor.focus(editor)\n }","useCallback(() => {\n if (readOnly) return\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n PortableTextEditor.focus(editor)\n }, [editor, readOnly])","() => {\n setMentionsMenuOpen(false)\n setMentionsSearchTerm('')\n setSelectionAtMentionInsert(null)\n }","useCallback(() => {\n setMentionsMenuOpen(false)\n setMentionsSearchTerm('')\n setSelectionAtMentionInsert(null)\n }, [])","() => {\n if (mentionOptions?.disabled) {\n return\n }\n setMentionsMenuOpen(true)\n setMentionsSearchTerm('')\n setMentionsMenuOpen(true)\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n setSelectionAtMentionInsert(PortableTextEditor.getSelection(editor))\n }","disabled","useCallback(() => {\n if (mentionOptions?.disabled) {\n return\n }\n setMentionsMenuOpen(true)\n setMentionsSearchTerm('')\n setMentionsMenuOpen(true)\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n setSelectionAtMentionInsert(PortableTextEditor.getSelection(editor))\n }, [editor, mentionOptions?.disabled])","(event: InputEvent): void => {\n if (mentionOptions?.disabled) {\n return\n }\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n const selection = PortableTextEditor.getSelection(editor)\n const cursorOffset = selection ? selection.focus.offset : 0\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n const focusChild = PortableTextEditor.focusChild(editor)\n const focusSpan = (isPortableTextSpan(focusChild) && focusChild) || undefined\n\n const isInsertText = event.inputType === 'insertText'\n const isDeleteText = event.inputType === 'deleteContentBackward'\n const isInsertingAtChar = isInsertText && event.data === '@'\n\n const lastIndexOfAt =\n focusSpan?.text.slice(0, Math.max(0, cursorOffset)).lastIndexOf('@') || 0\n\n const isWhitespaceCharBeforeCursorPosition =\n focusSpan?.text.slice(cursorOffset - 1, cursorOffset) === ' '\n\n const filterStartsWithSpaceChar = isInsertText && event.data === ' ' && !mentionsSearchTerm\n\n // If we are inserting a '@' character - open the mentions menu and reset the search term.\n // Only do this if it is in the start of the text, or if '@' is inserted when following a whitespace char.\n if (isInsertingAtChar && (cursorOffset < 1 || isWhitespaceCharBeforeCursorPosition)) {\n openMentions()\n return\n }\n\n // If the user begins typing their filter with a space, or if they are deleting\n // characters after activation and the '@' is no longer there,\n // clear the search term and close the mentions menu.\n if (\n filterStartsWithSpaceChar ||\n (isDeleteText &&\n (focusSpan?.text.length === 1 || lastIndexOfAt === (focusSpan?.text.length || 0) - 1))\n ) {\n closeMentions()\n return\n }\n\n // Update the search term\n if (isPortableTextSpan(focusChild)) {\n // Term starts with the @ char in the value until the cursor offset\n let term = focusChild.text.slice(lastIndexOfAt + 1, cursorOffset)\n // Add the char to the mentions search term\n if (isInsertText) {\n term += event.data\n }\n // Exclude the char from the mentions search term\n if (isDeleteText) {\n term = term.slice(0, Math.max(0, term.length - 1))\n }\n // Set the updated mentions search term\n setMentionsSearchTerm(term)\n }\n }","useCallback(\n (event: InputEvent): void => {\n if (mentionOptions?.disabled) {\n return\n }\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n const selection = PortableTextEditor.getSelection(editor)\n const cursorOffset = selection ? selection.focus.offset : 0\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n const focusChild = PortableTextEditor.focusChild(editor)\n const focusSpan = (isPortableTextSpan(focusChild) && focusChild) || undefined\n\n const isInsertText = event.inputType === 'insertText'\n const isDeleteText = event.inputType === 'deleteContentBackward'\n const isInsertingAtChar = isInsertText && event.data === '@'\n\n const lastIndexOfAt =\n focusSpan?.text.slice(0, Math.max(0, cursorOffset)).lastIndexOf('@') || 0\n\n const isWhitespaceCharBeforeCursorPosition =\n focusSpan?.text.slice(cursorOffset - 1, cursorOffset) === ' '\n\n const filterStartsWithSpaceChar = isInsertText && event.data === ' ' && !mentionsSearchTerm\n\n // If we are inserting a '@' character - open the mentions menu and reset the search term.\n // Only do this if it is in the start of the text, or if '@' is inserted when following a whitespace char.\n if (isInsertingAtChar && (cursorOffset < 1 || isWhitespaceCharBeforeCursorPosition)) {\n openMentions()\n return\n }\n\n // If the user begins typing their filter with a space, or if they are deleting\n // characters after activation and the '@' is no longer there,\n // clear the search term and close the mentions menu.\n if (\n filterStartsWithSpaceChar ||\n (isDeleteText &&\n (focusSpan?.text.length === 1 || lastIndexOfAt === (focusSpan?.text.length || 0) - 1))\n ) {\n closeMentions()\n return\n }\n\n // Update the search term\n if (isPortableTextSpan(focusChild)) {\n // Term starts with the @ char in the value until the cursor offset\n let term = focusChild.text.slice(lastIndexOfAt + 1, cursorOffset)\n // Add the char to the mentions search term\n if (isInsertText) {\n term += event.data\n }\n // Exclude the char from the mentions search term\n if (isDeleteText) {\n term = term.slice(0, Math.max(0, term.length - 1))\n }\n // Set the updated mentions search term\n setMentionsSearchTerm(term)\n }\n },\n [closeMentions, editor, mentionsSearchTerm, openMentions, mentionOptions?.disabled],\n )","() => {\n setMentionsMenuOpen(true)\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n PortableTextEditor.focus(editor)\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n PortableTextEditor.insertChild(editor, editor.schemaTypes.span, {text: '@'})\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n setSelectionAtMentionInsert(PortableTextEditor.getSelection(editor))\n }","useCallback(() => {\n setMentionsMenuOpen(true)\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n PortableTextEditor.focus(editor)\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n PortableTextEditor.insertChild(editor, editor.schemaTypes.span, {text: '@'})\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n setSelectionAtMentionInsert(PortableTextEditor.getSelection(editor))\n }, [editor])","() => onMentionMenuOpenChange?.(mentionsMenuOpen)","(userId: string) => {\n const mentionSchemaType = editor.schemaTypes.inlineObjects.find((t) => t.name === 'mention')\n let mentionPath: Path | undefined\n\n const [span, spanPath] =\n (selectionAtMentionInsert &&\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n PortableTextEditor.findByPath(editor, selectionAtMentionInsert.focus.path)) ||\n []\n if (span && isPortableTextSpan(span) && spanPath && mentionSchemaType) {\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n PortableTextEditor.focus(editor)\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n const offset = PortableTextEditor.getSelection(editor)?.focus.offset\n if (typeof offset !== 'undefined') {\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n PortableTextEditor.delete(\n editor,\n {\n anchor: {path: spanPath, offset: span.text.lastIndexOf('@')},\n focus: {path: spanPath, offset},\n },\n {mode: 'selected'},\n )\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n PortableTextEditor.insertChild(editor, mentionSchemaType, {\n userId: userId,\n })\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n PortableTextEditor.insertChild(editor, editor.schemaTypes.span, {text: ' '})\n }\n }\n }","editor.schemaTypes.inlineObjects","(t) => t.name === 'mention'","useCallback(\n (userId: string) => {\n const mentionSchemaType = editor.schemaTypes.inlineObjects.find((t) => t.name === 'mention')\n let mentionPath: Path | undefined\n\n const [span, spanPath] =\n (selectionAtMentionInsert &&\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n PortableTextEditor.findByPath(editor, selectionAtMentionInsert.focus.path)) ||\n []\n if (span && isPortableTextSpan(span) && spanPath && mentionSchemaType) {\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n PortableTextEditor.focus(editor)\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n const offset = PortableTextEditor.getSelection(editor)?.focus.offset\n if (typeof offset !== 'undefined') {\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n PortableTextEditor.delete(\n editor,\n {\n anchor: {path: spanPath, offset: span.text.lastIndexOf('@')},\n focus: {path: spanPath, offset},\n },\n {mode: 'selected'},\n )\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n PortableTextEditor.insertChild(editor, mentionSchemaType, {\n userId: userId,\n })\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n PortableTextEditor.insertChild(editor, editor.schemaTypes.span, {text: ' '})\n }\n }\n },\n [editor, selectionAtMentionInsert],\n )","{\n canSubmit,\n closeMentions,\n editor,\n expandOnFocus,\n focused,\n focusEditor,\n focusOnMount,\n hasChanges,\n insertAtChar,\n insertMention,\n mentionOptions,\n mentionsMenuOpen,\n mentionsSearchTerm,\n onBeforeInput,\n openMentions,\n readOnly: Boolean(readOnly),\n value,\n }","Boolean(readOnly)","useMemo(\n (): CommentInputContextValue => ({\n canSubmit,\n closeMentions,\n editor,\n expandOnFocus,\n focused,\n focusEditor,\n focusOnMount,\n hasChanges,\n insertAtChar,\n insertMention,\n mentionOptions,\n mentionsMenuOpen,\n mentionsSearchTerm,\n onBeforeInput,\n openMentions,\n readOnly: Boolean(readOnly),\n value,\n }),\n [\n canSubmit,\n closeMentions,\n editor,\n expandOnFocus,\n focused,\n focusEditor,\n focusOnMount,\n hasChanges,\n insertAtChar,\n insertMention,\n mentionOptions,\n mentionsMenuOpen,\n mentionsSearchTerm,\n onBeforeInput,\n openMentions,\n readOnly,\n value,\n ],\n )","<CommentInputContextV2.Provider value={ctxValue}>{children}</CommentInputContextV2.Provider>","CommentInputContextV2.Provider","() => editor","[editor]","focusLock = false","renderBlock = defaultRenderBlock","value = EMPTY_ARRAY","withAvatar = true","keyGenerator()","() => {\n requestAnimationFrame(() => {\n editorRef.current?.send({type: 'focus'})\n })\n }","useCallback(() => {\n requestAnimationFrame(() => {\n editorRef.current?.send({type: 'focus'})\n })\n }, [])","() => {\n // The discarded instance flushes pending mutations during teardown; drop\n // them in `handleEvent` so a finished draft cannot overwrite the\n // consumer's cleared draft state.\n resetInstanceRef.current = true\n setEditorInstanceKey(keyGenerator())\n }","useCallback(() => {\n // The discarded instance flushes pending mutations during teardown; drop\n // them in `handleEvent` so a finished draft cannot overwrite the\n // consumer's cleared draft state.\n resetInstanceRef.current = true\n setEditorInstanceKey(keyGenerator())\n }, [])","(event: EditorEmittedEvent) => {\n // Focus the editor when ready if focusOnMount is true\n if (event.type === 'ready') {\n resetInstanceRef.current = false\n if (focusOnMount) {\n requestFocus()\n }\n }\n if (event.type === 'focused') {\n setFocused(true)\n }\n\n if (event.type === 'blurred') {\n setFocused(false)\n }\n\n // Update the comment value whenever the comment is edited by the user.\n if (event.type === 'mutation' && !resetInstanceRef.current) {\n onChange(event.value || EMPTY_ARRAY)\n }\n }","useCallback(\n (event: EditorEmittedEvent) => {\n // Focus the editor when ready if focusOnMount is true\n if (event.type === 'ready') {\n resetInstanceRef.current = false\n if (focusOnMount) {\n requestFocus()\n }\n }\n if (event.type === 'focused') {\n setFocused(true)\n }\n\n if (event.type === 'blurred') {\n setFocused(false)\n }\n\n // Update the comment value whenever the comment is edited by the user.\n if (event.type === 'mutation' && !resetInstanceRef.current) {\n onChange(event.value || EMPTY_ARRAY)\n }\n },\n [focusOnMount, onChange, requestFocus],\n )","() => {\n editorContainerRef.current?.scrollIntoView(SCROLL_INTO_VIEW_OPTIONS)\n }","useCallback(() => {\n editorContainerRef.current?.scrollIntoView(SCROLL_INTO_VIEW_OPTIONS)\n }, [])","() => {\n // Read the editor's live value directly rather than the value mirrored\n // through the debounced `mutation` event, which can lag the latest\n // keystrokes by up to the flush interval and truncate the comment when\n // the user submits without pausing.\n const currentValue = editorRef.current ? getValue(editorRef.current.getSnapshot()) : EMPTY_ARRAY\n onSubmit?.(currentValue)\n resetEditorInstance()\n requestFocus()\n scrollToEditor()\n }","useCallback(() => {\n // Read the editor's live value directly rather than the value mirrored\n // through the debounced `mutation` event, which can lag the latest\n // keystrokes by up to the flush interval and truncate the comment when\n // the user submits without pausing.\n const currentValue = editorRef.current ? getValue(editorRef.current.getSnapshot()) : EMPTY_ARRAY\n onSubmit?.(currentValue)\n resetEditorInstance()\n requestFocus()\n scrollToEditor()\n }, [onSubmit, requestFocus, resetEditorInstance, scrollToEditor])","() => {\n onDiscardConfirm()\n resetEditorInstance()\n }","useCallback(() => {\n onDiscardConfirm()\n resetEditorInstance()\n }, [onDiscardConfirm, resetEditorInstance])","{\n open: () => {\n setShowDiscardDialog(true)\n },\n close: () => {\n setShowDiscardDialog(false)\n requestFocus()\n },\n }","useMemo((): CommentDiscardDialogController => {\n return {\n open: () => {\n setShowDiscardDialog(true)\n },\n close: () => {\n setShowDiscardDialog(false)\n requestFocus()\n },\n }\n }, [requestFocus])","() => {\n return {\n focus: requestFocus,\n blur() {\n editorRef.current?.send({type: 'blur'})\n },\n scrollTo: scrollToEditor,\n reset: resetEditorInstance,\n\n discardDialogController,\n }\n }","[discardDialogController, requestFocus, resetEditorInstance, scrollToEditor]","(event: FocusEvent<HTMLDivElement>) => {\n if (!focusLock) return\n\n const target = event.target\n const innerEl = innerRef.current\n\n if (innerEl && target === preDivRef.current) {\n focusLastDescendant(innerEl)\n return\n }\n\n if (innerEl && target === postDivRef.current) {\n focusFirstDescendant(innerEl)\n }\n }","event","useCallback(\n (event: FocusEvent<HTMLDivElement>) => {\n if (!focusLock) return\n\n const target = event.target\n const innerEl = innerRef.current\n\n if (innerEl && target === preDivRef.current) {\n focusLastDescendant(innerEl)\n return\n }\n\n if (innerEl && target === postDivRef.current) {\n focusFirstDescendant(innerEl)\n }\n },\n [focusLock],\n )","showDiscardDialog && onDiscardCancel && (\n <CommentInputDiscardDialog onClose={onDiscardCancel} onConfirm={handleDiscardConfirm} />\n )","sanitySchemaToPortableTextSchema(editorSchemaType)","{\n schemaDefinition: sanitySchemaToPortableTextSchema(editorSchemaType),\n initialValue: value || EMPTY_ARRAY,\n readOnly,\n }","value || EMPTY_ARRAY","<EditorRefPlugin ref={editorRef} />","<EventListenerPlugin on={handleEvent} />","<OneLinePlugin />","<UpdateReadOnlyPlugin readOnly={readOnly ?? false} />","readOnly ?? false","<UpdateValuePlugin value={value ?? undefined} />","value ?? undefined","focusLock && <div ref={preDivRef} tabIndex={0} />","<VStack ref={innerRef}>\n <CommentInputInner\n avatarSize={avatarSize}\n currentUser={currentUser}\n focusLock={focusLock}\n onBlur={onBlur}\n onFocus={onFocus}\n onKeyDown={onKeyDown}\n onSubmit={onSubmit && handleSubmit}\n placeholder={placeholder}\n renderBlock={renderBlock}\n withAvatar={withAvatar}\n />\n </VStack>","onSubmit && handleSubmit","focusLock && <div ref={postDivRef} tabIndex={0} />","<CommentInputProvider\n expandOnFocus={expandOnFocus}\n focused={focused}\n focusOnMount={focusOnMount}\n mentionOptions={mentionOptions}\n onMentionMenuOpenChange={onMentionMenuOpenChange}\n readOnly={readOnly}\n value={value}\n >\n {focusLock && <div ref={preDivRef} tabIndex={0} />}\n\n <VStack ref={innerRef}>\n <CommentInputInner\n avatarSize={avatarSize}\n currentUser={currentUser}\n focusLock={focusLock}\n onBlur={onBlur}\n onFocus={onFocus}\n onKeyDown={onKeyDown}\n onSubmit={onSubmit && handleSubmit}\n placeholder={placeholder}\n renderBlock={renderBlock}\n withAvatar={withAvatar}\n />\n </VStack>\n\n {focusLock && <div ref={postDivRef} tabIndex={0} />}\n </CommentInputProvider>","<EditorProvider\n key={editorInstanceKey}\n initialConfig={{\n schemaDefinition: sanitySchemaToPortableTextSchema(editorSchemaType),\n initialValue: value || EMPTY_ARRAY,\n readOnly,\n }}\n >\n <EditorRefPlugin ref={editorRef} />\n <EventListenerPlugin on={handleEvent} />\n <OneLinePlugin />\n <UpdateReadOnlyPlugin readOnly={readOnly ?? false} />\n <UpdateValuePlugin value={value ?? undefined} />\n <CommentInputProvider\n expandOnFocus={expandOnFocus}\n focused={focused}\n focusOnMount={focusOnMount}\n mentionOptions={mentionOptions}\n onMentionMenuOpenChange={onMentionMenuOpenChange}\n readOnly={readOnly}\n value={value}\n >\n {focusLock && <div ref={preDivRef} tabIndex={0} />}\n\n <VStack ref={innerRef}>\n <CommentInputInner\n avatarSize={avatarSize}\n currentUser={currentUser}\n focusLock={focusLock}\n onBlur={onBlur}\n onFocus={onFocus}\n onKeyDown={onKeyDown}\n onSubmit={onSubmit && handleSubmit}\n placeholder={placeholder}\n renderBlock={renderBlock}\n withAvatar={withAvatar}\n />\n </VStack>\n\n {focusLock && <div ref={postDivRef} tabIndex={0} />}\n </CommentInputProvider>\n </EditorProvider>","<VStack ref={editorContainerRef} data-testid=\"comment-input\" onFocus={handleFocus}>\n <EditorProvider\n key={editorInstanceKey}\n initialConfig={{\n schemaDefinition: sanitySchemaToPortableTextSchema(editorSchemaType),\n initialValue: value || EMPTY_ARRAY,\n readOnly,\n }}\n >\n <EditorRefPlugin ref={editorRef} />\n <EventListenerPlugin on={handleEvent} />\n <OneLinePlugin />\n <UpdateReadOnlyPlugin readOnly={readOnly ?? false} />\n <UpdateValuePlugin value={value ?? undefined} />\n <CommentInputProvider\n expandOnFocus={expandOnFocus}\n focused={focused}\n focusOnMount={focusOnMount}\n mentionOptions={mentionOptions}\n onMentionMenuOpenChange={onMentionMenuOpenChange}\n readOnly={readOnly}\n value={value}\n >\n {focusLock && <div ref={preDivRef} tabIndex={0} />}\n\n <VStack ref={innerRef}>\n <CommentInputInner\n avatarSize={avatarSize}\n currentUser={currentUser}\n focusLock={focusLock}\n onBlur={onBlur}\n onFocus={onFocus}\n onKeyDown={onKeyDown}\n onSubmit={onSubmit && handleSubmit}\n placeholder={placeholder}\n renderBlock={renderBlock}\n withAvatar={withAvatar}\n />\n </VStack>\n\n {focusLock && <div ref={postDivRef} tabIndex={0} />}\n </CommentInputProvider>\n </EditorProvider>\n </VStack>","<>\n {showDiscardDialog && onDiscardCancel && (\n <CommentInputDiscardDialog onClose={onDiscardCancel} onConfirm={handleDiscardConfirm} />\n )}\n\n <VStack ref={editorContainerRef} data-testid=\"comment-input\" onFocus={handleFocus}>\n <EditorProvider\n key={editorInstanceKey}\n initialConfig={{\n schemaDefinition: sanitySchemaToPortableTextSchema(editorSchemaType),\n initialValue: value || EMPTY_ARRAY,\n readOnly,\n }}\n >\n <EditorRefPlugin ref={editorRef} />\n <EventListenerPlugin on={handleEvent} />\n <OneLinePlugin />\n <UpdateReadOnlyPlugin readOnly={readOnly ?? false} />\n <UpdateValuePlugin value={value ?? undefined} />\n <CommentInputProvider\n expandOnFocus={expandOnFocus}\n focused={focused}\n focusOnMount={focusOnMount}\n mentionOptions={mentionOptions}\n onMentionMenuOpenChange={onMentionMenuOpenChange}\n readOnly={readOnly}\n value={value}\n >\n {focusLock && <div ref={preDivRef} tabIndex={0} />}\n\n <VStack ref={innerRef}>\n <CommentInputInner\n avatarSize={avatarSize}\n currentUser={currentUser}\n focusLock={focusLock}\n onBlur={onBlur}\n onFocus={onFocus}\n onKeyDown={onKeyDown}\n onSubmit={onSubmit && handleSubmit}\n placeholder={placeholder}\n renderBlock={renderBlock}\n withAvatar={withAvatar}\n />\n </VStack>\n\n {focusLock && <div ref={postDivRef} tabIndex={0} />}\n </CommentInputProvider>\n </EditorProvider>\n </VStack>\n </>","() => {\n editor.send({\n type: 'update readOnly',\n readOnly: props.readOnly,\n })\n }","[editor, props.readOnly]","readOnly","() => {\n editor.send({\n type: 'update value',\n value: props.value,\n })\n }","[editor, props.value]","value"],"sources":["../src/core/comments-v2/hooks/useComments.ts","../src/core/comments-v2/hooks/useCommentsScroll.ts","../src/core/comments-v2/components/pte/blocks/NormalBlock.tsx","../src/core/comments-v2/components/pte/config.ts","../src/core/comments-v2/components/pte/comment-input/CommentInputDiscardDialog.tsx","../src/core/comments-v2/components/avatars/CommentsAvatar.tsx","../src/core/comments-v2/components/icons/MentionIcon.tsx","../src/core/comments-v2/components/icons/SendIcon.tsx","../src/core/comments-v2/components/mentions/MentionsMenuItem.tsx","../src/core/comments-v2/components/mentions/MentionsMenu.tsx","../src/core/comments-v2/components/pte/blocks/MentionInlineBlock.tsx","../src/core/comments-v2/components/pte/comment-input/useCommentInput.ts","../src/core/comments-v2/components/pte/comment-input/useCursorElement.ts","../src/core/comments-v2/components/pte/comment-input/Editable.tsx","../src/core/comments-v2/components/pte/comment-input/CommentInputInner.tsx","../src/core/comments-v2/components/pte/comment-input/CommentInputProvider.tsx","../src/core/comments-v2/components/pte/comment-input/CommentInput.tsx"],"sourcesContent":["import {useContext} from 'react'\nimport {CommentsContextV2} from 'sanity/_singletons'\n\nimport {type CommentsContextValue} from '../context/comments/types'\n\n/**\n * @beta\n * @hidden\n */\nexport function useComments(): CommentsContextValue {\n const value = useContext(CommentsContextV2)\n\n if (!value) {\n throw new Error('useComments must be used within a CommentsProvider')\n }\n\n return value\n}\n","import {useCallback, useEffect, useMemo, useState} from 'react'\nimport scrollIntoViewIfNeeded, {type StandardBehaviorOptions} from 'scroll-into-view-if-needed'\n\nconst BASE_SCROLL_OPTIONS: StandardBehaviorOptions = {\n behavior: 'smooth',\n inline: 'center',\n scrollMode: 'if-needed',\n}\n\nconst GROUP_SCROLL_OPTIONS: StandardBehaviorOptions = {\n ...BASE_SCROLL_OPTIONS,\n block: 'start',\n}\n\nconst INLINE_COMMENT_SCROLL_OPTIONS: StandardBehaviorOptions = {\n ...BASE_SCROLL_OPTIONS,\n block: 'center',\n}\n\nconst SCROLL_TO_FIELD_OPTIONS: StandardBehaviorOptions = {\n ...BASE_SCROLL_OPTIONS,\n block: 'center',\n}\n\nconst SCROLL_TO_COMMENT_OPTIONS: StandardBehaviorOptions = {\n ...BASE_SCROLL_OPTIONS,\n block: 'center',\n}\n\nconst SCROLL_OPTIONS_BY_TYPE: Record<ScrollTargetTypes, StandardBehaviorOptions> = {\n 'comment': SCROLL_TO_COMMENT_OPTIONS,\n 'field': SCROLL_TO_FIELD_OPTIONS,\n 'group': GROUP_SCROLL_OPTIONS,\n 'inline-comment': INLINE_COMMENT_SCROLL_OPTIONS,\n}\n\n/**\n * A utility function that can be used to generate a valid attribute value\n * based on the given ID.\n *\n * Generate a value that can be used as an attribute value in HTML based\n * on the given ID. This is needed because, when we use the path of a field\n * as a data attribute value, we need to escape the value so that it can be\n * queried using `querySelector`.\n *\n * Example:\n *\n * ```js\n * const validId = generateValidAttrValue('[field[_key==\"title\"]')\n *\n * return <div data-field-id={validId}>...</div>\n * ```\n */\nfunction generateValidAttrValue(id: string): string {\n const symbolsToRemove = /[[\\]_\"_=.]/g\n\n const result = id.replace(symbolsToRemove, '')\n\n return result\n}\n\nexport function applyCommentIdAttr(id: string): Record<'data-comments-comment-id', string> {\n return {\n 'data-comments-comment-id': generateValidAttrValue(id),\n }\n}\n\nexport function applyCommentsFieldAttr(id: string): Record<'data-comments-field-id', string> {\n return {\n 'data-comments-field-id': generateValidAttrValue(id),\n }\n}\n\nexport function applyCommentsGroupAttr(id: string): Record<'data-comments-group-id', string> {\n return {\n 'data-comments-group-id': generateValidAttrValue(id),\n }\n}\n\nexport function applyInlineCommentIdAttr(\n id: string,\n): Record<'data-comments-inline-comment-id', string> {\n return {\n 'data-comments-inline-comment-id': generateValidAttrValue(id),\n }\n}\n\ninterface CommentsScrollHookValue {\n /**\n * Scroll to the comment with the given ID.\n */\n scrollToComment: (commentId: string) => void\n /**\n * Scroll to the field with the given ID.\n */\n scrollToField: (fieldId: string) => void\n /**\n * Scroll to the group with the given ID.\n */\n scrollToGroup: (groupId: string) => void\n /**\n * Scroll to the inline comment with the given ID.\n */\n scrollToInlineComment: (commentId: string) => void\n}\n\ninterface CommentsScrollHookOptions {\n boundaryElement?: HTMLElement | null\n}\n\ntype ScrollTargetTypes = 'comment' | 'field' | 'group' | 'inline-comment'\ninterface ScrollTarget {\n type: ScrollTargetTypes\n id: string\n}\n\nexport function useCommentsScroll(opts?: CommentsScrollHookOptions): CommentsScrollHookValue {\n const {boundaryElement} = opts || {}\n const [scrollTarget, setScrollTarget] = useState<ScrollTarget | null>(null)\n\n const scrollOpts: StandardBehaviorOptions = useMemo(() => {\n const options = SCROLL_OPTIONS_BY_TYPE[scrollTarget?.type || 'comment']\n\n // Only apply boundary for 'comment' type scrolls (scrolling within inspector panel)\n // Field, group, and inline-comment scrolls target the document pane and shouldn't be bounded\n const shouldApplyBoundary = scrollTarget?.type === 'comment'\n\n return {\n ...options,\n boundary: shouldApplyBoundary ? boundaryElement : undefined,\n }\n }, [boundaryElement, scrollTarget?.type])\n\n const handleScrollToComment = useCallback((commentId: string) => {\n setScrollTarget({type: 'comment', id: commentId})\n }, [])\n\n const handleScrollToGroup = useCallback((threadId: string) => {\n setScrollTarget({type: 'group', id: threadId})\n }, [])\n\n const handleScrollToField = useCallback((fieldPath: string) => {\n setScrollTarget({type: 'field', id: fieldPath})\n }, [])\n\n const handleScrollToInlineComment = useCallback((commentId: string) => {\n setScrollTarget({type: 'inline-comment', id: commentId})\n }, [])\n\n useEffect(() => {\n const raf = requestAnimationFrame(() => {\n if (!scrollTarget) return\n\n const {type, id} = scrollTarget\n\n const element = document?.querySelector(\n `[data-comments-${type}-id=\"${generateValidAttrValue(id)}\"]`,\n )\n\n if (element) {\n scrollIntoViewIfNeeded(element, scrollOpts)\n }\n })\n\n return () => {\n cancelAnimationFrame(raf)\n }\n }, [scrollOpts, scrollTarget])\n\n const value = useMemo(\n (): CommentsScrollHookValue => ({\n scrollToComment: handleScrollToComment,\n scrollToField: handleScrollToField,\n scrollToGroup: handleScrollToGroup,\n scrollToInlineComment: handleScrollToInlineComment,\n }),\n [handleScrollToComment, handleScrollToField, handleScrollToGroup, handleScrollToInlineComment],\n )\n\n return value\n}\n","import {type ReactNode} from 'react'\nimport {styled} from 'styled-components'\nimport {Text} from 'ui5'\n\nconst NormalText = styled(Text)`\n word-break: break-word;\n`\n\ninterface NormalBlockProps {\n children: ReactNode\n}\n\nexport function NormalBlock(props: NormalBlockProps): React.JSX.Element {\n const {children} = props\n\n return (\n <NormalText size={1} forwardedAs=\"div\" trim={true}>\n {children}\n </NormalText>\n )\n}\n","import {Schema} from '@sanity/schema'\nimport {defineArrayMember, defineField} from '@sanity/types'\n\nconst mentionObject = defineField({\n name: 'mention',\n type: 'object',\n fields: [\n {\n name: 'userId',\n type: 'string',\n },\n ],\n})\n\nconst blockType = defineField({\n type: 'block',\n name: 'block',\n of: [mentionObject],\n marks: {\n annotations: [],\n },\n styles: [{title: 'Normal', value: 'normal'}],\n lists: [],\n})\n\nconst portableTextType = defineArrayMember({\n type: 'array',\n name: 'body',\n of: [blockType],\n})\n\nconst schema = Schema.compile({\n name: 'comments',\n types: [portableTextType],\n})\n\nexport const editorSchemaType = schema.get('body')\n","import {DialogProvider, ThemeColorProvider} from '@sanity/ui'\nimport {type MouseEvent, useCallback} from 'react'\nimport {Text} from 'ui5'\n\nimport {Dialog} from '../../../../../ui-components/dialog/Dialog'\nimport {useTranslation} from '../../../../i18n/hooks/useTranslation'\nimport {commentsLocaleNamespace} from '../../../i18n'\n\nconst Z_OFFSET = 9999999 // Change to appropriate z-offset\n\n/**\n * @beta\n * @hidden\n */\nexport interface CommentInputDiscardDialogProps {\n onClose: () => void\n onConfirm: () => void\n}\n\n/**\n * @beta\n * @hidden\n */\nexport function CommentInputDiscardDialog(props: CommentInputDiscardDialogProps) {\n const {t} = useTranslation(commentsLocaleNamespace)\n const {onClose, onConfirm} = props\n\n const handleCancelClick = useCallback(\n (e: MouseEvent<HTMLButtonElement>) => {\n e.stopPropagation()\n onClose()\n },\n [onClose],\n )\n\n const handleConfirmClick = useCallback(\n (e: MouseEvent<HTMLButtonElement>) => {\n e.stopPropagation()\n onConfirm()\n },\n [onConfirm],\n )\n\n // The ThemeColorProvider is needed to make sure that the backdrop of the dialog not\n // inherits the tone of parent color providers.\n // The PortalProvider and DialogProvider is needed to make sure that the dialog is\n // rendered fullscreen and not scoped to the form view.\n return (\n <ThemeColorProvider tone=\"default\">\n <DialogProvider zOffset={Z_OFFSET}>\n <Dialog\n header={t('discard.header')}\n id=\"discard-comment-dialog\"\n onClose={onClose}\n width={0}\n onClickOutside={onClose}\n footer={{\n cancelButton: {\n onClick: handleCancelClick,\n },\n confirmButton: {\n onClick: handleConfirmClick,\n text: t('discard.button-confirm'),\n tone: 'critical',\n },\n }}\n >\n <Text size={1} as=\"div\" trim={true}>\n {t('discard.text')}\n </Text>\n </Dialog>\n </DialogProvider>\n </ThemeColorProvider>\n )\n}\n","import {type User} from '@sanity/types'\nimport {Avatar, type AvatarProps} from '@sanity/ui'\nimport {useMemo} from 'react'\nimport {styled} from 'styled-components'\n\nconst StyledAvatar = styled(Avatar)`\n svg > ellipse {\n stroke: transparent;\n }\n`\n\nconst SYMBOLS = /[^\\p{Alpha}\\p{White_Space}]/gu\nconst WHITESPACE = /\\p{White_Space}+/u\n\nfunction nameToInitials(fullName: string) {\n const namesArray = fullName.replace(SYMBOLS, '').split(WHITESPACE)\n\n if (namesArray.length === 1) {\n return `${namesArray[0].charAt(0)}`.toUpperCase()\n }\n\n return `${namesArray[0].charAt(0)}${namesArray[namesArray.length - 1].charAt(0)}`\n}\n\ninterface CommentsAvatarProps extends AvatarProps {\n user: User | undefined | null\n}\n\nexport function CommentsAvatar(props: CommentsAvatarProps) {\n const {user: userProp, ...restProps} = props\n const user = userProp as User\n const initials = useMemo(() => nameToInitials(user?.displayName || ''), [user?.displayName])\n\n if (!user) return <StyledAvatar {...restProps} />\n\n return (\n <StyledAvatar\n initials={initials}\n src={user?.imageUrl}\n title={user?.displayName}\n {...restProps}\n />\n )\n}\n","import {type RefAttributes, type SVGProps} from 'react'\n\nexport function MentionIcon(props: SVGProps<SVGSVGElement> & RefAttributes<SVGSVGElement>) {\n const {ref, ...rest} = props\n return (\n <svg\n data-sanity-icon=\"mention\"\n fill=\"none\"\n height=\"1em\"\n ref={ref}\n viewBox=\"0 0 25 25\"\n width=\"1em\"\n xmlns=\"http://www.w3.org/2000/svg\"\n {...rest}\n >\n <path\n d=\"M16.6633 18.9383C15.539 19.6562 14.2034 20.0723 12.7705 20.0723C8.77022 20.0723 5.52734 16.8294 5.52734 12.8291C5.52734 8.82881 8.77022 5.58594 12.7705 5.58594C16.7708 5.58594 20.0137 8.82881 20.0137 12.8291C20.0137 13.6623 19.8249 14.7093 19.6141 15.2077C19.5578 15.3408 19.479 15.4845 19.3936 15.6238C19.0955 16.1106 18.5507 16.3721 17.9807 16.4018V16.4018C16.8271 16.462 15.8588 15.5428 15.8588 14.3877V9.27302\"\n stroke=\"currentColor\"\n strokeWidth={1.2}\n strokeLinejoin=\"round\"\n />\n <circle cx=\"12.5732\" cy=\"12.8291\" r=\"3.08691\" stroke=\"currentColor\" strokeWidth={1.2} />\n </svg>\n )\n}\n","import {type RefAttributes, type SVGProps} from 'react'\n\nexport function SendIcon(props: SVGProps<SVGSVGElement> & RefAttributes<SVGSVGElement>) {\n const {ref, ...rest} = props\n return (\n <svg\n data-sanity-icon=\"send\"\n fill=\"none\"\n height=\"1em\"\n ref={ref}\n viewBox=\"0 0 25 25\"\n width=\"1em\"\n xmlns=\"http://www.w3.org/2000/svg\"\n {...rest}\n >\n <path\n clipRule=\"evenodd\"\n d=\"M21.1602 12.5L7.16016 19.5V14.8765L13.6656 12.4989L7.16016 9.97149L7.16016 5.5L21.1602 12.5Z\"\n stroke=\"currentColor\"\n strokeWidth={1.2}\n strokeLinejoin=\"round\"\n />\n </svg>\n )\n}\n","import {Badge, Card, TextSkeleton} from '@sanity/ui'\nimport {type CSSProperties, useCallback} from 'react'\nimport {styled} from 'styled-components'\nimport {Text, Box, Flex} from 'ui5'\n\nimport {type UserWithPermission} from '../../../hooks/useUserListWithPermissions'\nimport {useTranslation} from '../../../i18n/hooks/useTranslation'\nimport {useUser} from '../../../store/user/hooks'\nimport {commentsLocaleNamespace} from '../../i18n'\nimport {CommentsAvatar} from '../avatars/CommentsAvatar'\n\nconst InnerFlex = styled(Flex)``\n\nconst SKELETON_INLINE_STYLE: CSSProperties = {width: '50%'}\n\ninterface MentionsItemProps {\n user: UserWithPermission\n onSelect: (userId: string) => void\n}\n\nexport function MentionsMenuItem(props: MentionsItemProps) {\n const {user, onSelect} = props\n const [loadedUser] = useUser(user.id)\n const {t} = useTranslation(commentsLocaleNamespace)\n\n const avatar = <CommentsAvatar user={loadedUser} status={user.granted ? undefined : 'inactive'} />\n\n const text = loadedUser ? (\n <Text size={1} truncate={1} title={loadedUser.displayName} as=\"div\" trim={true}>\n {loadedUser.displayName}\n </Text>\n ) : (\n <TextSkeleton size={1} style={SKELETON_INLINE_STYLE} />\n )\n\n const handleSelect = useCallback(() => {\n onSelect(user.id)\n }, [onSelect, user.id])\n\n return (\n <Card as=\"button\" disabled={!user.granted} onClick={handleSelect} padding={2} radius={2}>\n <Flex alignItems=\"center\" gap={3}>\n <InnerFlex alignItems=\"center\" gap={2} flexBasis=\"0%\" flexGrow={1}>\n {avatar}\n <Box>{text}</Box>\n </InnerFlex>\n\n {!user.granted && <Badge fontSize={1}>{t('mentions.unauthorized-user')}</Badge>}\n </Flex>\n </Card>\n )\n}\n","import deburr from 'lodash-es/deburr.js'\nimport {\n type Ref,\n useCallback,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n type RefAttributes,\n} from 'react'\nimport {styled} from 'styled-components'\nimport {Text, Box, Flex, VStack} from 'ui5'\n\nimport {CommandList} from '../../../components/commandList/CommandList'\nimport {type CommandListHandle} from '../../../components/commandList/types'\nimport {LoadingBlock} from '../../../components/loadingBlock/LoadingBlock'\nimport {type UserWithPermission} from '../../../hooks/useUserListWithPermissions'\nimport {useTranslation} from '../../../i18n/hooks/useTranslation'\nimport {commentsLocaleNamespace} from '../../i18n'\nimport {MentionsMenuItem} from './MentionsMenuItem'\n\nconst EMPTY_ARRAY: UserWithPermission[] = []\n\nconst Root = styled(VStack)({\n maxWidth: '220px', // todo: improve\n})\n\nconst ITEM_HEIGHT = 41\nconst LIST_PADDING = 4\nconst MAX_ITEMS = 7\n\nconst FlexWrap = styled(Flex)({\n maxHeight: ITEM_HEIGHT * MAX_ITEMS + LIST_PADDING * 2 + ITEM_HEIGHT / 2,\n})\n\nexport interface MentionsMenuHandle {\n setSearchTerm: (term: string) => void\n}\ninterface MentionsMenuProps {\n loading: boolean\n inputElement?: HTMLDivElement | null\n onSelect: (userId: string) => void\n options: UserWithPermission[] | null\n}\n\nexport function MentionsMenu(props: MentionsMenuProps & RefAttributes<MentionsMenuHandle>) {\n const {t} = useTranslation(commentsLocaleNamespace)\n const {ref, loading, onSelect, options = [], inputElement} = props\n const [searchTerm, setSearchTerm] = useState<string>('')\n const commandListRef = useRef<CommandListHandle>(null)\n\n useImperativeHandle(ref, () => {\n return {\n setSearchTerm(term: string) {\n setSearchTerm(term)\n },\n }\n }, [])\n\n const renderItem = useCallback(\n (itemProps: UserWithPermission) => {\n return <MentionsMenuItem user={itemProps} onSelect={onSelect} />\n },\n [onSelect],\n )\n\n const getItemDisabled = useCallback(\n (index: number) => {\n return !options?.[index]?.granted\n },\n [options],\n )\n\n const filteredOptions = useMemo(() => {\n if (!searchTerm) return options || EMPTY_ARRAY\n\n // We deburr the search term and the display names so that when searching\n // for e.g \"bjorge\" we also get results for \"bjørge\"\n const deburredSearchTerm = deburr(searchTerm).toLocaleLowerCase()\n\n const deburredOptions = options?.map((option) => ({\n ...option,\n displayName: deburr(option.displayName || '').toLocaleLowerCase(),\n }))\n\n const filtered = deburredOptions\n ?.filter((option) => {\n return option?.displayName?.includes(deburredSearchTerm)\n })\n // Sort by whether the displayName starts with the search term to get more relevant results first\n ?.sort((a, b) => {\n const matchA = a.displayName?.startsWith(deburredSearchTerm)\n const matchB = b.displayName?.startsWith(deburredSearchTerm)\n\n if (matchA && !matchB) return -1\n if (!matchA && matchB) return 1\n\n return 0\n })\n\n return filtered || EMPTY_ARRAY\n }, [options, searchTerm])\n\n if (loading) {\n return (\n <Root>\n <LoadingBlock showText />\n </Root>\n )\n }\n\n // In this case the input element is the actual content editable HTMLDivElement from the PTE.\n // Typecast it to an input element to make the CommandList component happy.\n const _inputElement = inputElement ? (inputElement as HTMLInputElement) : undefined\n\n return (\n <Flex flexDirection=\"column\" height=\"100%\" data-testid=\"comments-mentions-menu\">\n {filteredOptions.length === 0 && (\n <Box padding={5}>\n <Text align=\"center\" size={1} muted as=\"div\" trim={true}>\n {t('mentions.no-users-found')}\n </Text>\n </Box>\n )}\n\n {filteredOptions.length > 0 && (\n <FlexWrap flexDirection=\"column\" flexBasis=\"0%\" flexGrow={1} overflow=\"hidden\">\n <CommandList\n activeItemDataAttr=\"data-hovered\"\n ariaLabel={t('mentions.user-list-aria-label')}\n fixedHeight\n getItemDisabled={getItemDisabled}\n inputElement={_inputElement}\n itemHeight={41}\n items={filteredOptions}\n padding={1}\n ref={commandListRef}\n renderItem={renderItem}\n />\n </FlexWrap>\n )}\n </Flex>\n )\n}\n","import {TextSkeleton} from '@sanity/ui'\nimport {css, styled} from 'styled-components'\nimport {Text, Flex} from 'ui5'\n\nimport {Tooltip} from '../../../../../ui-components/tooltip/Tooltip'\nimport {useCurrentUser, useUser} from '../../../../store/user/hooks'\nimport {CommentsAvatar} from '../../avatars/CommentsAvatar'\n\nconst Span = styled.span(({theme}) => {\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n const {regular} = theme.sanity.fonts?.text.weights || {}\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n const {hovered} = theme.sanity.color?.card || {}\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n const {bg} = theme.sanity.color.selectable?.caution.pressed || {}\n\n return css`\n font-weight: ${regular};\n color: var(--card-link-fg-color);\n border-radius: 2px;\n background-color: ${hovered.bg};\n padding: 1px;\n box-sizing: border-box;\n\n &[data-active='true'] {\n background-color: ${bg};\n }\n `\n})\n\ninterface MentionInlineBlockProps {\n userId: string\n selected: boolean\n}\n\nexport function MentionInlineBlock(props: MentionInlineBlockProps) {\n const {selected, userId} = props\n const [user, loading] = useUser(userId)\n const currentUser = useCurrentUser()\n\n if (!user || loading)\n return (\n <TextSkeleton\n data-testid=\"comment-mentions-loading-skeleton\"\n style={{width: '10ch'}}\n size={0}\n muted\n radius={1}\n animated\n />\n )\n\n return (\n <Tooltip\n portal\n content={\n <Flex alignItems=\"center\" gap={2}>\n <Flex>\n <CommentsAvatar user={user} />\n </Flex>\n\n <Text size={1} as=\"div\" trim={true}>\n {user.displayName}\n </Text>\n </Flex>\n }\n >\n <Span data-selected={selected} data-active={currentUser?.sanityUserId === userId}>\n @{user.displayName}\n </Span>\n </Tooltip>\n )\n}\n","import {useContext} from 'react'\nimport {CommentInputContextV2} from 'sanity/_singletons'\n\nimport {type CommentInputContextValue} from './CommentInputProvider'\n\nexport function useCommentInput(): CommentInputContextValue {\n const ctx = useContext(CommentInputContextV2)\n\n if (!ctx) {\n throw new Error('useCommentInputContext must be used within a CommentInputProvider')\n }\n\n return ctx\n}\n","import {useCallback, useEffect, useMemo, useState} from 'react'\n\nconst EVENT_LISTENER_OPTIONS: AddEventListenerOptions = {passive: true}\n\ninterface CursorElementHookOptions {\n disabled: boolean\n rootElement: HTMLElement | null\n}\n\nexport function useCursorElement(opts: CursorElementHookOptions): HTMLElement | null {\n const {disabled, rootElement} = opts\n const [cursorRect, setCursorRect] = useState<DOMRect | null>(null)\n\n const cursorElement = useMemo(() => {\n if (!cursorRect) {\n return null\n }\n return {\n getBoundingClientRect: () => {\n return cursorRect\n },\n } as HTMLElement\n }, [cursorRect])\n\n const handleSelectionChange = useCallback(() => {\n if (disabled) {\n setCursorRect(null)\n return\n }\n\n const sel = window.getSelection()\n\n if (!sel || !sel.isCollapsed || sel.rangeCount === 0) return\n\n const range = sel.getRangeAt(0)\n const isWithinRoot = rootElement?.contains(range.commonAncestorContainer)\n\n if (!isWithinRoot) {\n setCursorRect(null)\n return\n }\n const rect = range?.getBoundingClientRect()\n if (rect) {\n setCursorRect(rect)\n }\n }, [disabled, rootElement])\n\n useEffect(() => {\n document.addEventListener('selectionchange', handleSelectionChange, EVENT_LISTENER_OPTIONS)\n\n return () => {\n document.removeEventListener('selectionchange', handleSelectionChange)\n }\n }, [handleSelectionChange])\n\n return cursorElement\n}\n","import {\n defineInlineObject,\n defineTextBlock,\n type EditorSelection,\n PortableTextEditable,\n usePortableTextEditorSelection,\n} from '@portabletext/editor'\nimport {NodePlugin} from '@portabletext/editor/plugins'\nimport {isPortableTextSpan, isPortableTextTextBlock} from '@sanity/types'\nimport {useClickOutsideEvent} from '@sanity/ui'\nimport {getTheme_v2} from '@sanity/ui/theme'\nimport {dequal as isEqual} from 'dequal/lite'\nimport {type KeyboardEvent, useCallback, useEffect, useMemo, useRef, useState} from 'react'\nimport {css, styled} from 'styled-components'\n\nimport {Popover, type PopoverProps} from '../../../../../ui-components/popover/Popover'\nimport {useTranslation} from '../../../../i18n/hooks/useTranslation'\nimport {commentsLocaleNamespace} from '../../../i18n'\nimport {MentionsMenu, type MentionsMenuHandle} from '../../mentions/MentionsMenu'\nimport {MentionInlineBlock} from '../blocks/MentionInlineBlock'\nimport {type CommentInputRenderBlock} from './CommentInput'\nimport {useCommentInput} from './useCommentInput'\nimport {useCursorElement} from './useCursorElement'\n\nconst POPOVER_FALLBACK_PLACEMENTS: PopoverProps['fallbackPlacements'] = ['bottom', 'top']\nconst INLINE_STYLE: React.CSSProperties = {outline: 'none'}\nconst EMPTY_ARRAY: [] = []\n\nconst PlaceholderWrapper = styled.span((props) => {\n const {color} = getTheme_v2(props.theme)\n return css`\n color: ${color.input.default.enabled.placeholder};\n overflow: hidden;\n text-overflow: ellipsis;\n text-wrap: nowrap;\n display: block;\n `\n})\n\nconst StyledPopover = styled(Popover)(({theme}) => {\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n const {space, radius} = theme.sanity\n\n return css`\n &[data-placement='bottom'] {\n transform: translateY(${space[1]}px);\n }\n\n &[data-placement='top'] {\n transform: translateY(-${space[1]}px);\n }\n\n [data-ui='Popover__wrapper'] {\n border-radius: ${radius[3]}px;\n display: flex;\n flex-direction: column;\n overflow: clip;\n overflow: hidden;\n position: relative;\n width: 300px; // todo: improve\n }\n `\n})\n\ninterface EditableProps {\n focusLock?: boolean\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n onBlur?: (e: React.FormEvent<HTMLDivElement>) => void\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n onFocus?: (e: React.FormEvent<HTMLDivElement>) => void\n onKeyDown?: (e: React.KeyboardEvent) => void\n onSubmit?: () => void\n placeholder?: React.ReactNode\n renderBlock: CommentInputRenderBlock\n}\n\ninterface EditableHandle {\n setShowMentionOptions: (show: boolean) => void\n}\n\nexport function Editable(props: EditableProps) {\n const {t} = useTranslation(commentsLocaleNamespace)\n const {\n focusLock,\n onFocus,\n onBlur,\n onKeyDown,\n onSubmit,\n placeholder = t('compose.create-comment-placeholder'),\n renderBlock,\n } = props\n const popoverRef = useRef<HTMLDivElement | null>(null)\n const [rootElement, setRootElement] = useState<HTMLDivElement | null>(null)\n const [inputElement, setInputElement] = useState<HTMLDivElement | null>(null)\n const mentionsMenuRef = useRef<MentionsMenuHandle | null>(null)\n\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n const selection = usePortableTextEditorSelection()\n\n const {\n canSubmit,\n closeMentions,\n insertMention,\n mentionOptions,\n mentionsMenuOpen,\n mentionsSearchTerm,\n onBeforeInput,\n value,\n } = useCommentInput()\n\n const cursorElement = useCursorElement({\n disabled: !mentionsMenuOpen,\n rootElement: rootElement,\n })\n\n const renderPlaceholder = useCallback(\n () => <PlaceholderWrapper>{placeholder}</PlaceholderWrapper>,\n [placeholder],\n )\n\n const nodes = useMemo(\n () => [\n defineTextBlock({\n type: 'block',\n render: (blockProps) => (\n <div {...blockProps.attributes}>{renderBlock({children: blockProps.children})}</div>\n ),\n }),\n defineInlineObject({\n type: 'mention',\n render: (mentionProps) =>\n mentionProps.node.userId ? (\n <span {...mentionProps.attributes}>\n {/* Carries the engine's caret spacer; dropping this loses cursor placement around the mention. */}\n {mentionProps.children}\n {/* `draggable` makes the mention movable and keeps its text\n unselectable (a draggable element starts a drag instead of a\n text selection), matching the legacy pipeline's wrapper. */}\n <span draggable={!mentionProps.readOnly} style={{display: 'inline-block'}}>\n <MentionInlineBlock\n selected={mentionProps.selected}\n userId={mentionProps.node.userId as string}\n />\n </span>\n </span>\n ) : (\n mentionProps.renderDefault(mentionProps)\n ),\n }),\n ],\n [renderBlock],\n )\n\n useClickOutsideEvent(mentionsMenuOpen && closeMentions, () => [popoverRef.current])\n\n const handleKeyDown = useCallback(\n (event: KeyboardEvent) => {\n switch (event.key) {\n case 'Enter':\n // Shift enter is used to insert a new line,\n // keep the default behavior\n if (event.shiftKey) {\n break\n }\n\n // If the mention menu is open close it, but don't submit.\n if (mentionsMenuOpen) {\n // Enter is being used both to select something from the mentionsMenu, prevent the default behavior.\n event.preventDefault()\n event.stopPropagation()\n closeMentions()\n break\n }\n\n // Submit the comment if eligible for submission\n if (onSubmit && canSubmit) {\n // Enter is being used to submit the comment, prevent the default behavior.\n event.preventDefault()\n event.stopPropagation()\n onSubmit()\n }\n break\n\n case 'Escape':\n case 'ArrowLeft':\n case 'ArrowRight':\n if (mentionsMenuOpen) {\n // stop these events if the menu is open\n event.preventDefault()\n event.stopPropagation()\n closeMentions()\n }\n break\n default:\n }\n // Call parent key handler\n if (onKeyDown) onKeyDown(event)\n },\n [canSubmit, closeMentions, mentionsMenuOpen, onKeyDown, onSubmit],\n )\n\n const initialSelectionAtEndOfContent: EditorSelection | undefined = useMemo(() => {\n if (selection) {\n return undefined\n }\n const lastBlock = (value || EMPTY_ARRAY).slice(-1)[0]\n const lastChild = isPortableTextTextBlock(lastBlock)\n ? lastBlock.children.slice(-1)[0]\n : undefined\n if (!lastChild) {\n return undefined\n }\n const point = {\n path: [{_key: lastBlock._key}, 'children', {_key: lastChild._key}],\n offset: isPortableTextSpan(lastChild) ? lastChild.text.length : 0,\n }\n return {\n focus: point,\n anchor: point,\n }\n }, [value, selection])\n\n // Update the mentions search term in the mentions menu\n useEffect(() => {\n mentionsMenuRef.current?.setSearchTerm(mentionsSearchTerm)\n }, [mentionsSearchTerm])\n\n // Close mentions if the user selects text\n useEffect(() => {\n if (mentionsMenuOpen && selection && !isEqual(selection.anchor, selection.focus)) {\n closeMentions()\n }\n }, [mentionsMenuOpen, closeMentions, selection])\n\n const popoverContent = (\n <MentionsMenu\n inputElement={inputElement}\n loading={mentionOptions.loading}\n onSelect={insertMention}\n options={mentionOptions.data || EMPTY_ARRAY}\n ref={mentionsMenuRef}\n />\n )\n\n return (\n <div ref={setRootElement}>\n <StyledPopover\n arrow={false}\n constrainSize\n content={popoverContent}\n disabled={!mentionsMenuOpen}\n fallbackPlacements={POPOVER_FALLBACK_PLACEMENTS}\n open={mentionsMenuOpen}\n placement=\"bottom\"\n ref={popoverRef}\n referenceElement={cursorElement}\n />\n <NodePlugin nodes={nodes} />\n <PortableTextEditable\n data-testid=\"comment-input-editable\"\n data-ui=\"EditableElement\"\n onBeforeInput={onBeforeInput}\n onBlur={onBlur}\n onFocus={onFocus}\n onKeyDown={handleKeyDown}\n ref={setInputElement}\n renderPlaceholder={renderPlaceholder}\n selection={initialSelectionAtEndOfContent}\n style={INLINE_STYLE}\n tabIndex={focusLock ? 0 : undefined}\n />\n </div>\n )\n}\n","import {type CurrentUser} from '@sanity/types'\nimport {type AvatarSize, Card} from '@sanity/ui'\nimport {MenuDivider} from '@sanity/ui/menu'\nimport {getTheme_v2} from '@sanity/ui/theme'\nimport {useCallback} from 'react'\nimport {css, styled} from 'styled-components'\nimport {Box, Flex, VStack} from 'ui5'\n\nimport {Button} from '../../../../../ui-components/button/Button'\nimport {TooltipDelayGroupProvider} from '../../../../../ui-components/tooltipDelayGroupProvider/TooltipDelayGroupProvider'\nimport {useTranslation} from '../../../../i18n/hooks/useTranslation'\nimport {useUser} from '../../../../store/user/hooks'\nimport {commentsLocaleNamespace} from '../../../i18n'\nimport {CommentsAvatar} from '../../avatars/CommentsAvatar'\nimport {MentionIcon} from '../../icons/MentionIcon'\nimport {SendIcon} from '../../icons/SendIcon'\nimport {type CommentInputRenderBlock} from './CommentInput'\nimport {Editable} from './Editable'\nimport {useCommentInput} from './useCommentInput'\n\nconst EditableWrap = styled(Box)`\n max-height: 20vh;\n overflow-y: auto;\n`\n\nconst ButtonDivider = styled(MenuDivider)({\n height: 20,\n width: 1,\n})\n\nfunction focusRingBorderStyle(border: {color: string; width: number}): string {\n return `inset 0 0 0 ${border.width}px ${border.color}`\n}\n\nconst RootCard = styled(Card)(({theme}) => {\n const {color, input, radius} = getTheme_v2(theme)\n const radii = radius[2]\n\n return css`\n border-radius: ${radii}px;\n box-shadow: var(--input-box-shadow);\n\n --input-box-shadow: ${focusRingBorderStyle({\n color: color.input.default.enabled.border,\n width: input.border.width,\n })};\n\n &:not([data-expand-on-focus='false'], :focus-within) {\n background: transparent;\n box-shadow: unset;\n }\n\n &[data-focused='true']:focus-within {\n ${EditableWrap} {\n min-height: 1em;\n }\n\n /* box-shadow: inset 0 0 0 1px var(--card-focus-ring-color); */\n --input-box-shadow: ${focusRingBorderStyle({\n color: 'var(--card-focus-ring-color)',\n width: input.border.width,\n })};\n }\n\n &:focus-within {\n ${EditableWrap} {\n min-height: 1em;\n }\n }\n\n &[data-expand-on-focus='false'] {\n ${EditableWrap} {\n min-height: 1em;\n }\n }\n\n &[data-expand-on-focus='true'] {\n [data-ui='CommentInputActions']:not([hidden]) {\n display: none;\n }\n\n &:focus-within {\n [data-ui='CommentInputActions'] {\n display: flex;\n }\n }\n }\n &:hover {\n --input-box-shadow: ${focusRingBorderStyle({\n color: color.input.default.hovered.border,\n width: input.border.width,\n })};\n }\n `\n})\n\nconst AvatarContainer = styled.div((props) => {\n const theme = getTheme_v2(props.theme)\n return `\n min-height: ${theme.avatar.sizes[1]?.size}px;\n display: flex;\n align-items: center;\n `\n})\n\ninterface CommentInputInnerProps {\n avatarSize?: AvatarSize\n currentUser: CurrentUser\n focusLock?: boolean\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n onBlur?: (e: React.FormEvent<HTMLDivElement>) => void\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n onFocus?: (e: React.FormEvent<HTMLDivElement>) => void\n onKeyDown?: (e: React.KeyboardEvent) => void\n onSubmit?: () => void\n placeholder?: React.ReactNode\n renderBlock: CommentInputRenderBlock\n withAvatar?: boolean\n}\n\nexport function CommentInputInner(props: CommentInputInnerProps) {\n const {\n avatarSize = 1,\n currentUser,\n focusLock,\n onBlur,\n onFocus,\n onKeyDown,\n onSubmit,\n placeholder,\n renderBlock,\n withAvatar,\n } = props\n\n const [user] = useUser(currentUser.id)\n const {\n canSubmit,\n expandOnFocus,\n focused,\n hasChanges,\n insertAtChar,\n openMentions,\n readOnly,\n mentionOptions,\n } = useCommentInput()\n\n const {t} = useTranslation(commentsLocaleNamespace)\n const avatar = withAvatar ? (\n <AvatarContainer>\n <CommentsAvatar user={user} size={avatarSize} />\n </AvatarContainer>\n ) : null\n\n const handleMentionButtonClicked = useCallback(\n (e: React.MouseEvent<HTMLButtonElement>) => {\n e.stopPropagation()\n insertAtChar()\n openMentions()\n },\n [insertAtChar, openMentions],\n )\n\n return (\n <Flex alignItems=\"flex-start\" gap={2}>\n {avatar}\n\n <RootCard\n id=\"comment-input-root\"\n data-expand-on-focus={expandOnFocus && !canSubmit ? 'true' : 'false'}\n data-focused={focused ? 'true' : 'false'}\n flex={1}\n sizing=\"border\"\n tone={readOnly ? 'transparent' : 'default'}\n >\n <VStack>\n <EditableWrap data-ui=\"CommentInputEditableWrap\" paddingX={1} paddingY={2}>\n <Editable\n focusLock={focusLock}\n onBlur={onBlur}\n onFocus={onFocus}\n onKeyDown={onKeyDown}\n onSubmit={onSubmit}\n placeholder={placeholder}\n renderBlock={renderBlock}\n />\n </EditableWrap>\n\n <Flex\n alignItems=\"center\"\n data-ui=\"CommentInputActions\"\n gap={1}\n justifyContent=\"flex-end\"\n padding={1}\n >\n <TooltipDelayGroupProvider>\n {!mentionOptions.disabled && (\n <Button\n aria-label={t('compose.mention-user-aria-label')}\n data-testid=\"comment-input-mention-button\"\n disabled={readOnly}\n icon={MentionIcon}\n mode=\"bleed\"\n type=\"button\"\n onClick={handleMentionButtonClicked}\n tooltipProps={{content: t('compose.mention-user-tooltip')}}\n />\n )}\n {onSubmit && (\n <>\n {!mentionOptions.disabled && <ButtonDivider />}\n\n <Button\n aria-label={t('compose.send-comment-aria-label')}\n data-testid=\"comment-input-send-button\"\n disabled={!canSubmit || !hasChanges || readOnly}\n icon={SendIcon}\n mode={hasChanges && canSubmit ? 'default' : 'bleed'}\n onClick={onSubmit}\n tone={hasChanges && canSubmit ? 'primary' : 'default'}\n tooltipProps={{content: t('compose.send-comment-tooltip')}}\n />\n </>\n )}\n </TooltipDelayGroupProvider>\n </Flex>\n </VStack>\n </RootCard>\n </Flex>\n )\n}\n","import {type EditorSelection, PortableTextEditor, usePortableTextEditor} from '@portabletext/editor'\nimport {isPortableTextSpan, type Path} from '@sanity/types'\nimport {type ReactNode, useCallback, useMemo, useState} from 'react'\nimport {CommentInputContextV2} from 'sanity/_singletons'\n\nimport {useDidUpdate} from '../../../../form/hooks/useDidUpdate'\nimport {type UserListWithPermissionsHookValue} from '../../../../hooks/useUserListWithPermissions'\nimport {hasCommentMessageValue, useCommentHasChanged} from '../../../helpers'\nimport {type CommentMessage} from '../../../types'\n\nexport interface CommentInputContextValue {\n canSubmit?: boolean\n closeMentions: () => void\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n editor: PortableTextEditor\n expandOnFocus?: boolean\n focused: boolean\n focusEditor: () => void\n focusOnMount?: boolean\n hasChanges: boolean\n insertAtChar: () => void\n insertMention: (userId: string) => void\n mentionOptions: UserListWithPermissionsHookValue\n mentionsMenuOpen: boolean\n mentionsSearchTerm: string\n onBeforeInput: (event: InputEvent) => void\n openMentions: () => void\n readOnly: boolean\n value: CommentMessage\n}\n\ninterface CommentInputProviderProps {\n children: ReactNode\n expandOnFocus?: boolean\n focused: boolean\n focusOnMount?: boolean\n mentionOptions: UserListWithPermissionsHookValue\n onMentionMenuOpenChange?: (open: boolean) => void\n readOnly?: boolean\n value: CommentMessage\n}\n\nexport function CommentInputProvider(props: CommentInputProviderProps) {\n const {\n children,\n expandOnFocus = false,\n focused,\n focusOnMount = false,\n mentionOptions,\n onMentionMenuOpenChange,\n value,\n readOnly,\n } = props\n\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n const editor = usePortableTextEditor()\n\n const [mentionsMenuOpen, setMentionsMenuOpen] = useState<boolean>(false)\n const [mentionsSearchTerm, setMentionsSearchTerm] = useState<string>('')\n const [selectionAtMentionInsert, setSelectionAtMentionInsert] = useState<EditorSelection>(null)\n\n const canSubmit = useMemo(() => hasCommentMessageValue(value), [value])\n\n const hasChanges = useCommentHasChanged(value)\n\n const focusEditor = useCallback(() => {\n if (readOnly) return\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n PortableTextEditor.focus(editor)\n }, [editor, readOnly])\n\n const closeMentions = useCallback(() => {\n setMentionsMenuOpen(false)\n setMentionsSearchTerm('')\n setSelectionAtMentionInsert(null)\n }, [])\n\n const openMentions = useCallback(() => {\n if (mentionOptions?.disabled) {\n return\n }\n setMentionsMenuOpen(true)\n setMentionsSearchTerm('')\n setMentionsMenuOpen(true)\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n setSelectionAtMentionInsert(PortableTextEditor.getSelection(editor))\n }, [editor, mentionOptions?.disabled])\n\n // This function activates or deactivates the mentions menu and updates\n // the mention search term when the user types into the Portable Text Editor.\n const onBeforeInput = useCallback(\n (event: InputEvent): void => {\n if (mentionOptions?.disabled) {\n return\n }\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n const selection = PortableTextEditor.getSelection(editor)\n const cursorOffset = selection ? selection.focus.offset : 0\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n const focusChild = PortableTextEditor.focusChild(editor)\n const focusSpan = (isPortableTextSpan(focusChild) && focusChild) || undefined\n\n const isInsertText = event.inputType === 'insertText'\n const isDeleteText = event.inputType === 'deleteContentBackward'\n const isInsertingAtChar = isInsertText && event.data === '@'\n\n const lastIndexOfAt =\n focusSpan?.text.slice(0, Math.max(0, cursorOffset)).lastIndexOf('@') || 0\n\n const isWhitespaceCharBeforeCursorPosition =\n focusSpan?.text.slice(cursorOffset - 1, cursorOffset) === ' '\n\n const filterStartsWithSpaceChar = isInsertText && event.data === ' ' && !mentionsSearchTerm\n\n // If we are inserting a '@' character - open the mentions menu and reset the search term.\n // Only do this if it is in the start of the text, or if '@' is inserted when following a whitespace char.\n if (isInsertingAtChar && (cursorOffset < 1 || isWhitespaceCharBeforeCursorPosition)) {\n openMentions()\n return\n }\n\n // If the user begins typing their filter with a space, or if they are deleting\n // characters after activation and the '@' is no longer there,\n // clear the search term and close the mentions menu.\n if (\n filterStartsWithSpaceChar ||\n (isDeleteText &&\n (focusSpan?.text.length === 1 || lastIndexOfAt === (focusSpan?.text.length || 0) - 1))\n ) {\n closeMentions()\n return\n }\n\n // Update the search term\n if (isPortableTextSpan(focusChild)) {\n // Term starts with the @ char in the value until the cursor offset\n let term = focusChild.text.slice(lastIndexOfAt + 1, cursorOffset)\n // Add the char to the mentions search term\n if (isInsertText) {\n term += event.data\n }\n // Exclude the char from the mentions search term\n if (isDeleteText) {\n term = term.slice(0, Math.max(0, term.length - 1))\n }\n // Set the updated mentions search term\n setMentionsSearchTerm(term)\n }\n },\n [closeMentions, editor, mentionsSearchTerm, openMentions, mentionOptions?.disabled],\n )\n\n const insertAtChar = useCallback(() => {\n setMentionsMenuOpen(true)\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n PortableTextEditor.focus(editor)\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n PortableTextEditor.insertChild(editor, editor.schemaTypes.span, {text: '@'})\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n setSelectionAtMentionInsert(PortableTextEditor.getSelection(editor))\n }, [editor])\n\n useDidUpdate(mentionsMenuOpen, () => onMentionMenuOpenChange?.(mentionsMenuOpen))\n\n const insertMention = useCallback(\n (userId: string) => {\n const mentionSchemaType = editor.schemaTypes.inlineObjects.find((t) => t.name === 'mention')\n let mentionPath: Path | undefined\n\n const [span, spanPath] =\n (selectionAtMentionInsert &&\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n PortableTextEditor.findByPath(editor, selectionAtMentionInsert.focus.path)) ||\n []\n if (span && isPortableTextSpan(span) && spanPath && mentionSchemaType) {\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n PortableTextEditor.focus(editor)\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n const offset = PortableTextEditor.getSelection(editor)?.focus.offset\n if (typeof offset !== 'undefined') {\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n PortableTextEditor.delete(\n editor,\n {\n anchor: {path: spanPath, offset: span.text.lastIndexOf('@')},\n focus: {path: spanPath, offset},\n },\n {mode: 'selected'},\n )\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n PortableTextEditor.insertChild(editor, mentionSchemaType, {\n userId: userId,\n })\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n PortableTextEditor.insertChild(editor, editor.schemaTypes.span, {text: ' '})\n }\n }\n },\n [editor, selectionAtMentionInsert],\n )\n\n const ctxValue = useMemo(\n (): CommentInputContextValue => ({\n canSubmit,\n closeMentions,\n editor,\n expandOnFocus,\n focused,\n focusEditor,\n focusOnMount,\n hasChanges,\n insertAtChar,\n insertMention,\n mentionOptions,\n mentionsMenuOpen,\n mentionsSearchTerm,\n onBeforeInput,\n openMentions,\n readOnly: Boolean(readOnly),\n value,\n }),\n [\n canSubmit,\n closeMentions,\n editor,\n expandOnFocus,\n focused,\n focusEditor,\n focusOnMount,\n hasChanges,\n insertAtChar,\n insertMention,\n mentionOptions,\n mentionsMenuOpen,\n mentionsSearchTerm,\n onBeforeInput,\n openMentions,\n readOnly,\n value,\n ],\n )\n\n return (\n <CommentInputContextV2.Provider value={ctxValue}>{children}</CommentInputContextV2.Provider>\n )\n}\n","import {\n type Editor,\n type EditorEmittedEvent,\n EditorProvider,\n keyGenerator,\n useEditor,\n} from '@portabletext/editor'\nimport {EventListenerPlugin} from '@portabletext/editor/plugins'\nimport {getValue} from '@portabletext/editor/selectors'\nimport {OneLinePlugin} from '@portabletext/plugin-one-line'\nimport {sanitySchemaToPortableTextSchema} from '@portabletext/sanity-bridge'\nimport {type CurrentUser, type PortableTextBlock} from '@sanity/types'\nimport {type AvatarSize, focusFirstDescendant, focusLastDescendant} from '@sanity/ui'\nimport {\n type FocusEvent,\n type FormEvent,\n type KeyboardEvent,\n type ReactNode,\n useCallback,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n type RefAttributes,\n} from 'react'\nimport {VStack} from 'ui5'\n\nimport {type UserListWithPermissionsHookValue} from '../../../../hooks/useUserListWithPermissions'\nimport {NormalBlock} from '../blocks/NormalBlock'\nimport {editorSchemaType} from '../config'\nimport {CommentInputDiscardDialog} from './CommentInputDiscardDialog'\nimport {CommentInputInner} from './CommentInputInner'\nimport {CommentInputProvider} from './CommentInputProvider'\n\n/**\n * `EditorProvider` doesn't have a `ref` prop. This plugin takes care of\n * imperatively forwarding the editor instance.\n */\nfunction EditorRefPlugin(props: RefAttributes<Editor | null>) {\n const {ref} = props\n const editor = useEditor()\n\n useImperativeHandle(ref, () => editor, [editor])\n\n return null\n}\n\nconst EMPTY_ARRAY: [] = []\n\nconst defaultRenderBlock = ({children}: {children: ReactNode}) => (\n <NormalBlock>{children}</NormalBlock>\n)\n\n/**\n * @internal\n */\nexport type CommentInputRenderBlock = (props: {children: React.ReactNode}) => React.JSX.Element\n\nconst SCROLL_INTO_VIEW_OPTIONS: ScrollIntoViewOptions = {\n behavior: 'smooth',\n block: 'center',\n inline: 'center',\n}\n\n/**\n * @internal\n */\nexport interface CommentInputProps {\n currentUser: CurrentUser\n expandOnFocus?: boolean\n focusLock?: boolean\n focusOnMount?: boolean\n mentionOptions: UserListWithPermissionsHookValue\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n onBlur?: (e: FormEvent<HTMLDivElement>) => void\n onChange: (value: PortableTextBlock[]) => void\n onDiscardCancel?: () => void\n onDiscardConfirm: () => void\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n onFocus?: (e: FormEvent<HTMLDivElement>) => void\n onKeyDown?: (e: KeyboardEvent) => void\n onMentionMenuOpenChange?: (open: boolean) => void\n onSubmit?: (value: PortableTextBlock[]) => void\n placeholder?: ReactNode\n readOnly?: boolean\n renderBlock?: CommentInputRenderBlock\n value: PortableTextBlock[] | null\n withAvatar?: boolean\n avatarSize?: AvatarSize\n}\n\ninterface CommentDiscardDialogController {\n open: () => void\n close: () => void\n}\n\n/**\n * @internal\n */\nexport interface CommentInputHandle {\n blur: () => void\n discardDialogController: CommentDiscardDialogController\n focus: () => void\n scrollTo: () => void\n reset: () => void\n}\n\n/**\n * @internal\n * @hidden\n */\nexport function CommentInput(props: CommentInputProps & RefAttributes<CommentInputHandle>) {\n const {\n ref,\n avatarSize,\n currentUser,\n expandOnFocus,\n focusLock = false,\n focusOnMount,\n mentionOptions,\n onBlur,\n onChange,\n onDiscardCancel,\n onDiscardConfirm,\n onFocus,\n onKeyDown,\n onMentionMenuOpenChange,\n onSubmit,\n placeholder,\n readOnly,\n renderBlock = defaultRenderBlock,\n value = EMPTY_ARRAY,\n withAvatar = true,\n } = props\n const [focused, setFocused] = useState<boolean>(false)\n const editorRef = useRef<Editor | null>(null)\n const editorContainerRef = useRef<HTMLDivElement | null>(null)\n const resetInstanceRef = useRef(false)\n const [showDiscardDialog, setShowDiscardDialog] = useState<boolean>(false)\n\n const preDivRef = useRef<HTMLDivElement | null>(null)\n const postDivRef = useRef<HTMLDivElement | null>(null)\n const innerRef = useRef<HTMLDivElement | null>(null)\n\n // A unique (React) key for the editor instance.\n const [editorInstanceKey, setEditorInstanceKey] = useState(keyGenerator())\n\n const requestFocus = useCallback(() => {\n requestAnimationFrame(() => {\n editorRef.current?.send({type: 'focus'})\n })\n }, [])\n\n const resetEditorInstance = useCallback(() => {\n // The discarded instance flushes pending mutations during teardown; drop\n // them in `handleEvent` so a finished draft cannot overwrite the\n // consumer's cleared draft state.\n resetInstanceRef.current = true\n setEditorInstanceKey(keyGenerator())\n }, [])\n\n const handleEvent = useCallback(\n (event: EditorEmittedEvent) => {\n // Focus the editor when ready if focusOnMount is true\n if (event.type === 'ready') {\n resetInstanceRef.current = false\n if (focusOnMount) {\n requestFocus()\n }\n }\n if (event.type === 'focused') {\n setFocused(true)\n }\n\n if (event.type === 'blurred') {\n setFocused(false)\n }\n\n // Update the comment value whenever the comment is edited by the user.\n if (event.type === 'mutation' && !resetInstanceRef.current) {\n onChange(event.value || EMPTY_ARRAY)\n }\n },\n [focusOnMount, onChange, requestFocus],\n )\n\n const scrollToEditor = useCallback(() => {\n editorContainerRef.current?.scrollIntoView(SCROLL_INTO_VIEW_OPTIONS)\n }, [])\n\n const handleSubmit = useCallback(() => {\n // Read the editor's live value directly rather than the value mirrored\n // through the debounced `mutation` event, which can lag the latest\n // keystrokes by up to the flush interval and truncate the comment when\n // the user submits without pausing.\n const currentValue = editorRef.current ? getValue(editorRef.current.getSnapshot()) : EMPTY_ARRAY\n onSubmit?.(currentValue)\n resetEditorInstance()\n requestFocus()\n scrollToEditor()\n }, [onSubmit, requestFocus, resetEditorInstance, scrollToEditor])\n\n const handleDiscardConfirm = useCallback(() => {\n onDiscardConfirm()\n resetEditorInstance()\n }, [onDiscardConfirm, resetEditorInstance])\n\n // The way a user a comment can be discarded varies from the context it is used in.\n // This controller is used to take care of the main logic of the discard process, while\n // specific behavior is handled by the consumer.\n const discardDialogController = useMemo((): CommentDiscardDialogController => {\n return {\n open: () => {\n setShowDiscardDialog(true)\n },\n close: () => {\n setShowDiscardDialog(false)\n requestFocus()\n },\n }\n }, [requestFocus])\n\n useImperativeHandle(ref, () => {\n return {\n focus: requestFocus,\n blur() {\n editorRef.current?.send({type: 'blur'})\n },\n scrollTo: scrollToEditor,\n reset: resetEditorInstance,\n\n discardDialogController,\n }\n }, [discardDialogController, requestFocus, resetEditorInstance, scrollToEditor])\n\n const handleFocus = useCallback(\n (event: FocusEvent<HTMLDivElement>) => {\n if (!focusLock) return\n\n const target = event.target\n const innerEl = innerRef.current\n\n if (innerEl && target === preDivRef.current) {\n focusLastDescendant(innerEl)\n return\n }\n\n if (innerEl && target === postDivRef.current) {\n focusFirstDescendant(innerEl)\n }\n },\n [focusLock],\n )\n\n return (\n <>\n {showDiscardDialog && onDiscardCancel && (\n <CommentInputDiscardDialog onClose={onDiscardCancel} onConfirm={handleDiscardConfirm} />\n )}\n\n <VStack ref={editorContainerRef} data-testid=\"comment-input\" onFocus={handleFocus}>\n <EditorProvider\n key={editorInstanceKey}\n initialConfig={{\n schemaDefinition: sanitySchemaToPortableTextSchema(editorSchemaType),\n initialValue: value || EMPTY_ARRAY,\n readOnly,\n }}\n >\n <EditorRefPlugin ref={editorRef} />\n <EventListenerPlugin on={handleEvent} />\n <OneLinePlugin />\n <UpdateReadOnlyPlugin readOnly={readOnly ?? false} />\n <UpdateValuePlugin value={value ?? undefined} />\n <CommentInputProvider\n expandOnFocus={expandOnFocus}\n focused={focused}\n focusOnMount={focusOnMount}\n mentionOptions={mentionOptions}\n onMentionMenuOpenChange={onMentionMenuOpenChange}\n readOnly={readOnly}\n value={value}\n >\n {focusLock && <div ref={preDivRef} tabIndex={0} />}\n\n <VStack ref={innerRef}>\n <CommentInputInner\n avatarSize={avatarSize}\n currentUser={currentUser}\n focusLock={focusLock}\n onBlur={onBlur}\n onFocus={onFocus}\n onKeyDown={onKeyDown}\n onSubmit={onSubmit && handleSubmit}\n placeholder={placeholder}\n renderBlock={renderBlock}\n withAvatar={withAvatar}\n />\n </VStack>\n\n {focusLock && <div ref={postDivRef} tabIndex={0} />}\n </CommentInputProvider>\n </EditorProvider>\n </VStack>\n </>\n )\n}\n\n/**\n * `EditorProvider` doesn't have a `readOnly` prop. This plugin listens for the\n * prop change and sends an `update readOnly` event to the editor.\n */\nfunction UpdateReadOnlyPlugin(props: {readOnly: boolean}) {\n const editor = useEditor()\n\n useEffect(() => {\n editor.send({\n type: 'update readOnly',\n readOnly: props.readOnly,\n })\n }, [editor, props.readOnly])\n\n return null\n}\n\n/**\n * `EditorProvider` doesn't have a `value` prop. This plugin listens for the\n * prop change and sends an `update value` event to the editor.\n */\nfunction UpdateValuePlugin(props: {value: Array<PortableTextBlock> | undefined}) {\n const editor = useEditor()\n\n useEffect(() => {\n editor.send({\n type: 'update value',\n value: props.value,\n })\n }, [editor, props.value])\n\n return null\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CommentInput-BXYQnGhq.js","names":["opts || {}","{\n ...options,\n boundary: shouldApplyBoundary ? boundaryElement : undefined,\n }","shouldApplyBoundary ? boundaryElement : undefined","useMemo(() => {\n const options = SCROLL_OPTIONS_BY_TYPE[scrollTarget?.type || 'comment']\n\n // Only apply boundary for 'comment' type scrolls (scrolling within inspector panel)\n // Field, group, and inline-comment scrolls target the document pane and shouldn't be bounded\n const shouldApplyBoundary = scrollTarget?.type === 'comment'\n\n return {\n ...options,\n boundary: shouldApplyBoundary ? boundaryElement : undefined,\n }\n }, [boundaryElement, scrollTarget?.type])","(commentId: string) => {\n setScrollTarget({type: 'comment', id: commentId})\n }","useCallback((commentId: string) => {\n setScrollTarget({type: 'comment', id: commentId})\n }, [])","(threadId: string) => {\n setScrollTarget({type: 'group', id: threadId})\n }","useCallback((threadId: string) => {\n setScrollTarget({type: 'group', id: threadId})\n }, [])","(fieldPath: string) => {\n setScrollTarget({type: 'field', id: fieldPath})\n }","useCallback((fieldPath: string) => {\n setScrollTarget({type: 'field', id: fieldPath})\n }, [])","(commentId: string) => {\n setScrollTarget({type: 'inline-comment', id: commentId})\n }","commentId","useCallback((commentId: string) => {\n setScrollTarget({type: 'inline-comment', id: commentId})\n }, [])","() => {\n const raf = requestAnimationFrame(() => {\n if (!scrollTarget) return\n\n const {type, id} = scrollTarget\n\n const element = document?.querySelector(\n `[data-comments-${type}-id=\"${generateValidAttrValue(id)}\"]`,\n )\n\n if (element) {\n scrollIntoViewIfNeeded(element, scrollOpts)\n }\n })\n\n return () => {\n cancelAnimationFrame(raf)\n }\n }","[scrollOpts, scrollTarget]","{\n scrollToComment: handleScrollToComment,\n scrollToField: handleScrollToField,\n scrollToGroup: handleScrollToGroup,\n scrollToInlineComment: handleScrollToInlineComment,\n }","useMemo(\n (): CommentsScrollHookValue => ({\n scrollToComment: handleScrollToComment,\n scrollToField: handleScrollToField,\n scrollToGroup: handleScrollToGroup,\n scrollToInlineComment: handleScrollToInlineComment,\n }),\n [handleScrollToComment, handleScrollToField, handleScrollToGroup, handleScrollToInlineComment],\n )","<NormalText size={1} forwardedAs=\"div\" trim={true}>\n {children}\n </NormalText>","(e: MouseEvent<HTMLButtonElement>) => {\n e.stopPropagation()\n onClose()\n }","useCallback(\n (e: MouseEvent<HTMLButtonElement>) => {\n e.stopPropagation()\n onClose()\n },\n [onClose],\n )","(e: MouseEvent<HTMLButtonElement>) => {\n e.stopPropagation()\n onConfirm()\n }","useCallback(\n (e: MouseEvent<HTMLButtonElement>) => {\n e.stopPropagation()\n onConfirm()\n },\n [onConfirm],\n )","t('discard.header')","{\n onClick: handleCancelClick,\n }","t('discard.button-confirm')","{\n onClick: handleConfirmClick,\n text: t('discard.button-confirm'),\n tone: 'critical',\n }","{\n cancelButton: {\n onClick: handleCancelClick,\n },\n confirmButton: {\n onClick: handleConfirmClick,\n text: t('discard.button-confirm'),\n tone: 'critical',\n },\n }","t('discard.text')","<Text size={1} as=\"div\" trim={true}>\n {t('discard.text')}\n </Text>","<ThemeColorProvider tone=\"default\">\n <DialogProvider zOffset={Z_OFFSET}>\n <Dialog\n header={t('discard.header')}\n id=\"discard-comment-dialog\"\n onClose={onClose}\n width={0}\n onClickOutside={onClose}\n footer={{\n cancelButton: {\n onClick: handleCancelClick,\n },\n confirmButton: {\n onClick: handleConfirmClick,\n text: t('discard.button-confirm'),\n tone: 'critical',\n },\n }}\n >\n <Text size={1} as=\"div\" trim={true}>\n {t('discard.text')}\n </Text>\n </Dialog>\n </DialogProvider>\n </ThemeColorProvider>","nameToInitials(user?.displayName || '')","user?.displayName || ''","useMemo(() => nameToInitials(user?.displayName || ''), [user?.displayName])","<StyledAvatar {...restProps} />","<StyledAvatar\n initials={initials}\n src={user?.imageUrl}\n title={user?.displayName}\n {...restProps}\n />","user?.imageUrl","user?.displayName","<path\n d=\"M16.6633 18.9383C15.539 19.6562 14.2034 20.0723 12.7705 20.0723C8.77022 20.0723 5.52734 16.8294 5.52734 12.8291C5.52734 8.82881 8.77022 5.58594 12.7705 5.58594C16.7708 5.58594 20.0137 8.82881 20.0137 12.8291C20.0137 13.6623 19.8249 14.7093 19.6141 15.2077C19.5578 15.3408 19.479 15.4845 19.3936 15.6238C19.0955 16.1106 18.5507 16.3721 17.9807 16.4018V16.4018C16.8271 16.462 15.8588 15.5428 15.8588 14.3877V9.27302\"\n stroke=\"currentColor\"\n strokeWidth={1.2}\n strokeLinejoin=\"round\"\n />","<circle cx=\"12.5732\" cy=\"12.8291\" r=\"3.08691\" stroke=\"currentColor\" strokeWidth={1.2} />","<svg\n data-sanity-icon=\"mention\"\n fill=\"none\"\n height=\"1em\"\n ref={ref}\n viewBox=\"0 0 25 25\"\n width=\"1em\"\n xmlns=\"http://www.w3.org/2000/svg\"\n {...rest}\n >\n <path\n d=\"M16.6633 18.9383C15.539 19.6562 14.2034 20.0723 12.7705 20.0723C8.77022 20.0723 5.52734 16.8294 5.52734 12.8291C5.52734 8.82881 8.77022 5.58594 12.7705 5.58594C16.7708 5.58594 20.0137 8.82881 20.0137 12.8291C20.0137 13.6623 19.8249 14.7093 19.6141 15.2077C19.5578 15.3408 19.479 15.4845 19.3936 15.6238C19.0955 16.1106 18.5507 16.3721 17.9807 16.4018V16.4018C16.8271 16.462 15.8588 15.5428 15.8588 14.3877V9.27302\"\n stroke=\"currentColor\"\n strokeWidth={1.2}\n strokeLinejoin=\"round\"\n />\n <circle cx=\"12.5732\" cy=\"12.8291\" r=\"3.08691\" stroke=\"currentColor\" strokeWidth={1.2} />\n </svg>","<path\n clipRule=\"evenodd\"\n d=\"M21.1602 12.5L7.16016 19.5V14.8765L13.6656 12.4989L7.16016 9.97149L7.16016 5.5L21.1602 12.5Z\"\n stroke=\"currentColor\"\n strokeWidth={1.2}\n strokeLinejoin=\"round\"\n />","<svg\n data-sanity-icon=\"send\"\n fill=\"none\"\n height=\"1em\"\n ref={ref}\n viewBox=\"0 0 25 25\"\n width=\"1em\"\n xmlns=\"http://www.w3.org/2000/svg\"\n {...rest}\n >\n <path\n clipRule=\"evenodd\"\n d=\"M21.1602 12.5L7.16016 19.5V14.8765L13.6656 12.4989L7.16016 9.97149L7.16016 5.5L21.1602 12.5Z\"\n stroke=\"currentColor\"\n strokeWidth={1.2}\n strokeLinejoin=\"round\"\n />\n </svg>","<CommentsAvatar user={loadedUser} status={user.granted ? undefined : 'inactive'} />","user.granted ? undefined : 'inactive'","loadedUser ? (\n <Text size={1} truncate={1} title={loadedUser.displayName} as=\"div\" trim={true}>\n {loadedUser.displayName}\n </Text>\n ) : (\n <TextSkeleton size={1} style={SKELETON_INLINE_STYLE} />\n )","() => {\n onSelect(user.id)\n }","id","useCallback(() => {\n onSelect(user.id)\n }, [onSelect, user.id])","<Box>{text}</Box>","<InnerFlex alignItems=\"center\" gap={2} flexBasis=\"0%\" flexGrow={1}>\n {avatar}\n <Box>{text}</Box>\n </InnerFlex>","!user.granted && <Badge fontSize={1}>{t('mentions.unauthorized-user')}</Badge>","granted","<Flex alignItems=\"center\" gap={3}>\n <InnerFlex alignItems=\"center\" gap={2} flexBasis=\"0%\" flexGrow={1}>\n {avatar}\n <Box>{text}</Box>\n </InnerFlex>\n\n {!user.granted && <Badge fontSize={1}>{t('mentions.unauthorized-user')}</Badge>}\n </Flex>","<Card as=\"button\" disabled={!user.granted} onClick={handleSelect} padding={2} radius={2}>\n <Flex alignItems=\"center\" gap={3}>\n <InnerFlex alignItems=\"center\" gap={2} flexBasis=\"0%\" flexGrow={1}>\n {avatar}\n <Box>{text}</Box>\n </InnerFlex>\n\n {!user.granted && <Badge fontSize={1}>{t('mentions.unauthorized-user')}</Badge>}\n </Flex>\n </Card>","!user.granted","options = []","() => {\n return {\n setSearchTerm(term: string) {\n setSearchTerm(term)\n },\n }\n }","[]","(itemProps: UserWithPermission) => {\n return <MentionsMenuItem user={itemProps} onSelect={onSelect} />\n }","useCallback(\n (itemProps: UserWithPermission) => {\n return <MentionsMenuItem user={itemProps} onSelect={onSelect} />\n },\n [onSelect],\n )","(index: number) => {\n return !options?.[index]?.granted\n }","useCallback(\n (index: number) => {\n return !options?.[index]?.granted\n },\n [options],\n )","useMemo(() => {\n if (!searchTerm) return options || EMPTY_ARRAY\n\n // We deburr the search term and the display names so that when searching\n // for e.g \"bjorge\" we also get results for \"bjørge\"\n const deburredSearchTerm = deburr(searchTerm).toLocaleLowerCase()\n\n const deburredOptions = options?.map((option) => ({\n ...option,\n displayName: deburr(option.displayName || '').toLocaleLowerCase(),\n }))\n\n const filtered = deburredOptions\n ?.filter((option) => {\n return option?.displayName?.includes(deburredSearchTerm)\n })\n // Sort by whether the displayName starts with the search term to get more relevant results first\n ?.sort((a, b) => {\n const matchA = a.displayName?.startsWith(deburredSearchTerm)\n const matchB = b.displayName?.startsWith(deburredSearchTerm)\n\n if (matchA && !matchB) return -1\n if (!matchA && matchB) return 1\n\n return 0\n })\n\n return filtered || EMPTY_ARRAY\n }, [options, searchTerm])","deburredOptions\n ?.filter((option) => {\n return option?.displayName?.includes(deburredSearchTerm)\n })\n // Sort by whether the displayName starts with the search term to get more relevant results first\n ?.sort((a, b) => {\n const matchA = a.displayName?.startsWith(deburredSearchTerm)\n const matchB = b.displayName?.startsWith(deburredSearchTerm)\n\n if (matchA && !matchB) return -1\n if (!matchA && matchB) return 1\n\n return 0\n })","options?.map","(option) => ({\n ...option,\n displayName: deburr(option.displayName || '').toLocaleLowerCase(),\n })","option","<Root>\n <LoadingBlock showText />\n </Root>","filteredOptions.length === 0 && (\n <Box padding={5}>\n <Text align=\"center\" size={1} muted as=\"div\" trim={true}>\n {t('mentions.no-users-found')}\n </Text>\n </Box>\n )","length","filteredOptions.length > 0 && (\n <FlexWrap flexDirection=\"column\" flexBasis=\"0%\" flexGrow={1} overflow=\"hidden\">\n <CommandList\n activeItemDataAttr=\"data-hovered\"\n ariaLabel={t('mentions.user-list-aria-label')}\n fixedHeight\n getItemDisabled={getItemDisabled}\n inputElement={_inputElement}\n itemHeight={41}\n items={filteredOptions}\n padding={1}\n ref={commandListRef}\n renderItem={renderItem}\n />\n </FlexWrap>\n )","filteredOptions.length","<Flex flexDirection=\"column\" height=\"100%\" data-testid=\"comments-mentions-menu\">\n {filteredOptions.length === 0 && (\n <Box padding={5}>\n <Text align=\"center\" size={1} muted as=\"div\" trim={true}>\n {t('mentions.no-users-found')}\n </Text>\n </Box>\n )}\n\n {filteredOptions.length > 0 && (\n <FlexWrap flexDirection=\"column\" flexBasis=\"0%\" flexGrow={1} overflow=\"hidden\">\n <CommandList\n activeItemDataAttr=\"data-hovered\"\n ariaLabel={t('mentions.user-list-aria-label')}\n fixedHeight\n getItemDisabled={getItemDisabled}\n inputElement={_inputElement}\n itemHeight={41}\n items={filteredOptions}\n padding={1}\n ref={commandListRef}\n renderItem={renderItem}\n />\n </FlexWrap>\n )}\n </Flex>","<TextSkeleton\n data-testid=\"comment-mentions-loading-skeleton\"\n style={{width: '10ch'}}\n size={0}\n muted\n radius={1}\n animated\n />","<Flex>\n <CommentsAvatar user={user} />\n </Flex>","<Text size={1} as=\"div\" trim={true}>\n {user.displayName}\n </Text>","displayName","<Flex alignItems=\"center\" gap={2}>\n <Flex>\n <CommentsAvatar user={user} />\n </Flex>\n\n <Text size={1} as=\"div\" trim={true}>\n {user.displayName}\n </Text>\n </Flex>","<Span data-selected={selected} data-active={currentUser?.sanityUserId === userId}>\n @{user.displayName}\n </Span>","currentUser?.sanityUserId === userId","<Tooltip\n portal\n content={\n <Flex alignItems=\"center\" gap={2}>\n <Flex>\n <CommentsAvatar user={user} />\n </Flex>\n\n <Text size={1} as=\"div\" trim={true}>\n {user.displayName}\n </Text>\n </Flex>\n }\n >\n <Span data-selected={selected} data-active={currentUser?.sanityUserId === userId}>\n @{user.displayName}\n </Span>\n </Tooltip>","useMemo(() => {\n if (!cursorRect) {\n return null\n }\n return {\n getBoundingClientRect: () => {\n return cursorRect\n },\n } as HTMLElement\n }, [cursorRect])","{\n getBoundingClientRect: () => {\n return cursorRect\n },\n }","() => {\n if (disabled) {\n setCursorRect(null)\n return\n }\n\n const sel = window.getSelection()\n\n if (!sel || !sel.isCollapsed || sel.rangeCount === 0) return\n\n const range = sel.getRangeAt(0)\n const isWithinRoot = rootElement?.contains(range.commonAncestorContainer)\n\n if (!isWithinRoot) {\n setCursorRect(null)\n return\n }\n const rect = range?.getBoundingClientRect()\n if (rect) {\n setCursorRect(rect)\n }\n }","rootElement?.contains","useCallback(() => {\n if (disabled) {\n setCursorRect(null)\n return\n }\n\n const sel = window.getSelection()\n\n if (!sel || !sel.isCollapsed || sel.rangeCount === 0) return\n\n const range = sel.getRangeAt(0)\n const isWithinRoot = rootElement?.contains(range.commonAncestorContainer)\n\n if (!isWithinRoot) {\n setCursorRect(null)\n return\n }\n const rect = range?.getBoundingClientRect()\n if (rect) {\n setCursorRect(rect)\n }\n }, [disabled, rootElement])","() => {\n document.addEventListener('selectionchange', handleSelectionChange, EVENT_LISTENER_OPTIONS)\n\n return () => {\n document.removeEventListener('selectionchange', handleSelectionChange)\n }\n }","[handleSelectionChange]","placeholder = t('compose.create-comment-placeholder')","{\n disabled: !mentionsMenuOpen,\n rootElement: rootElement,\n }","!mentionsMenuOpen","() => <PlaceholderWrapper>{placeholder}</PlaceholderWrapper>","useCallback(\n () => <PlaceholderWrapper>{placeholder}</PlaceholderWrapper>,\n [placeholder],\n )","defineTextBlock({\n type: 'block',\n render: (blockProps) => (\n <div {...blockProps.attributes}>{renderBlock({children: blockProps.children})}</div>\n ),\n })","defineInlineObject({\n type: 'mention',\n render: (mentionProps) =>\n mentionProps.node.userId ? (\n <span {...mentionProps.attributes}>\n {/* Carries the engine's caret spacer; dropping this loses cursor placement around the mention. */}\n {mentionProps.children}\n {/* `draggable` makes the mention movable and keeps its text\n unselectable (a draggable element starts a drag instead of a\n text selection), matching the legacy pipeline's wrapper. */}\n <span draggable={!mentionProps.readOnly} style={{display: 'inline-block'}}>\n <MentionInlineBlock\n selected={mentionProps.selected}\n userId={mentionProps.node.userId as string}\n />\n </span>\n </span>\n ) : (\n mentionProps.renderDefault(mentionProps)\n ),\n })","(mentionProps) =>\n mentionProps.node.userId ? (\n <span {...mentionProps.attributes}>\n {/* Carries the engine's caret spacer; dropping this loses cursor placement around the mention. */}\n {mentionProps.children}\n {/* `draggable` makes the mention movable and keeps its text\n unselectable (a draggable element starts a drag instead of a\n text selection), matching the legacy pipeline's wrapper. */}\n <span draggable={!mentionProps.readOnly} style={{display: 'inline-block'}}>\n <MentionInlineBlock\n selected={mentionProps.selected}\n userId={mentionProps.node.userId as string}\n />\n </span>\n </span>\n ) : (\n mentionProps.renderDefault(mentionProps)\n )","[\n defineTextBlock({\n type: 'block',\n render: (blockProps) => (\n <div {...blockProps.attributes}>{renderBlock({children: blockProps.children})}</div>\n ),\n }),\n defineInlineObject({\n type: 'mention',\n render: (mentionProps) =>\n mentionProps.node.userId ? (\n <span {...mentionProps.attributes}>\n {/* Carries the engine's caret spacer; dropping this loses cursor placement around the mention. */}\n {mentionProps.children}\n {/* `draggable` makes the mention movable and keeps its text\n unselectable (a draggable element starts a drag instead of a\n text selection), matching the legacy pipeline's wrapper. */}\n <span draggable={!mentionProps.readOnly} style={{display: 'inline-block'}}>\n <MentionInlineBlock\n selected={mentionProps.selected}\n userId={mentionProps.node.userId as string}\n />\n </span>\n </span>\n ) : (\n mentionProps.renderDefault(mentionProps)\n ),\n }),\n ]","useMemo(\n () => [\n defineTextBlock({\n type: 'block',\n render: (blockProps) => (\n <div {...blockProps.attributes}>{renderBlock({children: blockProps.children})}</div>\n ),\n }),\n defineInlineObject({\n type: 'mention',\n render: (mentionProps) =>\n mentionProps.node.userId ? (\n <span {...mentionProps.attributes}>\n {/* Carries the engine's caret spacer; dropping this loses cursor placement around the mention. */}\n {mentionProps.children}\n {/* `draggable` makes the mention movable and keeps its text\n unselectable (a draggable element starts a drag instead of a\n text selection), matching the legacy pipeline's wrapper. */}\n <span draggable={!mentionProps.readOnly} style={{display: 'inline-block'}}>\n <MentionInlineBlock\n selected={mentionProps.selected}\n userId={mentionProps.node.userId as string}\n />\n </span>\n </span>\n ) : (\n mentionProps.renderDefault(mentionProps)\n ),\n }),\n ],\n [renderBlock],\n )","() => [popoverRef.current]","(event: KeyboardEvent) => {\n switch (event.key) {\n case 'Enter':\n // Shift enter is used to insert a new line,\n // keep the default behavior\n if (event.shiftKey) {\n break\n }\n\n // If the mention menu is open close it, but don't submit.\n if (mentionsMenuOpen) {\n // Enter is being used both to select something from the mentionsMenu, prevent the default behavior.\n event.preventDefault()\n event.stopPropagation()\n closeMentions()\n break\n }\n\n // Submit the comment if eligible for submission\n if (onSubmit && canSubmit) {\n // Enter is being used to submit the comment, prevent the default behavior.\n event.preventDefault()\n event.stopPropagation()\n onSubmit()\n }\n break\n\n case 'Escape':\n case 'ArrowLeft':\n case 'ArrowRight':\n if (mentionsMenuOpen) {\n // stop these events if the menu is open\n event.preventDefault()\n event.stopPropagation()\n closeMentions()\n }\n break\n default:\n }\n // Call parent key handler\n if (onKeyDown) onKeyDown(event)\n }","useCallback(\n (event: KeyboardEvent) => {\n switch (event.key) {\n case 'Enter':\n // Shift enter is used to insert a new line,\n // keep the default behavior\n if (event.shiftKey) {\n break\n }\n\n // If the mention menu is open close it, but don't submit.\n if (mentionsMenuOpen) {\n // Enter is being used both to select something from the mentionsMenu, prevent the default behavior.\n event.preventDefault()\n event.stopPropagation()\n closeMentions()\n break\n }\n\n // Submit the comment if eligible for submission\n if (onSubmit && canSubmit) {\n // Enter is being used to submit the comment, prevent the default behavior.\n event.preventDefault()\n event.stopPropagation()\n onSubmit()\n }\n break\n\n case 'Escape':\n case 'ArrowLeft':\n case 'ArrowRight':\n if (mentionsMenuOpen) {\n // stop these events if the menu is open\n event.preventDefault()\n event.stopPropagation()\n closeMentions()\n }\n break\n default:\n }\n // Call parent key handler\n if (onKeyDown) onKeyDown(event)\n },\n [canSubmit, closeMentions, mentionsMenuOpen, onKeyDown, onSubmit],\n )","useMemo(() => {\n if (selection) {\n return undefined\n }\n const lastBlock = (value || EMPTY_ARRAY).slice(-1)[0]\n const lastChild = isPortableTextTextBlock(lastBlock)\n ? lastBlock.children.slice(-1)[0]\n : undefined\n if (!lastChild) {\n return undefined\n }\n const point = {\n path: [{_key: lastBlock._key}, 'children', {_key: lastChild._key}],\n offset: isPortableTextSpan(lastChild) ? lastChild.text.length : 0,\n }\n return {\n focus: point,\n anchor: point,\n }\n }, [value, selection])","{\n focus: point,\n anchor: point,\n }","() => {\n mentionsMenuRef.current?.setSearchTerm(mentionsSearchTerm)\n }","[mentionsSearchTerm]","() => {\n if (mentionsMenuOpen && selection && !isEqual(selection.anchor, selection.focus)) {\n closeMentions()\n }\n }","[mentionsMenuOpen, closeMentions, selection]","<MentionsMenu\n inputElement={inputElement}\n loading={mentionOptions.loading}\n onSelect={insertMention}\n options={mentionOptions.data || EMPTY_ARRAY}\n ref={mentionsMenuRef}\n />","loading","mentionOptions.data || EMPTY_ARRAY","<StyledPopover\n arrow={false}\n constrainSize\n content={popoverContent}\n disabled={!mentionsMenuOpen}\n fallbackPlacements={POPOVER_FALLBACK_PLACEMENTS}\n open={mentionsMenuOpen}\n placement=\"bottom\"\n ref={popoverRef}\n referenceElement={cursorElement}\n />","<NodePlugin nodes={nodes} />","<PortableTextEditable\n data-testid=\"comment-input-editable\"\n data-ui=\"EditableElement\"\n onBeforeInput={onBeforeInput}\n onBlur={onBlur}\n onFocus={onFocus}\n onKeyDown={handleKeyDown}\n ref={setInputElement}\n renderPlaceholder={renderPlaceholder}\n selection={initialSelectionAtEndOfContent}\n style={INLINE_STYLE}\n tabIndex={focusLock ? 0 : undefined}\n />","focusLock ? 0 : undefined","<div ref={setRootElement}>\n <StyledPopover\n arrow={false}\n constrainSize\n content={popoverContent}\n disabled={!mentionsMenuOpen}\n fallbackPlacements={POPOVER_FALLBACK_PLACEMENTS}\n open={mentionsMenuOpen}\n placement=\"bottom\"\n ref={popoverRef}\n referenceElement={cursorElement}\n />\n <NodePlugin nodes={nodes} />\n <PortableTextEditable\n data-testid=\"comment-input-editable\"\n data-ui=\"EditableElement\"\n onBeforeInput={onBeforeInput}\n onBlur={onBlur}\n onFocus={onFocus}\n onKeyDown={handleKeyDown}\n ref={setInputElement}\n renderPlaceholder={renderPlaceholder}\n selection={initialSelectionAtEndOfContent}\n style={INLINE_STYLE}\n tabIndex={focusLock ? 0 : undefined}\n />\n </div>","avatarSize = 1","withAvatar ? (\n <AvatarContainer>\n <CommentsAvatar user={user} size={avatarSize} />\n </AvatarContainer>\n ) : null","(e: React.MouseEvent<HTMLButtonElement>) => {\n e.stopPropagation()\n insertAtChar()\n openMentions()\n }","useCallback(\n (e: React.MouseEvent<HTMLButtonElement>) => {\n e.stopPropagation()\n insertAtChar()\n openMentions()\n },\n [insertAtChar, openMentions],\n )","<EditableWrap data-ui=\"CommentInputEditableWrap\" paddingX={1} paddingY={2}>\n <Editable\n focusLock={focusLock}\n onBlur={onBlur}\n onFocus={onFocus}\n onKeyDown={onKeyDown}\n onSubmit={onSubmit}\n placeholder={placeholder}\n renderBlock={renderBlock}\n />\n </EditableWrap>","!mentionOptions.disabled && (\n <Button\n aria-label={t('compose.mention-user-aria-label')}\n data-testid=\"comment-input-mention-button\"\n disabled={readOnly}\n icon={MentionIcon}\n mode=\"bleed\"\n type=\"button\"\n onClick={handleMentionButtonClicked}\n tooltipProps={{content: t('compose.mention-user-tooltip')}}\n />\n )","disabled","onSubmit && (\n <>\n {!mentionOptions.disabled && <ButtonDivider />}\n\n <Button\n aria-label={t('compose.send-comment-aria-label')}\n data-testid=\"comment-input-send-button\"\n disabled={!canSubmit || !hasChanges || readOnly}\n icon={SendIcon}\n mode={hasChanges && canSubmit ? 'default' : 'bleed'}\n onClick={onSubmit}\n tone={hasChanges && canSubmit ? 'primary' : 'default'}\n tooltipProps={{content: t('compose.send-comment-tooltip')}}\n />\n </>\n )","<Flex\n alignItems=\"center\"\n data-ui=\"CommentInputActions\"\n gap={1}\n justifyContent=\"flex-end\"\n padding={1}\n >\n <TooltipDelayGroupProvider>\n {!mentionOptions.disabled && (\n <Button\n aria-label={t('compose.mention-user-aria-label')}\n data-testid=\"comment-input-mention-button\"\n disabled={readOnly}\n icon={MentionIcon}\n mode=\"bleed\"\n type=\"button\"\n onClick={handleMentionButtonClicked}\n tooltipProps={{content: t('compose.mention-user-tooltip')}}\n />\n )}\n {onSubmit && (\n <>\n {!mentionOptions.disabled && <ButtonDivider />}\n\n <Button\n aria-label={t('compose.send-comment-aria-label')}\n data-testid=\"comment-input-send-button\"\n disabled={!canSubmit || !hasChanges || readOnly}\n icon={SendIcon}\n mode={hasChanges && canSubmit ? 'default' : 'bleed'}\n onClick={onSubmit}\n tone={hasChanges && canSubmit ? 'primary' : 'default'}\n tooltipProps={{content: t('compose.send-comment-tooltip')}}\n />\n </>\n )}\n </TooltipDelayGroupProvider>\n </Flex>","<VStack>\n <EditableWrap data-ui=\"CommentInputEditableWrap\" paddingX={1} paddingY={2}>\n <Editable\n focusLock={focusLock}\n onBlur={onBlur}\n onFocus={onFocus}\n onKeyDown={onKeyDown}\n onSubmit={onSubmit}\n placeholder={placeholder}\n renderBlock={renderBlock}\n />\n </EditableWrap>\n\n <Flex\n alignItems=\"center\"\n data-ui=\"CommentInputActions\"\n gap={1}\n justifyContent=\"flex-end\"\n padding={1}\n >\n <TooltipDelayGroupProvider>\n {!mentionOptions.disabled && (\n <Button\n aria-label={t('compose.mention-user-aria-label')}\n data-testid=\"comment-input-mention-button\"\n disabled={readOnly}\n icon={MentionIcon}\n mode=\"bleed\"\n type=\"button\"\n onClick={handleMentionButtonClicked}\n tooltipProps={{content: t('compose.mention-user-tooltip')}}\n />\n )}\n {onSubmit && (\n <>\n {!mentionOptions.disabled && <ButtonDivider />}\n\n <Button\n aria-label={t('compose.send-comment-aria-label')}\n data-testid=\"comment-input-send-button\"\n disabled={!canSubmit || !hasChanges || readOnly}\n icon={SendIcon}\n mode={hasChanges && canSubmit ? 'default' : 'bleed'}\n onClick={onSubmit}\n tone={hasChanges && canSubmit ? 'primary' : 'default'}\n tooltipProps={{content: t('compose.send-comment-tooltip')}}\n />\n </>\n )}\n </TooltipDelayGroupProvider>\n </Flex>\n </VStack>","<RootCard\n id=\"comment-input-root\"\n data-expand-on-focus={expandOnFocus && !canSubmit ? 'true' : 'false'}\n data-focused={focused ? 'true' : 'false'}\n flex={1}\n sizing=\"border\"\n tone={readOnly ? 'transparent' : 'default'}\n >\n <VStack>\n <EditableWrap data-ui=\"CommentInputEditableWrap\" paddingX={1} paddingY={2}>\n <Editable\n focusLock={focusLock}\n onBlur={onBlur}\n onFocus={onFocus}\n onKeyDown={onKeyDown}\n onSubmit={onSubmit}\n placeholder={placeholder}\n renderBlock={renderBlock}\n />\n </EditableWrap>\n\n <Flex\n alignItems=\"center\"\n data-ui=\"CommentInputActions\"\n gap={1}\n justifyContent=\"flex-end\"\n padding={1}\n >\n <TooltipDelayGroupProvider>\n {!mentionOptions.disabled && (\n <Button\n aria-label={t('compose.mention-user-aria-label')}\n data-testid=\"comment-input-mention-button\"\n disabled={readOnly}\n icon={MentionIcon}\n mode=\"bleed\"\n type=\"button\"\n onClick={handleMentionButtonClicked}\n tooltipProps={{content: t('compose.mention-user-tooltip')}}\n />\n )}\n {onSubmit && (\n <>\n {!mentionOptions.disabled && <ButtonDivider />}\n\n <Button\n aria-label={t('compose.send-comment-aria-label')}\n data-testid=\"comment-input-send-button\"\n disabled={!canSubmit || !hasChanges || readOnly}\n icon={SendIcon}\n mode={hasChanges && canSubmit ? 'default' : 'bleed'}\n onClick={onSubmit}\n tone={hasChanges && canSubmit ? 'primary' : 'default'}\n tooltipProps={{content: t('compose.send-comment-tooltip')}}\n />\n </>\n )}\n </TooltipDelayGroupProvider>\n </Flex>\n </VStack>\n </RootCard>","expandOnFocus && !canSubmit ? 'true' : 'false'","focused ? 'true' : 'false'","readOnly ? 'transparent' : 'default'","<Flex alignItems=\"flex-start\" gap={2}>\n {avatar}\n\n <RootCard\n id=\"comment-input-root\"\n data-expand-on-focus={expandOnFocus && !canSubmit ? 'true' : 'false'}\n data-focused={focused ? 'true' : 'false'}\n flex={1}\n sizing=\"border\"\n tone={readOnly ? 'transparent' : 'default'}\n >\n <VStack>\n <EditableWrap data-ui=\"CommentInputEditableWrap\" paddingX={1} paddingY={2}>\n <Editable\n focusLock={focusLock}\n onBlur={onBlur}\n onFocus={onFocus}\n onKeyDown={onKeyDown}\n onSubmit={onSubmit}\n placeholder={placeholder}\n renderBlock={renderBlock}\n />\n </EditableWrap>\n\n <Flex\n alignItems=\"center\"\n data-ui=\"CommentInputActions\"\n gap={1}\n justifyContent=\"flex-end\"\n padding={1}\n >\n <TooltipDelayGroupProvider>\n {!mentionOptions.disabled && (\n <Button\n aria-label={t('compose.mention-user-aria-label')}\n data-testid=\"comment-input-mention-button\"\n disabled={readOnly}\n icon={MentionIcon}\n mode=\"bleed\"\n type=\"button\"\n onClick={handleMentionButtonClicked}\n tooltipProps={{content: t('compose.mention-user-tooltip')}}\n />\n )}\n {onSubmit && (\n <>\n {!mentionOptions.disabled && <ButtonDivider />}\n\n <Button\n aria-label={t('compose.send-comment-aria-label')}\n data-testid=\"comment-input-send-button\"\n disabled={!canSubmit || !hasChanges || readOnly}\n icon={SendIcon}\n mode={hasChanges && canSubmit ? 'default' : 'bleed'}\n onClick={onSubmit}\n tone={hasChanges && canSubmit ? 'primary' : 'default'}\n tooltipProps={{content: t('compose.send-comment-tooltip')}}\n />\n </>\n )}\n </TooltipDelayGroupProvider>\n </Flex>\n </VStack>\n </RootCard>\n </Flex>","expandOnFocus = false","focusOnMount = false","hasCommentMessageValue(value)","useMemo(() => hasCommentMessageValue(value), [value])","() => {\n if (readOnly) return\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n PortableTextEditor.focus(editor)\n }","useCallback(() => {\n if (readOnly) return\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n PortableTextEditor.focus(editor)\n }, [editor, readOnly])","() => {\n setMentionsMenuOpen(false)\n setMentionsSearchTerm('')\n setSelectionAtMentionInsert(null)\n }","useCallback(() => {\n setMentionsMenuOpen(false)\n setMentionsSearchTerm('')\n setSelectionAtMentionInsert(null)\n }, [])","() => {\n if (mentionOptions?.disabled) {\n return\n }\n setMentionsMenuOpen(true)\n setMentionsSearchTerm('')\n setMentionsMenuOpen(true)\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n setSelectionAtMentionInsert(PortableTextEditor.getSelection(editor))\n }","disabled","useCallback(() => {\n if (mentionOptions?.disabled) {\n return\n }\n setMentionsMenuOpen(true)\n setMentionsSearchTerm('')\n setMentionsMenuOpen(true)\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n setSelectionAtMentionInsert(PortableTextEditor.getSelection(editor))\n }, [editor, mentionOptions?.disabled])","(event: InputEvent): void => {\n if (mentionOptions?.disabled) {\n return\n }\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n const selection = PortableTextEditor.getSelection(editor)\n const cursorOffset = selection ? selection.focus.offset : 0\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n const focusChild = PortableTextEditor.focusChild(editor)\n const focusSpan = (isPortableTextSpan(focusChild) && focusChild) || undefined\n\n const isInsertText = event.inputType === 'insertText'\n const isDeleteText = event.inputType === 'deleteContentBackward'\n const isInsertingAtChar = isInsertText && event.data === '@'\n\n const lastIndexOfAt =\n focusSpan?.text.slice(0, Math.max(0, cursorOffset)).lastIndexOf('@') || 0\n\n const isWhitespaceCharBeforeCursorPosition =\n focusSpan?.text.slice(cursorOffset - 1, cursorOffset) === ' '\n\n const filterStartsWithSpaceChar = isInsertText && event.data === ' ' && !mentionsSearchTerm\n\n // If we are inserting a '@' character - open the mentions menu and reset the search term.\n // Only do this if it is in the start of the text, or if '@' is inserted when following a whitespace char.\n if (isInsertingAtChar && (cursorOffset < 1 || isWhitespaceCharBeforeCursorPosition)) {\n openMentions()\n return\n }\n\n // If the user begins typing their filter with a space, or if they are deleting\n // characters after activation and the '@' is no longer there,\n // clear the search term and close the mentions menu.\n if (\n filterStartsWithSpaceChar ||\n (isDeleteText &&\n (focusSpan?.text.length === 1 || lastIndexOfAt === (focusSpan?.text.length || 0) - 1))\n ) {\n closeMentions()\n return\n }\n\n // Update the search term\n if (isPortableTextSpan(focusChild)) {\n // Term starts with the @ char in the value until the cursor offset\n let term = focusChild.text.slice(lastIndexOfAt + 1, cursorOffset)\n // Add the char to the mentions search term\n if (isInsertText) {\n term += event.data\n }\n // Exclude the char from the mentions search term\n if (isDeleteText) {\n term = term.slice(0, Math.max(0, term.length - 1))\n }\n // Set the updated mentions search term\n setMentionsSearchTerm(term)\n }\n }","useCallback(\n (event: InputEvent): void => {\n if (mentionOptions?.disabled) {\n return\n }\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n const selection = PortableTextEditor.getSelection(editor)\n const cursorOffset = selection ? selection.focus.offset : 0\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n const focusChild = PortableTextEditor.focusChild(editor)\n const focusSpan = (isPortableTextSpan(focusChild) && focusChild) || undefined\n\n const isInsertText = event.inputType === 'insertText'\n const isDeleteText = event.inputType === 'deleteContentBackward'\n const isInsertingAtChar = isInsertText && event.data === '@'\n\n const lastIndexOfAt =\n focusSpan?.text.slice(0, Math.max(0, cursorOffset)).lastIndexOf('@') || 0\n\n const isWhitespaceCharBeforeCursorPosition =\n focusSpan?.text.slice(cursorOffset - 1, cursorOffset) === ' '\n\n const filterStartsWithSpaceChar = isInsertText && event.data === ' ' && !mentionsSearchTerm\n\n // If we are inserting a '@' character - open the mentions menu and reset the search term.\n // Only do this if it is in the start of the text, or if '@' is inserted when following a whitespace char.\n if (isInsertingAtChar && (cursorOffset < 1 || isWhitespaceCharBeforeCursorPosition)) {\n openMentions()\n return\n }\n\n // If the user begins typing their filter with a space, or if they are deleting\n // characters after activation and the '@' is no longer there,\n // clear the search term and close the mentions menu.\n if (\n filterStartsWithSpaceChar ||\n (isDeleteText &&\n (focusSpan?.text.length === 1 || lastIndexOfAt === (focusSpan?.text.length || 0) - 1))\n ) {\n closeMentions()\n return\n }\n\n // Update the search term\n if (isPortableTextSpan(focusChild)) {\n // Term starts with the @ char in the value until the cursor offset\n let term = focusChild.text.slice(lastIndexOfAt + 1, cursorOffset)\n // Add the char to the mentions search term\n if (isInsertText) {\n term += event.data\n }\n // Exclude the char from the mentions search term\n if (isDeleteText) {\n term = term.slice(0, Math.max(0, term.length - 1))\n }\n // Set the updated mentions search term\n setMentionsSearchTerm(term)\n }\n },\n [closeMentions, editor, mentionsSearchTerm, openMentions, mentionOptions?.disabled],\n )","() => {\n setMentionsMenuOpen(true)\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n PortableTextEditor.focus(editor)\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n PortableTextEditor.insertChild(editor, editor.schemaTypes.span, {text: '@'})\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n setSelectionAtMentionInsert(PortableTextEditor.getSelection(editor))\n }","useCallback(() => {\n setMentionsMenuOpen(true)\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n PortableTextEditor.focus(editor)\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n PortableTextEditor.insertChild(editor, editor.schemaTypes.span, {text: '@'})\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n setSelectionAtMentionInsert(PortableTextEditor.getSelection(editor))\n }, [editor])","() => onMentionMenuOpenChange?.(mentionsMenuOpen)","(userId: string) => {\n const mentionSchemaType = editor.schemaTypes.inlineObjects.find((t) => t.name === 'mention')\n let mentionPath: Path | undefined\n\n const [span, spanPath] =\n (selectionAtMentionInsert &&\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n PortableTextEditor.findByPath(editor, selectionAtMentionInsert.focus.path)) ||\n []\n if (span && isPortableTextSpan(span) && spanPath && mentionSchemaType) {\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n PortableTextEditor.focus(editor)\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n const offset = PortableTextEditor.getSelection(editor)?.focus.offset\n if (typeof offset !== 'undefined') {\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n PortableTextEditor.delete(\n editor,\n {\n anchor: {path: spanPath, offset: span.text.lastIndexOf('@')},\n focus: {path: spanPath, offset},\n },\n {mode: 'selected'},\n )\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n PortableTextEditor.insertChild(editor, mentionSchemaType, {\n userId: userId,\n })\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n PortableTextEditor.insertChild(editor, editor.schemaTypes.span, {text: ' '})\n }\n }\n }","editor.schemaTypes.inlineObjects","(t) => t.name === 'mention'","useCallback(\n (userId: string) => {\n const mentionSchemaType = editor.schemaTypes.inlineObjects.find((t) => t.name === 'mention')\n let mentionPath: Path | undefined\n\n const [span, spanPath] =\n (selectionAtMentionInsert &&\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n PortableTextEditor.findByPath(editor, selectionAtMentionInsert.focus.path)) ||\n []\n if (span && isPortableTextSpan(span) && spanPath && mentionSchemaType) {\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n PortableTextEditor.focus(editor)\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n const offset = PortableTextEditor.getSelection(editor)?.focus.offset\n if (typeof offset !== 'undefined') {\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n PortableTextEditor.delete(\n editor,\n {\n anchor: {path: spanPath, offset: span.text.lastIndexOf('@')},\n focus: {path: spanPath, offset},\n },\n {mode: 'selected'},\n )\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n PortableTextEditor.insertChild(editor, mentionSchemaType, {\n userId: userId,\n })\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n PortableTextEditor.insertChild(editor, editor.schemaTypes.span, {text: ' '})\n }\n }\n },\n [editor, selectionAtMentionInsert],\n )","{\n canSubmit,\n closeMentions,\n editor,\n expandOnFocus,\n focused,\n focusEditor,\n focusOnMount,\n hasChanges,\n insertAtChar,\n insertMention,\n mentionOptions,\n mentionsMenuOpen,\n mentionsSearchTerm,\n onBeforeInput,\n openMentions,\n readOnly: Boolean(readOnly),\n value,\n }","Boolean(readOnly)","useMemo(\n (): CommentInputContextValue => ({\n canSubmit,\n closeMentions,\n editor,\n expandOnFocus,\n focused,\n focusEditor,\n focusOnMount,\n hasChanges,\n insertAtChar,\n insertMention,\n mentionOptions,\n mentionsMenuOpen,\n mentionsSearchTerm,\n onBeforeInput,\n openMentions,\n readOnly: Boolean(readOnly),\n value,\n }),\n [\n canSubmit,\n closeMentions,\n editor,\n expandOnFocus,\n focused,\n focusEditor,\n focusOnMount,\n hasChanges,\n insertAtChar,\n insertMention,\n mentionOptions,\n mentionsMenuOpen,\n mentionsSearchTerm,\n onBeforeInput,\n openMentions,\n readOnly,\n value,\n ],\n )","<CommentInputContextV2.Provider value={ctxValue}>{children}</CommentInputContextV2.Provider>","CommentInputContextV2.Provider","() => editor","[editor]","focusLock = false","renderBlock = defaultRenderBlock","value = EMPTY_ARRAY","withAvatar = true","keyGenerator()","() => {\n requestAnimationFrame(() => {\n editorRef.current?.send({type: 'focus'})\n })\n }","useCallback(() => {\n requestAnimationFrame(() => {\n editorRef.current?.send({type: 'focus'})\n })\n }, [])","() => {\n // The discarded instance flushes pending mutations during teardown; drop\n // them in `handleEvent` so a finished draft cannot overwrite the\n // consumer's cleared draft state.\n resetInstanceRef.current = true\n setEditorInstanceKey(keyGenerator())\n }","useCallback(() => {\n // The discarded instance flushes pending mutations during teardown; drop\n // them in `handleEvent` so a finished draft cannot overwrite the\n // consumer's cleared draft state.\n resetInstanceRef.current = true\n setEditorInstanceKey(keyGenerator())\n }, [])","(event: EditorEmittedEvent) => {\n // Focus the editor when ready if focusOnMount is true\n if (event.type === 'ready') {\n resetInstanceRef.current = false\n if (focusOnMount) {\n requestFocus()\n }\n }\n if (event.type === 'focused') {\n setFocused(true)\n }\n\n if (event.type === 'blurred') {\n setFocused(false)\n }\n\n // Update the comment value whenever the comment is edited by the user.\n if (event.type === 'mutation' && !resetInstanceRef.current) {\n onChange(event.value || EMPTY_ARRAY)\n }\n }","useCallback(\n (event: EditorEmittedEvent) => {\n // Focus the editor when ready if focusOnMount is true\n if (event.type === 'ready') {\n resetInstanceRef.current = false\n if (focusOnMount) {\n requestFocus()\n }\n }\n if (event.type === 'focused') {\n setFocused(true)\n }\n\n if (event.type === 'blurred') {\n setFocused(false)\n }\n\n // Update the comment value whenever the comment is edited by the user.\n if (event.type === 'mutation' && !resetInstanceRef.current) {\n onChange(event.value || EMPTY_ARRAY)\n }\n },\n [focusOnMount, onChange, requestFocus],\n )","() => {\n editorContainerRef.current?.scrollIntoView(SCROLL_INTO_VIEW_OPTIONS)\n }","useCallback(() => {\n editorContainerRef.current?.scrollIntoView(SCROLL_INTO_VIEW_OPTIONS)\n }, [])","() => {\n // Read the editor's live value directly rather than the value mirrored\n // through the debounced `mutation` event, which can lag the latest\n // keystrokes by up to the flush interval and truncate the comment when\n // the user submits without pausing.\n const currentValue = editorRef.current ? getValue(editorRef.current.getSnapshot()) : EMPTY_ARRAY\n onSubmit?.(currentValue)\n resetEditorInstance()\n requestFocus()\n scrollToEditor()\n }","useCallback(() => {\n // Read the editor's live value directly rather than the value mirrored\n // through the debounced `mutation` event, which can lag the latest\n // keystrokes by up to the flush interval and truncate the comment when\n // the user submits without pausing.\n const currentValue = editorRef.current ? getValue(editorRef.current.getSnapshot()) : EMPTY_ARRAY\n onSubmit?.(currentValue)\n resetEditorInstance()\n requestFocus()\n scrollToEditor()\n }, [onSubmit, requestFocus, resetEditorInstance, scrollToEditor])","() => {\n onDiscardConfirm()\n resetEditorInstance()\n }","useCallback(() => {\n onDiscardConfirm()\n resetEditorInstance()\n }, [onDiscardConfirm, resetEditorInstance])","{\n open: () => {\n setShowDiscardDialog(true)\n },\n close: () => {\n setShowDiscardDialog(false)\n requestFocus()\n },\n }","useMemo((): CommentDiscardDialogController => {\n return {\n open: () => {\n setShowDiscardDialog(true)\n },\n close: () => {\n setShowDiscardDialog(false)\n requestFocus()\n },\n }\n }, [requestFocus])","() => {\n return {\n focus: requestFocus,\n blur() {\n editorRef.current?.send({type: 'blur'})\n },\n scrollTo: scrollToEditor,\n reset: resetEditorInstance,\n\n discardDialogController,\n }\n }","[discardDialogController, requestFocus, resetEditorInstance, scrollToEditor]","(event: FocusEvent<HTMLDivElement>) => {\n if (!focusLock) return\n\n const target = event.target\n const innerEl = innerRef.current\n\n if (innerEl && target === preDivRef.current) {\n focusLastDescendant(innerEl)\n return\n }\n\n if (innerEl && target === postDivRef.current) {\n focusFirstDescendant(innerEl)\n }\n }","event","useCallback(\n (event: FocusEvent<HTMLDivElement>) => {\n if (!focusLock) return\n\n const target = event.target\n const innerEl = innerRef.current\n\n if (innerEl && target === preDivRef.current) {\n focusLastDescendant(innerEl)\n return\n }\n\n if (innerEl && target === postDivRef.current) {\n focusFirstDescendant(innerEl)\n }\n },\n [focusLock],\n )","showDiscardDialog && onDiscardCancel && (\n <CommentInputDiscardDialog onClose={onDiscardCancel} onConfirm={handleDiscardConfirm} />\n )","sanitySchemaToPortableTextSchema(editorSchemaType)","{\n schemaDefinition: sanitySchemaToPortableTextSchema(editorSchemaType),\n initialValue: value || EMPTY_ARRAY,\n readOnly,\n }","value || EMPTY_ARRAY","<EditorRefPlugin ref={editorRef} />","<EventListenerPlugin on={handleEvent} />","<OneLinePlugin />","<UpdateReadOnlyPlugin readOnly={readOnly ?? false} />","readOnly ?? false","<UpdateValuePlugin value={value ?? undefined} />","value ?? undefined","focusLock && <div ref={preDivRef} tabIndex={0} />","<VStack ref={innerRef}>\n <CommentInputInner\n avatarSize={avatarSize}\n currentUser={currentUser}\n focusLock={focusLock}\n onBlur={onBlur}\n onFocus={onFocus}\n onKeyDown={onKeyDown}\n onSubmit={onSubmit && handleSubmit}\n placeholder={placeholder}\n renderBlock={renderBlock}\n withAvatar={withAvatar}\n />\n </VStack>","onSubmit && handleSubmit","focusLock && <div ref={postDivRef} tabIndex={0} />","<CommentInputProvider\n expandOnFocus={expandOnFocus}\n focused={focused}\n focusOnMount={focusOnMount}\n mentionOptions={mentionOptions}\n onMentionMenuOpenChange={onMentionMenuOpenChange}\n readOnly={readOnly}\n value={value}\n >\n {focusLock && <div ref={preDivRef} tabIndex={0} />}\n\n <VStack ref={innerRef}>\n <CommentInputInner\n avatarSize={avatarSize}\n currentUser={currentUser}\n focusLock={focusLock}\n onBlur={onBlur}\n onFocus={onFocus}\n onKeyDown={onKeyDown}\n onSubmit={onSubmit && handleSubmit}\n placeholder={placeholder}\n renderBlock={renderBlock}\n withAvatar={withAvatar}\n />\n </VStack>\n\n {focusLock && <div ref={postDivRef} tabIndex={0} />}\n </CommentInputProvider>","<EditorProvider\n key={editorInstanceKey}\n initialConfig={{\n schemaDefinition: sanitySchemaToPortableTextSchema(editorSchemaType),\n initialValue: value || EMPTY_ARRAY,\n readOnly,\n }}\n >\n <EditorRefPlugin ref={editorRef} />\n <EventListenerPlugin on={handleEvent} />\n <OneLinePlugin />\n <UpdateReadOnlyPlugin readOnly={readOnly ?? false} />\n <UpdateValuePlugin value={value ?? undefined} />\n <CommentInputProvider\n expandOnFocus={expandOnFocus}\n focused={focused}\n focusOnMount={focusOnMount}\n mentionOptions={mentionOptions}\n onMentionMenuOpenChange={onMentionMenuOpenChange}\n readOnly={readOnly}\n value={value}\n >\n {focusLock && <div ref={preDivRef} tabIndex={0} />}\n\n <VStack ref={innerRef}>\n <CommentInputInner\n avatarSize={avatarSize}\n currentUser={currentUser}\n focusLock={focusLock}\n onBlur={onBlur}\n onFocus={onFocus}\n onKeyDown={onKeyDown}\n onSubmit={onSubmit && handleSubmit}\n placeholder={placeholder}\n renderBlock={renderBlock}\n withAvatar={withAvatar}\n />\n </VStack>\n\n {focusLock && <div ref={postDivRef} tabIndex={0} />}\n </CommentInputProvider>\n </EditorProvider>","<VStack ref={editorContainerRef} data-testid=\"comment-input\" onFocus={handleFocus}>\n <EditorProvider\n key={editorInstanceKey}\n initialConfig={{\n schemaDefinition: sanitySchemaToPortableTextSchema(editorSchemaType),\n initialValue: value || EMPTY_ARRAY,\n readOnly,\n }}\n >\n <EditorRefPlugin ref={editorRef} />\n <EventListenerPlugin on={handleEvent} />\n <OneLinePlugin />\n <UpdateReadOnlyPlugin readOnly={readOnly ?? false} />\n <UpdateValuePlugin value={value ?? undefined} />\n <CommentInputProvider\n expandOnFocus={expandOnFocus}\n focused={focused}\n focusOnMount={focusOnMount}\n mentionOptions={mentionOptions}\n onMentionMenuOpenChange={onMentionMenuOpenChange}\n readOnly={readOnly}\n value={value}\n >\n {focusLock && <div ref={preDivRef} tabIndex={0} />}\n\n <VStack ref={innerRef}>\n <CommentInputInner\n avatarSize={avatarSize}\n currentUser={currentUser}\n focusLock={focusLock}\n onBlur={onBlur}\n onFocus={onFocus}\n onKeyDown={onKeyDown}\n onSubmit={onSubmit && handleSubmit}\n placeholder={placeholder}\n renderBlock={renderBlock}\n withAvatar={withAvatar}\n />\n </VStack>\n\n {focusLock && <div ref={postDivRef} tabIndex={0} />}\n </CommentInputProvider>\n </EditorProvider>\n </VStack>","<>\n {showDiscardDialog && onDiscardCancel && (\n <CommentInputDiscardDialog onClose={onDiscardCancel} onConfirm={handleDiscardConfirm} />\n )}\n\n <VStack ref={editorContainerRef} data-testid=\"comment-input\" onFocus={handleFocus}>\n <EditorProvider\n key={editorInstanceKey}\n initialConfig={{\n schemaDefinition: sanitySchemaToPortableTextSchema(editorSchemaType),\n initialValue: value || EMPTY_ARRAY,\n readOnly,\n }}\n >\n <EditorRefPlugin ref={editorRef} />\n <EventListenerPlugin on={handleEvent} />\n <OneLinePlugin />\n <UpdateReadOnlyPlugin readOnly={readOnly ?? false} />\n <UpdateValuePlugin value={value ?? undefined} />\n <CommentInputProvider\n expandOnFocus={expandOnFocus}\n focused={focused}\n focusOnMount={focusOnMount}\n mentionOptions={mentionOptions}\n onMentionMenuOpenChange={onMentionMenuOpenChange}\n readOnly={readOnly}\n value={value}\n >\n {focusLock && <div ref={preDivRef} tabIndex={0} />}\n\n <VStack ref={innerRef}>\n <CommentInputInner\n avatarSize={avatarSize}\n currentUser={currentUser}\n focusLock={focusLock}\n onBlur={onBlur}\n onFocus={onFocus}\n onKeyDown={onKeyDown}\n onSubmit={onSubmit && handleSubmit}\n placeholder={placeholder}\n renderBlock={renderBlock}\n withAvatar={withAvatar}\n />\n </VStack>\n\n {focusLock && <div ref={postDivRef} tabIndex={0} />}\n </CommentInputProvider>\n </EditorProvider>\n </VStack>\n </>","() => {\n editor.send({\n type: 'update readOnly',\n readOnly: props.readOnly,\n })\n }","[editor, props.readOnly]","readOnly","() => {\n editor.send({\n type: 'update value',\n value: props.value,\n })\n }","[editor, props.value]","value"],"sources":["../src/core/comments-v2/hooks/useComments.ts","../src/core/comments-v2/hooks/useCommentsScroll.ts","../src/core/comments-v2/components/pte/blocks/NormalBlock.tsx","../src/core/comments-v2/components/pte/config.ts","../src/core/comments-v2/components/pte/comment-input/CommentInputDiscardDialog.tsx","../src/core/comments-v2/components/avatars/CommentsAvatar.tsx","../src/core/comments-v2/components/icons/MentionIcon.tsx","../src/core/comments-v2/components/icons/SendIcon.tsx","../src/core/comments-v2/components/mentions/MentionsMenuItem.tsx","../src/core/comments-v2/components/mentions/MentionsMenu.tsx","../src/core/comments-v2/components/pte/blocks/MentionInlineBlock.tsx","../src/core/comments-v2/components/pte/comment-input/useCommentInput.ts","../src/core/comments-v2/components/pte/comment-input/useCursorElement.ts","../src/core/comments-v2/components/pte/comment-input/Editable.tsx","../src/core/comments-v2/components/pte/comment-input/CommentInputInner.tsx","../src/core/comments-v2/components/pte/comment-input/CommentInputProvider.tsx","../src/core/comments-v2/components/pte/comment-input/CommentInput.tsx"],"sourcesContent":["import {useContext} from 'react'\nimport {CommentsContextV2} from 'sanity/_singletons'\n\nimport {type CommentsContextValue} from '../context/comments/types'\n\n/**\n * @beta\n * @hidden\n */\nexport function useComments(): CommentsContextValue {\n const value = useContext(CommentsContextV2)\n\n if (!value) {\n throw new Error('useComments must be used within a CommentsProvider')\n }\n\n return value\n}\n","import {useCallback, useEffect, useMemo, useState} from 'react'\nimport scrollIntoViewIfNeeded, {type StandardBehaviorOptions} from 'scroll-into-view-if-needed'\n\nconst BASE_SCROLL_OPTIONS: StandardBehaviorOptions = {\n behavior: 'smooth',\n inline: 'center',\n scrollMode: 'if-needed',\n}\n\nconst GROUP_SCROLL_OPTIONS: StandardBehaviorOptions = {\n ...BASE_SCROLL_OPTIONS,\n block: 'start',\n}\n\nconst INLINE_COMMENT_SCROLL_OPTIONS: StandardBehaviorOptions = {\n ...BASE_SCROLL_OPTIONS,\n block: 'center',\n}\n\nconst SCROLL_TO_FIELD_OPTIONS: StandardBehaviorOptions = {\n ...BASE_SCROLL_OPTIONS,\n block: 'center',\n}\n\nconst SCROLL_TO_COMMENT_OPTIONS: StandardBehaviorOptions = {\n ...BASE_SCROLL_OPTIONS,\n block: 'center',\n}\n\nconst SCROLL_OPTIONS_BY_TYPE: Record<ScrollTargetTypes, StandardBehaviorOptions> = {\n 'comment': SCROLL_TO_COMMENT_OPTIONS,\n 'field': SCROLL_TO_FIELD_OPTIONS,\n 'group': GROUP_SCROLL_OPTIONS,\n 'inline-comment': INLINE_COMMENT_SCROLL_OPTIONS,\n}\n\n/**\n * A utility function that can be used to generate a valid attribute value\n * based on the given ID.\n *\n * Generate a value that can be used as an attribute value in HTML based\n * on the given ID. This is needed because, when we use the path of a field\n * as a data attribute value, we need to escape the value so that it can be\n * queried using `querySelector`.\n *\n * Example:\n *\n * ```js\n * const validId = generateValidAttrValue('[field[_key==\"title\"]')\n *\n * return <div data-field-id={validId}>...</div>\n * ```\n */\nfunction generateValidAttrValue(id: string): string {\n const symbolsToRemove = /[[\\]_\"_=.]/g\n\n const result = id.replace(symbolsToRemove, '')\n\n return result\n}\n\nexport function applyCommentIdAttr(id: string): Record<'data-comments-comment-id', string> {\n return {\n 'data-comments-comment-id': generateValidAttrValue(id),\n }\n}\n\nexport function applyCommentsFieldAttr(id: string): Record<'data-comments-field-id', string> {\n return {\n 'data-comments-field-id': generateValidAttrValue(id),\n }\n}\n\nexport function applyCommentsGroupAttr(id: string): Record<'data-comments-group-id', string> {\n return {\n 'data-comments-group-id': generateValidAttrValue(id),\n }\n}\n\nexport function applyInlineCommentIdAttr(\n id: string,\n): Record<'data-comments-inline-comment-id', string> {\n return {\n 'data-comments-inline-comment-id': generateValidAttrValue(id),\n }\n}\n\ninterface CommentsScrollHookValue {\n /**\n * Scroll to the comment with the given ID.\n */\n scrollToComment: (commentId: string) => void\n /**\n * Scroll to the field with the given ID.\n */\n scrollToField: (fieldId: string) => void\n /**\n * Scroll to the group with the given ID.\n */\n scrollToGroup: (groupId: string) => void\n /**\n * Scroll to the inline comment with the given ID.\n */\n scrollToInlineComment: (commentId: string) => void\n}\n\ninterface CommentsScrollHookOptions {\n boundaryElement?: HTMLElement | null\n}\n\ntype ScrollTargetTypes = 'comment' | 'field' | 'group' | 'inline-comment'\ninterface ScrollTarget {\n type: ScrollTargetTypes\n id: string\n}\n\nexport function useCommentsScroll(opts?: CommentsScrollHookOptions): CommentsScrollHookValue {\n const {boundaryElement} = opts || {}\n const [scrollTarget, setScrollTarget] = useState<ScrollTarget | null>(null)\n\n const scrollOpts: StandardBehaviorOptions = useMemo(() => {\n const options = SCROLL_OPTIONS_BY_TYPE[scrollTarget?.type || 'comment']\n\n // Only apply boundary for 'comment' type scrolls (scrolling within inspector panel)\n // Field, group, and inline-comment scrolls target the document pane and shouldn't be bounded\n const shouldApplyBoundary = scrollTarget?.type === 'comment'\n\n return {\n ...options,\n boundary: shouldApplyBoundary ? boundaryElement : undefined,\n }\n }, [boundaryElement, scrollTarget?.type])\n\n const handleScrollToComment = useCallback((commentId: string) => {\n setScrollTarget({type: 'comment', id: commentId})\n }, [])\n\n const handleScrollToGroup = useCallback((threadId: string) => {\n setScrollTarget({type: 'group', id: threadId})\n }, [])\n\n const handleScrollToField = useCallback((fieldPath: string) => {\n setScrollTarget({type: 'field', id: fieldPath})\n }, [])\n\n const handleScrollToInlineComment = useCallback((commentId: string) => {\n setScrollTarget({type: 'inline-comment', id: commentId})\n }, [])\n\n useEffect(() => {\n const raf = requestAnimationFrame(() => {\n if (!scrollTarget) return\n\n const {type, id} = scrollTarget\n\n const element = document?.querySelector(\n `[data-comments-${type}-id=\"${generateValidAttrValue(id)}\"]`,\n )\n\n if (element) {\n scrollIntoViewIfNeeded(element, scrollOpts)\n }\n })\n\n return () => {\n cancelAnimationFrame(raf)\n }\n }, [scrollOpts, scrollTarget])\n\n const value = useMemo(\n (): CommentsScrollHookValue => ({\n scrollToComment: handleScrollToComment,\n scrollToField: handleScrollToField,\n scrollToGroup: handleScrollToGroup,\n scrollToInlineComment: handleScrollToInlineComment,\n }),\n [handleScrollToComment, handleScrollToField, handleScrollToGroup, handleScrollToInlineComment],\n )\n\n return value\n}\n","import {type ReactNode} from 'react'\nimport {styled} from 'styled-components'\nimport {Text} from 'ui5'\n\nconst NormalText = styled(Text)`\n word-break: break-word;\n`\n\ninterface NormalBlockProps {\n children: ReactNode\n}\n\nexport function NormalBlock(props: NormalBlockProps): React.JSX.Element {\n const {children} = props\n\n return (\n <NormalText size={1} forwardedAs=\"div\" trim={true}>\n {children}\n </NormalText>\n )\n}\n","import {Schema} from '@sanity/schema'\nimport {defineArrayMember, defineField} from '@sanity/types'\n\nconst mentionObject = defineField({\n name: 'mention',\n type: 'object',\n fields: [\n {\n name: 'userId',\n type: 'string',\n },\n ],\n})\n\nconst blockType = defineField({\n type: 'block',\n name: 'block',\n of: [mentionObject],\n marks: {\n annotations: [],\n },\n styles: [{title: 'Normal', value: 'normal'}],\n lists: [],\n})\n\nconst portableTextType = defineArrayMember({\n type: 'array',\n name: 'body',\n of: [blockType],\n})\n\nconst schema = Schema.compile({\n name: 'comments',\n types: [portableTextType],\n})\n\nexport const editorSchemaType = schema.get('body')\n","import {DialogProvider, ThemeColorProvider} from '@sanity/ui'\nimport {type MouseEvent, useCallback} from 'react'\nimport {Text} from 'ui5'\n\nimport {Dialog} from '../../../../../ui-components/dialog/Dialog'\nimport {useTranslation} from '../../../../i18n/hooks/useTranslation'\nimport {commentsLocaleNamespace} from '../../../i18n'\n\nconst Z_OFFSET = 9999999 // Change to appropriate z-offset\n\n/**\n * @beta\n * @hidden\n */\nexport interface CommentInputDiscardDialogProps {\n onClose: () => void\n onConfirm: () => void\n}\n\n/**\n * @beta\n * @hidden\n */\nexport function CommentInputDiscardDialog(props: CommentInputDiscardDialogProps) {\n const {t} = useTranslation(commentsLocaleNamespace)\n const {onClose, onConfirm} = props\n\n const handleCancelClick = useCallback(\n (e: MouseEvent<HTMLButtonElement>) => {\n e.stopPropagation()\n onClose()\n },\n [onClose],\n )\n\n const handleConfirmClick = useCallback(\n (e: MouseEvent<HTMLButtonElement>) => {\n e.stopPropagation()\n onConfirm()\n },\n [onConfirm],\n )\n\n // The ThemeColorProvider is needed to make sure that the backdrop of the dialog not\n // inherits the tone of parent color providers.\n // The PortalProvider and DialogProvider is needed to make sure that the dialog is\n // rendered fullscreen and not scoped to the form view.\n return (\n <ThemeColorProvider tone=\"default\">\n <DialogProvider zOffset={Z_OFFSET}>\n <Dialog\n header={t('discard.header')}\n id=\"discard-comment-dialog\"\n onClose={onClose}\n width={0}\n onClickOutside={onClose}\n footer={{\n cancelButton: {\n onClick: handleCancelClick,\n },\n confirmButton: {\n onClick: handleConfirmClick,\n text: t('discard.button-confirm'),\n tone: 'critical',\n },\n }}\n >\n <Text size={1} as=\"div\" trim={true}>\n {t('discard.text')}\n </Text>\n </Dialog>\n </DialogProvider>\n </ThemeColorProvider>\n )\n}\n","import {type User} from '@sanity/types'\nimport {Avatar, type AvatarProps} from '@sanity/ui'\nimport {useMemo} from 'react'\nimport {styled} from 'styled-components'\n\nconst StyledAvatar = styled(Avatar)`\n svg > ellipse {\n stroke: transparent;\n }\n`\n\nconst SYMBOLS = /[^\\p{Alpha}\\p{White_Space}]/gu\nconst WHITESPACE = /\\p{White_Space}+/u\n\nfunction nameToInitials(fullName: string) {\n const namesArray = fullName.replace(SYMBOLS, '').split(WHITESPACE)\n\n if (namesArray.length === 1) {\n return `${namesArray[0].charAt(0)}`.toUpperCase()\n }\n\n return `${namesArray[0].charAt(0)}${namesArray[namesArray.length - 1].charAt(0)}`\n}\n\ninterface CommentsAvatarProps extends AvatarProps {\n user: User | undefined | null\n}\n\nexport function CommentsAvatar(props: CommentsAvatarProps) {\n const {user: userProp, ...restProps} = props\n const user = userProp as User\n const initials = useMemo(() => nameToInitials(user?.displayName || ''), [user?.displayName])\n\n if (!user) return <StyledAvatar {...restProps} />\n\n return (\n <StyledAvatar\n initials={initials}\n src={user?.imageUrl}\n title={user?.displayName}\n {...restProps}\n />\n )\n}\n","import {type RefAttributes, type SVGProps} from 'react'\n\nexport function MentionIcon(props: SVGProps<SVGSVGElement> & RefAttributes<SVGSVGElement>) {\n const {ref, ...rest} = props\n return (\n <svg\n data-sanity-icon=\"mention\"\n fill=\"none\"\n height=\"1em\"\n ref={ref}\n viewBox=\"0 0 25 25\"\n width=\"1em\"\n xmlns=\"http://www.w3.org/2000/svg\"\n {...rest}\n >\n <path\n d=\"M16.6633 18.9383C15.539 19.6562 14.2034 20.0723 12.7705 20.0723C8.77022 20.0723 5.52734 16.8294 5.52734 12.8291C5.52734 8.82881 8.77022 5.58594 12.7705 5.58594C16.7708 5.58594 20.0137 8.82881 20.0137 12.8291C20.0137 13.6623 19.8249 14.7093 19.6141 15.2077C19.5578 15.3408 19.479 15.4845 19.3936 15.6238C19.0955 16.1106 18.5507 16.3721 17.9807 16.4018V16.4018C16.8271 16.462 15.8588 15.5428 15.8588 14.3877V9.27302\"\n stroke=\"currentColor\"\n strokeWidth={1.2}\n strokeLinejoin=\"round\"\n />\n <circle cx=\"12.5732\" cy=\"12.8291\" r=\"3.08691\" stroke=\"currentColor\" strokeWidth={1.2} />\n </svg>\n )\n}\n","import {type RefAttributes, type SVGProps} from 'react'\n\nexport function SendIcon(props: SVGProps<SVGSVGElement> & RefAttributes<SVGSVGElement>) {\n const {ref, ...rest} = props\n return (\n <svg\n data-sanity-icon=\"send\"\n fill=\"none\"\n height=\"1em\"\n ref={ref}\n viewBox=\"0 0 25 25\"\n width=\"1em\"\n xmlns=\"http://www.w3.org/2000/svg\"\n {...rest}\n >\n <path\n clipRule=\"evenodd\"\n d=\"M21.1602 12.5L7.16016 19.5V14.8765L13.6656 12.4989L7.16016 9.97149L7.16016 5.5L21.1602 12.5Z\"\n stroke=\"currentColor\"\n strokeWidth={1.2}\n strokeLinejoin=\"round\"\n />\n </svg>\n )\n}\n","import {Badge, Card, TextSkeleton} from '@sanity/ui'\nimport {type CSSProperties, useCallback} from 'react'\nimport {styled} from 'styled-components'\nimport {Text, Box, Flex} from 'ui5'\n\nimport {type UserWithPermission} from '../../../hooks/useUserListWithPermissions'\nimport {useTranslation} from '../../../i18n/hooks/useTranslation'\nimport {useUser} from '../../../store/user/hooks'\nimport {commentsLocaleNamespace} from '../../i18n'\nimport {CommentsAvatar} from '../avatars/CommentsAvatar'\n\nconst InnerFlex = styled(Flex)``\n\nconst SKELETON_INLINE_STYLE: CSSProperties = {width: '50%'}\n\ninterface MentionsItemProps {\n user: UserWithPermission\n onSelect: (userId: string) => void\n}\n\nexport function MentionsMenuItem(props: MentionsItemProps) {\n const {user, onSelect} = props\n const [loadedUser] = useUser(user.id)\n const {t} = useTranslation(commentsLocaleNamespace)\n\n const avatar = <CommentsAvatar user={loadedUser} status={user.granted ? undefined : 'inactive'} />\n\n const text = loadedUser ? (\n <Text size={1} truncate={1} title={loadedUser.displayName} as=\"div\" trim={true}>\n {loadedUser.displayName}\n </Text>\n ) : (\n <TextSkeleton size={1} style={SKELETON_INLINE_STYLE} />\n )\n\n const handleSelect = useCallback(() => {\n onSelect(user.id)\n }, [onSelect, user.id])\n\n return (\n <Card as=\"button\" disabled={!user.granted} onClick={handleSelect} padding={2} radius={2}>\n <Flex alignItems=\"center\" gap={3}>\n <InnerFlex alignItems=\"center\" gap={2} flexBasis=\"0%\" flexGrow={1}>\n {avatar}\n <Box>{text}</Box>\n </InnerFlex>\n\n {!user.granted && <Badge fontSize={1}>{t('mentions.unauthorized-user')}</Badge>}\n </Flex>\n </Card>\n )\n}\n","import deburr from 'lodash-es/deburr.js'\nimport {\n type Ref,\n useCallback,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n type RefAttributes,\n} from 'react'\nimport {styled} from 'styled-components'\nimport {Text, Box, Flex, VStack} from 'ui5'\n\nimport {CommandList} from '../../../components/commandList/CommandList'\nimport {type CommandListHandle} from '../../../components/commandList/types'\nimport {LoadingBlock} from '../../../components/loadingBlock/LoadingBlock'\nimport {type UserWithPermission} from '../../../hooks/useUserListWithPermissions'\nimport {useTranslation} from '../../../i18n/hooks/useTranslation'\nimport {commentsLocaleNamespace} from '../../i18n'\nimport {MentionsMenuItem} from './MentionsMenuItem'\n\nconst EMPTY_ARRAY: UserWithPermission[] = []\n\nconst Root = styled(VStack)({\n maxWidth: '220px', // todo: improve\n})\n\nconst ITEM_HEIGHT = 41\nconst LIST_PADDING = 4\nconst MAX_ITEMS = 7\n\nconst FlexWrap = styled(Flex)({\n maxHeight: ITEM_HEIGHT * MAX_ITEMS + LIST_PADDING * 2 + ITEM_HEIGHT / 2,\n})\n\nexport interface MentionsMenuHandle {\n setSearchTerm: (term: string) => void\n}\ninterface MentionsMenuProps {\n loading: boolean\n inputElement?: HTMLDivElement | null\n onSelect: (userId: string) => void\n options: UserWithPermission[] | null\n}\n\nexport function MentionsMenu(props: MentionsMenuProps & RefAttributes<MentionsMenuHandle>) {\n const {t} = useTranslation(commentsLocaleNamespace)\n const {ref, loading, onSelect, options = [], inputElement} = props\n const [searchTerm, setSearchTerm] = useState<string>('')\n const commandListRef = useRef<CommandListHandle>(null)\n\n useImperativeHandle(ref, () => {\n return {\n setSearchTerm(term: string) {\n setSearchTerm(term)\n },\n }\n }, [])\n\n const renderItem = useCallback(\n (itemProps: UserWithPermission) => {\n return <MentionsMenuItem user={itemProps} onSelect={onSelect} />\n },\n [onSelect],\n )\n\n const getItemDisabled = useCallback(\n (index: number) => {\n return !options?.[index]?.granted\n },\n [options],\n )\n\n const filteredOptions = useMemo(() => {\n if (!searchTerm) return options || EMPTY_ARRAY\n\n // We deburr the search term and the display names so that when searching\n // for e.g \"bjorge\" we also get results for \"bjørge\"\n const deburredSearchTerm = deburr(searchTerm).toLocaleLowerCase()\n\n const deburredOptions = options?.map((option) => ({\n ...option,\n displayName: deburr(option.displayName || '').toLocaleLowerCase(),\n }))\n\n const filtered = deburredOptions\n ?.filter((option) => {\n return option?.displayName?.includes(deburredSearchTerm)\n })\n // Sort by whether the displayName starts with the search term to get more relevant results first\n ?.sort((a, b) => {\n const matchA = a.displayName?.startsWith(deburredSearchTerm)\n const matchB = b.displayName?.startsWith(deburredSearchTerm)\n\n if (matchA && !matchB) return -1\n if (!matchA && matchB) return 1\n\n return 0\n })\n\n return filtered || EMPTY_ARRAY\n }, [options, searchTerm])\n\n if (loading) {\n return (\n <Root>\n <LoadingBlock showText />\n </Root>\n )\n }\n\n // In this case the input element is the actual content editable HTMLDivElement from the PTE.\n // Typecast it to an input element to make the CommandList component happy.\n const _inputElement = inputElement ? (inputElement as HTMLInputElement) : undefined\n\n return (\n <Flex flexDirection=\"column\" height=\"100%\" data-testid=\"comments-mentions-menu\">\n {filteredOptions.length === 0 && (\n <Box padding={5}>\n <Text align=\"center\" size={1} muted as=\"div\" trim={true}>\n {t('mentions.no-users-found')}\n </Text>\n </Box>\n )}\n\n {filteredOptions.length > 0 && (\n <FlexWrap flexDirection=\"column\" flexBasis=\"0%\" flexGrow={1} overflow=\"hidden\">\n <CommandList\n activeItemDataAttr=\"data-hovered\"\n ariaLabel={t('mentions.user-list-aria-label')}\n fixedHeight\n getItemDisabled={getItemDisabled}\n inputElement={_inputElement}\n itemHeight={41}\n items={filteredOptions}\n padding={1}\n ref={commandListRef}\n renderItem={renderItem}\n />\n </FlexWrap>\n )}\n </Flex>\n )\n}\n","import {TextSkeleton} from '@sanity/ui'\nimport {css, styled} from 'styled-components'\nimport {Text, Flex} from 'ui5'\n\nimport {Tooltip} from '../../../../../ui-components/tooltip/Tooltip'\nimport {useCurrentUser, useUser} from '../../../../store/user/hooks'\nimport {CommentsAvatar} from '../../avatars/CommentsAvatar'\n\nconst Span = styled.span(({theme}) => {\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n const {regular} = theme.sanity.fonts?.text.weights || {}\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n const {hovered} = theme.sanity.color?.card || {}\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n const {bg} = theme.sanity.color.selectable?.caution.pressed || {}\n\n return css`\n font-weight: ${regular};\n color: var(--card-link-fg-color);\n border-radius: 2px;\n background-color: ${hovered.bg};\n padding: 1px;\n box-sizing: border-box;\n\n &[data-active='true'] {\n background-color: ${bg};\n }\n `\n})\n\ninterface MentionInlineBlockProps {\n userId: string\n selected: boolean\n}\n\nexport function MentionInlineBlock(props: MentionInlineBlockProps) {\n const {selected, userId} = props\n const [user, loading] = useUser(userId)\n const currentUser = useCurrentUser()\n\n if (!user || loading)\n return (\n <TextSkeleton\n data-testid=\"comment-mentions-loading-skeleton\"\n style={{width: '10ch'}}\n size={0}\n muted\n radius={1}\n animated\n />\n )\n\n return (\n <Tooltip\n portal\n content={\n <Flex alignItems=\"center\" gap={2}>\n <Flex>\n <CommentsAvatar user={user} />\n </Flex>\n\n <Text size={1} as=\"div\" trim={true}>\n {user.displayName}\n </Text>\n </Flex>\n }\n >\n <Span data-selected={selected} data-active={currentUser?.sanityUserId === userId}>\n @{user.displayName}\n </Span>\n </Tooltip>\n )\n}\n","import {useContext} from 'react'\nimport {CommentInputContextV2} from 'sanity/_singletons'\n\nimport {type CommentInputContextValue} from './CommentInputProvider'\n\nexport function useCommentInput(): CommentInputContextValue {\n const ctx = useContext(CommentInputContextV2)\n\n if (!ctx) {\n throw new Error('useCommentInputContext must be used within a CommentInputProvider')\n }\n\n return ctx\n}\n","import {useCallback, useEffect, useMemo, useState} from 'react'\n\nconst EVENT_LISTENER_OPTIONS: AddEventListenerOptions = {passive: true}\n\ninterface CursorElementHookOptions {\n disabled: boolean\n rootElement: HTMLElement | null\n}\n\nexport function useCursorElement(opts: CursorElementHookOptions): HTMLElement | null {\n const {disabled, rootElement} = opts\n const [cursorRect, setCursorRect] = useState<DOMRect | null>(null)\n\n const cursorElement = useMemo(() => {\n if (!cursorRect) {\n return null\n }\n return {\n getBoundingClientRect: () => {\n return cursorRect\n },\n } as HTMLElement\n }, [cursorRect])\n\n const handleSelectionChange = useCallback(() => {\n if (disabled) {\n setCursorRect(null)\n return\n }\n\n const sel = window.getSelection()\n\n if (!sel || !sel.isCollapsed || sel.rangeCount === 0) return\n\n const range = sel.getRangeAt(0)\n const isWithinRoot = rootElement?.contains(range.commonAncestorContainer)\n\n if (!isWithinRoot) {\n setCursorRect(null)\n return\n }\n const rect = range?.getBoundingClientRect()\n if (rect) {\n setCursorRect(rect)\n }\n }, [disabled, rootElement])\n\n useEffect(() => {\n document.addEventListener('selectionchange', handleSelectionChange, EVENT_LISTENER_OPTIONS)\n\n return () => {\n document.removeEventListener('selectionchange', handleSelectionChange)\n }\n }, [handleSelectionChange])\n\n return cursorElement\n}\n","import {\n defineInlineObject,\n defineTextBlock,\n type EditorSelection,\n PortableTextEditable,\n usePortableTextEditorSelection,\n} from '@portabletext/editor'\nimport {NodePlugin} from '@portabletext/editor/plugins'\nimport {isPortableTextSpan, isPortableTextTextBlock} from '@sanity/types'\nimport {useClickOutsideEvent} from '@sanity/ui'\nimport {getTheme_v2} from '@sanity/ui/theme'\nimport {dequal as isEqual} from 'dequal/lite'\nimport {type KeyboardEvent, useCallback, useEffect, useMemo, useRef, useState} from 'react'\nimport {css, styled} from 'styled-components'\n\nimport {Popover, type PopoverProps} from '../../../../../ui-components/popover/Popover'\nimport {useTranslation} from '../../../../i18n/hooks/useTranslation'\nimport {commentsLocaleNamespace} from '../../../i18n'\nimport {MentionsMenu, type MentionsMenuHandle} from '../../mentions/MentionsMenu'\nimport {MentionInlineBlock} from '../blocks/MentionInlineBlock'\nimport {type CommentInputRenderBlock} from './CommentInput'\nimport {useCommentInput} from './useCommentInput'\nimport {useCursorElement} from './useCursorElement'\n\nconst POPOVER_FALLBACK_PLACEMENTS: PopoverProps['fallbackPlacements'] = ['bottom', 'top']\nconst INLINE_STYLE: React.CSSProperties = {outline: 'none'}\nconst EMPTY_ARRAY: [] = []\n\nconst PlaceholderWrapper = styled.span((props) => {\n const {color} = getTheme_v2(props.theme)\n return css`\n color: ${color.input.default.enabled.placeholder};\n overflow: hidden;\n text-overflow: ellipsis;\n text-wrap: nowrap;\n display: block;\n `\n})\n\nconst StyledPopover = styled(Popover)(({theme}) => {\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n const {space, radius} = theme.sanity\n\n return css`\n &[data-placement='bottom'] {\n transform: translateY(${space[1]}px);\n }\n\n &[data-placement='top'] {\n transform: translateY(-${space[1]}px);\n }\n\n [data-ui='Popover__wrapper'] {\n border-radius: ${radius[3]}px;\n display: flex;\n flex-direction: column;\n overflow: clip;\n overflow: hidden;\n position: relative;\n width: 300px; // todo: improve\n }\n `\n})\n\ninterface EditableProps {\n focusLock?: boolean\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n onBlur?: (e: React.FormEvent<HTMLDivElement>) => void\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n onFocus?: (e: React.FormEvent<HTMLDivElement>) => void\n onKeyDown?: (e: React.KeyboardEvent) => void\n onSubmit?: () => void\n placeholder?: React.ReactNode\n renderBlock: CommentInputRenderBlock\n}\n\ninterface EditableHandle {\n setShowMentionOptions: (show: boolean) => void\n}\n\nexport function Editable(props: EditableProps) {\n const {t} = useTranslation(commentsLocaleNamespace)\n const {\n focusLock,\n onFocus,\n onBlur,\n onKeyDown,\n onSubmit,\n placeholder = t('compose.create-comment-placeholder'),\n renderBlock,\n } = props\n const popoverRef = useRef<HTMLDivElement | null>(null)\n const [rootElement, setRootElement] = useState<HTMLDivElement | null>(null)\n const [inputElement, setInputElement] = useState<HTMLDivElement | null>(null)\n const mentionsMenuRef = useRef<MentionsMenuHandle | null>(null)\n\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n const selection = usePortableTextEditorSelection()\n\n const {\n canSubmit,\n closeMentions,\n insertMention,\n mentionOptions,\n mentionsMenuOpen,\n mentionsSearchTerm,\n onBeforeInput,\n value,\n } = useCommentInput()\n\n const cursorElement = useCursorElement({\n disabled: !mentionsMenuOpen,\n rootElement: rootElement,\n })\n\n const renderPlaceholder = useCallback(\n () => <PlaceholderWrapper>{placeholder}</PlaceholderWrapper>,\n [placeholder],\n )\n\n const nodes = useMemo(\n () => [\n defineTextBlock({\n type: 'block',\n render: (blockProps) => (\n <div {...blockProps.attributes}>{renderBlock({children: blockProps.children})}</div>\n ),\n }),\n defineInlineObject({\n type: 'mention',\n render: (mentionProps) =>\n mentionProps.node.userId ? (\n <span {...mentionProps.attributes}>\n {/* Carries the engine's caret spacer; dropping this loses cursor placement around the mention. */}\n {mentionProps.children}\n {/* `draggable` makes the mention movable and keeps its text\n unselectable (a draggable element starts a drag instead of a\n text selection), matching the legacy pipeline's wrapper. */}\n <span draggable={!mentionProps.readOnly} style={{display: 'inline-block'}}>\n <MentionInlineBlock\n selected={mentionProps.selected}\n userId={mentionProps.node.userId as string}\n />\n </span>\n </span>\n ) : (\n mentionProps.renderDefault(mentionProps)\n ),\n }),\n ],\n [renderBlock],\n )\n\n useClickOutsideEvent(mentionsMenuOpen && closeMentions, () => [popoverRef.current])\n\n const handleKeyDown = useCallback(\n (event: KeyboardEvent) => {\n switch (event.key) {\n case 'Enter':\n // Shift enter is used to insert a new line,\n // keep the default behavior\n if (event.shiftKey) {\n break\n }\n\n // If the mention menu is open close it, but don't submit.\n if (mentionsMenuOpen) {\n // Enter is being used both to select something from the mentionsMenu, prevent the default behavior.\n event.preventDefault()\n event.stopPropagation()\n closeMentions()\n break\n }\n\n // Submit the comment if eligible for submission\n if (onSubmit && canSubmit) {\n // Enter is being used to submit the comment, prevent the default behavior.\n event.preventDefault()\n event.stopPropagation()\n onSubmit()\n }\n break\n\n case 'Escape':\n case 'ArrowLeft':\n case 'ArrowRight':\n if (mentionsMenuOpen) {\n // stop these events if the menu is open\n event.preventDefault()\n event.stopPropagation()\n closeMentions()\n }\n break\n default:\n }\n // Call parent key handler\n if (onKeyDown) onKeyDown(event)\n },\n [canSubmit, closeMentions, mentionsMenuOpen, onKeyDown, onSubmit],\n )\n\n const initialSelectionAtEndOfContent: EditorSelection | undefined = useMemo(() => {\n if (selection) {\n return undefined\n }\n const lastBlock = (value || EMPTY_ARRAY).slice(-1)[0]\n const lastChild = isPortableTextTextBlock(lastBlock)\n ? lastBlock.children.slice(-1)[0]\n : undefined\n if (!lastChild) {\n return undefined\n }\n const point = {\n path: [{_key: lastBlock._key}, 'children', {_key: lastChild._key}],\n offset: isPortableTextSpan(lastChild) ? lastChild.text.length : 0,\n }\n return {\n focus: point,\n anchor: point,\n }\n }, [value, selection])\n\n // Update the mentions search term in the mentions menu\n useEffect(() => {\n mentionsMenuRef.current?.setSearchTerm(mentionsSearchTerm)\n }, [mentionsSearchTerm])\n\n // Close mentions if the user selects text\n useEffect(() => {\n if (mentionsMenuOpen && selection && !isEqual(selection.anchor, selection.focus)) {\n closeMentions()\n }\n }, [mentionsMenuOpen, closeMentions, selection])\n\n const popoverContent = (\n <MentionsMenu\n inputElement={inputElement}\n loading={mentionOptions.loading}\n onSelect={insertMention}\n options={mentionOptions.data || EMPTY_ARRAY}\n ref={mentionsMenuRef}\n />\n )\n\n return (\n <div ref={setRootElement}>\n <StyledPopover\n arrow={false}\n constrainSize\n content={popoverContent}\n disabled={!mentionsMenuOpen}\n fallbackPlacements={POPOVER_FALLBACK_PLACEMENTS}\n open={mentionsMenuOpen}\n placement=\"bottom\"\n ref={popoverRef}\n referenceElement={cursorElement}\n />\n <NodePlugin nodes={nodes} />\n <PortableTextEditable\n data-testid=\"comment-input-editable\"\n data-ui=\"EditableElement\"\n onBeforeInput={onBeforeInput}\n onBlur={onBlur}\n onFocus={onFocus}\n onKeyDown={handleKeyDown}\n ref={setInputElement}\n renderPlaceholder={renderPlaceholder}\n selection={initialSelectionAtEndOfContent}\n style={INLINE_STYLE}\n tabIndex={focusLock ? 0 : undefined}\n />\n </div>\n )\n}\n","import {type CurrentUser} from '@sanity/types'\nimport {type AvatarSize, Card} from '@sanity/ui'\nimport {MenuDivider} from '@sanity/ui/menu'\nimport {getTheme_v2} from '@sanity/ui/theme'\nimport {useCallback} from 'react'\nimport {css, styled} from 'styled-components'\nimport {Box, Flex, VStack} from 'ui5'\n\nimport {Button} from '../../../../../ui-components/button/Button'\nimport {TooltipDelayGroupProvider} from '../../../../../ui-components/tooltipDelayGroupProvider/TooltipDelayGroupProvider'\nimport {useTranslation} from '../../../../i18n/hooks/useTranslation'\nimport {useUser} from '../../../../store/user/hooks'\nimport {commentsLocaleNamespace} from '../../../i18n'\nimport {CommentsAvatar} from '../../avatars/CommentsAvatar'\nimport {MentionIcon} from '../../icons/MentionIcon'\nimport {SendIcon} from '../../icons/SendIcon'\nimport {type CommentInputRenderBlock} from './CommentInput'\nimport {Editable} from './Editable'\nimport {useCommentInput} from './useCommentInput'\n\nconst EditableWrap = styled(Box)`\n max-height: 20vh;\n overflow-y: auto;\n`\n\nconst ButtonDivider = styled(MenuDivider)({\n height: 20,\n width: 1,\n})\n\nfunction focusRingBorderStyle(border: {color: string; width: number}): string {\n return `inset 0 0 0 ${border.width}px ${border.color}`\n}\n\nconst RootCard = styled(Card)(({theme}) => {\n const {color, input, radius} = getTheme_v2(theme)\n const radii = radius[2]\n\n return css`\n border-radius: ${radii}px;\n box-shadow: var(--input-box-shadow);\n\n --input-box-shadow: ${focusRingBorderStyle({\n color: color.input.default.enabled.border,\n width: input.border.width,\n })};\n\n &:not([data-expand-on-focus='false'], :focus-within) {\n background: transparent;\n box-shadow: unset;\n }\n\n &[data-focused='true']:focus-within {\n ${EditableWrap} {\n min-height: 1em;\n }\n\n /* box-shadow: inset 0 0 0 1px var(--card-focus-ring-color); */\n --input-box-shadow: ${focusRingBorderStyle({\n color: 'var(--card-focus-ring-color)',\n width: input.border.width,\n })};\n }\n\n &:focus-within {\n ${EditableWrap} {\n min-height: 1em;\n }\n }\n\n &[data-expand-on-focus='false'] {\n ${EditableWrap} {\n min-height: 1em;\n }\n }\n\n &[data-expand-on-focus='true'] {\n [data-ui='CommentInputActions']:not([hidden]) {\n display: none;\n }\n\n &:focus-within {\n [data-ui='CommentInputActions'] {\n display: flex;\n }\n }\n }\n &:hover {\n --input-box-shadow: ${focusRingBorderStyle({\n color: color.input.default.hovered.border,\n width: input.border.width,\n })};\n }\n `\n})\n\nconst AvatarContainer = styled.div((props) => {\n const theme = getTheme_v2(props.theme)\n return `\n min-height: ${theme.avatar.sizes[1]?.size}px;\n display: flex;\n align-items: center;\n `\n})\n\ninterface CommentInputInnerProps {\n avatarSize?: AvatarSize\n currentUser: CurrentUser\n focusLock?: boolean\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n onBlur?: (e: React.FormEvent<HTMLDivElement>) => void\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n onFocus?: (e: React.FormEvent<HTMLDivElement>) => void\n onKeyDown?: (e: React.KeyboardEvent) => void\n onSubmit?: () => void\n placeholder?: React.ReactNode\n renderBlock: CommentInputRenderBlock\n withAvatar?: boolean\n}\n\nexport function CommentInputInner(props: CommentInputInnerProps) {\n const {\n avatarSize = 1,\n currentUser,\n focusLock,\n onBlur,\n onFocus,\n onKeyDown,\n onSubmit,\n placeholder,\n renderBlock,\n withAvatar,\n } = props\n\n const [user] = useUser(currentUser.id)\n const {\n canSubmit,\n expandOnFocus,\n focused,\n hasChanges,\n insertAtChar,\n openMentions,\n readOnly,\n mentionOptions,\n } = useCommentInput()\n\n const {t} = useTranslation(commentsLocaleNamespace)\n const avatar = withAvatar ? (\n <AvatarContainer>\n <CommentsAvatar user={user} size={avatarSize} />\n </AvatarContainer>\n ) : null\n\n const handleMentionButtonClicked = useCallback(\n (e: React.MouseEvent<HTMLButtonElement>) => {\n e.stopPropagation()\n insertAtChar()\n openMentions()\n },\n [insertAtChar, openMentions],\n )\n\n return (\n <Flex alignItems=\"flex-start\" gap={2}>\n {avatar}\n\n <RootCard\n id=\"comment-input-root\"\n data-expand-on-focus={expandOnFocus && !canSubmit ? 'true' : 'false'}\n data-focused={focused ? 'true' : 'false'}\n flex={1}\n sizing=\"border\"\n tone={readOnly ? 'transparent' : 'default'}\n >\n <VStack>\n <EditableWrap data-ui=\"CommentInputEditableWrap\" paddingX={1} paddingY={2}>\n <Editable\n focusLock={focusLock}\n onBlur={onBlur}\n onFocus={onFocus}\n onKeyDown={onKeyDown}\n onSubmit={onSubmit}\n placeholder={placeholder}\n renderBlock={renderBlock}\n />\n </EditableWrap>\n\n <Flex\n alignItems=\"center\"\n data-ui=\"CommentInputActions\"\n gap={1}\n justifyContent=\"flex-end\"\n padding={1}\n >\n <TooltipDelayGroupProvider>\n {!mentionOptions.disabled && (\n <Button\n aria-label={t('compose.mention-user-aria-label')}\n data-testid=\"comment-input-mention-button\"\n disabled={readOnly}\n icon={MentionIcon}\n mode=\"bleed\"\n type=\"button\"\n onClick={handleMentionButtonClicked}\n tooltipProps={{content: t('compose.mention-user-tooltip')}}\n />\n )}\n {onSubmit && (\n <>\n {!mentionOptions.disabled && <ButtonDivider />}\n\n <Button\n aria-label={t('compose.send-comment-aria-label')}\n data-testid=\"comment-input-send-button\"\n disabled={!canSubmit || !hasChanges || readOnly}\n icon={SendIcon}\n mode={hasChanges && canSubmit ? 'default' : 'bleed'}\n onClick={onSubmit}\n tone={hasChanges && canSubmit ? 'primary' : 'default'}\n tooltipProps={{content: t('compose.send-comment-tooltip')}}\n />\n </>\n )}\n </TooltipDelayGroupProvider>\n </Flex>\n </VStack>\n </RootCard>\n </Flex>\n )\n}\n","import {type EditorSelection, PortableTextEditor, usePortableTextEditor} from '@portabletext/editor'\nimport {isPortableTextSpan, type Path} from '@sanity/types'\nimport {type ReactNode, useCallback, useMemo, useState} from 'react'\nimport {CommentInputContextV2} from 'sanity/_singletons'\n\nimport {useDidUpdate} from '../../../../form/hooks/useDidUpdate'\nimport {type UserListWithPermissionsHookValue} from '../../../../hooks/useUserListWithPermissions'\nimport {hasCommentMessageValue, useCommentHasChanged} from '../../../helpers'\nimport {type CommentMessage} from '../../../types'\n\nexport interface CommentInputContextValue {\n canSubmit?: boolean\n closeMentions: () => void\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n editor: PortableTextEditor\n expandOnFocus?: boolean\n focused: boolean\n focusEditor: () => void\n focusOnMount?: boolean\n hasChanges: boolean\n insertAtChar: () => void\n insertMention: (userId: string) => void\n mentionOptions: UserListWithPermissionsHookValue\n mentionsMenuOpen: boolean\n mentionsSearchTerm: string\n onBeforeInput: (event: InputEvent) => void\n openMentions: () => void\n readOnly: boolean\n value: CommentMessage\n}\n\ninterface CommentInputProviderProps {\n children: ReactNode\n expandOnFocus?: boolean\n focused: boolean\n focusOnMount?: boolean\n mentionOptions: UserListWithPermissionsHookValue\n onMentionMenuOpenChange?: (open: boolean) => void\n readOnly?: boolean\n value: CommentMessage\n}\n\nexport function CommentInputProvider(props: CommentInputProviderProps) {\n const {\n children,\n expandOnFocus = false,\n focused,\n focusOnMount = false,\n mentionOptions,\n onMentionMenuOpenChange,\n value,\n readOnly,\n } = props\n\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n const editor = usePortableTextEditor()\n\n const [mentionsMenuOpen, setMentionsMenuOpen] = useState<boolean>(false)\n const [mentionsSearchTerm, setMentionsSearchTerm] = useState<string>('')\n const [selectionAtMentionInsert, setSelectionAtMentionInsert] = useState<EditorSelection>(null)\n\n const canSubmit = useMemo(() => hasCommentMessageValue(value), [value])\n\n const hasChanges = useCommentHasChanged(value)\n\n const focusEditor = useCallback(() => {\n if (readOnly) return\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n PortableTextEditor.focus(editor)\n }, [editor, readOnly])\n\n const closeMentions = useCallback(() => {\n setMentionsMenuOpen(false)\n setMentionsSearchTerm('')\n setSelectionAtMentionInsert(null)\n }, [])\n\n const openMentions = useCallback(() => {\n if (mentionOptions?.disabled) {\n return\n }\n setMentionsMenuOpen(true)\n setMentionsSearchTerm('')\n setMentionsMenuOpen(true)\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n setSelectionAtMentionInsert(PortableTextEditor.getSelection(editor))\n }, [editor, mentionOptions?.disabled])\n\n // This function activates or deactivates the mentions menu and updates\n // the mention search term when the user types into the Portable Text Editor.\n const onBeforeInput = useCallback(\n (event: InputEvent): void => {\n if (mentionOptions?.disabled) {\n return\n }\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n const selection = PortableTextEditor.getSelection(editor)\n const cursorOffset = selection ? selection.focus.offset : 0\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n const focusChild = PortableTextEditor.focusChild(editor)\n const focusSpan = (isPortableTextSpan(focusChild) && focusChild) || undefined\n\n const isInsertText = event.inputType === 'insertText'\n const isDeleteText = event.inputType === 'deleteContentBackward'\n const isInsertingAtChar = isInsertText && event.data === '@'\n\n const lastIndexOfAt =\n focusSpan?.text.slice(0, Math.max(0, cursorOffset)).lastIndexOf('@') || 0\n\n const isWhitespaceCharBeforeCursorPosition =\n focusSpan?.text.slice(cursorOffset - 1, cursorOffset) === ' '\n\n const filterStartsWithSpaceChar = isInsertText && event.data === ' ' && !mentionsSearchTerm\n\n // If we are inserting a '@' character - open the mentions menu and reset the search term.\n // Only do this if it is in the start of the text, or if '@' is inserted when following a whitespace char.\n if (isInsertingAtChar && (cursorOffset < 1 || isWhitespaceCharBeforeCursorPosition)) {\n openMentions()\n return\n }\n\n // If the user begins typing their filter with a space, or if they are deleting\n // characters after activation and the '@' is no longer there,\n // clear the search term and close the mentions menu.\n if (\n filterStartsWithSpaceChar ||\n (isDeleteText &&\n (focusSpan?.text.length === 1 || lastIndexOfAt === (focusSpan?.text.length || 0) - 1))\n ) {\n closeMentions()\n return\n }\n\n // Update the search term\n if (isPortableTextSpan(focusChild)) {\n // Term starts with the @ char in the value until the cursor offset\n let term = focusChild.text.slice(lastIndexOfAt + 1, cursorOffset)\n // Add the char to the mentions search term\n if (isInsertText) {\n term += event.data\n }\n // Exclude the char from the mentions search term\n if (isDeleteText) {\n term = term.slice(0, Math.max(0, term.length - 1))\n }\n // Set the updated mentions search term\n setMentionsSearchTerm(term)\n }\n },\n [closeMentions, editor, mentionsSearchTerm, openMentions, mentionOptions?.disabled],\n )\n\n const insertAtChar = useCallback(() => {\n setMentionsMenuOpen(true)\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n PortableTextEditor.focus(editor)\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n PortableTextEditor.insertChild(editor, editor.schemaTypes.span, {text: '@'})\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n setSelectionAtMentionInsert(PortableTextEditor.getSelection(editor))\n }, [editor])\n\n useDidUpdate(mentionsMenuOpen, () => onMentionMenuOpenChange?.(mentionsMenuOpen))\n\n const insertMention = useCallback(\n (userId: string) => {\n const mentionSchemaType = editor.schemaTypes.inlineObjects.find((t) => t.name === 'mention')\n let mentionPath: Path | undefined\n\n const [span, spanPath] =\n (selectionAtMentionInsert &&\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n PortableTextEditor.findByPath(editor, selectionAtMentionInsert.focus.path)) ||\n []\n if (span && isPortableTextSpan(span) && spanPath && mentionSchemaType) {\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n PortableTextEditor.focus(editor)\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n const offset = PortableTextEditor.getSelection(editor)?.focus.offset\n if (typeof offset !== 'undefined') {\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n PortableTextEditor.delete(\n editor,\n {\n anchor: {path: spanPath, offset: span.text.lastIndexOf('@')},\n focus: {path: spanPath, offset},\n },\n {mode: 'selected'},\n )\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n PortableTextEditor.insertChild(editor, mentionSchemaType, {\n userId: userId,\n })\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n PortableTextEditor.insertChild(editor, editor.schemaTypes.span, {text: ' '})\n }\n }\n },\n [editor, selectionAtMentionInsert],\n )\n\n const ctxValue = useMemo(\n (): CommentInputContextValue => ({\n canSubmit,\n closeMentions,\n editor,\n expandOnFocus,\n focused,\n focusEditor,\n focusOnMount,\n hasChanges,\n insertAtChar,\n insertMention,\n mentionOptions,\n mentionsMenuOpen,\n mentionsSearchTerm,\n onBeforeInput,\n openMentions,\n readOnly: Boolean(readOnly),\n value,\n }),\n [\n canSubmit,\n closeMentions,\n editor,\n expandOnFocus,\n focused,\n focusEditor,\n focusOnMount,\n hasChanges,\n insertAtChar,\n insertMention,\n mentionOptions,\n mentionsMenuOpen,\n mentionsSearchTerm,\n onBeforeInput,\n openMentions,\n readOnly,\n value,\n ],\n )\n\n return (\n <CommentInputContextV2.Provider value={ctxValue}>{children}</CommentInputContextV2.Provider>\n )\n}\n","import {\n type Editor,\n type EditorEmittedEvent,\n EditorProvider,\n keyGenerator,\n useEditor,\n} from '@portabletext/editor'\nimport {EventListenerPlugin} from '@portabletext/editor/plugins'\nimport {getValue} from '@portabletext/editor/selectors'\nimport {OneLinePlugin} from '@portabletext/plugin-one-line'\nimport {sanitySchemaToPortableTextSchema} from '@portabletext/sanity-bridge'\nimport {type CurrentUser, type PortableTextBlock} from '@sanity/types'\nimport {type AvatarSize, focusFirstDescendant, focusLastDescendant} from '@sanity/ui'\nimport {\n type FocusEvent,\n type FormEvent,\n type KeyboardEvent,\n type ReactNode,\n useCallback,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n type RefAttributes,\n} from 'react'\nimport {VStack} from 'ui5'\n\nimport {type UserListWithPermissionsHookValue} from '../../../../hooks/useUserListWithPermissions'\nimport {NormalBlock} from '../blocks/NormalBlock'\nimport {editorSchemaType} from '../config'\nimport {CommentInputDiscardDialog} from './CommentInputDiscardDialog'\nimport {CommentInputInner} from './CommentInputInner'\nimport {CommentInputProvider} from './CommentInputProvider'\n\n/**\n * `EditorProvider` doesn't have a `ref` prop. This plugin takes care of\n * imperatively forwarding the editor instance.\n */\nfunction EditorRefPlugin(props: RefAttributes<Editor | null>) {\n const {ref} = props\n const editor = useEditor()\n\n useImperativeHandle(ref, () => editor, [editor])\n\n return null\n}\n\nconst EMPTY_ARRAY: [] = []\n\nconst defaultRenderBlock = ({children}: {children: ReactNode}) => (\n <NormalBlock>{children}</NormalBlock>\n)\n\n/**\n * @internal\n */\nexport type CommentInputRenderBlock = (props: {children: React.ReactNode}) => React.JSX.Element\n\nconst SCROLL_INTO_VIEW_OPTIONS: ScrollIntoViewOptions = {\n behavior: 'smooth',\n block: 'center',\n inline: 'center',\n}\n\n/**\n * @internal\n */\nexport interface CommentInputProps {\n currentUser: CurrentUser\n expandOnFocus?: boolean\n focusLock?: boolean\n focusOnMount?: boolean\n mentionOptions: UserListWithPermissionsHookValue\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n onBlur?: (e: FormEvent<HTMLDivElement>) => void\n onChange: (value: PortableTextBlock[]) => void\n onDiscardCancel?: () => void\n onDiscardConfirm: () => void\n // oxlint-disable-next-line no-deprecated -- will fix in follow up PR\n onFocus?: (e: FormEvent<HTMLDivElement>) => void\n onKeyDown?: (e: KeyboardEvent) => void\n onMentionMenuOpenChange?: (open: boolean) => void\n onSubmit?: (value: PortableTextBlock[]) => void\n placeholder?: ReactNode\n readOnly?: boolean\n renderBlock?: CommentInputRenderBlock\n value: PortableTextBlock[] | null\n withAvatar?: boolean\n avatarSize?: AvatarSize\n}\n\ninterface CommentDiscardDialogController {\n open: () => void\n close: () => void\n}\n\n/**\n * @internal\n */\nexport interface CommentInputHandle {\n blur: () => void\n discardDialogController: CommentDiscardDialogController\n focus: () => void\n scrollTo: () => void\n reset: () => void\n}\n\n/**\n * @internal\n * @hidden\n */\nexport function CommentInput(props: CommentInputProps & RefAttributes<CommentInputHandle>) {\n const {\n ref,\n avatarSize,\n currentUser,\n expandOnFocus,\n focusLock = false,\n focusOnMount,\n mentionOptions,\n onBlur,\n onChange,\n onDiscardCancel,\n onDiscardConfirm,\n onFocus,\n onKeyDown,\n onMentionMenuOpenChange,\n onSubmit,\n placeholder,\n readOnly,\n renderBlock = defaultRenderBlock,\n value = EMPTY_ARRAY,\n withAvatar = true,\n } = props\n const [focused, setFocused] = useState<boolean>(false)\n const editorRef = useRef<Editor | null>(null)\n const editorContainerRef = useRef<HTMLDivElement | null>(null)\n const resetInstanceRef = useRef(false)\n const [showDiscardDialog, setShowDiscardDialog] = useState<boolean>(false)\n\n const preDivRef = useRef<HTMLDivElement | null>(null)\n const postDivRef = useRef<HTMLDivElement | null>(null)\n const innerRef = useRef<HTMLDivElement | null>(null)\n\n // A unique (React) key for the editor instance.\n const [editorInstanceKey, setEditorInstanceKey] = useState(keyGenerator())\n\n const requestFocus = useCallback(() => {\n requestAnimationFrame(() => {\n editorRef.current?.send({type: 'focus'})\n })\n }, [])\n\n const resetEditorInstance = useCallback(() => {\n // The discarded instance flushes pending mutations during teardown; drop\n // them in `handleEvent` so a finished draft cannot overwrite the\n // consumer's cleared draft state.\n resetInstanceRef.current = true\n setEditorInstanceKey(keyGenerator())\n }, [])\n\n const handleEvent = useCallback(\n (event: EditorEmittedEvent) => {\n // Focus the editor when ready if focusOnMount is true\n if (event.type === 'ready') {\n resetInstanceRef.current = false\n if (focusOnMount) {\n requestFocus()\n }\n }\n if (event.type === 'focused') {\n setFocused(true)\n }\n\n if (event.type === 'blurred') {\n setFocused(false)\n }\n\n // Update the comment value whenever the comment is edited by the user.\n if (event.type === 'mutation' && !resetInstanceRef.current) {\n onChange(event.value || EMPTY_ARRAY)\n }\n },\n [focusOnMount, onChange, requestFocus],\n )\n\n const scrollToEditor = useCallback(() => {\n editorContainerRef.current?.scrollIntoView(SCROLL_INTO_VIEW_OPTIONS)\n }, [])\n\n const handleSubmit = useCallback(() => {\n // Read the editor's live value directly rather than the value mirrored\n // through the debounced `mutation` event, which can lag the latest\n // keystrokes by up to the flush interval and truncate the comment when\n // the user submits without pausing.\n const currentValue = editorRef.current ? getValue(editorRef.current.getSnapshot()) : EMPTY_ARRAY\n onSubmit?.(currentValue)\n resetEditorInstance()\n requestFocus()\n scrollToEditor()\n }, [onSubmit, requestFocus, resetEditorInstance, scrollToEditor])\n\n const handleDiscardConfirm = useCallback(() => {\n onDiscardConfirm()\n resetEditorInstance()\n }, [onDiscardConfirm, resetEditorInstance])\n\n // The way a user a comment can be discarded varies from the context it is used in.\n // This controller is used to take care of the main logic of the discard process, while\n // specific behavior is handled by the consumer.\n const discardDialogController = useMemo((): CommentDiscardDialogController => {\n return {\n open: () => {\n setShowDiscardDialog(true)\n },\n close: () => {\n setShowDiscardDialog(false)\n requestFocus()\n },\n }\n }, [requestFocus])\n\n useImperativeHandle(ref, () => {\n return {\n focus: requestFocus,\n blur() {\n editorRef.current?.send({type: 'blur'})\n },\n scrollTo: scrollToEditor,\n reset: resetEditorInstance,\n\n discardDialogController,\n }\n }, [discardDialogController, requestFocus, resetEditorInstance, scrollToEditor])\n\n const handleFocus = useCallback(\n (event: FocusEvent<HTMLDivElement>) => {\n if (!focusLock) return\n\n const target = event.target\n const innerEl = innerRef.current\n\n if (innerEl && target === preDivRef.current) {\n focusLastDescendant(innerEl)\n return\n }\n\n if (innerEl && target === postDivRef.current) {\n focusFirstDescendant(innerEl)\n }\n },\n [focusLock],\n )\n\n return (\n <>\n {showDiscardDialog && onDiscardCancel && (\n <CommentInputDiscardDialog onClose={onDiscardCancel} onConfirm={handleDiscardConfirm} />\n )}\n\n <VStack ref={editorContainerRef} data-testid=\"comment-input\" onFocus={handleFocus}>\n <EditorProvider\n key={editorInstanceKey}\n initialConfig={{\n schemaDefinition: sanitySchemaToPortableTextSchema(editorSchemaType),\n initialValue: value || EMPTY_ARRAY,\n readOnly,\n }}\n >\n <EditorRefPlugin ref={editorRef} />\n <EventListenerPlugin on={handleEvent} />\n <OneLinePlugin />\n <UpdateReadOnlyPlugin readOnly={readOnly ?? false} />\n <UpdateValuePlugin value={value ?? undefined} />\n <CommentInputProvider\n expandOnFocus={expandOnFocus}\n focused={focused}\n focusOnMount={focusOnMount}\n mentionOptions={mentionOptions}\n onMentionMenuOpenChange={onMentionMenuOpenChange}\n readOnly={readOnly}\n value={value}\n >\n {focusLock && <div ref={preDivRef} tabIndex={0} />}\n\n <VStack ref={innerRef}>\n <CommentInputInner\n avatarSize={avatarSize}\n currentUser={currentUser}\n focusLock={focusLock}\n onBlur={onBlur}\n onFocus={onFocus}\n onKeyDown={onKeyDown}\n onSubmit={onSubmit && handleSubmit}\n placeholder={placeholder}\n renderBlock={renderBlock}\n withAvatar={withAvatar}\n />\n </VStack>\n\n {focusLock && <div ref={postDivRef} tabIndex={0} />}\n </CommentInputProvider>\n </EditorProvider>\n </VStack>\n </>\n )\n}\n\n/**\n * `EditorProvider` doesn't have a `readOnly` prop. This plugin listens for the\n * prop change and sends an `update readOnly` event to the editor.\n */\nfunction UpdateReadOnlyPlugin(props: {readOnly: boolean}) {\n const editor = useEditor()\n\n useEffect(() => {\n editor.send({\n type: 'update readOnly',\n readOnly: props.readOnly,\n })\n }, [editor, props.readOnly])\n\n return null\n}\n\n/**\n * `EditorProvider` doesn't have a `value` prop. This plugin listens for the\n * prop change and sends an `update value` event to the editor.\n */\nfunction UpdateValuePlugin(props: {value: Array<PortableTextBlock> | undefined}) {\n const editor = useEditor()\n\n useEffect(() => {\n editor.send({\n type: 'update value',\n value: props.value,\n })\n }, [editor, props.value])\n\n return null\n}\n"],"mappings":"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"}
|