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
package/lib/_createContext.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import "sanity/bundle.css";
|
|
2
|
-
import { Da as set, Nr as EMPTY_ARRAY, Oa as setIfMissing, Pa as ScrollContainer, Pi as useDateTimeFormat, Wr as DivergencesProvider, _r as FormInput, a as LocaleProvider, ba as PatchEvent, c as defaultLocale, gr as VirtualizerScrollInstanceProvider, h as FormBuilder, hr as createPatchChannel, ir as PresenceOverlay, ka as unset, lr as getExpandOperations, m as TransformPatches, ma as CopyPasteProvider, mr as setAtPath, t as PerspectiveProvider, ur as useFormState } from "./PerspectiveProvider-
|
|
3
|
-
import { b as ChangeIndicatorsTracker, g as FormFieldHeaderText, u as FieldPresence } from "./TimeZoneButton-
|
|
4
|
-
import { L as validateDocument, Zt as useSchema, p as ResourceCacheProvider } from "./datastores-
|
|
5
|
-
import { d as pathToString } from "./useFieldActions-
|
|
2
|
+
import { Da as set, Nr as EMPTY_ARRAY, Oa as setIfMissing, Pa as ScrollContainer, Pi as useDateTimeFormat, Wr as DivergencesProvider, _r as FormInput, a as LocaleProvider, ba as PatchEvent, c as defaultLocale, gr as VirtualizerScrollInstanceProvider, h as FormBuilder, hr as createPatchChannel, ir as PresenceOverlay, ka as unset, lr as getExpandOperations, m as TransformPatches, ma as CopyPasteProvider, mr as setAtPath, t as PerspectiveProvider, ur as useFormState } from "./PerspectiveProvider-D-6sweQH.js";
|
|
3
|
+
import { b as ChangeIndicatorsTracker, g as FormFieldHeaderText, u as FieldPresence } from "./TimeZoneButton-B_ki5v8q.js";
|
|
4
|
+
import { L as validateDocument, Zt as useSchema, p as ResourceCacheProvider } from "./datastores-DNOJm1LF.js";
|
|
5
|
+
import { d as pathToString } from "./useFieldActions-BmY1Kh3s.js";
|
|
6
6
|
import { t as useTranslation } from "./useTranslation-Cqs6Itwv.js";
|
|
7
7
|
import { t as Translate } from "./Translate-YUHPpk6j.js";
|
|
8
|
-
import { a as SourceProvider, c as useWorkspace, s as WorkspaceProvider } from "./studioClient-
|
|
8
|
+
import { a as SourceProvider, c as useWorkspace, s as WorkspaceProvider } from "./studioClient-C7B6Aobi.js";
|
|
9
9
|
import { t as useCurrentLocale } from "./useLocale-ChRJXddd.js";
|
|
10
10
|
import { n as useRelativeTime } from "./ContextMenuButton-ODMhzmz6.js";
|
|
11
11
|
import "@sanity/ui/styles.css";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as getValueAtPath } from "./useFieldActions-
|
|
2
|
-
import { l as isTextSelectionComment, u as parseCommentFieldPath } from "./constants-
|
|
1
|
+
import { a as getValueAtPath } from "./useFieldActions-BmY1Kh3s.js";
|
|
2
|
+
import { l as isTextSelectionComment, u as parseCommentFieldPath } from "./constants-BQItnHll.js";
|
|
3
3
|
import { isPortableTextSpan, isPortableTextTextBlock } from "@sanity/types";
|
|
4
4
|
import * as PathUtils from "@sanity/util/paths";
|
|
5
5
|
import { DIFF_DELETE, DIFF_EQUAL, DIFF_INSERT, applyPatches, cleanupEfficiency, makeDiff, makePatches } from "@sanity/diff-match-patch";
|
|
@@ -91,4 +91,4 @@ function diffsLevenshtein(diffs) {
|
|
|
91
91
|
}
|
|
92
92
|
export { buildRangeDecorationSelectionsFromComments as n, COMMENT_INDICATORS as t };
|
|
93
93
|
|
|
94
|
-
//# sourceMappingURL=buildRangeDecorationSelectionsFromComments-
|
|
94
|
+
//# sourceMappingURL=buildRangeDecorationSelectionsFromComments-BnlhrvDK.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buildRangeDecorationSelectionsFromComments-B1-tJPvG.js","names":[],"sources":["../src/core/comments-v2/utils/inline-comments/buildRangeDecorationSelectionsFromComments.ts"],"sourcesContent":["import {type RangeDecoration} from '@portabletext/editor'\nimport {\n applyPatches,\n cleanupEfficiency,\n type Diff,\n DIFF_DELETE,\n DIFF_EQUAL,\n DIFF_INSERT,\n makeDiff,\n makePatches,\n type Patch,\n} from '@sanity/diff-match-patch'\nimport {\n isPortableTextSpan,\n isPortableTextTextBlock,\n type Path,\n type PortableTextBlock,\n type PortableTextTextBlock,\n} from '@sanity/types'\nimport * as PathUtils from '@sanity/util/paths'\n\nimport {getValueAtPath} from '../../../field/paths/helpers'\nimport {isTextSelectionComment, parseCommentFieldPath} from '../../helpers'\nimport {type CommentDocument, type CommentsTextSelectionItem} from '../../types'\n\n// This must be set high to avoid false positives\n// (for example, when there are multiple occurrences of the same word, and you delete the original commented word)\n// Don't set it above 15, as it will cause performance issues\nconst DMP_MARGIN = 15\n\nfunction diffText(current: string, next: string) {\n const diff = makeDiff(current, next)\n const diffs = cleanupEfficiency(diff)\n const levenshtein = diffsLevenshtein(diffs)\n return {patches: makePatches(current, diffs, {margin: DMP_MARGIN}), levenshtein}\n}\n\nfunction diffApply(current: string, patches: Patch[]) {\n return applyPatches(patches, current, {\n allowExceedingIndices: true,\n margin: DMP_MARGIN,\n })[0]\n}\n\nconst CHILD_SYMBOL = '\\uF0D0'\nfunction toPlainTextWithChildSeparators(inputBlock: PortableTextTextBlock) {\n return inputBlock.children\n .map((child) => (isPortableTextSpan(child) ? child.text.replaceAll(CHILD_SYMBOL, ' ') : ''))\n .join(CHILD_SYMBOL)\n}\n\nexport const COMMENT_INDICATORS = ['\\uF000', '\\uF001']\nconst COMMENT_INDICATORS_REGEX = new RegExp(`[${COMMENT_INDICATORS.join('')}]`, 'g')\n\nconst EMPTY_ARRAY: [] = []\n\n/**\n * @internal\n */\nexport interface BuildCommentsRangeDecorationsProps {\n value: PortableTextBlock[] | undefined\n comments: CommentDocument[]\n /**\n * Document value the stored `field` paths resolve against. Falls back to a\n * top-level `value.find` on the editor slice when absent.\n */\n documentValue?: unknown\n /** The editor's own document path. */\n basePath?: Path\n}\n\n/**\n * @internal\n */\nexport interface BuildCommentsRangeDecorationsResultItem {\n selection: RangeDecoration['selection']\n comment: CommentDocument\n range: CommentsTextSelectionItem\n}\n\n/**\n * A function that builds range decoration selections from comments and their associated text.\n * @internal\n */\nexport function buildRangeDecorationSelectionsFromComments(\n props: BuildCommentsRangeDecorationsProps,\n): BuildCommentsRangeDecorationsResultItem[] {\n const {value, comments, documentValue, basePath} = props\n\n if (!value || value.length === 0) return EMPTY_ARRAY\n\n const textSelections = comments.filter(isTextSelectionComment)\n const decorators: BuildCommentsRangeDecorationsResultItem[] = []\n\n textSelections.forEach((comment) => {\n let relative: Path = []\n if (documentValue !== undefined && basePath) {\n const fieldPath = parseCommentFieldPath(comment.target.path?.field)\n if (!fieldPath) {\n // A comment without a parseable `field` cannot resolve to a block.\n return\n }\n if (!PathUtils.startsWith(basePath, fieldPath)) return\n relative = fieldPath.slice(basePath.length)\n }\n\n comment.target.path?.selection?.value.forEach((selectionMember) => {\n // The block content must come from the editor `value`: decorations are\n // rendered against it, and persisted ranges must be computed against the\n // same text. The form `documentValue` (used above for path scoping) lags\n // the editor while typing, so reading text through it would produce\n // offsets that are stale relative to the rendered/persisted value.\n const matchedBlock =\n relative.length > 0\n ? getValueAtPath(value, [...relative, {_key: selectionMember._key}])\n : value.find((block) => block._key === selectionMember._key)\n if (!isPortableTextTextBlock(matchedBlock)) {\n return\n }\n const selectionText = selectionMember.text.replaceAll(COMMENT_INDICATORS_REGEX, '')\n const textWithChildSeparators = toPlainTextWithChildSeparators(matchedBlock)\n const {patches} = diffText(selectionText, selectionMember.text)\n const diffedText = diffApply(textWithChildSeparators, patches)\n const startIndex = diffedText.indexOf(COMMENT_INDICATORS[0])\n const endIndex = diffedText\n .replaceAll(COMMENT_INDICATORS[0], '')\n .indexOf(COMMENT_INDICATORS[1])\n const textWithoutCommentTags = diffedText.replaceAll(COMMENT_INDICATORS_REGEX, '')\n const oldCommentedText = selectionMember.text.slice(\n selectionMember.text.indexOf(COMMENT_INDICATORS[0]) + 1,\n selectionMember.text.indexOf(COMMENT_INDICATORS[1]),\n )\n const newCommentedText = textWithoutCommentTags.slice(startIndex, endIndex)\n const {levenshtein} = diffText(newCommentedText, oldCommentedText)\n const threshold = Math.round(newCommentedText.length + oldCommentedText.length / 2)\n\n let nullSelection = false\n\n if (newCommentedText.length === 0) {\n nullSelection = true\n }\n\n if (levenshtein > threshold) {\n nullSelection = true\n }\n\n // If there no longer is any text within the range, we don't need to create a decoration\n if (startIndex + 1 === endIndex) {\n nullSelection = true\n }\n\n if (startIndex !== -1 && endIndex !== -1) {\n let childIndexAnchor = 0\n let anchorOffset = 0\n let childIndexFocus = 0\n let focusOffset = 0\n for (let i = 0; i < textWithoutCommentTags.length; i++) {\n if (textWithoutCommentTags[i] === CHILD_SYMBOL) {\n if (i <= startIndex) {\n anchorOffset = -1\n childIndexAnchor++\n }\n focusOffset = -1\n childIndexFocus++\n }\n if (i < startIndex) {\n anchorOffset++\n }\n if (i < startIndex + newCommentedText.length) {\n focusOffset++\n }\n if (i === startIndex + newCommentedText.length) {\n break\n }\n }\n\n decorators.push({\n selection: {\n anchor: {\n path: [\n ...relative,\n {_key: matchedBlock._key},\n 'children',\n {_key: matchedBlock.children[childIndexAnchor]._key},\n ],\n offset: anchorOffset,\n },\n focus: {\n path: [\n ...relative,\n {_key: matchedBlock._key},\n 'children',\n {_key: matchedBlock.children[childIndexFocus]._key},\n ],\n offset: focusOffset,\n },\n },\n comment,\n range: {_key: matchedBlock._key, text: nullSelection ? '' : diffedText},\n })\n }\n })\n })\n if (decorators.length === 0) return EMPTY_ARRAY\n return decorators\n}\n\ninterface ValidateTextSelectionCommentProps {\n comment: CommentDocument\n value: PortableTextBlock[]\n}\n\nfunction validateTextSelectionComment(props: ValidateTextSelectionCommentProps): boolean {\n const {comment, value} = props\n if (!isTextSelectionComment(comment)) return false\n\n const selections = buildRangeDecorationSelectionsFromComments({comments: [comment], value})\n\n return selections.length > 0\n}\n\nfunction diffsLevenshtein(diffs: Diff[]): number {\n let levenshtein = 0\n let insertions = 0\n let deletions = 0\n for (let x = 0; x < diffs.length; x++) {\n const op = diffs[x][0]\n const data = diffs[x][1]\n switch (op) {\n case DIFF_INSERT:\n insertions += data.length\n break\n case DIFF_DELETE:\n deletions += data.length\n break\n case DIFF_EQUAL:\n // A deletion and an insertion is one substitution.\n levenshtein += Math.max(insertions, deletions)\n insertions = 0\n deletions = 0\n break\n default:\n // Do nothing\n }\n }\n levenshtein += Math.max(insertions, deletions)\n return levenshtein\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"buildRangeDecorationSelectionsFromComments-BnlhrvDK.js","names":[],"sources":["../src/core/comments-v2/utils/inline-comments/buildRangeDecorationSelectionsFromComments.ts"],"sourcesContent":["import {type RangeDecoration} from '@portabletext/editor'\nimport {\n applyPatches,\n cleanupEfficiency,\n type Diff,\n DIFF_DELETE,\n DIFF_EQUAL,\n DIFF_INSERT,\n makeDiff,\n makePatches,\n type Patch,\n} from '@sanity/diff-match-patch'\nimport {\n isPortableTextSpan,\n isPortableTextTextBlock,\n type Path,\n type PortableTextBlock,\n type PortableTextTextBlock,\n} from '@sanity/types'\nimport * as PathUtils from '@sanity/util/paths'\n\nimport {getValueAtPath} from '../../../field/paths/helpers'\nimport {isTextSelectionComment, parseCommentFieldPath} from '../../helpers'\nimport {type CommentDocument, type CommentsTextSelectionItem} from '../../types'\n\n// This must be set high to avoid false positives\n// (for example, when there are multiple occurrences of the same word, and you delete the original commented word)\n// Don't set it above 15, as it will cause performance issues\nconst DMP_MARGIN = 15\n\nfunction diffText(current: string, next: string) {\n const diff = makeDiff(current, next)\n const diffs = cleanupEfficiency(diff)\n const levenshtein = diffsLevenshtein(diffs)\n return {patches: makePatches(current, diffs, {margin: DMP_MARGIN}), levenshtein}\n}\n\nfunction diffApply(current: string, patches: Patch[]) {\n return applyPatches(patches, current, {\n allowExceedingIndices: true,\n margin: DMP_MARGIN,\n })[0]\n}\n\nconst CHILD_SYMBOL = '\\uF0D0'\nfunction toPlainTextWithChildSeparators(inputBlock: PortableTextTextBlock) {\n return inputBlock.children\n .map((child) => (isPortableTextSpan(child) ? child.text.replaceAll(CHILD_SYMBOL, ' ') : ''))\n .join(CHILD_SYMBOL)\n}\n\nexport const COMMENT_INDICATORS = ['\\uF000', '\\uF001']\nconst COMMENT_INDICATORS_REGEX = new RegExp(`[${COMMENT_INDICATORS.join('')}]`, 'g')\n\nconst EMPTY_ARRAY: [] = []\n\n/**\n * @internal\n */\nexport interface BuildCommentsRangeDecorationsProps {\n value: PortableTextBlock[] | undefined\n comments: CommentDocument[]\n /**\n * Document value the stored `field` paths resolve against. Falls back to a\n * top-level `value.find` on the editor slice when absent.\n */\n documentValue?: unknown\n /** The editor's own document path. */\n basePath?: Path\n}\n\n/**\n * @internal\n */\nexport interface BuildCommentsRangeDecorationsResultItem {\n selection: RangeDecoration['selection']\n comment: CommentDocument\n range: CommentsTextSelectionItem\n}\n\n/**\n * A function that builds range decoration selections from comments and their associated text.\n * @internal\n */\nexport function buildRangeDecorationSelectionsFromComments(\n props: BuildCommentsRangeDecorationsProps,\n): BuildCommentsRangeDecorationsResultItem[] {\n const {value, comments, documentValue, basePath} = props\n\n if (!value || value.length === 0) return EMPTY_ARRAY\n\n const textSelections = comments.filter(isTextSelectionComment)\n const decorators: BuildCommentsRangeDecorationsResultItem[] = []\n\n textSelections.forEach((comment) => {\n let relative: Path = []\n if (documentValue !== undefined && basePath) {\n const fieldPath = parseCommentFieldPath(comment.target.path?.field)\n if (!fieldPath) {\n // A comment without a parseable `field` cannot resolve to a block.\n return\n }\n if (!PathUtils.startsWith(basePath, fieldPath)) return\n relative = fieldPath.slice(basePath.length)\n }\n\n comment.target.path?.selection?.value.forEach((selectionMember) => {\n // The block content must come from the editor `value`: decorations are\n // rendered against it, and persisted ranges must be computed against the\n // same text. The form `documentValue` (used above for path scoping) lags\n // the editor while typing, so reading text through it would produce\n // offsets that are stale relative to the rendered/persisted value.\n const matchedBlock =\n relative.length > 0\n ? getValueAtPath(value, [...relative, {_key: selectionMember._key}])\n : value.find((block) => block._key === selectionMember._key)\n if (!isPortableTextTextBlock(matchedBlock)) {\n return\n }\n const selectionText = selectionMember.text.replaceAll(COMMENT_INDICATORS_REGEX, '')\n const textWithChildSeparators = toPlainTextWithChildSeparators(matchedBlock)\n const {patches} = diffText(selectionText, selectionMember.text)\n const diffedText = diffApply(textWithChildSeparators, patches)\n const startIndex = diffedText.indexOf(COMMENT_INDICATORS[0])\n const endIndex = diffedText\n .replaceAll(COMMENT_INDICATORS[0], '')\n .indexOf(COMMENT_INDICATORS[1])\n const textWithoutCommentTags = diffedText.replaceAll(COMMENT_INDICATORS_REGEX, '')\n const oldCommentedText = selectionMember.text.slice(\n selectionMember.text.indexOf(COMMENT_INDICATORS[0]) + 1,\n selectionMember.text.indexOf(COMMENT_INDICATORS[1]),\n )\n const newCommentedText = textWithoutCommentTags.slice(startIndex, endIndex)\n const {levenshtein} = diffText(newCommentedText, oldCommentedText)\n const threshold = Math.round(newCommentedText.length + oldCommentedText.length / 2)\n\n let nullSelection = false\n\n if (newCommentedText.length === 0) {\n nullSelection = true\n }\n\n if (levenshtein > threshold) {\n nullSelection = true\n }\n\n // If there no longer is any text within the range, we don't need to create a decoration\n if (startIndex + 1 === endIndex) {\n nullSelection = true\n }\n\n if (startIndex !== -1 && endIndex !== -1) {\n let childIndexAnchor = 0\n let anchorOffset = 0\n let childIndexFocus = 0\n let focusOffset = 0\n for (let i = 0; i < textWithoutCommentTags.length; i++) {\n if (textWithoutCommentTags[i] === CHILD_SYMBOL) {\n if (i <= startIndex) {\n anchorOffset = -1\n childIndexAnchor++\n }\n focusOffset = -1\n childIndexFocus++\n }\n if (i < startIndex) {\n anchorOffset++\n }\n if (i < startIndex + newCommentedText.length) {\n focusOffset++\n }\n if (i === startIndex + newCommentedText.length) {\n break\n }\n }\n\n decorators.push({\n selection: {\n anchor: {\n path: [\n ...relative,\n {_key: matchedBlock._key},\n 'children',\n {_key: matchedBlock.children[childIndexAnchor]._key},\n ],\n offset: anchorOffset,\n },\n focus: {\n path: [\n ...relative,\n {_key: matchedBlock._key},\n 'children',\n {_key: matchedBlock.children[childIndexFocus]._key},\n ],\n offset: focusOffset,\n },\n },\n comment,\n range: {_key: matchedBlock._key, text: nullSelection ? '' : diffedText},\n })\n }\n })\n })\n if (decorators.length === 0) return EMPTY_ARRAY\n return decorators\n}\n\ninterface ValidateTextSelectionCommentProps {\n comment: CommentDocument\n value: PortableTextBlock[]\n}\n\nfunction validateTextSelectionComment(props: ValidateTextSelectionCommentProps): boolean {\n const {comment, value} = props\n if (!isTextSelectionComment(comment)) return false\n\n const selections = buildRangeDecorationSelectionsFromComments({comments: [comment], value})\n\n return selections.length > 0\n}\n\nfunction diffsLevenshtein(diffs: Diff[]): number {\n let levenshtein = 0\n let insertions = 0\n let deletions = 0\n for (let x = 0; x < diffs.length; x++) {\n const op = diffs[x][0]\n const data = diffs[x][1]\n switch (op) {\n case DIFF_INSERT:\n insertions += data.length\n break\n case DIFF_DELETE:\n deletions += data.length\n break\n case DIFF_EQUAL:\n // A deletion and an insertion is one substitution.\n levenshtein += Math.max(insertions, deletions)\n insertions = 0\n deletions = 0\n break\n default:\n // Do nothing\n }\n }\n levenshtein += Math.max(insertions, deletions)\n return levenshtein\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as getValueAtPath } from "./useFieldActions-
|
|
2
|
-
import { f as isTextSelectionComment, n as COMMENTS_HIGHLIGHT_HUE_KEY, p as parseCommentFieldPath, v as applyInlineCommentIdAttr } from "./useComments-
|
|
1
|
+
import { a as getValueAtPath } from "./useFieldActions-BmY1Kh3s.js";
|
|
2
|
+
import { f as isTextSelectionComment, n as COMMENTS_HIGHLIGHT_HUE_KEY, p as parseCommentFieldPath, v as applyInlineCommentIdAttr } from "./useComments-DWh1k0kS.js";
|
|
3
3
|
import { memo, useEffect, useRef, useState } from "react";
|
|
4
4
|
import { c } from "react/compiler-runtime";
|
|
5
5
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -289,4 +289,4 @@ function findBlockByKey(arrays, key) {
|
|
|
289
289
|
}
|
|
290
290
|
export { CommentInlineHighlightSpan as a, buildRangeDecorationSelectionsFromComments as i, getCommentFieldPath as n, CommentDisabledIcon as o, buildCommentRangeDecorations as r, buildTextSelectionFromFragment as t };
|
|
291
291
|
|
|
292
|
-
//# sourceMappingURL=buildTextSelectionFromFragment-
|
|
292
|
+
//# sourceMappingURL=buildTextSelectionFromFragment-BXrYd9lr.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buildTextSelectionFromFragment-BiLg851R.js","names":["<path\n d=\"M5.92627 14.5381H7.92627V18.5381L11.9263 14.5381H15.9263C17.0308 14.5381 17.9263 13.6427 17.9263 12.5381V6.53809C17.9263 5.43352 17.0308 4.53809 15.9263 4.53809H5.92627C4.8217 4.53809 3.92627 5.43352 3.92627 6.53809V12.5381C3.92627 13.6427 4.8217 14.5381 5.92627 14.5381Z\"\n stroke=\"currentColor\"\n strokeWidth=\"1.2\"\n strokeLinejoin=\"round\"\n />","<path\n d=\"M2.77256 2.66835C2.54413 2.51319 2.23317 2.57259 2.07802 2.80103L1.40378 3.7937C1.32927 3.9034 1.30139 4.0382 1.32627 4.16845C1.35115 4.29871 1.42676 4.41374 1.53646 4.48825L19.5861 16.7479C19.8146 16.903 20.1255 16.8436 20.2807 16.6152L20.9549 15.6225C21.0294 15.5128 21.0573 15.378 21.0324 15.2478C21.0076 15.1175 20.9319 15.0025 20.8222 14.928L2.77256 2.66835Z\"\n fill=\"currentColor\"\n strokeLinejoin=\"round\"\n />","<svg\n data-sanity-icon=\"comment-disabled\"\n width=\"1em\"\n height=\"1em\"\n ref={ref}\n viewBox=\"0 0 25 25\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n {...rest}\n >\n <path\n d=\"M5.92627 14.5381H7.92627V18.5381L11.9263 14.5381H15.9263C17.0308 14.5381 17.9263 13.6427 17.9263 12.5381V6.53809C17.9263 5.43352 17.0308 4.53809 15.9263 4.53809H5.92627C4.8217 4.53809 3.92627 5.43352 3.92627 6.53809V12.5381C3.92627 13.6427 4.8217 14.5381 5.92627 14.5381Z\"\n stroke=\"currentColor\"\n strokeWidth=\"1.2\"\n strokeLinejoin=\"round\"\n />\n <path\n d=\"M2.77256 2.66835C2.54413 2.51319 2.23317 2.57259 2.07802 2.80103L1.40378 3.7937C1.32927 3.9034 1.30139 4.0382 1.32627 4.16845C1.35115 4.29871 1.42676 4.41374 1.53646 4.48825L19.5861 16.7479C19.8146 16.903 20.1255 16.8436 20.2807 16.6152L20.9549 15.6225C21.0294 15.5128 21.0573 15.378 21.0324 15.2478C21.0076 15.1175 20.9319 15.0025 20.8222 14.928L2.77256 2.66835Z\"\n fill=\"currentColor\"\n strokeLinejoin=\"round\"\n />\n </svg>","<HighlightSpan\n {...rest}\n data-hovered={isHovered ? 'true' : 'false'}\n data-inline-comment-nested={isNested ? 'true' : 'false'}\n data-inline-comment-state={state}\n ref={ref}\n >\n {children}\n </HighlightSpan>","isHovered ? 'true' : 'false'","isNested ? 'true' : 'false'","() => {\n // Get the previous and next sibling of the decorator element\n const prevEl = decoratorRef.current?.previousSibling as HTMLElement | null\n const nextEl = decoratorRef.current?.nextSibling as HTMLElement | null\n\n // If there is no previous or next sibling, then the decorator is not nested\n if (!prevEl || !nextEl) {\n setIsNested(false)\n return\n }\n\n // We use the `applyInlineCommentIdAttr` to get the key of the data attribute\n // used for the inline comment id on the decorator element.\n const [key] = Object.keys(applyInlineCommentIdAttr(''))\n\n const prevId = prevEl.getAttribute(key)\n const nextId = nextEl.getAttribute(key)\n\n const isEqual = prevId === nextId\n\n const isNestedDecorator = Boolean(prevId && nextId && isEqual)\n setParentCommentId(isNestedDecorator ? prevId : null)\n\n setIsNested(isNestedDecorator)\n }","[]","() => onHoverStart(commentId)","useCallback(() => onHoverStart(commentId), [commentId, onHoverStart])","() => onHoverEnd(null)","useCallback(() => onHoverEnd(null), [onHoverEnd])","() => onClick(commentId)","useCallback(() => onClick(commentId), [commentId, onClick])","applyInlineCommentIdAttr(threadId)","<CommentInlineHighlightSpan\n isAdded\n isHovered={hovered || selected}\n isNested={isNested}\n onClick={handleClick}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n ref={decoratorRef}\n {...applyInlineCommentIdAttr(threadId)}\n >\n {children}\n </CommentInlineHighlightSpan>","hovered || selected"],"sources":["../src/core/comments/components/icons/CommentDisabledIcon.tsx","../src/core/comments/components/pte/CommentInlineHighlightSpan.tsx","../src/core/comments/utils/inline-comments/buildRangeDecorationSelectionsFromComments.ts","../src/core/comments/utils/inline-comments/buildCommentRangeDecorations.tsx","../src/core/comments/utils/inline-comments/buildTextSelectionFromFragment.ts"],"sourcesContent":["import {type RefAttributes, type SVGProps} from 'react'\n\n/**\n * @internal\n */\nexport function CommentDisabledIcon(props: SVGProps<SVGSVGElement> & RefAttributes<SVGSVGElement>) {\n const {ref, ...rest} = props\n return (\n <svg\n data-sanity-icon=\"comment-disabled\"\n width=\"1em\"\n height=\"1em\"\n ref={ref}\n viewBox=\"0 0 25 25\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n {...rest}\n >\n <path\n d=\"M5.92627 14.5381H7.92627V18.5381L11.9263 14.5381H15.9263C17.0308 14.5381 17.9263 13.6427 17.9263 12.5381V6.53809C17.9263 5.43352 17.0308 4.53809 15.9263 4.53809H5.92627C4.8217 4.53809 3.92627 5.43352 3.92627 6.53809V12.5381C3.92627 13.6427 4.8217 14.5381 5.92627 14.5381Z\"\n stroke=\"currentColor\"\n strokeWidth=\"1.2\"\n strokeLinejoin=\"round\"\n />\n <path\n d=\"M2.77256 2.66835C2.54413 2.51319 2.23317 2.57259 2.07802 2.80103L1.40378 3.7937C1.32927 3.9034 1.30139 4.0382 1.32627 4.16845C1.35115 4.29871 1.42676 4.41374 1.53646 4.48825L19.5861 16.7479C19.8146 16.903 20.1255 16.8436 20.2807 16.6152L20.9549 15.6225C21.0294 15.5128 21.0573 15.378 21.0324 15.2478C21.0076 15.1175 20.9319 15.0025 20.8222 14.928L2.77256 2.66835Z\"\n fill=\"currentColor\"\n strokeLinejoin=\"round\"\n />\n </svg>\n )\n}\n","import {hues} from '@sanity/color'\nimport {type Theme} from '@sanity/ui'\nimport {type RefAttributes} from 'react'\nimport {css, styled} from 'styled-components'\n\nimport {COMMENTS_HIGHLIGHT_HUE_KEY} from '../../constants'\n\n// oxlint-disable-next-line no-deprecated -- will fix in follow up PR\nconst HighlightSpan = styled.span(({theme}: {theme: Theme}) => {\n const isDark = theme.sanity.v2?.color._dark\n\n // Colors used when a comment is added\n const addedBg = hues[COMMENTS_HIGHLIGHT_HUE_KEY][isDark ? 800 : 100].hex\n const addedBorder = hues[COMMENTS_HIGHLIGHT_HUE_KEY][isDark ? 700 : 300].hex\n\n const addedHoverBg = hues[COMMENTS_HIGHLIGHT_HUE_KEY][isDark ? 700 : 200].hex\n const addedHoverBorder = hues[COMMENTS_HIGHLIGHT_HUE_KEY][isDark ? 600 : 400].hex\n\n // Colors used when a comment is added and it is a nested comment\n const addedNestedBg = hues[COMMENTS_HIGHLIGHT_HUE_KEY][isDark ? 700 : 200].hex\n const addedNesterBorder = hues[COMMENTS_HIGHLIGHT_HUE_KEY][isDark ? 600 : 400].hex\n\n // Colors used when a comment is being authored.\n // For now, we use the same colors as when a comment is added.\n const authoringBg = addedBg\n const authoringBorder = addedBorder\n\n return css`\n box-sizing: border-box;\n transition:\n background-color 100ms ease,\n border-color 100ms ease;\n\n // Make sure that child elements appropriately blend with the\n // background of the highlight span\n * {\n mix-blend-mode: ${isDark ? 'screen' : 'multiply'};\n }\n\n &[data-inline-comment-state='added'][data-inline-comment-nested='false'] {\n background-color: ${addedBg};\n border-bottom: 2px solid ${addedBorder};\n }\n\n &[data-inline-comment-state='added'][data-inline-comment-nested='true'] {\n background-color: ${addedNestedBg};\n border-bottom: 2px solid ${addedNesterBorder};\n }\n\n &[data-inline-comment-state='added'][data-inline-comment-nested='false'][data-hovered='true'] {\n background-color: ${addedHoverBg};\n border-bottom: 2px solid ${addedHoverBorder};\n }\n\n &[data-inline-comment-state='authoring'] {\n background-color: ${authoringBg};\n border-bottom: 2px solid ${authoringBorder};\n }\n `\n})\n\ninterface CommentInlineHighlightSpanProps {\n children: React.ReactNode\n isAdded?: boolean\n isAuthoring?: boolean\n isHovered?: boolean\n isNested?: boolean\n}\n\n/**\n * @internal\n */\nexport function CommentInlineHighlightSpan(\n props: CommentInlineHighlightSpanProps &\n React.HTMLProps<HTMLSpanElement> &\n RefAttributes<HTMLSpanElement>,\n) {\n const {ref, children, isAdded, isAuthoring, isHovered, isNested, ...rest} = props\n\n const state = isAdded ? 'added' : isAuthoring ? 'authoring' : undefined\n\n return (\n <HighlightSpan\n {...rest}\n data-hovered={isHovered ? 'true' : 'false'}\n data-inline-comment-nested={isNested ? 'true' : 'false'}\n data-inline-comment-state={state}\n ref={ref}\n >\n {children}\n </HighlightSpan>\n )\n}\n","import {type RangeDecoration} from '@portabletext/editor'\nimport {\n applyPatches,\n cleanupEfficiency,\n type Diff,\n DIFF_DELETE,\n DIFF_EQUAL,\n DIFF_INSERT,\n makeDiff,\n makePatches,\n type Patch,\n} from '@sanity/diff-match-patch'\nimport {\n isPortableTextSpan,\n isPortableTextTextBlock,\n type Path,\n type PortableTextBlock,\n type PortableTextTextBlock,\n} from '@sanity/types'\nimport * as PathUtils from '@sanity/util/paths'\n\nimport {getValueAtPath} from '../../../field/paths/helpers'\nimport {isTextSelectionComment, parseCommentFieldPath} from '../../helpers'\nimport {type CommentDocument, type CommentsTextSelectionItem} from '../../types'\n\n// This must be set high to avoid false positives\n// (for example, when there are multiple occurrences of the same word, and you delete the original commented word)\n// Don't set it above 15, as it will cause performance issues\nconst DMP_MARGIN = 15\n\nfunction diffText(current: string, next: string) {\n const diff = makeDiff(current, next)\n const diffs = cleanupEfficiency(diff)\n const levenshtein = diffsLevenshtein(diffs)\n return {patches: makePatches(current, diffs, {margin: DMP_MARGIN}), levenshtein}\n}\n\nfunction diffApply(current: string, patches: Patch[]) {\n return applyPatches(patches, current, {\n allowExceedingIndices: true,\n margin: DMP_MARGIN,\n })[0]\n}\n\nconst CHILD_SYMBOL = '\\uF0D0'\nfunction toPlainTextWithChildSeparators(inputBlock: PortableTextTextBlock) {\n return inputBlock.children\n .map((child) => (isPortableTextSpan(child) ? child.text.replaceAll(CHILD_SYMBOL, ' ') : ''))\n .join(CHILD_SYMBOL)\n}\n\nexport const COMMENT_INDICATORS = ['\\uF000', '\\uF001']\nconst COMMENT_INDICATORS_REGEX = new RegExp(`[${COMMENT_INDICATORS.join('')}]`, 'g')\n\nconst EMPTY_ARRAY: [] = []\n\n/**\n * @internal\n */\nexport interface BuildCommentsRangeDecorationsProps {\n value: PortableTextBlock[] | undefined\n comments: CommentDocument[]\n /**\n * Document value the stored `field` paths resolve against. Falls back to a\n * top-level `value.find` on the editor slice when absent.\n */\n documentValue?: unknown\n /** The editor's own document path. */\n basePath?: Path\n}\n\n/**\n * @internal\n */\nexport interface BuildCommentsRangeDecorationsResultItem {\n selection: RangeDecoration['selection']\n comment: CommentDocument\n range: CommentsTextSelectionItem\n}\n\n/**\n * A function that builds range decoration selections from comments and their associated text.\n * @internal\n */\nexport function buildRangeDecorationSelectionsFromComments(\n props: BuildCommentsRangeDecorationsProps,\n): BuildCommentsRangeDecorationsResultItem[] {\n const {value, comments, documentValue, basePath} = props\n\n if (!value || value.length === 0) return EMPTY_ARRAY\n\n const textSelections = comments.filter(isTextSelectionComment)\n const decorators: BuildCommentsRangeDecorationsResultItem[] = []\n\n textSelections.forEach((comment) => {\n let relative: Path = []\n if (documentValue !== undefined && basePath) {\n const fieldPath = parseCommentFieldPath(comment.target.path?.field)\n if (!fieldPath) {\n // A comment without a parseable `field` cannot resolve to a block.\n return\n }\n if (!PathUtils.startsWith(basePath, fieldPath)) return\n relative = fieldPath.slice(basePath.length)\n }\n\n comment.target.path?.selection?.value.forEach((selectionMember) => {\n const matchedBlock =\n documentValue !== undefined && basePath\n ? (getValueAtPath(documentValue, [\n ...basePath,\n ...relative,\n {_key: selectionMember._key},\n ]) as PortableTextBlock | undefined)\n : value.find((block) => block._key === selectionMember._key)\n if (!matchedBlock || !isPortableTextTextBlock(matchedBlock)) {\n return\n }\n const selectionText = selectionMember.text.replaceAll(COMMENT_INDICATORS_REGEX, '')\n const textWithChildSeparators = toPlainTextWithChildSeparators(matchedBlock)\n const {patches} = diffText(selectionText, selectionMember.text)\n const diffedText = diffApply(textWithChildSeparators, patches)\n const startIndex = diffedText.indexOf(COMMENT_INDICATORS[0])\n const endIndex = diffedText\n .replaceAll(COMMENT_INDICATORS[0], '')\n .indexOf(COMMENT_INDICATORS[1])\n const textWithoutCommentTags = diffedText.replaceAll(COMMENT_INDICATORS_REGEX, '')\n const oldCommentedText = selectionMember.text.slice(\n selectionMember.text.indexOf(COMMENT_INDICATORS[0]) + 1,\n selectionMember.text.indexOf(COMMENT_INDICATORS[1]),\n )\n const newCommentedText = textWithoutCommentTags.slice(startIndex, endIndex)\n const {levenshtein} = diffText(newCommentedText, oldCommentedText)\n const threshold = Math.round(newCommentedText.length + oldCommentedText.length / 2)\n\n let nullSelection = false\n\n if (newCommentedText.length === 0) {\n nullSelection = true\n }\n\n if (levenshtein > threshold) {\n nullSelection = true\n }\n\n // If there no longer is any text within the range, we don't need to create a decoration\n if (startIndex + 1 === endIndex) {\n nullSelection = true\n }\n\n if (startIndex !== -1 && endIndex !== -1) {\n let childIndexAnchor = 0\n let anchorOffset = 0\n let childIndexFocus = 0\n let focusOffset = 0\n for (let i = 0; i < textWithoutCommentTags.length; i++) {\n if (textWithoutCommentTags[i] === CHILD_SYMBOL) {\n if (i <= startIndex) {\n anchorOffset = -1\n childIndexAnchor++\n }\n focusOffset = -1\n childIndexFocus++\n }\n if (i < startIndex) {\n anchorOffset++\n }\n if (i < startIndex + newCommentedText.length) {\n focusOffset++\n }\n if (i === startIndex + newCommentedText.length) {\n break\n }\n }\n\n decorators.push({\n selection: {\n anchor: {\n path: [\n ...relative,\n {_key: matchedBlock._key},\n 'children',\n {_key: matchedBlock.children[childIndexAnchor]._key},\n ],\n offset: anchorOffset,\n },\n focus: {\n path: [\n ...relative,\n {_key: matchedBlock._key},\n 'children',\n {_key: matchedBlock.children[childIndexFocus]._key},\n ],\n offset: focusOffset,\n },\n },\n comment,\n range: {_key: matchedBlock._key, text: nullSelection ? '' : diffedText},\n })\n }\n })\n })\n if (decorators.length === 0) return EMPTY_ARRAY\n return decorators\n}\n\ninterface ValidateTextSelectionCommentProps {\n comment: CommentDocument\n value: PortableTextBlock[]\n}\n\nfunction validateTextSelectionComment(props: ValidateTextSelectionCommentProps): boolean {\n const {comment, value} = props\n if (!isTextSelectionComment(comment)) return false\n\n const selections = buildRangeDecorationSelectionsFromComments({comments: [comment], value})\n\n return selections.length > 0\n}\n\nfunction diffsLevenshtein(diffs: Diff[]): number {\n let levenshtein = 0\n let insertions = 0\n let deletions = 0\n for (let x = 0; x < diffs.length; x++) {\n const op = diffs[x][0]\n const data = diffs[x][1]\n switch (op) {\n case DIFF_INSERT:\n insertions += data.length\n break\n case DIFF_DELETE:\n deletions += data.length\n break\n case DIFF_EQUAL:\n // A deletion and an insertion is one substitution.\n levenshtein += Math.max(insertions, deletions)\n insertions = 0\n deletions = 0\n break\n default:\n // Do nothing\n }\n }\n levenshtein += Math.max(insertions, deletions)\n return levenshtein\n}\n","import {type RangeDecoration, type RangeDecorationOnMovedDetails} from '@portabletext/editor'\nimport {type Path, type PortableTextBlock} from '@sanity/types'\nimport {memo, useCallback, useEffect, useRef, useState} from 'react'\n\nimport {CommentInlineHighlightSpan} from '../../components/pte/CommentInlineHighlightSpan'\nimport {applyInlineCommentIdAttr} from '../../hooks/useCommentsScroll'\nimport {type CommentDocument} from '../../types'\nimport {buildRangeDecorationSelectionsFromComments} from './buildRangeDecorationSelectionsFromComments'\n\ninterface CommentRangeDecorationProps {\n children: React.ReactNode\n commentId: string\n currentHoveredCommentId: string | null\n onClick: (commentId: string) => void\n onHoverEnd: (commentId: null) => void\n onHoverStart: (commentId: string) => void\n selectedThreadId: string | null\n threadId: string\n}\n\nconst CommentRangeDecoration = memo(function CommentRangeDecoration(\n props: CommentRangeDecorationProps,\n) {\n const {\n children,\n commentId,\n currentHoveredCommentId,\n onClick,\n onHoverEnd,\n onHoverStart,\n selectedThreadId,\n threadId,\n } = props\n const decoratorRef = useRef<HTMLSpanElement | null>(null)\n const [isNested, setIsNested] = useState(false)\n const [parentCommentId, setParentCommentId] = useState<string | null>(null)\n\n useEffect(() => {\n // Get the previous and next sibling of the decorator element\n const prevEl = decoratorRef.current?.previousSibling as HTMLElement | null\n const nextEl = decoratorRef.current?.nextSibling as HTMLElement | null\n\n // If there is no previous or next sibling, then the decorator is not nested\n if (!prevEl || !nextEl) {\n setIsNested(false)\n return\n }\n\n // We use the `applyInlineCommentIdAttr` to get the key of the data attribute\n // used for the inline comment id on the decorator element.\n const [key] = Object.keys(applyInlineCommentIdAttr(''))\n\n const prevId = prevEl.getAttribute(key)\n const nextId = nextEl.getAttribute(key)\n\n const isEqual = prevId === nextId\n\n const isNestedDecorator = Boolean(prevId && nextId && isEqual)\n setParentCommentId(isNestedDecorator ? prevId : null)\n\n setIsNested(isNestedDecorator)\n }, [])\n\n const handleMouseEnter = useCallback(() => onHoverStart(commentId), [commentId, onHoverStart])\n const handleMouseLeave = useCallback(() => onHoverEnd(null), [onHoverEnd])\n const handleClick = useCallback(() => onClick(commentId), [commentId, onClick])\n\n const hovered =\n currentHoveredCommentId === commentId ||\n (currentHoveredCommentId === parentCommentId && isNested)\n\n const selected = selectedThreadId === threadId\n\n return (\n <CommentInlineHighlightSpan\n isAdded\n isHovered={hovered || selected}\n isNested={isNested}\n onClick={handleClick}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n ref={decoratorRef}\n {...applyInlineCommentIdAttr(threadId)}\n >\n {children}\n </CommentInlineHighlightSpan>\n )\n})\n\ninterface BuildRangeDecorationsProps {\n comments: CommentDocument[]\n currentHoveredCommentId: string | null\n onDecorationClick: (commentId: string) => void\n onDecorationHoverEnd: (commentId: null) => void\n onDecorationHoverStart: (commentId: string) => void\n onDecorationMoved: (details: RangeDecorationOnMovedDetails) => void\n selectedThreadId: string | null\n value: PortableTextBlock[] | undefined\n documentValue?: unknown\n basePath?: Path\n}\n\n/**\n * @internal\n */\nexport function buildCommentRangeDecorations(props: BuildRangeDecorationsProps) {\n const {\n comments,\n currentHoveredCommentId,\n onDecorationClick,\n onDecorationHoverEnd,\n onDecorationHoverStart,\n onDecorationMoved,\n selectedThreadId,\n value,\n documentValue,\n basePath,\n } = props\n const rangeSelections = buildRangeDecorationSelectionsFromComments({\n comments,\n value,\n documentValue,\n basePath,\n })\n\n const decorations = rangeSelections.map(({selection, comment, range}) => {\n const decoration: RangeDecoration = {\n component: ({children}) => (\n <CommentRangeDecoration\n commentId={comment._id}\n currentHoveredCommentId={currentHoveredCommentId}\n onClick={onDecorationClick}\n onHoverEnd={onDecorationHoverEnd}\n onHoverStart={onDecorationHoverStart}\n selectedThreadId={selectedThreadId}\n threadId={comment.threadId}\n >\n {children}\n </CommentRangeDecoration>\n ),\n onMoved: onDecorationMoved,\n selection,\n payload: {\n commentId: comment._id,\n range,\n },\n }\n return decoration\n })\n return decorations\n}\n","import {type EditorSelection} from '@portabletext/editor'\nimport {toPlainText} from '@portabletext/react'\nimport {\n isPortableTextSpan,\n isPortableTextTextBlock,\n type Path,\n type PortableTextBlock,\n type PortableTextTextBlock,\n} from '@sanity/types'\nimport * as PathUtils from '@sanity/util/paths'\n\nimport {getValueAtPath} from '../../../field/paths/helpers'\nimport {type CommentTextSelection} from '../../types'\nimport {COMMENT_INDICATORS} from './buildRangeDecorationSelectionsFromComments'\n\ninterface BuildSelectionFromFragmentProps {\n fragment: PortableTextBlock[]\n documentValue: unknown\n basePath: Path\n selection: EditorSelection\n}\n\n/**\n * @internal\n */\nexport function buildTextSelectionFromFragment(\n props: BuildSelectionFromFragmentProps,\n): CommentTextSelection {\n const {fragment, documentValue, basePath, selection} = props\n if (!selection) {\n throw new Error('Selection is required')\n }\n const normalizedSelection: EditorSelection = selection.backward\n ? {backward: false, anchor: selection.focus, focus: selection.anchor}\n : selection\n\n const {block: anchorBlock, path: anchorBlockPath} =\n findEnclosingTextBlock(documentValue, basePath, normalizedSelection.anchor.path) ?? {}\n const {block: focusBlock, path: focusBlockPath} =\n findEnclosingTextBlock(documentValue, basePath, normalizedSelection.focus.path) ?? {}\n\n // A selection spanning three or more blocks has fragment blocks that are\n // neither the anchor nor the focus block. They live in the same containing\n // arrays, so resolve every fragment block by `_key` within those arrays.\n const containingArrays: Array<Array<unknown>> = []\n for (const blockPath of [anchorBlockPath, focusBlockPath]) {\n if (!blockPath) continue\n const containingArray = getValueAtPath(documentValue, [...basePath, ...blockPath.slice(0, -1)])\n if (Array.isArray(containingArray) && !containingArrays.includes(containingArray)) {\n containingArrays.push(containingArray)\n }\n }\n\n const textSelection: CommentTextSelection = {\n type: 'text',\n value: fragment.map((fragmentBlock) => {\n const originalBlock = findBlockByKey(containingArrays, fragmentBlock._key)\n if (!isPortableTextTextBlock(originalBlock)) {\n return {\n _key: fragmentBlock._key,\n text: '',\n }\n }\n const anchorBlockKey = anchorBlock?._key\n const focusBlockKey = focusBlock?._key\n const fragmentBlockText = toPlainText([fragmentBlock])\n const fragmentStartSpan = isPortableTextTextBlock(fragmentBlock)\n ? fragmentBlock.children[0]\n : undefined\n const fragmentEndSpan = isPortableTextTextBlock(fragmentBlock)\n ? fragmentBlock.children[fragmentBlock.children.length - 1]\n : undefined\n let originalTextBeforeSelection = ''\n let startChildIndex = -1\n if (anchorBlockKey === originalBlock._key) {\n for (const child of originalBlock.children) {\n startChildIndex++\n if (child._key === fragmentStartSpan?._key) {\n originalTextBeforeSelection +=\n (isPortableTextSpan(child) &&\n child.text.slice(0, Math.max(0, normalizedSelection.anchor.offset))) ||\n ''\n break\n }\n originalTextBeforeSelection += child.text\n }\n }\n let originalTextAfterSelection = ''\n if (focusBlockKey === originalBlock._key) {\n for (const child of originalBlock.children.slice(startChildIndex).reverse()) {\n if (child._key === fragmentEndSpan?._key) {\n originalTextAfterSelection =\n ((isPortableTextSpan(child) &&\n child.text.slice(normalizedSelection.focus.offset, child.text.length)) ||\n '') + originalTextAfterSelection\n break\n }\n originalTextAfterSelection = child.text + originalTextAfterSelection\n }\n }\n return {\n _key: originalBlock._key,\n text: `${originalTextBeforeSelection}${COMMENT_INDICATORS[0]}${fragmentBlockText}${COMMENT_INDICATORS[1]}${originalTextAfterSelection}`,\n }\n }),\n }\n\n return textSelection\n}\n\n/**\n * The data path to the block's containing array. Returns `undefined` if no\n * enclosing text block exists at the selection path.\n *\n * @internal\n */\nexport function getCommentFieldPath(\n documentValue: unknown,\n basePath: Path,\n selectionPath: Path,\n): string | undefined {\n const enclosingBlockPath = findEnclosingTextBlock(documentValue, basePath, selectionPath)?.path\n if (!enclosingBlockPath) return undefined\n return PathUtils.toString([...basePath, ...enclosingBlockPath.slice(0, -1)])\n}\n\n/**\n * Walk `path` up to root against the document value from `basePath`, returning\n * the deepest enclosing text block and the segments (relative to `basePath`)\n * that reach it. Selection paths from PTE are editor-relative.\n */\nfunction findEnclosingTextBlock(\n documentValue: unknown,\n basePath: Path,\n path: Path,\n): {block: PortableTextTextBlock; path: Path} | undefined {\n for (let end = path.length; end > 0; end--) {\n const relative = path.slice(0, end)\n const candidate = getValueAtPath(documentValue, [...basePath, ...relative])\n if (isPortableTextTextBlock(candidate)) {\n return {block: candidate, path: relative}\n }\n }\n return undefined\n}\n\nfunction findBlockByKey(\n arrays: Array<Array<unknown>>,\n key: string,\n): PortableTextTextBlock | undefined {\n for (const array of arrays) {\n for (const block of array) {\n if (isPortableTextTextBlock(block) && block._key === key) {\n return block\n }\n }\n }\n return undefined\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"buildTextSelectionFromFragment-BXrYd9lr.js","names":["<path\n d=\"M5.92627 14.5381H7.92627V18.5381L11.9263 14.5381H15.9263C17.0308 14.5381 17.9263 13.6427 17.9263 12.5381V6.53809C17.9263 5.43352 17.0308 4.53809 15.9263 4.53809H5.92627C4.8217 4.53809 3.92627 5.43352 3.92627 6.53809V12.5381C3.92627 13.6427 4.8217 14.5381 5.92627 14.5381Z\"\n stroke=\"currentColor\"\n strokeWidth=\"1.2\"\n strokeLinejoin=\"round\"\n />","<path\n d=\"M2.77256 2.66835C2.54413 2.51319 2.23317 2.57259 2.07802 2.80103L1.40378 3.7937C1.32927 3.9034 1.30139 4.0382 1.32627 4.16845C1.35115 4.29871 1.42676 4.41374 1.53646 4.48825L19.5861 16.7479C19.8146 16.903 20.1255 16.8436 20.2807 16.6152L20.9549 15.6225C21.0294 15.5128 21.0573 15.378 21.0324 15.2478C21.0076 15.1175 20.9319 15.0025 20.8222 14.928L2.77256 2.66835Z\"\n fill=\"currentColor\"\n strokeLinejoin=\"round\"\n />","<svg\n data-sanity-icon=\"comment-disabled\"\n width=\"1em\"\n height=\"1em\"\n ref={ref}\n viewBox=\"0 0 25 25\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n {...rest}\n >\n <path\n d=\"M5.92627 14.5381H7.92627V18.5381L11.9263 14.5381H15.9263C17.0308 14.5381 17.9263 13.6427 17.9263 12.5381V6.53809C17.9263 5.43352 17.0308 4.53809 15.9263 4.53809H5.92627C4.8217 4.53809 3.92627 5.43352 3.92627 6.53809V12.5381C3.92627 13.6427 4.8217 14.5381 5.92627 14.5381Z\"\n stroke=\"currentColor\"\n strokeWidth=\"1.2\"\n strokeLinejoin=\"round\"\n />\n <path\n d=\"M2.77256 2.66835C2.54413 2.51319 2.23317 2.57259 2.07802 2.80103L1.40378 3.7937C1.32927 3.9034 1.30139 4.0382 1.32627 4.16845C1.35115 4.29871 1.42676 4.41374 1.53646 4.48825L19.5861 16.7479C19.8146 16.903 20.1255 16.8436 20.2807 16.6152L20.9549 15.6225C21.0294 15.5128 21.0573 15.378 21.0324 15.2478C21.0076 15.1175 20.9319 15.0025 20.8222 14.928L2.77256 2.66835Z\"\n fill=\"currentColor\"\n strokeLinejoin=\"round\"\n />\n </svg>","<HighlightSpan\n {...rest}\n data-hovered={isHovered ? 'true' : 'false'}\n data-inline-comment-nested={isNested ? 'true' : 'false'}\n data-inline-comment-state={state}\n ref={ref}\n >\n {children}\n </HighlightSpan>","isHovered ? 'true' : 'false'","isNested ? 'true' : 'false'","() => {\n // Get the previous and next sibling of the decorator element\n const prevEl = decoratorRef.current?.previousSibling as HTMLElement | null\n const nextEl = decoratorRef.current?.nextSibling as HTMLElement | null\n\n // If there is no previous or next sibling, then the decorator is not nested\n if (!prevEl || !nextEl) {\n setIsNested(false)\n return\n }\n\n // We use the `applyInlineCommentIdAttr` to get the key of the data attribute\n // used for the inline comment id on the decorator element.\n const [key] = Object.keys(applyInlineCommentIdAttr(''))\n\n const prevId = prevEl.getAttribute(key)\n const nextId = nextEl.getAttribute(key)\n\n const isEqual = prevId === nextId\n\n const isNestedDecorator = Boolean(prevId && nextId && isEqual)\n setParentCommentId(isNestedDecorator ? prevId : null)\n\n setIsNested(isNestedDecorator)\n }","[]","() => onHoverStart(commentId)","useCallback(() => onHoverStart(commentId), [commentId, onHoverStart])","() => onHoverEnd(null)","useCallback(() => onHoverEnd(null), [onHoverEnd])","() => onClick(commentId)","useCallback(() => onClick(commentId), [commentId, onClick])","applyInlineCommentIdAttr(threadId)","<CommentInlineHighlightSpan\n isAdded\n isHovered={hovered || selected}\n isNested={isNested}\n onClick={handleClick}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n ref={decoratorRef}\n {...applyInlineCommentIdAttr(threadId)}\n >\n {children}\n </CommentInlineHighlightSpan>","hovered || selected"],"sources":["../src/core/comments/components/icons/CommentDisabledIcon.tsx","../src/core/comments/components/pte/CommentInlineHighlightSpan.tsx","../src/core/comments/utils/inline-comments/buildRangeDecorationSelectionsFromComments.ts","../src/core/comments/utils/inline-comments/buildCommentRangeDecorations.tsx","../src/core/comments/utils/inline-comments/buildTextSelectionFromFragment.ts"],"sourcesContent":["import {type RefAttributes, type SVGProps} from 'react'\n\n/**\n * @internal\n */\nexport function CommentDisabledIcon(props: SVGProps<SVGSVGElement> & RefAttributes<SVGSVGElement>) {\n const {ref, ...rest} = props\n return (\n <svg\n data-sanity-icon=\"comment-disabled\"\n width=\"1em\"\n height=\"1em\"\n ref={ref}\n viewBox=\"0 0 25 25\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n {...rest}\n >\n <path\n d=\"M5.92627 14.5381H7.92627V18.5381L11.9263 14.5381H15.9263C17.0308 14.5381 17.9263 13.6427 17.9263 12.5381V6.53809C17.9263 5.43352 17.0308 4.53809 15.9263 4.53809H5.92627C4.8217 4.53809 3.92627 5.43352 3.92627 6.53809V12.5381C3.92627 13.6427 4.8217 14.5381 5.92627 14.5381Z\"\n stroke=\"currentColor\"\n strokeWidth=\"1.2\"\n strokeLinejoin=\"round\"\n />\n <path\n d=\"M2.77256 2.66835C2.54413 2.51319 2.23317 2.57259 2.07802 2.80103L1.40378 3.7937C1.32927 3.9034 1.30139 4.0382 1.32627 4.16845C1.35115 4.29871 1.42676 4.41374 1.53646 4.48825L19.5861 16.7479C19.8146 16.903 20.1255 16.8436 20.2807 16.6152L20.9549 15.6225C21.0294 15.5128 21.0573 15.378 21.0324 15.2478C21.0076 15.1175 20.9319 15.0025 20.8222 14.928L2.77256 2.66835Z\"\n fill=\"currentColor\"\n strokeLinejoin=\"round\"\n />\n </svg>\n )\n}\n","import {hues} from '@sanity/color'\nimport {type Theme} from '@sanity/ui'\nimport {type RefAttributes} from 'react'\nimport {css, styled} from 'styled-components'\n\nimport {COMMENTS_HIGHLIGHT_HUE_KEY} from '../../constants'\n\n// oxlint-disable-next-line no-deprecated -- will fix in follow up PR\nconst HighlightSpan = styled.span(({theme}: {theme: Theme}) => {\n const isDark = theme.sanity.v2?.color._dark\n\n // Colors used when a comment is added\n const addedBg = hues[COMMENTS_HIGHLIGHT_HUE_KEY][isDark ? 800 : 100].hex\n const addedBorder = hues[COMMENTS_HIGHLIGHT_HUE_KEY][isDark ? 700 : 300].hex\n\n const addedHoverBg = hues[COMMENTS_HIGHLIGHT_HUE_KEY][isDark ? 700 : 200].hex\n const addedHoverBorder = hues[COMMENTS_HIGHLIGHT_HUE_KEY][isDark ? 600 : 400].hex\n\n // Colors used when a comment is added and it is a nested comment\n const addedNestedBg = hues[COMMENTS_HIGHLIGHT_HUE_KEY][isDark ? 700 : 200].hex\n const addedNesterBorder = hues[COMMENTS_HIGHLIGHT_HUE_KEY][isDark ? 600 : 400].hex\n\n // Colors used when a comment is being authored.\n // For now, we use the same colors as when a comment is added.\n const authoringBg = addedBg\n const authoringBorder = addedBorder\n\n return css`\n box-sizing: border-box;\n transition:\n background-color 100ms ease,\n border-color 100ms ease;\n\n // Make sure that child elements appropriately blend with the\n // background of the highlight span\n * {\n mix-blend-mode: ${isDark ? 'screen' : 'multiply'};\n }\n\n &[data-inline-comment-state='added'][data-inline-comment-nested='false'] {\n background-color: ${addedBg};\n border-bottom: 2px solid ${addedBorder};\n }\n\n &[data-inline-comment-state='added'][data-inline-comment-nested='true'] {\n background-color: ${addedNestedBg};\n border-bottom: 2px solid ${addedNesterBorder};\n }\n\n &[data-inline-comment-state='added'][data-inline-comment-nested='false'][data-hovered='true'] {\n background-color: ${addedHoverBg};\n border-bottom: 2px solid ${addedHoverBorder};\n }\n\n &[data-inline-comment-state='authoring'] {\n background-color: ${authoringBg};\n border-bottom: 2px solid ${authoringBorder};\n }\n `\n})\n\ninterface CommentInlineHighlightSpanProps {\n children: React.ReactNode\n isAdded?: boolean\n isAuthoring?: boolean\n isHovered?: boolean\n isNested?: boolean\n}\n\n/**\n * @internal\n */\nexport function CommentInlineHighlightSpan(\n props: CommentInlineHighlightSpanProps &\n React.HTMLProps<HTMLSpanElement> &\n RefAttributes<HTMLSpanElement>,\n) {\n const {ref, children, isAdded, isAuthoring, isHovered, isNested, ...rest} = props\n\n const state = isAdded ? 'added' : isAuthoring ? 'authoring' : undefined\n\n return (\n <HighlightSpan\n {...rest}\n data-hovered={isHovered ? 'true' : 'false'}\n data-inline-comment-nested={isNested ? 'true' : 'false'}\n data-inline-comment-state={state}\n ref={ref}\n >\n {children}\n </HighlightSpan>\n )\n}\n","import {type RangeDecoration} from '@portabletext/editor'\nimport {\n applyPatches,\n cleanupEfficiency,\n type Diff,\n DIFF_DELETE,\n DIFF_EQUAL,\n DIFF_INSERT,\n makeDiff,\n makePatches,\n type Patch,\n} from '@sanity/diff-match-patch'\nimport {\n isPortableTextSpan,\n isPortableTextTextBlock,\n type Path,\n type PortableTextBlock,\n type PortableTextTextBlock,\n} from '@sanity/types'\nimport * as PathUtils from '@sanity/util/paths'\n\nimport {getValueAtPath} from '../../../field/paths/helpers'\nimport {isTextSelectionComment, parseCommentFieldPath} from '../../helpers'\nimport {type CommentDocument, type CommentsTextSelectionItem} from '../../types'\n\n// This must be set high to avoid false positives\n// (for example, when there are multiple occurrences of the same word, and you delete the original commented word)\n// Don't set it above 15, as it will cause performance issues\nconst DMP_MARGIN = 15\n\nfunction diffText(current: string, next: string) {\n const diff = makeDiff(current, next)\n const diffs = cleanupEfficiency(diff)\n const levenshtein = diffsLevenshtein(diffs)\n return {patches: makePatches(current, diffs, {margin: DMP_MARGIN}), levenshtein}\n}\n\nfunction diffApply(current: string, patches: Patch[]) {\n return applyPatches(patches, current, {\n allowExceedingIndices: true,\n margin: DMP_MARGIN,\n })[0]\n}\n\nconst CHILD_SYMBOL = '\\uF0D0'\nfunction toPlainTextWithChildSeparators(inputBlock: PortableTextTextBlock) {\n return inputBlock.children\n .map((child) => (isPortableTextSpan(child) ? child.text.replaceAll(CHILD_SYMBOL, ' ') : ''))\n .join(CHILD_SYMBOL)\n}\n\nexport const COMMENT_INDICATORS = ['\\uF000', '\\uF001']\nconst COMMENT_INDICATORS_REGEX = new RegExp(`[${COMMENT_INDICATORS.join('')}]`, 'g')\n\nconst EMPTY_ARRAY: [] = []\n\n/**\n * @internal\n */\nexport interface BuildCommentsRangeDecorationsProps {\n value: PortableTextBlock[] | undefined\n comments: CommentDocument[]\n /**\n * Document value the stored `field` paths resolve against. Falls back to a\n * top-level `value.find` on the editor slice when absent.\n */\n documentValue?: unknown\n /** The editor's own document path. */\n basePath?: Path\n}\n\n/**\n * @internal\n */\nexport interface BuildCommentsRangeDecorationsResultItem {\n selection: RangeDecoration['selection']\n comment: CommentDocument\n range: CommentsTextSelectionItem\n}\n\n/**\n * A function that builds range decoration selections from comments and their associated text.\n * @internal\n */\nexport function buildRangeDecorationSelectionsFromComments(\n props: BuildCommentsRangeDecorationsProps,\n): BuildCommentsRangeDecorationsResultItem[] {\n const {value, comments, documentValue, basePath} = props\n\n if (!value || value.length === 0) return EMPTY_ARRAY\n\n const textSelections = comments.filter(isTextSelectionComment)\n const decorators: BuildCommentsRangeDecorationsResultItem[] = []\n\n textSelections.forEach((comment) => {\n let relative: Path = []\n if (documentValue !== undefined && basePath) {\n const fieldPath = parseCommentFieldPath(comment.target.path?.field)\n if (!fieldPath) {\n // A comment without a parseable `field` cannot resolve to a block.\n return\n }\n if (!PathUtils.startsWith(basePath, fieldPath)) return\n relative = fieldPath.slice(basePath.length)\n }\n\n comment.target.path?.selection?.value.forEach((selectionMember) => {\n const matchedBlock =\n documentValue !== undefined && basePath\n ? (getValueAtPath(documentValue, [\n ...basePath,\n ...relative,\n {_key: selectionMember._key},\n ]) as PortableTextBlock | undefined)\n : value.find((block) => block._key === selectionMember._key)\n if (!matchedBlock || !isPortableTextTextBlock(matchedBlock)) {\n return\n }\n const selectionText = selectionMember.text.replaceAll(COMMENT_INDICATORS_REGEX, '')\n const textWithChildSeparators = toPlainTextWithChildSeparators(matchedBlock)\n const {patches} = diffText(selectionText, selectionMember.text)\n const diffedText = diffApply(textWithChildSeparators, patches)\n const startIndex = diffedText.indexOf(COMMENT_INDICATORS[0])\n const endIndex = diffedText\n .replaceAll(COMMENT_INDICATORS[0], '')\n .indexOf(COMMENT_INDICATORS[1])\n const textWithoutCommentTags = diffedText.replaceAll(COMMENT_INDICATORS_REGEX, '')\n const oldCommentedText = selectionMember.text.slice(\n selectionMember.text.indexOf(COMMENT_INDICATORS[0]) + 1,\n selectionMember.text.indexOf(COMMENT_INDICATORS[1]),\n )\n const newCommentedText = textWithoutCommentTags.slice(startIndex, endIndex)\n const {levenshtein} = diffText(newCommentedText, oldCommentedText)\n const threshold = Math.round(newCommentedText.length + oldCommentedText.length / 2)\n\n let nullSelection = false\n\n if (newCommentedText.length === 0) {\n nullSelection = true\n }\n\n if (levenshtein > threshold) {\n nullSelection = true\n }\n\n // If there no longer is any text within the range, we don't need to create a decoration\n if (startIndex + 1 === endIndex) {\n nullSelection = true\n }\n\n if (startIndex !== -1 && endIndex !== -1) {\n let childIndexAnchor = 0\n let anchorOffset = 0\n let childIndexFocus = 0\n let focusOffset = 0\n for (let i = 0; i < textWithoutCommentTags.length; i++) {\n if (textWithoutCommentTags[i] === CHILD_SYMBOL) {\n if (i <= startIndex) {\n anchorOffset = -1\n childIndexAnchor++\n }\n focusOffset = -1\n childIndexFocus++\n }\n if (i < startIndex) {\n anchorOffset++\n }\n if (i < startIndex + newCommentedText.length) {\n focusOffset++\n }\n if (i === startIndex + newCommentedText.length) {\n break\n }\n }\n\n decorators.push({\n selection: {\n anchor: {\n path: [\n ...relative,\n {_key: matchedBlock._key},\n 'children',\n {_key: matchedBlock.children[childIndexAnchor]._key},\n ],\n offset: anchorOffset,\n },\n focus: {\n path: [\n ...relative,\n {_key: matchedBlock._key},\n 'children',\n {_key: matchedBlock.children[childIndexFocus]._key},\n ],\n offset: focusOffset,\n },\n },\n comment,\n range: {_key: matchedBlock._key, text: nullSelection ? '' : diffedText},\n })\n }\n })\n })\n if (decorators.length === 0) return EMPTY_ARRAY\n return decorators\n}\n\ninterface ValidateTextSelectionCommentProps {\n comment: CommentDocument\n value: PortableTextBlock[]\n}\n\nfunction validateTextSelectionComment(props: ValidateTextSelectionCommentProps): boolean {\n const {comment, value} = props\n if (!isTextSelectionComment(comment)) return false\n\n const selections = buildRangeDecorationSelectionsFromComments({comments: [comment], value})\n\n return selections.length > 0\n}\n\nfunction diffsLevenshtein(diffs: Diff[]): number {\n let levenshtein = 0\n let insertions = 0\n let deletions = 0\n for (let x = 0; x < diffs.length; x++) {\n const op = diffs[x][0]\n const data = diffs[x][1]\n switch (op) {\n case DIFF_INSERT:\n insertions += data.length\n break\n case DIFF_DELETE:\n deletions += data.length\n break\n case DIFF_EQUAL:\n // A deletion and an insertion is one substitution.\n levenshtein += Math.max(insertions, deletions)\n insertions = 0\n deletions = 0\n break\n default:\n // Do nothing\n }\n }\n levenshtein += Math.max(insertions, deletions)\n return levenshtein\n}\n","import {type RangeDecoration, type RangeDecorationOnMovedDetails} from '@portabletext/editor'\nimport {type Path, type PortableTextBlock} from '@sanity/types'\nimport {memo, useCallback, useEffect, useRef, useState} from 'react'\n\nimport {CommentInlineHighlightSpan} from '../../components/pte/CommentInlineHighlightSpan'\nimport {applyInlineCommentIdAttr} from '../../hooks/useCommentsScroll'\nimport {type CommentDocument} from '../../types'\nimport {buildRangeDecorationSelectionsFromComments} from './buildRangeDecorationSelectionsFromComments'\n\ninterface CommentRangeDecorationProps {\n children: React.ReactNode\n commentId: string\n currentHoveredCommentId: string | null\n onClick: (commentId: string) => void\n onHoverEnd: (commentId: null) => void\n onHoverStart: (commentId: string) => void\n selectedThreadId: string | null\n threadId: string\n}\n\nconst CommentRangeDecoration = memo(function CommentRangeDecoration(\n props: CommentRangeDecorationProps,\n) {\n const {\n children,\n commentId,\n currentHoveredCommentId,\n onClick,\n onHoverEnd,\n onHoverStart,\n selectedThreadId,\n threadId,\n } = props\n const decoratorRef = useRef<HTMLSpanElement | null>(null)\n const [isNested, setIsNested] = useState(false)\n const [parentCommentId, setParentCommentId] = useState<string | null>(null)\n\n useEffect(() => {\n // Get the previous and next sibling of the decorator element\n const prevEl = decoratorRef.current?.previousSibling as HTMLElement | null\n const nextEl = decoratorRef.current?.nextSibling as HTMLElement | null\n\n // If there is no previous or next sibling, then the decorator is not nested\n if (!prevEl || !nextEl) {\n setIsNested(false)\n return\n }\n\n // We use the `applyInlineCommentIdAttr` to get the key of the data attribute\n // used for the inline comment id on the decorator element.\n const [key] = Object.keys(applyInlineCommentIdAttr(''))\n\n const prevId = prevEl.getAttribute(key)\n const nextId = nextEl.getAttribute(key)\n\n const isEqual = prevId === nextId\n\n const isNestedDecorator = Boolean(prevId && nextId && isEqual)\n setParentCommentId(isNestedDecorator ? prevId : null)\n\n setIsNested(isNestedDecorator)\n }, [])\n\n const handleMouseEnter = useCallback(() => onHoverStart(commentId), [commentId, onHoverStart])\n const handleMouseLeave = useCallback(() => onHoverEnd(null), [onHoverEnd])\n const handleClick = useCallback(() => onClick(commentId), [commentId, onClick])\n\n const hovered =\n currentHoveredCommentId === commentId ||\n (currentHoveredCommentId === parentCommentId && isNested)\n\n const selected = selectedThreadId === threadId\n\n return (\n <CommentInlineHighlightSpan\n isAdded\n isHovered={hovered || selected}\n isNested={isNested}\n onClick={handleClick}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n ref={decoratorRef}\n {...applyInlineCommentIdAttr(threadId)}\n >\n {children}\n </CommentInlineHighlightSpan>\n )\n})\n\ninterface BuildRangeDecorationsProps {\n comments: CommentDocument[]\n currentHoveredCommentId: string | null\n onDecorationClick: (commentId: string) => void\n onDecorationHoverEnd: (commentId: null) => void\n onDecorationHoverStart: (commentId: string) => void\n onDecorationMoved: (details: RangeDecorationOnMovedDetails) => void\n selectedThreadId: string | null\n value: PortableTextBlock[] | undefined\n documentValue?: unknown\n basePath?: Path\n}\n\n/**\n * @internal\n */\nexport function buildCommentRangeDecorations(props: BuildRangeDecorationsProps) {\n const {\n comments,\n currentHoveredCommentId,\n onDecorationClick,\n onDecorationHoverEnd,\n onDecorationHoverStart,\n onDecorationMoved,\n selectedThreadId,\n value,\n documentValue,\n basePath,\n } = props\n const rangeSelections = buildRangeDecorationSelectionsFromComments({\n comments,\n value,\n documentValue,\n basePath,\n })\n\n const decorations = rangeSelections.map(({selection, comment, range}) => {\n const decoration: RangeDecoration = {\n component: ({children}) => (\n <CommentRangeDecoration\n commentId={comment._id}\n currentHoveredCommentId={currentHoveredCommentId}\n onClick={onDecorationClick}\n onHoverEnd={onDecorationHoverEnd}\n onHoverStart={onDecorationHoverStart}\n selectedThreadId={selectedThreadId}\n threadId={comment.threadId}\n >\n {children}\n </CommentRangeDecoration>\n ),\n onMoved: onDecorationMoved,\n selection,\n payload: {\n commentId: comment._id,\n range,\n },\n }\n return decoration\n })\n return decorations\n}\n","import {type EditorSelection} from '@portabletext/editor'\nimport {toPlainText} from '@portabletext/react'\nimport {\n isPortableTextSpan,\n isPortableTextTextBlock,\n type Path,\n type PortableTextBlock,\n type PortableTextTextBlock,\n} from '@sanity/types'\nimport * as PathUtils from '@sanity/util/paths'\n\nimport {getValueAtPath} from '../../../field/paths/helpers'\nimport {type CommentTextSelection} from '../../types'\nimport {COMMENT_INDICATORS} from './buildRangeDecorationSelectionsFromComments'\n\ninterface BuildSelectionFromFragmentProps {\n fragment: PortableTextBlock[]\n documentValue: unknown\n basePath: Path\n selection: EditorSelection\n}\n\n/**\n * @internal\n */\nexport function buildTextSelectionFromFragment(\n props: BuildSelectionFromFragmentProps,\n): CommentTextSelection {\n const {fragment, documentValue, basePath, selection} = props\n if (!selection) {\n throw new Error('Selection is required')\n }\n const normalizedSelection: EditorSelection = selection.backward\n ? {backward: false, anchor: selection.focus, focus: selection.anchor}\n : selection\n\n const {block: anchorBlock, path: anchorBlockPath} =\n findEnclosingTextBlock(documentValue, basePath, normalizedSelection.anchor.path) ?? {}\n const {block: focusBlock, path: focusBlockPath} =\n findEnclosingTextBlock(documentValue, basePath, normalizedSelection.focus.path) ?? {}\n\n // A selection spanning three or more blocks has fragment blocks that are\n // neither the anchor nor the focus block. They live in the same containing\n // arrays, so resolve every fragment block by `_key` within those arrays.\n const containingArrays: Array<Array<unknown>> = []\n for (const blockPath of [anchorBlockPath, focusBlockPath]) {\n if (!blockPath) continue\n const containingArray = getValueAtPath(documentValue, [...basePath, ...blockPath.slice(0, -1)])\n if (Array.isArray(containingArray) && !containingArrays.includes(containingArray)) {\n containingArrays.push(containingArray)\n }\n }\n\n const textSelection: CommentTextSelection = {\n type: 'text',\n value: fragment.map((fragmentBlock) => {\n const originalBlock = findBlockByKey(containingArrays, fragmentBlock._key)\n if (!isPortableTextTextBlock(originalBlock)) {\n return {\n _key: fragmentBlock._key,\n text: '',\n }\n }\n const anchorBlockKey = anchorBlock?._key\n const focusBlockKey = focusBlock?._key\n const fragmentBlockText = toPlainText([fragmentBlock])\n const fragmentStartSpan = isPortableTextTextBlock(fragmentBlock)\n ? fragmentBlock.children[0]\n : undefined\n const fragmentEndSpan = isPortableTextTextBlock(fragmentBlock)\n ? fragmentBlock.children[fragmentBlock.children.length - 1]\n : undefined\n let originalTextBeforeSelection = ''\n let startChildIndex = -1\n if (anchorBlockKey === originalBlock._key) {\n for (const child of originalBlock.children) {\n startChildIndex++\n if (child._key === fragmentStartSpan?._key) {\n originalTextBeforeSelection +=\n (isPortableTextSpan(child) &&\n child.text.slice(0, Math.max(0, normalizedSelection.anchor.offset))) ||\n ''\n break\n }\n originalTextBeforeSelection += child.text\n }\n }\n let originalTextAfterSelection = ''\n if (focusBlockKey === originalBlock._key) {\n for (const child of originalBlock.children.slice(startChildIndex).reverse()) {\n if (child._key === fragmentEndSpan?._key) {\n originalTextAfterSelection =\n ((isPortableTextSpan(child) &&\n child.text.slice(normalizedSelection.focus.offset, child.text.length)) ||\n '') + originalTextAfterSelection\n break\n }\n originalTextAfterSelection = child.text + originalTextAfterSelection\n }\n }\n return {\n _key: originalBlock._key,\n text: `${originalTextBeforeSelection}${COMMENT_INDICATORS[0]}${fragmentBlockText}${COMMENT_INDICATORS[1]}${originalTextAfterSelection}`,\n }\n }),\n }\n\n return textSelection\n}\n\n/**\n * The data path to the block's containing array. Returns `undefined` if no\n * enclosing text block exists at the selection path.\n *\n * @internal\n */\nexport function getCommentFieldPath(\n documentValue: unknown,\n basePath: Path,\n selectionPath: Path,\n): string | undefined {\n const enclosingBlockPath = findEnclosingTextBlock(documentValue, basePath, selectionPath)?.path\n if (!enclosingBlockPath) return undefined\n return PathUtils.toString([...basePath, ...enclosingBlockPath.slice(0, -1)])\n}\n\n/**\n * Walk `path` up to root against the document value from `basePath`, returning\n * the deepest enclosing text block and the segments (relative to `basePath`)\n * that reach it. Selection paths from PTE are editor-relative.\n */\nfunction findEnclosingTextBlock(\n documentValue: unknown,\n basePath: Path,\n path: Path,\n): {block: PortableTextTextBlock; path: Path} | undefined {\n for (let end = path.length; end > 0; end--) {\n const relative = path.slice(0, end)\n const candidate = getValueAtPath(documentValue, [...basePath, ...relative])\n if (isPortableTextTextBlock(candidate)) {\n return {block: candidate, path: relative}\n }\n }\n return undefined\n}\n\nfunction findBlockByKey(\n arrays: Array<Array<unknown>>,\n key: string,\n): PortableTextTextBlock | undefined {\n for (const array of arrays) {\n for (const block of array) {\n if (isPortableTextTextBlock(block) && block._key === key) {\n return block\n }\n }\n }\n return undefined\n}\n"],"mappings":"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"}
|
|
@@ -45,7 +45,7 @@ function isTextSelectionComment(comment) {
|
|
|
45
45
|
const commentsLocaleNamespace = "comments", commentsUsEnglishLocaleBundle = {
|
|
46
46
|
locale: "en-US",
|
|
47
47
|
namespace: commentsLocaleNamespace,
|
|
48
|
-
resources: () => import("./resources-
|
|
48
|
+
resources: () => import("./resources-Cq1lXH8T.js")
|
|
49
49
|
}, COMMENTS_INSPECTOR_NAME = "sanity/comments", COMMENTS_HIGHLIGHT_HUE_KEY = "yellow", COMMENT_REACTION_OPTIONS = [
|
|
50
50
|
{
|
|
51
51
|
shortName: ":+1:",
|
|
@@ -81,4 +81,4 @@ const commentsLocaleNamespace = "comments", commentsUsEnglishLocaleBundle = {
|
|
|
81
81
|
};
|
|
82
82
|
export { commentsLocaleNamespace as a, hasCommentMessageValue as c, useCommentHasChanged as d, COMMENT_REACTION_OPTIONS as i, isTextSelectionComment as l, COMMENTS_INSPECTOR_NAME as n, commentsUsEnglishLocaleBundle as o, COMMENT_REACTION_EMOJIS as r, commentIntentIfDiffers as s, COMMENTS_HIGHLIGHT_HUE_KEY as t, parseCommentFieldPath as u };
|
|
83
83
|
|
|
84
|
-
//# sourceMappingURL=constants-
|
|
84
|
+
//# sourceMappingURL=constants-BQItnHll.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants-
|
|
1
|
+
{"version":3,"file":"constants-BQItnHll.js","names":["isEqual(prevMessage, message)"],"sources":["../src/core/comments-v2/helpers.ts","../src/core/comments-v2/i18n/index.ts","../src/core/comments-v2/constants.ts"],"sourcesContent":["import {isPortableTextSpan, isPortableTextTextBlock, type Path} from '@sanity/types'\nimport * as PathUtils from '@sanity/util/paths'\nimport {dequal as isEqual} from 'dequal/lite'\nimport {useMemo, useState} from 'react'\n\nimport {type CommentContext, type CommentDocument, type CommentMessage} from './types'\n\nexport function useCommentHasChanged(message: CommentMessage): boolean {\n const [prevMessage] = useState<CommentMessage>(message)\n\n return useMemo(() => !isEqual(prevMessage, message), [prevMessage, message])\n}\n\n/**\n * @internal\n */\nexport function hasCommentMessageValue(value: CommentMessage): boolean {\n if (!value) return false\n\n return value?.some(\n (block) =>\n isPortableTextTextBlock(block) &&\n (block?.children || [])?.some((c) => (isPortableTextSpan(c) ? c.text : c.userId)),\n )\n}\n\nexport function commentIntentIfDiffers(\n parent?: CommentDocument,\n comment?: CommentDocument,\n): CommentContext['intent'] | undefined {\n const parentIntent = parent?.context?.intent\n const intent = comment?.context?.intent\n // If no intent, nothing to return\n if (!intent) return undefined\n // If no parent intent, no comparison necessary\n if (!parentIntent) return intent\n // If the preview param differs, return the intent\n if (\n 'preview' in intent.params &&\n 'preview' in parentIntent.params &&\n intent.params.preview !== parentIntent.params.preview\n ) {\n return intent\n }\n return undefined\n}\n\n/**\n * Parse a comment's persisted `fieldPath` string. Returns `undefined` for\n * empty or unparseable values: `fieldPath` is stored data, and a corrupt\n * comment must not crash rendering.\n * @internal\n */\nexport function parseCommentFieldPath(fieldPath: string | null | undefined): Path | undefined {\n if (!fieldPath) return undefined\n try {\n return PathUtils.fromString(fieldPath)\n } catch {\n return undefined\n }\n}\n\n/**\n * A function that checks whether a comment is a text selection comment\n * @internal\n */\nexport function isTextSelectionComment(comment: CommentDocument): boolean {\n if (!comment) return false\n\n return Boolean(\n comment?.target?.path?.selection?.type === 'text' && comment?.target?.path?.selection?.value,\n )\n}\n","import {type LocaleResourceBundle} from '../../i18n/types'\n\n/**\n * The locale namespace for the comments plugin\n *\n * @public\n */\nexport const commentsLocaleNamespace = 'comments' as const\n\n/**\n * The default locale bundle for the comments plugin, which is US English.\n *\n * @internal\n */\nexport const commentsUsEnglishLocaleBundle: LocaleResourceBundle = {\n locale: 'en-US',\n namespace: commentsLocaleNamespace,\n resources: () => import('./resources'),\n}\n","import {type ColorHueKey} from '@sanity/color'\n\nimport {type CommentReactionOption, type CommentReactionShortNames} from './types'\n\n/**\n * @internal\n * @hidden\n */\nexport const COMMENTS_INSPECTOR_NAME = 'sanity/comments'\n\nexport const COMMENTS_HIGHLIGHT_HUE_KEY: ColorHueKey = 'yellow'\n\n// These should not be alphabetized as the current order is intentional\nexport const COMMENT_REACTION_OPTIONS: CommentReactionOption[] = [\n {\n shortName: ':+1:',\n title: 'Thumbs up',\n },\n {\n shortName: ':-1:',\n title: 'Thumbs down',\n },\n {\n shortName: ':heart:',\n title: 'Heart',\n },\n {\n shortName: ':rocket:',\n title: 'Rocket',\n },\n {\n shortName: ':heavy_plus_sign:',\n title: 'Heavy plus sign',\n },\n {\n shortName: ':eyes:',\n title: 'Eyes',\n },\n]\n\nexport const COMMENT_REACTION_EMOJIS: Record<CommentReactionShortNames, string> = {\n ':-1:': '👎',\n ':+1:': '👍',\n ':eyes:': '👀',\n ':heart:': '❤️',\n ':heavy_plus_sign:': '➕',\n ':rocket:': '🚀',\n}\n"],"mappings":";;;;;AAOA,SAAgB,qBAAqB,SAAkC;eAC/D,CAAC,eAAe,SAAyB,OAAO,GAEhCA;CAAtB,OAA2C,EAAA,OAAA,WAAA,EAAA,OAAb,eAAR,KAAA,OAAQ,aAAa,OAAO,GAAP,EAAA,KAAA,SAAb,EAAA,KAAA,qCAAvB,CAAeA;AACxB;;;;AAKA,SAAgB,uBAAuB,OAAgC;CAGrE,OAFK,QAEE,OAAO,MACX,UACC,wBAAwB,KAAK,MAC5B,OAAO,YAAY,CAAC,EAAA,EAAI,MAAM,MAAO,mBAAmB,CAAC,IAAI,EAAE,OAAO,EAAE,MAAO,CACpF,IANmB;AAOrB;AAEA,SAAgB,uBACd,QACA,SACsC;CACtC,IAAM,eAAe,QAAQ,SAAS,QAChC,SAAS,SAAS,SAAS;CAE5B,eAED,CAAC,gBAGH,aAAa,OAAO,UACpB,aAAa,aAAa,UAC1B,OAAO,OAAO,YAAY,aAAa,OAAO,UAE9C,OAAO;AAGX;;;;;;;AAQA,SAAgB,sBAAsB,WAAwD;CACvF,eACL,IAAI;EACF,OAAO,UAAU,WAAW,SAAS;CACvC,QAAQ;EACN;CACF;AACF;;;;;AAMA,SAAgB,uBAAuB,SAAmC;CAGxE,OAFK,UAEE,GACL,SAAS,QAAQ,MAAM,WAAW,SAAS,UAAU,SAAS,QAAQ,MAAM,WAAW,SAHpE;AAKvB;;;;;;ACjEA,MAAa,0BAA0B,YAO1B,gCAAsD;CACjE,QAAQ;CACR,WAAW;CACX,iBAAiB,OAAO;AAC1B,GCVa,0BAA0B,mBAE1B,6BAA0C,UAG1C,2BAAoD;CAC/D;EACE,WAAW;EACX,OAAO;CACT;CACA;EACE,WAAW;EACX,OAAO;CACT;CACA;EACE,WAAW;EACX,OAAO;CACT;CACA;EACE,WAAW;EACX,OAAO;CACT;CACA;EACE,WAAW;EACX,OAAO;CACT;CACA;EACE,WAAW;EACX,OAAO;CACT;AACF,GAEa,0BAAqE;CAChF,QAAQ;CACR,QAAQ;CACR,UAAU;CACV,WAAW;CACX,qBAAqB;CACrB,YAAY;AACd"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as useTranslation } from "./useTranslation-Cqs6Itwv.js";
|
|
2
|
-
import { c as useWorkspace, i as useClient, n as DEFAULT_STUDIO_CLIENT_OPTIONS, o as useSource, r as versionedClient, t as DEFAULT_STUDIO_CLIENT_HEADERS } from "./studioClient-
|
|
2
|
+
import { c as useWorkspace, i as useClient, n as DEFAULT_STUDIO_CLIENT_OPTIONS, o as useSource, r as versionedClient, t as DEFAULT_STUDIO_CLIENT_HEADERS } from "./studioClient-C7B6Aobi.js";
|
|
3
3
|
import { C as isNonNullable, c as getIdPair, d as getVersionId, f as idMatchesPerspective, h as isDraftId$1, l as getPublishedId$1, o as documentIdEquals, s as getDraftId, u as getVersionFromId$1, y as isVersionId$1 } from "./draftUtils-D3HJGQaW.js";
|
|
4
4
|
import { n as VARIANTS_STUDIO_CLIENT_OPTIONS, r as VARIANT_DOCUMENTS_PATH, t as variantsApiClient } from "./variantsApiClient-Bjy3xOhq.js";
|
|
5
5
|
import { useContext, useEffect, useState } from "react";
|
|
@@ -5262,4 +5262,4 @@ function useComlinkStore() {
|
|
|
5262
5262
|
}
|
|
5263
5263
|
export { memoizeKeyGen as $, RESOLVE_INITIAL_VALUE_TIMEOUT_MS as $t, createGrantsStore as A, prepareForPreview as At, getInitialEditState as B, passthroughErrorHandler as Bt, removeMissingReferences as C, createDocumentPreviewStore as Ct, diffValue$1 as D, variantApiVersion as Dt, Timeline as E, joinPath as Et, getInitialValueStream as F, shallowEquals as Ft, RELEASE_DOCUMENTS_PATH as G, isRequestTimeoutError as Gt, measureFirstMatch as H, classifyRequestError as Ht, validation as I, createSWR as It, emitOperation as J, getApiErrorCode as Jt, RELEASE_DOCUMENT_TYPE as K, isTimeoutError as Kt, validateDocument as L, useTemplates as Lt, createDocumentStore as M, createPathObserver as Mt, normalizeDocumentPairTarget as N, applyMendozaPatch as Nt, isDev as O, RELEASES_STUDIO_CLIENT_OPTIONS as Ot, listenQuery as P, DOCUMENT_SYSTEM_FIELD as Pt, memoizedPair as Q, DEFAULT_MAX_RECURSION_DEPTH as Qt, validateDocumentWithReferences as R, useStudioErrorHandler as Rt, createHistoryStore as S, catchWithCount as St, getJsonStream as T, fieldNeedsEscape as Tt, getReleaseIdFromReleaseDocumentId as U, isClientRequestError as Ut, measureFirstEmission as V, classifyConfigError as Vt, isReleaseDocumentId as W, isNetworkError as Wt, isGoingToUnpublish as X, isUnauthorizedError as Xt, operationEvents as Y, isInvalidSessionError as Yt, snapshotPair as Z, useSchema as Zt, getProjectGrants as _, variantMatchesConditionFilters as _t, useGrantsStore as a, postTask as an, createBufferedDocument as at, createKeyValueStore as b, createConnectionStatusStore as bt, usePresenceStore as c, decodeVariantIdFromRoute as ct, useUserStore as d, getVariantDescription as dt, isBuilder as en, createMemoKey as et, createUserStore as f, getVariantId as ft, createProjectStore as g, isReleaseBundle as gt, createMultiKeyWeakMap as h, isPublishedBundleId as ht, useDocumentStore as i, validateTemplates as in, getPairListener as it, grantsPermissionOn as j, getPreviewPaths as jt, isProd as k, isReleasePerspective as kt, useProjectStore as l, filterVariantsForSearch as lt, useResourceCache as m, getVariantTitle as mt, useConnectionStatusStore as n, resolveInitialValue as nn, memoize$1 as nt, useHistoryStore as o, isRecord$2 as on, createObservableBufferedDocument as ot, ResourceCacheProvider as p, getVariantIdFromDocument as pt, GUARDED as q, parseRetryAfter as qt, useDocumentPreviewStore as r, resolveInitialValueForType as rn, checkoutPair as rt, useKeyValueStore as s, buildConditionFacets as st, useComlinkStore as t, resolveInitialObjectValue as tn, getClientCredentialSegments as tt, useRenderingContextStore as u, getVariantConditionsText as ut, SESSION_ID as v, getDocumentVariantType as vt, TimelineController as w, escapeField as wt, supportsLocalStorage as x, onRetry as xt, createPresenceStore as y, CONNECTING as yt, editState as z, createRequestErrorChannel as zt };
|
|
5264
5264
|
|
|
5265
|
-
//# sourceMappingURL=datastores-
|
|
5265
|
+
//# sourceMappingURL=datastores-DNOJm1LF.js.map
|