feat(editor): store real color values in edgeless (#9254)

### What's Changed!

* adds theme type: `ThemeSchema`
* adds default theme: `DefaultTheme`
* stores real color values
This commit is contained in:
fundon
2024-12-30 03:36:35 +00:00
parent a5641ae608
commit b9f2650369
287 changed files with 2219 additions and 1520 deletions

View File

@@ -17,7 +17,7 @@ import {
import { Bound } from '@blocksuite/global/utils';
import { BlockModel, defineBlockSchema, type Text } from '@blocksuite/store';
import type { Color } from '../../consts/index.js';
import type { Color } from '../../themes/index.js';
export type FrameBlockProps = {
title: Text;

View File

@@ -7,8 +7,6 @@ import { Bound } from '@blocksuite/global/utils';
import { BlockModel, defineBlockSchema } from '@blocksuite/store';
import {
type Color,
DEFAULT_NOTE_BACKGROUND_COLOR,
DEFAULT_NOTE_BORDER_SIZE,
DEFAULT_NOTE_BORDER_STYLE,
DEFAULT_NOTE_CORNER,
@@ -18,12 +16,13 @@ import {
NoteDisplayMode,
type StrokeStyle,
} from '../../consts/index.js';
import { type Color, DefaultTheme } from '../../themes/index.js';
export const NoteBlockSchema = defineBlockSchema({
flavour: 'affine:note',
props: (): NoteProps => ({
xywh: `[0,0,${DEFAULT_NOTE_WIDTH},${DEFAULT_NOTE_HEIGHT}]`,
background: DEFAULT_NOTE_BACKGROUND_COLOR,
background: DefaultTheme.noteBackgrounColor,
index: 'a0',
lockedBySelf: false,
hidden: false,

View File

@@ -1,3 +0,0 @@
import { StrokeColor } from './color.js';
export const DEFAULT_BRUSH_COLOR = StrokeColor.Blue;

View File

@@ -1,97 +0,0 @@
import { themeToVar } from '@toeverything/theme/v2';
import { z } from 'zod';
import { createEnumMap } from '../utils/enum.js';
export const Transparent = 'transparent';
export const White = themeToVar('edgeless/palette/white');
export const Black = themeToVar('edgeless/palette/black');
export const Light = {
Red: themeToVar('edgeless/palette/light/redLight'),
Orange: themeToVar('edgeless/palette/light/orangeLight'),
Yellow: themeToVar('edgeless/palette/light/yellowLight'),
Green: themeToVar('edgeless/palette/light/greenLight'),
Blue: themeToVar('edgeless/palette/light/blueLight'),
Purple: themeToVar('edgeless/palette/light/purpleLight'),
Magenta: themeToVar('edgeless/palette/light/magentaLight'),
Grey: themeToVar('edgeless/palette/light/greyLight'),
} as const;
export const LIGHT_PALETTES = [
Light.Red,
Light.Orange,
Light.Yellow,
Light.Green,
Light.Blue,
Light.Purple,
Light.Magenta,
Light.Grey,
] as const;
export const Medium = {
Red: themeToVar('edgeless/palette/medium/redMedium'),
Orange: themeToVar('edgeless/palette/medium/orangeMedium'),
Yellow: themeToVar('edgeless/palette/medium/yellowMedium'),
Green: themeToVar('edgeless/palette/medium/greenMedium'),
Blue: themeToVar('edgeless/palette/medium/blueMedium'),
Purple: themeToVar('edgeless/palette/medium/purpleMedium'),
Magenta: themeToVar('edgeless/palette/medium/magentaMedium'),
Grey: themeToVar('edgeless/palette/medium/greyMedium'),
} as const;
export const MEDIUM_PALETTES = [
Medium.Red,
Medium.Orange,
Medium.Yellow,
Medium.Green,
Medium.Blue,
Medium.Purple,
Medium.Magenta,
Medium.Grey,
] as const;
export const Heavy = {
Red: themeToVar('edgeless/palette/heavy/red'),
Orange: themeToVar('edgeless/palette/heavy/orange'),
Yellow: themeToVar('edgeless/palette/heavy/yellow'),
Green: themeToVar('edgeless/palette/heavy/green'),
Blue: themeToVar('edgeless/palette/heavy/blue'),
Purple: themeToVar('edgeless/palette/heavy/purple'),
Magenta: themeToVar('edgeless/palette/heavy/magenta'),
} as const;
export const HEAVY_PALETTES = [
Heavy.Red,
Heavy.Orange,
Heavy.Yellow,
Heavy.Green,
Heavy.Blue,
Heavy.Purple,
Heavy.Magenta,
] as const;
export const PALETTES = [
// Light
...LIGHT_PALETTES,
Transparent,
// Medium
...MEDIUM_PALETTES,
White,
// Heavy
...HEAVY_PALETTES,
Black,
] as const;
export const PaletteEnum = z.enum(PALETTES);
export const StrokeColor = { Black, White, ...Medium } as const;
export const StrokeColorMap = createEnumMap(StrokeColor);
export const STROKE_COLORS = [...MEDIUM_PALETTES, Black, White] as const;

View File

@@ -1,5 +1,4 @@
import { createEnumMap } from '../utils/enum.js';
import { StrokeColor } from './color.js';
export enum ConnectorEndpoint {
Front = 'Front',
@@ -16,10 +15,6 @@ export enum PointStyle {
export const PointStyleMap = createEnumMap(PointStyle);
export const DEFAULT_CONNECTOR_COLOR = StrokeColor.Grey;
export const DEFAULT_CONNECTOR_TEXT_COLOR = StrokeColor.Black;
export const DEFAULT_FRONT_END_POINT_STYLE = PointStyle.None;
export const DEFAULT_REAR_END_POINT_STYLE = PointStyle.Arrow;

View File

@@ -1,3 +0,0 @@
import { Light } from './color.js';
export const FrameBackgroundColor = Light;

View File

@@ -1,8 +1,5 @@
export * from './brush.js';
export * from './color.js';
export * from './connector.js';
export * from './doc.js';
export * from './frame.js';
export * from './image.js';
export * from './line.js';
export * from './mindmap.js';

View File

@@ -3,14 +3,14 @@ import { z } from 'zod';
import { createEnumMap } from '../utils/enum.js';
export enum LineWidth {
Eight = 8,
Two = 2,
// Thin
Four = 4,
Six = 6,
Eight = 8,
// Thick
Ten = 10,
Twelve = 12,
Two = 2,
}
export const LINE_WIDTHS = [
@@ -23,7 +23,7 @@ export const LINE_WIDTHS = [
];
/**
* Use `StrokeColor` instead.
* Use `DefaultTheme.StrokeColorMap` instead.
*
* @deprecated
*/
@@ -43,6 +43,11 @@ export enum LineColor {
export const LineColorMap = createEnumMap(LineColor);
/**
* Use `DefaultTheme.StrokeColorPalettes` instead.
*
* @deprecated
*/
export const LINE_COLORS = [
LineColor.Yellow,
LineColor.Orange,

View File

@@ -1,4 +1,3 @@
import { themeToVar } from '@toeverything/theme/v2';
import { z } from 'zod';
import { createEnumMap } from '../utils/enum.js';
@@ -9,40 +8,6 @@ export const NOTE_MIN_HEIGHT = 92;
export const DEFAULT_NOTE_WIDTH = NOTE_MIN_WIDTH;
export const DEFAULT_NOTE_HEIGHT = NOTE_MIN_HEIGHT;
export const NoteBackgroundColor = {
Yellow: themeToVar('edgeless/note/yellow'),
Orange: themeToVar('edgeless/note/orange'),
Red: themeToVar('edgeless/note/red'),
Magenta: themeToVar('edgeless/note/magenta'),
Purple: themeToVar('edgeless/note/purple'),
Blue: themeToVar('edgeless/note/blue'),
Teal: themeToVar('edgeless/note/teal'),
Green: themeToVar('edgeless/note/green'),
Black: themeToVar('edgeless/note/black'),
Grey: themeToVar('edgeless/note/grey'),
White: themeToVar('edgeless/note/white'),
} as const;
export const NoteBackgroundColorMap = createEnumMap(NoteBackgroundColor);
export const NOTE_BACKGROUND_PALETTES = [
NoteBackgroundColor.Yellow,
NoteBackgroundColor.Orange,
NoteBackgroundColor.Red,
NoteBackgroundColor.Magenta,
NoteBackgroundColor.Purple,
NoteBackgroundColor.Blue,
NoteBackgroundColor.Teal,
NoteBackgroundColor.Green,
NoteBackgroundColor.Black,
NoteBackgroundColor.Grey,
NoteBackgroundColor.White,
] as const;
export const NoteBackgroundPaletteEnum = z.enum(NOTE_BACKGROUND_PALETTES);
export const DEFAULT_NOTE_BACKGROUND_COLOR = NoteBackgroundColor.White;
export enum NoteShadow {
Box = '--affine-note-shadow-box',
Film = '--affine-note-shadow-film',

View File

@@ -1,5 +1,3 @@
import { Black, Light, LIGHT_PALETTES, StrokeColor, White } from './color.js';
export const DEFAULT_ROUGHNESS = 1.4;
// TODO: need to check the default central area ratio
@@ -46,13 +44,3 @@ export enum ShapeStyle {
General = 'General',
Scribbled = 'Scribbled',
}
export const ShapeFillColor = { Black, White, ...Light } as const;
export const SHAPE_FILL_COLORS = [...LIGHT_PALETTES, Black, White];
export const DEFAULT_SHAPE_FILL_COLOR = Light.Yellow;
export const DEFAULT_SHAPE_STROKE_COLOR = StrokeColor.Yellow;
export const DEFAULT_SHAPE_TEXT_COLOR = StrokeColor.Black;

View File

@@ -1,12 +1,5 @@
import type { Color } from '../themes/color.js';
import { createEnumMap } from '../utils/enum.js';
import { StrokeColor } from './color.js';
export enum ColorScheme {
Dark = 'dark',
Light = 'light',
}
export type Color = string | Partial<Record<ColorScheme | 'normal', string>>;
export enum TextAlign {
Center = 'center',
@@ -66,5 +59,3 @@ export enum TextResizing {
AUTO_WIDTH_AND_HEIGHT,
AUTO_HEIGHT,
}
export const DEFAULT_TEXT_COLOR = StrokeColor.Blue;

View File

@@ -28,7 +28,7 @@ import {
Vec,
} from '@blocksuite/global/utils';
import type { Color } from '../../consts/index.js';
import type { Color } from '../../themes/index.js';
export type BrushProps = BaseElementProps & {
/**

View File

@@ -26,7 +26,6 @@ import {
import { DocCollection, type Y } from '@blocksuite/store';
import {
type Color,
CONNECTOR_LABEL_MAX_WIDTH,
ConnectorLabelOffsetAnchor,
ConnectorMode,
@@ -39,6 +38,7 @@ import {
TextAlign,
type TextStyleProps,
} from '../../consts/index.js';
import type { Color } from '../../themes/index.ts';
export type SerializedConnection = {
id?: string;

View File

@@ -2,12 +2,12 @@ import { GfxLocalElementModel } from '@blocksuite/block-std/gfx';
import type { PointLocation } from '@blocksuite/global/utils';
import {
type Color,
ConnectorMode,
DEFAULT_ROUGHNESS,
type PointStyle,
StrokeStyle,
} from '../../consts/index.js';
import type { Color } from '../../themes/index.ts';
import type { Connection } from './connector.js';
export class LocalConnectorElementModel extends GfxLocalElementModel {

View File

@@ -1,11 +1,10 @@
import { isEqual, last } from '@blocksuite/global/utils';
import { ConnectorMode } from '../../consts/connector.js';
import { LineColor } from '../../consts/line.js';
import { MindmapStyle } from '../../consts/mindmap.js';
import { StrokeStyle } from '../../consts/note.js';
import { ShapeFillColor } from '../../consts/shape.js';
import { FontFamily, FontWeight, TextResizing } from '../../consts/text.js';
import { type Color, DefaultTheme } from '../../themes/index.js';
import type { MindmapNode } from './mindmap.js';
export type CollapseButton = {
@@ -14,9 +13,9 @@ export type CollapseButton = {
radius: number;
filled: boolean;
fillColor: string;
fillColor: Color;
strokeColor: string;
strokeColor: Color;
strokeWidth: number;
};
@@ -25,24 +24,24 @@ export type ExpandButton = CollapseButton & {
fontSize: number;
fontWeight: FontWeight;
color: string;
color: Color;
};
export type NodeStyle = {
radius: number;
strokeWidth: number;
strokeColor: string;
strokeColor: Color;
textResizing: TextResizing;
fontSize: number;
fontFamily: string;
fontWeight: FontWeight;
color: string;
color: Color;
filled: boolean;
fillColor: string;
fillColor: Color;
padding: [number, number];
@@ -56,7 +55,7 @@ export type NodeStyle = {
export type ConnectorStyle = {
strokeStyle: StrokeStyle;
stroke: string;
stroke: Color;
strokeWidth: number;
mode: ConnectorMode;
@@ -78,11 +77,11 @@ export abstract class MindmapStyleGetter {
export class StyleOne extends MindmapStyleGetter {
private readonly _colorOrders = [
LineColor.Purple,
LineColor.Magenta,
LineColor.Orange,
LineColor.Yellow,
LineColor.Green,
DefaultTheme.StrokeColorMap.Purple,
DefaultTheme.StrokeColorMap.Magenta,
DefaultTheme.StrokeColorMap.Orange,
DefaultTheme.StrokeColorMap.Yellow,
DefaultTheme.StrokeColorMap.Green,
'#7ae2d5',
];
@@ -92,15 +91,15 @@ export class StyleOne extends MindmapStyleGetter {
textResizing: TextResizing.AUTO_WIDTH_AND_HEIGHT,
strokeWidth: 4,
strokeColor: '#84CFFF',
strokeColor: '#84cfff',
fontFamily: FontFamily.Poppins,
fontSize: 20,
fontWeight: FontWeight.SemiBold,
color: '--affine-black',
color: DefaultTheme.pureBlack,
filled: true,
fillColor: '--affine-white',
fillColor: DefaultTheme.pureWhite,
padding: [11, 22] as [number, number],
@@ -133,7 +132,7 @@ export class StyleOne extends MindmapStyleGetter {
radius: 0.5,
filled: true,
fillColor: '--affine-white',
fillColor: DefaultTheme.pureWhite,
strokeColor: color,
strokeWidth: 3,
@@ -151,7 +150,7 @@ export class StyleOne extends MindmapStyleGetter {
padding: [4, 0],
color: '--affine-white',
color: DefaultTheme.pureWhite,
fontFamily: FontFamily.Inter,
fontWeight: FontWeight.Bold,
@@ -168,10 +167,10 @@ export class StyleOne extends MindmapStyleGetter {
fontFamily: FontFamily.Poppins,
fontSize: 16,
fontWeight: FontWeight.Medium,
color: '--affine-black',
color: DefaultTheme.pureBlack,
filled: true,
fillColor: '--affine-white',
fillColor: DefaultTheme.pureWhite,
padding: [6, 22] as [number, number],
@@ -189,9 +188,9 @@ export const styleOne = new StyleOne();
export class StyleTwo extends MindmapStyleGetter {
private readonly _colorOrders = [
ShapeFillColor.Blue,
DefaultTheme.StrokeColorMap.Blue,
'#7ae2d5',
ShapeFillColor.Yellow,
DefaultTheme.StrokeColorMap.Yellow,
];
readonly root = {
@@ -200,15 +199,15 @@ export class StyleTwo extends MindmapStyleGetter {
textResizing: TextResizing.AUTO_WIDTH_AND_HEIGHT,
strokeWidth: 3,
strokeColor: '--affine-black',
strokeColor: DefaultTheme.pureBlack,
fontFamily: FontFamily.Poppins,
fontSize: 18,
fontWeight: FontWeight.SemiBold,
color: ShapeFillColor.Black,
color: DefaultTheme.pureBlack,
filled: true,
fillColor: ShapeFillColor.Orange,
fillColor: DefaultTheme.StrokeColorMap.Yellow,
padding: [11, 22] as [number, number],
@@ -216,7 +215,7 @@ export class StyleTwo extends MindmapStyleGetter {
blur: 0,
offsetX: 3,
offsetY: 3,
color: '--affine-black',
color: DefaultTheme.pureBlack,
},
};
@@ -232,7 +231,7 @@ export class StyleTwo extends MindmapStyleGetter {
return {
connector: {
strokeStyle: StrokeStyle.Solid,
stroke: '--affine-black',
stroke: DefaultTheme.pureBlack,
strokeWidth: 3,
mode: ConnectorMode.Orthogonal,
@@ -243,9 +242,9 @@ export class StyleTwo extends MindmapStyleGetter {
radius: 0.5,
filled: true,
fillColor: '--affine-white',
fillColor: DefaultTheme.pureWhite,
strokeColor: '--affine-black',
strokeColor: DefaultTheme.pureBlack,
strokeWidth: 3,
},
expandButton: {
@@ -254,14 +253,14 @@ export class StyleTwo extends MindmapStyleGetter {
radius: 2,
filled: true,
fillColor: '--affine-black',
fillColor: DefaultTheme.pureBlack,
padding: [4, 0],
strokeColor: '--affine-black',
strokeColor: DefaultTheme.pureBlack,
strokeWidth: 0,
color: '--affine-white',
color: DefaultTheme.pureWhite,
fontFamily: FontFamily.Inter,
fontWeight: FontWeight.Bold,
@@ -273,12 +272,12 @@ export class StyleTwo extends MindmapStyleGetter {
textResizing: TextResizing.AUTO_WIDTH_AND_HEIGHT,
strokeWidth: 3,
strokeColor: '--affine-black',
strokeColor: DefaultTheme.pureBlack,
fontFamily: FontFamily.Poppins,
fontSize: 16,
fontWeight: FontWeight.SemiBold,
color: ShapeFillColor.Black,
color: DefaultTheme.pureBlack,
filled: true,
fillColor: color,
@@ -289,7 +288,7 @@ export class StyleTwo extends MindmapStyleGetter {
blur: 0,
offsetX: 3,
offsetY: 3,
color: '--affine-black',
color: DefaultTheme.pureBlack,
},
},
};
@@ -299,9 +298,9 @@ export const styleTwo = new StyleTwo();
export class StyleThree extends MindmapStyleGetter {
private readonly _strokeColor = [
LineColor.Yellow,
LineColor.Green,
LineColor.Teal,
DefaultTheme.StrokeColorMap.Yellow,
DefaultTheme.StrokeColorMap.Green,
DefaultTheme.StrokeColorMap.Teal,
];
readonly root = {
@@ -315,10 +314,10 @@ export class StyleThree extends MindmapStyleGetter {
fontFamily: FontFamily.Poppins,
fontSize: 16,
fontWeight: FontWeight.Medium,
color: ShapeFillColor.Black,
color: DefaultTheme.pureBlack,
filled: true,
fillColor: ShapeFillColor.Yellow,
fillColor: DefaultTheme.StrokeColorMap.Yellow,
padding: [10, 22] as [number, number],
@@ -349,10 +348,10 @@ export class StyleThree extends MindmapStyleGetter {
fontFamily: FontFamily.Poppins,
fontSize: 16,
fontWeight: FontWeight.Medium,
color: ShapeFillColor.Black,
color: DefaultTheme.pureBlack,
filled: true,
fillColor: ShapeFillColor.White,
fillColor: DefaultTheme.pureWhite,
padding: [6, 22] as [number, number],
@@ -369,9 +368,9 @@ export class StyleThree extends MindmapStyleGetter {
radius: 0.5,
filled: true,
fillColor: '--affine-white',
fillColor: DefaultTheme.pureWhite,
strokeColor: '#3CBC36',
strokeColor: '#3cbc36',
strokeWidth: 3,
},
expandButton: {
@@ -380,11 +379,11 @@ export class StyleThree extends MindmapStyleGetter {
radius: 8,
filled: true,
fillColor: '#3CBC36',
fillColor: '#3cbc36',
padding: [4, 0],
strokeColor: '#3CBC36',
strokeColor: '#3cbc36',
strokeWidth: 0,
color: '#fff',
@@ -407,12 +406,12 @@ export const styleThree = new StyleThree();
export class StyleFour extends MindmapStyleGetter {
private readonly _colors = [
ShapeFillColor.Purple,
ShapeFillColor.Magenta,
ShapeFillColor.Orange,
ShapeFillColor.Yellow,
ShapeFillColor.Green,
ShapeFillColor.Blue,
DefaultTheme.StrokeColorMap.Purple,
DefaultTheme.StrokeColorMap.Magenta,
DefaultTheme.StrokeColorMap.Orange,
DefaultTheme.StrokeColorMap.Yellow,
DefaultTheme.StrokeColorMap.Green,
DefaultTheme.StrokeColorMap.Blue,
];
readonly root = {
@@ -426,7 +425,7 @@ export class StyleFour extends MindmapStyleGetter {
fontFamily: FontFamily.Kalam,
fontSize: 22,
fontWeight: FontWeight.Bold,
color: '--affine-black',
color: DefaultTheme.black,
filled: true,
fillColor: 'transparent',
@@ -455,7 +454,7 @@ export class StyleFour extends MindmapStyleGetter {
radius: 0.5,
filled: true,
fillColor: '--affine-white',
fillColor: DefaultTheme.pureWhite,
strokeColor: stroke,
strokeWidth: 3,
@@ -473,7 +472,7 @@ export class StyleFour extends MindmapStyleGetter {
strokeColor: stroke,
strokeWidth: 0,
color: '--affine-white',
color: DefaultTheme.pureWhite,
fontFamily: FontFamily.Inter,
fontWeight: FontWeight.Bold,

View File

@@ -19,22 +19,20 @@ import type {
import { DocCollection, type Y } from '@blocksuite/store';
import {
type Color,
DEFAULT_ROUGHNESS,
FontFamily,
FontStyle,
FontWeight,
ShapeFillColor,
ShapeStyle,
ShapeTextFontSize,
ShapeType,
StrokeColor,
StrokeStyle,
TextAlign,
TextResizing,
type TextStyleProps,
TextVerticalAlign,
} from '../../consts/index.js';
import { type Color, DefaultTheme } from '../../themes/index.js';
import { shapeMethods } from './api/index.js';
export type ShapeProps = BaseElementProps & {
@@ -104,7 +102,7 @@ export class ShapeElementModel extends GfxPrimitiveElementModel<ShapeProps> {
accessor color!: Color;
@field()
accessor fillColor: Color = ShapeFillColor.Yellow;
accessor fillColor: Color = DefaultTheme.shapeFillColor;
@field()
accessor filled: boolean = false;
@@ -160,7 +158,7 @@ export class ShapeElementModel extends GfxPrimitiveElementModel<ShapeProps> {
accessor shapeType: ShapeType = ShapeType.Rect;
@field()
accessor strokeColor: Color = StrokeColor.Yellow;
accessor strokeColor: Color = DefaultTheme.shapeStrokeColor;
@field()
accessor strokeStyle: StrokeStyle = StrokeStyle.Solid;
@@ -205,7 +203,7 @@ export class LocalShapeElementModel extends GfxLocalElementModel {
accessor color: Color = '#000000';
@prop()
accessor fillColor: Color = ShapeFillColor.Yellow;
accessor fillColor: Color = DefaultTheme.shapeFillColor;
@prop()
accessor filled: boolean = false;
@@ -246,7 +244,7 @@ export class LocalShapeElementModel extends GfxLocalElementModel {
accessor shapeType: ShapeType = ShapeType.Rect;
@prop()
accessor strokeColor: Color = StrokeColor.Yellow;
accessor strokeColor: Color = DefaultTheme.shapeStrokeColor;
@prop()
accessor strokeStyle: StrokeStyle = StrokeStyle.Solid;

View File

@@ -11,13 +11,13 @@ import {
import { DocCollection, type Y } from '@blocksuite/store';
import {
type Color,
FontFamily,
FontStyle,
FontWeight,
TextAlign,
type TextStyleProps,
} from '../../consts/index.js';
import type { Color } from '../../themes/index.js';
export type TextElementProps = BaseElementProps & {
text: Y.Text;

View File

@@ -1,4 +1,5 @@
export * from './blocks/index.js';
export * from './consts/index.js';
export * from './elements/index.js';
export * from './themes/index.js';
export * from './utils/index.js';

View File

@@ -0,0 +1,54 @@
import { z } from 'zod';
export enum ColorScheme {
Dark = 'dark',
Light = 'light',
}
const ColorNormalSchema = z.object({
normal: z.string(),
});
const ColorDarkLightSchema = z.object({
[ColorScheme.Dark]: z.string(),
[ColorScheme.Light]: z.string(),
});
export const ColorSchema = z.union([
z.string(),
ColorNormalSchema,
ColorDarkLightSchema,
]);
export type Color = z.infer<typeof ColorSchema>;
// Converts `Color` type to string.
export function resolveColor(
color: Color,
colorScheme: ColorScheme,
fallback = 'transparent'
): string {
let value = fallback;
if (typeof color === 'object') {
if (ColorScheme.Dark in color && ColorScheme.Light in color) {
value = color[colorScheme];
} else if ('normal' in color) {
value = color.normal;
}
} else {
value = color;
}
if (!value) {
value = fallback;
}
return value;
}
export function isTransparent(color: Color) {
return (
typeof color === 'string' && color.toLowerCase().endsWith('transparent')
);
}

View File

@@ -0,0 +1,104 @@
import type { Palette, Theme } from './types.js';
import { buildPalettes, getColorByKey, pureBlack, pureWhite } from './utils.js';
const Transparent = 'transparent';
const White = getColorByKey('edgeless/palette/white');
const Black = getColorByKey('edgeless/palette/black');
const Light = {
Red: getColorByKey('edgeless/palette/light/redLight'),
Orange: getColorByKey('edgeless/palette/light/orangeLight'),
Yellow: getColorByKey('edgeless/palette/light/yellowLight'),
Green: getColorByKey('edgeless/palette/light/greenLight'),
Blue: getColorByKey('edgeless/palette/light/blueLight'),
Purple: getColorByKey('edgeless/palette/light/purpleLight'),
Magenta: getColorByKey('edgeless/palette/light/magentaLight'),
Grey: getColorByKey('edgeless/palette/light/greyLight'),
} as const;
const Medium = {
Red: getColorByKey('edgeless/palette/medium/redMedium'),
Orange: getColorByKey('edgeless/palette/medium/orangeMedium'),
Yellow: getColorByKey('edgeless/palette/medium/yellowMedium'),
Green: getColorByKey('edgeless/palette/medium/greenMedium'),
Blue: getColorByKey('edgeless/palette/medium/blueMedium'),
Purple: getColorByKey('edgeless/palette/medium/purpleMedium'),
Magenta: getColorByKey('edgeless/palette/medium/magentaMedium'),
Grey: getColorByKey('edgeless/palette/medium/greyMedium'),
} as const;
const Heavy = {
Red: getColorByKey('edgeless/palette/heavy/red'),
Orange: getColorByKey('edgeless/palette/heavy/orange'),
Yellow: getColorByKey('edgeless/palette/heavy/yellow'),
Green: getColorByKey('edgeless/palette/heavy/green'),
Blue: getColorByKey('edgeless/palette/heavy/blue'),
Purple: getColorByKey('edgeless/palette/heavy/purple'),
Magenta: getColorByKey('edgeless/palette/heavy/magenta'),
} as const;
const NoteBackgroundColorMap = {
Yellow: getColorByKey('edgeless/note/yellow'),
Orange: getColorByKey('edgeless/note/orange'),
Red: getColorByKey('edgeless/note/red'),
Magenta: getColorByKey('edgeless/note/magenta'),
Purple: getColorByKey('edgeless/note/purple'),
Blue: getColorByKey('edgeless/note/blue'),
Teal: getColorByKey('edgeless/note/teal'),
Green: getColorByKey('edgeless/note/green'),
Black: getColorByKey('edgeless/note/black'),
Grey: getColorByKey('edgeless/note/grey'),
White: getColorByKey('edgeless/note/white'),
} as const;
const Palettes: Palette[] = [
// Light
...buildPalettes(Light, 'Light'),
{ key: 'Transparent', value: Transparent },
// Medium
...buildPalettes(Medium, 'Medium'),
{ key: 'White', value: White },
// Heavy
...buildPalettes(Heavy, 'Heavy'),
{ key: 'Black', value: Black },
] as const;
const NoteBackgroundColorPalettes: Palette[] = [
...buildPalettes(NoteBackgroundColorMap),
] as const;
const StrokeColorMap = { ...Medium, Black, White } as const;
const StrokeColorPalettes: Palette[] = [
...buildPalettes(StrokeColorMap),
] as const;
const FillColorMap = { ...Light, Black, White } as const;
const FillColorPalettes: Palette[] = [...buildPalettes(FillColorMap)] as const;
export const DefaultTheme: Theme = {
pureBlack,
pureWhite,
black: Black,
white: White,
transparent: Transparent,
textColor: Medium.Blue,
shapeTextColor: Black,
shapeStrokeColor: Medium.Yellow,
shapeFillColor: Light.Yellow,
connectorColor: Medium.Grey,
noteBackgrounColor: NoteBackgroundColorMap.White,
Palettes,
StrokeColorMap,
StrokeColorPalettes,
FillColorMap,
FillColorPalettes,
NoteBackgroundColorMap,
NoteBackgroundColorPalettes,
} as const;

View File

@@ -0,0 +1,10 @@
import { DefaultTheme } from './default.js';
import type { Theme } from './types.js';
export * from './color.js';
export { DefaultTheme } from './default.js';
export * from './types.js';
export const Themes: Record<string, Theme> = {
default: DefaultTheme,
};

View File

@@ -0,0 +1,36 @@
import { z } from 'zod';
import { ColorSchema } from './color.js';
export const PaletteSchema = z.object({
key: z.string(),
value: ColorSchema,
});
export type Palette = z.infer<typeof PaletteSchema>;
export const ThemeSchema = z.object({
pureBlack: z.string(),
pureWhite: z.string(),
black: ColorSchema,
white: ColorSchema,
transparent: z.literal('transparent'),
textColor: ColorSchema,
shapeTextColor: ColorSchema,
shapeStrokeColor: ColorSchema,
shapeFillColor: ColorSchema,
connectorColor: ColorSchema,
noteBackgrounColor: ColorSchema,
// Universal color palette
Palettes: z.array(PaletteSchema),
StrokeColorMap: z.record(z.string(), ColorSchema),
// Usually used in global toolbar and editor preview
StrokeColorPalettes: z.array(PaletteSchema),
FillColorMap: z.record(z.string(), ColorSchema),
// Usually used in global toolbar and editor preview
FillColorPalettes: z.array(PaletteSchema),
NoteBackgroundColorMap: z.record(z.string(), ColorSchema),
NoteBackgroundColorPalettes: z.array(PaletteSchema),
});
export type Theme = z.infer<typeof ThemeSchema>;

View File

@@ -0,0 +1,29 @@
import {
type AffineThemeKeyV2,
darkThemeV2,
lightThemeV2,
} from '@toeverything/theme/v2';
import type { Color } from './color.js';
import type { Palette } from './types.js';
// Converts a color map to color list.
export function buildPalettes(
obj: Record<string, Color>,
prefix = ''
): Palette[] {
return Object.entries<Color>(obj).map(([key, value]) => ({
key: `${prefix}${key}`,
value,
}));
}
export function getColorByKey(key: AffineThemeKeyV2): Color {
const dark = darkThemeV2[key];
const light = lightThemeV2[key];
if (dark === light) return dark;
return { dark, light };
}
export const pureBlack = lightThemeV2['edgeless/palette/black'];
export const pureWhite = lightThemeV2['edgeless/palette/white'];