Skip to content

Commit

Permalink
[form-builder] Use @sanity/types for schema type definitions
Browse files Browse the repository at this point in the history
  • Loading branch information
rexxars committed Oct 6, 2020
1 parent a863a07 commit 85086a7
Show file tree
Hide file tree
Showing 33 changed files with 241 additions and 235 deletions.
11 changes: 6 additions & 5 deletions packages/@sanity/form-builder/src/FormBuilderContext.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import PropTypes from 'prop-types'
import React from 'react'
import pubsub from 'nano-pubsub'
import {Schema, SchemaType} from '@sanity/types'
import {fallbackInputs} from './fallbackInputs'
import {Type} from './typedefs'

const RESOLVE_NULL = (arg: any) => null

Expand Down Expand Up @@ -49,16 +49,17 @@ function memoize(method) {
}

interface Props {
schema: object
value: any
schema: Schema
value: unknown
children: any
filterField?: any
patchChannel: {
onPatch?: (patch: any) => void
}
resolveInputComponent: (type: Type) => React.ComponentType
resolvePreviewComponent: (type: Type) => React.ComponentType
resolveInputComponent: (type: SchemaType) => React.ComponentType
resolvePreviewComponent: (type: SchemaType) => React.ComponentType
}

export default class FormBuilderContext extends React.Component<Props> {
static createPatchChannel = () => {
const channel = pubsub()
Expand Down
26 changes: 12 additions & 14 deletions packages/@sanity/form-builder/src/FormBuilderInput.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,23 @@
/* eslint-disable complexity */
import React from 'react'
import shallowEquals from 'shallow-equals'
import {Marker, Path, PathSegment} from '@sanity/types'
import {Marker, Path, SchemaType} from '@sanity/types'
import {ChangeIndicatorProvider} from '@sanity/base/lib/change-indicators'
import * as PathUtils from '@sanity/util/paths'
import generateHelpUrl from '@sanity/generate-help-url'
import {FormFieldPresence, FormFieldPresenceContext} from '@sanity/base/presence'
import PatchEvent from './PatchEvent'
import {Type} from './typedefs'
import {emptyArray, emptyObject} from './utils/empty'
import {ChangeIndicatorProvider} from '@sanity/base/lib/change-indicators'

const EMPTY_PROPS = emptyObject<{}>()
const EMPTY_MARKERS: Marker[] = emptyArray()
const EMPTY_PATH: Path = emptyArray()
const EMPTY_PRESENCE: FormFieldPresence[] = emptyArray()

interface Props {
value: any
type: Type
onChange: (arg0: PatchEvent) => void
onFocus: (arg0: Path) => void
value: unknown
type: SchemaType
onChange: (event: PatchEvent) => void
onFocus: (path: Path) => void
onBlur: () => void
readOnly: boolean
presence?: FormFieldPresence[]
Expand All @@ -28,7 +26,7 @@ interface Props {
compareValue?: any
level: number
isRoot?: boolean
path: Array<PathSegment>
path: Path
filterField?: Function
onKeyUp?: (ev: React.KeyboardEvent) => void
onKeyPress?: (ev: React.KeyboardEvent) => void
Expand Down Expand Up @@ -105,7 +103,7 @@ export class FormBuilderInput extends React.Component<Props> {
}
}

resolveInputComponent(type: Type) {
resolveInputComponent(type: SchemaType) {
return this.context.formBuilder.resolveInputComponent(type)
}

Expand Down Expand Up @@ -230,10 +228,10 @@ export class FormBuilderInput extends React.Component<Props> {
readOnly || !presence || presence.length === 0
? EMPTY_PRESENCE
: presence
.filter(presence => PathUtils.startsWith(path, presence.path))
.map(presence => ({
...presence,
path: PathUtils.trimChildPath(path, presence.path)
.filter(item => PathUtils.startsWith(path, item.path))
.map(item => ({
...item,
path: PathUtils.trimChildPath(path, item.path)
}))

const childCompareValue = PathUtils.get(compareValue, path)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@
import React from 'react'
import {ArraySchemaType, SchemaType, isReferenceSchemaType} from '@sanity/types'
import DropDownButton from 'part:@sanity/components/buttons/dropdown'
import Button from 'part:@sanity/components/buttons/default'
import ButtonGrid from 'part:@sanity/components/buttons/button-grid'
import {Type} from '../../typedefs'
import styles from './styles/ArrayInput.css'
import {ArrayType, ItemValue} from './typedefs'
import PatchEvent from '../../PatchEvent'
import PlusIcon from 'part:@sanity/base/plus-icon'
import PatchEvent from '../../PatchEvent'
import styles from './styles/ArrayInput.css'
import {ItemValue} from './typedefs'

type Props = {
type: ArrayType
type: ArraySchemaType
children: Node | null
value: Array<ItemValue>
value: ItemValue[]
readOnly: boolean | null
onAppendItem: (itemValue: ItemValue) => void
onPrependItem: (itemValue: ItemValue) => void
onFocusItem: (item: ItemValue) => void
onCreateValue: (type: Type) => ItemValue
onCreateValue: (type: SchemaType) => ItemValue
onChange: (event: PatchEvent) => void
}
export default class ArrayFunctions extends React.Component<Props, {}> {
handleDropDownAction = (menuItem: {type: Type}) => {

export default class ArrayFunctions extends React.Component<Props> {
handleDropDownAction = (menuItem: {type: SchemaType}) => {
this.handleInsertItem(menuItem.type)
}
handleAddBtnClick = () => {
Expand All @@ -33,7 +35,11 @@ export default class ArrayFunctions extends React.Component<Props, {}> {
renderSelectType() {
const items = this.props.type.of.map(memberDef => {
// Use reference icon if reference is to one type only
const referenceIcon = (memberDef.to || []).length === 1 && memberDef.to[0].icon
const referenceIcon =
isReferenceSchemaType(memberDef) &&
(memberDef.to || []).length === 1 &&
memberDef.to[0].icon

const icon = memberDef.icon || memberDef.type.icon || referenceIcon || PlusIcon
return {
title: memberDef.title || memberDef.type.name,
Expand Down
29 changes: 12 additions & 17 deletions packages/@sanity/form-builder/src/inputs/ArrayInput/ArrayInput.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
import React from 'react'
import {map} from 'rxjs/operators'
import {isPlainObject, get} from 'lodash'
import {Marker, Path} from '@sanity/types'
import {ArraySchemaType, isObjectSchemaType, Marker, Path, SchemaType} from '@sanity/types'
import {FOCUS_TERMINATOR, startsWith} from '@sanity/util/paths'
import formBuilderConfig from 'config:@sanity/form-builder'
import ArrayFunctions from 'part:@sanity/form-builder/input/array/functions'
import DefaultButton from 'part:@sanity/components/buttons/default'
import Fieldset from 'part:@sanity/components/fieldsets/default'
import {ResolvedUploader, Uploader} from '../../sanity/uploads/typedefs'
import {Type} from '../../typedefs'
import {Subscription} from '../../typedefs/observable'
import {resolveTypeName} from '../../utils/resolveTypeName'
import UploadTargetFieldset from '../../utils/UploadTargetFieldset'
import {insert, PatchEvent, set, setIfMissing, unset} from '../../PatchEvent'
import Details from '../common/Details'
import Warning from '../Warning'
import resolveListComponents from './resolveListComponents'
import {ArrayType, ItemValue} from './typedefs'
import {ItemValue} from './typedefs'
import RenderItemValue from './ItemValue'
import randomKey from './randomKey'

Expand All @@ -25,34 +24,30 @@ import styles from './styles/ArrayInput.css'
const NO_MARKERS: Marker[] = []
const SUPPORT_DIRECT_UPLOADS = get(formBuilderConfig, 'images.directUploads')

function createProtoValue(type: Type): ItemValue {
if (type.jsonType !== 'object') {
function createProtoValue(type: SchemaType): ItemValue {
if (!isObjectSchemaType(type)) {
throw new Error(
`Invalid item type: "${type.type}". Default array input can only contain objects (for now)`
)
}

const key = randomKey(12)
return type.name === 'object'
? {_key: key}
: {
_type: type.name,
_key: key
}
return type.name === 'object' ? {_key: key} : {_type: type.name, _key: key}
}

export type Props = {
type: ArrayType
value: Array<ItemValue>
compareValue: Array<ItemValue>
markers: Array<Marker>
type: ArraySchemaType
value: ItemValue[]
compareValue: ItemValue[]
markers: Marker[]
level: number
onChange: (event: PatchEvent) => void
onFocus: (path: Path) => void
onBlur: () => void
focusPath: Path
readOnly: boolean
filterField: () => any
resolveUploader?: (type: Type, file: File) => Uploader
resolveUploader?: (type: SchemaType, file: File) => Uploader
presence: any
}
type ArrayInputState = {
Expand Down Expand Up @@ -145,7 +140,7 @@ export default class ArrayInput extends React.Component<Props, ArrayInputState>
)
}

getMemberTypeOfItem(item: ItemValue): Type {
getMemberTypeOfItem(item: ItemValue): SchemaType {
const {type} = this.props
const itemTypeName = resolveTypeName(item)
return type.of.find(memberType => memberType.name === itemTypeName)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import React from 'react'
import {ArraySchemaType} from '@sanity/types'
import PatchEvent from '../../PatchEvent'
import {resolveTypeName} from '../../utils/resolveTypeName'
import InvalidValueInput from '../InvalidValueInput'
import {ArrayType, ItemValue} from './typedefs'
import {ItemValue} from './typedefs'

interface Props {
type: ArrayType
type: ArraySchemaType
value: unknown
onChange: (event: PatchEvent, valueOverride?: ItemValue) => void
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
/* eslint-disable complexity */
import React from 'react'
import {isValidationMarker, Marker, Path} from '@sanity/types'
import {ArraySchemaType, isValidationMarker, Marker, Path, SchemaType} from '@sanity/types'
import {ChangeIndicatorScope} from '@sanity/base/lib/change-indicators'
import {ContextProvidedChangeIndicator} from '@sanity/base/lib/change-indicators/ChangeIndicator'
import LinkIcon from 'part:@sanity/base/link-icon'
import {FormFieldPresence, FieldPresence, PresenceOverlay} from '@sanity/base/presence'
import Button from 'part:@sanity/components/buttons/default'
Expand All @@ -19,12 +20,10 @@ import {FormBuilderInput} from '../../FormBuilderInput'
import PatchEvent from '../../PatchEvent'
import Preview from '../../Preview'
import {resolveTypeName} from '../../utils/resolveTypeName'
import {Type} from '../../typedefs'
import ConfirmButton from './ConfirmButton'
import styles from './styles/ItemValue.css'
import {ArrayType, ItemValue} from './typedefs'
import {ItemValue} from './typedefs'
import InvalidItem from './InvalidItem'
import {ContextProvidedChangeIndicator} from '@sanity/base/lib/change-indicators/ChangeIndicator'

const DragHandle = createDragHandle(() => (
<span className={styles.dragHandle}>
Expand All @@ -49,7 +48,7 @@ const DragHandle = createDragHandle(() => (
// secondary: true
// }
type Props = {
type: ArrayType
type: ArraySchemaType
value: ItemValue
compareValue?: any[]
level: number
Expand Down Expand Up @@ -121,7 +120,7 @@ export default class RenderItemValue extends React.PureComponent<Props> {
const {onChange, value} = this.props
onChange(event, typeof valueOverride === 'undefined' ? value : valueOverride)
}
getMemberType(): Type | null {
getMemberType(): SchemaType | null {
const {value, type} = this.props
const itemTypeName = resolveTypeName(value)
return itemTypeName === 'object' && type.of.length === 1
Expand Down Expand Up @@ -250,7 +249,7 @@ export default class RenderItemValue extends React.PureComponent<Props> {
)
}
renderItem() {
const {value, markers, type, readOnly, presence, focusPath, onChange} = this.props
const {value, markers, type, readOnly, presence, focusPath} = this.props
const options = type.options || {}
const isGrid = options.layout === 'grid'
const isSortable = !readOnly && !type.readOnly && options.sortable !== false
Expand Down
15 changes: 0 additions & 15 deletions packages/@sanity/form-builder/src/inputs/ArrayInput/typedefs.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,5 @@
import {Type} from '../../typedefs'

export type ModalType = 'modal' | 'fullscreen' | string

export type ArrayType = Type & {
name: string
title: string
description: string
readOnly: boolean | null
options: {
editModal?: ModalType
sortable?: boolean
layout?: 'grid'
}
of: Array<Type>
}

export type ItemValue = {
_type?: string
_key: string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@ import {Item as DefaultItem, List as DefaultList} from 'part:@sanity/components/
import {Item as SortableItem, List as SortableList} from 'part:@sanity/components/lists/sortable'
import ArrayFunctions from 'part:@sanity/form-builder/input/array/functions'
import Fieldset from 'part:@sanity/components/fieldsets/default'
import {Marker, Path} from '@sanity/types'
import {ArraySchemaType, Marker, Path} from '@sanity/types'
import {startsWith} from '@sanity/util/paths'
import DefaultButton from 'part:@sanity/components/buttons/default'
import {PatchEvent, set, unset} from '../../PatchEvent'
import {resolveTypeName} from '../../utils/resolveTypeName'
import {Type} from '../../typedefs'
import Warning from '../Warning'
import styles from './styles/ArrayOfPrimitivesInput.css'
import getEmptyValue from './getEmptyValue'
Expand All @@ -32,7 +31,7 @@ function insertAt(arr, index, item) {
}
type Primitive = string | number | boolean
type Props = {
type: Type
type: ArraySchemaType<Primitive>
value: Primitive[]
compareValue?: Primitive[]
level: number
Expand All @@ -41,9 +40,10 @@ type Props = {
onBlur: () => void
focusPath: Path
readOnly: boolean | null
markers: Array<Marker>
markers: Marker[]
presence: any
}

export default class ArrayOfPrimitivesInput extends React.PureComponent<Props> {
_element: Fieldset | null
_lastAddedIndex = -1
Expand Down Expand Up @@ -107,15 +107,13 @@ export default class ArrayOfPrimitivesInput extends React.PureComponent<Props> {
)
}

renderItem = (item, index) => {
renderItem = (item: Primitive, index: number) => {
const {
type,
level,
markers,
value,
compareValue,
focusPath,
onChange,
onFocus,
readOnly,
onBlur,
Expand All @@ -126,6 +124,7 @@ export default class ArrayOfPrimitivesInput extends React.PureComponent<Props> {
if (!itemMemberType) {
return null
}

const isSortable = get(type, 'options.sortable') !== false
const ListItem = isSortable ? SortableItem : DefaultItem
const filteredMarkers = markers.filter(marker => startsWith([index], marker.path))
Expand All @@ -136,7 +135,7 @@ export default class ArrayOfPrimitivesInput extends React.PureComponent<Props> {
level={level + 1}
index={index}
value={item}
compareValue={compareValue}
compareValue={(compareValue || [])[index]}
readOnly={readOnly}
markers={filteredMarkers.length === 0 ? NO_MARKERS : filteredMarkers}
isSortable={isSortable}
Expand Down

0 comments on commit 85086a7

Please sign in to comment.