[WIKI-578] refactor: editor types structure #7536
This commit is contained in:
parent
fa150c2b47
commit
7ead606798
29 changed files with 103 additions and 111 deletions
|
|
@ -30,6 +30,7 @@ const DocumentEditor = (props: IDocumentEditorProps) => {
|
||||||
flaggedExtensions,
|
flaggedExtensions,
|
||||||
forwardedRef,
|
forwardedRef,
|
||||||
id,
|
id,
|
||||||
|
isTouchDevice,
|
||||||
handleEditorReady,
|
handleEditorReady,
|
||||||
mentionHandler,
|
mentionHandler,
|
||||||
onChange,
|
onChange,
|
||||||
|
|
@ -96,6 +97,7 @@ const DocumentEditor = (props: IDocumentEditorProps) => {
|
||||||
editor={editor}
|
editor={editor}
|
||||||
editorContainerClassName={cn(editorContainerClassName, "document-editor")}
|
editorContainerClassName={cn(editorContainerClassName, "document-editor")}
|
||||||
id={id}
|
id={id}
|
||||||
|
isTouchDevice={!!isTouchDevice}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
import { Editor, EditorContent } from "@tiptap/react";
|
import { type Editor, EditorContent } from "@tiptap/react";
|
||||||
import { FC, ReactNode } from "react";
|
import { FC, ReactNode } from "react";
|
||||||
|
|
||||||
interface EditorContentProps {
|
type Props = {
|
||||||
children?: ReactNode;
|
children?: ReactNode;
|
||||||
editor: Editor | null;
|
editor: Editor | null;
|
||||||
id: string;
|
id: string;
|
||||||
tabIndex?: number;
|
tabIndex?: number;
|
||||||
}
|
};
|
||||||
|
|
||||||
export const EditorContentWrapper: FC<EditorContentProps> = (props) => {
|
export const EditorContentWrapper: FC<Props> = (props) => {
|
||||||
const { editor, children, tabIndex, id } = props;
|
const { editor, children, tabIndex, id } = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,12 @@ import { FC, useCallback, useEffect, useRef, useState } from "react";
|
||||||
// components
|
// components
|
||||||
import { LinkView, LinkViewProps } from "@/components/links";
|
import { LinkView, LinkViewProps } from "@/components/links";
|
||||||
|
|
||||||
interface LinkViewContainerProps {
|
type Props = {
|
||||||
editor: Editor;
|
editor: Editor;
|
||||||
containerRef: React.RefObject<HTMLDivElement>;
|
containerRef: React.RefObject<HTMLDivElement>;
|
||||||
}
|
};
|
||||||
|
|
||||||
export const LinkViewContainer: FC<LinkViewContainerProps> = ({ editor, containerRef }) => {
|
export const LinkViewContainer: FC<Props> = ({ editor, containerRef }) => {
|
||||||
const [linkViewProps, setLinkViewProps] = useState<LinkViewProps>();
|
const [linkViewProps, setLinkViewProps] = useState<LinkViewProps>();
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
const [virtualElement, setVirtualElement] = useState<Element | null>(null);
|
const [virtualElement, setVirtualElement] = useState<Element | null>(null);
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,13 @@ import { LinkViewProps, LinkViews } from "@/components/links";
|
||||||
// helpers
|
// helpers
|
||||||
import { isValidHttpUrl } from "@/helpers/common";
|
import { isValidHttpUrl } from "@/helpers/common";
|
||||||
|
|
||||||
interface InputViewProps {
|
type InputViewProps = {
|
||||||
label: string;
|
label: string;
|
||||||
value: string;
|
value: string;
|
||||||
placeholder: string;
|
placeholder: string;
|
||||||
onChange: (value: string) => void;
|
onChange: (value: string) => void;
|
||||||
autoFocus?: boolean;
|
autoFocus?: boolean;
|
||||||
}
|
};
|
||||||
|
|
||||||
const InputView = ({ label, value, placeholder, onChange, autoFocus }: InputViewProps) => (
|
const InputView = ({ label, value, placeholder, onChange, autoFocus }: InputViewProps) => (
|
||||||
<div className="flex flex-col gap-1">
|
<div className="flex flex-col gap-1">
|
||||||
|
|
@ -28,10 +28,10 @@ const InputView = ({ label, value, placeholder, onChange, autoFocus }: InputView
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
interface LinkEditViewProps {
|
type LinkEditViewProps = {
|
||||||
viewProps: LinkViewProps;
|
viewProps: LinkViewProps;
|
||||||
switchView: (view: LinkViews) => void;
|
switchView: (view: LinkViews) => void;
|
||||||
}
|
};
|
||||||
|
|
||||||
export const LinkEditView = ({ viewProps }: LinkEditViewProps) => {
|
export const LinkEditView = ({ viewProps }: LinkEditViewProps) => {
|
||||||
const { editor, from, to, url: initialUrl, text: initialText, closeLinkView } = viewProps;
|
const { editor, from, to, url: initialUrl, text: initialText, closeLinkView } = viewProps;
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import { LinkEditView, LinkPreview } from "@/components/links";
|
||||||
|
|
||||||
export type LinkViews = "LinkPreview" | "LinkEditView";
|
export type LinkViews = "LinkPreview" | "LinkEditView";
|
||||||
|
|
||||||
export interface LinkViewProps {
|
export type LinkViewProps = {
|
||||||
view?: LinkViews;
|
view?: LinkViews;
|
||||||
editor: Editor;
|
editor: Editor;
|
||||||
from: number;
|
from: number;
|
||||||
|
|
@ -13,7 +13,7 @@ export interface LinkViewProps {
|
||||||
url: string;
|
url: string;
|
||||||
text?: string;
|
text?: string;
|
||||||
closeLinkView: () => void;
|
closeLinkView: () => void;
|
||||||
}
|
};
|
||||||
|
|
||||||
export const LinkView = (props: LinkViewProps & { style: CSSProperties }) => {
|
export const LinkView = (props: LinkViewProps & { style: CSSProperties }) => {
|
||||||
const [currentView, setCurrentView] = useState<LinkViews>(props.view ?? "LinkPreview");
|
const [currentView, setCurrentView] = useState<LinkViews>(props.view ?? "LinkPreview");
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
import { Editor } from "@tiptap/react";
|
import type { Editor } from "@tiptap/react";
|
||||||
import { Copy, LucideIcon, Trash2 } from "lucide-react";
|
import { Copy, LucideIcon, Trash2 } from "lucide-react";
|
||||||
import { useCallback, useEffect, useRef } from "react";
|
import { useCallback, useEffect, useRef } from "react";
|
||||||
import tippy, { Instance } from "tippy.js";
|
import tippy, { Instance } from "tippy.js";
|
||||||
// constants
|
// constants
|
||||||
import { CORE_EXTENSIONS } from "@/constants/extension";
|
import { CORE_EXTENSIONS } from "@/constants/extension";
|
||||||
|
|
||||||
interface BlockMenuProps {
|
type Props = {
|
||||||
editor: Editor;
|
editor: Editor;
|
||||||
}
|
};
|
||||||
|
|
||||||
export const BlockMenu = (props: BlockMenuProps) => {
|
export const BlockMenu = (props: Props) => {
|
||||||
const { editor } = props;
|
const { editor } = props;
|
||||||
const menuRef = useRef<HTMLDivElement>(null);
|
const menuRef = useRef<HTMLDivElement>(null);
|
||||||
const popup = useRef<Instance | null>(null);
|
const popup = useRef<Instance | null>(null);
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ import { TextAlignmentSelector } from "./alignment-selector";
|
||||||
|
|
||||||
type EditorBubbleMenuProps = Omit<BubbleMenuProps, "children">;
|
type EditorBubbleMenuProps = Omit<BubbleMenuProps, "children">;
|
||||||
|
|
||||||
export interface EditorStateType {
|
export type EditorStateType = {
|
||||||
code: boolean;
|
code: boolean;
|
||||||
bold: boolean;
|
bold: boolean;
|
||||||
italic: boolean;
|
italic: boolean;
|
||||||
|
|
@ -47,7 +47,7 @@ export interface EditorStateType {
|
||||||
backgroundColor: string;
|
backgroundColor: string;
|
||||||
}
|
}
|
||||||
| undefined;
|
| undefined;
|
||||||
}
|
};
|
||||||
|
|
||||||
export const EditorBubbleMenu: FC<EditorBubbleMenuProps> = (props: { editor: Editor }) => {
|
export const EditorBubbleMenu: FC<EditorBubbleMenuProps> = (props: { editor: Editor }) => {
|
||||||
const menuRef = useRef<HTMLDivElement>(null);
|
const menuRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,9 @@ import { Mark, markInputRule, markPasteRule, mergeAttributes } from "@tiptap/cor
|
||||||
// constants
|
// constants
|
||||||
import { CORE_EXTENSIONS } from "@/constants/extension";
|
import { CORE_EXTENSIONS } from "@/constants/extension";
|
||||||
|
|
||||||
export interface CodeOptions {
|
type InlineCodeOptions = {
|
||||||
HTMLAttributes: Record<string, any>;
|
HTMLAttributes: Record<string, unknown>;
|
||||||
}
|
};
|
||||||
|
|
||||||
declare module "@tiptap/core" {
|
declare module "@tiptap/core" {
|
||||||
interface Commands<ReturnType> {
|
interface Commands<ReturnType> {
|
||||||
|
|
@ -28,7 +28,7 @@ declare module "@tiptap/core" {
|
||||||
export const inputRegex = /(?:^|\s)((?:`)((?:[^`]+))(?:`))$/;
|
export const inputRegex = /(?:^|\s)((?:`)((?:[^`]+))(?:`))$/;
|
||||||
const pasteRegex = /(?:^|\s)((?:`)((?:[^`]+))(?:`))/g;
|
const pasteRegex = /(?:^|\s)((?:`)((?:[^`]+))(?:`))/g;
|
||||||
|
|
||||||
export const CustomCodeInlineExtension = Mark.create<CodeOptions>({
|
export const CustomCodeInlineExtension = Mark.create<InlineCodeOptions>({
|
||||||
name: CORE_EXTENSIONS.CODE_INLINE,
|
name: CORE_EXTENSIONS.CODE_INLINE,
|
||||||
|
|
||||||
addOptions() {
|
addOptions() {
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,10 @@
|
||||||
import { CodeBlockOptions, CodeBlock } from "./code-block";
|
import { CodeBlockOptions, CodeBlock } from "./code-block";
|
||||||
import { LowlightPlugin } from "./lowlight-plugin";
|
import { LowlightPlugin } from "./lowlight-plugin";
|
||||||
|
|
||||||
export interface CodeBlockLowlightOptions extends CodeBlockOptions {
|
type CodeBlockLowlightOptions = CodeBlockOptions & {
|
||||||
lowlight: any;
|
lowlight: any;
|
||||||
defaultLanguage: string | null | undefined;
|
defaultLanguage: string | null | undefined;
|
||||||
}
|
};
|
||||||
|
|
||||||
export const CodeBlockLowlight = CodeBlock.extend<CodeBlockLowlightOptions>({
|
export const CodeBlockLowlight = CodeBlock.extend<CodeBlockLowlightOptions>({
|
||||||
addOptions() {
|
addOptions() {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { Node as ProseMirrorNode } from "@tiptap/pm/model";
|
import type { Node as ProseMirrorNode } from "@tiptap/pm/model";
|
||||||
import { NodeViewWrapper, NodeViewContent } from "@tiptap/react";
|
import { NodeViewWrapper, NodeViewContent } from "@tiptap/react";
|
||||||
import ts from "highlight.js/lib/languages/typescript";
|
import ts from "highlight.js/lib/languages/typescript";
|
||||||
import { common, createLowlight } from "lowlight";
|
import { common, createLowlight } from "lowlight";
|
||||||
|
|
@ -15,11 +15,11 @@ import { cn } from "@plane/utils";
|
||||||
const lowlight = createLowlight(common);
|
const lowlight = createLowlight(common);
|
||||||
lowlight.register("ts", ts);
|
lowlight.register("ts", ts);
|
||||||
|
|
||||||
interface CodeBlockComponentProps {
|
type Props = {
|
||||||
node: ProseMirrorNode;
|
node: ProseMirrorNode;
|
||||||
}
|
};
|
||||||
|
|
||||||
export const CodeBlockComponent: React.FC<CodeBlockComponentProps> = ({ node }) => {
|
export const CodeBlockComponent: React.FC<Props> = ({ node }) => {
|
||||||
const [copied, setCopied] = useState(false);
|
const [copied, setCopied] = useState(false);
|
||||||
|
|
||||||
const copyToClipboard = async (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
|
const copyToClipboard = async (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { Plugin, PluginKey } from "@tiptap/pm/state";
|
||||||
// constants
|
// constants
|
||||||
import { CORE_EXTENSIONS } from "@/constants/extension";
|
import { CORE_EXTENSIONS } from "@/constants/extension";
|
||||||
|
|
||||||
export interface CodeBlockOptions {
|
export type CodeBlockOptions = {
|
||||||
/**
|
/**
|
||||||
* Adds a prefix to language classes that are applied to code tags.
|
* Adds a prefix to language classes that are applied to code tags.
|
||||||
* Defaults to `'language-'`.
|
* Defaults to `'language-'`.
|
||||||
|
|
@ -22,8 +22,8 @@ export interface CodeBlockOptions {
|
||||||
/**
|
/**
|
||||||
* Custom HTML attributes that should be added to the rendered HTML tag.
|
* Custom HTML attributes that should be added to the rendered HTML tag.
|
||||||
*/
|
*/
|
||||||
HTMLAttributes: Record<string, any>;
|
HTMLAttributes: Record<string, unknown>;
|
||||||
}
|
};
|
||||||
|
|
||||||
declare module "@tiptap/core" {
|
declare module "@tiptap/core" {
|
||||||
interface Commands<ReturnType> {
|
interface Commands<ReturnType> {
|
||||||
|
|
|
||||||
|
|
@ -10,12 +10,12 @@ import { autolink } from "./helpers/autolink";
|
||||||
import { clickHandler } from "./helpers/clickHandler";
|
import { clickHandler } from "./helpers/clickHandler";
|
||||||
import { pasteHandler } from "./helpers/pasteHandler";
|
import { pasteHandler } from "./helpers/pasteHandler";
|
||||||
|
|
||||||
export interface LinkProtocolOptions {
|
type LinkProtocolOptions = {
|
||||||
scheme: string;
|
scheme: string;
|
||||||
optionalSlashes?: boolean;
|
optionalSlashes?: boolean;
|
||||||
}
|
};
|
||||||
|
|
||||||
export interface LinkOptions {
|
type LinkOptions = {
|
||||||
/**
|
/**
|
||||||
* If enabled, it adds links as you type.
|
* If enabled, it adds links as you type.
|
||||||
*/
|
*/
|
||||||
|
|
@ -40,14 +40,14 @@ export interface LinkOptions {
|
||||||
/**
|
/**
|
||||||
* A list of HTML attributes to be rendered.
|
* A list of HTML attributes to be rendered.
|
||||||
*/
|
*/
|
||||||
HTMLAttributes: Record<string, any>;
|
HTMLAttributes: Record<string, unknown>;
|
||||||
/**
|
/**
|
||||||
* A validation function that modifies link verification for the auto linker.
|
* A validation function that modifies link verification for the auto linker.
|
||||||
* @param url - The url to be validated.
|
* @param url - The url to be validated.
|
||||||
* @returns - True if the url is valid, false otherwise.
|
* @returns - True if the url is valid, false otherwise.
|
||||||
*/
|
*/
|
||||||
validate?: (url: string) => boolean;
|
validate?: (url: string) => boolean;
|
||||||
}
|
};
|
||||||
|
|
||||||
declare module "@tiptap/core" {
|
declare module "@tiptap/core" {
|
||||||
interface Commands<ReturnType> {
|
interface Commands<ReturnType> {
|
||||||
|
|
|
||||||
|
|
@ -1,28 +1,17 @@
|
||||||
import { computePosition, flip, shift } from "@floating-ui/dom";
|
import { computePosition, flip, shift } from "@floating-ui/dom";
|
||||||
import { Editor, posToDOMRect } from "@tiptap/react";
|
import { type Editor, posToDOMRect } from "@tiptap/react";
|
||||||
import { SuggestionKeyDownProps } from "@tiptap/suggestion";
|
import { SuggestionKeyDownProps } from "@tiptap/suggestion";
|
||||||
import { forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState } from "react";
|
import { forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState } from "react";
|
||||||
// plane imports
|
// plane imports
|
||||||
import { cn } from "@plane/utils";
|
import { cn } from "@plane/utils";
|
||||||
|
|
||||||
export interface EmojiItem {
|
export type EmojiItem = {
|
||||||
name: string;
|
name: string;
|
||||||
emoji: string;
|
emoji: string;
|
||||||
shortcodes: string[];
|
shortcodes: string[];
|
||||||
tags: string[];
|
tags: string[];
|
||||||
fallbackImage?: string;
|
fallbackImage?: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
export interface EmojiListProps {
|
|
||||||
items: EmojiItem[];
|
|
||||||
command: (item: { name: string }) => void;
|
|
||||||
editor: Editor;
|
|
||||||
query: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface EmojiListRef {
|
|
||||||
onKeyDown: (props: SuggestionKeyDownProps) => boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
const updatePosition = (editor: Editor, element: HTMLElement) => {
|
const updatePosition = (editor: Editor, element: HTMLElement) => {
|
||||||
const virtualElement = {
|
const virtualElement = {
|
||||||
|
|
@ -43,7 +32,18 @@ const updatePosition = (editor: Editor, element: HTMLElement) => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const EmojiList = forwardRef<EmojiListRef, EmojiListProps>((props, ref) => {
|
export type EmojiListRef = {
|
||||||
|
onKeyDown: (props: SuggestionKeyDownProps) => boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
items: EmojiItem[];
|
||||||
|
command: (item: { name: string }) => void;
|
||||||
|
editor: Editor;
|
||||||
|
query: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const EmojiList = forwardRef<EmojiListRef, Props>((props, ref) => {
|
||||||
const { items, command, editor, query } = props;
|
const { items, command, editor, query } = props;
|
||||||
const [selectedIndex, setSelectedIndex] = useState<number>(0);
|
const [selectedIndex, setSelectedIndex] = useState<number>(0);
|
||||||
const [isVisible, setIsVisible] = useState(false);
|
const [isVisible, setIsVisible] = useState(false);
|
||||||
|
|
|
||||||
|
|
@ -65,11 +65,11 @@ export type EmojiItem = {
|
||||||
/**
|
/**
|
||||||
* Store some custom data
|
* Store some custom data
|
||||||
*/
|
*/
|
||||||
[key: string]: any;
|
[key: string]: unknown;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type EmojiOptions = {
|
export type EmojiOptions = {
|
||||||
HTMLAttributes: Record<string, any>;
|
HTMLAttributes: Record<string, unknown>;
|
||||||
emojis: EmojiItem[];
|
emojis: EmojiItem[];
|
||||||
enableEmoticons: boolean;
|
enableEmoticons: boolean;
|
||||||
forceFallbackImages: boolean;
|
forceFallbackImages: boolean;
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,8 @@ import { Extension } from "@tiptap/core";
|
||||||
import { Plugin, PluginKey } from "@tiptap/pm/state";
|
import { Plugin, PluginKey } from "@tiptap/pm/state";
|
||||||
// constants
|
// constants
|
||||||
import { CORE_EXTENSIONS } from "@/constants/extension";
|
import { CORE_EXTENSIONS } from "@/constants/extension";
|
||||||
|
// types
|
||||||
export interface IMarking {
|
import type { IMarking } from "@/types";
|
||||||
type: "heading";
|
|
||||||
level: number;
|
|
||||||
text: string;
|
|
||||||
sequence: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type HeadingExtensionStorage = {
|
export type HeadingExtensionStorage = {
|
||||||
headings: IMarking[];
|
headings: IMarking[];
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,9 @@ import { NodeSelection, TextSelection } from "@tiptap/pm/state";
|
||||||
// constants
|
// constants
|
||||||
import { CORE_EXTENSIONS } from "@/constants/extension";
|
import { CORE_EXTENSIONS } from "@/constants/extension";
|
||||||
|
|
||||||
export interface HorizontalRuleOptions {
|
type HorizontalRuleOptions = {
|
||||||
HTMLAttributes: Record<string, any>;
|
HTMLAttributes: Record<string, unknown>;
|
||||||
}
|
};
|
||||||
|
|
||||||
declare module "@tiptap/core" {
|
declare module "@tiptap/core" {
|
||||||
interface Commands<ReturnType> {
|
interface Commands<ReturnType> {
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,9 @@ import { TableCellSelectionOutlinePlugin } from "./plugins/selection-outline/plu
|
||||||
import { DEFAULT_COLUMN_WIDTH } from "./table";
|
import { DEFAULT_COLUMN_WIDTH } from "./table";
|
||||||
import { isCellSelection } from "./table/utilities/helpers";
|
import { isCellSelection } from "./table/utilities/helpers";
|
||||||
|
|
||||||
export interface TableCellOptions {
|
type TableCellOptions = {
|
||||||
HTMLAttributes: Record<string, any>;
|
HTMLAttributes: Record<string, unknown>;
|
||||||
}
|
};
|
||||||
|
|
||||||
export const TableCell = Node.create<TableCellOptions>({
|
export const TableCell = Node.create<TableCellOptions>({
|
||||||
name: CORE_EXTENSIONS.TABLE_CELL,
|
name: CORE_EXTENSIONS.TABLE_CELL,
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,9 @@ import { CORE_EXTENSIONS } from "@/constants/extension";
|
||||||
// local imports
|
// local imports
|
||||||
import { DEFAULT_COLUMN_WIDTH } from "./table";
|
import { DEFAULT_COLUMN_WIDTH } from "./table";
|
||||||
|
|
||||||
export interface TableHeaderOptions {
|
type TableHeaderOptions = {
|
||||||
HTMLAttributes: Record<string, any>;
|
HTMLAttributes: Record<string, unknown>;
|
||||||
}
|
};
|
||||||
|
|
||||||
export const TableHeader = Node.create<TableHeaderOptions>({
|
export const TableHeader = Node.create<TableHeaderOptions>({
|
||||||
name: CORE_EXTENSIONS.TABLE_HEADER,
|
name: CORE_EXTENSIONS.TABLE_HEADER,
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,9 @@ import { mergeAttributes, Node } from "@tiptap/core";
|
||||||
// constants
|
// constants
|
||||||
import { CORE_EXTENSIONS } from "@/constants/extension";
|
import { CORE_EXTENSIONS } from "@/constants/extension";
|
||||||
|
|
||||||
export interface TableRowOptions {
|
type TableRowOptions = {
|
||||||
HTMLAttributes: Record<string, any>;
|
HTMLAttributes: Record<string, unknown>;
|
||||||
}
|
};
|
||||||
|
|
||||||
export const TableRow = Node.create<TableRowOptions>({
|
export const TableRow = Node.create<TableRowOptions>({
|
||||||
name: CORE_EXTENSIONS.TABLE_ROW,
|
name: CORE_EXTENSIONS.TABLE_ROW,
|
||||||
|
|
|
||||||
|
|
@ -32,14 +32,14 @@ import { insertLineAboveTableAction } from "./utilities/insert-line-above-table-
|
||||||
import { insertLineBelowTableAction } from "./utilities/insert-line-below-table-action";
|
import { insertLineBelowTableAction } from "./utilities/insert-line-below-table-action";
|
||||||
import { DEFAULT_COLUMN_WIDTH } from ".";
|
import { DEFAULT_COLUMN_WIDTH } from ".";
|
||||||
|
|
||||||
export interface TableOptions {
|
type TableOptions = {
|
||||||
HTMLAttributes: Record<string, any>;
|
HTMLAttributes: Record<string, unknown>;
|
||||||
resizable: boolean;
|
resizable: boolean;
|
||||||
handleWidth: number;
|
handleWidth: number;
|
||||||
cellMinWidth: number;
|
cellMinWidth: number;
|
||||||
lastColumnResizable: boolean;
|
lastColumnResizable: boolean;
|
||||||
allowTableNodeSelection: boolean;
|
allowTableNodeSelection: boolean;
|
||||||
}
|
};
|
||||||
|
|
||||||
declare module "@tiptap/core" {
|
declare module "@tiptap/core" {
|
||||||
interface Commands<ReturnType> {
|
interface Commands<ReturnType> {
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { Fragment, Node as ProsemirrorNode, NodeType } from "@tiptap/pm/model";
|
||||||
export function createCell(
|
export function createCell(
|
||||||
cellType: NodeType,
|
cellType: NodeType,
|
||||||
cellContent?: Fragment | ProsemirrorNode | Array<ProsemirrorNode>,
|
cellContent?: Fragment | ProsemirrorNode | Array<ProsemirrorNode>,
|
||||||
attrs?: Record<string, any>
|
attrs?: Record<string, unknown>
|
||||||
): ProsemirrorNode | null | undefined {
|
): ProsemirrorNode | null | undefined {
|
||||||
if (cellContent) {
|
if (cellContent) {
|
||||||
return cellType.createChecked(attrs, cellContent);
|
return cellType.createChecked(attrs, cellContent);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { Editor, findParentNodeClosestToPos, KeyboardShortcutCommand } from "@tiptap/core";
|
import { type Editor, findParentNodeClosestToPos, type KeyboardShortcutCommand } from "@tiptap/core";
|
||||||
import type { Node as ProseMirrorNode } from "@tiptap/pm/model";
|
import type { Node as ProseMirrorNode } from "@tiptap/pm/model";
|
||||||
import { CellSelection, TableMap } from "@tiptap/pm/tables";
|
import { CellSelection, TableMap } from "@tiptap/pm/tables";
|
||||||
// constants
|
// constants
|
||||||
|
|
@ -6,18 +6,18 @@ import { CORE_EXTENSIONS } from "@/constants/extension";
|
||||||
// extensions
|
// extensions
|
||||||
import { isCellEmpty, isCellSelection } from "@/extensions/table/table/utilities/helpers";
|
import { isCellEmpty, isCellSelection } from "@/extensions/table/table/utilities/helpers";
|
||||||
|
|
||||||
interface CellCoord {
|
type CellCoord = {
|
||||||
row: number;
|
row: number;
|
||||||
col: number;
|
col: number;
|
||||||
}
|
};
|
||||||
|
|
||||||
interface TableInfo {
|
type TableInfo = {
|
||||||
node: ProseMirrorNode;
|
node: ProseMirrorNode;
|
||||||
pos: number;
|
pos: number;
|
||||||
map: TableMap;
|
map: TableMap;
|
||||||
totalColumns: number;
|
totalColumns: number;
|
||||||
totalRows: number;
|
totalRows: number;
|
||||||
}
|
};
|
||||||
|
|
||||||
export const handleDeleteKeyOnTable: KeyboardShortcutCommand = (props) => {
|
export const handleDeleteKeyOnTable: KeyboardShortcutCommand = (props) => {
|
||||||
const { editor } = props;
|
const { editor } = props;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
import type { Node as ProseMirrorNode } from "@tiptap/pm/model";
|
import type { Node as ProseMirrorNode } from "@tiptap/pm/model";
|
||||||
import type { Selection } from "@tiptap/pm/state";
|
import type { Selection } from "@tiptap/pm/state";
|
||||||
import { CellSelection } from "@tiptap/pm/tables";
|
import { CellSelection } from "@tiptap/pm/tables";
|
||||||
|
// constants
|
||||||
|
import { CORE_EXTENSIONS } from "@/constants/extension";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Check if the selection is a cell selection
|
* @description Check if the selection is a cell selection
|
||||||
|
|
@ -22,7 +24,7 @@ export const isCellEmpty = (cell: ProseMirrorNode | null): boolean => {
|
||||||
// Check if cell has any non-empty content
|
// Check if cell has any non-empty content
|
||||||
let hasContent = false;
|
let hasContent = false;
|
||||||
cell.content.forEach((node) => {
|
cell.content.forEach((node) => {
|
||||||
if (node.type.name === "paragraph") {
|
if (node.type.name === CORE_EXTENSIONS.PARAGRAPH) {
|
||||||
if (node.content.size > 0) {
|
if (node.content.size > 0) {
|
||||||
hasContent = true;
|
hasContent = true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { textInputRule } from "@tiptap/core";
|
import { textInputRule } from "@tiptap/core";
|
||||||
|
|
||||||
export interface TypographyOptions {
|
export type TypographyOptions = {
|
||||||
emDash: false | string;
|
emDash: false | string;
|
||||||
ellipsis: false | string;
|
ellipsis: false | string;
|
||||||
leftArrow: false | string;
|
leftArrow: false | string;
|
||||||
|
|
@ -20,7 +20,7 @@ export interface TypographyOptions {
|
||||||
oneQuarter: false | string;
|
oneQuarter: false | string;
|
||||||
threeQuarters: false | string;
|
threeQuarters: false | string;
|
||||||
impliesArrowRight: false | string;
|
impliesArrowRight: false | string;
|
||||||
}
|
};
|
||||||
|
|
||||||
export const emDash = (override?: string) =>
|
export const emDash = (override?: string) =>
|
||||||
textInputRule({
|
textInputRule({
|
||||||
|
|
|
||||||
|
|
@ -30,13 +30,13 @@ declare module "@tiptap/core" {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UtilityExtensionStorage {
|
export type UtilityExtensionStorage = {
|
||||||
assetsList: TEditorAsset[];
|
assetsList: TEditorAsset[];
|
||||||
assetsUploadStatus: TFileHandler["assetsUploadStatus"];
|
assetsUploadStatus: TFileHandler["assetsUploadStatus"];
|
||||||
uploadInProgress: boolean;
|
uploadInProgress: boolean;
|
||||||
activeDropbarExtensions: TActiveDropbarExtensions[];
|
activeDropbarExtensions: TActiveDropbarExtensions[];
|
||||||
isTouchDevice: boolean;
|
isTouchDevice: boolean;
|
||||||
}
|
};
|
||||||
|
|
||||||
type Props = Pick<IEditorProps, "disabledExtensions"> & {
|
type Props = Pick<IEditorProps, "disabledExtensions"> & {
|
||||||
fileHandler: TFileHandler;
|
fileHandler: TFileHandler;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { ReactNodeViewRenderer, NodeViewWrapper } from "@tiptap/react";
|
import { ReactNodeViewRenderer, NodeViewWrapper, type NodeViewProps } from "@tiptap/react";
|
||||||
// local imports
|
// local imports
|
||||||
import { WorkItemEmbedExtensionConfig } from "./extension-config";
|
import { WorkItemEmbedExtensionConfig } from "./extension-config";
|
||||||
|
|
||||||
|
|
@ -17,7 +17,7 @@ type Props = {
|
||||||
export const WorkItemEmbedExtension = (props: Props) =>
|
export const WorkItemEmbedExtension = (props: Props) =>
|
||||||
WorkItemEmbedExtensionConfig.extend({
|
WorkItemEmbedExtensionConfig.extend({
|
||||||
addNodeView() {
|
addNodeView() {
|
||||||
return ReactNodeViewRenderer((issueProps: any) => (
|
return ReactNodeViewRenderer((issueProps: NodeViewProps) => (
|
||||||
<NodeViewWrapper>
|
<NodeViewWrapper>
|
||||||
{props.widgetCallback({
|
{props.widgetCallback({
|
||||||
issueId: issueProps.node.attrs.entity_identifier,
|
issueId: issueProps.node.attrs.entity_identifier,
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,13 @@ import { cn } from "@plane/utils";
|
||||||
// constants
|
// constants
|
||||||
import { CORE_EXTENSIONS } from "@/constants/extension";
|
import { CORE_EXTENSIONS } from "@/constants/extension";
|
||||||
|
|
||||||
interface EditorClassNames {
|
type EditorClassNameArgs = {
|
||||||
noBorder?: boolean;
|
noBorder?: boolean;
|
||||||
borderOnFocus?: boolean;
|
borderOnFocus?: boolean;
|
||||||
containerClassName?: string;
|
containerClassName?: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
export const getEditorClassNames = ({ noBorder, borderOnFocus, containerClassName }: EditorClassNames) =>
|
export const getEditorClassNames = ({ noBorder, borderOnFocus, containerClassName }: EditorClassNameArgs) =>
|
||||||
cn(
|
cn(
|
||||||
"w-full max-w-full sm:rounded-lg focus:outline-none focus:border-0",
|
"w-full max-w-full sm:rounded-lg focus:outline-none focus:border-0",
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,6 @@
|
||||||
import { Editor } from "@tiptap/react";
|
import type { Editor } from "@tiptap/react";
|
||||||
|
// types
|
||||||
export interface IMarking {
|
import type { IMarking } from "@/types";
|
||||||
type: "heading";
|
|
||||||
level: number;
|
|
||||||
text: string;
|
|
||||||
sequence: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
function findNthH1(editor: Editor, n: number, level: number): number {
|
function findNthH1(editor: Editor, n: number, level: number): number {
|
||||||
let count = 0;
|
let count = 0;
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,9 @@ import type { Selection } from "@tiptap/pm/state";
|
||||||
import type { EditorProps, EditorView } from "@tiptap/pm/view";
|
import type { EditorProps, EditorView } from "@tiptap/pm/view";
|
||||||
// extension types
|
// extension types
|
||||||
import type { TTextAlign } from "@/extensions";
|
import type { TTextAlign } from "@/extensions";
|
||||||
// helpers
|
|
||||||
import type { IMarking } from "@/helpers/scroll-to-node";
|
|
||||||
// types
|
// types
|
||||||
import type {
|
import type {
|
||||||
|
IMarking,
|
||||||
TAIHandler,
|
TAIHandler,
|
||||||
TDisplayConfig,
|
TDisplayConfig,
|
||||||
TDocumentEventEmitter,
|
TDocumentEventEmitter,
|
||||||
|
|
@ -129,7 +128,7 @@ export type EditorRefApi = {
|
||||||
};
|
};
|
||||||
|
|
||||||
// editor props
|
// editor props
|
||||||
export interface IEditorProps {
|
export type IEditorProps = {
|
||||||
autofocus?: boolean;
|
autofocus?: boolean;
|
||||||
bubbleMenuEnabled?: boolean;
|
bubbleMenuEnabled?: boolean;
|
||||||
containerClassName?: string;
|
containerClassName?: string;
|
||||||
|
|
@ -155,7 +154,7 @@ export interface IEditorProps {
|
||||||
placeholder?: string | ((isFocused: boolean, value: string) => string);
|
placeholder?: string | ((isFocused: boolean, value: string) => string);
|
||||||
tabIndex?: number;
|
tabIndex?: number;
|
||||||
value?: string | null;
|
value?: string | null;
|
||||||
}
|
};
|
||||||
|
|
||||||
export type ILiteTextEditorProps = IEditorProps;
|
export type ILiteTextEditorProps = IEditorProps;
|
||||||
|
|
||||||
|
|
@ -163,8 +162,7 @@ export type IRichTextEditorProps = IEditorProps & {
|
||||||
dragDropEnabled?: boolean;
|
dragDropEnabled?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface ICollaborativeDocumentEditorProps
|
export type ICollaborativeDocumentEditorProps = Omit<IEditorProps, "initialValue" | "onEnterKeyPress" | "value"> & {
|
||||||
extends Omit<IEditorProps, "initialValue" | "onEnterKeyPress" | "value"> {
|
|
||||||
aiHandler?: TAIHandler;
|
aiHandler?: TAIHandler;
|
||||||
documentLoaderClassName?: string;
|
documentLoaderClassName?: string;
|
||||||
dragDropEnabled?: boolean;
|
dragDropEnabled?: boolean;
|
||||||
|
|
@ -173,16 +171,16 @@ export interface ICollaborativeDocumentEditorProps
|
||||||
realtimeConfig: TRealtimeConfig;
|
realtimeConfig: TRealtimeConfig;
|
||||||
serverHandler?: TServerHandler;
|
serverHandler?: TServerHandler;
|
||||||
user: TUserDetails;
|
user: TUserDetails;
|
||||||
}
|
};
|
||||||
|
|
||||||
export interface IDocumentEditorProps extends Omit<IEditorProps, "initialValue" | "onEnterKeyPress" | "value"> {
|
export type IDocumentEditorProps = Omit<IEditorProps, "initialValue" | "onEnterKeyPress" | "value"> & {
|
||||||
aiHandler?: TAIHandler;
|
aiHandler?: TAIHandler;
|
||||||
embedHandler: TEmbedConfig;
|
embedHandler: TEmbedConfig;
|
||||||
user?: TUserDetails;
|
user?: TUserDetails;
|
||||||
value: Content;
|
value: Content;
|
||||||
}
|
};
|
||||||
|
|
||||||
export interface EditorEvents {
|
export type EditorEvents = {
|
||||||
beforeCreate: never;
|
beforeCreate: never;
|
||||||
create: never;
|
create: never;
|
||||||
update: never;
|
update: never;
|
||||||
|
|
@ -192,4 +190,4 @@ export interface EditorEvents {
|
||||||
blur: never;
|
blur: never;
|
||||||
destroy: never;
|
destroy: never;
|
||||||
ready: { height: number };
|
ready: { height: number };
|
||||||
}
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue