diff --git a/packages/sanity/src/core/form/inputs/PortableText/BlockActions.tsx b/packages/sanity/src/core/form/inputs/PortableText/BlockActions.tsx
index 6e0ba6fe07f..cd1ef7f0ae7 100644
--- a/packages/sanity/src/core/form/inputs/PortableText/BlockActions.tsx
+++ b/packages/sanity/src/core/form/inputs/PortableText/BlockActions.tsx
@@ -1,10 +1,7 @@
-import {
- PortableTextEditor,
- PortableTextBlock,
- usePortableTextEditor,
-} from '@sanity/portable-text-editor'
+import {PortableTextEditor, usePortableTextEditor} from '@sanity/portable-text-editor'
import React, {useCallback, useMemo} from 'react'
import styled from 'styled-components'
+import {PortableTextBlock} from '@sanity/types'
import {PatchArg} from '../../patch'
import {RenderBlockActionsCallback, RenderBlockActionsProps} from './types'
import {createInsertCallback, createSetCallback, createUnsetCallback} from './callbacks'
@@ -20,21 +17,10 @@ const Root = styled.div`
pointer-events: 'all';
`
-// function isClassComponent(component: React.ComponentType) {
-// return typeof component === 'function' && !!component.prototype?.isReactComponent
-// }
-
-// function isFunctionComponent(component: React.ComponentType) {
-// return typeof component === 'function' && String(component).includes('return React.createElement')
-// }
-
export function BlockActions(props: BlockActionsProps) {
const editor = usePortableTextEditor()
const {block, onChange, renderBlockActions} = props
- const decoratorValues = useMemo(
- () => PortableTextEditor.getPortableTextFeatures(editor).decorators.map((d) => d.value),
- [editor]
- )
+ const decoratorValues = useMemo(() => editor.types.decorators.map((d) => d.value), [editor])
const blockActions = useMemo(() => {
if (renderBlockActions) {
@@ -45,12 +31,6 @@ export function BlockActions(props: BlockActionsProps) {
unset: createUnsetCallback({block, onChange}),
insert: createInsertCallback({allowedDecorators: decoratorValues, block, onChange}),
}
-
- // // Support returning a class component for renderBlockActions (to keep backward compatability as it was possible before)
- // if (isClassComponent(renderBlockActions) || isFunctionComponent(renderBlockActions)) {
- // const RenderComponent = renderBlockActions
- // return
- // }
return renderBlockActions(blockActionProps)
}
return undefined
diff --git a/packages/sanity/src/core/form/inputs/PortableText/Compositor.tsx b/packages/sanity/src/core/form/inputs/PortableText/Compositor.tsx
index 05bd2ccff9c..d76aac903ba 100644
--- a/packages/sanity/src/core/form/inputs/PortableText/Compositor.tsx
+++ b/packages/sanity/src/core/form/inputs/PortableText/Compositor.tsx
@@ -3,13 +3,13 @@ import {
EditorSelection,
OnCopyFn,
OnPasteFn,
- PortableTextBlock,
- PortableTextEditor,
usePortableTextEditor,
HotkeyOptions,
- RenderAttributes,
+ BlockRenderProps,
+ BlockChildRenderProps,
+ BlockAnnotationRenderProps,
} from '@sanity/portable-text-editor'
-import {ObjectSchemaType, Path} from '@sanity/types'
+import {BlockSchemaType, Path, PortableTextBlock, PortableTextTextBlock} from '@sanity/types'
import {
BoundaryElementProvider,
Portal,
@@ -53,7 +53,7 @@ interface InputProps extends ArrayOfObjectsInputProps {
export type PortableTextEditorElement = HTMLDivElement | HTMLSpanElement | null
/** @internal */
-export function Compositor(props: InputProps) {
+export function Compositor(props: Omit) {
const {
changed,
focusPath = EMPTY_ARRAY,
@@ -65,8 +65,9 @@ export function Compositor(props: InputProps) {
onChange,
onCopy,
onActivate,
- onItemOpen,
onItemClose,
+ onItemOpen,
+ onItemRemove,
onPaste,
onToggleFullscreen,
path,
@@ -111,8 +112,8 @@ export function Compositor(props: InputProps) {
const editorHotkeys = useHotkeys(hotkeysWithFullscreenToggle)
- const ptFeatures = useMemo(() => PortableTextEditor.getPortableTextFeatures(editor), [editor])
- const hasContent = !!value
+ const _renderBlockActions = !!value && renderBlockActions ? renderBlockActions : undefined
+ const _renderCustomMarkers = !!value && renderCustomMarkers ? renderCustomMarkers : undefined
const initialSelection = useMemo(
(): EditorSelection =>
@@ -127,104 +128,113 @@ export function Compositor(props: InputProps) {
)
const renderBlock = useCallback(
- (
- block: PortableTextBlock,
- blockType: ObjectSchemaType,
- attributes: RenderAttributes,
- defaultRender: (b: PortableTextBlock) => JSX.Element
- ) => {
- const isTextBlock = block._type === ptFeatures.types.block.name
+ (blockProps: BlockRenderProps) => {
+ const {
+ value: block,
+ type: blockType,
+ renderDefault,
+ focused: blockFocused,
+ selected,
+ path: blockPath,
+ } = blockProps
+ const isTextBlock = block._type === editor.types.block.name
if (isTextBlock) {
return (
- {defaultRender(block)}
+ {renderDefault(blockProps)}
)
}
-
return (
)
},
[
- hasContent,
+ _renderBlockActions,
+ _renderCustomMarkers,
+ editor.types.block.name,
isFullscreen,
onChange,
onItemOpen,
- ptFeatures.types.block.name,
+ onItemClose,
+ onItemRemove,
readOnly,
- renderBlockActions,
- renderCustomMarkers,
renderPreview,
]
)
const renderChild = useCallback(
- (child: any, childType: any, attributes: any, defaultRender: any) => {
- const isSpan = child._type === ptFeatures.types.span.name
+ (childProps: BlockChildRenderProps) => {
+ const {
+ focused: childFocused,
+ path: childPath,
+ renderDefault,
+ selected,
+ type: childType,
+ value: child,
+ } = childProps
+ const isSpan = child._type === editor.types.span.name
if (isSpan) {
- return defaultRender(child)
+ return renderDefault(childProps)
}
-
return (
)
},
- [
- onItemOpen,
- ptFeatures.types.span.name,
- readOnly,
- renderCustomMarkers,
- renderPreview,
- scrollElement,
- ]
+ [editor, onItemOpen, readOnly, renderCustomMarkers, renderPreview, scrollElement]
)
const renderAnnotation = useCallback(
- (annotation: any, annotationType: any, attributes: any, defaultRender: any) => {
+ (annotationProps: BlockAnnotationRenderProps) => {
return (
- {defaultRender()}
-
+ />
)
},
- [onItemOpen, readOnly, renderCustomMarkers, scrollElement]
+ [onItemOpen, onItemClose, readOnly, renderCustomMarkers, scrollElement]
)
const [portalElement, setPortalElement] = useState(null)
diff --git a/packages/sanity/src/core/form/inputs/PortableText/Editor.tsx b/packages/sanity/src/core/form/inputs/PortableText/Editor.tsx
index a41c6d4cdfd..b7a1f8cddfb 100644
--- a/packages/sanity/src/core/form/inputs/PortableText/Editor.tsx
+++ b/packages/sanity/src/core/form/inputs/PortableText/Editor.tsx
@@ -10,6 +10,8 @@ import {
EditorSelection,
PortableTextEditor,
usePortableTextEditor,
+ RenderStyleFunction,
+ RenderListItemFunction,
} from '@sanity/portable-text-editor'
import {Path} from '@sanity/types'
import {BoundaryElementProvider, useBoundaryElement, useGlobalKeyDown, useLayer} from '@sanity/ui'
@@ -26,6 +28,8 @@ import {
} from './Editor.styles'
import {useSpellcheck} from './hooks/useSpellCheck'
import {useScrollSelectionIntoView} from './hooks/useScrollSelectionIntoView'
+import {Style} from './text/Style'
+import {ListItem} from './text/ListItem'
interface EditorProps {
hotkeys: HotkeyOptions
@@ -46,8 +50,34 @@ interface EditorProps {
setScrollElement: (scrollElement: HTMLElement | null) => void
}
-const renderDecorator: RenderDecoratorFunction = (mark, mType, attributes, defaultRender) => {
- return {defaultRender()}
+const renderDecorator: RenderDecoratorFunction = (props) => {
+ const {value, renderDefault, type, focused, selected} = props
+ const CustomComponent = type.components?.item
+ const rendered = renderDefault(props)
+ if (CustomComponent) {
+ // eslint-disable-next-line react/jsx-no-bind
+ return (
+ {rendered}}
+ >
+ {rendered}
+
+ )
+ }
+ return {rendered}
+}
+
+const renderStyle: RenderStyleFunction = (props) => {
+ return
+}
+
+const renderListItem: RenderListItemFunction = (props) => {
+ return
}
export function Editor(props: EditorProps) {
@@ -114,7 +144,9 @@ export function Editor(props: EditorProps) {
renderBlock={renderBlock}
renderChild={renderChild}
renderDecorator={renderDecorator}
+ renderListItem={renderListItem}
renderPlaceholder={renderPlaceholder}
+ renderStyle={renderStyle}
scrollSelectionIntoView={scrollSelectionIntoView}
selection={initialSelection}
spellCheck={spellcheck}
diff --git a/packages/sanity/src/core/form/inputs/PortableText/PortableTextInput.tsx b/packages/sanity/src/core/form/inputs/PortableText/PortableTextInput.tsx
index 2703052601d..a383a9157dd 100644
--- a/packages/sanity/src/core/form/inputs/PortableText/PortableTextInput.tsx
+++ b/packages/sanity/src/core/form/inputs/PortableText/PortableTextInput.tsx
@@ -1,10 +1,9 @@
-import {ArraySchemaType} from '@sanity/types'
+import {ArraySchemaType, PortableTextBlock} from '@sanity/types'
import {
EditorChange,
OnCopyFn,
OnPasteFn,
Patch as EditorPatch,
- PortableTextBlock,
PortableTextEditor,
HotkeyOptions,
InvalidValue,
@@ -29,7 +28,6 @@ import {ArrayOfObjectsItemMember, ObjectFormNode} from '../../store'
import type {ArrayOfObjectsInputProps, PortableTextMarker, RenderCustomMarkers} from '../../types'
import {EMPTY_ARRAY} from '../../../util'
import {pathToString} from '../../../field'
-import {FIXME} from '../../../FIXME'
import {isMemberArrayOfObjects} from '../../members/object/fields/asserters'
import {Compositor, PortableTextEditorElement} from './Compositor'
import {InvalidValue as RespondToInvalidContent} from './InvalidValue'
@@ -39,23 +37,20 @@ import {PortableTextMarkersProvider} from './contexts/PortableTextMarkers'
import {PortableTextMemberItemsProvider} from './contexts/PortableTextMembers'
import {_isArrayOfObjectsFieldMember, _isBlockType} from './_helpers'
-/** @internal */
-export type PTObjectMember = ArrayOfObjectsItemMember
-
/** @internal */
export interface PortableTextMemberItem {
kind: 'annotation' | 'textBlock' | 'objectBlock' | 'inlineObject'
key: string
- member: PTObjectMember
+ member: ArrayOfObjectsItemMember
node: ObjectFormNode
elementRef?: React.MutableRefObject | undefined
}
/**
- * @alpha
+ * @beta
*/
export interface PortableTextInputProps
- extends ArrayOfObjectsInputProps {
+ extends ArrayOfObjectsInputProps> {
hotkeys?: HotkeyOptions
markers?: PortableTextMarker[]
onCopy?: OnCopyFn
@@ -67,7 +62,7 @@ export interface PortableTextInputProps
/**
* The root Portable Text Input component
*
- * @alpha
+ * @beta
*/
export function PortableTextInput(props: PortableTextInputProps) {
const {
@@ -159,7 +154,7 @@ export function PortableTextInput(props: PortableTextInputProps) {
const portableTextMemberItems: PortableTextMemberItem[] = useMemo(() => {
const result: {
kind: PortableTextMemberItem['kind']
- member: PTObjectMember
+ member: ArrayOfObjectsItemMember
node: ObjectFormNode
}[] = []
@@ -343,7 +338,7 @@ export function PortableTextInput(props: PortableTextInputProps) {
onChange={handleEditorChange}
maxBlocks={undefined} // TODO: from schema?
readOnly={readOnly}
- type={type as FIXME}
+ type={type}
value={value}
>
{
- const dupBlock: TextBlock = {
+ const dupBlock: PortableTextTextBlock = {
...block,
_type: 'block',
_key: keyGenerator(),
- children: block.children || [],
- markDefs: block.markDefs || [],
+ children: (Array.isArray(block.children) && block.children) || [],
+ markDefs: (Array.isArray(block.markDefs) && block.markDefs) || [],
}
if (dupBlock.children) {
diff --git a/packages/sanity/src/core/form/inputs/PortableText/__workshop__/customSchema/values.ts b/packages/sanity/src/core/form/inputs/PortableText/__workshop__/customSchema/values.ts
index 0050137c4db..d03ce210b15 100644
--- a/packages/sanity/src/core/form/inputs/PortableText/__workshop__/customSchema/values.ts
+++ b/packages/sanity/src/core/form/inputs/PortableText/__workshop__/customSchema/values.ts
@@ -1,4 +1,5 @@
-import {keyGenerator as createKey, PortableTextBlock} from '@sanity/portable-text-editor'
+import {keyGenerator as createKey} from '@sanity/portable-text-editor'
+import {PortableTextBlock} from '@sanity/types'
import {words} from './words'
export const valueOptions: Record = {
diff --git a/packages/sanity/src/core/form/inputs/PortableText/__workshop__/defaultSchema/values.ts b/packages/sanity/src/core/form/inputs/PortableText/__workshop__/defaultSchema/values.ts
index 47b1ad4ef65..d16c0a74f8b 100644
--- a/packages/sanity/src/core/form/inputs/PortableText/__workshop__/defaultSchema/values.ts
+++ b/packages/sanity/src/core/form/inputs/PortableText/__workshop__/defaultSchema/values.ts
@@ -1,4 +1,4 @@
-import {PortableTextBlock} from '@sanity/portable-text-editor'
+import {PortableTextBlock} from '@sanity/types'
export const valueOptions = {
Empty: 'empty',
diff --git a/packages/sanity/src/core/form/inputs/PortableText/callbacks/insertCallback.ts b/packages/sanity/src/core/form/inputs/PortableText/callbacks/insertCallback.ts
index c6d0f01c0ad..5b03139c840 100644
--- a/packages/sanity/src/core/form/inputs/PortableText/callbacks/insertCallback.ts
+++ b/packages/sanity/src/core/form/inputs/PortableText/callbacks/insertCallback.ts
@@ -1,5 +1,5 @@
import {normalizeBlock} from '@sanity/block-tools'
-import {PortableTextBlock} from '@sanity/portable-text-editor'
+import {PortableTextBlock} from '@sanity/types'
import {FormPatch, insert} from '../../../patch'
import {InsertCallback} from './types'
diff --git a/packages/sanity/src/core/form/inputs/PortableText/callbacks/setCallback.ts b/packages/sanity/src/core/form/inputs/PortableText/callbacks/setCallback.ts
index a397e15fdf7..eacdb68350c 100644
--- a/packages/sanity/src/core/form/inputs/PortableText/callbacks/setCallback.ts
+++ b/packages/sanity/src/core/form/inputs/PortableText/callbacks/setCallback.ts
@@ -1,5 +1,5 @@
import {normalizeBlock} from '@sanity/block-tools'
-import {PortableTextBlock} from '@sanity/portable-text-editor'
+import {PortableTextBlock} from '@sanity/types'
import {FormPatch, set} from '../../../patch'
import {SetCallback} from './types'
diff --git a/packages/sanity/src/core/form/inputs/PortableText/callbacks/types.ts b/packages/sanity/src/core/form/inputs/PortableText/callbacks/types.ts
index 874ea595b88..154a9054837 100644
--- a/packages/sanity/src/core/form/inputs/PortableText/callbacks/types.ts
+++ b/packages/sanity/src/core/form/inputs/PortableText/callbacks/types.ts
@@ -1,4 +1,4 @@
-import {PortableTextBlock} from '@sanity/portable-text-editor'
+import {PortableTextBlock} from '@sanity/types'
export type UnsetCallback = () => void
export type SetCallback = (block: PortableTextBlock) => void
diff --git a/packages/sanity/src/core/form/inputs/PortableText/callbacks/unsetCallback.ts b/packages/sanity/src/core/form/inputs/PortableText/callbacks/unsetCallback.ts
index 03ed25b33f5..6e59b7171c8 100644
--- a/packages/sanity/src/core/form/inputs/PortableText/callbacks/unsetCallback.ts
+++ b/packages/sanity/src/core/form/inputs/PortableText/callbacks/unsetCallback.ts
@@ -1,4 +1,4 @@
-import {PortableTextBlock} from '@sanity/portable-text-editor'
+import {PortableTextBlock} from '@sanity/types'
import {FormPatch, unset} from '../../../patch'
import {UnsetCallback} from './types'
diff --git a/packages/sanity/src/core/form/inputs/PortableText/hooks/useHotKeys.tsx b/packages/sanity/src/core/form/inputs/PortableText/hooks/useHotKeys.tsx
index b35032ff316..7b8b6d4b2b8 100644
--- a/packages/sanity/src/core/form/inputs/PortableText/hooks/useHotKeys.tsx
+++ b/packages/sanity/src/core/form/inputs/PortableText/hooks/useHotKeys.tsx
@@ -1,9 +1,5 @@
import {useMemo} from 'react'
-import {
- HotkeyOptions,
- PortableTextEditor,
- usePortableTextEditor,
-} from '@sanity/portable-text-editor'
+import {HotkeyOptions, usePortableTextEditor} from '@sanity/portable-text-editor'
// This hook will create final hotkeys for the editor from on those from props.
export function useHotkeys(hotkeys: HotkeyOptions): HotkeyOptions {
@@ -19,8 +15,7 @@ export function useHotkeys(hotkeys: HotkeyOptions): HotkeyOptions {
}
return useMemo(() => {
const defaultHotkeys: {marks: Record} = {marks: {}}
- const ptFeatures = PortableTextEditor.getPortableTextFeatures(editor)
- ptFeatures.decorators.forEach((dec) => {
+ editor.types.decorators.forEach((dec) => {
switch (dec.value) {
case 'strong':
defaultHotkeys.marks['mod+b'] = dec.value
diff --git a/packages/sanity/src/core/form/inputs/PortableText/hooks/useSpellCheck.tsx b/packages/sanity/src/core/form/inputs/PortableText/hooks/useSpellCheck.tsx
index b9507e6fc64..883f2a6f288 100644
--- a/packages/sanity/src/core/form/inputs/PortableText/hooks/useSpellCheck.tsx
+++ b/packages/sanity/src/core/form/inputs/PortableText/hooks/useSpellCheck.tsx
@@ -7,7 +7,7 @@ export function useSpellcheck(): boolean {
// Chrome 96. has serious perf. issues with spellchecking
// https://bugs.chromium.org/p/chromium/issues/detail?id=1271918
// This issue is verified fixed in Chrome 97.
- const spellCheckOption = editor.portableTextFeatures.types.block.options?.spellCheck
+ const spellCheckOption = editor.types.block.options?.spellCheck
const isChrome96 =
typeof navigator === 'undefined' ? false : /Chrome\/96/.test(navigator.userAgent)
return spellCheckOption === undefined && isChrome96 === true ? false : spellCheckOption
diff --git a/packages/sanity/src/core/form/inputs/PortableText/object/BlockObject.tsx b/packages/sanity/src/core/form/inputs/PortableText/object/BlockObject.tsx
index bfba317bea2..d0a183d992f 100644
--- a/packages/sanity/src/core/form/inputs/PortableText/object/BlockObject.tsx
+++ b/packages/sanity/src/core/form/inputs/PortableText/object/BlockObject.tsx
@@ -1,15 +1,13 @@
import {
PortableTextEditor,
- PortableTextBlock,
- RenderAttributes,
EditorSelection,
usePortableTextEditor,
} from '@sanity/portable-text-editor'
-import {ObjectSchemaType, Path} from '@sanity/types'
+import {ObjectSchemaType, Path, PortableTextBlock} from '@sanity/types'
import {Tooltip, Flex, ResponsivePaddingProps} from '@sanity/ui'
-import React, {useCallback, useMemo, useRef, useState} from 'react'
+import React, {ComponentType, useCallback, useMemo, useRef, useState} from 'react'
import {PatchArg} from '../../../patch'
-import {RenderCustomMarkers, RenderPreviewCallback} from '../../../types'
+import {BlockProps, RenderCustomMarkers, RenderPreviewCallback} from '../../../types'
import {RenderBlockActionsCallback} from '../types'
import {BlockActions} from '../BlockActions'
import {ReviewChangesHighlightBlock, StyledChangeIndicatorWithProvidedFullPath} from '../_common'
@@ -32,31 +30,38 @@ import {
} from './BlockObject.styles'
interface BlockObjectProps {
- attributes: RenderAttributes
block: PortableTextBlock
+ focused: boolean
isActive?: boolean
isFullscreen?: boolean
onChange: (...patches: PatchArg[]) => void
onItemOpen: (path: Path) => void
+ onItemClose: () => void
+ onItemRemove: (itemKey: string) => void
+ path: Path
readOnly?: boolean
renderBlockActions?: RenderBlockActionsCallback
renderCustomMarkers?: RenderCustomMarkers
renderPreview: RenderPreviewCallback
+ selected: boolean
type: ObjectSchemaType
}
export function BlockObject(props: BlockObjectProps) {
const {
- attributes: {focused, selected, path},
block,
+ focused,
isActive,
isFullscreen,
onChange,
onItemOpen,
+ onItemClose,
+ path,
readOnly,
renderBlockActions,
renderCustomMarkers,
renderPreview,
+ selected,
type,
} = props
const {Markers} = useFormBuilder().__internal.components
@@ -69,7 +74,7 @@ export function BlockObject(props: BlockObjectProps) {
const handleMouseOver = useCallback(() => setReviewChangesHovered(true), [])
const handleMouseOut = useCallback(() => setReviewChangesHovered(false), [])
- const handleEdit = useCallback(() => {
+ const openItem = useCallback(() => {
if (memberItem) {
onItemOpen(memberItem.node.path)
}
@@ -80,37 +85,38 @@ export function BlockObject(props: BlockObjectProps) {
e.preventDefault()
e.stopPropagation()
PortableTextEditor.blur(editor)
- handleEdit()
+ openItem()
},
- [editor, handleEdit]
+ [editor, openItem]
)
- const handleDelete = useCallback(
- (e: any) => {
- e.stopPropagation()
- e.preventDefault()
- const sel: EditorSelection = {focus: {path, offset: 0}, anchor: {path, offset: 0}}
- PortableTextEditor.delete(editor, sel, {mode: 'blocks'})
- // Focus will not stick unless this is done through a timeout when deleted through clicking the menu button.
- setTimeout(() => PortableTextEditor.focus(editor))
- },
- [editor, path]
- )
+ const onRemove = useCallback(() => {
+ const sel: EditorSelection = {focus: {path, offset: 0}, anchor: {path, offset: 0}}
+ PortableTextEditor.delete(editor, sel, {mode: 'blocks'})
+ // Focus will not stick unless this is done through a timeout when deleted through clicking the menu button.
+ setTimeout(() => PortableTextEditor.focus(editor))
+ }, [editor, path])
const blockPreview = useMemo(() => {
+ const _handleDelete = (e: React.MouseEvent) => {
+ e.preventDefault()
+ e.stopPropagation()
+ onRemove()
+ }
return (
)
- }, [focused, isActive, handleDelete, handleEdit, readOnly, renderPreview, type, block])
+ }, [focused, isActive, onRemove, openItem, readOnly, renderPreview, type, block])
const tone = selected || focused ? 'primary' : 'default'
@@ -155,7 +161,7 @@ export function BlockObject(props: BlockObjectProps) {
[Markers, markers, renderCustomMarkers, tooltipEnabled, validation]
)
- const returned = useMemo(
+ const defaultRendered = useMemo(
() => (
@@ -245,5 +251,27 @@ export function BlockObject(props: BlockObjectProps) {
]
)
- return returned
+ const CustomComponent = type.components?.block as ComponentType
+
+ const renderDefault = useCallback(() => defaultRendered, [defaultRendered])
+
+ return CustomComponent ? (
+
+ }>
+ {blockPreview}
+
+
+ ) : (
+ defaultRendered
+ )
}
diff --git a/packages/sanity/src/core/form/inputs/PortableText/object/BlockObjectPreview.tsx b/packages/sanity/src/core/form/inputs/PortableText/object/BlockObjectPreview.tsx
index e207c27fdf0..39d8852b4e2 100644
--- a/packages/sanity/src/core/form/inputs/PortableText/object/BlockObjectPreview.tsx
+++ b/packages/sanity/src/core/form/inputs/PortableText/object/BlockObjectPreview.tsx
@@ -1,9 +1,5 @@
import {EditIcon, LinkIcon, TrashIcon, EyeOpenIcon, EllipsisVerticalIcon} from '@sanity/icons'
-import {
- PortableTextBlock,
- PortableTextEditor,
- usePortableTextEditor,
-} from '@sanity/portable-text-editor'
+import {PortableTextEditor, usePortableTextEditor} from '@sanity/portable-text-editor'
import {
Button,
Menu,
@@ -22,10 +18,9 @@ import React, {
useRef,
useId,
} from 'react'
-import {ObjectSchemaType} from '@sanity/types'
+import {ObjectSchemaType, PortableTextBlock} from '@sanity/types'
import {RenderPreviewCallback} from '../../../types'
import {is} from '../../../utils/is'
-import {FIXME} from '../../../../FIXME'
import {IntentLink} from 'sanity/router'
interface BlockObjectPreviewProps {
@@ -66,10 +61,15 @@ export function BlockObjectPreview(props: BlockObjectPreviewProps): ReactElement
const referenceLink = useMemo(
() =>
- forwardRef(function ReferenceLink(linkProps: FIXME, ref: FIXME) {
- return
- }),
- [value?._ref]
+ '_ref' in value && value._ref
+ ? forwardRef(function ReferenceLink(
+ linkProps,
+ ref: React.Ref | undefined
+ ) {
+ return
+ })
+ : undefined,
+ [value]
)
// Go to menu when tabbed to
@@ -113,15 +113,17 @@ export function BlockObjectPreview(props: BlockObjectPreviewProps): ReactElement
id={menuButtonId}
menu={
}
popover={POPOVER_PROPS}
diff --git a/packages/sanity/src/core/form/inputs/PortableText/object/InlineObject.tsx b/packages/sanity/src/core/form/inputs/PortableText/object/InlineObject.tsx
index f1234dcc747..04597406bf0 100644
--- a/packages/sanity/src/core/form/inputs/PortableText/object/InlineObject.tsx
+++ b/packages/sanity/src/core/form/inputs/PortableText/object/InlineObject.tsx
@@ -1,12 +1,6 @@
import {hues} from '@sanity/color'
-import {
- PortableTextChild,
- PortableTextEditor,
- RenderAttributes,
- Type,
- usePortableTextEditor,
-} from '@sanity/portable-text-editor'
-import {Path} from '@sanity/types'
+import {PortableTextEditor, usePortableTextEditor} from '@sanity/portable-text-editor'
+import {ObjectSchemaType, Path, PortableTextChild} from '@sanity/types'
import React, {useCallback, useEffect, useMemo, useState} from 'react'
import styled, {css} from 'styled-components'
import {Box, Card, Theme, Tooltip} from '@sanity/ui'
@@ -21,13 +15,15 @@ import {FIXME} from '../../../../FIXME'
import {InlineObjectToolbarPopover} from './InlineObjectToolbarPopover'
interface InlineObjectProps {
- attributes: RenderAttributes
+ focused: boolean
+ selected: boolean
+ path: Path
onItemOpen: (path: Path) => void
readOnly?: boolean
renderCustomMarkers?: RenderCustomMarkers
renderPreview: RenderPreviewCallback
scrollElement: HTMLElement | null
- type: Type
+ type: ObjectSchemaType
value: PortableTextChild
}
@@ -114,12 +110,14 @@ export const InlineObject = React.forwardRef(function InlineObject(
forwardedRef: React.ForwardedRef
) {
const {
- attributes: {focused, selected, path},
+ focused,
onItemOpen,
+ path,
readOnly,
renderCustomMarkers,
renderPreview,
scrollElement,
+ selected,
type,
value,
} = props
diff --git a/packages/sanity/src/core/form/inputs/PortableText/text/Annotation.tsx b/packages/sanity/src/core/form/inputs/PortableText/text/Annotation.tsx
index 0af7aeaafea..b2d0518d780 100644
--- a/packages/sanity/src/core/form/inputs/PortableText/text/Annotation.tsx
+++ b/packages/sanity/src/core/form/inputs/PortableText/text/Annotation.tsx
@@ -1,17 +1,15 @@
import {hues} from '@sanity/color'
import {
- PortableTextChild,
+ BlockAnnotationRenderProps,
PortableTextEditor,
- RenderAttributes,
usePortableTextEditor,
} from '@sanity/portable-text-editor'
-import {ObjectSchemaType, Path} from '@sanity/types'
+import {Path} from '@sanity/types'
import {Box, Theme, ThemeColorToneKey, Tooltip} from '@sanity/ui'
-import React, {SyntheticEvent, useCallback, useMemo, useRef, useState} from 'react'
+import React, {ComponentType, SyntheticEvent, useCallback, useMemo, useRef, useState} from 'react'
import styled, {css} from 'styled-components'
-import {FIXME} from '../../../../FIXME'
import {pathToString} from '../../../../field'
-import {RenderCustomMarkers} from '../../../types'
+import {BlockAnnotationProps, RenderCustomMarkers} from '../../../types'
import {DefaultMarkers} from '../_legacyDefaultParts/Markers'
import {useFormBuilder} from '../../../useFormBuilder'
import {useMemberValidation} from '../hooks/useMemberValidation'
@@ -20,14 +18,12 @@ import {usePortableTextMemberItem} from '../hooks/usePortableTextMembers'
import {AnnotationToolbarPopover} from './AnnotationToolbarPopover'
interface AnnotationProps {
- attributes: RenderAttributes
- children: JSX.Element
+ renderProps: BlockAnnotationRenderProps
onItemOpen: (path: Path) => void
+ onItemClose: () => void
readOnly?: boolean
renderCustomMarkers?: RenderCustomMarkers
scrollElement: HTMLElement | null
- type: ObjectSchemaType
- value: PortableTextChild
}
const Root = styled.span<{$toneKey?: Exclude}>(
@@ -65,16 +61,8 @@ const TooltipBox = styled(Box).attrs({forwardedAs: 'span'})`
`
export const Annotation = function Annotation(props: AnnotationProps) {
- const {
- attributes: {path},
- children,
- onItemOpen,
- renderCustomMarkers,
- scrollElement,
- readOnly,
- type,
- value,
- } = props
+ const {onItemOpen, onItemClose, renderCustomMarkers, scrollElement, renderProps, readOnly} = props
+ const {type, value, path, renderDefault, selected, focused} = renderProps
const {Markers = DefaultMarkers} = useFormBuilder().__internal.components
const annotationRef = useRef(null)
const editor = usePortableTextEditor()
@@ -87,14 +75,16 @@ export const Annotation = function Annotation(props: AnnotationProps) {
const {validation, hasError, hasWarning} = useMemberValidation(memberItem?.node)
const markers = usePortableTextMarkers(path)
+ const CustomComponent = type.components?.annotation as ComponentType
+
const text = useMemo(
() => (
- {children}
+ {renderDefault(renderProps)}
),
- [children]
+ [renderDefault, renderProps]
)
const openItem = useCallback(() => {
@@ -139,7 +129,7 @@ export const Annotation = function Annotation(props: AnnotationProps) {
(event: React.MouseEvent): void => {
event.preventDefault()
event.stopPropagation()
- PortableTextEditor.removeAnnotation(editor, type as FIXME)
+ PortableTextEditor.removeAnnotation(editor, type)
PortableTextEditor.focus(editor)
},
[editor, type]
@@ -163,7 +153,7 @@ export const Annotation = function Annotation(props: AnnotationProps) {
}, [isLink, hasError, hasWarning])
const hasCustomMarkers = markers.length > 0
- return (
+ const defaultRendered = (
)
+ return CustomComponent && memberItem ? (
+ {
+ PortableTextEditor.removeAnnotation(editor, type)
+ PortableTextEditor.focus(editor)
+ }}
+ path={memberItem?.node.path || path}
+ // eslint-disable-next-line react/jsx-no-bind
+ renderDefault={() => defaultRendered}
+ selected={selected}
+ value={value}
+ >
+ {text}
+
+ ) : (
+ defaultRendered
+ )
}
diff --git a/packages/sanity/src/core/form/inputs/PortableText/text/ListItem.tsx b/packages/sanity/src/core/form/inputs/PortableText/text/ListItem.tsx
new file mode 100644
index 00000000000..b498796c17d
--- /dev/null
+++ b/packages/sanity/src/core/form/inputs/PortableText/text/ListItem.tsx
@@ -0,0 +1,26 @@
+import {BlockListItemRenderProps} from '@sanity/portable-text-editor'
+import React, {useCallback, useMemo} from 'react'
+
+export const ListItem = (props: BlockListItemRenderProps) => {
+ const {block, type, selected, focused, level, value, renderDefault} = props
+ const children = useMemo(() => renderDefault(props), [props, renderDefault])
+ const _renderDefault = useCallback(() => children, [children])
+
+ const CustomComponent = type.components?.item
+ if (CustomComponent) {
+ return (
+
+ {children}
+
+ )
+ }
+ return children
+}
diff --git a/packages/sanity/src/core/form/inputs/PortableText/text/Style.tsx b/packages/sanity/src/core/form/inputs/PortableText/text/Style.tsx
new file mode 100644
index 00000000000..1e81cb96d6f
--- /dev/null
+++ b/packages/sanity/src/core/form/inputs/PortableText/text/Style.tsx
@@ -0,0 +1,34 @@
+import {Text} from '@sanity/ui'
+import {BlockStyleRenderProps} from '@sanity/portable-text-editor'
+import React, {useCallback, useMemo} from 'react'
+import {TEXT_STYLES} from './textStyles'
+
+export const Style = (props: BlockStyleRenderProps) => {
+ const {block, type, selected, focused, value, renderDefault} = props
+ const DefaultComponent = useMemo(
+ () => (block.style && TEXT_STYLES[block.style] ? TEXT_STYLES[block.style] : TEXT_STYLES[0]),
+ [block.style]
+ )
+
+ const children = useMemo(() => renderDefault(props), [props, renderDefault])
+ const _renderDefault = useCallback(() => children, [children])
+
+ const CustomComponent = type.components?.item
+ if (CustomComponent) {
+ return (
+
+
+ {children}
+
+
+ )
+ }
+ return {children}
+}
diff --git a/packages/sanity/src/core/form/inputs/PortableText/text/TextBlock.tsx b/packages/sanity/src/core/form/inputs/PortableText/text/TextBlock.tsx
index e4e334f0db0..9f83d2c6d3e 100644
--- a/packages/sanity/src/core/form/inputs/PortableText/text/TextBlock.tsx
+++ b/packages/sanity/src/core/form/inputs/PortableText/text/TextBlock.tsx
@@ -1,7 +1,12 @@
-import {PortableTextBlock, RenderAttributes} from '@sanity/portable-text-editor'
-import {Box, Flex, ResponsivePaddingProps, Tooltip} from '@sanity/ui'
-import React, {RefObject, useCallback, useMemo, useState} from 'react'
-import {RenderCustomMarkers} from '../../../types'
+import {Box, Flex, ResponsivePaddingProps, Tooltip, Text} from '@sanity/ui'
+import React, {ComponentType, RefObject, useCallback, useMemo, useState} from 'react'
+import {BlockSchemaType, Path, PortableTextTextBlock} from '@sanity/types'
+import {
+ EditorSelection,
+ PortableTextEditor,
+ usePortableTextEditor,
+} from '@sanity/portable-text-editor'
+import {BlockProps, RenderCustomMarkers} from '../../../types'
import {PatchArg} from '../../../patch'
import {useFormBuilder} from '../../../useFormBuilder'
import {BlockActions} from '../BlockActions'
@@ -24,36 +29,43 @@ import {
TextRoot,
TooltipBox,
} from './TextBlock.styles'
-import {TEXT_STYLES} from './textStyles'
+import {TextContainer} from './textStyles'
export interface TextBlockProps {
- attributes: RenderAttributes
- block: PortableTextBlock
+ block: PortableTextTextBlock
children: React.ReactNode
+ focused: boolean
isFullscreen?: boolean
onChange: (...patches: PatchArg[]) => void
+ path: Path
readOnly?: boolean
renderBlockActions?: RenderBlockActionsCallback
renderCustomMarkers?: RenderCustomMarkers
+ selected: boolean
spellCheck?: boolean
+ type: BlockSchemaType
}
export function TextBlock(props: TextBlockProps) {
const {
- attributes: {path, focused},
block,
children,
+ focused,
isFullscreen,
onChange,
+ path,
readOnly,
renderBlockActions,
renderCustomMarkers,
+ selected,
spellCheck,
+ type,
} = props
const {Markers} = useFormBuilder().__internal.components
const [reviewChangesHovered, setReviewChangesHovered] = useState(false)
const markers = usePortableTextMarkers(path)
const memberItem = usePortableTextMemberItem(pathToString(path))
+ const editor = usePortableTextEditor()
const handleChangeIndicatorMouseEnter = useCallback(() => setReviewChangesHovered(true), [])
const handleChangeIndicatorMouseLeave = useCallback(() => setReviewChangesHovered(false), [])
@@ -65,21 +77,21 @@ export function TextBlock(props: TextBlockProps) {
const tooltipEnabled = hasError || hasWarning || hasMarkers || hasInfo
const text = useMemo(() => {
- const TextStyle = TEXT_STYLES[block.style] || TEXT_STYLES.normal
-
return (
{block.listItem && (
-
+
+
+
)}
-
+
{children}
-
+
)
- }, [block.style, block.listItem, block.level, children])
+ }, [block.listItem, block.level, children])
const innerPaddingProps: ResponsivePaddingProps = useMemo(() => {
if (isFullscreen && !renderBlockActions) {
@@ -105,80 +117,149 @@ export function TextBlock(props: TextBlockProps) {
return {paddingY: 2}
}
- return TEXT_STYLE_PADDING[block.style] || {paddingY: 2}
+ return TEXT_STYLE_PADDING[block.style || 'normal'] || {paddingY: 2}
}, [block])
- return (
-
-
- }
- >
-
-
-
-
- )
- }
- >
- (
+
+
+ }
+ >
+
+
+
+
+ )
+ }
>
- {text}
-
-
-
-
-
-
-
- {renderBlockActions && focused && !readOnly && (
-
+ {text}
+
+
+
+
+
+
+
+ {renderBlockActions && focused && !readOnly && (
+
+ )}
+
+
+
+ {isFullscreen && memberItem && (
+
+
- )}
-
-
-
- {isFullscreen && memberItem && (
-
-
-
- )}
-
- {reviewChangesHovered && }
-
-
-
+
+ )}
+
+ {reviewChangesHovered && }
+
+
+
+ ),
+ [
+ Markers,
+ block,
+ focused,
+ handleChangeIndicatorMouseEnter,
+ handleChangeIndicatorMouseLeave,
+ hasError,
+ hasMarkers,
+ hasWarning,
+ innerPaddingProps,
+ isFullscreen,
+ markers,
+ memberItem,
+ onChange,
+ outerPaddingProps,
+ readOnly,
+ renderBlockActions,
+ renderCustomMarkers,
+ reviewChangesHovered,
+ spellCheck,
+ text,
+ tooltipEnabled,
+ validation,
+ ]
+ )
+
+ const onRemove = useCallback(() => {
+ const sel: EditorSelection = {focus: {path, offset: 0}, anchor: {path, offset: 0}}
+ PortableTextEditor.delete(editor, sel, {mode: 'blocks'})
+ // Focus will not stick unless this is done through a timeout when deleted through clicking the menu button.
+ setTimeout(() => PortableTextEditor.focus(editor))
+ }, [editor, path])
+
+ const CustomComponent = type.components?.block as ComponentType
+
+ const renderDefault = useCallback(() => defaultRendered, [defaultRendered])
+ const notImplementedWarning = useCallback(() => {
+ console.warn("Regular text blocks don't open or close, but are edited inline.")
+ }, [])
+
+ return CustomComponent ? (
+
+
+ {text}
+
+
+ ) : (
+ defaultRendered
)
}
diff --git a/packages/sanity/src/core/form/inputs/PortableText/text/textStyles.tsx b/packages/sanity/src/core/form/inputs/PortableText/text/textStyles.tsx
index 5860bbfe0f5..0bdad90dea2 100644
--- a/packages/sanity/src/core/form/inputs/PortableText/text/textStyles.tsx
+++ b/packages/sanity/src/core/form/inputs/PortableText/text/textStyles.tsx
@@ -6,7 +6,7 @@ type TextStyleProps = Omit, 'as' | 'ref'>
type BlockQuoteStyleProps = Omit, 'as' | 'ref'>
// Without this container, editing with Android breaks due to how Text is styled via responsiveFont in @sanity/ui
-const TextContainer = styled.div`
+export const TextContainer = styled.div`
display: block;
`
diff --git a/packages/sanity/src/core/form/inputs/PortableText/toolbar/ActionMenu.tsx b/packages/sanity/src/core/form/inputs/PortableText/toolbar/ActionMenu.tsx
index 75953af325c..faa6e183858 100644
--- a/packages/sanity/src/core/form/inputs/PortableText/toolbar/ActionMenu.tsx
+++ b/packages/sanity/src/core/form/inputs/PortableText/toolbar/ActionMenu.tsx
@@ -4,7 +4,7 @@ import {EllipsisVerticalIcon} from '@sanity/icons'
import {PortableTextEditor, usePortableTextEditor} from '@sanity/portable-text-editor'
import {CollapseMenu, CollapseMenuButton} from '../../../../components/collapseMenu'
import {PTEToolbarAction, PTEToolbarActionGroup} from './types'
-import {useActiveActionKeys, useFeatures, useFocusBlock} from './hooks'
+import {useActiveActionKeys, useFocusBlock} from './hooks'
import {getActionIcon} from './helpers'
const CollapseMenuMemo = memo(CollapseMenu)
@@ -22,12 +22,14 @@ interface ActionMenuProps {
export const ActionMenu = memo(function ActionMenu(props: ActionMenuProps) {
const {disabled: disabledProp, groups, isFullscreen, collapsed} = props
const focusBlock = useFocusBlock()
- const features = useFeatures()
const editor = usePortableTextEditor()
- const isVoidBlock = focusBlock?._type !== features.types.block.name
+ const isVoidBlock = focusBlock?._type !== editor.types.block.name
const isEmptyTextBlock =
- !isVoidBlock && focusBlock?.children.length === 1 && focusBlock?.children[0].text === ''
+ !isVoidBlock &&
+ Array.isArray(focusBlock.children) &&
+ focusBlock.children.length === 1 &&
+ focusBlock?.children[0].text === ''
const disabled = disabledProp || isVoidBlock
diff --git a/packages/sanity/src/core/form/inputs/PortableText/toolbar/BlockStyleSelect.tsx b/packages/sanity/src/core/form/inputs/PortableText/toolbar/BlockStyleSelect.tsx
index 6e74a7de117..a0102a27c66 100644
--- a/packages/sanity/src/core/form/inputs/PortableText/toolbar/BlockStyleSelect.tsx
+++ b/packages/sanity/src/core/form/inputs/PortableText/toolbar/BlockStyleSelect.tsx
@@ -13,7 +13,7 @@ import {
BlockQuote,
Normal,
} from '../text/textStyles'
-import {useActiveStyleKeys, useFeatures, useFocusBlock} from './hooks'
+import {useActiveStyleKeys, useFocusBlock} from './hooks'
import {BlockStyleItem} from './types'
const MenuButtonMemo = memo(MenuButton)
@@ -69,12 +69,10 @@ export const BlockStyleSelect = memo(function BlockStyleSelect(
): JSX.Element {
const {disabled, items: itemsProp} = props
const editor = usePortableTextEditor()
- const features = useFeatures()
const focusBlock = useFocusBlock()
const [changed, setChanged] = useState(false)
- const _disabled =
- disabled || (focusBlock ? features.types.block.name !== focusBlock._type : false)
+ const _disabled = disabled || (focusBlock ? editor.types.block.name !== focusBlock._type : false)
// @todo: Explain what this does
const activeKeys = useActiveStyleKeys({items: itemsProp})
diff --git a/packages/sanity/src/core/form/inputs/PortableText/toolbar/InsertMenu.tsx b/packages/sanity/src/core/form/inputs/PortableText/toolbar/InsertMenu.tsx
index c4a0b7fb0fc..846bf32cc9f 100644
--- a/packages/sanity/src/core/form/inputs/PortableText/toolbar/InsertMenu.tsx
+++ b/packages/sanity/src/core/form/inputs/PortableText/toolbar/InsertMenu.tsx
@@ -4,7 +4,7 @@ import {Button, PopoverProps} from '@sanity/ui'
import {PortableTextEditor, usePortableTextEditor} from '@sanity/portable-text-editor'
import {CollapseMenu, CollapseMenuButton} from '../../../../components/collapseMenu'
import {BlockItem} from './types'
-import {useFeatures, useFocusBlock} from './hooks'
+import {useFocusBlock} from './hooks'
const CollapseMenuMemo = memo(CollapseMenu)
@@ -19,11 +19,10 @@ interface InsertMenuProps {
export const InsertMenu = memo(function InsertMenu(props: InsertMenuProps) {
const {disabled, items, isFullscreen, collapsed} = props
- const features = useFeatures()
const focusBlock = useFocusBlock()
const editor = usePortableTextEditor()
- const isVoidFocus = focusBlock && focusBlock._type !== features.types.block.name
+ const isVoidFocus = focusBlock && focusBlock._type !== editor.types.block.name
const handleMenuClose = useCallback(() => {
PortableTextEditor.focus(editor)
diff --git a/packages/sanity/src/core/form/inputs/PortableText/toolbar/Toolbar.tsx b/packages/sanity/src/core/form/inputs/PortableText/toolbar/Toolbar.tsx
index 11c482b3a8b..1e43b234593 100644
--- a/packages/sanity/src/core/form/inputs/PortableText/toolbar/Toolbar.tsx
+++ b/packages/sanity/src/core/form/inputs/PortableText/toolbar/Toolbar.tsx
@@ -9,14 +9,13 @@ import {ObjectSchemaType, Path, SchemaType} from '@sanity/types'
import {Box, Button, Flex, Hotkeys, Text, Tooltip, useElementRect, useToast} from '@sanity/ui'
import {CollapseIcon, ExpandIcon} from '@sanity/icons'
import styled, {css} from 'styled-components'
-import {FIXME} from '../../../../FIXME'
import {useRovingFocus} from '../../../../components'
import {useResolveInitialValueForType} from '../../../../store'
import {ActionMenu} from './ActionMenu'
import {BlockStyleSelect} from './BlockStyleSelect'
import {InsertMenu} from './InsertMenu'
import {getBlockStyles, getInsertMenuItems} from './helpers'
-import {useActionGroups, useFeatures} from './hooks'
+import {useActionGroups} from './hooks'
import {BlockItem, BlockStyleItem, PTEToolbarActionGroup} from './types'
interface ToolbarProps {
@@ -151,7 +150,6 @@ const InnerToolbar = memo(function InnerToolbar({
export function Toolbar(props: ToolbarProps) {
const {hotkeys, isFullscreen, readOnly, onMemberOpen, onToggleFullscreen} = props
- const features = useFeatures()
const editor = usePortableTextEditor()
const selection = usePortableTextEditorSelection()
const resolveInitialValueForType = useResolveInitialValueForType()
@@ -202,7 +200,7 @@ export function Toolbar(props: ToolbarProps) {
const handleInsertBlock = useCallback(
async (type: ObjectSchemaType) => {
const initialValue = await resolveInitialValue(type)
- const path = PortableTextEditor.insertBlock(editor, type as FIXME, initialValue)
+ const path = PortableTextEditor.insertBlock(editor, type, initialValue)
if (path) {
onMemberOpen(path)
}
@@ -213,7 +211,7 @@ export function Toolbar(props: ToolbarProps) {
const handleInsertInline = useCallback(
async (type: ObjectSchemaType) => {
const initialValue = await resolveInitialValue(type)
- const path = PortableTextEditor.insertChild(editor, type as FIXME, initialValue)
+ const path = PortableTextEditor.insertChild(editor, type, initialValue)
if (path) {
onMemberOpen(path)
}
@@ -228,11 +226,11 @@ export function Toolbar(props: ToolbarProps) {
disabled: true,
})
- const blockStyles = useMemo(() => getBlockStyles(features), [features])
+ const blockStyles = useMemo(() => getBlockStyles(editor.types), [editor])
const insertMenuItems = useMemo(
- () => getInsertMenuItems(features, disabled, handleInsertBlock, handleInsertInline),
- [disabled, features, handleInsertBlock, handleInsertInline]
+ () => getInsertMenuItems(editor.types, disabled, handleInsertBlock, handleInsertInline),
+ [disabled, editor, handleInsertBlock, handleInsertInline]
)
return (
diff --git a/packages/sanity/src/core/form/inputs/PortableText/toolbar/helpers.tsx b/packages/sanity/src/core/form/inputs/PortableText/toolbar/helpers.tsx
index 2d747e0506c..7fd401c1531 100644
--- a/packages/sanity/src/core/form/inputs/PortableText/toolbar/helpers.tsx
+++ b/packages/sanity/src/core/form/inputs/PortableText/toolbar/helpers.tsx
@@ -14,13 +14,11 @@ import {
import {
HotkeyOptions,
PortableTextEditor,
- PortableTextFeature,
- PortableTextFeatures,
+ PortableTextMemberTypes,
} from '@sanity/portable-text-editor'
-import {get} from 'lodash'
+import {capitalize, get} from 'lodash'
import React from 'react'
import {ObjectSchemaType} from '@sanity/types'
-import {FIXME} from '../../../../FIXME'
import {BlockItem, BlockStyleItem, PTEToolbarAction, PTEToolbarActionGroup} from './types'
import {CustomIcon} from './CustomIcon'
@@ -29,8 +27,8 @@ function getPTEFormatActions(
disabled: boolean,
hotkeyOpts: HotkeyOptions
): PTEToolbarAction[] {
- const features = PortableTextEditor.getPortableTextFeatures(editor)
- return features.decorators.map((decorator) => {
+ const types = editor.types
+ return types.decorators.map((decorator) => {
const shortCutKey = Object.keys(hotkeyOpts.marks || {}).find(
(key) => hotkeyOpts.marks?.[key] === decorator.value
)
@@ -43,7 +41,7 @@ function getPTEFormatActions(
return {
type: 'format',
disabled: disabled,
- icon: decorator.blockEditor?.icon,
+ icon: decorator?.icon,
key: decorator.value,
handle: (): void => {
PortableTextEditor.toggleMark(editor, decorator.value)
@@ -56,13 +54,13 @@ function getPTEFormatActions(
}
function getPTEListActions(editor: PortableTextEditor, disabled: boolean): PTEToolbarAction[] {
- const features = PortableTextEditor.getPortableTextFeatures(editor)
- return features.lists.map((listItem: PortableTextFeature) => {
+ const types = PortableTextEditor.getTypes(editor)
+ return types.lists.map((listItem) => {
return {
type: 'listStyle',
key: listItem.value,
disabled: disabled,
- icon: listItem.blockEditor?.icon,
+ icon: listItem?.icon,
handle: (): void => {
PortableTextEditor.toggleList(editor, listItem.value)
},
@@ -71,13 +69,12 @@ function getPTEListActions(editor: PortableTextEditor, disabled: boolean): PTETo
})
}
-function getAnnotationIcon(item: PortableTextFeature): React.ComponentType | string | undefined {
+function getAnnotationIcon(type: ObjectSchemaType): React.ComponentType | string | undefined {
return (
- get(item, 'icon') ||
- get(item, 'blockEditor.icon') ||
- get(item, 'type.icon') ||
- get(item, 'type.to.icon') ||
- get(item, 'type.to[0].icon')
+ get(type, 'icon') ||
+ get(type, 'type.icon') ||
+ get(type, 'type.to.icon') ||
+ get(type, 'type.to[0].icon')
)
}
@@ -86,24 +83,24 @@ function getPTEAnnotationActions(
disabled: boolean,
onInsert: (type: ObjectSchemaType) => void
): PTEToolbarAction[] {
- const features = PortableTextEditor.getPortableTextFeatures(editor)
+ const types = editor.types
const focusChild = PortableTextEditor.focusChild(editor)
const hasText = focusChild && focusChild.text
- return features.annotations.map((item) => {
+ return types.annotations.map((aType) => {
return {
type: 'annotation',
disabled: !hasText || disabled,
- icon: getAnnotationIcon(item),
- key: item.value,
+ icon: getAnnotationIcon(aType),
+ key: aType.name,
handle: (active?: boolean): void => {
if (active) {
- PortableTextEditor.removeAnnotation(editor, item.type)
+ PortableTextEditor.removeAnnotation(editor, aType)
PortableTextEditor.focus(editor)
} else {
- onInsert(item.type as FIXME)
+ onInsert(aType)
}
},
- title: item.title,
+ title: aType.title || capitalize(aType.name),
}
})
}
@@ -121,12 +118,12 @@ export function getPTEToolbarActionGroups(
]
}
-export function getBlockStyles(features: PortableTextFeatures): BlockStyleItem[] {
- return features.styles.map((style: PortableTextFeature) => {
+export function getBlockStyles(types: PortableTextMemberTypes): BlockStyleItem[] {
+ return types.styles.map((style) => {
return {
key: `style-${style.value}`,
style: style.value,
- styleComponent: style && style.blockEditor && style.blockEditor.render,
+ styleComponent: style && style.components?.item,
title: style.title,
}
})
@@ -142,28 +139,28 @@ function getInsertMenuIcon(
}
export function getInsertMenuItems(
- features: PortableTextFeatures,
+ types: PortableTextMemberTypes,
disabled: boolean,
onInsertBlock: (type: ObjectSchemaType) => void,
onInsertInline: (type: ObjectSchemaType) => void
): BlockItem[] {
- const blockItems = features.types.blockObjects.map(
+ const blockItems = types.blockObjects.map(
(type, index): BlockItem => ({
- handle: () => onInsertBlock(type as FIXME),
- icon: getInsertMenuIcon(type as FIXME, BlockElementIcon),
+ handle: () => onInsertBlock(type),
+ icon: getInsertMenuIcon(type, BlockElementIcon),
inline: false,
key: `block-${index}`,
- type: type as FIXME,
+ type,
})
)
- const inlineItems = features.types.inlineObjects.map(
+ const inlineItems = types.inlineObjects.map(
(type, index): BlockItem => ({
- handle: () => onInsertInline(type as FIXME),
- icon: getInsertMenuIcon(type as FIXME, InlineElementIcon),
+ handle: () => onInsertInline(type),
+ icon: getInsertMenuIcon(type, InlineElementIcon),
inline: true,
key: `inline-${index}`,
- type: type as FIXME,
+ type,
})
)
diff --git a/packages/sanity/src/core/form/inputs/PortableText/toolbar/hooks.ts b/packages/sanity/src/core/form/inputs/PortableText/toolbar/hooks.ts
index 69a54650de8..c0760c5a277 100644
--- a/packages/sanity/src/core/form/inputs/PortableText/toolbar/hooks.ts
+++ b/packages/sanity/src/core/form/inputs/PortableText/toolbar/hooks.ts
@@ -1,13 +1,10 @@
import {
HotkeyOptions,
- PortableTextBlock,
- PortableTextChild,
PortableTextEditor,
- PortableTextFeatures,
usePortableTextEditor,
usePortableTextEditorSelection,
} from '@sanity/portable-text-editor'
-import {ObjectSchemaType, Path} from '@sanity/types'
+import {ObjectSchemaType, Path, PortableTextBlock, PortableTextChild} from '@sanity/types'
import {useCallback, useMemo} from 'react'
import {FIXME} from '../../../../FIXME'
import {useUnique} from '../../../../util'
@@ -30,12 +27,6 @@ export function useFocusChild(): PortableTextChild | undefined {
return useMemo(() => PortableTextEditor.focusChild(editor), [editor, selection]) // selection must be an additional dep here
}
-export function useFeatures(): PortableTextFeatures {
- const editor = usePortableTextEditor()
-
- return useMemo(() => PortableTextEditor.getPortableTextFeatures(editor), [editor])
-}
-
export function useActionGroups({
hotkeys,
onMemberOpen,
diff --git a/packages/sanity/src/core/form/inputs/PortableText/toolbar/types.ts b/packages/sanity/src/core/form/inputs/PortableText/toolbar/types.ts
index b161ef3d138..ad50e39a1c6 100644
--- a/packages/sanity/src/core/form/inputs/PortableText/toolbar/types.ts
+++ b/packages/sanity/src/core/form/inputs/PortableText/toolbar/types.ts
@@ -1,6 +1,7 @@
// import {Type} from '@sanity/portable-text-editor'
import {ObjectSchemaType} from '@sanity/types'
+import {ComponentType, ReactNode} from 'react'
export interface BlockItem {
handle: () => void
@@ -20,7 +21,7 @@ export interface BlockStyleItem {
export interface PTEToolbarAction {
type: 'annotation' | 'format' | 'listStyle'
disabled: boolean
- icon?: React.ElementType | string
+ icon?: ReactNode | ComponentType
handle: (active?: boolean) => void
hotkeys?: string[]
key: string
diff --git a/packages/sanity/src/core/form/inputs/PortableText/types.tsx b/packages/sanity/src/core/form/inputs/PortableText/types.tsx
index 5c42fe602d3..bd8568a559c 100644
--- a/packages/sanity/src/core/form/inputs/PortableText/types.tsx
+++ b/packages/sanity/src/core/form/inputs/PortableText/types.tsx
@@ -1,5 +1,4 @@
-import type {PortableTextBlock} from '@sanity/portable-text-editor'
-import type {Path} from '@sanity/types'
+import type {PortableTextBlock, Path} from '@sanity/types'
/**
* @internal