(
+ ({ onSuccess, onCancel }) => (
+ <>
+
+
+
+
+
+ >
+ ),
+ () => ,
+)
+
+
+export const LinkElement = (props: EditorRenderElementProps) => {
+ const editor = useEditor()
+ return (
+
+ {props.children}
+
+ (
+
+ )}
+ >
+
+
+
+
+
+
+
+ )
+}
diff --git a/packages/admin-sandbox/src/components/editorButton.sass b/packages/admin-sandbox/src/components/editorButton.sass
new file mode 100644
index 0000000000..2eefc0e168
--- /dev/null
+++ b/packages/admin-sandbox/src/components/editorButton.sass
@@ -0,0 +1,16 @@
+.editorButton
+ border-radius: 50%
+ width: 1.8em
+ height: 1.8em
+ background: white
+ border: 1px solid #e2e2ea
+ margin-left: .3em
+ font-size: .7rem
+ cursor: pointer
+ display: inline-flex
+ align-items: center
+ justify-content: center
+
+ &:focus
+ outline: none
+ background: #f2f2f2
diff --git a/packages/admin/src/components/bindingFacade/richText/blockEditor/BlockEditor.tsx b/packages/admin/src/components/bindingFacade/richText/blockEditor/BlockEditor.tsx
index 60661809f2..812a537769 100644
--- a/packages/admin/src/components/bindingFacade/richText/blockEditor/BlockEditor.tsx
+++ b/packages/admin/src/components/bindingFacade/richText/blockEditor/BlockEditor.tsx
@@ -34,7 +34,7 @@ import {
ToolbarButtonSpec,
} from '../toolbars'
import { BlockHoveringToolbarContents, BlockHoveringToolbarContentsProps } from './BlockHoveringToolbarContents'
-import { initBlockEditor } from './editor'
+import { EditorWithBlocks, initBlockEditor } from './editor'
import type { EmbedHandler } from './embed'
import type { FieldBackedElement } from './FieldBackedElement'
import { useCreateElementReference } from './references'
@@ -46,7 +46,7 @@ import { useBlockEditorState } from './state/useBlockEditorState'
import { ContentOutlet, ContentOutletProps, useEditorReferenceBlocks } from './templating'
import { useReferentiallyStableCallback } from './useReferentiallyStableCallback'
-export interface BlockEditorProps extends SugaredRelativeEntityList, CreateEditorPublicOptions {
+export interface BlockEditorProps extends SugaredRelativeEntityList, CreateEditorPublicOptions {
label: string
contentField: SugaredFieldProps['field']
sortableBy: SugaredFieldProps['field']
diff --git a/packages/admin/src/components/bindingFacade/richText/blockEditor/editor/initBlockEditor.ts b/packages/admin/src/components/bindingFacade/richText/blockEditor/editor/initBlockEditor.ts
index 558a9a3bee..95a6ea7bb0 100644
--- a/packages/admin/src/components/bindingFacade/richText/blockEditor/editor/initBlockEditor.ts
+++ b/packages/admin/src/components/bindingFacade/richText/blockEditor/editor/initBlockEditor.ts
@@ -20,7 +20,7 @@ export interface CreateEditorOptions
ReferenceElementOptions,
OverrideInsertDataOptions,
OverrideInsertElementWithReferenceOptions,
- CreateEditorPublicOptions {}
+ CreateEditorPublicOptions {}
export const initBlockEditor = ({ editor, ...options }: CreateEditorOptions & { editor: Editor }) => {
if (options.plugins && options.plugins.indexOf(paragraphElementType) === -1) {
diff --git a/packages/admin/src/components/bindingFacade/richText/editorFactory/createEditor.ts b/packages/admin/src/components/bindingFacade/richText/editorFactory/createEditor.ts
index 904e7bcc32..5ae2f20093 100644
--- a/packages/admin/src/components/bindingFacade/richText/editorFactory/createEditor.ts
+++ b/packages/admin/src/components/bindingFacade/richText/editorFactory/createEditor.ts
@@ -18,10 +18,10 @@ import {
} from '../plugins'
import type { BuiltinEditorPlugins } from './BuiltinEditorPlugins'
import { defaultEditorPluginPreset } from './presets'
-import { Editor as SlateEditor } from 'slate'
+import { Editor, Editor as SlateEditor } from 'slate'
const pluginAugmenters: {
- [pluginName in BuiltinEditorPlugins]: (editor: SlateEditor) => SlateEditor
+ [pluginName in BuiltinEditorPlugins]: (editor: E) => E
} = {
anchor: withAnchors,
paragraph: withParagraphs,
@@ -40,15 +40,15 @@ const pluginAugmenters: {
underline: withUnderline,
}
-export interface CreateEditorPublicOptions {
+export interface CreateEditorPublicOptions {
plugins?: BuiltinEditorPlugins[]
- augmentEditor?: (baseEditor: SlateEditor) => SlateEditor
- augmentEditorBuiltins?: (editor: SlateEditor) => SlateEditor
+ augmentEditor?: (baseEditor: Editor) => Editor | void
+ augmentEditorBuiltins?: (editor: E) => E | void
}
-export interface CreateEditorOptions extends CreateEditorPublicOptions {
+export interface CreateEditorOptions extends CreateEditorPublicOptions {
defaultElementType: string
- addEditorBuiltins: (augmentedBaseEditor: SlateEditor) => SlateEditor
+ addEditorBuiltins: (augmentedBaseEditor: SlateEditor) => E | void
}
export const createEditor = ({
@@ -63,19 +63,19 @@ export const createEditor = ({
}
-export const initializeEditor = ({
+export const initializeEditor = ({
editor,
plugins = defaultEditorPluginPreset,
augmentEditorBuiltins = identityFunction,
addEditorBuiltins,
augmentEditor = identityFunction,
-}: Omit & {editor: SlateEditor}) => {
+}: Omit, 'defaultElementType'> & {editor: Editor}): E => {
for (const plugin of new Set(plugins)) {
editor = pluginAugmenters[plugin](editor)
}
- const withAugmentedBase = augmentEditor(editor)
- const withBuiltins = addEditorBuiltins(withAugmentedBase)
+ const withAugmentedBase = augmentEditor(editor) ?? editor
+ const withBuiltins = addEditorBuiltins(withAugmentedBase) ?? (withAugmentedBase as E)
- return augmentEditorBuiltins(withBuiltins)
+ return augmentEditorBuiltins(withBuiltins) ?? withBuiltins
}
diff --git a/packages/admin/src/components/bindingFacade/richText/plugins/element/lists/withLists.ts b/packages/admin/src/components/bindingFacade/richText/plugins/element/lists/withLists.ts
index a65ff108e6..d59782400a 100644
--- a/packages/admin/src/components/bindingFacade/richText/plugins/element/lists/withLists.ts
+++ b/packages/admin/src/components/bindingFacade/richText/plugins/element/lists/withLists.ts
@@ -15,7 +15,7 @@ import { unorderedListElementPlugin } from './UnorderedListElement'
import { isListElement } from './ListElement'
import { listHtmlDeserializerFactory } from './ListHtmlDeserializer'
-export const withLists = (editor: E): Editor => {
+export const withLists = (editor: E): E => {
const {
insertBreak,
onKeyDown,
diff --git a/packages/admin/src/components/bindingFacade/richText/slate-reexport.ts b/packages/admin/src/components/bindingFacade/richText/slate-reexport.ts
index f1c397628a..6ea5ed92fc 100644
--- a/packages/admin/src/components/bindingFacade/richText/slate-reexport.ts
+++ b/packages/admin/src/components/bindingFacade/richText/slate-reexport.ts
@@ -1,3 +1,6 @@
import { Editor } from 'slate'
+import { useSlateStatic } from 'slate-react'
+
export { Transforms as EditorTransforms } from 'slate'
export const EditorUtils = Editor
+export const useEditor = useSlateStatic
diff --git a/packages/admin/src/components/bindingFacade/richText/slate-types.ts b/packages/admin/src/components/bindingFacade/richText/slate-types.ts
index 5fd7ce5609..f5e950197d 100644
--- a/packages/admin/src/components/bindingFacade/richText/slate-types.ts
+++ b/packages/admin/src/components/bindingFacade/richText/slate-types.ts
@@ -1,4 +1,4 @@
-import { BaseEditor, Descendant } from 'slate'
+import { BaseEditor, Descendant, Selection, Point, Range, Ancestor, Path } from 'slate'
import { EditorWithEssentials } from './baseEditor'
import { ReactEditor, RenderElementProps } from 'slate-react'
import { HistoryEditor } from 'slate-history'
@@ -17,6 +17,11 @@ export type EditorText = {
}
export type EditorDescendant = Descendant
+export type EditorAncestor = Ancestor
+export type EditorSelection = Selection
+export type EditorRange = Range
+export type EditorPath = Path
+export type EditorPoint = Point
export type EditorRenderElementProps = RenderElementProps
declare module 'slate' {
diff --git a/packages/admin/src/components/bindingFacade/richText/toolbars/HoveringToolbarContents.tsx b/packages/admin/src/components/bindingFacade/richText/toolbars/HoveringToolbarContents.tsx
index c38c87dafc..515ae10594 100644
--- a/packages/admin/src/components/bindingFacade/richText/toolbars/HoveringToolbarContents.tsx
+++ b/packages/admin/src/components/bindingFacade/richText/toolbars/HoveringToolbarContents.tsx
@@ -5,6 +5,8 @@ import { Transforms } from 'slate'
import { useSlate } from 'slate-react'
import type { EditorWithBlocks } from '../blockEditor'
import type { ToolbarButtonSpec } from './ToolbarButtonSpec'
+import { EditorTransforms } from '../slate-reexport'
+import { referenceElementType } from '../blockEditor'
export interface HoveringToolbarContentsProps {
buttons: ToolbarButtonSpec[] | ToolbarButtonSpec[][]
@@ -69,7 +71,26 @@ export const HoveringToolbarContents = memo(({ buttons: rawButtons }: HoveringTo
referenceId={reference.id}
editor={editor}
selection={selection}
- onSuccess={() => props.resolve(undefined)}
+ onSuccess={({ createElement } = {}) => {
+ if (createElement !== undefined) {
+ if (!selection) {
+ return
+ }
+ EditorTransforms.select(editor, selection)
+ EditorTransforms.wrapNodes(
+ editor,
+ {
+ type: referenceElementType,
+ children: [{ text: '' }],
+ referenceId: reference.id,
+ ...createElement,
+ },
+ { split: true },
+ )
+ EditorTransforms.collapse(editor, { edge: 'end' })
+ }
+ props.resolve(undefined)
+ }}
onCancel={() => props.reject()}
/>
diff --git a/packages/admin/src/components/bindingFacade/richText/toolbars/ToolbarButtonSpec.ts b/packages/admin/src/components/bindingFacade/richText/toolbars/ToolbarButtonSpec.ts
index d41c1d4a93..5cfeb8678b 100644
--- a/packages/admin/src/components/bindingFacade/richText/toolbars/ToolbarButtonSpec.ts
+++ b/packages/admin/src/components/bindingFacade/richText/toolbars/ToolbarButtonSpec.ts
@@ -20,7 +20,7 @@ export interface InitializeReferenceContentProps {
referenceId: string
editor: EditorWithBlocks
selection: SlateRange | null
- onSuccess: () => void
+ onSuccess: (options?: { createElement?: Partial }) => void
onCancel: () => void
}