diff --git a/apps/docs/astro.config.mjs b/apps/docs/astro.config.mjs index bd567c55c..fb65da6e2 100644 --- a/apps/docs/astro.config.mjs +++ b/apps/docs/astro.config.mjs @@ -3,7 +3,13 @@ import starlight from '@astrojs/starlight' import tailwind from '@astrojs/tailwind' import {defineConfig} from 'astro/config' import starlightLinksValidator from 'starlight-links-validator' -import starlightTypeDoc, {typeDocSidebarGroup} from 'starlight-typedoc' +import {createStarlightTypeDocPlugin} from 'starlight-typedoc' + +const [editorTypeDoc, editorTypeDocSidebar] = createStarlightTypeDocPlugin() +const [behaviorTypeDoc, behaviorTypeDocSidebar] = createStarlightTypeDocPlugin() +const [selectorsTypeDoc, selectorsTypeDocSidebar] = + createStarlightTypeDocPlugin() +const tsconfig = '../../packages/editor/tsconfig.json' // https://astro.build/config export default defineConfig({ @@ -58,9 +64,31 @@ export default defineConfig({ }, { label: 'Reference', - autogenerate: {directory: 'reference'}, + collapsed: true, + items: [ + { + label: 'Editor', + items: [ + {label: 'Overview', slug: 'reference/editor'}, + {...editorTypeDocSidebar, badge: 'Generated'}, + ], + }, + { + label: 'Behaviors', + items: [ + {label: 'Overview', slug: 'reference/behavior-api'}, + {...behaviorTypeDocSidebar, badge: 'Generated'}, + ], + }, + { + label: 'Selectors', + items: [ + {label: 'Overview', slug: 'reference/selectors'}, + {...selectorsTypeDocSidebar, badge: 'Generated'}, + ], + }, + ], }, - typeDocSidebarGroup, { label: 'Integrations', autogenerate: {directory: 'integrations'}, @@ -71,9 +99,38 @@ export default defineConfig({ }, ], plugins: [ - starlightTypeDoc({ + editorTypeDoc({ entryPoints: ['../../packages/editor/src/index.ts'], - tsconfig: '../../packages/editor/tsconfig.json', + output: 'api/editor', + typeDoc: { + excludeReferences: true, + }, + sidebar: { + collapsed: true, + }, + tsconfig, + }), + behaviorTypeDoc({ + entryPoints: ['../../packages/editor/src/behaviors/index.ts'], + output: 'api/behaviors', + typeDoc: { + excludeReferences: true, + }, + sidebar: { + collapsed: true, + }, + tsconfig, + }), + selectorsTypeDoc({ + entryPoints: ['../../packages/editor/src/selectors/index.ts'], + output: 'api/selectors', + typeDoc: { + excludeReferences: true, + }, + sidebar: { + collapsed: true, + }, + tsconfig, }), ...(process.env.CHECK_LINKS ? [starlightLinksValidator()] : []), ], diff --git a/apps/docs/src/content/docs/reference/behavior-api.mdx b/apps/docs/src/content/docs/reference/behavior-api.mdx index b37505027..6ff802473 100644 --- a/apps/docs/src/content/docs/reference/behavior-api.mdx +++ b/apps/docs/src/content/docs/reference/behavior-api.mdx @@ -1,5 +1,5 @@ --- -title: Behavior API +title: Behavior API Overview description: Reference documentation for the Behavior API. --- diff --git a/apps/docs/src/content/docs/reference/hooks.mdx b/apps/docs/src/content/docs/reference/editor.mdx similarity index 70% rename from apps/docs/src/content/docs/reference/hooks.mdx rename to apps/docs/src/content/docs/reference/editor.mdx index eefe7235c..89671427f 100644 --- a/apps/docs/src/content/docs/reference/hooks.mdx +++ b/apps/docs/src/content/docs/reference/editor.mdx @@ -1,8 +1,12 @@ --- -title: Hooks -description: Hooks reference +title: Editor API Overview +description: Editor API reference overview --- +The editor API provides access to the editor context and selectors for deriving state. + +Use the following hooks to access the editor from within your components. + ## `useEditor` Access the editor context. Commonly used when building toolbars or passing context to selectors. diff --git a/apps/docs/src/content/docs/reference/selectors.mdx b/apps/docs/src/content/docs/reference/selectors.mdx index 5d31b23c4..d4cffd87e 100644 --- a/apps/docs/src/content/docs/reference/selectors.mdx +++ b/apps/docs/src/content/docs/reference/selectors.mdx @@ -1,5 +1,5 @@ --- -title: Selectors +title: Selectors API Overview description: Selectors reference prev: false next: false diff --git a/packages/editor/package.config.ts b/packages/editor/package.config.ts index ce1a898b9..51cc847dd 100644 --- a/packages/editor/package.config.ts +++ b/packages/editor/package.config.ts @@ -17,6 +17,16 @@ export default defineConfig({ allowMultiple: true, syntaxKind: 'block', }, + { + name: 'group', + allowMultiple: true, + syntaxKind: 'block', + }, + { + name: 'groupDescription', + allowMultiple: true, + syntaxKind: 'block', + }, ], rules: { // Disable rules for now diff --git a/packages/editor/src/behaviors/behavior.markdown.ts b/packages/editor/src/behaviors/behavior.markdown.ts index ce0e0ac4f..ab944a8f5 100644 --- a/packages/editor/src/behaviors/behavior.markdown.ts +++ b/packages/editor/src/behaviors/behavior.markdown.ts @@ -25,6 +25,48 @@ export type MarkdownBehaviorsConfig = { /** * @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 ( + * { + * 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, + * }), + * ] + * }} + * > + * {...} + * + * ) + * } + * ``` + * */ export function createMarkdownBehaviors(config: MarkdownBehaviorsConfig) { const automaticBlockquoteOnSpace = defineBehavior({ diff --git a/packages/editor/src/behaviors/behavior.types.ts b/packages/editor/src/behaviors/behavior.types.ts index 541bd5e91..a3294db24 100644 --- a/packages/editor/src/behaviors/behavior.types.ts +++ b/packages/editor/src/behaviors/behavior.types.ts @@ -306,6 +306,21 @@ export type BehaviorActionIntendSet = ( /** * @beta + * + * @example + * + * ```tsx + * const noLowerCaseA = defineBehavior({ + * on: 'insert.text', + * guard: ({event, context}) => event.text === 'a', + * actions: [({event, context}) => [{type: 'insert.text', text: 'A'}]], + * }) + * ``` + * + * + * + * + * */ export function defineBehavior< TPayload extends Record, diff --git a/packages/editor/src/editor/Editable.tsx b/packages/editor/src/editor/Editable.tsx index 11966d0f4..4bce2e373 100644 --- a/packages/editor/src/editor/Editable.tsx +++ b/packages/editor/src/editor/Editable.tsx @@ -113,6 +113,23 @@ export type PortableTextEditableProps = Omit< /** * @public + * + * + * The core component that renders the editor. Must be placed within the {@link EventProvider} component. + * + * @example + * ```tsx + * import { PortableTextEditable, EditorProvider } from '@portabletext/editor' + * + * function MyComponent() { + * return ( + * + * + * + * ) + * } + * ``` + * @group Components */ export const PortableTextEditable = forwardRef< Omit, diff --git a/packages/editor/src/editor/define-schema.ts b/packages/editor/src/editor/define-schema.ts index 8833b49e5..4d26de50c 100644 --- a/packages/editor/src/editor/define-schema.ts +++ b/packages/editor/src/editor/define-schema.ts @@ -28,6 +28,26 @@ export type SchemaDefinition< /** * @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: [], + * } + * ``` */ export function defineSchema( definition: TSchemaDefinition, diff --git a/packages/editor/src/editor/editor-event-listener.tsx b/packages/editor/src/editor/editor-event-listener.tsx index 3e00fc424..8017deca8 100644 --- a/packages/editor/src/editor/editor-event-listener.tsx +++ b/packages/editor/src/editor/editor-event-listener.tsx @@ -5,6 +5,51 @@ import {useEditor} from './editor-provider' /** * @public + * Listen for events emitted by the editor. Must be used inside `EditorProvider`. Events available include: + * - 'blurred' + * - 'done loading' + * - 'editable' + * - 'error' + * - 'focused' + * - 'invalid value' + * - 'loading' + * - 'mutation' + * - 'patch' + * - 'read only' + * - 'ready' + * - 'selection' + * - 'value changed' + * + * @example + * Listen and log events. + * ```tsx + * import {EditorEventListener, EditorProvider} from '@portabletext/editor' + * + * function MyComponent() { + * return ( + * + * { + * console.log(event) + * } + * } /> + * { ... } + * + * ) + * } + * ``` + * @example + * Handle events when there is a mutation. + * ```tsx + * { + * if (event.type === 'mutation') { + * console.log('Value changed:', event.snapshot) + * } + * }} + * /> + * ``` + * @group Components */ export function EditorEventListener(props: { on: (event: EditorEmittedEvent) => void diff --git a/packages/editor/src/editor/editor-provider.tsx b/packages/editor/src/editor/editor-provider.tsx index 8af1cbebe..2c88dbbec 100644 --- a/packages/editor/src/editor/editor-provider.tsx +++ b/packages/editor/src/editor/editor-provider.tsx @@ -23,6 +23,21 @@ export type EditorProviderProps = { /** * @public + * The EditorProvider component is used to set up the editor context and configure the Portable Text Editor. + * @example + * ```tsx + * import {EditorProvider} from '@portabletext/editor' + * + * function App() { + * return ( + * + * ... + * + * ) + * } + * + * ``` + * @group Components */ export function EditorProvider(props: EditorProviderProps) { const editor = useCreateEditor(props.initialConfig) @@ -66,6 +81,18 @@ export function EditorProvider(props: EditorProviderProps) { /** * @public + * Get the current editor context from the `EditorProvider`. + * Must be used inside the `EditorProvider` component. + * @returns The current editor object. + * @example + * ```tsx + * import { useEditor } from '@portabletext/editor' + * + * function MyComponent() { + * const editor = useEditor() + * } + * ``` + * @group Hooks */ export function useEditor() { const editor = React.useContext(EditorContext) diff --git a/packages/editor/src/editor/editor-selector.ts b/packages/editor/src/editor/editor-selector.ts index dacfcd305..583dcdc58 100644 --- a/packages/editor/src/editor/editor-selector.ts +++ b/packages/editor/src/editor/editor-selector.ts @@ -17,6 +17,27 @@ export type EditorSelector = (snapshot: EditorSnapshot) => TSelected /** * @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 */ export function useEditorSelector( editor: Editor,