refactor: update SCSS syntax & remove open-color dep (#10633)
This commit is contained in:
@@ -1,46 +0,0 @@
|
||||
import { THEME } from "@excalidraw/common";
|
||||
import oc from "open-color";
|
||||
import React from "react";
|
||||
|
||||
import type { Theme } from "@excalidraw/element/types";
|
||||
|
||||
// https://github.com/tholman/github-corners
|
||||
export const GitHubCorner = React.memo(
|
||||
({ theme, dir }: { theme: Theme; dir: string }) => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="40"
|
||||
height="40"
|
||||
viewBox="0 0 250 250"
|
||||
className="rtl-mirror"
|
||||
style={{
|
||||
marginTop: "calc(var(--space-factor) * -1)",
|
||||
[dir === "rtl" ? "marginLeft" : "marginRight"]:
|
||||
"calc(var(--space-factor) * -1)",
|
||||
}}
|
||||
>
|
||||
<a
|
||||
href="https://github.com/excalidraw/excalidraw"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
aria-label="GitHub repository"
|
||||
>
|
||||
<path
|
||||
d="M0 0l115 115h15l12 27 108 108V0z"
|
||||
fill={theme === THEME.LIGHT ? oc.gray[6] : oc.gray[7]}
|
||||
/>
|
||||
<path
|
||||
className="octo-arm"
|
||||
d="M128 109c-15-9-9-19-9-19 3-7 2-11 2-11-1-7 3-2 3-2 4 5 2 11 2 11-3 10 5 15 9 16"
|
||||
style={{ transformOrigin: "130px 106px" }}
|
||||
fill={theme === THEME.LIGHT ? oc.white : "var(--default-bg-color)"}
|
||||
/>
|
||||
<path
|
||||
className="octo-body"
|
||||
d="M115 115s4 2 5 0l14-14c3-2 6-3 8-3-8-11-15-24 2-41 5-5 10-7 16-7 1-2 3-7 12-11 0 0 5 3 7 16 4 2 8 5 12 9s7 8 9 12c14 3 17 7 17 7-4 8-9 11-11 11 0 6-2 11-7 16-16 16-30 10-41 2 0 3-1 7-5 11l-12 11c-1 1 1 5 1 5z"
|
||||
fill={theme === THEME.LIGHT ? oc.white : "var(--default-bg-color)"}
|
||||
/>
|
||||
</a>
|
||||
</svg>
|
||||
),
|
||||
);
|
||||
@@ -1,5 +1,97 @@
|
||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`COLOR_PALETTE > color palette doesn't regress 1`] = `
|
||||
{
|
||||
"black": "#1e1e1e",
|
||||
"blue": [
|
||||
"#e7f5ff",
|
||||
"#a5d8ff",
|
||||
"#4dabf7",
|
||||
"#228be6",
|
||||
"#1971c2",
|
||||
],
|
||||
"bronze": [
|
||||
"#f8f1ee",
|
||||
"#eaddd7",
|
||||
"#d2bab0",
|
||||
"#a18072",
|
||||
"#846358",
|
||||
],
|
||||
"cyan": [
|
||||
"#e3fafc",
|
||||
"#99e9f2",
|
||||
"#3bc9db",
|
||||
"#15aabf",
|
||||
"#0c8599",
|
||||
],
|
||||
"grape": [
|
||||
"#f8f0fc",
|
||||
"#eebefa",
|
||||
"#da77f2",
|
||||
"#be4bdb",
|
||||
"#9c36b5",
|
||||
],
|
||||
"gray": [
|
||||
"#f8f9fa",
|
||||
"#e9ecef",
|
||||
"#ced4da",
|
||||
"#868e96",
|
||||
"#343a40",
|
||||
],
|
||||
"green": [
|
||||
"#ebfbee",
|
||||
"#b2f2bb",
|
||||
"#69db7c",
|
||||
"#40c057",
|
||||
"#2f9e44",
|
||||
],
|
||||
"orange": [
|
||||
"#fff4e6",
|
||||
"#ffd8a8",
|
||||
"#ffa94d",
|
||||
"#fd7e14",
|
||||
"#e8590c",
|
||||
],
|
||||
"pink": [
|
||||
"#fff0f6",
|
||||
"#fcc2d7",
|
||||
"#f783ac",
|
||||
"#e64980",
|
||||
"#c2255c",
|
||||
],
|
||||
"red": [
|
||||
"#fff5f5",
|
||||
"#ffc9c9",
|
||||
"#ff8787",
|
||||
"#fa5252",
|
||||
"#e03131",
|
||||
],
|
||||
"teal": [
|
||||
"#e6fcf5",
|
||||
"#96f2d7",
|
||||
"#38d9a9",
|
||||
"#12b886",
|
||||
"#099268",
|
||||
],
|
||||
"transparent": "transparent",
|
||||
"violet": [
|
||||
"#f3f0ff",
|
||||
"#d0bfff",
|
||||
"#9775fa",
|
||||
"#7950f2",
|
||||
"#6741d9",
|
||||
],
|
||||
"white": "#ffffff",
|
||||
"yellow": [
|
||||
"#fff9db",
|
||||
"#ffec99",
|
||||
"#ffd43b",
|
||||
"#fab005",
|
||||
"#f08c00",
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`applyDarkModeFilter > COLOR_PALETTE regression tests > matches snapshot for all palette colors 1`] = `
|
||||
{
|
||||
"black": "#d3d3d3",
|
||||
|
||||
@@ -4,6 +4,12 @@ import {
|
||||
rgbToHex,
|
||||
} from "@excalidraw/common";
|
||||
|
||||
describe("COLOR_PALETTE", () => {
|
||||
it("color palette doesn't regress", () => {
|
||||
expect(COLOR_PALETTE).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe("applyDarkModeFilter", () => {
|
||||
describe("basic transformations", () => {
|
||||
it("transforms black to near-white", () => {
|
||||
|
||||
+102
-48
@@ -1,4 +1,3 @@
|
||||
import oc from "open-color";
|
||||
import tinycolor from "tinycolor2";
|
||||
|
||||
import { clamp } from "@excalidraw/math";
|
||||
@@ -6,18 +5,14 @@ import { degreesToRadians } from "@excalidraw/math";
|
||||
|
||||
import type { Degrees } from "@excalidraw/math";
|
||||
|
||||
import type { Merge } from "./utility-types";
|
||||
|
||||
export { tinycolor };
|
||||
// ---------------------------------------------------------------------------
|
||||
// Dark mode color transformation
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// Browser-only cache to avoid memory leaks on server
|
||||
const DARK_MODE_COLORS_CACHE: Map<string, string> | null =
|
||||
typeof window !== "undefined" ? new Map() : null;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Dark mode color transformation
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function cssHueRotate(
|
||||
red: number,
|
||||
green: number,
|
||||
@@ -115,8 +110,8 @@ export const applyDarkModeFilter = (color: string): string => {
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export const COLOR_OUTLINE_CONTRAST_THRESHOLD = 240;
|
||||
// Color palette
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// FIXME can't put to utils.ts rn because of circular dependency
|
||||
const pick = <R extends Record<string, any>, K extends readonly (keyof R)[]>(
|
||||
@@ -131,15 +126,7 @@ const pick = <R extends Record<string, any>, K extends readonly (keyof R)[]>(
|
||||
}, {} as Pick<R, K[number]>) as Pick<R, K[number]>;
|
||||
};
|
||||
|
||||
export type ColorPickerColor =
|
||||
| Exclude<keyof oc, "indigo" | "lime">
|
||||
| "transparent"
|
||||
| "bronze";
|
||||
export type ColorTuple = readonly [string, string, string, string, string];
|
||||
export type ColorPalette = Merge<
|
||||
Record<ColorPickerColor, ColorTuple>,
|
||||
{ black: "#1e1e1e"; white: "#ffffff"; transparent: "transparent" }
|
||||
>;
|
||||
|
||||
// used general type instead of specific type (ColorPalette) to support custom colors
|
||||
export type ColorPaletteCustom = { [key: string]: ColorTuple | string };
|
||||
@@ -152,38 +139,30 @@ export const DEFAULT_CHART_COLOR_INDEX = 4;
|
||||
|
||||
export const DEFAULT_ELEMENT_STROKE_COLOR_INDEX = 4;
|
||||
export const DEFAULT_ELEMENT_BACKGROUND_COLOR_INDEX = 1;
|
||||
export const ELEMENTS_PALETTE_SHADE_INDEXES = [0, 2, 4, 6, 8] as const;
|
||||
export const CANVAS_PALETTE_SHADE_INDEXES = [0, 1, 2, 3, 4] as const;
|
||||
|
||||
export const getSpecificColorShades = (
|
||||
color: Exclude<
|
||||
ColorPickerColor,
|
||||
"transparent" | "white" | "black" | "bronze"
|
||||
>,
|
||||
indexArr: Readonly<ColorShadesIndexes>,
|
||||
) => {
|
||||
return indexArr.map((index) => oc[color][index]) as any as ColorTuple;
|
||||
};
|
||||
|
||||
export const COLOR_PALETTE = {
|
||||
transparent: "transparent",
|
||||
black: "#1e1e1e",
|
||||
white: "#ffffff",
|
||||
// open-colors
|
||||
gray: getSpecificColorShades("gray", ELEMENTS_PALETTE_SHADE_INDEXES),
|
||||
red: getSpecificColorShades("red", ELEMENTS_PALETTE_SHADE_INDEXES),
|
||||
pink: getSpecificColorShades("pink", ELEMENTS_PALETTE_SHADE_INDEXES),
|
||||
grape: getSpecificColorShades("grape", ELEMENTS_PALETTE_SHADE_INDEXES),
|
||||
violet: getSpecificColorShades("violet", ELEMENTS_PALETTE_SHADE_INDEXES),
|
||||
blue: getSpecificColorShades("blue", ELEMENTS_PALETTE_SHADE_INDEXES),
|
||||
cyan: getSpecificColorShades("cyan", ELEMENTS_PALETTE_SHADE_INDEXES),
|
||||
teal: getSpecificColorShades("teal", ELEMENTS_PALETTE_SHADE_INDEXES),
|
||||
green: getSpecificColorShades("green", ELEMENTS_PALETTE_SHADE_INDEXES),
|
||||
yellow: getSpecificColorShades("yellow", ELEMENTS_PALETTE_SHADE_INDEXES),
|
||||
orange: getSpecificColorShades("orange", ELEMENTS_PALETTE_SHADE_INDEXES),
|
||||
// radix bronze shades 3,5,7,9,11
|
||||
// open-color from https://github.com/yeun/open-color/blob/master/open-color.js
|
||||
// corresponds to indexes [0,2,4,6,8] (weights: 50, 200, 400, 600, 800)
|
||||
gray: ["#f8f9fa", "#e9ecef", "#ced4da", "#868e96", "#343a40"],
|
||||
red: ["#fff5f5", "#ffc9c9", "#ff8787", "#fa5252", "#e03131"],
|
||||
pink: ["#fff0f6", "#fcc2d7", "#f783ac", "#e64980", "#c2255c"],
|
||||
grape: ["#f8f0fc", "#eebefa", "#da77f2", "#be4bdb", "#9c36b5"],
|
||||
violet: ["#f3f0ff", "#d0bfff", "#9775fa", "#7950f2", "#6741d9"],
|
||||
blue: ["#e7f5ff", "#a5d8ff", "#4dabf7", "#228be6", "#1971c2"],
|
||||
cyan: ["#e3fafc", "#99e9f2", "#3bc9db", "#15aabf", "#0c8599"],
|
||||
teal: ["#e6fcf5", "#96f2d7", "#38d9a9", "#12b886", "#099268"],
|
||||
green: ["#ebfbee", "#b2f2bb", "#69db7c", "#40c057", "#2f9e44"],
|
||||
yellow: ["#fff9db", "#ffec99", "#ffd43b", "#fab005", "#f08c00"],
|
||||
orange: ["#fff4e6", "#ffd8a8", "#ffa94d", "#fd7e14", "#e8590c"],
|
||||
// radix bronze shades [3,5,7,9,11]
|
||||
bronze: ["#f8f1ee", "#eaddd7", "#d2bab0", "#a18072", "#846358"],
|
||||
} as ColorPalette;
|
||||
} as const;
|
||||
|
||||
export type ColorPalette = typeof COLOR_PALETTE;
|
||||
export type ColorPickerColor = keyof typeof COLOR_PALETTE;
|
||||
|
||||
const COMMON_ELEMENT_SHADES = pick(COLOR_PALETTE, [
|
||||
"cyan",
|
||||
@@ -198,7 +177,6 @@ const COMMON_ELEMENT_SHADES = pick(COLOR_PALETTE, [
|
||||
"red",
|
||||
]);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// quick picks defaults
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
@@ -233,7 +211,6 @@ export const DEFAULT_CANVAS_BACKGROUND_PICKS = [
|
||||
"#fdf8f6",
|
||||
] as ColorTuple;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// palette defaults
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
@@ -259,8 +236,7 @@ export const DEFAULT_ELEMENT_BACKGROUND_COLOR_PALETTE = {
|
||||
...COMMON_ELEMENT_SHADES,
|
||||
} as const;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// helpers
|
||||
// color palette helpers
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// !!!MUST BE WITHOUT GRAY, TRANSPARENT AND BLACK!!!
|
||||
@@ -281,6 +257,10 @@ export const getAllColorsSpecificShade = (index: 0 | 1 | 2 | 3 | 4) =>
|
||||
COLOR_PALETTE.red[index],
|
||||
] as const;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// other helpers
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
export const rgbToHex = (r: number, g: number, b: number, a?: number) => {
|
||||
// (1 << 24) adds 0x1000000 to ensure the hex string is always 7 chars,
|
||||
// then slice(1) removes the leading "1" to get exactly 6 hex digits
|
||||
@@ -299,4 +279,78 @@ export const rgbToHex = (r: number, g: number, b: number, a?: number) => {
|
||||
return hex6;
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns #RRGGBB or #RRGGBBAA based on color containing non-opaque alpha,
|
||||
* null if not valid color
|
||||
*/
|
||||
export const colorToHex = (color: string): string | null => {
|
||||
const tc = tinycolor(color);
|
||||
if (!tc.isValid()) {
|
||||
return null;
|
||||
}
|
||||
const { r, g, b, a } = tc.toRgb();
|
||||
return rgbToHex(r, g, b, a);
|
||||
};
|
||||
|
||||
export const isTransparent = (color: string) => {
|
||||
return tinycolor(color).getAlpha() === 0;
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// color contract helpers
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
export const COLOR_OUTLINE_CONTRAST_THRESHOLD = 240;
|
||||
|
||||
const calculateContrast = (r: number, g: number, b: number): number => {
|
||||
const yiq = (r * 299 + g * 587 + b * 114) / 1000;
|
||||
return yiq;
|
||||
};
|
||||
|
||||
// YIQ algo, inspiration from https://stackoverflow.com/a/11868398
|
||||
export const isColorDark = (color: string, threshold = 160): boolean => {
|
||||
// no color ("") -> assume it default to black
|
||||
if (!color) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isTransparent(color)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const tc = tinycolor(color);
|
||||
if (!tc.isValid()) {
|
||||
// invalid color -> assume it defaults to black
|
||||
return true;
|
||||
}
|
||||
|
||||
const { r, g, b } = tc.toRgb();
|
||||
return calculateContrast(r, g, b) < threshold;
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// normalization
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* tries to keep the input color as-is if it's valid, making minimal adjustments
|
||||
* (trimming whitespace or adding `#` to hex colors)
|
||||
*/
|
||||
export const normalizeInputColor = (color: string): string | null => {
|
||||
color = color.trim();
|
||||
if (isTransparent(color)) {
|
||||
return color;
|
||||
}
|
||||
|
||||
const tc = tinycolor(color);
|
||||
if (tc.isValid()) {
|
||||
// testing for `#` first fixes a bug on Electron (more specfically, an
|
||||
// Obsidian popout window), where a hex color without `#` is considered valid
|
||||
if (tc.getFormat() === "hex" && !color.startsWith("#")) {
|
||||
return `#${color}`;
|
||||
}
|
||||
return color;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
@@ -10,7 +10,6 @@ import type {
|
||||
Zoom,
|
||||
} from "@excalidraw/excalidraw/types";
|
||||
|
||||
import { tinycolor } from "./colors";
|
||||
import {
|
||||
DEFAULT_VERSION,
|
||||
ENV,
|
||||
@@ -548,10 +547,6 @@ export const mapFind = <T, K>(
|
||||
return undefined;
|
||||
};
|
||||
|
||||
export const isTransparent = (color: string) => {
|
||||
return tinycolor(color).getAlpha() === 0;
|
||||
};
|
||||
|
||||
export type ResolvablePromise<T> = Promise<T> & {
|
||||
resolve: [T] extends [undefined]
|
||||
? (value?: MaybePromise<Awaited<T>>) => void
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "../css/variables.module.scss";
|
||||
@use "../css/variables.module" as *;
|
||||
|
||||
.excalidraw {
|
||||
.Avatar {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "../css/theme";
|
||||
@use "../css/theme" as *;
|
||||
|
||||
.excalidraw {
|
||||
.excalidraw-button {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "../css/theme";
|
||||
@use "../css/theme" as *;
|
||||
|
||||
.excalidraw {
|
||||
button.standalone {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "../css/variables.module.scss";
|
||||
@use "../css/variables.module.scss" as *;
|
||||
|
||||
.excalidraw {
|
||||
.Card {
|
||||
@@ -19,7 +19,7 @@
|
||||
padding: 1.4rem;
|
||||
border-radius: 50%;
|
||||
background: var(--card-color);
|
||||
color: $oc-white;
|
||||
color: #fff;
|
||||
|
||||
svg {
|
||||
width: 2.8rem;
|
||||
@@ -46,7 +46,7 @@
|
||||
background-color: var(--card-color-darkest);
|
||||
}
|
||||
.ToolIcon__label {
|
||||
color: $oc-white;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.Spinner {
|
||||
|
||||
@@ -1,25 +1,35 @@
|
||||
import OpenColor from "open-color";
|
||||
|
||||
import "./Card.scss";
|
||||
|
||||
// for open-color see https://github.com/yeun/open-color/blob/master/open-color.scss
|
||||
const COLOR_MAP = {
|
||||
primary: {
|
||||
base: "var(--color-primary)",
|
||||
darker: "var(--color-primary-darker)",
|
||||
darkest: "var(--color-primary-darkest)",
|
||||
},
|
||||
lime: {
|
||||
base: "#74b816", // open-color lime[7]
|
||||
darker: "#66a80f", // open-color lime[8]
|
||||
darkest: "#5c940d", // open-color lime[9]
|
||||
},
|
||||
pink: {
|
||||
base: "#d6336c", // open-color pink[7]
|
||||
darker: "#c2255c", // open-color pink[8]
|
||||
darkest: "#a61e4d", // open-color pink[9]
|
||||
},
|
||||
};
|
||||
|
||||
export const Card: React.FC<{
|
||||
color: keyof OpenColor | "primary";
|
||||
color: "primary" | "lime" | "pink";
|
||||
children?: React.ReactNode;
|
||||
}> = ({ children, color }) => {
|
||||
return (
|
||||
<div
|
||||
className="Card"
|
||||
style={{
|
||||
["--card-color" as any]:
|
||||
color === "primary" ? "var(--color-primary)" : OpenColor[color][7],
|
||||
["--card-color-darker" as any]:
|
||||
color === "primary"
|
||||
? "var(--color-primary-darker)"
|
||||
: OpenColor[color][8],
|
||||
["--card-color-darkest" as any]:
|
||||
color === "primary"
|
||||
? "var(--color-primary-darkest)"
|
||||
: OpenColor[color][9],
|
||||
["--card-color" as any]: COLOR_MAP[color].base,
|
||||
["--card-color-darker" as any]: COLOR_MAP[color].darker,
|
||||
["--card-color-darkest" as any]: COLOR_MAP[color].darkest,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
@import "../css/variables.module.scss";
|
||||
@use "sass:color";
|
||||
@use "../css/variables.module" as *;
|
||||
|
||||
.excalidraw {
|
||||
.Checkbox {
|
||||
@@ -12,7 +13,7 @@
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
|
||||
&:hover:not(.is-checked) .Checkbox-box:not(:focus) {
|
||||
box-shadow: 0 0 0 2px #{$oc-blue-4};
|
||||
box-shadow: 0 0 0 2px #{$color-blue-4};
|
||||
}
|
||||
|
||||
&:hover:not(.is-checked) .Checkbox-box:not(:focus) {
|
||||
@@ -24,25 +25,25 @@
|
||||
|
||||
&:active {
|
||||
.Checkbox-box {
|
||||
box-shadow: 0 0 2px 1px inset #{$oc-blue-7} !important;
|
||||
box-shadow: 0 0 2px 1px inset #{$color-blue-7} !important;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.Checkbox-box {
|
||||
background-color: fade-out($oc-blue-1, 0.8);
|
||||
background-color: color.adjust($color-blue-1, $alpha: -0.8);
|
||||
}
|
||||
}
|
||||
|
||||
&.is-checked {
|
||||
.Checkbox-box {
|
||||
background-color: #{$oc-blue-1};
|
||||
background-color: #{$color-blue-1};
|
||||
svg {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
&:hover .Checkbox-box {
|
||||
background-color: #{$oc-blue-2};
|
||||
background-color: #{$color-blue-2};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,16 +59,16 @@
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
box-shadow: 0 0 0 2px #{$oc-blue-7};
|
||||
box-shadow: 0 0 0 2px #{$color-blue-7};
|
||||
background-color: transparent;
|
||||
border-radius: 4px;
|
||||
|
||||
color: #{$oc-blue-7};
|
||||
color: #{$color-blue-7};
|
||||
|
||||
border: 0;
|
||||
|
||||
&:focus {
|
||||
box-shadow: 0 0 0 3px #{$oc-blue-7};
|
||||
box-shadow: 0 0 0 3px #{$color-blue-7};
|
||||
}
|
||||
|
||||
svg {
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import clsx from "clsx";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
|
||||
import { isTransparent, KEYS } from "@excalidraw/common";
|
||||
|
||||
import tinycolor from "tinycolor2";
|
||||
import { KEYS, normalizeInputColor } from "@excalidraw/common";
|
||||
|
||||
import { getShortcutKey } from "../..//shortcut";
|
||||
import { useAtom } from "../../editor-jotai";
|
||||
@@ -16,29 +14,6 @@ import { activeColorPickerSectionAtom } from "./colorPickerUtils";
|
||||
|
||||
import type { ColorPickerType } from "./colorPickerUtils";
|
||||
|
||||
/**
|
||||
* tries to keep the input color as-is if it's valid, making minimal adjustments
|
||||
* (trimming whitespace or adding `#` to hex colors)
|
||||
*/
|
||||
export const normalizeInputColor = (color: string): string | null => {
|
||||
color = color.trim();
|
||||
if (isTransparent(color)) {
|
||||
return color;
|
||||
}
|
||||
|
||||
const tc = tinycolor(color);
|
||||
if (tc.isValid()) {
|
||||
// testing for `#` first fixes a bug on Electron (more specfically, an
|
||||
// Obsidian popout window), where a hex color without `#` is considered valid
|
||||
if (tc.getFormat() === "hex" && !color.startsWith("#")) {
|
||||
return `#${color}`;
|
||||
}
|
||||
return color;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
export const ColorInput = ({
|
||||
color,
|
||||
onChange,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
@import "../../css/variables.module.scss";
|
||||
@use "sass:color";
|
||||
@use "../../css/variables.module" as *;
|
||||
|
||||
.excalidraw {
|
||||
.focus-visible-none {
|
||||
@@ -185,8 +186,8 @@
|
||||
|
||||
.color-picker {
|
||||
background: var(--popup-bg-color);
|
||||
border: 0 solid transparentize($oc-white, 0.75);
|
||||
box-shadow: transparentize($oc-black, 0.75) 0 1px 4px;
|
||||
border: 0 solid color.adjust(#fff, $alpha: -0.75);
|
||||
box-shadow: color.adjust(#000, $alpha: -0.75) 0 1px 4px;
|
||||
border-radius: 4px;
|
||||
position: absolute;
|
||||
|
||||
@@ -243,7 +244,7 @@
|
||||
}
|
||||
|
||||
.color-picker-triangle-shadow {
|
||||
border-color: transparent transparent transparentize($oc-black, 0.9);
|
||||
border-color: transparent transparent color.adjust(#000, $alpha: -0.9);
|
||||
|
||||
:root[dir="ltr"] & {
|
||||
left: -14px;
|
||||
@@ -280,7 +281,7 @@
|
||||
padding: 0.25rem;
|
||||
|
||||
&-title {
|
||||
color: $oc-gray-6;
|
||||
color: $color-gray-6;
|
||||
font-size: 12px;
|
||||
padding: 0 0.25rem;
|
||||
}
|
||||
@@ -319,7 +320,7 @@
|
||||
|
||||
.color-picker-transparent {
|
||||
border-radius: 4px;
|
||||
box-shadow: transparentize($oc-black, 0.9) 0 0 0 1px inset;
|
||||
box-shadow: color.adjust(#000, $alpha: -0.9) 0 0 0 1px inset;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
@@ -473,7 +474,7 @@
|
||||
}
|
||||
|
||||
.color-picker-type-elementBackground .color-picker-keybinding {
|
||||
color: $oc-white;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.color-picker-swatch[aria-label="transparent"] .color-picker-keybinding {
|
||||
@@ -486,10 +487,10 @@
|
||||
|
||||
&.theme--dark {
|
||||
.color-picker-type-elementBackground .color-picker-keybinding {
|
||||
color: $oc-black;
|
||||
color: #000;
|
||||
}
|
||||
.color-picker-swatch[aria-label="transparent"] .color-picker-keybinding {
|
||||
color: $oc-black;
|
||||
color: #000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import { useRef, useEffect } from "react";
|
||||
import {
|
||||
COLOR_OUTLINE_CONTRAST_THRESHOLD,
|
||||
COLOR_PALETTE,
|
||||
isColorDark,
|
||||
isWritableElement,
|
||||
} from "@excalidraw/common";
|
||||
|
||||
@@ -29,7 +30,7 @@ import { ColorInput } from "./ColorInput";
|
||||
import { Picker } from "./Picker";
|
||||
import PickerHeading from "./PickerHeading";
|
||||
import { TopPicks } from "./TopPicks";
|
||||
import { activeColorPickerSectionAtom, isColorDark } from "./colorPickerUtils";
|
||||
import { activeColorPickerSectionAtom } from "./colorPickerUtils";
|
||||
|
||||
import "./ColorPicker.scss";
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import React from "react";
|
||||
|
||||
import { isColorDark } from "./colorPickerUtils";
|
||||
import { isColorDark } from "@excalidraw/common";
|
||||
|
||||
interface HotkeyLabelProps {
|
||||
color: string;
|
||||
|
||||
@@ -5,10 +5,9 @@ import {
|
||||
DEFAULT_CANVAS_BACKGROUND_PICKS,
|
||||
DEFAULT_ELEMENT_BACKGROUND_PICKS,
|
||||
DEFAULT_ELEMENT_STROKE_PICKS,
|
||||
isColorDark,
|
||||
} from "@excalidraw/common";
|
||||
|
||||
import { isColorDark } from "./colorPickerUtils";
|
||||
|
||||
import type { ColorPickerType } from "./colorPickerUtils";
|
||||
|
||||
interface TopPicksProps {
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
import {
|
||||
isTransparent,
|
||||
MAX_CUSTOM_COLORS_USED_IN_CANVAS,
|
||||
tinycolor,
|
||||
} from "@excalidraw/common";
|
||||
import { MAX_CUSTOM_COLORS_USED_IN_CANVAS } from "@excalidraw/common";
|
||||
|
||||
import type { ExcalidrawElement } from "@excalidraw/element/types";
|
||||
|
||||
@@ -100,32 +96,6 @@ export type ActiveColorPickerSectionAtomType =
|
||||
export const activeColorPickerSectionAtom =
|
||||
atom<ActiveColorPickerSectionAtomType>(null);
|
||||
|
||||
const calculateContrast = (r: number, g: number, b: number): number => {
|
||||
const yiq = (r * 299 + g * 587 + b * 114) / 1000;
|
||||
return yiq;
|
||||
};
|
||||
|
||||
// YIQ algo, inspiration from https://stackoverflow.com/a/11868398
|
||||
export const isColorDark = (color: string, threshold = 160): boolean => {
|
||||
// no color ("") -> assume it default to black
|
||||
if (!color) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isTransparent(color)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const tc = tinycolor(color);
|
||||
if (!tc.isValid()) {
|
||||
// invalid color -> assume it defaults to black
|
||||
return true;
|
||||
}
|
||||
|
||||
const { r, g, b } = tc.toRgb();
|
||||
return calculateContrast(r, g, b) < threshold;
|
||||
};
|
||||
|
||||
export type ColorPickerType =
|
||||
| "canvasBackground"
|
||||
| "elementBackground"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "../../css/variables.module.scss";
|
||||
@use "../../css/variables.module" as *;
|
||||
|
||||
$verticalBreakpoint: 861px;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "../css/variables.module.scss";
|
||||
@use "../css/variables.module" as *;
|
||||
|
||||
.excalidraw {
|
||||
.confirm-dialog {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
@import "../css/variables.module.scss";
|
||||
@use "sass:color";
|
||||
@use "../css/variables.module" as *;
|
||||
|
||||
.excalidraw {
|
||||
.context-menu-popover {
|
||||
@@ -8,7 +9,7 @@
|
||||
.context-menu {
|
||||
position: relative;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 3px 10px transparentize($oc-black, 0.8);
|
||||
box-shadow: 0 3px 10px color.adjust(#000, $alpha: -0.8);
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
user-select: none;
|
||||
@@ -49,7 +50,7 @@
|
||||
|
||||
&.dangerous {
|
||||
.context-menu-item__label {
|
||||
color: $oc-red-7;
|
||||
color: $color-red-7;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +74,7 @@
|
||||
.context-menu-item__label {
|
||||
color: var(--popup-bg-color);
|
||||
}
|
||||
background-color: $oc-red-6;
|
||||
background-color: $color-red-6;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,6 +98,6 @@
|
||||
|
||||
.context-menu-item-separator {
|
||||
border: none;
|
||||
border-top: 1px solid $oc-gray-5;
|
||||
border-top: 1px solid $color-gray-5;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "../css//variables.module.scss";
|
||||
@use "../css/variables.module" as *;
|
||||
|
||||
.excalidraw {
|
||||
.ConvertElementTypePopup {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "../css/variables.module.scss";
|
||||
@use "../css/variables.module" as *;
|
||||
|
||||
.excalidraw {
|
||||
.Dialog {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "../css/variables.module.scss";
|
||||
@use "../css/variables.module" as *;
|
||||
|
||||
.excalidraw {
|
||||
.ElementLinkDialog {
|
||||
@@ -59,7 +59,7 @@
|
||||
}
|
||||
|
||||
.ElementLinkDialog__remove {
|
||||
color: $oc-red-9;
|
||||
color: $color-red-9;
|
||||
margin-left: 1rem;
|
||||
|
||||
.ToolIcon__icon {
|
||||
@@ -68,7 +68,7 @@
|
||||
}
|
||||
|
||||
.ToolIcon__icon svg {
|
||||
color: $oc-red-6;
|
||||
color: $color-red-6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "../css/variables.module.scss";
|
||||
@use "../css/variables.module" as *;
|
||||
|
||||
.excalidraw {
|
||||
.ExportDialog__preview {
|
||||
@@ -112,7 +112,7 @@
|
||||
|
||||
font-family: Cascadia;
|
||||
font-size: 1.8em;
|
||||
color: $oc-white;
|
||||
color: #fff;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--button-color-darker);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "../css/variables.module.scss";
|
||||
@use "../css/variables.module" as *;
|
||||
|
||||
@keyframes successStatusAnimation {
|
||||
0% {
|
||||
@@ -24,6 +24,14 @@
|
||||
background-color: var(--back-color);
|
||||
border-color: var(--border-color);
|
||||
|
||||
border-radius: 0.5rem;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
|
||||
font-family: var(--font-family);
|
||||
|
||||
user-select: none;
|
||||
|
||||
&:hover {
|
||||
transition: all 150ms ease-out;
|
||||
}
|
||||
@@ -266,14 +274,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
border-radius: 0.5rem;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
|
||||
font-family: var(--font-family);
|
||||
|
||||
user-select: none;
|
||||
|
||||
&--size-large {
|
||||
font-weight: 600;
|
||||
font-size: 0.875rem;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "../css/variables.module.scss";
|
||||
@use "../css/variables.module" as *;
|
||||
|
||||
.excalidraw {
|
||||
.FixedSideContainer {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "../../css/variables.module.scss";
|
||||
@use "../../css/variables.module" as *;
|
||||
|
||||
.excalidraw {
|
||||
.FontPicker__container {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "../css/variables.module.scss";
|
||||
@use "../css/variables.module" as *;
|
||||
|
||||
.excalidraw {
|
||||
.HelpDialog {
|
||||
@@ -60,11 +60,12 @@
|
||||
|
||||
&__islands-container {
|
||||
display: grid;
|
||||
grid-column-gap: 1.5rem;
|
||||
grid-row-gap: 2rem;
|
||||
|
||||
@media screen and (min-width: 1024px) {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
grid-column-gap: 1.5rem;
|
||||
grid-row-gap: 2rem;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1024px) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "../css/variables.module.scss";
|
||||
@use "../css/variables.module" as *;
|
||||
|
||||
// this is loosely based on the longest hint text
|
||||
$wide-viewport-width: 1000px;
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
@import "../css/variables.module.scss";
|
||||
@use "sass:color";
|
||||
@use "../css/variables.module" as *;
|
||||
|
||||
.excalidraw {
|
||||
.picker {
|
||||
padding: 0.5rem;
|
||||
background: var(--popup-bg-color);
|
||||
border: 0 solid transparentize($oc-white, 0.75);
|
||||
border: 0 solid color.adjust(#fff, $alpha: -0.75);
|
||||
box-shadow: var(--shadow-island);
|
||||
border-radius: 4px;
|
||||
position: absolute;
|
||||
@@ -87,7 +88,7 @@
|
||||
}
|
||||
|
||||
.picker-type-elementBackground .picker-keybinding {
|
||||
color: $oc-white;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.picker-swatch[aria-label="transparent"] .picker-keybinding {
|
||||
@@ -100,10 +101,10 @@
|
||||
|
||||
&.theme--dark {
|
||||
.picker-type-elementBackground .picker-keybinding {
|
||||
color: $oc-black;
|
||||
color: #000;
|
||||
}
|
||||
.picker-swatch[aria-label="transparent"] .picker-keybinding {
|
||||
color: $oc-black;
|
||||
color: #000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "../css/variables.module.scss";
|
||||
@use "../css/variables.module" as *;
|
||||
|
||||
.excalidraw {
|
||||
--ImageExportModal-preview-border: #d6d6d6;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@import "open-color/open-color";
|
||||
@import "../css/variables.module.scss";
|
||||
@use "../css/variables.module" as *;
|
||||
|
||||
.excalidraw {
|
||||
.layer-ui__wrapper.animate {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "open-color/open-color";
|
||||
@use "../css/variables.module" as *;
|
||||
|
||||
.excalidraw {
|
||||
.layer-ui__library {
|
||||
@@ -46,15 +46,15 @@
|
||||
}
|
||||
|
||||
&-close.ToolIcon_type_button {
|
||||
background-color: $oc-blue-6;
|
||||
background-color: $color-blue-6;
|
||||
align-self: flex-end;
|
||||
&:hover {
|
||||
background-color: $oc-blue-8;
|
||||
background-color: $color-blue-8;
|
||||
}
|
||||
.ToolIcon__icon {
|
||||
width: auto;
|
||||
font-size: 1rem;
|
||||
color: $oc-white;
|
||||
color: #fff;
|
||||
padding: 0 0.5rem;
|
||||
}
|
||||
}
|
||||
@@ -90,7 +90,7 @@
|
||||
|
||||
border-radius: var(--border-radius-lg);
|
||||
background-color: var(--color-primary);
|
||||
color: $oc-white;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
text-decoration: none !important;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "open-color/open-color";
|
||||
@use "../css/variables.module" as *;
|
||||
|
||||
.excalidraw {
|
||||
--container-padding-y: 1rem;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "../css/variables.module.scss";
|
||||
@use "../css/variables.module" as *;
|
||||
|
||||
.excalidraw {
|
||||
.library-unit {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@import "open-color/open-color.scss";
|
||||
@import "../css/variables.module.scss";
|
||||
@use "../css/variables.module" as *;
|
||||
|
||||
.excalidraw {
|
||||
.mobile-toolbar {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "../css/variables.module.scss";
|
||||
@use "../css/variables.module" as *;
|
||||
|
||||
.excalidraw {
|
||||
&.excalidraw-modal-container {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "../../css/variables.module.scss";
|
||||
@use "../../css/variables.module" as *;
|
||||
|
||||
.excalidraw {
|
||||
.OverwriteConfirm {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "../css/variables.module.scss";
|
||||
@use "../css/variables.module" as *;
|
||||
|
||||
.excalidraw {
|
||||
.PasteChartDialog {
|
||||
@@ -25,7 +25,7 @@
|
||||
height: 128px;
|
||||
border-radius: 2px;
|
||||
padding: 1px;
|
||||
border: 1px solid $oc-gray-4;
|
||||
border: 1px solid $color-gray-4;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@@ -39,7 +39,7 @@
|
||||
}
|
||||
&:hover {
|
||||
padding: 0;
|
||||
border: 2px solid $oc-blue-5;
|
||||
border: 2px solid $color-blue-5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import oc from "open-color";
|
||||
import React, { useLayoutEffect, useRef, useState } from "react";
|
||||
|
||||
import type { ChartType } from "@excalidraw/element/types";
|
||||
@@ -49,7 +48,7 @@ const ChartPreviewBtn = (props: {
|
||||
elements,
|
||||
{
|
||||
exportBackground: false,
|
||||
viewBackgroundColor: oc.white,
|
||||
viewBackgroundColor: "#fff",
|
||||
},
|
||||
null, // files
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "../css/variables.module.scss";
|
||||
@use "../css/variables.module" as *;
|
||||
|
||||
.excalidraw {
|
||||
.publish-library {
|
||||
@@ -14,7 +14,7 @@
|
||||
span {
|
||||
font-weight: 500;
|
||||
font-size: 1rem;
|
||||
color: $oc-gray-6;
|
||||
color: $color-gray-6;
|
||||
}
|
||||
input,
|
||||
textarea {
|
||||
@@ -24,7 +24,7 @@
|
||||
}
|
||||
|
||||
.required {
|
||||
color: $oc-red-8;
|
||||
color: $color-red-8;
|
||||
margin: 0.2rem;
|
||||
}
|
||||
}
|
||||
@@ -48,22 +48,22 @@
|
||||
}
|
||||
|
||||
&--confirm.ToolIcon_type_button {
|
||||
background-color: $oc-blue-6;
|
||||
background-color: $color-blue-6;
|
||||
|
||||
&:hover {
|
||||
background-color: $oc-blue-8;
|
||||
background-color: $color-blue-8;
|
||||
}
|
||||
}
|
||||
|
||||
&--cancel.ToolIcon_type_button {
|
||||
background-color: $oc-gray-5;
|
||||
background-color: $color-gray-5;
|
||||
&:hover {
|
||||
background-color: $oc-gray-6;
|
||||
background-color: $color-gray-6;
|
||||
}
|
||||
}
|
||||
|
||||
.ToolIcon__icon {
|
||||
color: $oc-white;
|
||||
color: #fff;
|
||||
.Spinner {
|
||||
--spinner-color: #fff;
|
||||
svg {
|
||||
@@ -83,7 +83,7 @@
|
||||
}
|
||||
|
||||
&-warning {
|
||||
color: $oc-red-6;
|
||||
color: $color-red-6;
|
||||
}
|
||||
|
||||
&-note {
|
||||
@@ -102,14 +102,14 @@
|
||||
top: 0.3rem;
|
||||
left: 0.3rem;
|
||||
font-size: 0.7rem;
|
||||
color: $oc-red-7;
|
||||
color: $color-red-7;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
padding: 0.1rem 0.2rem;
|
||||
border-radius: 0.2rem;
|
||||
}
|
||||
|
||||
&__svg {
|
||||
background-color: $oc-white;
|
||||
background-color: #fff;
|
||||
padding: 0.3rem;
|
||||
width: 7.5rem;
|
||||
height: 7.5rem;
|
||||
@@ -121,7 +121,7 @@
|
||||
}
|
||||
|
||||
.ToolIcon__icon {
|
||||
background-color: $oc-white;
|
||||
background-color: #fff;
|
||||
width: auto;
|
||||
height: auto;
|
||||
margin: 0 0.5rem;
|
||||
@@ -132,7 +132,7 @@
|
||||
}
|
||||
.required,
|
||||
.error {
|
||||
color: $oc-red-8;
|
||||
color: $color-red-8;
|
||||
font-weight: 700;
|
||||
font-size: 1rem;
|
||||
margin: 0.2rem;
|
||||
@@ -152,16 +152,16 @@
|
||||
margin: 0;
|
||||
}
|
||||
.ToolIcon__icon {
|
||||
background-color: $oc-red-6;
|
||||
background-color: $color-red-6;
|
||||
&:hover {
|
||||
background-color: $oc-red-7;
|
||||
background-color: $color-red-7;
|
||||
}
|
||||
&:active {
|
||||
background-color: $oc-red-8;
|
||||
background-color: $color-red-8;
|
||||
}
|
||||
}
|
||||
svg {
|
||||
color: $oc-white;
|
||||
color: #fff;
|
||||
padding: 0.26rem;
|
||||
border-radius: 0.3em;
|
||||
width: 1rem;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { exportToCanvas, exportToSvg } from "@excalidraw/utils/export";
|
||||
import OpenColor from "open-color";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
|
||||
import {
|
||||
@@ -57,7 +56,7 @@ const generatePreviewImage = async (libraryItems: LibraryItems) => {
|
||||
|
||||
const ctx = canvas.getContext("2d")!;
|
||||
|
||||
ctx.fillStyle = OpenColor.white;
|
||||
ctx.fillStyle = "#fff";
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
// draw items
|
||||
@@ -87,7 +86,7 @@ const generatePreviewImage = async (libraryItems: LibraryItems) => {
|
||||
// draw item border
|
||||
// -------------------------------------------------------------------------
|
||||
ctx.lineWidth = BORDER_WIDTH;
|
||||
ctx.strokeStyle = OpenColor.gray[4];
|
||||
ctx.strokeStyle = "#ced4da";
|
||||
ctx.strokeRect(
|
||||
colOffset + BOX_PADDING / 2,
|
||||
rowOffset + BOX_PADDING / 2,
|
||||
@@ -131,7 +130,7 @@ const SingleLibraryItem = ({
|
||||
elements: libItem.elements,
|
||||
appState: {
|
||||
...appState,
|
||||
viewBackgroundColor: OpenColor.white,
|
||||
viewBackgroundColor: "#fff",
|
||||
exportBackground: true,
|
||||
},
|
||||
files: null,
|
||||
@@ -175,7 +174,7 @@ const SingleLibraryItem = ({
|
||||
}}
|
||||
>
|
||||
<div style={{ padding: "0.5em 0" }}>
|
||||
<span style={{ fontWeight: 500, color: OpenColor.gray[6] }}>
|
||||
<span style={{ fontWeight: 500, color: "#868e96" }}>
|
||||
{t("publishDialog.itemName")}
|
||||
</span>
|
||||
<span aria-hidden="true" className="required">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "../css/variables.module.scss";
|
||||
@use "../css/variables.module" as *;
|
||||
|
||||
.excalidraw {
|
||||
--RadioGroup-background: var(--island-bg-color);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "../css/variables.module.scss";
|
||||
@use "../css/variables.module" as *;
|
||||
|
||||
.excalidraw {
|
||||
--slider-thumb-size: 16px;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "../css/variables.module.scss";
|
||||
@use "../css/variables.module" as *;
|
||||
|
||||
.excalidraw {
|
||||
.SVGLayer {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@import "open-color/open-color";
|
||||
@import "../css//variables.module.scss";
|
||||
@use "../css/variables.module" as *;
|
||||
|
||||
.excalidraw {
|
||||
.layer-ui__search {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "../css/variables.module.scss";
|
||||
@use "../css/variables.module" as *;
|
||||
|
||||
.excalidraw {
|
||||
.ShareableLinkDialog {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@import "open-color/open-color";
|
||||
@import "../../css/variables.module.scss";
|
||||
@use "../../css/variables.module" as *;
|
||||
|
||||
.excalidraw {
|
||||
.sidebar {
|
||||
@@ -19,6 +18,12 @@
|
||||
|
||||
pointer-events: var(--ui-pointerEvents);
|
||||
|
||||
overflow: hidden;
|
||||
border-radius: 0;
|
||||
width: calc(var(--right-sidebar-width) - var(--space-factor) * 2);
|
||||
|
||||
border-left: 1px solid var(--sidebar-border-color);
|
||||
|
||||
:root[dir="rtl"] & {
|
||||
left: 0;
|
||||
right: auto;
|
||||
@@ -28,12 +33,6 @@
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
overflow: hidden;
|
||||
border-radius: 0;
|
||||
width: calc(var(--right-sidebar-width) - var(--space-factor) * 2);
|
||||
|
||||
border-left: 1px solid var(--sidebar-border-color);
|
||||
|
||||
:root[dir="rtl"] & {
|
||||
border-right: 1px solid var(--sidebar-border-color);
|
||||
border-left: 0;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "../../css/variables.module.scss";
|
||||
@use "../../css/variables.module" as *;
|
||||
|
||||
.excalidraw {
|
||||
.sidebar-trigger {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "open-color/open-color.scss";
|
||||
@use "../css/variables.module" as *;
|
||||
|
||||
$duration: 1.6s;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "../css/variables.module.scss";
|
||||
@use "../css/variables.module" as *;
|
||||
|
||||
.excalidraw {
|
||||
--Switch-disabled-color: var(--color-border-outline);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "../../css/variables.module.scss";
|
||||
@use "../../css/variables.module" as *;
|
||||
|
||||
$verticalBreakpoint: 861px;
|
||||
|
||||
@@ -241,7 +241,7 @@ $verticalBreakpoint: 861px;
|
||||
height: 2.5rem;
|
||||
|
||||
font-size: 12px;
|
||||
color: $oc-white;
|
||||
color: #fff;
|
||||
background-color: var(--color-primary);
|
||||
width: 100%;
|
||||
|
||||
@@ -271,7 +271,9 @@ $verticalBreakpoint: 861px;
|
||||
}
|
||||
}
|
||||
|
||||
position: relative;
|
||||
& {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
div {
|
||||
display: contents;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "../css/variables.module.scss";
|
||||
@use "../css/variables.module" as *;
|
||||
|
||||
.excalidraw {
|
||||
--ExcTextField--color: var(--color-on-surface);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "../css/variables.module.scss";
|
||||
@use "../css/variables.module" as *;
|
||||
|
||||
.excalidraw {
|
||||
.TextInput {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "../css/variables.module.scss";
|
||||
@use "../css/variables.module" as *;
|
||||
|
||||
.excalidraw {
|
||||
.Toast {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@import "open-color/open-color.scss";
|
||||
@import "../css/variables.module.scss";
|
||||
@use "../css/variables.module" as *;
|
||||
|
||||
.excalidraw {
|
||||
.ToolIcon {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "../css/variables.module.scss";
|
||||
@use "../css/variables.module" as *;
|
||||
|
||||
.excalidraw {
|
||||
.tool-popover-content {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@import "open-color/open-color.scss";
|
||||
@import "../css/variables.module.scss";
|
||||
@use "../css/variables.module" as *;
|
||||
|
||||
.excalidraw {
|
||||
.App-toolbar {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "../css/variables.module.scss";
|
||||
@use "../css/variables.module" as *;
|
||||
|
||||
// container in body where the actual tooltip is appended to
|
||||
.excalidraw-tooltip {
|
||||
@@ -14,13 +14,13 @@
|
||||
pointer-events: none;
|
||||
word-wrap: break-word;
|
||||
|
||||
background: $oc-black;
|
||||
background: #000;
|
||||
|
||||
line-height: 1.5;
|
||||
text-align: center;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
color: $oc-white;
|
||||
color: #fff;
|
||||
|
||||
display: none;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "../css/variables.module.scss";
|
||||
@use "../css/variables.module" as *;
|
||||
|
||||
.excalidraw {
|
||||
.UnlockPopup {
|
||||
|
||||
@@ -1,10 +1,22 @@
|
||||
@import "../css/variables.module.scss";
|
||||
@use "../css/variables.module" as *;
|
||||
|
||||
.excalidraw {
|
||||
--avatar-size: 1.75rem;
|
||||
--avatarList-gap: 0.625rem;
|
||||
--userList-padding: var(--space-factor);
|
||||
|
||||
--userlist-hint-bg-color: var(--color-gray-10);
|
||||
--userlist-hint-heading-color: var(--color-gray-80);
|
||||
--userlist-hint-text-color: var(--color-gray-60);
|
||||
--userlist-collaborators-border-color: var(--color-gray-20);
|
||||
|
||||
&.theme--dark {
|
||||
--userlist-hint-bg-color: var(--color-gray-90);
|
||||
--userlist-hint-heading-color: var(--color-gray-30);
|
||||
--userlist-hint-text-color: var(--color-gray-40);
|
||||
--userlist-collaborators-border-color: var(--color-gray-80);
|
||||
}
|
||||
|
||||
.UserList__wrapper {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
@@ -50,13 +62,16 @@
|
||||
|
||||
.UserList__more {
|
||||
@include avatarStyles;
|
||||
background-color: var(--color-gray-20);
|
||||
border: 0 !important;
|
||||
font-size: 0.625rem;
|
||||
font-weight: 400;
|
||||
flex-shrink: 0;
|
||||
color: var(--color-gray-100);
|
||||
font-weight: bold;
|
||||
|
||||
& {
|
||||
background-color: var(--color-gray-20);
|
||||
border: 0 !important;
|
||||
font-size: 0.625rem;
|
||||
font-weight: 400;
|
||||
flex-shrink: 0;
|
||||
color: var(--color-gray-100);
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.UserList__collaborator-name {
|
||||
@@ -141,18 +156,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
--userlist-hint-bg-color: var(--color-gray-10);
|
||||
--userlist-hint-heading-color: var(--color-gray-80);
|
||||
--userlist-hint-text-color: var(--color-gray-60);
|
||||
--userlist-collaborators-border-color: var(--color-gray-20);
|
||||
|
||||
&.theme--dark {
|
||||
--userlist-hint-bg-color: var(--color-gray-90);
|
||||
--userlist-hint-heading-color: var(--color-gray-30);
|
||||
--userlist-hint-text-color: var(--color-gray-40);
|
||||
--userlist-collaborators-border-color: var(--color-gray-80);
|
||||
}
|
||||
|
||||
.UserList__collaborators {
|
||||
top: auto;
|
||||
max-height: 50vh;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "../../css/variables.module.scss";
|
||||
@use "../../css/variables.module" as *;
|
||||
|
||||
.excalidraw {
|
||||
.dropdown-menu {
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
.footer-center {
|
||||
pointer-events: none;
|
||||
& > * {
|
||||
pointer-events: var(--ui-pointerEvents);
|
||||
}
|
||||
|
||||
display: flex;
|
||||
width: 100%;
|
||||
justify-content: flex-start;
|
||||
margin-inline-end: 0.6rem;
|
||||
|
||||
& > * {
|
||||
pointer-events: var(--ui-pointerEvents);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "../../css/variables.module.scss";
|
||||
@use "../../css/variables.module" as *;
|
||||
|
||||
.excalidraw-hyperlinkContainer {
|
||||
display: flex;
|
||||
@@ -47,16 +47,16 @@
|
||||
}
|
||||
|
||||
button {
|
||||
color: $oc-blue-6;
|
||||
color: $color-blue-6;
|
||||
background-color: transparent !important;
|
||||
font-weight: 500;
|
||||
&.excalidraw-hyperlinkContainer--remove {
|
||||
color: $oc-red-9;
|
||||
color: $color-red-9;
|
||||
}
|
||||
}
|
||||
|
||||
&--remove .ToolIcon__icon svg {
|
||||
color: $oc-red-6;
|
||||
color: $color-red-6;
|
||||
}
|
||||
|
||||
.ToolIcon__icon {
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
// to determine whether or not the icons should be mirrored in right-to-left languages.
|
||||
|
||||
import clsx from "clsx";
|
||||
import oc from "open-color";
|
||||
import React from "react";
|
||||
|
||||
import { THEME } from "@excalidraw/common";
|
||||
@@ -17,7 +16,7 @@ import type { Theme } from "@excalidraw/element/types";
|
||||
export const iconFillColor = (theme: Theme) => "var(--icon-fill-color)";
|
||||
|
||||
const handlerColor = (theme: Theme) =>
|
||||
theme === THEME.LIGHT ? oc.white : "#1e1e1e";
|
||||
theme === THEME.LIGHT ? "#fff" : "#1e1e1e";
|
||||
|
||||
type Opts = {
|
||||
width?: number;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "../../css/variables.module.scss";
|
||||
@use "../../css/variables.module" as *;
|
||||
|
||||
.excalidraw {
|
||||
.collab-button {
|
||||
@@ -58,8 +58,8 @@
|
||||
bottom: -5px;
|
||||
padding: 3px;
|
||||
border-radius: 50%;
|
||||
background-color: $oc-green-2;
|
||||
color: $oc-green-9;
|
||||
background-color: $color-green-2;
|
||||
color: $color-green-9;
|
||||
font-size: 0.6rem;
|
||||
font-family: "Cascadia";
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
@import "open-color/open-color.scss";
|
||||
|
||||
.visually-hidden {
|
||||
position: absolute !important;
|
||||
height: 1px;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
@import "./variables.module.scss";
|
||||
@import "./theme";
|
||||
@use "./variables.module" as *;
|
||||
@use "./theme";
|
||||
|
||||
:root {
|
||||
--zIndex-canvas: 1;
|
||||
@@ -210,7 +210,7 @@ body.excalidraw-cursor-resize * {
|
||||
|
||||
.divider {
|
||||
width: 1px;
|
||||
background-color: $oc-gray-2;
|
||||
background-color: $color-gray-2;
|
||||
margin: 1px;
|
||||
}
|
||||
|
||||
@@ -729,8 +729,8 @@ body.excalidraw-cursor-resize * {
|
||||
justify-content: center;
|
||||
|
||||
padding: 40px;
|
||||
background-color: $oc-red-1;
|
||||
border: 3px solid $oc-red-9;
|
||||
background-color: $color-red-1;
|
||||
border: 3px solid $color-red-9;
|
||||
}
|
||||
|
||||
.ErrorSplash-paragraph {
|
||||
|
||||
@@ -1,35 +1,36 @@
|
||||
@import "open-color/open-color.scss";
|
||||
@import "./variables.module.scss";
|
||||
@use "sass:color";
|
||||
@use "./variables.module" as *;
|
||||
@forward "./variables.module";
|
||||
|
||||
.excalidraw {
|
||||
--theme-filter: none;
|
||||
--button-destructive-bg-color: #{$oc-red-1};
|
||||
--button-destructive-color: #{$oc-red-9};
|
||||
--button-gray-1: #{$oc-gray-2};
|
||||
--button-gray-2: #{$oc-gray-4};
|
||||
--button-gray-3: #{$oc-gray-5};
|
||||
--button-destructive-bg-color: #{$color-red-1};
|
||||
--button-destructive-color: #{$color-red-9};
|
||||
--button-gray-1: #{$color-gray-2};
|
||||
--button-gray-2: #{$color-gray-4};
|
||||
--button-gray-3: #{$color-gray-5};
|
||||
--mobile-action-button-bg: rgba(255, 255, 255, 0.35);
|
||||
--mobile-color-border: var(--default-border-color);
|
||||
--button-special-active-bg-color: #{$oc-green-0};
|
||||
--button-special-active-bg-color: #{$color-green-0};
|
||||
--dialog-border-color: var(--color-gray-20);
|
||||
--dropdown-icon: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="292.4" height="292.4" viewBox="0 0 292 292"><path d="M287 197L159 69c-4-3-8-5-13-5s-9 2-13 5L5 197c-3 4-5 8-5 13s2 9 5 13c4 4 8 5 13 5h256c5 0 9-1 13-5s5-8 5-13-1-9-5-13z"/></svg>');
|
||||
--focus-highlight-color: #{$oc-blue-2};
|
||||
--focus-highlight-color: #{$color-blue-2};
|
||||
--icon-fill-color: var(--color-on-surface);
|
||||
--icon-green-fill-color: #{$oc-green-9};
|
||||
--default-bg-color: #{$oc-white};
|
||||
--input-bg-color: #{$oc-white};
|
||||
--input-border-color: #{$oc-gray-4};
|
||||
--input-hover-bg-color: #{$oc-gray-1};
|
||||
--input-label-color: #{$oc-gray-7};
|
||||
--icon-green-fill-color: #{$color-green-9};
|
||||
--default-bg-color: #fff;
|
||||
--input-bg-color: #fff;
|
||||
--input-border-color: #{$color-gray-4};
|
||||
--input-hover-bg-color: #{$color-gray-1};
|
||||
--input-label-color: #{$color-gray-7};
|
||||
--island-bg-color: #ffffff;
|
||||
--keybinding-color: var(--color-gray-40);
|
||||
--link-color: #{$oc-blue-7};
|
||||
--overlay-bg-color: #{transparentize($oc-white, 0.12)};
|
||||
--link-color: #{$color-blue-7};
|
||||
--overlay-bg-color: #{color.adjust(#fff, $alpha: -0.12)};
|
||||
--popup-bg-color: var(--island-bg-color);
|
||||
--popup-secondary-bg-color: #{$oc-gray-1};
|
||||
--popup-text-color: #{$oc-black};
|
||||
--popup-text-inverted-color: #{$oc-white};
|
||||
--select-highlight-color: #{$oc-blue-5};
|
||||
--popup-secondary-bg-color: #{$color-gray-1};
|
||||
--popup-text-color: #000;
|
||||
--popup-text-inverted-color: #fff;
|
||||
--select-highlight-color: #{$color-blue-5};
|
||||
--shadow-island: 0px 0px 0.9310142993927002px 0px rgba(0, 0, 0, 0.17),
|
||||
0px 0px 3.1270833015441895px 0px rgba(0, 0, 0, 0.08),
|
||||
0px 7px 14px 0px rgba(0, 0, 0, 0.05);
|
||||
@@ -46,17 +47,6 @@
|
||||
--editor-container-padding: 1rem;
|
||||
--mobile-action-button-size: 2rem;
|
||||
|
||||
@include isMobile {
|
||||
--editor-container-padding: 0.75rem;
|
||||
}
|
||||
|
||||
@media screen and (min-device-width: 1921px) {
|
||||
--lg-button-size: 2.5rem;
|
||||
--lg-icon-size: 1.25rem;
|
||||
--default-button-size: 2.25rem;
|
||||
--default-icon-size: 1.25rem;
|
||||
}
|
||||
|
||||
--scrollbar-thumb: var(--button-gray-2);
|
||||
--scrollbar-thumb-hover: var(--button-gray-3);
|
||||
|
||||
@@ -87,7 +77,7 @@
|
||||
|
||||
--color-selection: #6965db;
|
||||
|
||||
--color-icon-white: #{$oc-white};
|
||||
--color-icon-white: #fff;
|
||||
|
||||
--color-primary: #6965db;
|
||||
--color-primary-darker: #5b57d1;
|
||||
@@ -170,6 +160,17 @@
|
||||
--color-badge: #0b6513;
|
||||
--background-color-badge: #d3ffd2;
|
||||
|
||||
@include isMobile {
|
||||
--editor-container-padding: 0.75rem;
|
||||
}
|
||||
|
||||
@media screen and (min-device-width: 1921px) {
|
||||
--lg-button-size: 2.5rem;
|
||||
--lg-icon-size: 1.25rem;
|
||||
--default-button-size: 2.25rem;
|
||||
--default-icon-size: 1.25rem;
|
||||
}
|
||||
|
||||
&.theme--dark {
|
||||
&.theme--dark-background-none {
|
||||
background: none;
|
||||
@@ -179,7 +180,7 @@
|
||||
&.theme--dark {
|
||||
--theme-filter: invert(93%) hue-rotate(180deg);
|
||||
--button-destructive-bg-color: #5a0000;
|
||||
--button-destructive-color: #{$oc-red-3};
|
||||
--button-destructive-color: #{$color-red-3};
|
||||
|
||||
--button-gray-1: #363636;
|
||||
--button-gray-2: #272727;
|
||||
@@ -189,21 +190,21 @@
|
||||
--button-special-active-bg-color: #204624;
|
||||
--dialog-border-color: var(--color-gray-80);
|
||||
--dropdown-icon: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="292.4" height="292.4" viewBox="0 0 292 292"><path fill="%23ced4da" d="M287 197L159 69c-4-3-8-5-13-5s-9 2-13 5L5 197c-3 4-5 8-5 13s2 9 5 13c4 4 8 5 13 5h256c5 0 9-1 13-5s5-8 5-13-1-9-5-13z"/></svg>');
|
||||
--focus-highlight-color: #{$oc-blue-6};
|
||||
--icon-green-fill-color: #{$oc-green-4};
|
||||
--focus-highlight-color: #{$color-blue-6};
|
||||
--icon-green-fill-color: #{$color-green-4};
|
||||
--default-bg-color: #121212;
|
||||
--input-bg-color: #121212;
|
||||
--input-border-color: #2e2e2e;
|
||||
--input-hover-bg-color: #181818;
|
||||
--input-label-color: #{$oc-gray-2};
|
||||
--input-label-color: #{$color-gray-2};
|
||||
--island-bg-color: #232329;
|
||||
--keybinding-color: var(--color-gray-60);
|
||||
--link-color: #{$oc-blue-4};
|
||||
--overlay-bg-color: #{transparentize($oc-gray-8, 0.88)};
|
||||
--link-color: #{$color-blue-4};
|
||||
--overlay-bg-color: #{color.adjust($color-gray-8, $alpha: -0.88)};
|
||||
--popup-secondary-bg-color: #222;
|
||||
--popup-text-color: #{$oc-gray-4};
|
||||
--popup-text-color: #{$color-gray-4};
|
||||
--popup-text-inverted-color: #2c2c2c;
|
||||
--select-highlight-color: #{$oc-blue-4};
|
||||
--select-highlight-color: #{$color-blue-4};
|
||||
--shadow-island: 0px 0px 0.9310142993927002px 0px rgba(0, 0, 0, 0.17),
|
||||
0px 0px 3.1270833015441895px 0px rgba(0, 0, 0, 0.08),
|
||||
0px 7px 14px 0px rgba(0, 0, 0, 0.05);
|
||||
@@ -216,8 +217,8 @@
|
||||
0px 2.76726px 2.21381px rgba(0, 0, 0, 0.0196802);
|
||||
--avatar-border-color: var(--color-gray-85);
|
||||
|
||||
--scrollbar-thumb: #{$oc-gray-8};
|
||||
--scrollbar-thumb-hover: #{$oc-gray-7};
|
||||
--scrollbar-thumb: #{$color-gray-8};
|
||||
--scrollbar-thumb-hover: #{$color-gray-7};
|
||||
|
||||
--color-slider-track: hsl(244, 23%, 39%);
|
||||
|
||||
|
||||
@@ -1,4 +1,27 @@
|
||||
@import "open-color/open-color.scss";
|
||||
$color-red-1: #ffe3e3;
|
||||
$color-red-3: #ffa8a8;
|
||||
$color-red-6: #fa5252;
|
||||
$color-red-7: #f03e3e;
|
||||
$color-red-8: #e03131;
|
||||
$color-red-9: #c92a2a;
|
||||
$color-gray-1: #f1f3f5;
|
||||
$color-gray-2: #e9ecef;
|
||||
$color-gray-4: #ced4da;
|
||||
$color-gray-5: #adb5bd;
|
||||
$color-gray-6: #868e96;
|
||||
$color-gray-7: #495057;
|
||||
$color-gray-8: #343a40;
|
||||
$color-green-0: #ebfbee;
|
||||
$color-green-2: #b2f2bb;
|
||||
$color-green-4: #69db7c;
|
||||
$color-green-9: #2b8a3e;
|
||||
$color-blue-1: #d0ebff;
|
||||
$color-blue-2: #a5d8ff;
|
||||
$color-blue-4: #4dabf7;
|
||||
$color-blue-5: #339af0;
|
||||
$color-blue-6: #228be6;
|
||||
$color-blue-7: #1c7ed6;
|
||||
$color-blue-8: #1971c2;
|
||||
|
||||
@mixin isMobile() {
|
||||
@at-root .excalidraw--mobile#{&} {
|
||||
@@ -137,7 +160,10 @@
|
||||
|
||||
@mixin outlineButtonIconStyles {
|
||||
@include outlineButtonStyles;
|
||||
padding: 0;
|
||||
|
||||
& {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
svg {
|
||||
width: var(--default-icon-size);
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import OpenColor from "open-color";
|
||||
|
||||
import { CURSOR_TYPE, MIME_TYPES, THEME } from "@excalidraw/common";
|
||||
|
||||
import { isHandToolActive, isEraserActive } from "./appState";
|
||||
@@ -60,9 +58,9 @@ export const setEraserCursor = (
|
||||
0,
|
||||
2 * Math.PI,
|
||||
);
|
||||
context.fillStyle = isDarkTheme ? OpenColor.black : OpenColor.white;
|
||||
context.fillStyle = isDarkTheme ? "#000" : "#fff";
|
||||
context.fill();
|
||||
context.strokeStyle = isDarkTheme ? OpenColor.white : OpenColor.black;
|
||||
context.strokeStyle = isDarkTheme ? "#fff" : "#000";
|
||||
context.stroke();
|
||||
previewDataURL = eraserCanvasCache.toDataURL(MIME_TYPES.svg) as DataURL;
|
||||
};
|
||||
|
||||
@@ -100,7 +100,6 @@
|
||||
"lodash.debounce": "4.0.8",
|
||||
"lodash.throttle": "4.1.1",
|
||||
"nanoid": "3.3.3",
|
||||
"open-color": "1.9.1",
|
||||
"pako": "2.0.3",
|
||||
"perfect-freehand": "1.2.0",
|
||||
"pica": "7.1.1",
|
||||
|
||||
@@ -6,7 +6,6 @@ import {
|
||||
type LocalPoint,
|
||||
type Radians,
|
||||
} from "@excalidraw/math";
|
||||
import oc from "open-color";
|
||||
|
||||
import {
|
||||
arrayToMap,
|
||||
@@ -1301,7 +1300,7 @@ const _renderInteractiveScene = ({
|
||||
elementsMap,
|
||||
);
|
||||
}
|
||||
const selectionColor = renderConfig.selectionColor || oc.black;
|
||||
const selectionColor = renderConfig.selectionColor || "#000";
|
||||
|
||||
if (showBoundingBox) {
|
||||
// Optimisation for finding quickly relevant element ids
|
||||
@@ -1384,7 +1383,7 @@ const _renderInteractiveScene = ({
|
||||
y2,
|
||||
selectionColors: groupElements.some((el) => el.locked)
|
||||
? ["#ced4da"]
|
||||
: [oc.black],
|
||||
: ["#000"],
|
||||
dashed: true,
|
||||
cx: x1 + (x2 - x1) / 2,
|
||||
cy: y1 + (y2 - y1) / 2,
|
||||
@@ -1410,7 +1409,7 @@ const _renderInteractiveScene = ({
|
||||
context.translate(appState.scrollX, appState.scrollY);
|
||||
|
||||
if (selectedElements.length === 1) {
|
||||
context.fillStyle = oc.white;
|
||||
context.fillStyle = "#fff";
|
||||
const transformHandles = getTransformHandles(
|
||||
selectedElements[0],
|
||||
appState.zoom,
|
||||
@@ -1455,7 +1454,7 @@ const _renderInteractiveScene = ({
|
||||
) {
|
||||
const dashedLinePadding =
|
||||
(DEFAULT_TRANSFORM_HANDLE_SPACING * 2) / appState.zoom.value;
|
||||
context.fillStyle = oc.white;
|
||||
context.fillStyle = "#fff";
|
||||
const [x1, y1, x2, y2] = getCommonBounds(selectedElements, elementsMap);
|
||||
const initialLineDash = context.getLineDash();
|
||||
context.setLineDash([2 / appState.zoom.value]);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { normalizeInputColor } from "../components/ColorPicker/ColorInput";
|
||||
import { normalizeInputColor } from "@excalidraw/common";
|
||||
|
||||
describe("normalizeInputColor", () => {
|
||||
describe("hex colors", () => {
|
||||
|
||||
@@ -5,13 +5,13 @@ import { getOriginalContainerHeightFromCache } from "@excalidraw/element";
|
||||
|
||||
import {
|
||||
CODES,
|
||||
colorToHex,
|
||||
KEYS,
|
||||
FONT_FAMILY,
|
||||
TEXT_ALIGN,
|
||||
THEME,
|
||||
VERTICAL_ALIGN,
|
||||
applyDarkModeFilter,
|
||||
tinycolor,
|
||||
} from "@excalidraw/common";
|
||||
|
||||
import type {
|
||||
@@ -1672,7 +1672,7 @@ describe("textWysiwyg", () => {
|
||||
|
||||
// Helper to compare colors (browser may return rgb format)
|
||||
const colorsAreEqual = (color1: string, color2: string) => {
|
||||
return tinycolor(color1).toHex() === tinycolor(color2).toHex();
|
||||
return colorToHex(color1) === colorToHex(color2);
|
||||
};
|
||||
|
||||
beforeEach(async () => {
|
||||
|
||||
@@ -51,7 +51,6 @@
|
||||
"@braintree/sanitize-url": "6.0.2",
|
||||
"@excalidraw/laser-pointer": "1.3.1",
|
||||
"browser-fs-access": "0.29.1",
|
||||
"open-color": "1.9.1",
|
||||
"pako": "2.0.3",
|
||||
"perfect-freehand": "1.2.0",
|
||||
"png-chunk-text": "1.0.0",
|
||||
|
||||
+45
-1
@@ -1,4 +1,6 @@
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
const { pathToFileURL } = require("url");
|
||||
|
||||
const { build } = require("esbuild");
|
||||
const { sassPlugin } = require("esbuild-sass-plugin");
|
||||
@@ -16,6 +18,44 @@ const ENV_VARS = {
|
||||
},
|
||||
};
|
||||
|
||||
// Resolve a relative path from the source file's directory
|
||||
const resolveRelativePath = (importPath, sourceFile) => {
|
||||
const sourceDir = path.dirname(sourceFile);
|
||||
const extensions = [".scss", ".css", ""];
|
||||
|
||||
for (const ext of extensions) {
|
||||
const fullPath = path.resolve(sourceDir, importPath + ext);
|
||||
if (fs.existsSync(fullPath)) {
|
||||
return fullPath;
|
||||
}
|
||||
// Try with underscore prefix for partials
|
||||
const partialPath = path.join(
|
||||
path.dirname(fullPath),
|
||||
`_${path.basename(fullPath)}`,
|
||||
);
|
||||
if (fs.existsSync(partialPath)) {
|
||||
return partialPath;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
// Precompile function to convert relative paths to absolute paths
|
||||
const precompile = (source, sourcePath) => {
|
||||
// Match @use and @forward statements with relative paths
|
||||
const importRegex = /(@use|@forward)\s+["'](\.[^"']+)["']/g;
|
||||
|
||||
return source.replace(importRegex, (match, directive, importPath) => {
|
||||
const resolvedPath = resolveRelativePath(importPath, sourcePath);
|
||||
if (resolvedPath) {
|
||||
// Convert to file:// URL format for sass
|
||||
const fileUrl = pathToFileURL(resolvedPath).href;
|
||||
return `${directive} "${fileUrl}"`;
|
||||
}
|
||||
return match;
|
||||
});
|
||||
};
|
||||
|
||||
// excludes all external dependencies and bundles only the source code
|
||||
const getConfig = (outdir) => ({
|
||||
outdir,
|
||||
@@ -23,7 +63,11 @@ const getConfig = (outdir) => ({
|
||||
splitting: true,
|
||||
format: "esm",
|
||||
packages: "external",
|
||||
plugins: [sassPlugin()],
|
||||
plugins: [
|
||||
sassPlugin({
|
||||
precompile,
|
||||
}),
|
||||
],
|
||||
target: "es2020",
|
||||
assetNames: "[dir]/[name]",
|
||||
chunkNames: "[dir]/[name]-[hash]",
|
||||
|
||||
@@ -7616,11 +7616,6 @@ onetime@^5.1.0, onetime@^5.1.2:
|
||||
dependencies:
|
||||
mimic-fn "^2.1.0"
|
||||
|
||||
open-color@1.9.1:
|
||||
version "1.9.1"
|
||||
resolved "https://registry.yarnpkg.com/open-color/-/open-color-1.9.1.tgz#a6e6328f60eff7aa60e3e8fcfa50f53ff3eece35"
|
||||
integrity sha512-vCseG/EQ6/RcvxhUcGJiHViOgrtz4x0XbZepXvKik66TMGkvbmjeJrKFyBEx6daG5rNyyd14zYXhz0hZVwQFOw==
|
||||
|
||||
opener@^1.5.1:
|
||||
version "1.5.2"
|
||||
resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598"
|
||||
|
||||
Reference in New Issue
Block a user