feat: cache last used color

This commit is contained in:
thecodrr
2022-06-21 09:32:32 +05:00
parent d5efcd95fd
commit 14e68b514a
10 changed files with 102 additions and 62 deletions

View File

@@ -23,7 +23,7 @@ export declare class PortalProvider extends React.Component<BasePortalProviderPr
static displayName: string;
portalProviderAPI: PortalProviderAPI;
constructor(props: BasePortalProviderProps);
render(): React.ReactChild | JSX.Element | null;
render(): JSX.Element | React.ReactChild | null;
componentDidUpdate(): void;
}
export declare class PortalRenderer extends React.Component<{

View File

@@ -2,7 +2,7 @@
export declare const DEFAULT_COLORS: string[];
declare type ColorPickerProps = {
colors?: string[];
color: string;
color?: string;
onClear: () => void;
expanded?: boolean;
onChange: (color: string) => void;

View File

@@ -55,7 +55,7 @@ export function ColorPicker(props) {
var _a = props.colors, colors = _a === void 0 ? DEFAULT_COLORS : _a, color = props.color, onClear = props.onClear, onChange = props.onChange, title = props.title, onClose = props.onClose, expanded = props.expanded;
var ref = useRef();
var _b = __read(useState(expanded || false), 2), isPickerOpen = _b[0], setIsPickerOpen = _b[1];
var _c = __read(useState(tinycolor(color).toHexString()), 2), currentColor = _c[0], setCurrentColor = _c[1];
var _c = __read(useState(tinycolor(color || colors[0]).toHexString()), 2), currentColor = _c[0], setCurrentColor = _c[1];
var tColor = tinycolor(currentColor);
useEffect(function () {
if (!ref.current)

View File

@@ -3,9 +3,9 @@ import { Editor } from "@tiptap/core";
import { ToolProps } from "../types";
declare type ColorToolProps = ToolProps & {
onColorChange: (editor: Editor, color?: string) => void;
isActive: (editor: Editor) => boolean;
getActiveColor: (editor: Editor) => string;
title: string;
cacheKey: string;
};
export declare function ColorTool(props: ColorToolProps): JSX.Element;
export declare function Highlight(props: ToolProps): JSX.Element;

View File

@@ -40,55 +40,46 @@ import { jsx as _jsx } from "react/jsx-runtime";
import { useState } from "react";
import tinycolor from "tinycolor2";
import { PopupWrapper } from "../../components/popup-presenter";
import { useEditorContext } from "../../components/popup-presenter/popuprenderer";
import { config } from "../../utils/config";
import { SplitButton } from "../components/split-button";
import { ColorPicker } from "../popups/color-picker";
import { useToolbarLocation } from "../stores/toolbar-store";
import { getToolbarElement } from "../utils/dom";
export function ColorTool(props) {
var onColorChange = props.onColorChange, isActive = props.isActive, getActiveColor = props.getActiveColor, title = props.title, toolProps = __rest(props, ["onColorChange", "isActive", "getActiveColor", "title"]);
var editor = useEditorContext();
var activeColor = getActiveColor(editor);
var _isActive = isActive(editor);
var editor = props.editor, onColorChange = props.onColorChange, getActiveColor = props.getActiveColor, title = props.title, cacheKey = props.cacheKey, toolProps = __rest(props, ["editor", "onColorChange", "getActiveColor", "title", "cacheKey"]);
var activeColor = getActiveColor(editor) || config.get(cacheKey);
var tColor = tinycolor(activeColor);
var toolbarLocation = useToolbarLocation();
var isBottom = toolbarLocation === "bottom";
var isBottom = useToolbarLocation() === "bottom";
var _a = __read(useState(false), 2), isOpen = _a[0], setIsOpen = _a[1];
// const { hide, isOpen, show } = usePopup({
// id: title,
// group: "color",
// theme: editor?.storage.theme,
// blocking: false,
// focusOnRender: false,
// });
// console.log("Updating color", editor);
return (_jsx(SplitButton, __assign({}, toolProps, { iconColor: _isActive && tColor.isDark() ? "static" : "icon", sx: {
return (_jsx(SplitButton, __assign({}, toolProps, { iconColor: activeColor && tColor.isDark() ? "static" : "icon", sx: {
mr: 0,
bg: _isActive ? activeColor : "transparent",
bg: activeColor || "transparent",
":hover": {
bg: _isActive && !isBottom
? tColor.darken(5).toRgbString()
: "transparent",
bg: activeColor ? tColor.darken(5).toRgbString() : "transparent",
},
}, onOpen: function () {
setIsOpen(function (s) { return !s; });
}, toggled: isOpen }, { children: _jsx(PopupWrapper, { isOpen: isOpen, id: props.icon, group: "color", position: {
}, onOpen: function () { return setIsOpen(function (s) { return !s; }); }, toggled: isOpen, onClick: function () { return onColorChange(editor, activeColor); } }, { children: _jsx(PopupWrapper, { isOpen: isOpen, id: props.icon, group: "color", position: {
isTargetAbsolute: true,
target: getToolbarElement(),
align: isBottom ? "center" : "end",
location: isBottom ? "top" : "below",
yOffset: 10,
}, focusOnRender: false, blocking: false, renderPopup: function (close) { return (_jsx(ColorPicker, { color: activeColor, onClear: function () { return onColorChange(editor); }, onChange: function (color) { return onColorChange(editor, color); }, onClose: close, title: title })); } }) })));
}, focusOnRender: false, blocking: false, renderPopup: function (close) { return (_jsx(ColorPicker, { color: activeColor, onClear: function () {
onColorChange(editor);
config.set(cacheKey, null);
}, onChange: function (color) {
onColorChange(editor, color);
config.set(cacheKey, color);
}, onClose: close, title: title })); } }) })));
}
export function Highlight(props) {
return (_jsx(ColorTool, __assign({}, props, { isActive: function (editor) { return editor.isActive("highlight", { color: /\W+/gm }); }, getActiveColor: function (editor) { return editor.getAttributes("highlight").color; }, title: "Background color", onColorChange: function (editor, color) {
return (_jsx(ColorTool, __assign({}, props, { cacheKey: "highlight", getActiveColor: function (editor) { return editor.getAttributes("highlight").color; }, title: "Background color", onColorChange: function (editor, color) {
return color
? editor.chain().focus().toggleHighlight({ color: color }).run()
: editor.chain().focus().unsetHighlight().run();
} })));
}
export function TextColor(props) {
return (_jsx(ColorTool, __assign({}, props, { isActive: function (editor) { return editor.isActive("textStyle", { color: /\W+/gm }); }, getActiveColor: function (editor) { return editor.getAttributes("textStyle").color; }, title: "Text color", onColorChange: function (editor, color) {
return (_jsx(ColorTool, __assign({}, props, { cacheKey: "textColor", getActiveColor: function (editor) { return editor.getAttributes("textStyle").color; }, title: "Text color", onColorChange: function (editor, color) {
return color
? editor.chain().focus().setColor(color).run()
: editor.chain().focus().unsetColor().run();

View File

@@ -0,0 +1,7 @@
declare function set<T>(key: string, value: T | null): void;
declare function get<T>(key: string, def?: T): T | undefined;
export declare const config: {
set: typeof set;
get: typeof get;
};
export {};

22
packages/editor/dist/utils/config.js vendored Normal file
View File

@@ -0,0 +1,22 @@
function set(key, value) {
if (!value)
return window.localStorage.removeItem(key);
window.localStorage.setItem(key, JSON.stringify(value));
}
function get(key, def) {
var value = window.localStorage.getItem(key);
if (!value)
return def;
return tryParse(value);
}
export var config = { set: set, get: get };
function tryParse(val) {
if (val === "undefined" || val === "null")
return;
try {
return JSON.parse(val);
}
catch (e) {
return val;
}
}

View File

@@ -26,7 +26,7 @@ export const DEFAULT_COLORS = [
type ColorPickerProps = {
colors?: string[];
color: string;
color?: string;
onClear: () => void;
expanded?: boolean;
onChange: (color: string) => void;
@@ -47,7 +47,7 @@ export function ColorPicker(props: ColorPickerProps) {
const ref = useRef<HTMLDivElement>();
const [isPickerOpen, setIsPickerOpen] = useState(expanded || false);
const [currentColor, setCurrentColor] = useState<string>(
tinycolor(color).toHexString()
tinycolor(color || colors[0]).toHexString()
);
const tColor = tinycolor(currentColor);

View File

@@ -2,7 +2,7 @@ import { Editor } from "@tiptap/core";
import { useState } from "react";
import tinycolor from "tinycolor2";
import { PopupWrapper } from "../../components/popup-presenter";
import { useEditorContext } from "../../components/popup-presenter/popuprenderer";
import { config } from "../../utils/config";
import { SplitButton } from "../components/split-button";
import { ColorPicker } from "../popups/color-picker";
import { useToolbarLocation } from "../stores/toolbar-store";
@@ -11,47 +11,38 @@ import { getToolbarElement } from "../utils/dom";
type ColorToolProps = ToolProps & {
onColorChange: (editor: Editor, color?: string) => void;
isActive: (editor: Editor) => boolean;
getActiveColor: (editor: Editor) => string;
title: string;
cacheKey: string;
};
export function ColorTool(props: ColorToolProps) {
const { onColorChange, isActive, getActiveColor, title, ...toolProps } =
props;
const editor = useEditorContext();
const activeColor = getActiveColor(editor);
const _isActive = isActive(editor);
const {
editor,
onColorChange,
getActiveColor,
title,
cacheKey,
...toolProps
} = props;
const activeColor = getActiveColor(editor) || config.get(cacheKey);
const tColor = tinycolor(activeColor);
const toolbarLocation = useToolbarLocation();
const isBottom = toolbarLocation === "bottom";
const isBottom = useToolbarLocation() === "bottom";
const [isOpen, setIsOpen] = useState<boolean>(false);
// const { hide, isOpen, show } = usePopup({
// id: title,
// group: "color",
// theme: editor?.storage.theme,
// blocking: false,
// focusOnRender: false,
// });
// console.log("Updating color", editor);
return (
<SplitButton
{...toolProps}
iconColor={_isActive && tColor.isDark() ? "static" : "icon"}
iconColor={activeColor && tColor.isDark() ? "static" : "icon"}
sx={{
mr: 0,
bg: _isActive ? activeColor : "transparent",
bg: activeColor || "transparent",
":hover": {
bg:
_isActive && !isBottom
? tColor.darken(5).toRgbString()
: "transparent",
bg: activeColor ? tColor.darken(5).toRgbString() : "transparent",
},
}}
onOpen={() => {
setIsOpen((s) => !s);
}}
onOpen={() => setIsOpen((s) => !s)}
toggled={isOpen}
onClick={() => onColorChange(editor, activeColor)}
>
<PopupWrapper
isOpen={isOpen}
@@ -69,8 +60,14 @@ export function ColorTool(props: ColorToolProps) {
renderPopup={(close) => (
<ColorPicker
color={activeColor}
onClear={() => onColorChange(editor)}
onChange={(color) => onColorChange(editor, color)}
onClear={() => {
onColorChange(editor);
config.set(cacheKey, null);
}}
onChange={(color) => {
onColorChange(editor, color);
config.set(cacheKey, color);
}}
onClose={close}
title={title}
/>
@@ -84,7 +81,7 @@ export function Highlight(props: ToolProps) {
return (
<ColorTool
{...props}
isActive={(editor) => editor.isActive("highlight", { color: /\W+/gm })}
cacheKey="highlight"
getActiveColor={(editor) => editor.getAttributes("highlight").color}
title={"Background color"}
onColorChange={(editor, color) =>
@@ -100,7 +97,7 @@ export function TextColor(props: ToolProps) {
return (
<ColorTool
{...props}
isActive={(editor) => editor.isActive("textStyle", { color: /\W+/gm })}
cacheKey={"textColor"}
getActiveColor={(editor) => editor.getAttributes("textStyle").color}
title="Text color"
onColorChange={(editor, color) =>

View File

@@ -0,0 +1,23 @@
function set<T>(key: string, value: T | null) {
if (!value) return window.localStorage.removeItem(key);
window.localStorage.setItem(key, JSON.stringify(value));
}
function get<T>(key: string, def?: T): T | undefined {
const value = window.localStorage.getItem(key);
if (!value) return def;
return tryParse(value) as T;
}
export const config = { set, get };
function tryParse<T>(val: string): T | string | undefined {
if (val === "undefined" || val === "null") return;
try {
return JSON.parse(val);
} catch (e) {
return val;
}
}