Skip to content

Commit

Permalink
[field] Use built-in preview abstraction for reference diff
Browse files Browse the repository at this point in the history
  • Loading branch information
rexxars committed Oct 6, 2020
1 parent fc457aa commit 104e336
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 56 deletions.
30 changes: 28 additions & 2 deletions packages/@sanity/field/src/@types/parts.d.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,36 @@
// declare module 'part:*'

declare module 'part:@sanity/base/authentication-fetcher'
declare module 'part:@sanity/base/client'
declare module 'part:@sanity/base/preview'
declare module 'part:@sanity/base/user'

declare module 'part:@sanity/base/preview' {
import {Observable} from 'rxjs'

const PreviewBase: React.ComponentType<{
type?: object // Schema type
fields?: string[]
value: any
children?: (props: any) => React.ComponentType
layout: 'inline' | 'block' | 'default' | 'card' | 'media'
}>

type previewObserver = (
value: Reference | string,
schemaType: object
) => Observable<{snapshot: {title: string}}>

export const observeForPreview: previewObserver
export default PreviewBase
}

declare module 'part:@sanity/base/schema' {
interface Schema {
get(typeName: string): unknown
}
const schema: Schema
export default schema
}

declare module 'all:part:@sanity/base/diff-resolver' {
import {ComponentType} from 'react'

Expand Down
8 changes: 4 additions & 4 deletions packages/@sanity/field/src/diff/hooks/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@ export function getRefValue<T = unknown>(refId: string | undefined | null): T |
}

export function useRefPreview(
value: Reference,
value: Reference | undefined | null,
schemaType: SchemaType
): PreviewSnapshot | undefined {
const [preview, setPreview] = useState(undefined)
const [preview, setPreview] = useState<PreviewSnapshot | undefined>(undefined)
useEffect(() => {
let subscription
if (value && schemaType) {
if (value) {
subscription = observeForPreview(value, schemaType).subscribe(result =>
setPreview(result.snapshot)
)
Expand All @@ -41,6 +41,6 @@ export function useRefPreview(
subscription.unsubscribe()
}
}
}, [value])
}, [value, schemaType])
return preview
}
6 changes: 5 additions & 1 deletion packages/@sanity/field/src/preview/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import {
BooleanSchemaType,
StringSchemaType,
NumberSchemaType,
ObjectSchemaType
ObjectSchemaType,
Reference,
ReferenceSchemaType
} from '../diff'

export type PreviewComponent<T> = ComponentType<{
Expand All @@ -18,6 +20,8 @@ export type PreviewComponent<T> = ComponentType<{
? StringSchemaType
: T extends number
? NumberSchemaType
: T extends Reference
? ReferenceSchemaType
: T extends object
? ObjectSchemaType
: any
Expand Down
22 changes: 17 additions & 5 deletions packages/@sanity/field/src/schema/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,20 @@
import {ArraySchemaType, Diff, KeyedObject, SchemaType, TypedObject} from '../diff'
import schema from 'part:@sanity/base/schema'
import {ArraySchemaType, Diff, SchemaType, TypedObject, ReferenceSchemaType} from '../diff'

export function getReferencedType(referenceType: ReferenceSchemaType): SchemaType | undefined {
if (!referenceType.to) {
return referenceType.type
? getReferencedType(referenceType.type as ReferenceSchemaType)
: undefined
}

if (Array.isArray(referenceType.to) && referenceType.to.length !== 1) {
return undefined
}

const targetType = schema.get(referenceType.to[0].name) as SchemaType
return targetType
}

export function resolveTypeName(value: unknown) {
return isTypedObject(value) ? value._type : resolveJSType(value)
Expand Down Expand Up @@ -47,10 +63,6 @@ function isTypedObject(val: unknown): val is TypedObject {
return typeof val === 'object' && val !== null && typeof (val as TypedObject)._type === 'string'
}

function isKeyedObject(val: unknown): val is KeyedObject {
return typeof val === 'object' && val !== null && typeof (val as KeyedObject)._key === 'string'
}

function resolveJSType(val: unknown) {
if (Array.isArray(val)) {
return 'array'
Expand Down
4 changes: 3 additions & 1 deletion packages/@sanity/field/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,9 @@ export interface Reference {
_weak?: boolean
}

export type ReferenceSchemaType = ObjectSchemaType<Reference>
export type ReferenceSchemaType = ObjectSchemaType<Reference> & {
to: SchemaType[]
}

export type SchemaType<A = unknown, O extends object = Record<string, any>> =
| ArraySchemaType<A>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,49 +1,16 @@
import React from 'react'
import LinkIcon from 'part:@sanity/base/link-icon'
import {
DiffComponent,
ReferenceDiff,
DiffAnnotationTooltip,
DiffAnnotationCard
} from '../../../diff'
import styles from './ReferenceFieldDiff.css'
import {useRefPreview} from '../../../diff/hooks'
import {ChangeLayout, MetaInfo} from '../../../diff/components'

// TODO: fix hooks error
import {DiffComponent, ReferenceDiff} from '../../../diff'
import {Change} from '../../../diff/components'
import {ReferencePreview} from '../preview/ReferencePreview'

export const ReferenceFieldDiff: DiffComponent<ReferenceDiff> = ({diff, schemaType}) => {
const {fromValue, toValue} = diff
const prev = fromValue && useRefPreview(fromValue, schemaType)
const next = toValue && useRefPreview(toValue, schemaType)

return (
<DiffAnnotationTooltip as="div" diff={diff} path="_ref">
<ChangeLayout
layout={prev && next ? 'grid' : 'inline'}
from={
prev && (
<DiffAnnotationCard className={styles.annotation} diff={diff} path="_ref">
<MetaInfo
title={prev.title || 'Untitled'}
action={prev && next ? 'changed' : 'removed'}
icon={LinkIcon}
/>
</DiffAnnotationCard>
)
}
to={
next && (
<DiffAnnotationCard className={styles.annotation} diff={diff} path="_ref">
<MetaInfo
title={next.title || 'Untitled'}
action={prev && next ? 'changed' : 'added'}
icon={LinkIcon}
/>
</DiffAnnotationCard>
)
}
/>
</DiffAnnotationTooltip>
<Change
previewComponent={ReferencePreview}
layout="grid"
path="_ref"
diff={diff}
schemaType={schemaType}
/>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import React from 'react'
import Preview from 'part:@sanity/base/preview'
import {getReferencedType} from '../../../schema/helpers'
import {PreviewComponent} from '../../../preview/types'
import {Reference} from '../../../diff'

export const ReferencePreview: PreviewComponent<Reference> = ({value, schemaType}) => (
<Preview type={getReferencedType(schemaType)} value={value} layout="default" />
)

0 comments on commit 104e336

Please sign in to comment.