@portabletext/editor
Advanced tools
Comparing version 1.21.6 to 1.22.0
@@ -1,2 +0,2 @@ | ||
import { reverseSelection, getBlockStartPoint } from "./util.get-block-start-point.js"; | ||
import { reverseSelection, getBlockStartPoint } from "./util.reverse-selection.js"; | ||
import { isKeyedSegment } from "./util.is-keyed-segment.js"; | ||
@@ -3,0 +3,0 @@ import { isPortableTextTextBlock, isPortableTextSpan } from "@sanity/types"; |
@@ -692,2 +692,44 @@ import type { | ||
* @beta | ||
* Create markdown behaviors for common markdown actions such as converting ### to headings, --- to HRs, and more. | ||
* | ||
* @example | ||
* Configure the bundled markdown behaviors | ||
* ```ts | ||
* import {EditorProvider} from '@portabletext/editor' | ||
* import {createMarkdownBehaviors, coreBehaviors} from '@portabletext/editor/behaviors' | ||
* | ||
* function App() { | ||
* return ( | ||
* <EditorProvider | ||
* initialConfig={{ | ||
* behaviors: [ | ||
* ...coreBehaviors, | ||
* ...createMarkdownBehaviors({ | ||
* horizontalRuleObject: ({schema}) => { | ||
* const name = schema.blockObjects.find( | ||
* (object) => object.name === 'break', | ||
* )?.name | ||
* return name ? {name} : undefined | ||
* }, | ||
* defaultStyle: ({schema}) => schema.styles[0].value, | ||
* headingStyle: ({schema, level}) => | ||
* schema.styles.find((style) => style.value === `h${level}`) | ||
* ?.value, | ||
* blockquoteStyle: ({schema}) => | ||
* schema.styles.find((style) => style.value === 'blockquote') | ||
* ?.value, | ||
* unorderedListStyle: ({schema}) => | ||
* schema.lists.find((list) => list.value === 'bullet')?.value, | ||
* orderedListStyle: ({schema}) => | ||
* schema.lists.find((list) => list.value === 'number')?.value, | ||
* }), | ||
* ] | ||
* }} | ||
* > | ||
* {...} | ||
* </EditorProvider> | ||
* ) | ||
* } | ||
* ``` | ||
* | ||
*/ | ||
@@ -734,2 +776,17 @@ export declare function createMarkdownBehaviors( | ||
* @beta | ||
* | ||
* @example | ||
* | ||
* ```tsx | ||
* const noLowerCaseA = defineBehavior({ | ||
* on: 'insert.text', | ||
* guard: ({event, context}) => event.text === 'a', | ||
* actions: [({event, context}) => [{type: 'insert.text', text: 'A'}]], | ||
* }) | ||
* ``` | ||
* | ||
* | ||
* | ||
* | ||
* | ||
*/ | ||
@@ -736,0 +793,0 @@ export declare function defineBehavior< |
@@ -203,2 +203,7 @@ import type { | ||
*/ | ||
export declare const getSelectedSlice: EditorSelector<Array<PortableTextBlock>> | ||
/** | ||
* @public | ||
*/ | ||
export declare const getSelectedSpans: EditorSelector< | ||
@@ -205,0 +210,0 @@ Array<{ |
import { getSelectedBlocks, createGuards, isSelectionCollapsed } from "../_chunks-es/selector.is-selection-collapsed.js"; | ||
import { getFirstBlock, getFocusBlock, getFocusBlockObject, getFocusChild, getFocusListBlock, getFocusSpan, getFocusTextBlock, getLastBlock, getNextBlock, getPreviousBlock, getSelectionEndBlock, getSelectionStartBlock } from "../_chunks-es/selector.is-selection-collapsed.js"; | ||
import { sliceBlocks } from "../_chunks-es/util.slice-blocks.js"; | ||
import { isKeySegment, isPortableTextTextBlock, isPortableTextSpan } from "@sanity/types"; | ||
import { getBlockTextBefore, getSelectionText } from "../_chunks-es/selector.get-text-before.js"; | ||
import { reverseSelection } from "../_chunks-es/util.get-block-start-point.js"; | ||
import { reverseSelection } from "../_chunks-es/util.reverse-selection.js"; | ||
const getActiveListItem = ({ | ||
@@ -32,4 +33,9 @@ context | ||
return firstStyle; | ||
}, getSelectedSpans = ({ | ||
}, getSelectedSlice = ({ | ||
context | ||
}) => sliceBlocks({ | ||
blocks: context.value, | ||
selection: context.selection | ||
}), getSelectedSpans = ({ | ||
context | ||
}) => { | ||
@@ -240,2 +246,3 @@ if (!context.selection) | ||
getSelectedBlocks, | ||
getSelectedSlice, | ||
getSelectedSpans, | ||
@@ -242,0 +249,0 @@ getSelectionEndBlock, |
@@ -79,2 +79,13 @@ import {KeyedSegment, PortableTextBlock} from '@sanity/types' | ||
*/ | ||
export declare function sliceBlocks({ | ||
blocks, | ||
selection, | ||
}: { | ||
blocks: Array<PortableTextBlock> | ||
selection: EditorSelection | ||
}): Array<PortableTextBlock> | ||
/** | ||
* @public | ||
*/ | ||
export declare function spanSelectionPointToBlockOffset({ | ||
@@ -81,0 +92,0 @@ value, |
import { blockOffsetToSpanSelectionPoint, getTextBlockText, isEmptyTextBlock, spanSelectionPointToBlockOffset } from "../_chunks-es/util.is-empty-text-block.js"; | ||
import { getBlockStartPoint, reverseSelection } from "../_chunks-es/util.get-block-start-point.js"; | ||
import { getBlockStartPoint, reverseSelection } from "../_chunks-es/util.reverse-selection.js"; | ||
import { isKeyedSegment } from "../_chunks-es/util.is-keyed-segment.js"; | ||
import { sliceBlocks } from "../_chunks-es/util.slice-blocks.js"; | ||
export { | ||
@@ -11,4 +12,5 @@ blockOffsetToSpanSelectionPoint, | ||
reverseSelection, | ||
sliceBlocks, | ||
spanSelectionPointToBlockOffset | ||
}; | ||
//# sourceMappingURL=index.js.map |
{ | ||
"name": "@portabletext/editor", | ||
"version": "1.21.6", | ||
"version": "1.22.0", | ||
"description": "Portable Text Editor made in React", | ||
@@ -85,3 +85,3 @@ "keywords": [ | ||
"@testing-library/jest-dom": "^6.6.3", | ||
"@testing-library/react": "^16.1.0", | ||
"@testing-library/react": "^16.2.0", | ||
"@types/debug": "^4.1.12", | ||
@@ -88,0 +88,0 @@ "@types/lodash": "^4.17.13", |
@@ -28,2 +28,44 @@ import {isPortableTextTextBlock} from '@sanity/types' | ||
* @beta | ||
* Create markdown behaviors for common markdown actions such as converting ### to headings, --- to HRs, and more. | ||
* | ||
* @example | ||
* Configure the bundled markdown behaviors | ||
* ```ts | ||
* import {EditorProvider} from '@portabletext/editor' | ||
* import {createMarkdownBehaviors, coreBehaviors} from '@portabletext/editor/behaviors' | ||
* | ||
* function App() { | ||
* return ( | ||
* <EditorProvider | ||
* initialConfig={{ | ||
* behaviors: [ | ||
* ...coreBehaviors, | ||
* ...createMarkdownBehaviors({ | ||
* horizontalRuleObject: ({schema}) => { | ||
* const name = schema.blockObjects.find( | ||
* (object) => object.name === 'break', | ||
* )?.name | ||
* return name ? {name} : undefined | ||
* }, | ||
* defaultStyle: ({schema}) => schema.styles[0].value, | ||
* headingStyle: ({schema, level}) => | ||
* schema.styles.find((style) => style.value === `h${level}`) | ||
* ?.value, | ||
* blockquoteStyle: ({schema}) => | ||
* schema.styles.find((style) => style.value === 'blockquote') | ||
* ?.value, | ||
* unorderedListStyle: ({schema}) => | ||
* schema.lists.find((list) => list.value === 'bullet')?.value, | ||
* orderedListStyle: ({schema}) => | ||
* schema.lists.find((list) => list.value === 'number')?.value, | ||
* }), | ||
* ] | ||
* }} | ||
* > | ||
* {...} | ||
* </EditorProvider> | ||
* ) | ||
* } | ||
* ``` | ||
* | ||
*/ | ||
@@ -30,0 +72,0 @@ export function createMarkdownBehaviors(config: MarkdownBehaviorsConfig) { |
@@ -309,2 +309,17 @@ import type {KeyedSegment, PortableTextTextBlock} from '@sanity/types' | ||
* @beta | ||
* | ||
* @example | ||
* | ||
* ```tsx | ||
* const noLowerCaseA = defineBehavior({ | ||
* on: 'insert.text', | ||
* guard: ({event, context}) => event.text === 'a', | ||
* actions: [({event, context}) => [{type: 'insert.text', text: 'A'}]], | ||
* }) | ||
* ``` | ||
* | ||
* | ||
* | ||
* | ||
* | ||
*/ | ||
@@ -311,0 +326,0 @@ export function defineBehavior< |
@@ -31,2 +31,22 @@ import {Schema as SanitySchema} from '@sanity/schema' | ||
* @public | ||
* A helper wrapper that adds editor support, such as autocomplete and type checking, for a schema definition. | ||
* @example | ||
* ```ts | ||
* import { defineSchema } from '@portabletext/editor' | ||
* | ||
* const schemaDefinition = defineSchema({ | ||
* decorators: [{name: 'strong'}, {name: 'em'}, {name: 'underline'}], | ||
* annotations: [{name: 'link'}], | ||
* styles: [ | ||
* {name: 'normal'}, | ||
* {name: 'h1'}, | ||
* {name: 'h2'}, | ||
* {name: 'h3'}, | ||
* {name: 'blockquote'}, | ||
* ], | ||
* lists: [], | ||
* inlineObjects: [], | ||
* blockObjects: [], | ||
* } | ||
* ``` | ||
*/ | ||
@@ -54,3 +74,6 @@ export function defineSchema<const TSchemaDefinition extends SchemaDefinition>( | ||
name: blockObject.name === 'image' ? 'tmp-image' : blockObject.name, | ||
title: blockObject.title, | ||
title: | ||
blockObject.name === 'image' && blockObject.title === undefined | ||
? 'Image' | ||
: blockObject.title, | ||
fields: [], | ||
@@ -57,0 +80,0 @@ }), |
@@ -23,5 +23,2 @@ import type {Patch} from '@portabletext/patches' | ||
} from '../behaviors/behavior.types' | ||
import {toPortableTextRange} from '../internal-utils/ranges' | ||
import {fromSlateValue} from '../internal-utils/values' | ||
import {KEY_TO_VALUE_ELEMENT} from '../internal-utils/weakMaps' | ||
import type {OmitFromUnion, PickFromUnion} from '../type-utils' | ||
@@ -34,4 +31,3 @@ import type { | ||
import type {EditorSchema} from './define-schema' | ||
import type {EditorContext} from './editor-snapshot' | ||
import {getActiveDecorators} from './get-active-decorators' | ||
import {createEditorSnapshot} from './editor-snapshot' | ||
import {withApplyingBehaviorActions} from './with-applying-behavior-actions' | ||
@@ -347,23 +343,7 @@ | ||
const value = fromSlateValue( | ||
event.editor.children, | ||
context.schema.block.name, | ||
KEY_TO_VALUE_ELEMENT.get(event.editor), | ||
) | ||
const selection = toPortableTextRange( | ||
value, | ||
event.editor.selection, | ||
context.schema, | ||
) | ||
const editorContext = { | ||
activeDecorators: getActiveDecorators({ | ||
schema: context.schema, | ||
slateEditorInstance: event.editor, | ||
}), | ||
const editorSnapshot = createEditorSnapshot({ | ||
editor: event.editor, | ||
keyGenerator: context.keyGenerator, | ||
schema: context.schema, | ||
selection, | ||
value, | ||
} satisfies EditorContext | ||
}) | ||
@@ -376,3 +356,3 @@ let behaviorOverwritten = false | ||
eventBehavior.guard({ | ||
context: editorContext, | ||
context: editorSnapshot.context, | ||
event: event.behaviorEvent, | ||
@@ -387,3 +367,3 @@ }) | ||
actionSet( | ||
{context: editorContext, event: event.behaviorEvent}, | ||
{context: editorSnapshot.context, event: event.behaviorEvent}, | ||
shouldRun, | ||
@@ -390,0 +370,0 @@ ), |
@@ -20,2 +20,23 @@ import {useSelector} from '@xstate/react' | ||
* @public | ||
* Hook to select a value from the editor state. | ||
* @example | ||
* Pass a selector as the second argument | ||
* ```tsx | ||
* import { useEditorSelector } from '@portabletext/editor' | ||
* | ||
* function MyComponent(editor) { | ||
* const value = useEditorSelector(editor, selector) | ||
* } | ||
* ``` | ||
* @example | ||
* Pass an inline selector as the second argument. | ||
* In this case, use the editor context to obtain the schema. | ||
* ```tsx | ||
* import { useEditorSelector } from '@portabletext/editor' | ||
* | ||
* function MyComponent(editor) { | ||
* const schema = useEditorSelector(editor, (snapshot) => snapshot.context.schema) | ||
* } | ||
* ``` | ||
* @group Hooks | ||
*/ | ||
@@ -22,0 +43,0 @@ export function useEditorSelector<TSelected>( |
import type {PortableTextBlock} from '@sanity/types' | ||
import type {EditorSelection} from '../types/editor' | ||
import {toPortableTextRange} from '../internal-utils/ranges' | ||
import {fromSlateValue} from '../internal-utils/values' | ||
import {KEY_TO_VALUE_ELEMENT} from '../internal-utils/weakMaps' | ||
import type {EditorSelection, PortableTextSlateEditor} from '../types/editor' | ||
import type {EditorSchema} from './define-schema' | ||
import {getActiveDecorators} from './get-active-decorators' | ||
@@ -22,1 +26,33 @@ /** | ||
} | ||
export function createEditorSnapshot({ | ||
editor, | ||
keyGenerator, | ||
schema, | ||
}: { | ||
editor: PortableTextSlateEditor | ||
keyGenerator: () => string | ||
schema: EditorSchema | ||
}) { | ||
const value = fromSlateValue( | ||
editor.children, | ||
schema.block.name, | ||
KEY_TO_VALUE_ELEMENT.get(editor), | ||
) | ||
const selection = toPortableTextRange(value, editor.selection, schema) | ||
const context = { | ||
activeDecorators: getActiveDecorators({ | ||
schema, | ||
slateEditorInstance: editor, | ||
}), | ||
keyGenerator, | ||
schema, | ||
selection, | ||
value, | ||
} satisfies EditorContext | ||
return { | ||
context, | ||
} satisfies EditorSnapshot | ||
} |
@@ -12,2 +12,3 @@ export type {EditorSelector} from '../editor/editor-selector' | ||
export {getActiveStyle} from './selector.get-active-style' | ||
export {getSelectedSlice} from './selector.get-selected-slice' | ||
export {getSelectedSpans} from './selector.get-selected-spans' | ||
@@ -14,0 +15,0 @@ export {getSelectionText} from './selector.get-selection-text' |
@@ -12,1 +12,2 @@ export type {BlockOffset} from '../behaviors/behavior.types' | ||
export {reverseSelection} from './util.reverse-selection' | ||
export {sliceBlocks} from './util.slice-blocks' |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
3479994
195
49494