diff --git a/packages/react-dsfr-tiptap/src/components/Loader.tsx b/packages/react-dsfr-tiptap/src/components/Loader.tsx index a598ea6..1ea14a2 100644 --- a/packages/react-dsfr-tiptap/src/components/Loader.tsx +++ b/packages/react-dsfr-tiptap/src/components/Loader.tsx @@ -1,9 +1,9 @@ -import { LazyExoticComponent, ReactNode, useEffect, useMemo, useState } from "react"; +import { ReactNode, useEffect, useMemo, useState } from "react"; import { AnyExtension } from "@tiptap/react"; import StarterKit from "@tiptap/starter-kit"; import { Control } from "../types/controls"; -import { richTextEditorControls } from "../utils/controls"; +import { ControlComponent, richTextEditorControls } from "../utils/controls"; import RichTextEditorContent from "./Content"; import RichTextEditorMenu from "./Menu"; @@ -24,8 +24,8 @@ export type Extension = | "youtube"; export interface ILoaderProps extends Omit { - controlMap?: Partial ReactNode) | LazyExoticComponent<() => ReactNode>>>; - controls: (Control | (() => ReactNode) | LazyExoticComponent<() => ReactNode>)[][]; + controlMap?: Partial>; + controls: (Control | ControlComponent)[][]; extensionLoader?: Partial Promise>>; menu?: "top" | "bottom"; } diff --git a/packages/react-dsfr-tiptap/src/components/MarkdownEditor.tsx b/packages/react-dsfr-tiptap/src/components/MarkdownEditor.tsx index 7586f89..489dde1 100644 --- a/packages/react-dsfr-tiptap/src/components/MarkdownEditor.tsx +++ b/packages/react-dsfr-tiptap/src/components/MarkdownEditor.tsx @@ -1,9 +1,9 @@ -import { LazyExoticComponent, ReactNode } from "react"; +import { ReactNode } from "react"; import { EditorEvents } from "@tiptap/react"; import { markdownEditorDefaultControls, markdownEditorDefaultExtensions } from "../constants/markdownEditor"; import { MarkdownControl } from "../types/controls"; -import { markdownControls } from "../utils/controls"; +import { ControlComponent, markdownControls } from "../utils/controls"; import RichTextEditorProvider from "./Provider"; import RichTextEditorLoader, { ILoaderProps } from "./Loader"; @@ -12,12 +12,12 @@ import RichTextEditorContent from "./Content"; import RichTextEditorGroup from "./Group"; export interface IMarkdownEditorProps extends Omit { - controls?: (MarkdownControl | (() => ReactNode) | LazyExoticComponent<() => ReactNode>)[][]; + controls?: (MarkdownControl | ControlComponent)[][]; onContentUpdate?: (content: string) => void; } type MarkdownControls = { - [key in MarkdownControl]: (() => ReactNode) | LazyExoticComponent<() => ReactNode>; + [key in MarkdownControl]: ControlComponent; }; interface IMarkdownEditor extends MarkdownControls { diff --git a/packages/react-dsfr-tiptap/src/components/RichTextEditor.tsx b/packages/react-dsfr-tiptap/src/components/RichTextEditor.tsx index 970f066..0c8bbd5 100644 --- a/packages/react-dsfr-tiptap/src/components/RichTextEditor.tsx +++ b/packages/react-dsfr-tiptap/src/components/RichTextEditor.tsx @@ -1,9 +1,9 @@ -import { LazyExoticComponent, ReactNode } from "react"; +import { ReactNode } from "react"; import { EditorEvents } from "@tiptap/react"; import { richTextEditorDefaultControls, richTextEditorDefaultExtensions } from "../constants/richTextEditor"; import { Control } from "../types/controls"; -import { richTextEditorControls } from "../utils/controls"; +import { ControlComponent, richTextEditorControls } from "../utils/controls"; import RichTextEditorProvider from "./Provider"; import RichTextEditorLoader, { ILoaderProps } from "./Loader"; @@ -12,12 +12,12 @@ import RichTextEditorMenu from "./Menu"; import RichTextEditorGroup from "./Group"; export interface IRichTextEditorProps extends Omit { - controls?: (Control | (() => ReactNode) | LazyExoticComponent<() => ReactNode>)[][]; + controls?: (Control | ControlComponent)[][]; onContentUpdate?: (content: string) => void; } type RichTextEditorControls = { - [key in Control]: (() => ReactNode) | LazyExoticComponent<() => ReactNode>; + [key in Control]: ControlComponent; }; interface IRichTextEditor extends RichTextEditorControls { diff --git a/packages/react-dsfr-tiptap/src/controls/createControls.tsx b/packages/react-dsfr-tiptap/src/controls/createControls.tsx index ab162f4..349bc36 100644 --- a/packages/react-dsfr-tiptap/src/controls/createControls.tsx +++ b/packages/react-dsfr-tiptap/src/controls/createControls.tsx @@ -13,12 +13,13 @@ interface IEditorState { interface ICreateCustomControlProps { Control: (editor: Editor, editorState: IEditorState, ref: RefObject) => ReactNode; DialogContent?: ElementType; + container?: Element | DocumentFragment; isActive?: { name: string; attributes?: Record | string }; isDisabled?: (editor: Editor) => boolean; } export function createCustomControl(configuration: ICreateCustomControlProps) { - const { Control, DialogContent, isActive, isDisabled } = configuration; + const { Control, DialogContent, container, isActive, isDisabled } = configuration; return function CustomControl(): ReactNode { const editor = useEditor(); const ref = useRef(null); @@ -34,7 +35,7 @@ export function createCustomControl(configuration: ICreateCustomControlProps) { <> {Control(editor, editorState, ref)} {DialogContent && ( - + )} diff --git a/packages/react-dsfr-tiptap/src/dialogs/Dialog.tsx b/packages/react-dsfr-tiptap/src/dialogs/Dialog.tsx index cbdb405..92ab048 100644 --- a/packages/react-dsfr-tiptap/src/dialogs/Dialog.tsx +++ b/packages/react-dsfr-tiptap/src/dialogs/Dialog.tsx @@ -1,6 +1,7 @@ import { forwardRef, ReactNode, useCallback, useId, useImperativeHandle, useMemo, useRef } from "react"; import { createModal } from "@codegouvfr/react-dsfr/Modal/index.js"; import { useIsModalOpen } from "@codegouvfr/react-dsfr/Modal/useIsModalOpen.js"; +import { createPortal } from "react-dom"; import { dialogContext } from "../contexts/dialog"; @@ -9,12 +10,13 @@ export interface IDialogHandle { open: () => void; } -interface IDialogProps { +export interface IDialogProps { children: ReactNode; + container?: Element | DocumentFragment; } const Dialog = forwardRef((props, ref) => { - const { children } = props; + const { children, container = document.body } = props; const id = useId(); const { current: modal } = useRef( @@ -45,7 +47,7 @@ const Dialog = forwardRef((props, ref) => { [close, isOpened, modal] ); - return {children}; + return {createPortal(children, container)}; }); export default Dialog; diff --git a/packages/react-dsfr-tiptap/src/utils/controls.ts b/packages/react-dsfr-tiptap/src/utils/controls.ts index dc1d098..1ce9db8 100644 --- a/packages/react-dsfr-tiptap/src/utils/controls.ts +++ b/packages/react-dsfr-tiptap/src/utils/controls.ts @@ -33,7 +33,9 @@ import { } from "../controls/Controls"; import { ControlColor } from "../controls/CustomControls"; -export const markdownControls: Record, (() => ReactNode) | LazyExoticComponent<() => ReactNode>> = { +export type ControlComponent = (() => ReactNode) | LazyExoticComponent<() => ReactNode>; + +export const markdownControls: Record, ControlComponent> = { Blockquote: ControlBlockquote, Bold: ControlBold, BulletList: ControlBulletList, @@ -55,7 +57,7 @@ export const markdownControls: Record, ( Undo: ControlUndo, }; -export const richTextEditorControls: Record, (() => ReactNode) | LazyExoticComponent<() => ReactNode>> = { +export const richTextEditorControls: Record, ControlComponent> = { ...markdownControls, AlignCenter: ControlAlignCenter, AlignJustify: ControlAlignJustify,