UNPKG

@portabletext/editor

Version:

Portable Text Editor made in React

999 lines (935 loc) 23.2 kB
import type { Path, PortableTextBlock, PortableTextObject, PortableTextTextBlock, } from '@sanity/types' declare type AbstractBehaviorEvent = | { type: StrictExtract<SyntheticBehaviorEventType, 'annotation.set'> at: AnnotationPath props: Record<string, unknown> } | { type: StrictExtract<SyntheticBehaviorEventType, 'annotation.toggle'> annotation: { name: string value: { [prop: string]: unknown } } } | { type: StrictExtract<SyntheticBehaviorEventType, 'decorator.toggle'> decorator: string at?: { anchor: BlockOffset focus: BlockOffset } } | { type: StrictExtract<SyntheticBehaviorEventType, 'delete.backward'> unit: 'character' | 'word' | 'line' | 'block' } | { type: StrictExtract<SyntheticBehaviorEventType, 'delete.block'> at: BlockPath } | { type: StrictExtract<SyntheticBehaviorEventType, 'delete.child'> at: ChildPath } | { type: StrictExtract<SyntheticBehaviorEventType, 'delete.forward'> unit: 'character' | 'word' | 'line' | 'block' } | { type: StrictExtract<SyntheticBehaviorEventType, 'delete.text'> at: { anchor: BlockOffset focus: BlockOffset } } | { type: StrictExtract<SyntheticBehaviorEventType, 'deserialize'> originEvent: | PickFromUnion< NativeBehaviorEvent, 'type', 'drag.drop' | 'clipboard.paste' > | InputBehaviorEvent } | { type: StrictExtract<SyntheticBehaviorEventType, 'serialize'> originEvent: PickFromUnion< NativeBehaviorEvent, 'type', 'clipboard.copy' | 'clipboard.cut' | 'drag.dragstart' > } | { type: StrictExtract<SyntheticBehaviorEventType, 'deserialization.success'> mimeType: MIMEType data: Array<PortableTextBlock> originEvent: | PickFromUnion< NativeBehaviorEvent, 'type', 'drag.drop' | 'clipboard.paste' > | InputBehaviorEvent } | { type: StrictExtract<SyntheticBehaviorEventType, 'deserialization.failure'> mimeType: MIMEType reason: string originEvent: | PickFromUnion< NativeBehaviorEvent, 'type', 'drag.drop' | 'clipboard.paste' > | InputBehaviorEvent } | { type: StrictExtract<SyntheticBehaviorEventType, 'serialization.success'> mimeType: MIMEType data: string originEvent: PickFromUnion< NativeBehaviorEvent, 'type', 'clipboard.copy' | 'clipboard.cut' | 'drag.dragstart' > } | { type: StrictExtract<SyntheticBehaviorEventType, 'serialization.failure'> mimeType: MIMEType reason: string originEvent: PickFromUnion< NativeBehaviorEvent, 'type', 'clipboard.copy' | 'clipboard.cut' | 'drag.dragstart' > } | { type: StrictExtract<SyntheticBehaviorEventType, 'insert.blocks'> blocks: Array<BlockWithOptionalKey> placement: InsertPlacement select?: 'start' | 'end' | 'none' } | { type: StrictExtract<SyntheticBehaviorEventType, 'insert.break'> } | { type: StrictExtract<SyntheticBehaviorEventType, 'insert.soft break'> } | { type: StrictExtract<SyntheticBehaviorEventType, 'list item.add'> listItem: string } | { type: StrictExtract<SyntheticBehaviorEventType, 'list item.remove'> listItem: string } | { type: StrictExtract<SyntheticBehaviorEventType, 'list item.toggle'> listItem: string } | { type: StrictExtract<SyntheticBehaviorEventType, 'move.block down'> at: BlockPath } | { type: StrictExtract<SyntheticBehaviorEventType, 'move.block up'> at: BlockPath } | { type: StrictExtract<SyntheticBehaviorEventType, 'select.previous block'> select?: 'start' | 'end' } | { type: StrictExtract<SyntheticBehaviorEventType, 'select.next block'> select?: 'start' | 'end' } | { type: StrictExtract<SyntheticBehaviorEventType, 'split'> } | { type: StrictExtract<SyntheticBehaviorEventType, 'style.add'> style: string } | { type: StrictExtract<SyntheticBehaviorEventType, 'style.remove'> style: string } | { type: StrictExtract<SyntheticBehaviorEventType, 'style.toggle'> style: string } /************************************** * Abstract events **************************************/ declare const abstractBehaviorEventTypes: readonly [ 'annotation.set', 'annotation.toggle', 'decorator.toggle', 'delete.backward', 'delete.block', 'delete.child', 'delete.forward', 'delete.text', 'deserialize', 'deserialization.success', 'deserialization.failure', 'insert.blocks', 'insert.break', 'insert.soft break', 'list item.add', 'list item.remove', 'list item.toggle', 'move.block down', 'move.block up', 'select.previous block', 'select.next block', 'serialize', 'serialization.success', 'serialization.failure', 'split', 'style.add', 'style.remove', 'style.toggle', ] /** * @public */ declare type AnnotationPath = [ { _key: string }, 'markDefs', { _key: string }, ] /** * @public */ declare type AnnotationSchemaType = BaseDefinition & { fields: ReadonlyArray<FieldDefinition> } /** * @public */ declare type BaseDefinition = { name: string title?: string } /** * @beta */ export declare type Behavior< TBehaviorEventType extends | '*' | `${BehaviorEventTypeNamespace}.*` | BehaviorEvent['type'] = | '*' | `${BehaviorEventTypeNamespace}.*` | BehaviorEvent['type'], TGuardResponse = true, TBehaviorEvent extends ResolveBehaviorEvent<TBehaviorEventType> = ResolveBehaviorEvent<TBehaviorEventType>, > = { /** * Editor Event that triggers this Behavior. */ on: TBehaviorEventType /** * Predicate function that determines if the Behavior should be executed. * Returning a non-nullable value from the guard will pass the value to the * actions and execute them. */ guard?: BehaviorGuard<TBehaviorEvent, TGuardResponse> /** * Array of Behavior Action sets. * Each set represents a step in the history stack. */ actions: Array<BehaviorActionSet<TBehaviorEvent, TGuardResponse>> } /** * @beta */ export declare type BehaviorAction = | { type: 'execute' event: SyntheticBehaviorEvent } | { type: 'forward' event: NativeBehaviorEvent | SyntheticBehaviorEvent | CustomBehaviorEvent } | { type: 'raise' event: SyntheticBehaviorEvent | CustomBehaviorEvent } | { type: 'effect' effect: () => void } /** * @beta */ export declare type BehaviorActionSet<TBehaviorEvent, TGuardResponse> = ( payload: { snapshot: EditorSnapshot event: TBehaviorEvent dom: EditorDom }, guardResponse: TGuardResponse, ) => Array<BehaviorAction> /** * @beta */ export declare type BehaviorEvent = | SyntheticBehaviorEvent | NativeBehaviorEvent | CustomBehaviorEvent declare type BehaviorEventTypeNamespace = | SyntheticBehaviorEventNamespace | NativeBehaviorEventNamespace | CustomBehaviorEventNamespace /** * @beta */ export declare type BehaviorGuard<TBehaviorEvent, TGuardResponse> = (payload: { snapshot: EditorSnapshot event: TBehaviorEvent dom: EditorDom }) => TGuardResponse | false /** * @public */ declare type BlockObjectSchemaType = BaseDefinition & { fields: ReadonlyArray<FieldDefinition> } /** * @beta */ declare type BlockOffset = { path: BlockPath offset: number } /** * @public */ declare type BlockPath = [ { _key: string }, ] declare type BlockWithOptionalKey = | TextBlockWithOptionalKey | ObjectBlockWithOptionalKey /** * @public */ declare type ChildPath = [ { _key: string }, 'children', { _key: string }, ] declare type ClipboardBehaviorEvent = | { type: StrictExtract<NativeBehaviorEventType, 'clipboard.copy'> originEvent: { dataTransfer: DataTransfer } position: Pick<EventPosition, 'selection'> } | { type: StrictExtract<NativeBehaviorEventType, 'clipboard.cut'> originEvent: { dataTransfer: DataTransfer } position: Pick<EventPosition, 'selection'> } | { type: StrictExtract<NativeBehaviorEventType, 'clipboard.paste'> originEvent: { dataTransfer: DataTransfer } position: Pick<EventPosition, 'selection'> } declare type Converter<TMIMEType extends MIMEType = MIMEType> = { mimeType: TMIMEType serialize: Serializer<TMIMEType> deserialize: Deserializer<TMIMEType> } declare type ConverterEvent<TMIMEType extends MIMEType = MIMEType> = | { type: 'serialize' originEvent: 'clipboard.copy' | 'clipboard.cut' | 'drag.dragstart' } | { type: 'serialization.failure' mimeType: TMIMEType originEvent: 'clipboard.copy' | 'clipboard.cut' | 'drag.dragstart' reason: string } | { type: 'serialization.success' data: string mimeType: TMIMEType originEvent: 'clipboard.copy' | 'clipboard.cut' | 'drag.dragstart' } | { type: 'deserialize' data: string } | { type: 'deserialization.failure' mimeType: TMIMEType reason: string } | { type: 'deserialization.success' data: Array<PortableTextBlock> mimeType: TMIMEType } /** * @beta */ export declare type CustomBehaviorEvent< TPayload extends Record<string, unknown> = Record<string, unknown>, TType extends string = string, TInternalType extends CustomBehaviorEventType< 'custom', TType > = CustomBehaviorEventType<'custom', TType>, > = { type: TInternalType } & TPayload /************************************** * Custom events **************************************/ declare type CustomBehaviorEventNamespace = 'custom' declare type CustomBehaviorEventType< TNamespace extends CustomBehaviorEventNamespace, TType extends string = '', > = TType extends '' ? `${TNamespace}` : `${TNamespace}.${TType}` /** * @public */ declare type DecoratorSchemaType = BaseDefinition & { /** * @deprecated * Use `name` instead */ value: string } /** * @beta * * @example * * ```tsx * const noLowerCaseA = defineBehavior({ * on: 'insert.text', * guard: ({event, snapshot}) => event.text === 'a', * actions: [({event, snapshot}) => [{type: 'insert.text', text: 'A'}]], * }) * ``` * */ export declare function defineBehavior< TPayload extends Record<string, unknown>, TBehaviorEventType extends | '*' | `${BehaviorEventTypeNamespace}.*` | BehaviorEvent['type'] = CustomBehaviorEvent['type'], TGuardResponse = true, >( behavior: Behavior< TBehaviorEventType, TGuardResponse, ResolveBehaviorEvent<TBehaviorEventType, TPayload> >, ): Behavior declare type Deserializer<TMIMEType extends MIMEType> = ({ snapshot, event, }: { snapshot: EditorSnapshot event: PickFromUnion<ConverterEvent<TMIMEType>, 'type', 'deserialize'> }) => PickFromUnion< ConverterEvent<TMIMEType>, 'type', 'deserialization.success' | 'deserialization.failure' > declare type DragBehaviorEvent = | { type: StrictExtract<NativeBehaviorEventType, 'drag.dragstart'> originEvent: { clientX: number clientY: number dataTransfer: DataTransfer } position: Pick<EventPosition, 'selection'> } | { type: StrictExtract<NativeBehaviorEventType, 'drag.drag'> originEvent: { dataTransfer: DataTransfer } } | { type: StrictExtract<NativeBehaviorEventType, 'drag.dragend'> originEvent: { dataTransfer: DataTransfer } } | { type: StrictExtract<NativeBehaviorEventType, 'drag.dragenter'> originEvent: { dataTransfer: DataTransfer } position: EventPosition } | { type: StrictExtract<NativeBehaviorEventType, 'drag.dragover'> originEvent: { dataTransfer: DataTransfer } dragOrigin?: Pick<EventPosition, 'selection'> position: EventPosition } | { type: StrictExtract<NativeBehaviorEventType, 'drag.drop'> originEvent: { dataTransfer: DataTransfer } dragOrigin?: Pick<EventPosition, 'selection'> position: EventPosition } | { type: StrictExtract<NativeBehaviorEventType, 'drag.dragleave'> originEvent: { dataTransfer: DataTransfer } } /** * @public */ declare type EditorContext = { converters: Array<Converter> keyGenerator: () => string readOnly: boolean schema: EditorSchema selection: EditorSelection value: Array<PortableTextBlock> } declare type EditorDom = { getBlockNodes: (snapshot: EditorSnapshot) => Array<Node> getChildNodes: (snapshot: EditorSnapshot) => Array<Node> /** * Let the Editor set the drag ghost. This is to be sure that it will get * properly removed again when the drag ends. */ setDragGhost: ({ event, ghost, }: { event: PickFromUnion<BehaviorEvent, 'type', 'drag.dragstart'> ghost: { element: HTMLElement x: number y: number } }) => void } /** * @public */ declare type EditorSchema = { annotations: ReadonlyArray<AnnotationSchemaType> block: { name: string } blockObjects: ReadonlyArray<BlockObjectSchemaType> decorators: ReadonlyArray<DecoratorSchemaType> inlineObjects: ReadonlyArray<InlineObjectSchemaType> span: { name: string } styles: ReadonlyArray<StyleSchemaType> lists: ReadonlyArray<ListSchemaType> } /** @public */ declare type EditorSelection = { anchor: EditorSelectionPoint focus: EditorSelectionPoint backward?: boolean } | null /** @public */ declare type EditorSelectionPoint = { path: Path offset: number } /** * @public */ declare type EditorSnapshot = { context: EditorContext blockIndexMap: Map<string, number> /** * @beta * Subject to change */ decoratorState: Record<string, boolean | undefined> } /** * @beta */ export declare function effect( effect: () => void, ): PickFromUnion<BehaviorAction, 'type', 'effect'> declare type EventPosition = { block: 'start' | 'end' /** * Did the event origin from the editor DOM node itself or from a child node? */ isEditor: boolean selection: NonNullable<EditorSelection> } /** * @beta */ export declare function execute( event: SyntheticBehaviorEvent, ): PickFromUnion<BehaviorAction, 'type', 'execute'> declare type ExtractNamespace<TType extends string> = TType extends `${infer Namespace}.${string}` ? Namespace : TType /** * @public */ declare type FieldDefinition = BaseDefinition & { type: 'string' | 'number' | 'boolean' | 'array' | 'object' } /** * @beta */ export declare function forward( event: NativeBehaviorEvent | SyntheticBehaviorEvent | CustomBehaviorEvent, ): PickFromUnion<BehaviorAction, 'type', 'forward'> /** * @public */ declare type InlineObjectSchemaType = BaseDefinition & { fields: ReadonlyArray<FieldDefinition> } /** * Used to represent native InputEvents that hold a DataTransfer object. * * These can either be one of: * * - insertFromPaste * - insertFromPasteAsQuotation * - insertFromDrop * - insertReplacementText * - insertFromYank */ declare type InputBehaviorEvent = { type: StrictExtract<NativeBehaviorEventType, 'input.*'> originEvent: { dataTransfer: DataTransfer } } /** * @beta */ export declare type InsertPlacement = 'auto' | 'after' | 'before' declare type KeyboardBehaviorEvent = | { type: StrictExtract<NativeBehaviorEventType, 'keyboard.keydown'> originEvent: Pick< KeyboardEvent, 'key' | 'code' | 'altKey' | 'ctrlKey' | 'metaKey' | 'shiftKey' > } | { type: StrictExtract<NativeBehaviorEventType, 'keyboard.keyup'> originEvent: Pick< KeyboardEvent, 'key' | 'code' | 'altKey' | 'ctrlKey' | 'metaKey' | 'shiftKey' > } /** * @public */ declare type ListSchemaType = BaseDefinition & { /** * @deprecated * Use `name` instead */ value: string } declare type MIMEType = `${string}/${string}` declare type MouseBehaviorEvent = { type: StrictExtract<NativeBehaviorEventType, 'mouse.click'> position: EventPosition } declare type NamespacedBehaviorEventType< TNamespace extends BehaviorEventTypeNamespace | '', > = TNamespace extends '' ? BehaviorEvent['type'] : Extract<BehaviorEvent['type'], TNamespace | `${TNamespace}.${string}`> /** * @beta */ export declare type NativeBehaviorEvent = | ClipboardBehaviorEvent | DragBehaviorEvent | InputBehaviorEvent | KeyboardBehaviorEvent | MouseBehaviorEvent declare type NativeBehaviorEventNamespace = ExtractNamespace<NativeBehaviorEventType> declare type NativeBehaviorEventType = (typeof nativeBehaviorEventTypes)[number] /************************************** * Native events **************************************/ declare const nativeBehaviorEventTypes: readonly [ 'clipboard.copy', 'clipboard.cut', 'clipboard.paste', 'drag.dragstart', 'drag.drag', 'drag.dragend', 'drag.dragenter', 'drag.dragover', 'drag.dragleave', 'drag.drop', 'input.*', 'keyboard.keydown', 'keyboard.keyup', 'mouse.click', ] declare type ObjectBlockWithOptionalKey = Omit<PortableTextObject, '_key'> & { _key?: PortableTextObject['_key'] } /** * @internal */ declare type PickFromUnion< TUnion, TTagKey extends keyof TUnion, TPickedTags extends TUnion[TTagKey], > = TUnion extends Record<TTagKey, TPickedTags> ? TUnion : never /** * @beta */ export declare function raise( event: SyntheticBehaviorEvent | CustomBehaviorEvent, ): PickFromUnion<BehaviorAction, 'type', 'raise'> /************************************** * Resolve behavior event **************************************/ declare type ResolveBehaviorEvent< TBehaviorEventType extends | '*' | `${BehaviorEventTypeNamespace}.*` | BehaviorEvent['type'], TPayload extends Record<string, unknown> = Record<string, unknown>, > = TBehaviorEventType extends '*' ? BehaviorEvent : TBehaviorEventType extends `${infer TNamespace}.*` ? TNamespace extends BehaviorEventTypeNamespace ? PickFromUnion< BehaviorEvent, 'type', NamespacedBehaviorEventType<TNamespace> > : never : TBehaviorEventType extends `custom.${infer TType}` ? CustomBehaviorEvent<TPayload, TType> : TBehaviorEventType extends BehaviorEvent['type'] ? PickFromUnion<BehaviorEvent, 'type', TBehaviorEventType> : never declare type Serializer<TMIMEType extends MIMEType> = ({ snapshot, event, }: { snapshot: EditorSnapshot event: PickFromUnion<ConverterEvent<TMIMEType>, 'type', 'serialize'> }) => PickFromUnion< ConverterEvent<TMIMEType>, 'type', 'serialization.success' | 'serialization.failure' > declare type StrictExtract<T, U extends T> = U /** * @public */ declare type StyleSchemaType = BaseDefinition & { /** * @deprecated * Use `name` instead */ value: string } /** * @beta */ export declare type SyntheticBehaviorEvent = | { type: StrictExtract<SyntheticBehaviorEventType, 'annotation.add'> annotation: { name: string value: { [prop: string]: unknown } } } | { type: StrictExtract<SyntheticBehaviorEventType, 'annotation.remove'> annotation: { name: string } } | { type: StrictExtract<SyntheticBehaviorEventType, 'block.set'> at: BlockPath props: Record<string, unknown> } | { type: StrictExtract<SyntheticBehaviorEventType, 'block.unset'> at: BlockPath props: Array<string> } | { type: StrictExtract<SyntheticBehaviorEventType, 'child.set'> at: ChildPath props: { [prop: string]: unknown } } | { type: StrictExtract<SyntheticBehaviorEventType, 'child.unset'> at: ChildPath props: Array<string> } | { type: StrictExtract<SyntheticBehaviorEventType, 'decorator.add'> decorator: string at?: { anchor: BlockOffset focus: BlockOffset } } | { type: StrictExtract<SyntheticBehaviorEventType, 'decorator.remove'> decorator: string } | { type: StrictExtract<SyntheticBehaviorEventType, 'delete'> at: NonNullable<EditorSelection> /** * Defaults to forward deletion. */ direction?: 'backward' | 'forward' /** * Defaults to character deletion. */ unit?: 'character' | 'word' | 'line' | 'block' } | { type: StrictExtract<SyntheticBehaviorEventType, 'history.redo'> } | { type: StrictExtract<SyntheticBehaviorEventType, 'history.undo'> } | { type: StrictExtract<SyntheticBehaviorEventType, 'insert.inline object'> inlineObject: { name: string value?: { [prop: string]: unknown } } } | { type: StrictExtract<SyntheticBehaviorEventType, 'insert.block'> block: BlockWithOptionalKey placement: InsertPlacement select?: 'start' | 'end' | 'none' } | { type: StrictExtract<SyntheticBehaviorEventType, 'insert.span'> text: string annotations?: Array<{ name: string value: { [prop: string]: unknown } }> decorators?: Array<string> } | { type: StrictExtract<SyntheticBehaviorEventType, 'insert.text'> text: string } | { type: StrictExtract<SyntheticBehaviorEventType, 'move.backward'> distance: number } | { type: StrictExtract<SyntheticBehaviorEventType, 'move.block'> at: BlockPath to: BlockPath } | { type: StrictExtract<SyntheticBehaviorEventType, 'move.forward'> distance: number } | { type: StrictExtract<SyntheticBehaviorEventType, 'select'> at: EditorSelection } | AbstractBehaviorEvent declare type SyntheticBehaviorEventNamespace = ExtractNamespace<SyntheticBehaviorEventType> declare type SyntheticBehaviorEventType = | (typeof syntheticBehaviorEventTypes)[number] | (typeof abstractBehaviorEventTypes)[number] /************************************** * Synthetic events **************************************/ declare const syntheticBehaviorEventTypes: readonly [ 'annotation.add', 'annotation.remove', 'block.set', 'block.unset', 'child.set', 'child.unset', 'decorator.add', 'decorator.remove', 'delete', 'history.redo', 'history.undo', 'insert.inline object', 'insert.block', 'insert.span', 'insert.text', 'move.backward', 'move.block', 'move.forward', 'select', ] declare type TextBlockWithOptionalKey = Omit<PortableTextTextBlock, '_key'> & { _key?: PortableTextTextBlock['_key'] } export {}