mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
chore: update custom css variables
This commit is contained in:
parent
78bb3085f3
commit
b1c6eaf2f0
@ -1,16 +1,10 @@
|
|||||||
import { BubbleMenu, BubbleMenuProps } from "@tiptap/react";
|
import { BubbleMenu, BubbleMenuProps } from "@tiptap/react";
|
||||||
import { FC, useState } from "react";
|
import { FC, useState } from "react";
|
||||||
import {
|
import { BoldIcon, ItalicIcon, UnderlineIcon, StrikethroughIcon, CodeIcon } from "lucide-react";
|
||||||
BoldIcon,
|
|
||||||
ItalicIcon,
|
|
||||||
UnderlineIcon,
|
|
||||||
StrikethroughIcon,
|
|
||||||
CodeIcon,
|
|
||||||
} from "lucide-react";
|
|
||||||
|
|
||||||
import { NodeSelector } from "./node-selector";
|
import { NodeSelector } from "./node-selector";
|
||||||
import { LinkSelector } from "./link-selector";
|
import { LinkSelector } from "./link-selector";
|
||||||
import { cn } from "../utils"
|
import { cn } from "../utils";
|
||||||
|
|
||||||
export interface BubbleMenuItem {
|
export interface BubbleMenuItem {
|
||||||
name: string;
|
name: string;
|
||||||
@ -81,7 +75,7 @@ export const EditorBubbleMenu: FC<EditorBubbleMenuProps> = (props) => {
|
|||||||
return (
|
return (
|
||||||
<BubbleMenu
|
<BubbleMenu
|
||||||
{...bubbleMenuProps}
|
{...bubbleMenuProps}
|
||||||
className="flex w-fit divide-x divide-custom-border-400 rounded border border-custom-text-200 bg-custom-background-100 shadow-xl"
|
className="flex w-fit divide-x divide-custom-border-300 rounded border border-custom-border-300 bg-custom-background-100 shadow-xl"
|
||||||
>
|
>
|
||||||
<NodeSelector
|
<NodeSelector
|
||||||
editor={props.editor}
|
editor={props.editor}
|
||||||
@ -108,7 +102,7 @@ export const EditorBubbleMenu: FC<EditorBubbleMenuProps> = (props) => {
|
|||||||
>
|
>
|
||||||
<item.icon
|
<item.icon
|
||||||
className={cn("h-4 w-4", {
|
className={cn("h-4 w-4", {
|
||||||
"text-blue-500": item.isActive(),
|
"text-custom-primary-100": item.isActive(),
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { Editor } from "@tiptap/core";
|
import { Editor } from "@tiptap/core";
|
||||||
import { Check, Trash } from "lucide-react";
|
import { Check, Trash } from "lucide-react";
|
||||||
import { Dispatch, FC, SetStateAction, useEffect, useRef } from "react";
|
import { Dispatch, FC, SetStateAction, useEffect, useRef } from "react";
|
||||||
import { cn } from '../utils';
|
import { cn } from "../utils";
|
||||||
|
|
||||||
interface LinkSelectorProps {
|
interface LinkSelectorProps {
|
||||||
editor: Editor;
|
editor: Editor;
|
||||||
@ -9,11 +9,7 @@ interface LinkSelectorProps {
|
|||||||
setIsOpen: Dispatch<SetStateAction<boolean>>;
|
setIsOpen: Dispatch<SetStateAction<boolean>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const LinkSelector: FC<LinkSelectorProps> = ({
|
export const LinkSelector: FC<LinkSelectorProps> = ({ editor, isOpen, setIsOpen }) => {
|
||||||
editor,
|
|
||||||
isOpen,
|
|
||||||
setIsOpen,
|
|
||||||
}) => {
|
|
||||||
const inputRef = useRef<HTMLInputElement>(null);
|
const inputRef = useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -46,13 +42,13 @@ export const LinkSelector: FC<LinkSelectorProps> = ({
|
|||||||
editor.chain().focus().setLink({ href: input.value }).run();
|
editor.chain().focus().setLink({ href: input.value }).run();
|
||||||
setIsOpen(false);
|
setIsOpen(false);
|
||||||
}}
|
}}
|
||||||
className="fixed top-full z-[99999] mt-1 flex w-60 overflow-hidden rounded border border-custom-border-100 bg-custom-background-100 dow-xl animate-in fade-in slide-in-from-top-1"
|
className="fixed top-full z-[99999] mt-1 flex w-60 overflow-hidden rounded border border-custom-border-300 bg-custom-background-100 dow-xl animate-in fade-in slide-in-from-top-1"
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
type="url"
|
type="url"
|
||||||
placeholder="Paste a link"
|
placeholder="Paste a link"
|
||||||
className="flex-1 bg-custom-background-100 border border-blue-900 p-1 text-sm outline-none"
|
className="flex-1 bg-custom-background-100 border border-custom-border-300 p-1 text-sm outline-none placeholder:text-custom-text-400"
|
||||||
defaultValue={editor.getAttributes("link").href || ""}
|
defaultValue={editor.getAttributes("link").href || ""}
|
||||||
/>
|
/>
|
||||||
{editor.getAttributes("link").href ? (
|
{editor.getAttributes("link").href ? (
|
||||||
@ -66,7 +62,7 @@ export const LinkSelector: FC<LinkSelectorProps> = ({
|
|||||||
<Trash className="h-4 w-4" />
|
<Trash className="h-4 w-4" />
|
||||||
</button>
|
</button>
|
||||||
) : (
|
) : (
|
||||||
<button className="flex items-center rounded-sm p-1 text-custom-text-300 transition-all hover:bg-stone-100">
|
<button className="flex items-center rounded-sm p-1 text-custom-text-300 transition-all hover:bg-custom-background-90">
|
||||||
<Check className="h-4 w-4" />
|
<Check className="h-4 w-4" />
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
@ -75,4 +71,3 @@ export const LinkSelector: FC<LinkSelectorProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -22,17 +22,12 @@ interface NodeSelectorProps {
|
|||||||
setIsOpen: Dispatch<SetStateAction<boolean>>;
|
setIsOpen: Dispatch<SetStateAction<boolean>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const NodeSelector: FC<NodeSelectorProps> = ({
|
export const NodeSelector: FC<NodeSelectorProps> = ({ editor, isOpen, setIsOpen }) => {
|
||||||
editor,
|
|
||||||
isOpen,
|
|
||||||
setIsOpen,
|
|
||||||
}) => {
|
|
||||||
const items: BubbleMenuItem[] = [
|
const items: BubbleMenuItem[] = [
|
||||||
{
|
{
|
||||||
name: "Text",
|
name: "Text",
|
||||||
icon: TextIcon,
|
icon: TextIcon,
|
||||||
command: () =>
|
command: () => editor.chain().focus().toggleNode("paragraph", "paragraph").run(),
|
||||||
editor.chain().focus().toggleNode("paragraph", "paragraph").run(),
|
|
||||||
isActive: () =>
|
isActive: () =>
|
||||||
editor.isActive("paragraph") &&
|
editor.isActive("paragraph") &&
|
||||||
!editor.isActive("bulletList") &&
|
!editor.isActive("bulletList") &&
|
||||||
@ -78,12 +73,7 @@ export const NodeSelector: FC<NodeSelectorProps> = ({
|
|||||||
name: "Quote",
|
name: "Quote",
|
||||||
icon: TextQuote,
|
icon: TextQuote,
|
||||||
command: () =>
|
command: () =>
|
||||||
editor
|
editor.chain().focus().toggleNode("paragraph", "paragraph").toggleBlockquote().run(),
|
||||||
.chain()
|
|
||||||
.focus()
|
|
||||||
.toggleNode("paragraph", "paragraph")
|
|
||||||
.toggleBlockquote()
|
|
||||||
.run(),
|
|
||||||
isActive: () => editor.isActive("blockquote"),
|
isActive: () => editor.isActive("blockquote"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -117,10 +107,13 @@ export const NodeSelector: FC<NodeSelectorProps> = ({
|
|||||||
item.command();
|
item.command();
|
||||||
setIsOpen(false);
|
setIsOpen(false);
|
||||||
}}
|
}}
|
||||||
className={cn("flex items-center justify-between rounded-sm px-2 py-1 text-sm text-custom-text-200 hover:bg-gray-800 hover:text-custom-text-100", { "bg-gray-800": activeItem.name === item.name })}
|
className={cn(
|
||||||
|
"flex items-center justify-between rounded-sm px-2 py-1 text-sm text-custom-text-200 hover:bg-custom-background-100/5 hover:text-custom-text-100",
|
||||||
|
{ "bg-custom-primary-100/5": activeItem.name === item.name }
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
<div className="flex items-center space-x-2">
|
<div className="flex items-center space-x-2">
|
||||||
<div className="rounded-sm border border-custom-border-300 p-1" >
|
<div className="rounded-sm border border-custom-border-300 p-1">
|
||||||
<item.icon className="h-3 w-3" />
|
<item.icon className="h-3 w-3" />
|
||||||
</div>
|
</div>
|
||||||
<span>{item.name}</span>
|
<span>{item.name}</span>
|
||||||
@ -129,8 +122,7 @@ export const NodeSelector: FC<NodeSelectorProps> = ({
|
|||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
</section>
|
</section>
|
||||||
)
|
)}
|
||||||
}
|
</div>
|
||||||
</div >
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -11,18 +11,18 @@ import TaskList from "@tiptap/extension-task-list";
|
|||||||
import { Markdown } from "tiptap-markdown";
|
import { Markdown } from "tiptap-markdown";
|
||||||
import Highlight from "@tiptap/extension-highlight";
|
import Highlight from "@tiptap/extension-highlight";
|
||||||
import CodeBlockLowlight from "@tiptap/extension-code-block-lowlight";
|
import CodeBlockLowlight from "@tiptap/extension-code-block-lowlight";
|
||||||
import { lowlight } from 'lowlight/lib/core'
|
import { lowlight } from "lowlight/lib/core";
|
||||||
import SlashCommand from "../slash-command";
|
import SlashCommand from "../slash-command";
|
||||||
import { InputRule } from "@tiptap/core";
|
import { InputRule } from "@tiptap/core";
|
||||||
import { Node as ProseMirrorNode } from '@tiptap/pm/model';
|
import { Node as ProseMirrorNode } from "@tiptap/pm/model";
|
||||||
|
|
||||||
import ts from 'highlight.js/lib/languages/typescript'
|
import ts from "highlight.js/lib/languages/typescript";
|
||||||
|
|
||||||
import 'highlight.js/styles/github-dark.css';
|
import "highlight.js/styles/github-dark.css";
|
||||||
import UploadImagesPlugin from "../plugins/upload-image";
|
import UploadImagesPlugin from "../plugins/upload-image";
|
||||||
import UniqueID from "@tiptap-pro/extension-unique-id";
|
import UniqueID from "@tiptap-pro/extension-unique-id";
|
||||||
|
|
||||||
lowlight.registerLanguage('ts', ts)
|
lowlight.registerLanguage("ts", ts);
|
||||||
|
|
||||||
const CustomImage = TiptapImage.extend({
|
const CustomImage = TiptapImage.extend({
|
||||||
addProseMirrorPlugins() {
|
addProseMirrorPlugins() {
|
||||||
@ -49,13 +49,12 @@ export const TiptapExtensions = [
|
|||||||
},
|
},
|
||||||
blockquote: {
|
blockquote: {
|
||||||
HTMLAttributes: {
|
HTMLAttributes: {
|
||||||
class: "border-l-4 border-stone-700",
|
class: "border-l-4 border-custom-border-300",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
code: {
|
code: {
|
||||||
HTMLAttributes: {
|
HTMLAttributes: {
|
||||||
class:
|
class: "rounded-md bg-custom-bg-1000 px-1 py-1 font-mono font-medium text-custom-text-200",
|
||||||
"rounded-md bg-custom-bg-1000 px-1 py-1 font-mono font-medium text-stone-900",
|
|
||||||
spellcheck: "false",
|
spellcheck: "false",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -84,25 +83,25 @@ export const TiptapExtensions = [
|
|||||||
const end = range.to;
|
const end = range.to;
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
tr.replaceWith(start - 1, end, this.type.create(attributes));
|
tr.replaceWith(start - 1, end, this.type.create(attributes));
|
||||||
}
|
},
|
||||||
}),
|
}),
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
}).configure({
|
}).configure({
|
||||||
HTMLAttributes: {
|
HTMLAttributes: {
|
||||||
class: "mb-6 border-t border-custom-border-400",
|
class: "mb-6 border-t border-custom-border-300",
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
TiptapLink.configure({
|
TiptapLink.configure({
|
||||||
HTMLAttributes: {
|
HTMLAttributes: {
|
||||||
class:
|
class:
|
||||||
"text-stone-400 underline underline-offset-[3px] hover:text-stone-600 transition-colors cursor-pointer",
|
"text-custom-text-200 underline underline-offset-[3px] hover:text-custom-text-100 transition-colors cursor-pointer",
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
CustomImage.configure({
|
CustomImage.configure({
|
||||||
allowBase64: true,
|
allowBase64: true,
|
||||||
HTMLAttributes: {
|
HTMLAttributes: {
|
||||||
class: "rounded-lg border border-stone-200",
|
class: "rounded-lg border border-custom-border-300",
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
Placeholder.configure({
|
Placeholder.configure({
|
||||||
@ -116,7 +115,7 @@ export const TiptapExtensions = [
|
|||||||
includeChildren: true,
|
includeChildren: true,
|
||||||
}),
|
}),
|
||||||
UniqueID.configure({
|
UniqueID.configure({
|
||||||
types: ['image'],
|
types: ["image"],
|
||||||
}),
|
}),
|
||||||
SlashCommand,
|
SlashCommand,
|
||||||
TiptapUnderline,
|
TiptapUnderline,
|
||||||
|
@ -22,10 +22,7 @@ const UploadImagesPlugin = () =>
|
|||||||
const placeholder = document.createElement("div");
|
const placeholder = document.createElement("div");
|
||||||
placeholder.setAttribute("class", "img-placeholder");
|
placeholder.setAttribute("class", "img-placeholder");
|
||||||
const image = document.createElement("img");
|
const image = document.createElement("img");
|
||||||
image.setAttribute(
|
image.setAttribute("class", "opacity-10 rounded-lg border border-custom-border-300");
|
||||||
"class",
|
|
||||||
"opacity-10 rounded-lg border border-stone-200",
|
|
||||||
);
|
|
||||||
image.src = src;
|
image.src = src;
|
||||||
placeholder.appendChild(image);
|
placeholder.appendChild(image);
|
||||||
const deco = Decoration.widget(pos + 1, placeholder, {
|
const deco = Decoration.widget(pos + 1, placeholder, {
|
||||||
@ -33,9 +30,7 @@ const UploadImagesPlugin = () =>
|
|||||||
});
|
});
|
||||||
set = set.add(tr.doc, [deco]);
|
set = set.add(tr.doc, [deco]);
|
||||||
} else if (action && action.remove) {
|
} else if (action && action.remove) {
|
||||||
set = set.remove(
|
set = set.remove(set.find(undefined, undefined, (spec) => spec.id == action.remove.id));
|
||||||
set.find(undefined, undefined, (spec) => spec.id == action.remove.id),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return set;
|
return set;
|
||||||
},
|
},
|
||||||
@ -43,7 +38,7 @@ const UploadImagesPlugin = () =>
|
|||||||
props: {
|
props: {
|
||||||
decorations(state) {
|
decorations(state) {
|
||||||
return this.getState(state);
|
return this.getState(state);
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -51,7 +46,11 @@ export default UploadImagesPlugin;
|
|||||||
|
|
||||||
function findPlaceholder(state: EditorState, id: {}) {
|
function findPlaceholder(state: EditorState, id: {}) {
|
||||||
const decos = uploadKey.getState(state);
|
const decos = uploadKey.getState(state);
|
||||||
const found = decos.find(undefined, undefined, (spec: { id: number | undefined }) => spec.id == id);
|
const found = decos.find(
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
(spec: { id: number | undefined }) => spec.id == id
|
||||||
|
);
|
||||||
return found.length ? found[0].from : null;
|
return found.length ? found[0].from : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,7 +80,7 @@ export async function startImageUpload(file: File, view: EditorView, pos: number
|
|||||||
};
|
};
|
||||||
|
|
||||||
const src = await UploadImageHandler(file);
|
const src = await UploadImageHandler(file);
|
||||||
console.log(src, "src")
|
console.log(src, "src");
|
||||||
const { schema } = view.state;
|
const { schema } = view.state;
|
||||||
pos = findPlaceholder(view.state, id);
|
pos = findPlaceholder(view.state, id);
|
||||||
|
|
||||||
@ -111,10 +110,9 @@ const UploadImageHandler = (file: File): Promise<string> => {
|
|||||||
image.onload = () => {
|
image.onload = () => {
|
||||||
resolve(imageUrl);
|
resolve(imageUrl);
|
||||||
};
|
};
|
||||||
})
|
});
|
||||||
}
|
} catch (error) {
|
||||||
catch (error) {
|
console.log(error);
|
||||||
console.log(error)
|
|
||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -261,19 +261,19 @@ const CommandList = ({
|
|||||||
<div
|
<div
|
||||||
id="slash-command"
|
id="slash-command"
|
||||||
ref={commandListContainer}
|
ref={commandListContainer}
|
||||||
className="z-20 h-auto max-h-[330px] w-72 overflow-y-auto rounded-md border border-custom-border-200 bg-custom-background-100 px-1 py-2 shadow-md transition-all"
|
className="z-20 h-auto max-h-[330px] w-72 overflow-y-auto rounded-md border border-custom-border-300 bg-custom-background-100 px-1 py-2 shadow-md transition-all"
|
||||||
>
|
>
|
||||||
{items.map((item: CommandItemProps, index: number) => (
|
{items.map((item: CommandItemProps, index: number) => (
|
||||||
<button
|
<button
|
||||||
className={`flex w-full items-center space-x-2 rounded-md px-2 py-1 text-left text-sm text-custom-text-90 hover:text-custom-text-100 ${
|
className={`flex w-full items-center space-x-2 rounded-md px-2 py-1 text-left text-sm hover:bg-custom-primary-100/5 ${
|
||||||
index === selectedIndex ? "bg-gray-800 text-custom-text-90" : ""
|
index === selectedIndex ? "bg-custom-primary-100/5" : ""
|
||||||
}`}
|
}`}
|
||||||
key={index}
|
key={index}
|
||||||
onClick={() => selectItem(index)}
|
onClick={() => selectItem(index)}
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<p className="font-medium">{item.title}</p>
|
<p className="font-medium">{item.title}</p>
|
||||||
<p className="text-xs text-stone-500">{item.description}</p>
|
<p className="text-xs text-custom-text-200">{item.description}</p>
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
|
Loading…
Reference in New Issue
Block a user