mirror of
https://github.com/docmost/docmost.git
synced 2026-05-07 06:23:06 +08:00
feat: Text background highlight (#1754)
* #1196/feat: add text background highlight * unify text color * dark mode support * unify text color and highlight * dark mode support for color selector trigger * fix see through in color selector dark mode * fix selection highlight in dark mode * brown color * clean up --------- Co-authored-by: sanua356 <sanek.pankratov356@gmail.com>
This commit is contained in:
@@ -234,9 +234,7 @@
|
|||||||
"Anyone with this link can join this workspace.": "Jeder mit diesem Link kann dem Arbeitsbereich beitreten.",
|
"Anyone with this link can join this workspace.": "Jeder mit diesem Link kann dem Arbeitsbereich beitreten.",
|
||||||
"Invite link": "Einladungslink",
|
"Invite link": "Einladungslink",
|
||||||
"Copy": "Kopieren",
|
"Copy": "Kopieren",
|
||||||
"Copy to space": "In Raum kopieren",
|
|
||||||
"Copied": "Kopiert",
|
"Copied": "Kopiert",
|
||||||
"Duplicate": "Duplizieren",
|
|
||||||
"Select a user": "Benutzer auswählen",
|
"Select a user": "Benutzer auswählen",
|
||||||
"Select a group": "Gruppe auswählen",
|
"Select a group": "Gruppe auswählen",
|
||||||
"Export all pages and attachments in this space.": "Alle Seiten und Anhänge in diesem Bereich exportieren.",
|
"Export all pages and attachments in this space.": "Alle Seiten und Anhänge in diesem Bereich exportieren.",
|
||||||
|
|||||||
@@ -554,5 +554,8 @@
|
|||||||
"Select expiration date": "Select expiration date",
|
"Select expiration date": "Select expiration date",
|
||||||
"This action cannot be undone. Any applications using this API key will stop working.": "This action cannot be undone. Any applications using this API key will stop working.",
|
"This action cannot be undone. Any applications using this API key will stop working.": "This action cannot be undone. Any applications using this API key will stop working.",
|
||||||
"Update API key": "Update API key",
|
"Update API key": "Update API key",
|
||||||
"Manage API keys for all users in the workspace": "Manage API keys for all users in the workspace"
|
"Manage API keys for all users in the workspace": "Manage API keys for all users in the workspace",
|
||||||
|
"Background color": "Background color",
|
||||||
|
"Highlight color": "Highlight color",
|
||||||
|
"Remove color": "Remove color"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -144,16 +144,16 @@ export const EditorBubbleMenu: FC<EditorBubbleMenuProps> = (props) => {
|
|||||||
onHide: () => {
|
onHide: () => {
|
||||||
setIsNodeSelectorOpen(false);
|
setIsNodeSelectorOpen(false);
|
||||||
setIsTextAlignmentOpen(false);
|
setIsTextAlignmentOpen(false);
|
||||||
setIsColorSelectorOpen(false);
|
|
||||||
setIsLinkSelectorOpen(false);
|
setIsLinkSelectorOpen(false);
|
||||||
|
setIsColorSelectorOpen(false);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const [isNodeSelectorOpen, setIsNodeSelectorOpen] = useState(false);
|
const [isNodeSelectorOpen, setIsNodeSelectorOpen] = useState(false);
|
||||||
const [isTextAlignmentSelectorOpen, setIsTextAlignmentOpen] = useState(false);
|
const [isTextAlignmentSelectorOpen, setIsTextAlignmentOpen] = useState(false);
|
||||||
const [isColorSelectorOpen, setIsColorSelectorOpen] = useState(false);
|
|
||||||
const [isLinkSelectorOpen, setIsLinkSelectorOpen] = useState(false);
|
const [isLinkSelectorOpen, setIsLinkSelectorOpen] = useState(false);
|
||||||
|
const [isColorSelectorOpen, setIsColorSelectorOpen] = useState(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BubbleMenu {...bubbleMenuProps}>
|
<BubbleMenu {...bubbleMenuProps}>
|
||||||
@@ -164,8 +164,8 @@ export const EditorBubbleMenu: FC<EditorBubbleMenuProps> = (props) => {
|
|||||||
setIsOpen={() => {
|
setIsOpen={() => {
|
||||||
setIsNodeSelectorOpen(!isNodeSelectorOpen);
|
setIsNodeSelectorOpen(!isNodeSelectorOpen);
|
||||||
setIsTextAlignmentOpen(false);
|
setIsTextAlignmentOpen(false);
|
||||||
setIsColorSelectorOpen(false);
|
|
||||||
setIsLinkSelectorOpen(false);
|
setIsLinkSelectorOpen(false);
|
||||||
|
setIsColorSelectorOpen(false);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -175,8 +175,8 @@ export const EditorBubbleMenu: FC<EditorBubbleMenuProps> = (props) => {
|
|||||||
setIsOpen={() => {
|
setIsOpen={() => {
|
||||||
setIsTextAlignmentOpen(!isTextAlignmentSelectorOpen);
|
setIsTextAlignmentOpen(!isTextAlignmentSelectorOpen);
|
||||||
setIsNodeSelectorOpen(false);
|
setIsNodeSelectorOpen(false);
|
||||||
setIsColorSelectorOpen(false);
|
|
||||||
setIsLinkSelectorOpen(false);
|
setIsLinkSelectorOpen(false);
|
||||||
|
setIsColorSelectorOpen(false);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Dispatch, FC, SetStateAction } from "react";
|
import React, { Dispatch, FC, SetStateAction } from "react";
|
||||||
import { IconCheck, IconPalette } from "@tabler/icons-react";
|
import { IconCheck, IconChevronDown, IconPalette } from "@tabler/icons-react";
|
||||||
import {
|
import {
|
||||||
ActionIcon,
|
ActionIcon,
|
||||||
Button,
|
Button,
|
||||||
@@ -8,6 +8,9 @@ import {
|
|||||||
ScrollArea,
|
ScrollArea,
|
||||||
Text,
|
Text,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
|
SimpleGrid,
|
||||||
|
Box,
|
||||||
|
Stack,
|
||||||
} from "@mantine/core";
|
} from "@mantine/core";
|
||||||
import type { Editor } from "@tiptap/react";
|
import type { Editor } from "@tiptap/react";
|
||||||
import { useEditorState } from "@tiptap/react";
|
import { useEditorState } from "@tiptap/react";
|
||||||
@@ -61,9 +64,12 @@ const TEXT_COLORS: BubbleColorMenuItem[] = [
|
|||||||
name: "Gray",
|
name: "Gray",
|
||||||
color: "#A8A29E",
|
color: "#A8A29E",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "Brown",
|
||||||
|
color: "#92400E",
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
// TODO: handle dark mode
|
|
||||||
const HIGHLIGHT_COLORS: BubbleColorMenuItem[] = [
|
const HIGHLIGHT_COLORS: BubbleColorMenuItem[] = [
|
||||||
{
|
{
|
||||||
name: "Default",
|
name: "Default",
|
||||||
@@ -71,35 +77,39 @@ const HIGHLIGHT_COLORS: BubbleColorMenuItem[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Blue",
|
name: "Blue",
|
||||||
color: "#c1ecf9",
|
color: "#98d8f2",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Green",
|
name: "Green",
|
||||||
color: "#acf79f",
|
color: "#7edb6c",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Purple",
|
name: "Purple",
|
||||||
color: "#f6f3f8",
|
color: "#e0d6ed",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Red",
|
name: "Red",
|
||||||
color: "#fdebeb",
|
color: "#ffc6c2",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Yellow",
|
name: "Yellow",
|
||||||
color: "#fbf4a2",
|
color: "#faf594",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Orange",
|
name: "Orange",
|
||||||
color: "#faebdd",
|
color: "#f5c8a9",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Pink",
|
name: "Pink",
|
||||||
color: "#faf1f5",
|
color: "#f5cfe0",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Gray",
|
name: "Gray",
|
||||||
color: "#f1f1ef",
|
color: "#dfdfd7",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Brown",
|
||||||
|
color: "#d7c4b7",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -112,17 +122,21 @@ export const ColorSelector: FC<ColorSelectorProps> = ({
|
|||||||
|
|
||||||
const editorState = useEditorState({
|
const editorState = useEditorState({
|
||||||
editor,
|
editor,
|
||||||
selector: ctx => {
|
selector: (ctx) => {
|
||||||
if (!ctx.editor) {
|
if (!ctx.editor) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const activeColors: Record<string, boolean> = {};
|
const activeColors: Record<string, boolean> = {};
|
||||||
TEXT_COLORS.forEach(({ color }) => {
|
TEXT_COLORS.forEach(({ color }) => {
|
||||||
activeColors[`text_${color}`] = ctx.editor.isActive("textStyle", { color });
|
activeColors[`text_${color}`] = ctx.editor.isActive("textStyle", {
|
||||||
|
color,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
HIGHLIGHT_COLORS.forEach(({ color }) => {
|
HIGHLIGHT_COLORS.forEach(({ color }) => {
|
||||||
activeColors[`highlight_${color}`] = ctx.editor.isActive("highlight", { color });
|
activeColors[`highlight_${color}`] = ctx.editor.isActive("highlight", {
|
||||||
|
color,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
return activeColors;
|
return activeColors;
|
||||||
@@ -133,67 +147,152 @@ export const ColorSelector: FC<ColorSelectorProps> = ({
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const activeColorItem = TEXT_COLORS.find(({ color }) =>
|
const activeColorItem = TEXT_COLORS.find(
|
||||||
editorState[`text_${color}`]
|
({ color }) => editorState[`text_${color}`],
|
||||||
);
|
);
|
||||||
|
|
||||||
const activeHighlightItem = HIGHLIGHT_COLORS.find(({ color }) =>
|
const activeHighlightItem = HIGHLIGHT_COLORS.find(
|
||||||
editorState[`highlight_${color}`]
|
({ color }) => editorState[`highlight_${color}`],
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Popover width={200} opened={isOpen} withArrow>
|
<Popover width={220} opened={isOpen} withArrow>
|
||||||
<Popover.Target>
|
<Popover.Target>
|
||||||
<Tooltip label={t("Text color")} withArrow>
|
<Tooltip label={t("Text color")} withArrow>
|
||||||
<ActionIcon
|
<Button
|
||||||
variant="default"
|
variant="default"
|
||||||
size="lg"
|
|
||||||
radius="0"
|
radius="0"
|
||||||
style={{
|
rightSection={<IconChevronDown size={16} />}
|
||||||
border: "none",
|
|
||||||
color: activeColorItem?.color,
|
|
||||||
}}
|
|
||||||
onClick={() => setIsOpen(!isOpen)}
|
onClick={() => setIsOpen(!isOpen)}
|
||||||
|
data-text-color={activeColorItem?.color || ""}
|
||||||
|
data-highlight-color={activeHighlightItem?.color || ""}
|
||||||
|
className="color-selector-trigger"
|
||||||
|
style={{
|
||||||
|
height: "34px",
|
||||||
|
border: "none",
|
||||||
|
fontWeight: 500,
|
||||||
|
fontSize: rem(16),
|
||||||
|
paddingLeft: rem(8),
|
||||||
|
paddingRight: rem(4),
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<IconPalette size={16} stroke={2} />
|
A
|
||||||
</ActionIcon>
|
</Button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</Popover.Target>
|
</Popover.Target>
|
||||||
|
|
||||||
<Popover.Dropdown>
|
<Popover.Dropdown>
|
||||||
{/* make mah responsive */}
|
|
||||||
<ScrollArea.Autosize type="scroll" mah="400">
|
<ScrollArea.Autosize type="scroll" mah="400">
|
||||||
<Text span c="dimmed" tt="uppercase" inherit>
|
<Stack gap="md">
|
||||||
{t("Color")}
|
<Box>
|
||||||
|
<Text size="sm" fw={600} mb="xs">
|
||||||
|
{t("Text color")}
|
||||||
</Text>
|
</Text>
|
||||||
|
<SimpleGrid cols={5} spacing="xs">
|
||||||
<Button.Group orientation="vertical">
|
|
||||||
{TEXT_COLORS.map(({ name, color }, index) => (
|
{TEXT_COLORS.map(({ name, color }, index) => (
|
||||||
<Button
|
<Tooltip key={index} label={t(name)} withArrow>
|
||||||
key={index}
|
<Box
|
||||||
variant="default"
|
|
||||||
leftSection={<span style={{ color }}>A</span>}
|
|
||||||
justify="left"
|
|
||||||
fullWidth
|
|
||||||
rightSection={
|
|
||||||
editorState[`text_${color}`] && (
|
|
||||||
<IconCheck style={{ width: rem(16) }} />
|
|
||||||
)
|
|
||||||
}
|
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (name === "Default") {
|
if (name === "Default") {
|
||||||
editor.commands.unsetColor();
|
editor.commands.unsetColor();
|
||||||
} else {
|
} else {
|
||||||
editor.chain().focus().setColor(color || "").run();
|
editor
|
||||||
|
.chain()
|
||||||
|
.focus()
|
||||||
|
.setColor(color || "")
|
||||||
|
.run();
|
||||||
}
|
}
|
||||||
setIsOpen(false);
|
setIsOpen(false);
|
||||||
}}
|
}}
|
||||||
style={{ border: "none" }}
|
style={{
|
||||||
|
width: rem(28),
|
||||||
|
height: rem(28),
|
||||||
|
borderRadius: rem(6),
|
||||||
|
border: editorState[`text_${color}`]
|
||||||
|
? "2px solid var(--mantine-color-gray-8)"
|
||||||
|
: "1px solid var(--mantine-color-gray-4)",
|
||||||
|
cursor: "pointer",
|
||||||
|
position: "relative",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
fontSize: rem(16),
|
||||||
|
fontWeight: 600,
|
||||||
|
color: color || "var(--mantine-color-gray-8)",
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{t(name)}
|
A
|
||||||
</Button>
|
</Box>
|
||||||
|
</Tooltip>
|
||||||
))}
|
))}
|
||||||
</Button.Group>
|
</SimpleGrid>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Box>
|
||||||
|
<Text size="sm" fw={600} mb="xs">
|
||||||
|
{t("Highlight color")}
|
||||||
|
</Text>
|
||||||
|
<SimpleGrid cols={5} spacing="xs">
|
||||||
|
{HIGHLIGHT_COLORS.map(({ name, color }, index) => (
|
||||||
|
<Tooltip key={index} label={t(name)} withArrow>
|
||||||
|
<Box
|
||||||
|
onClick={() => {
|
||||||
|
if (name === "Default") {
|
||||||
|
editor.commands.unsetHighlight();
|
||||||
|
} else {
|
||||||
|
editor
|
||||||
|
.chain()
|
||||||
|
.focus()
|
||||||
|
.toggleMark("highlight", {
|
||||||
|
color: color || "",
|
||||||
|
colorName: name.toLowerCase() || "",
|
||||||
|
})
|
||||||
|
.run();
|
||||||
|
}
|
||||||
|
setIsOpen(false);
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
width: rem(28),
|
||||||
|
height: rem(28),
|
||||||
|
borderRadius: rem(4),
|
||||||
|
backgroundColor: color || "var(--mantine-color-gray-2)",
|
||||||
|
border: "1px solid var(--mantine-color-gray-4)",
|
||||||
|
cursor: "pointer",
|
||||||
|
position: "relative",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
fontSize: rem(16),
|
||||||
|
fontWeight: 600,
|
||||||
|
color: "var(--mantine-color-gray-8)",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{editorState[`highlight_${color}`] ? (
|
||||||
|
<IconCheck
|
||||||
|
size={16}
|
||||||
|
color="var(--mantine-color-green-7)"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
"A"
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
</Tooltip>
|
||||||
|
))}
|
||||||
|
</SimpleGrid>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
variant="default"
|
||||||
|
fullWidth
|
||||||
|
onClick={() => {
|
||||||
|
editor.commands.unsetColor();
|
||||||
|
editor.commands.unsetHighlight();
|
||||||
|
setIsOpen(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t("Remove color")}
|
||||||
|
</Button>
|
||||||
|
</Stack>
|
||||||
</ScrollArea.Autosize>
|
</ScrollArea.Autosize>
|
||||||
</Popover.Dropdown>
|
</Popover.Dropdown>
|
||||||
</Popover>
|
</Popover>
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import { TaskItem } from "@tiptap/extension-task-item";
|
|||||||
import { Underline } from "@tiptap/extension-underline";
|
import { Underline } from "@tiptap/extension-underline";
|
||||||
import { Superscript } from "@tiptap/extension-superscript";
|
import { Superscript } from "@tiptap/extension-superscript";
|
||||||
import SubScript from "@tiptap/extension-subscript";
|
import SubScript from "@tiptap/extension-subscript";
|
||||||
import { Highlight } from "@tiptap/extension-highlight";
|
|
||||||
import { Typography } from "@tiptap/extension-typography";
|
import { Typography } from "@tiptap/extension-typography";
|
||||||
import { TextStyle } from "@tiptap/extension-text-style";
|
import { TextStyle } from "@tiptap/extension-text-style";
|
||||||
import { Color } from "@tiptap/extension-color";
|
import { Color } from "@tiptap/extension-color";
|
||||||
@@ -40,6 +39,7 @@ import {
|
|||||||
Mention,
|
Mention,
|
||||||
Subpages,
|
Subpages,
|
||||||
TableDndExtension,
|
TableDndExtension,
|
||||||
|
Highlight
|
||||||
} from "@docmost/editor-ext";
|
} from "@docmost/editor-ext";
|
||||||
import {
|
import {
|
||||||
randomElement,
|
randomElement,
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
);
|
);
|
||||||
color: light-dark(
|
color: light-dark(
|
||||||
var(--mantine-color-default-color),
|
var(--mantine-color-default-color),
|
||||||
var(--mantine-color-dark-0)
|
var(--mantine-color-white)
|
||||||
);
|
);
|
||||||
font-size: var(--mantine-font-size-md);
|
font-size: var(--mantine-font-size-md);
|
||||||
line-height: var(--mantine-line-height-xl);
|
line-height: var(--mantine-line-height-xl);
|
||||||
@@ -141,7 +141,7 @@
|
|||||||
|
|
||||||
.selection,
|
.selection,
|
||||||
*::selection {
|
*::selection {
|
||||||
background-color: Highlight;
|
background-color: light-dark(Highlight, var(--mantine-color-gray-7));
|
||||||
}
|
}
|
||||||
|
|
||||||
.comment-mark {
|
.comment-mark {
|
||||||
@@ -209,4 +209,3 @@
|
|||||||
.actionIconGroup {
|
.actionIconGroup {
|
||||||
background: var(--mantine-color-body);
|
background: var(--mantine-color-body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,177 @@
|
|||||||
|
/* Highlight colors with dark mode support */
|
||||||
|
|
||||||
|
.ProseMirror {
|
||||||
|
/* Blue */
|
||||||
|
mark[data-color="#98d8f2"] {
|
||||||
|
background-color: light-dark(
|
||||||
|
rgb(224 242 254),
|
||||||
|
rgba(37, 99, 235, 0.35)
|
||||||
|
) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Green */
|
||||||
|
mark[data-color="#7edb6c"] {
|
||||||
|
background-color: light-dark(
|
||||||
|
rgb(220 252 231),
|
||||||
|
rgba(0, 138, 0, 0.35)
|
||||||
|
) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Purple */
|
||||||
|
mark[data-color="#e0d6ed"] {
|
||||||
|
background-color: light-dark(
|
||||||
|
rgb(243 232 255),
|
||||||
|
rgba(147, 51, 234, 0.35)
|
||||||
|
) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Red */
|
||||||
|
mark[data-color="#ffc6c2"] {
|
||||||
|
background-color: light-dark(
|
||||||
|
rgb(255 228 230),
|
||||||
|
rgba(224, 0, 0, 0.35)
|
||||||
|
) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Yellow */
|
||||||
|
mark[data-color="#faf594"] {
|
||||||
|
background-color: light-dark(
|
||||||
|
rgb(254 249 195),
|
||||||
|
rgba(234, 179, 8, 0.35)
|
||||||
|
) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Orange */
|
||||||
|
mark[data-color="#f5c8a9"] {
|
||||||
|
background-color: light-dark(
|
||||||
|
rgb(251, 236, 221),
|
||||||
|
rgba(255, 165, 0, 0.45)
|
||||||
|
) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pink */
|
||||||
|
mark[data-color="#f5cfe0"] {
|
||||||
|
background-color: light-dark(
|
||||||
|
rgb(252, 241, 246),
|
||||||
|
rgba(186, 64, 129, 0.35)
|
||||||
|
) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Gray */
|
||||||
|
mark[data-color="#dfdfd7"] {
|
||||||
|
background-color: light-dark(
|
||||||
|
rgb(238 238 235),
|
||||||
|
rgba(168, 162, 158, 0.35)
|
||||||
|
) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Brown */
|
||||||
|
mark[data-color="#d7c4b7"] {
|
||||||
|
background-color: light-dark(
|
||||||
|
rgb(215 196 183),
|
||||||
|
rgba(146, 64, 14, 0.35)
|
||||||
|
) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Color selector trigger button styles */
|
||||||
|
.color-selector-trigger[data-text-color="#2563EB"] {
|
||||||
|
color: #2563EB !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-selector-trigger[data-text-color="#008A00"] {
|
||||||
|
color: #008A00 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-selector-trigger[data-text-color="#9333EA"] {
|
||||||
|
color: #9333EA !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-selector-trigger[data-text-color="#E00000"] {
|
||||||
|
color: #E00000 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-selector-trigger[data-text-color="#EAB308"] {
|
||||||
|
color: #EAB308 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-selector-trigger[data-text-color="#FFA500"] {
|
||||||
|
color: #FFA500 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-selector-trigger[data-text-color="#BA4081"] {
|
||||||
|
color: #BA4081 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-selector-trigger[data-text-color="#A8A29E"] {
|
||||||
|
color: #A8A29E !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-selector-trigger[data-text-color="#92400E"] {
|
||||||
|
color: #92400E !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Highlight background colors with light-dark support - solid colors for trigger button */
|
||||||
|
.color-selector-trigger[data-highlight-color="#98d8f2"] {
|
||||||
|
background-color: light-dark(
|
||||||
|
rgb(224 242 254),
|
||||||
|
rgb(30 64 175)
|
||||||
|
) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-selector-trigger[data-highlight-color="#7edb6c"] {
|
||||||
|
background-color: light-dark(
|
||||||
|
rgb(220 252 231),
|
||||||
|
rgb(21 128 61)
|
||||||
|
) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-selector-trigger[data-highlight-color="#e0d6ed"] {
|
||||||
|
background-color: light-dark(
|
||||||
|
rgb(243 232 255),
|
||||||
|
rgb(107 33 168)
|
||||||
|
) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-selector-trigger[data-highlight-color="#ffc6c2"] {
|
||||||
|
background-color: light-dark(
|
||||||
|
rgb(255 228 230),
|
||||||
|
rgb(185 28 28)
|
||||||
|
) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-selector-trigger[data-highlight-color="#faf594"] {
|
||||||
|
background-color: light-dark(
|
||||||
|
rgb(254 249 195),
|
||||||
|
rgb(161 98 7)
|
||||||
|
) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-selector-trigger[data-highlight-color="#f5c8a9"] {
|
||||||
|
background-color: light-dark(
|
||||||
|
rgb(251 236 221),
|
||||||
|
rgb(194 65 12)
|
||||||
|
) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-selector-trigger[data-highlight-color="#f5cfe0"] {
|
||||||
|
background-color: light-dark(
|
||||||
|
rgb(252 241 246),
|
||||||
|
rgb(157 23 77)
|
||||||
|
) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-selector-trigger[data-highlight-color="#dfdfd7"] {
|
||||||
|
background-color: light-dark(
|
||||||
|
rgb(238 238 235),
|
||||||
|
rgb(115 115 115)
|
||||||
|
) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-selector-trigger[data-highlight-color="#d7c4b7"] {
|
||||||
|
background-color: light-dark(
|
||||||
|
rgb(215 196 183),
|
||||||
|
rgb(120 53 15)
|
||||||
|
) !important;
|
||||||
|
}
|
||||||
@@ -12,3 +12,4 @@
|
|||||||
@import "./find.css";
|
@import "./find.css";
|
||||||
@import "./mention.css";
|
@import "./mention.css";
|
||||||
@import "./ordered-list.css";
|
@import "./ordered-list.css";
|
||||||
|
@import "./highlight.css";
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import { TaskItem } from '@tiptap/extension-task-item';
|
|||||||
import { Underline } from '@tiptap/extension-underline';
|
import { Underline } from '@tiptap/extension-underline';
|
||||||
import { Superscript } from '@tiptap/extension-superscript';
|
import { Superscript } from '@tiptap/extension-superscript';
|
||||||
import SubScript from '@tiptap/extension-subscript';
|
import SubScript from '@tiptap/extension-subscript';
|
||||||
import { Highlight } from '@tiptap/extension-highlight';
|
|
||||||
import { Typography } from '@tiptap/extension-typography';
|
import { Typography } from '@tiptap/extension-typography';
|
||||||
import { TextStyle } from '@tiptap/extension-text-style';
|
import { TextStyle } from '@tiptap/extension-text-style';
|
||||||
import { Color } from '@tiptap/extension-color';
|
import { Color } from '@tiptap/extension-color';
|
||||||
@@ -33,6 +32,7 @@ import {
|
|||||||
Embed,
|
Embed,
|
||||||
Mention,
|
Mention,
|
||||||
Subpages,
|
Subpages,
|
||||||
|
Highlight
|
||||||
} from '@docmost/editor-ext';
|
} from '@docmost/editor-ext';
|
||||||
import { generateText, getSchema, JSONContent } from '@tiptap/core';
|
import { generateText, getSchema, JSONContent } from '@tiptap/core';
|
||||||
import { generateHTML, generateJSON } from '../common/helpers/prosemirror/html';
|
import { generateHTML, generateJSON } from '../common/helpers/prosemirror/html';
|
||||||
|
|||||||
@@ -20,3 +20,4 @@ export * from "./lib/markdown";
|
|||||||
export * from "./lib/search-and-replace";
|
export * from "./lib/search-and-replace";
|
||||||
export * from "./lib/embed-provider";
|
export * from "./lib/embed-provider";
|
||||||
export * from "./lib/subpages";
|
export * from "./lib/subpages";
|
||||||
|
export * from "./lib/highlight";
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
import {
|
||||||
|
Highlight as TiptapHighlight,
|
||||||
|
type HighlightOptions,
|
||||||
|
} from "@tiptap/extension-highlight";
|
||||||
|
|
||||||
|
export const Highlight = TiptapHighlight.extend<HighlightOptions>({
|
||||||
|
addAttributes() {
|
||||||
|
return {
|
||||||
|
...this.parent?.(),
|
||||||
|
color: {
|
||||||
|
default: null,
|
||||||
|
parseHTML: (element) =>
|
||||||
|
element.getAttribute("data-color") || element.style.backgroundColor,
|
||||||
|
renderHTML: (attributes) => {
|
||||||
|
if (!attributes.color) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
"data-color": attributes.color,
|
||||||
|
style: `background-color: ${attributes.color}; color: inherit`,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
colorName: {
|
||||||
|
default: null,
|
||||||
|
parseHTML: (element) =>
|
||||||
|
element.getAttribute("data-highlight-color-name") || null,
|
||||||
|
renderHTML: (attributes) => {
|
||||||
|
if (!attributes.colorName) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
"data-highlight-color-name": attributes.colorName.toLowerCase(),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user