@examplary/ui 0.0.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/README.md +3 -0
- package/dist/components/button.d.ts +11 -0
- package/dist/components/button.js +58 -0
- package/dist/components/input.d.ts +4 -0
- package/dist/components/input.js +31 -0
- package/dist/components/rich-text/index.d.ts +5 -0
- package/dist/components/rich-text/index.js +5 -0
- package/dist/components/rich-text/minimal-rich-text-field.d.ts +17 -0
- package/dist/components/rich-text/minimal-rich-text-field.js +99 -0
- package/dist/components/rich-text/rich-text-display.d.ts +13 -0
- package/dist/components/rich-text/rich-text-display.js +38 -0
- package/dist/components/rich-text/rich-text-input.d.ts +14 -0
- package/dist/components/rich-text/rich-text-input.js +31 -0
- package/dist/components/rich-text/rich-text-toolbar.d.ts +3 -0
- package/dist/components/rich-text/rich-text-toolbar.js +33 -0
- package/dist/components/rich-text/tiptap/file-attachment.d.ts +3 -0
- package/dist/components/rich-text/tiptap/file-attachment.js +40 -0
- package/dist/components/rich-text/tiptap/file-handler.d.ts +4 -0
- package/dist/components/rich-text/tiptap/file-handler.js +196 -0
- package/dist/components/rich-text/tiptap/image.d.ts +51 -0
- package/dist/components/rich-text/tiptap/image.js +88 -0
- package/dist/components/rich-text/tiptap/page-clipping.d.ts +3 -0
- package/dist/components/rich-text/tiptap/page-clipping.js +54 -0
- package/dist/components/rich-text/tiptap/png-scanner.d.ts +6 -0
- package/dist/components/rich-text/tiptap/png-scanner.js +208 -0
- package/dist/components/rich-text/tiptap/rich-text-formatting-menu.d.ts +3 -0
- package/dist/components/rich-text/tiptap/rich-text-formatting-menu.js +34 -0
- package/dist/components/web-components/file-attachment.d.ts +12 -0
- package/dist/components/web-components/file-attachment.js +40 -0
- package/dist/components/web-components/index.d.ts +3 -0
- package/dist/components/web-components/index.js +12 -0
- package/dist/components/web-components/page-clipping.d.ts +4 -0
- package/dist/components/web-components/page-clipping.js +41 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +5 -0
- package/dist/utils.d.ts +1 -0
- package/dist/utils.js +9 -0
- package/package.json +40 -0
package/README.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { type VariantProps } from "class-variance-authority";
|
|
3
|
+
declare const buttonVariants: (props?: {
|
|
4
|
+
variant?: "default" | "transparent" | "primary" | "noShadow" | "neutral" | "simple" | "pressed" | "reverse";
|
|
5
|
+
size?: "default" | "sm" | "lg" | "icon";
|
|
6
|
+
} & import("class-variance-authority/types").ClassProp) => string;
|
|
7
|
+
export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
|
|
8
|
+
asChild?: boolean;
|
|
9
|
+
}
|
|
10
|
+
declare const Button: React.ForwardRefExoticComponent<ButtonProps & React.RefAttributes<HTMLButtonElement>>;
|
|
11
|
+
export { Button, buttonVariants };
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
var __assign = (this && this.__assign) || function () {
|
|
2
|
+
__assign = Object.assign || function(t) {
|
|
3
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
4
|
+
s = arguments[i];
|
|
5
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
6
|
+
t[p] = s[p];
|
|
7
|
+
}
|
|
8
|
+
return t;
|
|
9
|
+
};
|
|
10
|
+
return __assign.apply(this, arguments);
|
|
11
|
+
};
|
|
12
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
13
|
+
var t = {};
|
|
14
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
15
|
+
t[p] = s[p];
|
|
16
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
17
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
18
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
19
|
+
t[p[i]] = s[p[i]];
|
|
20
|
+
}
|
|
21
|
+
return t;
|
|
22
|
+
};
|
|
23
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
24
|
+
import * as React from "react";
|
|
25
|
+
import { Slot } from "@radix-ui/react-slot";
|
|
26
|
+
import { cva } from "class-variance-authority";
|
|
27
|
+
import { cn } from "../utils";
|
|
28
|
+
var buttonVariants = cva("inline-flex font-medium cursor-pointer items-center text-text justify-center whitespace-nowrap rounded-base text-sm font-base ring-offset-white transition-all gap-2 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-black focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", {
|
|
29
|
+
variants: {
|
|
30
|
+
variant: {
|
|
31
|
+
default: "bg-white border-2 border-border dark:border-darkBorder shadow-light dark:shadow-dark hover:translate-x-boxShadowX hover:translate-y-boxShadowY hover:shadow-none dark:hover:shadow-none",
|
|
32
|
+
transparent: "border-2 border-border dark:border-darkBorder shadow-light dark:shadow-dark hover:translate-x-boxShadowX hover:translate-y-boxShadowY hover:shadow-none dark:hover:shadow-none",
|
|
33
|
+
primary: "bg-bright border-2 border-border dark:border-darkBorder shadow-light dark:shadow-dark hover:translate-x-boxShadowX hover:translate-y-boxShadowY hover:shadow-none dark:hover:shadow-none",
|
|
34
|
+
noShadow: "bg-white border-2 border-border dark:border-darkBorder",
|
|
35
|
+
neutral: "bg-white dark:bg-secondaryBlack dark:text-darkText border-2 border-border dark:border-darkBorder shadow-light dark:shadow-dark hover:translate-x-boxShadowX hover:translate-y-boxShadowY hover:shadow-none dark:hover:shadow-none",
|
|
36
|
+
simple: "bg-white border-2 border-border dark:border-darkBorder",
|
|
37
|
+
pressed: "bg-white border-2 border-border mt-1 ml-1",
|
|
38
|
+
reverse: "bg-white border-2 border-border dark:border-darkBorder hover:translate-x-reverseBoxShadowX hover:translate-y-reverseBoxShadowY hover:shadow-light dark:hover:shadow-dark",
|
|
39
|
+
},
|
|
40
|
+
size: {
|
|
41
|
+
default: "h-10 px-4 py-2",
|
|
42
|
+
sm: "h-9 px-3",
|
|
43
|
+
lg: "h-11 px-8",
|
|
44
|
+
icon: "h-10 w-10",
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
defaultVariants: {
|
|
48
|
+
variant: "default",
|
|
49
|
+
size: "default",
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
var Button = React.forwardRef(function (_a, ref) {
|
|
53
|
+
var className = _a.className, variant = _a.variant, size = _a.size, _b = _a.asChild, asChild = _b === void 0 ? false : _b, props = __rest(_a, ["className", "variant", "size", "asChild"]);
|
|
54
|
+
var Comp = asChild ? Slot : "button";
|
|
55
|
+
return (_jsx(Comp, __assign({ className: cn(buttonVariants({ variant: variant, size: size, className: className })), ref: ref }, props)));
|
|
56
|
+
});
|
|
57
|
+
Button.displayName = "Button";
|
|
58
|
+
export { Button, buttonVariants };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
var __assign = (this && this.__assign) || function () {
|
|
2
|
+
__assign = Object.assign || function(t) {
|
|
3
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
4
|
+
s = arguments[i];
|
|
5
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
6
|
+
t[p] = s[p];
|
|
7
|
+
}
|
|
8
|
+
return t;
|
|
9
|
+
};
|
|
10
|
+
return __assign.apply(this, arguments);
|
|
11
|
+
};
|
|
12
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
13
|
+
var t = {};
|
|
14
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
15
|
+
t[p] = s[p];
|
|
16
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
17
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
18
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
19
|
+
t[p[i]] = s[p[i]];
|
|
20
|
+
}
|
|
21
|
+
return t;
|
|
22
|
+
};
|
|
23
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
24
|
+
import * as React from "react";
|
|
25
|
+
import { cn } from "../utils";
|
|
26
|
+
var Input = React.forwardRef(function (_a, ref) {
|
|
27
|
+
var className = _a.className, type = _a.type, props = __rest(_a, ["className", "type"]);
|
|
28
|
+
return (_jsx("input", __assign({ type: type, className: cn("flex h-10 w-full rounded-base border-2 text-text dark:text-darkText font-base selection:bg-main selection:text-text border-border dark:border-darkBorder bg-white dark:bg-secondaryBlack px-3 py-2 text-sm ring-offset-white file:border-0 file:bg-transparent file:text-sm file:font-base focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-black focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50", className), ref: ref }, props)));
|
|
29
|
+
});
|
|
30
|
+
Input.displayName = "Input";
|
|
31
|
+
export { Input };
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { RichTextDisplay } from "./rich-text-display";
|
|
2
|
+
export { RichTextInput } from "./rich-text-input";
|
|
3
|
+
export { RichTextToolbar } from "./rich-text-toolbar";
|
|
4
|
+
export { MinimalRichTextField } from "./minimal-rich-text-field";
|
|
5
|
+
export { processFilesAsString } from "./tiptap/file-handler";
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { RichTextDisplay } from "./rich-text-display";
|
|
2
|
+
export { RichTextInput } from "./rich-text-input";
|
|
3
|
+
export { RichTextToolbar } from "./rich-text-toolbar";
|
|
4
|
+
export { MinimalRichTextField } from "./minimal-rich-text-field";
|
|
5
|
+
export { processFilesAsString } from "./tiptap/file-handler";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { EditorContentProps } from "@tiptap/react";
|
|
2
|
+
export type MinimalRichTextFieldProps = {
|
|
3
|
+
className?: string;
|
|
4
|
+
editorClassName?: string;
|
|
5
|
+
value?: string;
|
|
6
|
+
placeholder?: string;
|
|
7
|
+
onChange?: (value: string) => void;
|
|
8
|
+
slotBefore?: (editor: any) => React.ReactNode;
|
|
9
|
+
singleLine?: boolean;
|
|
10
|
+
autoFocus?: boolean;
|
|
11
|
+
showFormattingMenu?: boolean;
|
|
12
|
+
uploadFile?: (file: File) => Promise<{
|
|
13
|
+
url: string;
|
|
14
|
+
name: string;
|
|
15
|
+
}>;
|
|
16
|
+
} & Omit<EditorContentProps, "editor">;
|
|
17
|
+
export declare const MinimalRichTextField: ({ className, editorClassName, value, placeholder, onChange, slotBefore, singleLine, autoFocus, showFormattingMenu, uploadFile, ...props }: MinimalRichTextFieldProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
var __assign = (this && this.__assign) || function () {
|
|
2
|
+
__assign = Object.assign || function(t) {
|
|
3
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
4
|
+
s = arguments[i];
|
|
5
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
6
|
+
t[p] = s[p];
|
|
7
|
+
}
|
|
8
|
+
return t;
|
|
9
|
+
};
|
|
10
|
+
return __assign.apply(this, arguments);
|
|
11
|
+
};
|
|
12
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
13
|
+
var t = {};
|
|
14
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
15
|
+
t[p] = s[p];
|
|
16
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
17
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
18
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
19
|
+
t[p[i]] = s[p[i]];
|
|
20
|
+
}
|
|
21
|
+
return t;
|
|
22
|
+
};
|
|
23
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
24
|
+
import { useEffect, useMemo, useState } from "react";
|
|
25
|
+
import Document from "@tiptap/extension-document";
|
|
26
|
+
import Highlight from "@tiptap/extension-highlight";
|
|
27
|
+
import Link from "@tiptap/extension-link";
|
|
28
|
+
// TODO: fix maths integration
|
|
29
|
+
// import Mathematics, { migrateMathStrings } from "@tiptap/extension-mathematics";
|
|
30
|
+
import Placeholder from "@tiptap/extension-placeholder";
|
|
31
|
+
import Typography from "@tiptap/extension-typography";
|
|
32
|
+
import { EditorContent, useEditor, } from "@tiptap/react";
|
|
33
|
+
import StarterKit from "@tiptap/starter-kit";
|
|
34
|
+
import { cn } from "../../utils";
|
|
35
|
+
import { registerWebComponents } from "../web-components";
|
|
36
|
+
import FileAttachment from "./tiptap/file-attachment";
|
|
37
|
+
import { fileHandler } from "./tiptap/file-handler";
|
|
38
|
+
import Image from "./tiptap/image";
|
|
39
|
+
import PageClipping from "./tiptap/page-clipping";
|
|
40
|
+
import { RichTextFormattingMenu } from "./tiptap/rich-text-formatting-menu";
|
|
41
|
+
registerWebComponents();
|
|
42
|
+
export var MinimalRichTextField = function (_a) {
|
|
43
|
+
var _b = _a.className, className = _b === void 0 ? "" : _b, _c = _a.editorClassName, editorClassName = _c === void 0 ? "" : _c, _d = _a.value, value = _d === void 0 ? "" : _d, _e = _a.placeholder, placeholder = _e === void 0 ? "" : _e, onChange = _a.onChange, slotBefore = _a.slotBefore, _f = _a.singleLine, singleLine = _f === void 0 ? false : _f, _g = _a.autoFocus, autoFocus = _g === void 0 ? false : _g, _h = _a.showFormattingMenu, showFormattingMenu = _h === void 0 ? false : _h, _j = _a.uploadFile, uploadFile = _j === void 0 ? undefined : _j, props = __rest(_a, ["className", "editorClassName", "value", "placeholder", "onChange", "slotBefore", "singleLine", "autoFocus", "showFormattingMenu", "uploadFile"]);
|
|
44
|
+
var _k = useState(value), content = _k[0], setContent = _k[1];
|
|
45
|
+
var extensions = useMemo(function () {
|
|
46
|
+
return [
|
|
47
|
+
StarterKit.configure({
|
|
48
|
+
document: singleLine ? false : undefined,
|
|
49
|
+
link: false,
|
|
50
|
+
}),
|
|
51
|
+
singleLine &&
|
|
52
|
+
Document.extend({
|
|
53
|
+
content: "block",
|
|
54
|
+
}),
|
|
55
|
+
Link.configure({
|
|
56
|
+
openOnClick: false,
|
|
57
|
+
}),
|
|
58
|
+
Typography,
|
|
59
|
+
Image,
|
|
60
|
+
placeholder && Placeholder.configure({ placeholder: placeholder }),
|
|
61
|
+
FileAttachment,
|
|
62
|
+
PageClipping,
|
|
63
|
+
// Mathematics,
|
|
64
|
+
Highlight,
|
|
65
|
+
uploadFile && fileHandler(uploadFile),
|
|
66
|
+
].filter(Boolean);
|
|
67
|
+
}, [singleLine, placeholder, uploadFile]);
|
|
68
|
+
var editor = useEditor({
|
|
69
|
+
onUpdate: function (_a) {
|
|
70
|
+
var editor = _a.editor;
|
|
71
|
+
var html = editor.getHTML();
|
|
72
|
+
setContent(html);
|
|
73
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(html);
|
|
74
|
+
},
|
|
75
|
+
// onCreate: ({ editor: currentEditor }) => {
|
|
76
|
+
// migrateMathStrings(currentEditor);
|
|
77
|
+
// },
|
|
78
|
+
autofocus: autoFocus,
|
|
79
|
+
content: content,
|
|
80
|
+
extensions: extensions,
|
|
81
|
+
editorProps: {
|
|
82
|
+
attributes: {
|
|
83
|
+
class: editorClassName || "",
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
useEffect(function () {
|
|
88
|
+
if (value !== content) {
|
|
89
|
+
setContent(value);
|
|
90
|
+
editor === null || editor === void 0 ? void 0 : editor.commands.setContent(value, {
|
|
91
|
+
emitUpdate: false,
|
|
92
|
+
parseOptions: {
|
|
93
|
+
preserveWhitespace: "full",
|
|
94
|
+
},
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}, [value, content, editor]);
|
|
98
|
+
return (_jsxs(_Fragment, { children: [slotBefore ? slotBefore(editor) : null, showFormattingMenu && _jsx(RichTextFormattingMenu, { editor: editor }), _jsx("div", { className: cn("max-w-none", className), children: _jsx(EditorContent, __assign({ editor: editor }, props)) })] }));
|
|
99
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare const RichTextDisplay: ({ as, children, className, ...props }: {
|
|
2
|
+
[x: string]: any;
|
|
3
|
+
as?: string;
|
|
4
|
+
children: any;
|
|
5
|
+
className?: string;
|
|
6
|
+
}) => import("react").DOMElement<{
|
|
7
|
+
key: string;
|
|
8
|
+
className: string;
|
|
9
|
+
dangerouslySetInnerHTML: {
|
|
10
|
+
__html: any;
|
|
11
|
+
};
|
|
12
|
+
ref: import("react").RefObject<HTMLDivElement>;
|
|
13
|
+
}, HTMLDivElement>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
var __assign = (this && this.__assign) || function () {
|
|
2
|
+
__assign = Object.assign || function(t) {
|
|
3
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
4
|
+
s = arguments[i];
|
|
5
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
6
|
+
t[p] = s[p];
|
|
7
|
+
}
|
|
8
|
+
return t;
|
|
9
|
+
};
|
|
10
|
+
return __assign.apply(this, arguments);
|
|
11
|
+
};
|
|
12
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
13
|
+
var t = {};
|
|
14
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
15
|
+
t[p] = s[p];
|
|
16
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
17
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
18
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
19
|
+
t[p[i]] = s[p[i]];
|
|
20
|
+
}
|
|
21
|
+
return t;
|
|
22
|
+
};
|
|
23
|
+
import { createElement, useEffect, useRef } from "react";
|
|
24
|
+
import renderMathInElement from "katex/dist/contrib/auto-render.js";
|
|
25
|
+
import { cn } from "../../utils";
|
|
26
|
+
export var RichTextDisplay = function (_a) {
|
|
27
|
+
var _b = _a.as, as = _b === void 0 ? "div" : _b, children = _a.children, _c = _a.className, className = _c === void 0 ? "" : _c, props = __rest(_a, ["as", "children", "className"]);
|
|
28
|
+
var ref = useRef(null);
|
|
29
|
+
useEffect(function () {
|
|
30
|
+
if (!ref.current)
|
|
31
|
+
return;
|
|
32
|
+
renderMathInElement(ref.current, {
|
|
33
|
+
delimiters: [{ left: "$", right: "$", display: false }],
|
|
34
|
+
throwOnError: false,
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
return createElement(as, __assign(__assign({}, props), { key: "rich-text-display", className: cn("tiptap", className), dangerouslySetInnerHTML: { __html: children }, ref: ref }));
|
|
38
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { MinimalRichTextFieldProps } from "./minimal-rich-text-field";
|
|
2
|
+
export type RichTextInputProps = {
|
|
3
|
+
name: string;
|
|
4
|
+
defaultValue?: string;
|
|
5
|
+
className?: string;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
} & MinimalRichTextFieldProps;
|
|
8
|
+
export declare const RichTextInput: ({ name, defaultValue, className, disabled, ...props }: {
|
|
9
|
+
[x: string]: any;
|
|
10
|
+
name: any;
|
|
11
|
+
defaultValue: any;
|
|
12
|
+
className?: string;
|
|
13
|
+
disabled?: boolean;
|
|
14
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
var __assign = (this && this.__assign) || function () {
|
|
2
|
+
__assign = Object.assign || function(t) {
|
|
3
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
4
|
+
s = arguments[i];
|
|
5
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
6
|
+
t[p] = s[p];
|
|
7
|
+
}
|
|
8
|
+
return t;
|
|
9
|
+
};
|
|
10
|
+
return __assign.apply(this, arguments);
|
|
11
|
+
};
|
|
12
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
13
|
+
var t = {};
|
|
14
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
15
|
+
t[p] = s[p];
|
|
16
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
17
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
18
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
19
|
+
t[p[i]] = s[p[i]];
|
|
20
|
+
}
|
|
21
|
+
return t;
|
|
22
|
+
};
|
|
23
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
24
|
+
import { useState } from "react";
|
|
25
|
+
import { MinimalRichTextField, } from "./minimal-rich-text-field";
|
|
26
|
+
import { cn } from "../../utils";
|
|
27
|
+
export var RichTextInput = function (_a) {
|
|
28
|
+
var name = _a.name, defaultValue = _a.defaultValue, _b = _a.className, className = _b === void 0 ? "" : _b, _c = _a.disabled, disabled = _c === void 0 ? false : _c, props = __rest(_a, ["name", "defaultValue", "className", "disabled"]);
|
|
29
|
+
var _d = useState(defaultValue), value = _d[0], setValue = _d[1];
|
|
30
|
+
return (_jsxs(_Fragment, { children: [_jsx("input", { type: "hidden", name: name, value: value }), _jsx(MinimalRichTextField, __assign({ className: cn("rounded-base border-2 text-sm font-base bg-white", "ring-offset-white focus-within:outline-none focus-within:ring-2 focus-within:ring-black focus-within:ring-offset-2", disabled && "opacity-50 pointer-events-none", className), editorClassName: "px-3 py-2", value: value, onChange: setValue }, props))] }));
|
|
31
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback } from "react";
|
|
3
|
+
import { Bold, Italic, LinkIcon, List, TextQuote } from "lucide-react";
|
|
4
|
+
import { cn } from "../../utils";
|
|
5
|
+
export var RichTextToolbar = function (_a) {
|
|
6
|
+
var editor = _a.editor;
|
|
7
|
+
var setLink = useCallback(function () {
|
|
8
|
+
if (editor.isActive("link")) {
|
|
9
|
+
editor.chain().focus().extendMarkRange("link").unsetLink().run();
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
var previousUrl = editor.getAttributes("link").href;
|
|
13
|
+
var url = window.prompt("Where do you want to link to? Enter a link that starts with 'https://'.", previousUrl);
|
|
14
|
+
// cancelled
|
|
15
|
+
if (url === null) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
// empty
|
|
19
|
+
if (url === "") {
|
|
20
|
+
editor.chain().focus().extendMarkRange("link").unsetLink().run();
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
if (url.indexOf("http") !== 0) {
|
|
24
|
+
url = "http://" + url;
|
|
25
|
+
}
|
|
26
|
+
// update link
|
|
27
|
+
editor.chain().focus().extendMarkRange("link").setLink({ href: url }).run();
|
|
28
|
+
}, [editor]);
|
|
29
|
+
if (!editor) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
return (_jsxs("div", { className: "border-2 border-b-0 rounded-t-base p-1 gap-1 flex items-center", children: [_jsx("span", { onClick: function () { return editor.chain().focus().toggleBold().run(); }, className: cn("p-2 cursor-pointer", editor.isActive("bold") ? "bg-bright rounded-base" : ""), children: _jsx(Bold, { size: 16 }) }), _jsx("span", { onClick: function () { return editor.chain().focus().toggleItalic().run(); }, className: cn("p-2 cursor-pointer", editor.isActive("italic") ? "bg-bright rounded-base" : ""), children: _jsx(Italic, { size: 16 }) }), _jsx("span", { onClick: setLink, className: cn("p-2 cursor-pointer", editor.isActive("link") ? "bg-bright rounded-base" : ""), children: _jsx(LinkIcon, { size: 16 }) }), _jsx("span", { onClick: function () { return editor.chain().focus().toggleBulletList().run(); }, className: cn("p-2 cursor-pointer", editor.isActive("bulletList") ? "bg-bright rounded-base" : ""), children: _jsx(List, { size: 16 }) }), _jsx("span", { onClick: function () { return editor.chain().focus().toggleOrderedList().run(); }, className: cn("p-2 cursor-pointer", editor.isActive("orderedList") ? "bg-bright rounded-base" : ""), children: _jsx(List, { size: 16 }) }), _jsx("span", { onClick: function () { return editor.chain().focus().toggleBlockquote().run(); }, className: cn("p-2 cursor-pointer", editor.isActive("blockquote") ? "bg-bright rounded-base" : ""), children: _jsx(TextQuote, { size: 16 }) })] }));
|
|
33
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { mergeAttributes, Node } from "@tiptap/core";
|
|
3
|
+
import { createRoot } from "react-dom/client";
|
|
4
|
+
import { FileAttachmentView } from "../../web-components/file-attachment";
|
|
5
|
+
export default Node.create({
|
|
6
|
+
name: "file-attachment",
|
|
7
|
+
group: "block",
|
|
8
|
+
content: "inline*",
|
|
9
|
+
atom: true,
|
|
10
|
+
addAttributes: function () {
|
|
11
|
+
return {
|
|
12
|
+
href: {},
|
|
13
|
+
title: {},
|
|
14
|
+
type: {},
|
|
15
|
+
};
|
|
16
|
+
},
|
|
17
|
+
parseHTML: function () {
|
|
18
|
+
return [
|
|
19
|
+
{
|
|
20
|
+
tag: "file-attachment",
|
|
21
|
+
},
|
|
22
|
+
];
|
|
23
|
+
},
|
|
24
|
+
renderHTML: function (_a) {
|
|
25
|
+
var HTMLAttributes = _a.HTMLAttributes;
|
|
26
|
+
return ["file-attachment", mergeAttributes(HTMLAttributes)];
|
|
27
|
+
},
|
|
28
|
+
addNodeView: function () {
|
|
29
|
+
return function (_a) {
|
|
30
|
+
var node = _a.node;
|
|
31
|
+
var dom = document.createElement("div");
|
|
32
|
+
dom.classList.add("file-attachment");
|
|
33
|
+
var root = createRoot(dom);
|
|
34
|
+
root.render(_jsx(FileAttachmentView, { title: node.attrs.title, type: node.attrs.type, href: node.attrs.href, className: "pointer-events-none" }));
|
|
35
|
+
return {
|
|
36
|
+
dom: dom,
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
},
|
|
40
|
+
});
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { Editor } from "@tiptap/react";
|
|
2
|
+
export declare const processFilesAsString: (uploadFile: any, files: any) => Promise<unknown>;
|
|
3
|
+
export declare const processFiles: (uploadFile: any, currentEditor: Editor, files: any, pos: any) => void;
|
|
4
|
+
export declare const fileHandler: (uploadFile: any) => import("@tiptap/core").Extension<Omit<import("@tiptap-pro/extension-file-handler").FileHandlePluginOptions, "key" | "editor">, any>;
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
11
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
12
|
+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
13
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
14
|
+
function step(op) {
|
|
15
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
16
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
17
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
18
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
19
|
+
switch (op[0]) {
|
|
20
|
+
case 0: case 1: t = op; break;
|
|
21
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
22
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
23
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
24
|
+
default:
|
|
25
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
26
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
27
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
28
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
29
|
+
if (t[2]) _.ops.pop();
|
|
30
|
+
_.trys.pop(); continue;
|
|
31
|
+
}
|
|
32
|
+
op = body.call(thisArg, _);
|
|
33
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
34
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
import toast from "react-hot-toast";
|
|
38
|
+
import FileHandler from "@tiptap-pro/extension-file-handler";
|
|
39
|
+
import { getImageSize } from "../tiptap/png-scanner";
|
|
40
|
+
export var processFilesAsString = function (uploadFile, files) {
|
|
41
|
+
return new Promise(function (resolve) {
|
|
42
|
+
toast.promise(function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
43
|
+
var items, e_1;
|
|
44
|
+
return __generator(this, function (_a) {
|
|
45
|
+
switch (_a.label) {
|
|
46
|
+
case 0:
|
|
47
|
+
_a.trys.push([0, 2, , 3]);
|
|
48
|
+
return [4 /*yield*/, Promise.all(Array.from(files).map(function (file) { return __awaiter(void 0, void 0, void 0, function () {
|
|
49
|
+
var _a, url, name_1, isImage, attrs, width, _1, e_2;
|
|
50
|
+
return __generator(this, function (_b) {
|
|
51
|
+
switch (_b.label) {
|
|
52
|
+
case 0:
|
|
53
|
+
_b.trys.push([0, 6, , 7]);
|
|
54
|
+
return [4 /*yield*/, uploadFile(file)];
|
|
55
|
+
case 1:
|
|
56
|
+
_a = _b.sent(), url = _a.url, name_1 = _a.name;
|
|
57
|
+
isImage = file.type.startsWith("image/");
|
|
58
|
+
attrs = {
|
|
59
|
+
src: url,
|
|
60
|
+
title: name_1,
|
|
61
|
+
type: file.type,
|
|
62
|
+
};
|
|
63
|
+
if (!isImage) return [3 /*break*/, 5];
|
|
64
|
+
_b.label = 2;
|
|
65
|
+
case 2:
|
|
66
|
+
_b.trys.push([2, 4, , 5]);
|
|
67
|
+
return [4 /*yield*/, getImageSize(file)];
|
|
68
|
+
case 3:
|
|
69
|
+
width = (_b.sent()).width;
|
|
70
|
+
if (width)
|
|
71
|
+
attrs.width = width;
|
|
72
|
+
return [3 /*break*/, 5];
|
|
73
|
+
case 4:
|
|
74
|
+
_1 = _b.sent();
|
|
75
|
+
return [3 /*break*/, 5];
|
|
76
|
+
case 5:
|
|
77
|
+
if (isImage) {
|
|
78
|
+
return [2 /*return*/, "<img src=\"".concat(url, "\" title=\"").concat(name_1, "\" width=\"").concat(attrs.width, "\" alt=\"").concat(name_1, "\"/>")];
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
return [2 /*return*/, "<file-attachment title=\"".concat(name_1, "\" type=\"").concat(file.type, "\" href=\"").concat(url, "\">").concat(name_1, "</file-attachment>")];
|
|
82
|
+
}
|
|
83
|
+
return [3 /*break*/, 7];
|
|
84
|
+
case 6:
|
|
85
|
+
e_2 = _b.sent();
|
|
86
|
+
console.log(e_2);
|
|
87
|
+
throw e_2;
|
|
88
|
+
case 7: return [2 /*return*/];
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
}); }))];
|
|
92
|
+
case 1:
|
|
93
|
+
items = _a.sent();
|
|
94
|
+
resolve(items.join(""));
|
|
95
|
+
return [3 /*break*/, 3];
|
|
96
|
+
case 2:
|
|
97
|
+
e_1 = _a.sent();
|
|
98
|
+
console.log(e_1);
|
|
99
|
+
throw e_1;
|
|
100
|
+
case 3: return [2 /*return*/];
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
}); }, {
|
|
104
|
+
loading: "Uploading file...",
|
|
105
|
+
success: "Uploaded successfully!",
|
|
106
|
+
error: "Failed to upload file",
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
};
|
|
110
|
+
export var processFiles = function (uploadFile, currentEditor, files, pos) {
|
|
111
|
+
toast.promise(Promise.all(files.map(function (file) { return __awaiter(void 0, void 0, void 0, function () {
|
|
112
|
+
var _a, url, name_2, isImage, attrs, width, _2, content, e_3;
|
|
113
|
+
return __generator(this, function (_b) {
|
|
114
|
+
switch (_b.label) {
|
|
115
|
+
case 0:
|
|
116
|
+
_b.trys.push([0, 6, , 7]);
|
|
117
|
+
return [4 /*yield*/, uploadFile(file)];
|
|
118
|
+
case 1:
|
|
119
|
+
_a = _b.sent(), url = _a.url, name_2 = _a.name;
|
|
120
|
+
isImage = file.type.startsWith("image/");
|
|
121
|
+
attrs = {
|
|
122
|
+
src: url,
|
|
123
|
+
title: name_2,
|
|
124
|
+
type: file.type,
|
|
125
|
+
};
|
|
126
|
+
if (!isImage) return [3 /*break*/, 5];
|
|
127
|
+
_b.label = 2;
|
|
128
|
+
case 2:
|
|
129
|
+
_b.trys.push([2, 4, , 5]);
|
|
130
|
+
return [4 /*yield*/, getImageSize(file)];
|
|
131
|
+
case 3:
|
|
132
|
+
width = (_b.sent()).width;
|
|
133
|
+
if (width)
|
|
134
|
+
attrs.width = width;
|
|
135
|
+
return [3 /*break*/, 5];
|
|
136
|
+
case 4:
|
|
137
|
+
_2 = _b.sent();
|
|
138
|
+
return [3 /*break*/, 5];
|
|
139
|
+
case 5:
|
|
140
|
+
content = isImage
|
|
141
|
+
? {
|
|
142
|
+
type: "image",
|
|
143
|
+
attrs: attrs,
|
|
144
|
+
}
|
|
145
|
+
: {
|
|
146
|
+
type: "file-attachment",
|
|
147
|
+
attrs: attrs,
|
|
148
|
+
content: [
|
|
149
|
+
{
|
|
150
|
+
type: "text",
|
|
151
|
+
href: url,
|
|
152
|
+
text: name_2,
|
|
153
|
+
},
|
|
154
|
+
],
|
|
155
|
+
};
|
|
156
|
+
currentEditor.chain().insertContentAt(pos, content).focus().run();
|
|
157
|
+
return [3 /*break*/, 7];
|
|
158
|
+
case 6:
|
|
159
|
+
e_3 = _b.sent();
|
|
160
|
+
console.log(e_3);
|
|
161
|
+
throw e_3;
|
|
162
|
+
case 7: return [2 /*return*/];
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
}); })), {
|
|
166
|
+
loading: "Uploading file...",
|
|
167
|
+
success: "Uploaded successfully!",
|
|
168
|
+
error: "Failed to upload file",
|
|
169
|
+
});
|
|
170
|
+
};
|
|
171
|
+
export var fileHandler = function (uploadFile) {
|
|
172
|
+
return FileHandler.configure({
|
|
173
|
+
allowedMimeTypes: [
|
|
174
|
+
"image/png",
|
|
175
|
+
"image/jpeg",
|
|
176
|
+
"image/gif",
|
|
177
|
+
"image/webp",
|
|
178
|
+
"application/pdf",
|
|
179
|
+
"text/html",
|
|
180
|
+
"text/plain",
|
|
181
|
+
],
|
|
182
|
+
onDrop: function (currentEditor, files, pos) {
|
|
183
|
+
processFiles(uploadFile, currentEditor, files, pos);
|
|
184
|
+
},
|
|
185
|
+
onPaste: function (currentEditor, files, htmlContent) {
|
|
186
|
+
files.forEach(function (file) {
|
|
187
|
+
if (htmlContent) {
|
|
188
|
+
// if there is htmlContent, stop manual insertion & let other extensions handle insertion via inputRule
|
|
189
|
+
// you could extract the pasted file from this url string and upload it to a server for example
|
|
190
|
+
return false;
|
|
191
|
+
}
|
|
192
|
+
processFiles(uploadFile, currentEditor, [file], currentEditor.state.selection.anchor);
|
|
193
|
+
});
|
|
194
|
+
},
|
|
195
|
+
});
|
|
196
|
+
};
|