@examplary/ui 1.76.0 → 1.77.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/rich-text/index.d.ts +1 -0
- package/dist/components/rich-text/minimal-rich-text-field.d.ts +4 -1
- package/dist/components/rich-text/minimal-rich-text-field.js +3 -3
- package/dist/components/rich-text/tiptap/extensions.d.ts +1 -1
- package/dist/components/rich-text/tiptap/extensions.js +1 -1
- package/dist/components/rich-text/tiptap/image.d.ts +14 -0
- package/dist/components/rich-text/tiptap/rich-text-formatting-menu.d.ts +12 -1
- package/dist/components/rich-text/tiptap/rich-text-formatting-menu.js +23 -3
- package/package.json +1 -1
|
@@ -2,6 +2,7 @@ export { RichTextDisplay } from "./rich-text-display";
|
|
|
2
2
|
export { RichTextField } from "./rich-text-field";
|
|
3
3
|
export { RichTextToolbar } from "./rich-text-toolbar";
|
|
4
4
|
export { MinimalRichTextField, getEditorById } from "./minimal-rich-text-field";
|
|
5
|
+
export type { GraphEditorProps } from "./tiptap/rich-text-formatting-menu";
|
|
5
6
|
export { processFilesAsString } from "./tiptap/file-handler";
|
|
6
7
|
export { bubbleMenuVirtualElement } from "./tiptap/bubble-menu-virtual-element";
|
|
7
8
|
export * from "./tiptap/extensions";
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { ComponentType } from "react";
|
|
1
2
|
import { Editor, EditorContentProps } from "@tiptap/react";
|
|
2
3
|
import { CommentAuthor } from "tiptap-inline-comments";
|
|
3
4
|
import { XmlFragment } from "yjs";
|
|
5
|
+
import { GraphEditorProps } from "./tiptap/rich-text-formatting-menu";
|
|
4
6
|
export declare const getEditorById: (id: string) => Editor | undefined;
|
|
5
7
|
export type MinimalRichTextFieldProps = {
|
|
6
8
|
className?: string;
|
|
@@ -20,7 +22,8 @@ export type MinimalRichTextFieldProps = {
|
|
|
20
22
|
url: string;
|
|
21
23
|
name: string;
|
|
22
24
|
}>;
|
|
25
|
+
GraphEditor?: ComponentType<GraphEditorProps>;
|
|
23
26
|
fragment?: XmlFragment;
|
|
24
27
|
awareness?: any;
|
|
25
28
|
} & Omit<EditorContentProps, "editor">;
|
|
26
|
-
export declare const MinimalRichTextField: ({ className, value, defaultValue, placeholder, onChange, onBlur, slotBefore, style, singleLine, autoFocus, showFormattingMenu, commentAuthor, uploadFile, fragment, awareness, id, ...props }: MinimalRichTextFieldProps) => import("react/jsx-runtime").JSX.Element;
|
|
29
|
+
export declare const MinimalRichTextField: ({ className, value, defaultValue, placeholder, onChange, onBlur, slotBefore, style, singleLine, autoFocus, showFormattingMenu, commentAuthor, uploadFile, GraphEditor, fragment, awareness, id, ...props }: MinimalRichTextFieldProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -14,7 +14,7 @@ import { CommentBubble } from "./tiptap/comments/comment-bubble";
|
|
|
14
14
|
import { defaultRichTextExtensions } from "./tiptap/extensions";
|
|
15
15
|
import { fileHandler } from "./tiptap/file-handler";
|
|
16
16
|
import Image from "./tiptap/image";
|
|
17
|
-
import { RichTextFormattingMenu } from "./tiptap/rich-text-formatting-menu";
|
|
17
|
+
import { RichTextFormattingMenu, } from "./tiptap/rich-text-formatting-menu";
|
|
18
18
|
registerWebComponents();
|
|
19
19
|
const textEditors = new Map();
|
|
20
20
|
export const getEditorById = (id) => {
|
|
@@ -50,7 +50,7 @@ const isEmpty = (value) => {
|
|
|
50
50
|
}
|
|
51
51
|
return false;
|
|
52
52
|
};
|
|
53
|
-
export const MinimalRichTextField = ({ className = "", value = "", defaultValue, placeholder = "", onChange, onBlur, slotBefore, style, singleLine = false, autoFocus = false, showFormattingMenu = false, commentAuthor, uploadFile = undefined, fragment, awareness, id, ...props }) => {
|
|
53
|
+
export const MinimalRichTextField = ({ className = "", value = "", defaultValue, placeholder = "", onChange, onBlur, slotBefore, style, singleLine = false, autoFocus = false, showFormattingMenu = false, commentAuthor, uploadFile = undefined, GraphEditor, fragment, awareness, id, ...props }) => {
|
|
54
54
|
const [content, setContent] = useState(value);
|
|
55
55
|
const extensions = useMemo(() => [
|
|
56
56
|
...defaultRichTextExtensions,
|
|
@@ -132,5 +132,5 @@ export const MinimalRichTextField = ({ className = "", value = "", defaultValue,
|
|
|
132
132
|
}
|
|
133
133
|
};
|
|
134
134
|
}, [editor, id]);
|
|
135
|
-
return (_jsxs(_Fragment, { children: [slotBefore ? slotBefore(editor) : null, showFormattingMenu && (_jsx(RichTextFormattingMenu, { allowComments: !!commentAuthor, editor: editor })), !!commentAuthor && (_jsx(CommentBubble, { editor: editor, commentAuthor: commentAuthor })), _jsx(EditorContent, { editor: editor, ...props })] }));
|
|
135
|
+
return (_jsxs(_Fragment, { children: [slotBefore ? slotBefore(editor) : null, showFormattingMenu && (_jsx(RichTextFormattingMenu, { allowComments: !!commentAuthor, editor: editor, GraphEditor: GraphEditor })), !!commentAuthor && (_jsx(CommentBubble, { editor: editor, commentAuthor: commentAuthor })), _jsx(EditorContent, { editor: editor, ...props })] }));
|
|
136
136
|
};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export declare const defaultRichTextExtensions: (import("@tiptap/core").Mark<any, any> | import("@tiptap/core").Node<any, any> | import("@tiptap/core").Mark<import("@tiptap/extension-bold").BoldOptions, any> | import("@tiptap/core").Extension<import("@tiptap/starter-kit").StarterKitOptions, any> | import("@tiptap/core").Mark<import("@tiptap/extension-link").LinkOptions, any> | import("@tiptap/core").Extension<import("@tiptap/extension-typography").TypographyOptions, any> | import("@tiptap/core").Mark<import("@tiptap/extension-highlight").HighlightOptions, any> | import("@tiptap/core").Extension<import("@tiptap/extension-table").TableKitOptions, any>)[];
|
|
2
|
-
export declare const htmlRenderingRichTextExtensions: (import("@tiptap/core").Mark<any, any> | import("@tiptap/core").Node<any, any> | import("@tiptap/core").
|
|
2
|
+
export declare const htmlRenderingRichTextExtensions: (import("@tiptap/core").Mark<any, any> | import("@tiptap/core").Node<any, any> | import("@tiptap/core").Node<import("./image.js").ImageOptions, any> | import("@tiptap/core").Mark<import("@tiptap/extension-bold").BoldOptions, any> | import("@tiptap/core").Extension<import("@tiptap/starter-kit").StarterKitOptions, any> | import("@tiptap/core").Mark<import("@tiptap/extension-link").LinkOptions, any> | import("@tiptap/core").Extension<import("@tiptap/extension-typography").TypographyOptions, any> | import("@tiptap/core").Mark<import("@tiptap/extension-highlight").HighlightOptions, any> | import("@tiptap/core").Extension<import("@tiptap/extension-table").TableKitOptions, any> | import("@tiptap/core").Extension<import("tiptap-inline-comments").CommentOptions, any>)[];
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import Bold from "@tiptap/extension-bold";
|
|
2
2
|
import Document from "@tiptap/extension-document";
|
|
3
3
|
import Highlight from "@tiptap/extension-highlight";
|
|
4
|
-
import Image from "@tiptap/extension-image";
|
|
5
4
|
import Italic from "@tiptap/extension-italic";
|
|
6
5
|
import Link from "@tiptap/extension-link";
|
|
7
6
|
import { TableKit } from "@tiptap/extension-table";
|
|
@@ -10,6 +9,7 @@ import StarterKit from "@tiptap/starter-kit";
|
|
|
10
9
|
import { InlineComments } from "tiptap-inline-comments";
|
|
11
10
|
import ContentReference from "./content-reference.js";
|
|
12
11
|
import FileAttachment from "./file-attachment.js";
|
|
12
|
+
import Image from "./image.js";
|
|
13
13
|
import { Mathematics } from "./mathematics.js";
|
|
14
14
|
import PageClipping from "./page-clipping.js";
|
|
15
15
|
// Disable the markdown shortcuts (**bold**, __bold__, *italic*, _italic_):
|
|
@@ -20,6 +20,20 @@ export interface ImageOptions {
|
|
|
20
20
|
*/
|
|
21
21
|
HTMLAttributes: Record<string, any>;
|
|
22
22
|
}
|
|
23
|
+
declare module "@tiptap/core" {
|
|
24
|
+
interface Commands<ReturnType> {
|
|
25
|
+
image: {
|
|
26
|
+
setImage: (options: {
|
|
27
|
+
src: string;
|
|
28
|
+
alt?: string;
|
|
29
|
+
title?: string;
|
|
30
|
+
width?: number;
|
|
31
|
+
height?: number;
|
|
32
|
+
"data-graph"?: string;
|
|
33
|
+
}) => ReturnType;
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
}
|
|
23
37
|
/**
|
|
24
38
|
* Matches an image to a  on input.
|
|
25
39
|
*/
|
|
@@ -1,7 +1,18 @@
|
|
|
1
|
+
import { ComponentType } from "react";
|
|
1
2
|
import { Editor } from "@tiptap/core";
|
|
3
|
+
export type GraphEditorProps = {
|
|
4
|
+
graph: unknown;
|
|
5
|
+
onClose: () => void;
|
|
6
|
+
onSave: (image: {
|
|
7
|
+
src: string;
|
|
8
|
+
alt: string;
|
|
9
|
+
graph: unknown;
|
|
10
|
+
}) => void;
|
|
11
|
+
};
|
|
2
12
|
type RichTextFormattingMenuProps = {
|
|
3
13
|
editor: Editor;
|
|
4
14
|
allowComments?: boolean;
|
|
15
|
+
GraphEditor?: ComponentType<GraphEditorProps>;
|
|
5
16
|
};
|
|
6
|
-
export declare const RichTextFormattingMenu: ({ allowComments, editor, }: RichTextFormattingMenuProps) => import("react/jsx-runtime").JSX.Element | null;
|
|
17
|
+
export declare const RichTextFormattingMenu: ({ allowComments, editor, GraphEditor, }: RichTextFormattingMenuProps) => import("react/jsx-runtime").JSX.Element | null;
|
|
7
18
|
export {};
|
|
@@ -3,14 +3,15 @@ import { useCallback, useMemo, useState } from "react";
|
|
|
3
3
|
import { useTranslation } from "react-i18next";
|
|
4
4
|
import { useEditorState } from "@tiptap/react";
|
|
5
5
|
import { BubbleMenu } from "@tiptap/react/menus";
|
|
6
|
-
import { BoldIcon, CropIcon, HighlighterIcon, ItalicIcon, LinkIcon, ListIcon, MessageCircleIcon, SquareFunctionIcon, TextQuoteIcon, TrashIcon, } from "lucide-react";
|
|
6
|
+
import { BoldIcon, ChartLineIcon, CropIcon, HighlighterIcon, ItalicIcon, LinkIcon, ListIcon, MessageCircleIcon, SquareFunctionIcon, TextQuoteIcon, TrashIcon, } from "lucide-react";
|
|
7
7
|
import { bubbleMenuVirtualElement } from "./bubble-menu-virtual-element";
|
|
8
8
|
import { CropPageClippingModal } from "./crop-page-clipping-modal";
|
|
9
9
|
import { cn } from "../../../utils";
|
|
10
10
|
import { FloatingMenu } from "../../ui/floating-menu";
|
|
11
11
|
import { showPromptDialog } from "../../ui/prompt";
|
|
12
|
-
export const RichTextFormattingMenu = ({ allowComments, editor, }) => {
|
|
12
|
+
export const RichTextFormattingMenu = ({ allowComments, editor, GraphEditor, }) => {
|
|
13
13
|
const [pageClipping, setPageClipping] = useState(null);
|
|
14
|
+
const [graph, setGraph] = useState(null);
|
|
14
15
|
const { t } = useTranslation();
|
|
15
16
|
const setLink = useCallback(async () => {
|
|
16
17
|
if (editor.isActive("link")) {
|
|
@@ -55,6 +56,7 @@ export const RichTextFormattingMenu = ({ allowComments, editor, }) => {
|
|
|
55
56
|
isPageClipping: ctx.editor.isActive("page-clipping"),
|
|
56
57
|
isFileAttachment: ctx.editor.isActive("file-attachment"),
|
|
57
58
|
isImage: ctx.editor.isActive("image"),
|
|
59
|
+
isGraph: !!ctx.editor.getAttributes("image")?.["data-graph"],
|
|
58
60
|
isComment: allowComments ? ctx.editor.isActive("comment") : false,
|
|
59
61
|
}),
|
|
60
62
|
});
|
|
@@ -77,6 +79,13 @@ export const RichTextFormattingMenu = ({ allowComments, editor, }) => {
|
|
|
77
79
|
});
|
|
78
80
|
}
|
|
79
81
|
else if (state.isImage || state.isFileAttachment) {
|
|
82
|
+
if (state.isGraph && GraphEditor) {
|
|
83
|
+
items.push({
|
|
84
|
+
icon: ChartLineIcon,
|
|
85
|
+
label: t("formatting.graph.edit"),
|
|
86
|
+
action: () => setGraph(JSON.parse(editor.getAttributes("image")["data-graph"])),
|
|
87
|
+
});
|
|
88
|
+
}
|
|
80
89
|
items.push({
|
|
81
90
|
icon: TrashIcon,
|
|
82
91
|
label: t("formatting.delete"),
|
|
@@ -129,7 +138,7 @@ export const RichTextFormattingMenu = ({ allowComments, editor, }) => {
|
|
|
129
138
|
});
|
|
130
139
|
}
|
|
131
140
|
return items;
|
|
132
|
-
}, [state, setLink, t, allowComments, editor]);
|
|
141
|
+
}, [state, setLink, t, allowComments, editor, GraphEditor]);
|
|
133
142
|
if (!editor) {
|
|
134
143
|
return null;
|
|
135
144
|
}
|
|
@@ -140,5 +149,16 @@ export const RichTextFormattingMenu = ({ allowComments, editor, }) => {
|
|
|
140
149
|
.focus()
|
|
141
150
|
.updateAttributes("page-clipping", newParameters)
|
|
142
151
|
.run();
|
|
152
|
+
} })), GraphEditor && !!graph && (_jsx(GraphEditor, { graph: graph, onClose: () => setGraph(null), onSave: ({ src, alt, graph }) => {
|
|
153
|
+
setGraph(null);
|
|
154
|
+
editor
|
|
155
|
+
.chain()
|
|
156
|
+
.focus()
|
|
157
|
+
.updateAttributes("image", {
|
|
158
|
+
src,
|
|
159
|
+
alt,
|
|
160
|
+
"data-graph": JSON.stringify(graph),
|
|
161
|
+
})
|
|
162
|
+
.run();
|
|
143
163
|
} })), _jsx(BubbleMenu, { editor: editor, getReferencedVirtualElement: bubbleMenuVirtualElement(editor), children: _jsx(FloatingMenu, { className: "ml-2 flex items-center gap-0.5", children: actions.map((item, index) => (_jsx("button", { onClick: item.action, type: "button", title: item.label, "aria-label": item.label, className: cn("p-1 cursor-pointer flex items-center gap-1 hover:bg-zinc-100 rounded-md", item.active ? "bg-zinc-200" : ""), children: _jsx(item.icon, { className: "size-3.5 m-0.5" }) }, index))) }) })] }));
|
|
144
164
|
};
|