sanity
Version:
Sanity is a real-time content infrastructure with a scalable, hosted backend featuring a Graph Oriented Query Language (GROQ), asset pipelines and fast edge caches
1 lines • 1.14 MB
Source Map (JSON)
{"version":3,"file":"pane.mjs","sources":["../../src/structure/diffView/hooks/useCreatePathSyncChannel.ts","../../src/structure/diffView/constants.ts","../../src/structure/diffView/hooks/useDiffViewRouter.ts","../../src/structure/diffView/types/diffViewMode.ts","../../src/structure/diffView/hooks/useDiffViewState.ts","../../src/structure/diffView/hooks/useScrollMirror.tsx","../../src/structure/diffView/versionMode/components/VersionModeHeader.tsx","../../src/structure/diffView/components/DialogLayout.ts","../../src/structure/panes/document/document-layout/pickDocumentLayoutComponent.ts","../../src/structure/diffView/hooks/usePathSyncChannel.ts","../../src/structure/diffView/components/Scroller.ts","../../src/structure/diffView/components/DiffViewPane.tsx","../../src/structure/diffView/components/EditReferenceLinkComponent.tsx","../../src/structure/diffView/components/DiffView.tsx","../../src/structure/diffView/plugin/DiffViewDocumentLayout.tsx","../../src/structure/components/pane/constants.ts","../../src/structure/components/pane/usePaneLayout.ts","../../src/structure/components/pane/PaneDivider.tsx","../../src/structure/components/pane/Pane.tsx","../../src/structure/components/pane/PaneContent.styles.tsx","../../src/structure/components/pane/usePane.ts","../../src/structure/components/pane/PaneContent.tsx","../../src/structure/util/toLowerCaseNoSpaces.tsx","../../src/structure/components/pane/PaneMenuButtonItem.tsx","../../src/structure/components/pane/PaneContextMenuButton.tsx","../../src/structure/components/pane/PaneFooter.styles.tsx","../../src/structure/components/pane/PaneFooter.tsx","../../src/structure/components/pane/PaneHeader.styles.tsx","../../src/structure/components/pane/PaneHeader.tsx","../../src/structure/components/pane/PaneHeaderActionButton.tsx","../../src/structure/components/pane/PaneLayout.styles.tsx","../../src/structure/components/pane/helpers/_calcPaneResize.ts","../../src/structure/components/pane/helpers/_getDOMPath.ts","../../src/structure/components/pane/helpers/_sortElements.ts","../../src/structure/components/pane/paneLayoutController.ts","../../src/structure/components/pane/PaneLayout.tsx","../../src/structure/panes/error/ErrorPane.tsx","../../src/structure/components/Delay.tsx","../../src/structure/panes/loading/getWaitMessages.ts","../../src/structure/panes/loading/LoadingPane.tsx","../../src/structure/panes/document/useDocumentPane.tsx","../../src/structure/panes/document/comments/CommentsWrapper.tsx","../../src/structure/components/paneRouter/usePaneRouter.ts","../../src/structure/hooks/useFilteredReleases.ts","../../src/structure/hooks/useDocumentIdStack.ts","../../src/structure/useStructureTool.ts","../../src/structure/panes/document/constants.ts","../../src/structure/panes/document/DocumentInspectorMenuItemsResolver.tsx","../../src/structure/panes/document/useDocumentTitle.ts","../../src/structure/panes/document/DocumentOperationResults.tsx","../../src/structure/components/paneItem/helpers.tsx","../../src/structure/hasObsoleteDraft.ts","../../src/structure/mustChooseNewDocumentDestination.ts","../../src/structure/panes/document/documentInspector/DocumentInspectorHeader.tsx","../../src/structure/panes/document/documentInspector/DocumentInspectorPanel.tsx","../../src/structure/useStructureToolSetting.ts","../../src/structure/panes/document/inspectDialog/constants.ts","../../src/structure/panes/document/inspectDialog/helpers.ts","../../src/structure/panes/document/inspectDialog/InspectDialog.styles.tsx","../../src/structure/panes/document/inspectDialog/Search.tsx","../../src/structure/panes/document/inspectDialog/InspectDialog.tsx","../../src/structure/panes/document/documentPanel/banners/Banner.tsx","../../src/structure/panes/document/documentPanel/banners/DeletedDocumentBanners.tsx","../../src/structure/panes/document/documentPanel/banners/DeprecatedDocumentTypeBanner.tsx","../../src/structure/components/requestPermissionDialog/__telemetry__/RequestPermissionDialog.telemetry.ts","../../src/structure/components/requestPermissionDialog/RequestPermissionDialog.tsx","../../src/structure/components/requestPermissionDialog/useRoleRequestsStatus.tsx","../../src/structure/panes/document/documentPanel/banners/InsufficientPermissionBanner.tsx","../../src/structure/panes/document/documentPanel/banners/ReferenceChangedBanner.tsx","../../src/structure/panes/document/documentPanel/banners/ArchivedReleaseDocumentBanner.tsx","../../src/structure/panes/document/documentPanel/banners/CanvasLinkedBanner.tsx","../../src/structure/panes/document/documentPanel/banners/ChooseNewDocumentDestinationBanner.tsx","../../src/structure/panes/document/documentPanel/banners/CreateLinkedBanner.tsx","../../src/structure/panes/document/documentPanel/banners/DocumentNotInReleaseBanner.tsx","../../src/structure/panes/document/documentPanel/banners/__telemetry__/DraftLiveEditBanner.telemetry.ts","../../src/structure/panes/document/documentPanel/banners/ObsoleteDraftBanner.tsx","../../src/structure/panes/document/documentPanel/banners/OpenReleaseToEditBanner.tsx","../../src/structure/panes/document/documentPanel/banners/RevisionNotFoundBanner.tsx","../../src/structure/panes/document/documentPanel/banners/ScheduledReleaseBanner.tsx","../../src/structure/panes/document/documentPanel/banners/UnpublishedDocumentBanner.tsx","../../src/structure/panes/document/documentPanel/documentViews/FormHeader.tsx","../../src/structure/panes/document/documentPanel/documentViews/FormView.tsx","../../src/structure/panes/document/documentPanel/header/DocumentHeaderTabs.tsx","../../src/structure/panes/document/documentPanel/header/DocumentHeaderTitle.tsx","../../src/structure/panes/document/documentPanel/header/FavoriteToggle.tsx","../../src/structure/panes/document/documentPanel/header/DocumentPanelSubHeader.tsx","../../src/structure/panes/document/documentPanel/DocumentPanel.tsx","../../src/structure/menuNodes.ts","../../src/structure/constants.ts","../../src/structure/panes/document/statusBar/dialogs/constants.ts","../../src/structure/panes/document/statusBar/dialogs/ConfirmDialog.tsx","../../src/structure/panes/document/statusBar/dialogs/ModalDialog.tsx","../../src/structure/panes/document/statusBar/dialogs/PopoverDialog.tsx","../../src/structure/panes/document/statusBar/ActionStateDialog.tsx","../../src/structure/panes/document/statusBar/ActionMenuButton.tsx","../../src/structure/documentActions/DeleteAction.tsx","../../src/structure/documentActions/DiscardChangesAction.tsx","../../src/structure/documentActions/DuplicateAction.tsx","../../src/structure/documentActions/HistoryRestoreAction.tsx","../../src/structure/documentActions/__telemetry__/documentActions.telemetry.ts","../../src/structure/documentActions/PublishAction.tsx","../../src/structure/documentActions/UnpublishAction.tsx","../../src/structure/panes/document/statusBar/DocumentStatusBarActions.tsx","../../src/structure/panes/document/documentPanel/header/hook/useChipScrollPosition.tsx","../../src/structure/panes/document/documentPanel/header/perspective/DocumentPerspectiveList.tsx","../../src/structure/panes/document/documentPanel/header/DocumentPanelHeader.tsx","../../src/structure/components/spacerButton/SpacerButton.tsx","../../src/structure/panes/document/statusBar/DocumentBadges.tsx","../../src/structure/panes/document/timeline/constants.ts","../../src/structure/panes/document/timeline/helpers.ts","../../src/structure/panes/document/timeline/expandableTimelineItemButton.tsx","../../src/structure/panes/document/timeline/timeline.styled.tsx","../../src/structure/panes/document/timeline/timelineI18n.ts","../../src/structure/panes/document/timeline/userAvatarStack.tsx","../../src/structure/panes/document/timeline/timelineItem.tsx","../../src/structure/panes/document/timeline/utils.ts","../../src/structure/panes/document/timeline/timeline.tsx","../../src/structure/panes/document/timeline/TimelineError.tsx","../../src/structure/panes/document/timeline/timelineMenu.tsx","../../src/structure/panes/document/statusBar/DocumentStatusPulse/AnimatedStatusIcon.tsx","../../src/structure/panes/document/statusBar/DocumentStatusPulse/DocumentStatusPulse.tsx","../../src/structure/panes/document/statusBar/DocumentStatusLine.tsx","../../src/structure/panes/document/statusBar/RevisionStatusLine.tsx","../../src/structure/panes/document/statusBar/useResizeObserver.ts","../../src/structure/panes/document/statusBar/DocumentStatusBar.tsx","../../src/structure/panes/document/keyboardShortcuts/DocumentActionShortcuts.tsx","../../src/structure/panes/document/menuItems.ts","../../src/structure/panes/document/document-layout/DocumentLayoutError.tsx","../../src/structure/panes/document/document-layout/DocumentLayoutFooter.tsx","../../src/structure/panes/document/document-layout/DocumentLayout.tsx","../../src/structure/panes/document/document-layout/useDocumentLayoutComponent.ts","../../src/structure/hooks/useDocumentLastRev.ts","../../src/structure/panes/document/__telemetry__/documentPanes.telemetry.ts","../../src/structure/panes/document/getInitialValueTemplateOpts.ts","../../src/structure/panes/document/useDocumentPaneInitialValue.ts","../../src/structure/panes/document/useDocumentPaneInspector.ts","../../src/structure/panes/document/usePreviewUrl.ts","../../src/structure/panes/document/DocumentPaneProvider.tsx","../../src/structure/panes/document/DocumentEventsPane.tsx","../../src/structure/panes/document/DocumentPaneLegacyTimeline.tsx","../../src/structure/panes/document/DocumentPaneProviderWrapper.tsx","../../src/structure/panes/document/useResetHistoryParams.ts","../../src/structure/panes/document/DocumentPane.tsx","../../src/structure/components/paneRouter/BackLink.tsx","../../src/structure/components/paneRouter/ChildLink.tsx","../../src/structure/components/paneRouter/ParameterizedLink.tsx","../../src/structure/components/paneRouter/ReferenceChildLink.tsx","../../src/structure/components/paneRouter/PaneRouterProvider.tsx","../../src/structure/panes/unknown/UnknownPaneType.tsx","../../src/structure/panes/StructureToolPane.tsx","../../src/structure/components/DocTitle.tsx","../../src/structure/components/confirmDeleteDialog/ConfirmDeleteDialogBody.styles.tsx","../../src/structure/components/paneItem/PaneItemPreview.tsx","../../src/structure/components/confirmDeleteDialog/ReferencePreviewLink.tsx","../../src/structure/components/confirmDeleteDialog/ConfirmDeleteDialogBody.tsx","../../src/structure/components/confirmDeleteDialog/useReferringDocuments.ts","../../src/structure/components/confirmDeleteDialog/ConfirmDeleteDialog.tsx","../../src/structure/components/confirmDeleteDialog/index.tsx","../../src/structure/components/IntentButton.tsx","../../src/structure/components/paneHeaderActions/InsufficientPermissionsMessageTooltip.tsx","../../src/structure/components/paneHeaderActions/PaneHeaderCreateButton.tsx","../../src/structure/components/paneHeaderActions/PaneHeaderActions.tsx","../../src/structure/components/MissingSchemaType.tsx","../../src/structure/components/paneItem/PaneItem.tsx","../../src/structure/components/RenderActionCollectionState.tsx","../../src/structure/components/RenderBadgeCollectionState.tsx","../../src/structure/panes/documentList/constants.ts","../../src/structure/panes/documentList/DocumentListPaneContent.tsx","../../src/structure/panes/documentList/helpers.ts","../../src/structure/panes/documentList/listenSearchQuery.ts","../../src/structure/panes/documentList/useDocumentList.ts","../../src/structure/panes/documentList/DocumentListPane.tsx","../../src/structure/panes/documentList/PaneHeader.tsx","../../src/structure/panes/documentList/sheetList/DocumentSheetListSelect.tsx","../../src/structure/panes/documentList/sheetList/DocumentSheetListProvider.tsx","../../src/structure/panes/documentList/sheetList/SheetListCell.tsx","../../src/structure/panes/documentList/sheetList/useDocumentSheetColumns.tsx","../../src/structure/panes/documentList/sheetList/ColumnsControl.tsx","../../src/structure/panes/documentList/sheetList/DocumentSheetListFilter.tsx","../../src/structure/panes/documentList/sheetList/DocumentSheetListHeader.tsx","../../src/structure/panes/documentList/sheetList/DocumentSheetListPaginator.tsx","../../src/structure/panes/documentList/sheetList/useDocumentSheetListStore.ts","../../src/structure/panes/documentList/sheetList/useDocumentSheetList.ts","../../src/structure/panes/documentList/sheetList/DocumentSheetListPane.tsx","../../src/structure/panes/documentList/PaneContainer.tsx","../../src/structure/documentBadges/LiveEditBadge.ts","../../src/structure/getIntentState.ts","../../src/structure/panes/document/inspectors/changes/ChangesInspector.tsx","../../src/structure/panes/document/timeline/events/EventTimelineItem.tsx","../../src/structure/panes/document/timeline/events/PublishedEventMenu.tsx","../../src/structure/panes/document/timeline/events/EventsTimeline.tsx","../../src/structure/panes/document/timeline/events/EventsTimelineMenu.tsx","../../src/structure/panes/document/inspectors/changes/EventsInspector.tsx","../../src/structure/panes/document/inspectors/changes/EventsSelector.tsx","../../src/structure/panes/document/inspectors/changes/HistorySelector.tsx","../../src/structure/panes/document/inspectors/changes/ChangesTabs.tsx","../../src/structure/panes/document/inspectors/changes/index.ts","../../src/structure/panes/document/inspectors/validation/getPathTitles.ts","../../src/structure/panes/document/inspectors/validation/ValidationInspector.tsx","../../src/structure/panes/document/inspectors/validation/index.ts","../../src/structure/router.ts","../../src/structure/structureTool.ts"],"sourcesContent":["import {useMemo} from 'react'\nimport {Subject} from 'rxjs'\n\nimport {type PathSyncChannel, type PathSyncState} from '../types/pathSyncChannel'\n\n/**\n * @internal\n */\nexport function useCreatePathSyncChannel(): PathSyncChannel {\n return useMemo(() => new Subject<PathSyncState>(), [])\n}\n","/**\n * @internal\n */\nexport const DIFF_VIEW_SEARCH_PARAMETER = 'diffView'\n\n/**\n * @internal\n */\nexport const DIFF_VIEW_PREVIOUS_DOCUMENT_SEARCH_PARAMETER = 'previousDocument'\n\n/**\n * @internal\n */\nexport const DIFF_VIEW_NEXT_DOCUMENT_SEARCH_PARAMETER = 'nextDocument'\n\n/**\n * @internal\n */\nexport const DIFF_SEARCH_PARAM_DELIMITER = ','\n","import {fromPairs, toPairs} from 'lodash'\nimport {useCallback} from 'react'\nimport {useRouter} from 'sanity/router'\n\nimport {\n DIFF_SEARCH_PARAM_DELIMITER,\n DIFF_VIEW_NEXT_DOCUMENT_SEARCH_PARAMETER,\n DIFF_VIEW_PREVIOUS_DOCUMENT_SEARCH_PARAMETER,\n DIFF_VIEW_SEARCH_PARAMETER,\n} from '../constants'\nimport {type DiffViewMode} from '../types/diffViewMode'\n\ntype NavigateDiffView = (\n options: {\n mode?: DiffViewMode\n } & Partial<\n Record<\n 'previousDocument' | 'nextDocument',\n {\n type: string\n id: string\n }\n >\n >,\n) => void\n\nexport interface DiffViewRouter {\n navigateDiffView: NavigateDiffView\n exitDiffView: () => void\n}\n\n/**\n * @internal\n */\nexport function useDiffViewRouter(): DiffViewRouter {\n const {navigate, state: routerState} = useRouter()\n\n const navigateDiffView = useCallback<NavigateDiffView>(\n ({mode, previousDocument, nextDocument}) => {\n const next = {\n ...fromPairs(routerState._searchParams),\n ...(mode\n ? {\n [DIFF_VIEW_SEARCH_PARAMETER]: mode,\n }\n : {}),\n ...(previousDocument\n ? {\n [DIFF_VIEW_PREVIOUS_DOCUMENT_SEARCH_PARAMETER]: [\n previousDocument.type,\n previousDocument.id,\n ].join(DIFF_SEARCH_PARAM_DELIMITER),\n }\n : {}),\n ...(nextDocument\n ? {\n [DIFF_VIEW_NEXT_DOCUMENT_SEARCH_PARAMETER]: [nextDocument.type, nextDocument.id].join(\n DIFF_SEARCH_PARAM_DELIMITER,\n ),\n }\n : {}),\n }\n\n navigate({\n ...routerState,\n _searchParams: toPairs(next),\n })\n },\n [navigate, routerState],\n )\n\n const exitDiffView = useCallback(() => {\n navigate({\n ...routerState,\n _searchParams: (routerState._searchParams ?? []).filter(\n ([key]) =>\n ![\n DIFF_VIEW_SEARCH_PARAMETER,\n DIFF_VIEW_PREVIOUS_DOCUMENT_SEARCH_PARAMETER,\n DIFF_VIEW_NEXT_DOCUMENT_SEARCH_PARAMETER,\n ].includes(key),\n ),\n })\n }, [navigate, routerState])\n\n return {\n navigateDiffView,\n exitDiffView,\n }\n}\n","/**\n * @internal\n */\nexport const diffViewModes = ['version'] as const\n\n/**\n * @internal\n */\nexport type DiffViewMode = (typeof diffViewModes)[number]\n","import {useEffect, useMemo} from 'react'\nimport {useRouter} from 'sanity/router'\n\nimport {\n DIFF_SEARCH_PARAM_DELIMITER,\n DIFF_VIEW_NEXT_DOCUMENT_SEARCH_PARAMETER,\n DIFF_VIEW_PREVIOUS_DOCUMENT_SEARCH_PARAMETER,\n DIFF_VIEW_SEARCH_PARAMETER,\n} from '../constants'\nimport {type DiffViewMode, diffViewModes} from '../types/diffViewMode'\n\nfunction isDiffViewMode(maybeDiffViewMode: unknown): maybeDiffViewMode is DiffViewMode {\n return diffViewModes.includes(maybeDiffViewMode as DiffViewMode)\n}\n\ntype DiffViewState =\n | {\n isActive: true\n state: 'ready'\n mode: DiffViewMode\n documents: Record<\n 'previous' | 'next',\n {\n type: string\n id: string\n }\n >\n }\n | {\n isActive: true\n state: 'error'\n mode: DiffViewMode\n documents?: never\n }\n | {\n isActive: false\n state?: never\n mode?: never\n documents?: never\n }\n\nexport function useDiffViewState({\n onParamsError,\n}: {\n onParamsError?: (errors: DiffViewStateErrorWithInput[]) => void\n} = {}): DiffViewState {\n const {state: routerState} = useRouter()\n const searchParams = new URLSearchParams(routerState._searchParams)\n const previousDocument = searchParams.get(DIFF_VIEW_PREVIOUS_DOCUMENT_SEARCH_PARAMETER)\n const nextDocument = searchParams.get(DIFF_VIEW_NEXT_DOCUMENT_SEARCH_PARAMETER)\n const mode = searchParams.get(DIFF_VIEW_SEARCH_PARAMETER)\n const anyParamSet = [previousDocument, nextDocument, mode].some((param) => param !== null)\n\n const params = useMemo(\n () =>\n parseParams({\n previousDocument: previousDocument ?? '',\n nextDocument: nextDocument ?? '',\n mode: mode ?? '',\n }),\n [mode, nextDocument, previousDocument],\n )\n\n useEffect(() => {\n if (params.result === 'error' && anyParamSet) {\n onParamsError?.(params.errors)\n }\n }, [anyParamSet, onParamsError, params])\n\n if (params.result === 'error') {\n return {\n isActive: false,\n }\n }\n\n return {\n state: 'ready',\n isActive: true,\n ...params.params,\n }\n}\n\ntype DiffViewStateError =\n | 'invalidModeParam'\n | 'invalidPreviousDocumentParam'\n | 'invalidNextDocumentParam'\n\ntype DiffViewStateErrorWithInput = [error: DiffViewStateError, input: unknown]\n\ninterface ParamsSuccess {\n result: 'success'\n params: Pick<DiffViewState & {state: 'ready'}, 'mode' | 'documents'>\n}\n\ninterface ParamsError {\n result: 'error'\n errors: DiffViewStateErrorWithInput[]\n}\n\nfunction parseParams({\n previousDocument,\n nextDocument,\n mode,\n}: {\n previousDocument: string\n nextDocument: string\n mode: string\n}): ParamsSuccess | ParamsError {\n const errors: DiffViewStateErrorWithInput[] = []\n\n const [previousDocumentType, previousDocumentId] = previousDocument\n .split(DIFF_SEARCH_PARAM_DELIMITER)\n .filter(Boolean)\n\n const [nextDocumentType, nextDocumentId] = nextDocument\n .split(DIFF_SEARCH_PARAM_DELIMITER)\n .filter(Boolean)\n\n if (!isDiffViewMode(mode)) {\n errors.push(['invalidModeParam', mode])\n }\n\n if (typeof previousDocumentType === 'undefined' || typeof previousDocumentId === 'undefined') {\n errors.push(['invalidPreviousDocumentParam', previousDocument])\n }\n\n if (typeof nextDocumentType === 'undefined' || typeof nextDocumentId === 'undefined') {\n errors.push(['invalidNextDocumentParam', nextDocument])\n }\n\n if (errors.length !== 0) {\n return {\n result: 'error',\n errors,\n }\n }\n\n return {\n result: 'success',\n params: {\n mode,\n documents: {\n previous: {\n type: previousDocumentType,\n id: previousDocumentId,\n },\n next: {\n type: nextDocumentType,\n id: nextDocumentId,\n },\n },\n },\n } as ParamsSuccess\n}\n","import {useEffect} from 'react'\nimport ScrollMirror from 'scrollmirror'\n\n/**\n * Use the ScrollMirror library to synchronise the scroll position for an array of elements.\n *\n * @internal\n */\nexport function useScrollMirror(elements: (HTMLElement | null)[]): void {\n useEffect(() => {\n const existentElements = elements.filter((element) => element !== null)\n\n if (existentElements.length === 0) {\n return undefined\n }\n\n const scrollMirror = new ScrollMirror(existentElements)\n return () => scrollMirror.destroy()\n }, [elements])\n}\n","import {CloseIcon, LockIcon, TransferIcon} from '@sanity/icons'\nimport {\n Box,\n // eslint-disable-next-line no-restricted-imports -- we need more control over how the `Button` component is rendered\n Button,\n type ButtonTone,\n Flex,\n Menu,\n // eslint-disable-next-line no-restricted-imports -- the `VersionModeHeader` component needs more control over how the `MenuItem` component is rendered\n MenuItem,\n Stack,\n Text,\n} from '@sanity/ui'\n// eslint-disable-next-line @sanity/i18n/no-i18next-import -- figure out how to have the linter be fine with importing types-only\nimport {type TFunction} from 'i18next'\nimport {type ComponentProps, type ComponentType, useCallback, useMemo} from 'react'\nimport {\n type DocumentLayoutProps,\n formatRelativeLocalePublishDate,\n getDraftId,\n getPublishedId,\n getReleaseIdFromReleaseDocumentId,\n getReleaseTone,\n getVersionFromId,\n getVersionId,\n isDraftId,\n isPublishedId,\n isReleaseDocument,\n isReleaseScheduledOrScheduling,\n ReleaseAvatar,\n type ReleaseDocument,\n useActiveReleases,\n useDocumentVersions,\n useEditState,\n useTranslation,\n useWorkspace,\n} from 'sanity'\nimport {styled} from 'styled-components'\n\nimport {MenuButton} from '../../../../ui-components/menuButton/MenuButton'\nimport {structureLocaleNamespace} from '../../../i18n'\nimport {useDiffViewRouter} from '../../hooks/useDiffViewRouter'\nimport {useDiffViewState} from '../../hooks/useDiffViewState'\n\nconst VersionModeHeaderLayout = styled.header`\n display: grid;\n grid-area: header;\n grid-template-columns: 1fr min-content 1fr;\n border-block-end: 1px solid var(--card-border-color);\n`\n\nconst VersionModeHeaderLayoutSection = styled.div`\n display: flex;\n justify-content: space-between;\n align-items: center;\n`\n\n/**\n * The header component that is rendered when diff view is being used to compare versions of a\n * document.\n *\n * @internal\n */\nexport const VersionModeHeader: ComponentType<\n {state: 'pending' | 'ready' | 'error'} & Pick<DocumentLayoutProps, 'documentId'>\n> = ({documentId, state}) => {\n const {t} = useTranslation(structureLocaleNamespace)\n const {data: documentVersions} = useDocumentVersions({documentId})\n const {exitDiffView, navigateDiffView} = useDiffViewRouter()\n const {documents} = useDiffViewState()\n const activeReleases = useActiveReleases()\n const releasesIds = documentVersions.flatMap((id) => getVersionFromId(id) ?? [])\n\n const releases = useMemo(() => {\n return activeReleases.data.filter((release) => {\n const releaseId = getReleaseIdFromReleaseDocumentId(release._id)\n return typeof releaseId !== 'undefined' && releasesIds.includes(releaseId)\n })\n }, [activeReleases.data, releasesIds])\n\n const onSelectPreviousRelease = useCallback(\n (selectedDocumentId: string): void => {\n if (typeof documents?.previous !== 'undefined') {\n navigateDiffView({\n previousDocument: {\n ...documents.previous,\n id: selectedDocumentId,\n },\n })\n }\n },\n [documents?.previous, navigateDiffView],\n )\n\n const onSelectNextRelease = useCallback(\n (selectedDocumentId: string): void => {\n if (typeof documents?.next !== 'undefined') {\n navigateDiffView({\n nextDocument: {\n ...documents.next,\n id: selectedDocumentId,\n },\n })\n }\n },\n [documents?.next, navigateDiffView],\n )\n\n return (\n <VersionModeHeaderLayout>\n <VersionModeHeaderLayoutSection>\n <Box padding={4}>\n <Text as=\"h1\" size={1} muted>\n {t('compare-versions.title')}\n </Text>\n </Box>\n {typeof documents?.previous !== 'undefined' && (\n <VersionMenu\n releases={releases}\n onSelectRelease={onSelectPreviousRelease}\n role=\"previous\"\n documentId={documentId}\n state={state}\n document={documents.previous}\n />\n )}\n </VersionModeHeaderLayoutSection>\n <Flex align=\"center\" paddingX={3}>\n <Text size={1}>\n <TransferIcon />\n </Text>\n </Flex>\n <VersionModeHeaderLayoutSection>\n {typeof documents?.next !== 'undefined' && (\n <VersionMenu\n releases={releases}\n onSelectRelease={onSelectNextRelease}\n role=\"next\"\n documentId={documentId}\n state={state}\n document={documents.next}\n />\n )}\n <Box\n padding={3}\n style={{\n justifySelf: 'end',\n }}\n >\n <Button icon={CloseIcon} mode=\"bleed\" onClick={exitDiffView} padding={2} />\n </Box>\n </VersionModeHeaderLayoutSection>\n </VersionModeHeaderLayout>\n )\n}\n\ninterface VersionMenuProps {\n state: 'pending' | 'ready' | 'error'\n releases: ReleaseDocument[]\n role: 'previous' | 'next'\n onSelectRelease: (releaseId: string) => void\n documentId: string\n document: {\n type: string\n id: string\n }\n}\n\nconst VersionMenu: ComponentType<VersionMenuProps> = ({\n releases = [],\n onSelectRelease,\n role,\n documentId,\n document,\n}) => {\n const {published, draft} = useEditState(getPublishedId(document.id), document.type)\n const selected = useMemo(() => findRelease(document.id, releases), [document.id, releases])\n const {t: tStructure} = useTranslation(structureLocaleNamespace)\n const {t: tCore} = useTranslation()\n\n const {\n document: {\n drafts: {enabled: isDraftModelEnabled},\n },\n } = useWorkspace()\n\n return (\n <MenuButton\n id={role}\n button={\n <Button\n type=\"button\"\n mode=\"bleed\"\n padding={2}\n paddingRight={3}\n radius=\"full\"\n selected\n {...getMenuButtonProps({selected, tCore, tStructure})}\n />\n }\n menu={\n <Menu>\n {published && (\n <VersionMenuItem\n type=\"published\"\n onSelect={onSelectRelease}\n isSelected={selected === 'published'}\n documentId={documentId}\n />\n )}\n {isDraftModelEnabled && draft && (\n <VersionMenuItem\n type=\"draft\"\n onSelect={onSelectRelease}\n isSelected={selected === 'draft'}\n documentId={documentId}\n />\n )}\n {releases.map((release) => (\n <VersionMenuItem\n key={release._id}\n release={release}\n onSelect={onSelectRelease}\n isSelected={typeof selected !== 'string' && selected?._id === release._id}\n documentId={documentId}\n />\n ))}\n </Menu>\n }\n />\n )\n}\n\ntype VersionMenuItemProps = {\n onSelect: (releaseId: string) => void\n isSelected?: boolean\n documentId: string\n} & (\n | {\n release: ReleaseDocument\n type?: never\n }\n | {\n type: 'published' | 'draft'\n release?: never\n }\n)\n\nconst VersionMenuItem: ComponentType<VersionMenuItemProps> = ({\n type,\n release,\n onSelect,\n isSelected,\n documentId,\n}) => {\n const {t: tCore} = useTranslation()\n const {t: tStructure} = useTranslation(structureLocaleNamespace)\n\n const onClick = useCallback(() => {\n if (type === 'draft') {\n onSelect(getDraftId(documentId))\n return\n }\n\n if (type === 'published') {\n onSelect(getPublishedId(documentId))\n return\n }\n\n if (typeof release?._id !== 'undefined') {\n onSelect(getVersionId(documentId, getReleaseIdFromReleaseDocumentId(release._id)))\n }\n }, [type, onSelect, documentId, release?._id])\n\n if (type) {\n const tone: ButtonTone = type === 'published' ? 'positive' : 'caution'\n\n return (\n <MenuItem padding={1} paddingRight={3} onClick={onClick} pressed={isSelected}>\n <Flex gap={1}>\n <ReleaseAvatar padding={2} tone={tone} />\n <Box paddingY={2}>\n <Text size={1} weight=\"medium\">\n {tStructure(['compare-versions.status', type].join('.'))}\n </Text>\n </Box>\n </Flex>\n </MenuItem>\n )\n }\n\n const tone: ButtonTone = release ? getReleaseTone(release) : 'neutral'\n\n return (\n <MenuItem padding={1} paddingRight={3} onClick={onClick} pressed={isSelected}>\n <Flex gap={1}>\n <ReleaseAvatar padding={2} tone={tone} />\n <Stack flex={1} paddingY={2} paddingRight={2} space={2}>\n <Text size={1} weight=\"medium\">\n {release.metadata.title || tCore('release.placeholder-untitled-release')}\n </Text>\n {['asap', 'undecided'].includes(release.metadata.releaseType) && (\n <Text muted size={1}>\n {tCore(`release.type.${release.metadata.releaseType}`)}\n </Text>\n )}\n {release.metadata.releaseType === 'scheduled' && (\n <Text muted size={1}>\n {formatRelativeLocalePublishDate(release)}\n </Text>\n )}\n </Stack>\n <Flex flex=\"none\">\n {isReleaseScheduledOrScheduling(release) && (\n <Box padding={2}>\n <Text size={1}>\n <LockIcon />\n </Text>\n </Box>\n )}\n </Flex>\n </Flex>\n </MenuItem>\n )\n}\n\nfunction getMenuButtonProps({\n selected,\n tCore,\n tStructure,\n}: {\n selected?: ReleaseDocument | 'published' | 'draft'\n tCore: TFunction\n tStructure: TFunction\n}): Pick<ComponentProps<typeof Button>, 'text' | 'tone' | 'icon' | 'iconRight' | 'disabled'> {\n if (typeof selected === 'undefined') {\n return {\n text: tCore('common.loading'),\n tone: 'neutral',\n disabled: true,\n }\n }\n\n if (isReleaseDocument(selected)) {\n const tone: ButtonTone = selected ? getReleaseTone(selected) : 'neutral'\n\n return {\n text: selected?.metadata.title || tCore('release.placeholder-untitled-release'),\n icon: <ReleaseAvatar padding={1} tone={tone} />,\n iconRight: selected && isReleaseScheduledOrScheduling(selected) ? <LockIcon /> : undefined,\n tone,\n }\n }\n\n const tone: ButtonTone = selected === 'published' ? 'positive' : 'caution'\n\n return {\n text: tStructure(['compare-versions.status', selected].join('.')),\n icon: <ReleaseAvatar padding={1} tone={tone} />,\n tone,\n }\n}\n\n/**\n * If the provided document id represents a version, find and return the corresponding release\n * document. Otherwise, return a string literal signifying whether the document id represents a\n * published or draft document.\n */\nfunction findRelease(\n documentId: string,\n releases: ReleaseDocument[],\n): ReleaseDocument | 'published' | 'draft' | undefined {\n if (isPublishedId(documentId)) {\n return 'published'\n }\n\n if (isDraftId(documentId)) {\n return 'draft'\n }\n\n return releases.find(\n ({_id}) => getReleaseIdFromReleaseDocumentId(_id) === getVersionFromId(documentId),\n )\n}\n","import {styled} from 'styled-components'\n\nexport const DialogLayout = styled.div`\n --offset-block: 40px;\n display: grid;\n height: calc(100vh - var(--offset-block));\n min-height: 0;\n overflow: hidden;\n grid-template-areas:\n 'header header'\n 'previous-document next-document';\n grid-template-columns: 1fr 1fr;\n grid-template-rows: min-content minmax(0, 1fr);\n`\n","import {type ComponentType} from 'react'\nimport {type DocumentLayoutProps, type PluginOptions} from 'sanity'\n\n/**\n * Pick the document layout component when composing the component middleware chain.\n */\nexport function pickDocumentLayoutComponent(plugin: PluginOptions) {\n return plugin.document?.components?.unstable_layout as ComponentType<\n Omit<DocumentLayoutProps, 'renderDefault'>\n >\n}\n","import {type Path} from '@sanity/types'\nimport {useCallback, useMemo} from 'react'\nimport deepEquals from 'react-fast-compare'\nimport {distinctUntilChanged, filter, map, type Observable} from 'rxjs'\n\nimport {type PathSyncChannelProps, type PathSyncState} from '../types/pathSyncChannel'\n\ntype Push = (state: PathSyncState) => void\n\n/**\n * Synchronise the open path between multiple document panes.\n *\n * @internal\n */\nexport function usePathSyncChannel({syncChannel, id}: PathSyncChannelProps): {\n push: Push\n path: Observable<Path>\n} {\n const push = useCallback<Push>(\n (state) => syncChannel.next({...state, source: id}),\n [id, syncChannel],\n )\n\n const path = useMemo(\n () =>\n syncChannel.pipe(\n distinctUntilChanged<PathSyncState>((previous, next) =>\n deepEquals(previous.path, next.path),\n ),\n filter(({source}) => source !== id),\n map((state) => state.path),\n ),\n [id, syncChannel],\n )\n\n return {\n path,\n push,\n }\n}\n","import {styled} from 'styled-components'\n\nexport const Scroller = styled.div`\n position: relative;\n height: 100%;\n overflow: auto;\n scroll-behavior: smooth;\n scrollbar-width: var(--scrollbar-width);\n overscroll-behavior: contain;\n will-change: scroll-position;\n`\n","import {type Path, type SanityDocument} from '@sanity/types'\nimport {\n BoundaryElementProvider,\n Card,\n Container as UiContainer,\n DialogProvider,\n PortalProvider,\n} from '@sanity/ui'\nimport {noop} from 'lodash'\nimport {\n type ComponentType,\n type CSSProperties,\n forwardRef,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react'\nimport {\n ChangeIndicatorsTracker,\n createPatchChannel,\n FormBuilder,\n getPublishedId,\n getVersionFromId,\n isDraftId,\n isPublishedId,\n isVersionId,\n LoadingBlock,\n useDocumentForm,\n useEditState,\n useMiddlewareComponents,\n VirtualizerScrollInstanceProvider,\n} from 'sanity'\nimport {CommentsEnabledContext, ReviewChangesContext} from 'sanity/_singletons'\nimport {styled} from 'styled-components'\n\nimport {pickDocumentLayoutComponent} from '../../panes/document/document-layout/pickDocumentLayoutComponent'\nimport {usePathSyncChannel} from '../hooks/usePathSyncChannel'\nimport {type PathSyncChannel} from '../types/pathSyncChannel'\nimport {Scroller} from './Scroller'\n\nconst DiffViewPaneLayout = styled(Card)`\n position: relative;\n grid-area: var(--grid-area);\n`\n\nconst Container = styled(UiContainer)`\n width: auto;\n`\n\ninterface DiffViewPaneProps {\n documentType: string\n documentId: string\n role: 'previous' | 'next'\n scrollElement: HTMLElement | null\n syncChannel: PathSyncChannel\n compareDocument: {\n type: string\n id: string\n }\n}\n\nexport const DiffViewPane = forwardRef<HTMLDivElement, DiffViewPaneProps>(function DiffViewPane(\n {role, documentType, documentId, scrollElement, syncChannel, compareDocument},\n ref,\n) {\n const containerElement = useRef<HTMLDivElement | null>(null)\n const [portalElement, setPortalElement] = useState<HTMLDivElement | null>(null)\n const [boundaryElement, setBoundaryElement] = useState<HTMLDivElement | null>(null)\n\n const DocumentLayout = useMiddlewareComponents({\n pick: pickDocumentLayoutComponent,\n defaultComponent: useCallback(\n () => (\n <DiffViewDocument\n compareDocument={compareDocument}\n documentId={documentId}\n documentType={documentType}\n role={role}\n scrollElement={scrollElement}\n syncChannel={syncChannel}\n />\n ),\n [compareDocument, documentId, documentType, role, scrollElement, syncChannel],\n ),\n })\n\n return (\n <ReviewChangesContext.Provider\n value={{\n // Render the change indicators inertly, because the diff view modal does not currently\n // provide a way to display document inspectors.\n isInteractive: false,\n onOpenReviewChanges: noop,\n onSetFocus: noop,\n isReviewChangesOpen: false,\n }}\n >\n <ChangeIndicatorsTracker>\n <VirtualizerScrollInstanceProvider\n scrollElement={scrollElement}\n containerElement={containerElement}\n >\n <BoundaryElementProvider element={boundaryElement}>\n <DiffViewPaneLayout\n ref={setBoundaryElement}\n style={\n {\n '--grid-area': `${role}-document`,\n } as CSSProperties\n }\n borderLeft={role === 'next'}\n >\n <Scroller\n ref={ref}\n style={\n {\n // The scroll position is synchronised between panes. This style hides the\n // scrollbar for all panes except the one displaying the next document.\n '--scrollbar-width': role !== 'next' && 'none',\n } as CSSProperties\n }\n >\n <PortalProvider element={portalElement}>\n <DialogProvider position=\"absolute\">\n <Container ref={containerElement} padding={4} width={1}>\n <DocumentLayout documentId={documentId} documentType={documentType} />\n </Container>\n </DialogProvider>\n </PortalProvider>\n </Scroller>\n <div data-testid=\"diffView-document-panel-portal\" ref={setPortalElement} />\n </DiffViewPaneLayout>\n </BoundaryElementProvider>\n </VirtualizerScrollInstanceProvider>\n </ChangeIndicatorsTracker>\n </ReviewChangesContext.Provider>\n )\n})\n\nconst DiffViewDocument: ComponentType<DiffViewPaneProps> = ({\n role,\n documentType,\n documentId,\n syncChannel,\n compareDocument,\n}) => {\n const compareValue = useCompareValue({compareDocument})\n const [patchChannel] = useState(() => createPatchChannel())\n\n const {\n formState,\n onChange,\n onFocus,\n onBlur,\n onSetActiveFieldGroup,\n onSetCollapsedFieldSet,\n onSetCollapsedPath,\n collapsedFieldSets,\n ready,\n collapsedPaths,\n schemaType,\n value,\n onProgrammaticFocus,\n ...documentForm\n } = useDocumentForm({\n documentId: getPublishedId(documentId),\n documentType,\n selectedPerspectiveName: perspectiveName(documentId),\n releaseId: getVersionFromId(documentId),\n comparisonValue: compareValue,\n })\n\n const isLoading = formState === null || !ready\n\n const pathSyncChannel = usePathSyncChannel({\n id: role,\n syncChannel,\n })\n\n const onPathOpen = useCallback(\n (path: Path) => {\n documentForm.onPathOpen(path)\n pathSyncChannel.push({source: role, path})\n },\n [documentForm, pathSyncChannel, role],\n )\n\n useEffect(() => {\n const subscription = pathSyncChannel.path.subscribe(onProgrammaticFocus)\n return () => subscription.unsubscribe()\n }, [onProgrammaticFocus, pathSyncChannel.path])\n\n return isLoading ? (\n <LoadingBlock showText />\n ) : (\n <CommentsEnabledContext.Provider\n value={{\n enabled: false,\n mode: null,\n }}\n >\n <FormBuilder\n __internal_patchChannel={patchChannel}\n id={`diffView-pane-${role}`}\n onChange={onChange}\n onPathFocus={onFocus}\n onPathOpen={onPathOpen}\n onPathBlur={onBlur}\n onFieldGroupSelect={onSetActiveFieldGroup}\n onSetFieldSetCollapsed={onSetCollapsedFieldSet}\n onSetPathCollapsed={onSetCollapsedPath}\n collapsedPaths={collapsedPaths}\n collapsedFieldSets={collapsedFieldSets}\n focusPath={formState.focusPath}\n changed={formState.changed}\n focused={formState.focused}\n groups={formState.groups}\n validation={formState.validation}\n members={formState.members}\n presence={formState.presence}\n schemaType={schemaType}\n value={value}\n />\n </CommentsEnabledContext.Provider>\n )\n}\n\nfunction perspectiveName(documentId: string): string | undefined {\n if (isVersionId(documentId)) {\n return getVersionFromId(documentId)\n }\n\n if (isPublishedId(documentId)) {\n return 'published'\n }\n\n return undefined\n}\n\ntype UseCompareValueOptions = Pick<DiffViewPaneProps, 'compareDocument'>\n\n/**\n * Fetch the contents of `compareDocument` for comparison with another version of the document.\n */\nfunction useCompareValue({compareDocument}: UseCompareValueOptions): SanityDocument | undefined {\n const compareDocumentEditState = useEditState(\n getPublishedId(compareDocument.id),\n compareDocument.type,\n 'low',\n getVersionFromId(compareDocument.id),\n )\n\n return useMemo(() => {\n if (isVersionId(compareDocument.id)) {\n return compareDocumentEditState.version ?? undefined\n }\n\n if (isDraftId(compareDocument.id)) {\n return compareDocumentEditState.draft ?? undefined\n }\n\n if (isPublishedId(compareDocument.id)) {\n return compareDocumentEditState.published ?? undefined\n }\n\n return undefined\n }, [\n compareDocument.id,\n compareDocumentEditState.draft,\n compareDocumentEditState.published,\n compareDocumentEditState.version,\n ])\n}\n","import {type ReferenceInputOptions} from 'sanity'\nimport {useIntentLink} from 'sanity/router'\nimport {styled} from 'styled-components'\n\nconst Link = styled.a`\n flex: 1;\n text-decoration: none;\n color: inherit;\n`\n\nexport const EditReferenceLinkComponent: ReferenceInputOptions['EditReferenceLinkComponent'] = ({\n children,\n documentId: _documentId,\n documentType,\n}) => {\n const {href} = useIntentLink({\n intent: 'edit',\n params: {\n id: _documentId,\n type: documentType,\n },\n })\n\n return (\n <Link href={href} target=\"_blank\" rel=\"noopener noreferrer\">\n {children}\n </Link>\n )\n}\n","import {type ComponentType, useContext, useMemo, useState} from 'react'\nimport {type DocumentLayoutProps} from 'sanity'\nimport {ReferenceInputOptionsContext} from 'sanity/_singletons'\n\nimport {Dialog} from '../../../ui-components/dialog/Dialog'\nimport {useCreatePathSyncChannel} from '../hooks/useCreatePathSyncChannel'\nimport {useDiffViewRouter} from '../hooks/useDiffViewRouter'\nimport {useDiffViewState} from '../hooks/useDiffViewState'\nimport {useScrollMirror} from '../hooks/useScrollMirror'\nimport {VersionModeHeader} from '../versionMode/components/VersionModeHeader'\nimport {DialogLayout} from './DialogLayout'\nimport {DiffViewPane} from './DiffViewPane'\nimport {EditReferenceLinkComponent} from './EditReferenceLinkComponent'\n\nexport const DiffView: ComponentType<Pick<DocumentLayoutProps, 'documentId'>> = ({documentId}) => {\n const {documents, state, mode} = useDiffViewState()\n const {exitDiffView} = useDiffViewRouter()\n const syncChannel = useCreatePathSyncChannel()\n const [previousPaneElement, setPreviousPaneElement] = useState<HTMLElement | null>(null)\n const [nextPaneElement, setNextPaneElement] = useState<HTMLElement | null>(null)\n const referenceInputOptionsContext = useContext(ReferenceInputOptionsContext)\n\n const diffViewReferenceInputOptionsContext = useMemo(\n () => ({\n ...referenceInputOptionsContext,\n disableNew: true,\n EditReferenceLinkComponent,\n }),\n [referenceInputOptionsContext],\n )\n\n useScrollMirror([previousPaneElement, nextPaneElement])\n\n return (\n <ReferenceInputOptionsContext.Provider value={diffViewReferenceInputOptionsContext}>\n <Dialog\n id=\"diffView\"\n width=\"auto\"\n onClose={exitDiffView}\n padding={false}\n __unstable_hideCloseButton\n >\n <DialogLayout>\n {mode === 'version' && <VersionModeHeader documentId={documentId} state={state} />}\n {state === 'ready' && (\n <>\n <DiffViewPane\n documentType={documents.previous.type}\n documentId={documents.previous.id}\n role=\"previous\"\n ref={setPreviousPaneElement}\n scrollElement={previousPaneElement}\n syncChannel={syncChannel}\n compareDocument={documents.previous}\n />\n <DiffViewPane\n documentType={documents.next.type}\n documentId={documents.next.id}\n role=\"next\"\n ref={setNextPaneElement}\n scrollElement={nextPaneElement}\n syncChannel={syncChannel}\n // The previous document's edit state is used to calculate the diff inroduced by the next document.\n compareDocument={documents.previous}\n />\n </>\n )}\n </DialogLayout>\n </Dialog>\n </ReferenceInputOptionsContext.Provider>\n )\n}\n","import {useToast} from '@sanity/ui'\nimport {type ComponentType, type PropsWithChildren} from 'react'\nimport {type DocumentLayoutProps, useTranslation} from 'sanity'\n\nimport {structureLocaleNamespace} from '../../i18n'\nimport {DiffView} from '../components/DiffView'\nimport {useDiffViewState} from '../hooks/useDiffViewState'\n\nexport const DiffViewDocumentLayout: ComponentType<\n PropsWithChildren<Pick<DocumentLayoutProps, 'documentId' | 'documentType'>>\n> = ({children, documentId}) => {\n const toast = useToast()\n const {t} = useTranslation(structureLocaleNamespace)\n const {isActive} = useDiffViewState({\n onParamsError: (errors) => {\n toast.push({\n id: 'diffViewParamsParsingError',\n status: 'error',\n title: t('compare-version.error.invalidParams.title'),\n description: (\n <ul>\n {errors.map(([error, input]) => (\n <li key={error}>\n {t(`compare-version.error.${error}`, {\n input,\n })}\n </li>\n ))}\n </ul>\n ),\n })\n },\n })\n\n return (\n <>\n {children}\n {isActive && <DiffView documentId={documentId} />}\n </>\n )\n}\n","/**\n * @internal\n */\nexport const PANE_DEBUG = false\n\n/**\n * @internal\n */\nexport const PANE_COLLAPSED_WIDTH = 51\n\n/**\n * @internal\n */\nexport const PANE_DEFAULT_MIN_WIDTH = PANE_COLLAPSED_WIDTH * 4\n","import {useContext} from 'react'\nimport {PaneLayoutContext} from 'sanity/_singletons'\n\nimport {type PaneLayoutContextValue} from './types'\n\n/**\n *\n * @hidden\n * @beta This API will change. DO NOT USE IN PRODUCTION.\n */\nexport function usePaneLayout(): PaneLayoutContextValue {\n const pane = useContext(PaneLayoutContext)\n\n if (!pane) {\n throw new Error('PaneLayout: missing context value')\n }\n\n return pane\n}\n","import {Layer} from '@sanity/ui'\nimport {useCallback, useState} from 'react'\nimport {styled} from 'styled-components'\n\nimport {usePaneLayout} from './usePaneLayout'\n\nconst Root = styled(Layer)`\n position: relative;\n width: 1px;\n min-width: 1px;\n\n &:before {\n content: '';\n display: block;\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n width: 1px;\n background-color: var(--card-border-color);\n }\n\n &:not([data-disabled]) {\n cursor: ew-resize;\n width: 9px;\n min-width: 9px;\n margin: 0 -4px;\n\n &:before {\n left: 4px;\n }\n\n &:after {\n content: '';\n display: block;\n position: absolute;\n top: 0;\n left: 0;\n width: 9px;\n bottom: 0;\n background-color: var(--card-border-color);\n opacity: 0;\n transition: opacity 150ms;\n }\n\n &[data-dragging]:after,\n &:hover:after {\n opacity: 0.2;\n }\n }\n`\n\n/**\n *\n * @hidden\n * @beta This API will change. DO NOT USE IN PRODUCTION.\n */\nexport function PaneDivider({\n disabled,\n element,\n}: {\n disabled?: boolean\n element: HTMLElement | null\n}) {\n const {resize} = usePaneLayout()\n const [dragging, setDragging] = useState(false)\n\n const handleMouseDown = useCallback(\n (event: any) => {\n if (!element) return\n\n setDragging(true)\n\n event.preventDefault()\n\n const startX = event.pageX\n\n resize('start', element, 0)\n\n const handleMouseMove = (e: MouseEvent) => {\n e.preventDefault()\n\n const deltaX = e.pageX - startX\n\n resize('move', element, deltaX)\n }\n\n const handleMouseUp = (e: MouseEvent) => {\n e.preventDefault()\n\n setDragging(false)\n\n