Skip to content

Commit

Permalink
[field] PT: improve rendering of deleted nodes, use context for annot…
Browse files Browse the repository at this point in the history
…ation and inline objects.
  • Loading branch information
skogsmaskin authored and rexxars committed Oct 6, 2020
1 parent 0889ffa commit ca976e7
Show file tree
Hide file tree
Showing 8 changed files with 285 additions and 129 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,28 +23,23 @@
cursor: pointer;
}

.removed {
text-decoration: line-through;
}

.empty {
font-size: var(--font-size-small);
color: var(--text-muted);
font-size: var(--font-size-xsmall--uppercase);
line-height: var(--line-height-xsmall--uppercase);
text-transform: uppercase;
font-weight: 600;
}

.popoverContainer {
min-width: 160px;
padding: calc(var(--medium-padding) - var(--extra-small-padding));
@nest & .popoverContent {
}
@nest & .goToLink {
position: relative;
top: -5px;
white-space: nowrap;
float: right;
font-size: var(--font-size-small);
}
@nest & .goToLink svg {
font-size: var(--font-size-large + 4px);
position: relative;
top: 4px;
left: 4px;
}
}

.previewContainer {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import {toString} from '@sanity/util/paths'
import classNames from 'classnames'
import {Path} from '@sanity/types'
import {isKeySegment, Path} from '@sanity/types'
import ChevronDownIcon from 'part:@sanity/base/chevron-down-icon'
import LinkIcon from 'part:@sanity/base/link-icon'
import {ClickOutside} from 'part:@sanity/components/click-outside'
import {Popover} from 'part:@sanity/components/popover'
import React, {useCallback, useState} from 'react'
import {ConnectorContext} from '@sanity/base/lib/change-indicators'
import React, {useCallback, useEffect, useState} from 'react'
import {ConnectorContext, useReportedValues} from '@sanity/base/lib/change-indicators'
import {
ChangeList,
DiffContext,
DiffTooltip,
ObjectDiff,
ObjectSchemaType,
useDiffAnnotationColor,
DiffContext
useDiffAnnotationColor
} from '../../../../diff'
import {PortableTextChild} from '../types'
import {isEmptyObject} from '../helpers'
Expand All @@ -22,15 +23,15 @@ interface AnnotationProps {
object: PortableTextChild
children: JSX.Element
schemaType?: ObjectSchemaType
spanPath: Path
path: Path
}

export function Annotation({
children,
diff,
object,
schemaType,
spanPath,
path,
...restProps
}: AnnotationProps & Omit<React.HTMLProps<HTMLSpanElement>, 'onClick'>) {
if (!schemaType) {
Expand All @@ -47,7 +48,7 @@ export function Annotation({
diff={diff}
object={object}
schemaType={schemaType}
spanPath={spanPath}
path={path}
>
{children}
</AnnnotationWithDiff>
Expand All @@ -60,19 +61,19 @@ interface AnnnotationWithDiffProps {
diff: ObjectDiff
object: PortableTextChild
schemaType: ObjectSchemaType
spanPath: Path
path: Path
}

function AnnnotationWithDiff({
diff,
children,
object,
schemaType,
spanPath,
path,
...restProps
}: AnnnotationWithDiffProps & Omit<React.HTMLProps<HTMLSpanElement>, 'onClick'>) {
const {onSetFocus} = React.useContext(ConnectorContext)
const {path} = React.useContext(DiffContext)
const {path: fullPath} = React.useContext(DiffContext)
const color = useDiffAnnotationColor(diff, [])
const style = color ? {background: color.background, color: color.text} : {}
const className = classNames(
Expand All @@ -82,50 +83,69 @@ function AnnnotationWithDiff({
)
const [open, setOpen] = useState(false)
const emptyObject = object && isEmptyObject(object)
const focusPath = path.slice(0, -1).concat(spanPath)
const annotationPath = path.concat(['markDefs', {_key: object._key}, '$'])
const handleOpen = useCallback(
event => {
event.stopPropagation()
setOpen(true)
onSetFocus(focusPath)
},
[focusPath]
const markDefPath = [path[0]].concat(['markDefs', {_key: object._key}])
const prefix = fullPath.slice(
0,
fullPath.findIndex(seg => isKeySegment(seg) && seg._key === object._key)
)
const handleGoto = useCallback(
const annotationPath = prefix.concat(path)
const myPath = prefix.concat(markDefPath)
const myValue = `field-${toString(myPath)}`
const values = useReportedValues()
const isEditing = values.filter(([p]) => p.startsWith(myValue)).length > 0

useEffect(() => {
if (!open && isEditing) {
setOpen(true)
onSetFocus(myPath)
}
}, [isEditing, open])

const handleOpenPopup = useCallback(
event => {
event.stopPropagation()
setOpen(true)
onSetFocus(annotationPath)
onSetFocus(annotationPath) // Go to span first
setTimeout(() => onSetFocus(myPath), 10) // Open edit object interface
},
[annotationPath]
)
const annotation = (diff.action !== 'unchanged' && diff.annotation) || null
const annotations = annotation ? [annotation] : []

const popoverContent = (
<div className={styles.popoverContainer}>
<div className={styles.goToLink}>
<span onClick={handleGoto}>
<LinkIcon /> Open
</span>
<DiffContext.Provider value={{path: myPath}}>
<div className={styles.popoverContainer}>
<div className={styles.popoverContent}>
{emptyObject && <span className={styles.empty}>Empty {schemaType.title}</span>}
{!emptyObject && <ChangeList diff={diff} schemaType={schemaType} />}
</div>
</div>
<div className={styles.popoverContent}>
{emptyObject && <span className={styles.empty}>Empty {schemaType.title}</span>}
{!emptyObject && <ChangeList diff={diff} schemaType={schemaType} />}
</div>
</div>
</DiffContext.Provider>
)

const handleClickOutside = useCallback(() => {
setOpen(false)
}, [])
if (!isEditing) {
setOpen(false)
}
}, [isEditing])
return (
<ClickOutside onClickOutside={handleClickOutside}>
{ref => (
<span {...restProps} className={className} onClick={handleOpen} ref={ref} style={style}>
<span
{...restProps}
className={className}
onClick={handleOpenPopup}
ref={ref}
style={style}
>
<Popover content={popoverContent} open={open}>
<span className={styles.previewContainer}>
<span>{children}</span>
<ChevronDownIcon />
<DiffTooltip annotations={annotations} description={`${diff.action} annotation`}>
<span>
<span>{children}</span>
<ChevronDownIcon />
</span>
</DiffTooltip>
</span>
</Popover>
</span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,26 @@
text-decoration: line-through;
}

.empty {
color: var(--text-muted);
font-size: var(--font-size-xsmall--uppercase);
line-height: var(--line-height-xsmall--uppercase);
text-transform: uppercase;
font-weight: 600;
}

.popoverContent {
min-width: 160px;
max-height: calc(100vh - 49px - 65px - 16px);
padding: calc(var(--medium-padding) - var(--extra-small-padding));
@nest & .popoverContent {
}
}

.previewContainer {
display: inline-flex;
vertical-align: top;
max-width: 120px;
max-width: 160px;
margin: 0;
padding: 0 0 3px;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
import {useClickOutside} from '@sanity/components'
import {FOCUS_TERMINATOR, toString} from '@sanity/util/paths'
import classNames from 'classnames'
import {isKeySegment, Path} from '@sanity/types'
import ChevronDownIcon from 'part:@sanity/base/chevron-down-icon'
import SanityPreview from 'part:@sanity/base/preview'
import {ClickOutside} from 'part:@sanity/components/click-outside'
import {useClickOutside} from '@sanity/components'
import {Popover} from 'part:@sanity/components/popover'
import React, {useCallback, useState} from 'react'
import {ChangeList, ObjectDiff, ObjectSchemaType, useDiffAnnotationColor} from '../../../../diff'
import React, {useCallback, useState, useEffect} from 'react'
import {ConnectorContext, useReportedValues} from '@sanity/base/lib/change-indicators'
import {
ChangeList,
DiffContext,
DiffTooltip,
ObjectDiff,
ObjectSchemaType,
useDiffAnnotationColor
} from '../../../../diff'
import {PortableTextChild} from '../types'
import {isEmptyObject} from '../helpers'

Expand All @@ -14,6 +23,7 @@ import styles from './InlineObject.css'
interface InlineObjectProps {
diff?: ObjectDiff
object: PortableTextChild
path: Path
schemaType?: ObjectSchemaType
}

Expand Down Expand Up @@ -47,31 +57,53 @@ export function InlineObject({
interface InlineObjectWithDiffProps {
diff: ObjectDiff
object: PortableTextChild
path: Path
schemaType: ObjectSchemaType
}

function InlineObjectWithDiff({
diff,
object,
path,
schemaType,
...restProps
}: InlineObjectWithDiffProps & Omit<React.HTMLProps<HTMLSpanElement>, 'onClick'>) {
const [popoverElement, setPopoverElement] = useState<HTMLDivElement | null>(null)
const {path: fullPath} = React.useContext(DiffContext)
const {onSetFocus} = React.useContext(ConnectorContext)
const color = useDiffAnnotationColor(diff, [])
const style = color ? {background: color.background, color: color.text} : {}
const className = classNames(styles.root, diff.action === 'removed' && styles.removed)
const [open, setOpen] = useState(false)
const emptyObject = object && isEmptyObject(object)
const [popoverElement, setPopoverElement] = useState<HTMLDivElement | null>(null)
const prefix = fullPath.slice(
0,
fullPath.findIndex(seg => isKeySegment(seg) && seg._key === object._key)
)
const myPath = prefix.concat(path)
const myValue = `field-${toString(myPath)}`
const values = useReportedValues()
const isEditing = values.filter(([p]) => p.startsWith(myValue)).length > 0

const handleClick = useCallback(() => {
setOpen(true)
}, [])
const focusPath = fullPath
.slice(0, -1)
.concat(path)
.concat([FOCUS_TERMINATOR])

const popoverContent = (
<div className={styles.popoverContent}>
{emptyObject && <span>Empty {schemaType.title}</span>}
{!emptyObject && <ChangeList diff={diff} schemaType={schemaType} />}
</div>
useEffect(() => {
if (isEditing) {
setOpen(true)
onSetFocus(focusPath)
}
}, [isEditing])

const handleOpenPopup = useCallback(
event => {
event.stopPropagation()
setOpen(true)
onSetFocus(focusPath)
},
[focusPath]
)

const handleClickOutside = useCallback(() => {
Expand All @@ -80,12 +112,28 @@ function InlineObjectWithDiff({

useClickOutside(handleClickOutside, [popoverElement])

const popoverContent = (
<DiffContext.Provider value={{path: myPath}}>
<div className={styles.popoverContent}>
{emptyObject && <span className={styles.empty}>Empty {schemaType.title}</span>}
{!emptyObject && <ChangeList diff={diff} schemaType={schemaType} />}
</div>
</DiffContext.Provider>
)

const annotation = (diff.action !== 'unchanged' && diff.annotation) || null
const annotations = annotation ? [annotation] : []

return (
<span {...restProps} className={className} onClick={handleClick} style={style}>
<Popover content={popoverContent} open={open} placement="auto" portal ref={setPopoverElement}>
<span {...restProps} className={className} onClick={handleOpenPopup} style={style}>
<Popover content={popoverContent} open={open} ref={setPopoverElement}>
<span className={styles.previewContainer}>
<SanityPreview type={schemaType} value={object} layout="inline" />
<ChevronDownIcon />
<DiffTooltip annotations={annotations} description={`${diff.action} inline object`}>
<span>
<SanityPreview type={schemaType} value={object} layout="inline" />
<ChevronDownIcon />
</span>
</DiffTooltip>
</span>
</Popover>
</span>
Expand Down

0 comments on commit ca976e7

Please sign in to comment.