diff --git a/packages/affine/block-surface/src/renderer/canvas-renderer.ts b/packages/affine/block-surface/src/renderer/canvas-renderer.ts index f6d2a4f5aaeb..29b449e9a1d2 100644 --- a/packages/affine/block-surface/src/renderer/canvas-renderer.ts +++ b/packages/affine/block-surface/src/renderer/canvas-renderer.ts @@ -25,7 +25,7 @@ import { RoughCanvas } from '../utils/rough/canvas.js'; type EnvProvider = { generateColorProperty: (color: Color, fallback: string) => string; getColorScheme: () => ColorScheme; - getColorValue: (color: Color, fallback?: string, real?: boolean) => string; + getColorValue: (color: Color, fallback?: Color, real?: boolean) => string; getPropertyValue: (property: string) => string; selectedElements?: () => string[]; }; @@ -411,7 +411,7 @@ export class CanvasRenderer { return this.provider.getColorScheme?.() ?? ColorScheme.Light; } - getColorValue(color: Color, fallback?: string, real?: boolean) { + getColorValue(color: Color, fallback?: Color, real?: boolean) { return ( this.provider.getColorValue?.(color, fallback, real) ?? 'transparent' ); diff --git a/packages/affine/block-surface/src/renderer/elements/brush/index.ts b/packages/affine/block-surface/src/renderer/elements/brush/index.ts index 6dc720828daf..7565b4a78ab2 100644 --- a/packages/affine/block-surface/src/renderer/elements/brush/index.ts +++ b/packages/affine/block-surface/src/renderer/elements/brush/index.ts @@ -1,4 +1,4 @@ -import type { BrushElementModel } from '@blocksuite/affine-model'; +import { type BrushElementModel, DefaultTheme } from '@blocksuite/affine-model'; import type { CanvasRenderer } from '../../canvas-renderer.js'; @@ -17,7 +17,7 @@ export function brush( matrix.translateSelf(cx, cy).rotateSelf(rotate).translateSelf(-cx, -cy) ); - const color = renderer.getColorValue(model.color, '#000000', true); + const color = renderer.getColorValue(model.color, DefaultTheme.black, true); ctx.fillStyle = color; diff --git a/packages/affine/block-surface/src/renderer/elements/connector/index.ts b/packages/affine/block-surface/src/renderer/elements/connector/index.ts index 0da545ea98b5..308d27ed5228 100644 --- a/packages/affine/block-surface/src/renderer/elements/connector/index.ts +++ b/packages/affine/block-surface/src/renderer/elements/connector/index.ts @@ -1,6 +1,7 @@ import { type ConnectorElementModel, ConnectorMode, + DefaultTheme, type LocalConnectorElementModel, type PointStyle, } from '@blocksuite/affine-model'; @@ -76,7 +77,11 @@ export function connector( ctx.clip(path, 'evenodd'); } - const strokeColor = renderer.getColorValue(model.stroke, '#000000', true); + const strokeColor = renderer.getColorValue( + model.stroke, + DefaultTheme.connectorColor, + true + ); renderPoints( model, @@ -250,7 +255,7 @@ function renderLabel( ctx.font = font; ctx.textAlign = textAlign; ctx.textBaseline = 'middle'; - ctx.fillStyle = renderer.getColorValue(color, '#000000', true); + ctx.fillStyle = renderer.getColorValue(color, DefaultTheme.black, true); let textMaxWidth = textAlign === 'center' ? 0 : getMaxTextWidth(lines, font); if (hasMaxWidth && maxWidth > 0) { diff --git a/packages/affine/block-surface/src/renderer/elements/shape/index.ts b/packages/affine/block-surface/src/renderer/elements/shape/index.ts index b7361d9c75e6..c7400264f0fd 100644 --- a/packages/affine/block-surface/src/renderer/elements/shape/index.ts +++ b/packages/affine/block-surface/src/renderer/elements/shape/index.ts @@ -5,12 +5,7 @@ import type { } from '@blocksuite/affine-model'; import type { IBound } from '@blocksuite/global/utils'; -import { - DEFAULT_SHAPE_FILL_COLOR, - DEFAULT_SHAPE_STROKE_COLOR, - DEFAULT_SHAPE_TEXT_COLOR, - TextAlign, -} from '@blocksuite/affine-model'; +import { DefaultTheme, TextAlign } from '@blocksuite/affine-model'; import { Bound } from '@blocksuite/global/utils'; import { deltaInsertsToChunks } from '@blocksuite/inline'; @@ -57,17 +52,17 @@ export function shape( ) { const color = renderer.getColorValue( model.color, - DEFAULT_SHAPE_TEXT_COLOR, + DefaultTheme.shapeTextColor, true ); const fillColor = renderer.getColorValue( model.fillColor, - DEFAULT_SHAPE_FILL_COLOR, + DefaultTheme.shapeFillColor, true ); const strokeColor = renderer.getColorValue( model.strokeColor, - DEFAULT_SHAPE_STROKE_COLOR, + DefaultTheme.shapeStrokeColor, true ); const colors = { color, fillColor, strokeColor }; diff --git a/packages/affine/block-surface/src/renderer/elements/text/index.ts b/packages/affine/block-surface/src/renderer/elements/text/index.ts index 9be3ec8f5178..94efc471c166 100644 --- a/packages/affine/block-surface/src/renderer/elements/text/index.ts +++ b/packages/affine/block-surface/src/renderer/elements/text/index.ts @@ -1,5 +1,4 @@ -import type { TextElementModel } from '@blocksuite/affine-model'; - +import { DefaultTheme, type TextElementModel } from '@blocksuite/affine-model'; import { deltaInsertsToChunks } from '@blocksuite/inline'; import type { CanvasRenderer } from '../../canvas-renderer.js'; @@ -41,7 +40,11 @@ export function text( const horizontalOffset = textAlign === 'center' ? w / 2 : textAlign === 'right' ? w : 0; - const color = renderer.getColorValue(model.color, '#000000', true); + const color = renderer.getColorValue( + model.color, + DefaultTheme.textColor, + true + ); ctx.font = font; ctx.fillStyle = color; diff --git a/packages/affine/model/src/blocks/note/note-model.ts b/packages/affine/model/src/blocks/note/note-model.ts index 4a5767150dfb..eec28ee5d2f8 100644 --- a/packages/affine/model/src/blocks/note/note-model.ts +++ b/packages/affine/model/src/blocks/note/note-model.ts @@ -9,13 +9,13 @@ import { BlockModel, defineBlockSchema } from '@blocksuite/store'; import { type Color, - DEFAULT_NOTE_BACKGROUND_COLOR, DEFAULT_NOTE_BORDER_SIZE, DEFAULT_NOTE_BORDER_STYLE, DEFAULT_NOTE_CORNER, DEFAULT_NOTE_HEIGHT, DEFAULT_NOTE_SHADOW, DEFAULT_NOTE_WIDTH, + DefaultTheme, NoteDisplayMode, type StrokeStyle, } from '../../consts/index.js'; @@ -24,7 +24,7 @@ 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, diff --git a/packages/affine/model/src/consts/brush.ts b/packages/affine/model/src/consts/brush.ts deleted file mode 100644 index 209d66e30e92..000000000000 --- a/packages/affine/model/src/consts/brush.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { StrokeColor } from './color.js'; - -export const DEFAULT_BRUSH_COLOR = StrokeColor.Blue; diff --git a/packages/affine/model/src/consts/color.ts b/packages/affine/model/src/consts/color.ts index 6d60d5235b1b..e4c770f969d2 100644 --- a/packages/affine/model/src/consts/color.ts +++ b/packages/affine/model/src/consts/color.ts @@ -1,98 +1,54 @@ -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 type PaletteEnum = z.infer; - -export const StrokeColor = { Black, White, ...Medium } as const; - -export const StrokeColorMap = createEnumMap(StrokeColor); - -export const STROKE_COLORS = [...MEDIUM_PALETTES, Black, White] as const; +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; + +// 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') + ); +} diff --git a/packages/affine/model/src/consts/connector.ts b/packages/affine/model/src/consts/connector.ts index 97b35b7808ce..fd90c36ba9c2 100644 --- a/packages/affine/model/src/consts/connector.ts +++ b/packages/affine/model/src/consts/connector.ts @@ -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; diff --git a/packages/affine/model/src/consts/frame.ts b/packages/affine/model/src/consts/frame.ts deleted file mode 100644 index fd5d90841847..000000000000 --- a/packages/affine/model/src/consts/frame.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { Light } from './color.js'; - -export const FrameBackgroundColor = Light; diff --git a/packages/affine/model/src/consts/index.ts b/packages/affine/model/src/consts/index.ts index 62c70b8c25fc..31cdc8c3b3ff 100644 --- a/packages/affine/model/src/consts/index.ts +++ b/packages/affine/model/src/consts/index.ts @@ -1,10 +1,9 @@ -export * from './brush.js'; export * from './color.js'; export * from './connector.js'; export * from './doc.js'; -export * from './frame.js'; export * from './line.js'; export * from './mindmap.js'; export * from './note.js'; export * from './shape.js'; export * from './text.js'; +export * from './themes/index.js'; diff --git a/packages/affine/model/src/consts/note.ts b/packages/affine/model/src/consts/note.ts index e8d0c4dec5ff..7321290eb5d6 100644 --- a/packages/affine/model/src/consts/note.ts +++ b/packages/affine/model/src/consts/note.ts @@ -1,4 +1,3 @@ -import { themeToVar } from '@toeverything/theme/v2'; import { z } from 'zod'; import { createEnumMap } from '../utils/enum.js'; @@ -72,40 +71,3 @@ export const DEFAULT_NOTE_CORNER = NoteCorners.Small; export const NoteCornersSchema = z.nativeEnum(NoteCorners); export const DEFAULT_NOTE_BORDER_SIZE = 4; - -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 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 type NoteBackgroundPaletteEnum = z.infer< - typeof NoteBackgroundPaletteEnum ->; - -export const NoteBackgroundColorMap = createEnumMap(NoteBackgroundColor); - -export const DEFAULT_NOTE_BACKGROUND_COLOR = NoteBackgroundColor.White; diff --git a/packages/affine/model/src/consts/shape.ts b/packages/affine/model/src/consts/shape.ts index 427bdad8263d..e81821cdb1db 100644 --- a/packages/affine/model/src/consts/shape.ts +++ b/packages/affine/model/src/consts/shape.ts @@ -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; diff --git a/packages/affine/model/src/consts/text.ts b/packages/affine/model/src/consts/text.ts index 3f9887621ef2..bbef16b7a41d 100644 --- a/packages/affine/model/src/consts/text.ts +++ b/packages/affine/model/src/consts/text.ts @@ -1,12 +1,6 @@ -import { createEnumMap } from '../utils/enum.js'; -import { StrokeColor } from './color.js'; - -export enum ColorScheme { - Dark = 'dark', - Light = 'light', -} +import type { Color } from './color.js'; -export type Color = string | Partial>; +import { createEnumMap } from '../utils/enum.js'; export enum TextAlign { Center = 'center', @@ -66,5 +60,3 @@ export enum TextResizing { AUTO_WIDTH_AND_HEIGHT, AUTO_HEIGHT, } - -export const DEFAULT_TEXT_COLOR = StrokeColor.Blue; diff --git a/packages/affine/model/src/consts/themes/default.ts b/packages/affine/model/src/consts/themes/default.ts new file mode 100644 index 000000000000..e0e8b7e90ccf --- /dev/null +++ b/packages/affine/model/src/consts/themes/default.ts @@ -0,0 +1,104 @@ +import type { Palette, Theme } from './types.js'; + +import { buildPalettes, getColorByKey } 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 NoteBackgroundColor = { + 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 notePalettes: Palette[] = [ + ...buildPalettes(NoteBackgroundColor), +] as const; + +const StrokeColor = { ...Medium, Black, White } as const; + +const globalToolbarPalettes: Palette[] = [ + ...buildPalettes(StrokeColor), +] as const; + +const FillColor = { ...Light, Black, White } as const; + +const globalToolbarShapeFillPalettes: Palette[] = [ + ...buildPalettes(FillColor), +] as const; + +export const DefaultTheme: Theme = { + black: Black, + white: White, + transparent: Transparent, + palettes, + textColor: Medium.Blue, + shapeTextColor: Black, + shapeStrokeColor: Medium.Yellow, + shapeFillColor: Light.Yellow, + connectorColor: Medium.Grey, + notePalettes, + noteBackgrounColor: NoteBackgroundColor.White, + globalToolbarPalettes, + globalToolbarShapeFillPalettes, + StrokeColor, + FillColor, +} as const; diff --git a/packages/affine/model/src/consts/themes/index.ts b/packages/affine/model/src/consts/themes/index.ts new file mode 100644 index 000000000000..c008991f02ff --- /dev/null +++ b/packages/affine/model/src/consts/themes/index.ts @@ -0,0 +1,10 @@ +import type { Theme } from './types.js'; + +import { DefaultTheme } from './default.js'; + +export { DefaultTheme } from './default.js'; +export * from './types.js'; + +export const Themes: Record = { + default: DefaultTheme, +}; diff --git a/packages/affine/model/src/consts/themes/types.ts b/packages/affine/model/src/consts/themes/types.ts new file mode 100644 index 000000000000..aa9b2c7a8ec2 --- /dev/null +++ b/packages/affine/model/src/consts/themes/types.ts @@ -0,0 +1,30 @@ +import { z } from 'zod'; + +import { ColorSchema } from '../color.js'; + +export const PaletteSchema = z.object({ + key: z.string(), + value: ColorSchema, +}); + +export type Palette = z.infer; + +export const ThemeSchema = z.object({ + black: ColorSchema, + white: ColorSchema, + transparent: z.literal('transparent'), + textColor: ColorSchema, + shapeTextColor: ColorSchema, + shapeStrokeColor: ColorSchema, + shapeFillColor: ColorSchema, + connectorColor: ColorSchema, + palettes: z.array(PaletteSchema), + noteBackgrounColor: ColorSchema, + notePalettes: z.array(PaletteSchema), + globalToolbarPalettes: z.array(PaletteSchema), + globalToolbarShapeFillPalettes: z.array(PaletteSchema), + StrokeColor: z.record(z.string(), ColorSchema), + FillColor: z.record(z.string(), ColorSchema), +}); + +export type Theme = z.infer; diff --git a/packages/affine/model/src/consts/themes/utils.ts b/packages/affine/model/src/consts/themes/utils.ts new file mode 100644 index 000000000000..c8a9a1035234 --- /dev/null +++ b/packages/affine/model/src/consts/themes/utils.ts @@ -0,0 +1,26 @@ +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, + prefix = '' +): Palette[] { + return Object.entries(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 }; +} diff --git a/packages/affine/model/src/elements/mindmap/style.ts b/packages/affine/model/src/elements/mindmap/style.ts index e7ad9b61dfc1..1139aee2325a 100644 --- a/packages/affine/model/src/elements/mindmap/style.ts +++ b/packages/affine/model/src/elements/mindmap/style.ts @@ -1,13 +1,14 @@ import { isEqual, last } from '@blocksuite/global/utils'; +import type { Color } from '../../consts/color.js'; import type { MindmapNode } from './mindmap.js'; 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 { DefaultTheme } from '../../consts/themes/default.js'; export type CollapseButton = { width: number; @@ -15,9 +16,9 @@ export type CollapseButton = { radius: number; filled: boolean; - fillColor: string; + fillColor: Color; - strokeColor: string; + strokeColor: Color; strokeWidth: number; }; @@ -26,24 +27,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]; @@ -57,7 +58,7 @@ export type NodeStyle = { export type ConnectorStyle = { strokeStyle: StrokeStyle; - stroke: string; + stroke: Color; strokeWidth: number; mode: ConnectorMode; @@ -190,9 +191,9 @@ export const styleOne = new StyleOne(); export class StyleTwo extends MindmapStyleGetter { private _colorOrders = [ - ShapeFillColor.Blue, + DefaultTheme.FillColor.Blue, '#7ae2d5', - ShapeFillColor.Yellow, + DefaultTheme.FillColor.Yellow, ]; readonly root = { @@ -206,10 +207,10 @@ export class StyleTwo extends MindmapStyleGetter { fontFamily: FontFamily.Poppins, fontSize: 18, fontWeight: FontWeight.SemiBold, - color: ShapeFillColor.Black, + color: DefaultTheme.FillColor.Black, filled: true, - fillColor: ShapeFillColor.Orange, + fillColor: DefaultTheme.FillColor.Orange, padding: [11, 22] as [number, number], @@ -279,7 +280,7 @@ export class StyleTwo extends MindmapStyleGetter { fontFamily: FontFamily.Poppins, fontSize: 16, fontWeight: FontWeight.SemiBold, - color: ShapeFillColor.Black, + color: DefaultTheme.FillColor.Black, filled: true, fillColor: color, @@ -312,10 +313,10 @@ export class StyleThree extends MindmapStyleGetter { fontFamily: FontFamily.Poppins, fontSize: 16, fontWeight: FontWeight.Medium, - color: ShapeFillColor.Black, + color: DefaultTheme.FillColor.Black, filled: true, - fillColor: ShapeFillColor.Yellow, + fillColor: DefaultTheme.FillColor.Yellow, padding: [10, 22] as [number, number], @@ -346,10 +347,10 @@ export class StyleThree extends MindmapStyleGetter { fontFamily: FontFamily.Poppins, fontSize: 16, fontWeight: FontWeight.Medium, - color: ShapeFillColor.Black, + color: DefaultTheme.FillColor.Black, filled: true, - fillColor: ShapeFillColor.White, + fillColor: DefaultTheme.FillColor.White, padding: [6, 22] as [number, number], @@ -404,12 +405,12 @@ export const styleThree = new StyleThree(); export class StyleFour extends MindmapStyleGetter { private _colors = [ - ShapeFillColor.Purple, - ShapeFillColor.Magenta, - ShapeFillColor.Orange, - ShapeFillColor.Yellow, - ShapeFillColor.Green, - ShapeFillColor.Blue, + DefaultTheme.FillColor.Purple, + DefaultTheme.FillColor.Magenta, + DefaultTheme.FillColor.Orange, + DefaultTheme.FillColor.Yellow, + DefaultTheme.FillColor.Green, + DefaultTheme.FillColor.Blue, ]; readonly root = { diff --git a/packages/affine/model/src/elements/shape/shape.ts b/packages/affine/model/src/elements/shape/shape.ts index 07ffb445812d..871a4b62e7f4 100644 --- a/packages/affine/model/src/elements/shape/shape.ts +++ b/packages/affine/model/src/elements/shape/shape.ts @@ -25,8 +25,6 @@ import { FontFamily, FontStyle, FontWeight, - LineColor, - ShapeFillColor, ShapeStyle, ShapeTextFontSize, ShapeType, @@ -36,6 +34,7 @@ import { type TextStyleProps, TextVerticalAlign, } from '../../consts/index.js'; +import { DefaultTheme } from '../../consts/themes/default.js'; import { shapeMethods } from './api/index.js'; export type ShapeProps = BaseElementProps & { @@ -105,7 +104,7 @@ export class ShapeElementModel extends GfxPrimitiveElementModel { accessor color!: Color; @field() - accessor fillColor: Color = ShapeFillColor.Yellow; + accessor fillColor: Color = DefaultTheme.shapeFillColor; @field() accessor filled: boolean = false; @@ -161,7 +160,7 @@ export class ShapeElementModel extends GfxPrimitiveElementModel { accessor shapeType: ShapeType = ShapeType.Rect; @field() - accessor strokeColor: Color = LineColor.Yellow; + accessor strokeColor: Color = DefaultTheme.shapeStrokeColor; @field() accessor strokeStyle: StrokeStyle = StrokeStyle.Solid; @@ -206,7 +205,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; @@ -247,7 +246,7 @@ export class LocalShapeElementModel extends GfxLocalElementModel { accessor shapeType: ShapeType = ShapeType.Rect; @prop() - accessor strokeColor: Color = LineColor.Yellow; + accessor strokeColor: Color = DefaultTheme.shapeStrokeColor; @prop() accessor strokeStyle: StrokeStyle = StrokeStyle.Solid; diff --git a/packages/affine/shared/src/services/edit-props-store.ts b/packages/affine/shared/src/services/edit-props-store.ts index d5353723408f..e271a62daa91 100644 --- a/packages/affine/shared/src/services/edit-props-store.ts +++ b/packages/affine/shared/src/services/edit-props-store.ts @@ -1,3 +1,4 @@ +import { ColorSchema } from '@blocksuite/affine-model'; import { type BlockStdScope, LifeCycleWatcher } from '@blocksuite/block-std'; import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions'; import { @@ -11,11 +12,7 @@ import clonedeep from 'lodash.clonedeep'; import mergeWith from 'lodash.mergewith'; import { z } from 'zod'; -import { - ColorSchema, - makeDeepOptional, - NodePropsSchema, -} from '../utils/index.js'; +import { makeDeepOptional, NodePropsSchema } from '../utils/index.js'; import { EditorSettingProvider } from './editor-setting-service.js'; const LastPropsSchema = NodePropsSchema; diff --git a/packages/affine/shared/src/services/theme-service.ts b/packages/affine/shared/src/services/theme-service.ts index cf1789766df6..5b04547818d9 100644 --- a/packages/affine/shared/src/services/theme-service.ts +++ b/packages/affine/shared/src/services/theme-service.ts @@ -1,4 +1,9 @@ -import { type Color, ColorScheme } from '@blocksuite/affine-model'; +import { + type Color, + ColorScheme, + DefaultTheme, + resolveColor, +} from '@blocksuite/affine-model'; import { type BlockStdScope, Extension, @@ -15,8 +20,6 @@ import { import { isInsideEdgelessEditor } from '../utils/index.js'; -const TRANSPARENT = 'transparent'; - export const ThemeExtensionIdentifier = createIdentifier( 'AffineThemeExtension' ); @@ -52,9 +55,7 @@ export class ThemeService extends Extension { } get theme() { - return isInsideEdgelessEditor(this.std.host) - ? this.edgelessTheme - : this.appTheme; + return this.theme$.peek(); } get theme$() { @@ -94,24 +95,19 @@ export class ThemeService extends Extension { */ generateColorProperty( color: Color, - fallback = 'transparent', + fallback: Color = DefaultTheme.transparent, theme = this.theme ) { - let result: string | undefined = undefined; + const result = resolveColor(color, theme, resolveColor(fallback, theme)); - if (typeof color === 'object') { - result = color[theme] ?? color.normal; - } else { - result = color; - } - if (!result) { - result = fallback; - } + // Compatible old data if (result.startsWith('--')) { - return result.endsWith(TRANSPARENT) ? TRANSPARENT : `var(${result})`; + return result.endsWith('transparent') + ? DefaultTheme.transparent + : `var(${result})`; } - return result ?? TRANSPARENT; + return result; } /** @@ -132,35 +128,30 @@ export class ThemeService extends Extension { */ getColorValue( color: Color, - fallback = TRANSPARENT, + fallback: Color = DefaultTheme.transparent, real = false, theme = this.theme ) { - let result: string | undefined = undefined; + let result = resolveColor(color, theme, resolveColor(fallback, theme)); - if (typeof color === 'object') { - result = color[theme] ?? color.normal; - } else { - result = color; - } - if (!result) { - result = fallback; - } + // Compatible old data if (real && result.startsWith('--')) { - result = result.endsWith(TRANSPARENT) - ? TRANSPARENT + result = result.endsWith('transparent') + ? DefaultTheme.transparent : this.getCssVariableColor(result, theme); } - return result ?? TRANSPARENT; + return result ?? DefaultTheme.transparent; } getCssVariableColor(property: string, theme = this.theme) { + // Compatible old data if (property.startsWith('--')) { - if (property.endsWith(TRANSPARENT)) { - return TRANSPARENT; + if (property.endsWith('transparent')) { + return DefaultTheme.transparent; } const key = property as keyof AffineCssVariables; + // V1 theme const color = theme === ColorScheme.Dark ? combinedDarkCssVariables[key] diff --git a/packages/affine/shared/src/utils/zod-schema.ts b/packages/affine/shared/src/utils/zod-schema.ts index ef8ce0d68bdf..1e929c64ba07 100644 --- a/packages/affine/shared/src/utils/zod-schema.ts +++ b/packages/affine/shared/src/utils/zod-schema.ts @@ -1,33 +1,24 @@ import { + ColorSchema, ConnectorMode, - DEFAULT_CONNECTOR_COLOR, - DEFAULT_CONNECTOR_TEXT_COLOR, DEFAULT_FRONT_END_POINT_STYLE, - DEFAULT_NOTE_BACKGROUND_COLOR, DEFAULT_NOTE_BORDER_SIZE, DEFAULT_NOTE_BORDER_STYLE, DEFAULT_NOTE_CORNER, DEFAULT_NOTE_SHADOW, DEFAULT_REAR_END_POINT_STYLE, DEFAULT_ROUGHNESS, - DEFAULT_SHAPE_FILL_COLOR, - DEFAULT_SHAPE_STROKE_COLOR, - DEFAULT_SHAPE_TEXT_COLOR, - DEFAULT_TEXT_COLOR, + DefaultTheme, FontFamily, FontStyle, FontWeight, LayoutType, - LineColorsSchema, LineWidth, MindmapStyle, - NoteBackgroundPaletteEnum, NoteDisplayMode, NoteShadowsSchema, - PaletteEnum, PointStyle, ShapeStyle, - StrokeColor, StrokeStyle, TextAlign, TextVerticalAlign, @@ -48,34 +39,17 @@ const ConnectorModeSchema = z.nativeEnum(ConnectorMode); const LayoutTypeSchema = z.nativeEnum(LayoutType); const MindmapStyleSchema = z.nativeEnum(MindmapStyle); -export const ColorSchema = z.union([ - z.object({ - normal: z.string(), - }), - z.object({ - light: z.string(), - dark: z.string(), - }), -]); -const ColorPaletteSchema = z.union([ColorSchema, PaletteEnum]); -const LineColorSchema = z.union([LineColorsSchema, ColorPaletteSchema]); -const TextColorSchema = z.union([LineColorsSchema, ColorPaletteSchema]); -const NoteBackgroundColorSchema = z.union([ - ColorSchema, - NoteBackgroundPaletteEnum, -]); - export const ConnectorSchema = z .object({ frontEndpointStyle: ConnectorEndpointSchema, rearEndpointStyle: ConnectorEndpointSchema, - stroke: LineColorSchema, + stroke: ColorSchema, strokeStyle: StrokeStyleSchema, strokeWidth: LineWidthSchema, rough: z.boolean(), mode: ConnectorModeSchema, labelStyle: z.object({ - color: TextColorSchema, + color: ColorSchema, fontSize: z.number(), fontFamily: FontFamilySchema, fontWeight: FontWeightSchema, @@ -86,13 +60,13 @@ export const ConnectorSchema = z .default({ frontEndpointStyle: DEFAULT_FRONT_END_POINT_STYLE, rearEndpointStyle: DEFAULT_REAR_END_POINT_STYLE, - stroke: DEFAULT_CONNECTOR_COLOR, + stroke: DefaultTheme.connectorColor, strokeStyle: StrokeStyle.Solid, strokeWidth: LineWidth.Two, rough: false, mode: ConnectorMode.Curve, labelStyle: { - color: DEFAULT_CONNECTOR_TEXT_COLOR, + color: DefaultTheme.black, fontSize: 16, fontFamily: FontFamily.Inter, fontWeight: FontWeight.Regular, @@ -103,18 +77,18 @@ export const ConnectorSchema = z export const BrushSchema = z .object({ - color: ColorPaletteSchema, + color: ColorSchema, lineWidth: LineWidthSchema, }) .default({ - color: StrokeColor.Black, + color: DefaultTheme.black, lineWidth: LineWidth.Four, }); const DEFAULT_SHAPE = { - color: DEFAULT_SHAPE_TEXT_COLOR, - fillColor: DEFAULT_SHAPE_FILL_COLOR, - strokeColor: DEFAULT_SHAPE_STROKE_COLOR, + color: DefaultTheme.shapeTextColor, + fillColor: DefaultTheme.shapeFillColor, + strokeColor: DefaultTheme.shapeStrokeColor, strokeStyle: StrokeStyle.Solid, strokeWidth: LineWidth.Two, shapeStyle: ShapeStyle.General, @@ -129,9 +103,9 @@ const DEFAULT_SHAPE = { }; const ShapeObject = { - color: TextColorSchema, - fillColor: ColorPaletteSchema, - strokeColor: ColorPaletteSchema, + color: ColorSchema, + fillColor: ColorSchema, + strokeColor: ColorSchema, strokeStyle: StrokeStyleSchema, strokeWidth: z.number(), shapeStyle: ShapeStyleSchema, @@ -155,7 +129,7 @@ export const RoundedShapeSchema = z export const TextSchema = z .object({ - color: TextColorSchema, + color: ColorSchema, fontSize: z.number(), fontFamily: FontFamilySchema, fontWeight: FontWeightSchema, @@ -163,7 +137,7 @@ export const TextSchema = z textAlign: TextAlignSchema, }) .default({ - color: DEFAULT_TEXT_COLOR, + color: DefaultTheme.textColor, fontSize: 24, fontFamily: FontFamily.Inter, fontWeight: FontWeight.Regular, @@ -173,14 +147,14 @@ export const TextSchema = z export const EdgelessTextSchema = z .object({ - color: TextColorSchema, + color: ColorSchema, fontFamily: FontFamilySchema, fontWeight: FontWeightSchema, fontStyle: FontStyleSchema, textAlign: TextAlignSchema, }) .default({ - color: DEFAULT_TEXT_COLOR, + color: DefaultTheme.textColor, fontFamily: FontFamily.Inter, fontWeight: FontWeight.Regular, fontStyle: FontStyle.Normal, @@ -189,7 +163,7 @@ export const EdgelessTextSchema = z export const NoteSchema = z .object({ - background: NoteBackgroundColorSchema, + background: ColorSchema, displayMode: NoteDisplayModeSchema, edgeless: z.object({ style: z.object({ @@ -201,7 +175,7 @@ export const NoteSchema = z }), }) .default({ - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, displayMode: NoteDisplayMode.EdgelessOnly, edgeless: { style: { @@ -225,7 +199,7 @@ export const MindmapSchema = z export const FrameSchema = z .object({ - background: ColorPaletteSchema.optional(), + background: ColorSchema.optional(), }) .default({}); diff --git a/packages/blocks/package.json b/packages/blocks/package.json index 8a17aaf75104..30db5f4f3c9d 100644 --- a/packages/blocks/package.json +++ b/packages/blocks/package.json @@ -49,6 +49,7 @@ "html2canvas": "^1.4.1", "katex": "^0.16.11", "lit": "^3.2.0", + "lodash.isequal": "^4.5.0", "lz-string": "^1.5.0", "mdast-util-gfm-autolink-literal": "^2.0.1", "mdast-util-gfm-strikethrough": "^2.0.0", @@ -106,6 +107,7 @@ ], "devDependencies": { "@types/dompurify": "^3.0.5", - "@types/katex": "^0.16.7" + "@types/katex": "^0.16.7", + "@types/lodash.isequal": "^4.5.8" } } diff --git a/packages/blocks/src/__tests__/adapters/html.unit.spec.ts b/packages/blocks/src/__tests__/adapters/html.unit.spec.ts index 8ba21683c9c5..973529790c7b 100644 --- a/packages/blocks/src/__tests__/adapters/html.unit.spec.ts +++ b/packages/blocks/src/__tests__/adapters/html.unit.spec.ts @@ -4,10 +4,7 @@ import type { JobMiddleware, } from '@blocksuite/store'; -import { - DEFAULT_NOTE_BACKGROUND_COLOR, - NoteDisplayMode, -} from '@blocksuite/affine-model'; +import { DefaultTheme, NoteDisplayMode } from '@blocksuite/affine-model'; import { AssetsManager, MemoryBlobCRUD } from '@blocksuite/store'; import { describe, expect, test } from 'vitest'; @@ -95,7 +92,7 @@ describe('snapshot to html', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -161,7 +158,7 @@ describe('snapshot to html', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -227,7 +224,7 @@ describe('snapshot to html', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -293,7 +290,7 @@ describe('snapshot to html', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -479,7 +476,7 @@ describe('snapshot to html', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -624,7 +621,7 @@ describe('snapshot to html', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -729,7 +726,7 @@ describe('snapshot to html', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -803,7 +800,7 @@ describe('snapshot to html', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -877,7 +874,7 @@ describe('snapshot to html', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -952,7 +949,7 @@ describe('snapshot to html', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -1027,7 +1024,7 @@ describe('snapshot to html', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -1147,7 +1144,7 @@ describe('snapshot to html', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -1208,7 +1205,7 @@ describe('snapshot to html', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -1472,7 +1469,7 @@ describe('snapshot to html', () => { version: 1, props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -1563,7 +1560,7 @@ describe('snapshot to html', () => { version: 1, props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: 'both', @@ -1956,7 +1953,7 @@ describe('html to snapshot', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -1998,7 +1995,7 @@ describe('html to snapshot', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -2108,7 +2105,7 @@ describe('html to snapshot', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -2174,7 +2171,7 @@ describe('html to snapshot', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -2221,7 +2218,7 @@ describe('html to snapshot', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -2257,7 +2254,7 @@ describe('html to snapshot', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -2369,7 +2366,7 @@ describe('html to snapshot', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -2413,7 +2410,7 @@ describe('html to snapshot', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -2457,7 +2454,7 @@ describe('html to snapshot', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -2510,7 +2507,7 @@ describe('html to snapshot', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -2560,7 +2557,7 @@ describe('html to snapshot', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, diff --git a/packages/blocks/src/__tests__/adapters/markdown.unit.spec.ts b/packages/blocks/src/__tests__/adapters/markdown.unit.spec.ts index 2f45fcd008b4..e2a7ff49f718 100644 --- a/packages/blocks/src/__tests__/adapters/markdown.unit.spec.ts +++ b/packages/blocks/src/__tests__/adapters/markdown.unit.spec.ts @@ -5,10 +5,7 @@ import type { SliceSnapshot, } from '@blocksuite/store'; -import { - DEFAULT_NOTE_BACKGROUND_COLOR, - NoteDisplayMode, -} from '@blocksuite/affine-model'; +import { DefaultTheme, NoteDisplayMode } from '@blocksuite/affine-model'; import { AssetsManager, MemoryBlobCRUD } from '@blocksuite/store'; import { describe, expect, test } from 'vitest'; @@ -45,7 +42,7 @@ describe('snapshot to markdown', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -109,7 +106,7 @@ describe('snapshot to markdown', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -308,7 +305,7 @@ hhh flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -456,7 +453,7 @@ hhh flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -608,7 +605,7 @@ hhh version: 1, props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: 'both', @@ -751,7 +748,7 @@ hhh version: 1, props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: 'both', @@ -912,7 +909,7 @@ hhh flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -984,7 +981,7 @@ hhh flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -1056,7 +1053,7 @@ hhh flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -1112,7 +1109,7 @@ hhh flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -1184,7 +1181,7 @@ hhh flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -1253,7 +1250,7 @@ hhh flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -1326,7 +1323,7 @@ hhh flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -1399,7 +1396,7 @@ hhh flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -1708,7 +1705,7 @@ hhh flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -1976,7 +1973,7 @@ hhh version: 1, props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: 'both', @@ -2349,7 +2346,7 @@ describe('markdown to snapshot', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -2394,7 +2391,7 @@ describe('markdown to snapshot', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: 'both', @@ -2445,7 +2442,7 @@ describe('markdown to snapshot', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: 'both', @@ -2496,7 +2493,7 @@ describe('markdown to snapshot', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: 'both', @@ -2559,7 +2556,7 @@ hhh flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -2729,7 +2726,7 @@ hhh flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -2865,7 +2862,7 @@ hhh flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -2999,7 +2996,7 @@ bbb flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -3100,7 +3097,7 @@ bbb flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -3154,7 +3151,7 @@ bbb flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: 'both', @@ -3207,7 +3204,7 @@ bbb flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -3257,7 +3254,7 @@ bbb flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -3308,7 +3305,7 @@ bbb flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -3359,7 +3356,7 @@ bbb flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -3413,7 +3410,7 @@ bbb flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -3531,7 +3528,7 @@ bbb flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -3572,7 +3569,7 @@ bbb flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -3623,7 +3620,7 @@ bbb flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -3674,7 +3671,7 @@ hhh flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: 'both', diff --git a/packages/blocks/src/__tests__/adapters/notion-html.unit.spec.ts b/packages/blocks/src/__tests__/adapters/notion-html.unit.spec.ts index e2a04090250d..c98ce10617f3 100644 --- a/packages/blocks/src/__tests__/adapters/notion-html.unit.spec.ts +++ b/packages/blocks/src/__tests__/adapters/notion-html.unit.spec.ts @@ -1,7 +1,4 @@ -import { - DEFAULT_NOTE_BACKGROUND_COLOR, - NoteDisplayMode, -} from '@blocksuite/affine-model'; +import { DefaultTheme, NoteDisplayMode } from '@blocksuite/affine-model'; import { AssetsManager, type BlockSnapshot, @@ -29,7 +26,7 @@ describe('notion html to snapshot', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -84,7 +81,7 @@ describe('notion html to snapshot', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -199,7 +196,7 @@ describe('notion html to snapshot', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -365,7 +362,7 @@ describe('notion html to snapshot', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -810,7 +807,7 @@ describe('notion html to snapshot', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -939,7 +936,7 @@ describe('notion html to snapshot', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -1040,7 +1037,7 @@ describe('notion html to snapshot', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -1089,7 +1086,7 @@ describe('notion html to snapshot', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -1158,7 +1155,7 @@ describe('notion html to snapshot', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -1207,7 +1204,7 @@ describe('notion html to snapshot', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -1254,7 +1251,7 @@ describe('notion html to snapshot', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -1298,7 +1295,7 @@ describe('notion html to snapshot', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -1422,7 +1419,7 @@ describe('notion html to snapshot', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -1701,7 +1698,7 @@ describe('notion html to snapshot', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: 'both', @@ -1894,7 +1891,7 @@ describe('notion html to snapshot', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -1935,7 +1932,7 @@ describe('notion html to snapshot', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -1977,7 +1974,7 @@ describe('notion html to snapshot', () => { test('inline style', async () => { const html = `

- strong italic underline strikethrough code + strong italic underline strikethrough code

`; @@ -1987,7 +1984,7 @@ describe('notion html to snapshot', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, diff --git a/packages/blocks/src/__tests__/adapters/notion-text.unit.spec.ts b/packages/blocks/src/__tests__/adapters/notion-text.unit.spec.ts index 5cf68a54baea..466d5bc5a3ea 100644 --- a/packages/blocks/src/__tests__/adapters/notion-text.unit.spec.ts +++ b/packages/blocks/src/__tests__/adapters/notion-text.unit.spec.ts @@ -1,6 +1,6 @@ import type { SliceSnapshot } from '@blocksuite/store'; -import { DEFAULT_NOTE_BACKGROUND_COLOR } from '@blocksuite/affine-model'; +import { DefaultTheme } from '@blocksuite/affine-model'; import { describe, expect, test } from 'vitest'; import { NotionTextAdapter } from '../../_common/adapters/notion-text.js'; @@ -21,7 +21,7 @@ describe('notion-text to snapshot', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: 'both', diff --git a/packages/blocks/src/__tests__/adapters/plain-text.unit.spec.ts b/packages/blocks/src/__tests__/adapters/plain-text.unit.spec.ts index 286ac0342222..68c32843dddf 100644 --- a/packages/blocks/src/__tests__/adapters/plain-text.unit.spec.ts +++ b/packages/blocks/src/__tests__/adapters/plain-text.unit.spec.ts @@ -4,10 +4,7 @@ import type { JobMiddleware, } from '@blocksuite/store'; -import { - DEFAULT_NOTE_BACKGROUND_COLOR, - NoteDisplayMode, -} from '@blocksuite/affine-model'; +import { DefaultTheme, NoteDisplayMode } from '@blocksuite/affine-model'; import { describe, expect, test } from 'vitest'; import { PlainTextAdapter } from '../../_common/adapters/plain-text/plain-text.js'; @@ -42,7 +39,7 @@ describe('snapshot to plain text', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -195,7 +192,7 @@ describe('snapshot to plain text', () => { version: 1, props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -351,7 +348,7 @@ describe('snapshot to plain text', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -421,7 +418,7 @@ describe('snapshot to plain text', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -484,7 +481,7 @@ describe('snapshot to plain text', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -650,7 +647,7 @@ describe('snapshot to plain text', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -713,7 +710,7 @@ describe('snapshot to plain text', () => { version: 1, props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -803,7 +800,7 @@ describe('snapshot to plain text', () => { version: 1, props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: 'both', @@ -1162,7 +1159,7 @@ describe('snapshot to plain text', () => { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, diff --git a/packages/blocks/src/_common/adapters/html-adapter/html.ts b/packages/blocks/src/_common/adapters/html-adapter/html.ts index 7c56577d1968..8564aa3a5398 100644 --- a/packages/blocks/src/_common/adapters/html-adapter/html.ts +++ b/packages/blocks/src/_common/adapters/html-adapter/html.ts @@ -1,10 +1,7 @@ import type { ExtensionType } from '@blocksuite/block-std'; import type { Root } from 'hast'; -import { - DEFAULT_NOTE_BACKGROUND_COLOR, - NoteDisplayMode, -} from '@blocksuite/affine-model'; +import { DefaultTheme, NoteDisplayMode } from '@blocksuite/affine-model'; import { type AdapterContext, type BlockHtmlAdapterMatcher, @@ -260,7 +257,7 @@ export class HtmlAdapter extends BaseAdapter { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -285,7 +282,7 @@ export class HtmlAdapter extends BaseAdapter { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -345,7 +342,7 @@ export class HtmlAdapter extends BaseAdapter { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, diff --git a/packages/blocks/src/_common/adapters/markdown/markdown.ts b/packages/blocks/src/_common/adapters/markdown/markdown.ts index d378b58f3db5..03ee093721a1 100644 --- a/packages/blocks/src/_common/adapters/markdown/markdown.ts +++ b/packages/blocks/src/_common/adapters/markdown/markdown.ts @@ -1,10 +1,7 @@ import type { ExtensionType } from '@blocksuite/block-std'; import type { Root } from 'mdast'; -import { - DEFAULT_NOTE_BACKGROUND_COLOR, - NoteDisplayMode, -} from '@blocksuite/affine-model'; +import { DefaultTheme, NoteDisplayMode } from '@blocksuite/affine-model'; import { type AdapterContext, type BlockMarkdownAdapterMatcher, @@ -271,7 +268,7 @@ export class MarkdownAdapter extends BaseAdapter { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -295,7 +292,7 @@ export class MarkdownAdapter extends BaseAdapter { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -414,7 +411,7 @@ export class MarkdownAdapter extends BaseAdapter { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, diff --git a/packages/blocks/src/_common/adapters/mix-text.ts b/packages/blocks/src/_common/adapters/mix-text.ts index 34a6b44ffe22..4d4548f4c486 100644 --- a/packages/blocks/src/_common/adapters/mix-text.ts +++ b/packages/blocks/src/_common/adapters/mix-text.ts @@ -1,10 +1,7 @@ import type { ExtensionType } from '@blocksuite/block-std'; import type { DeltaInsert } from '@blocksuite/inline'; -import { - DEFAULT_NOTE_BACKGROUND_COLOR, - NoteDisplayMode, -} from '@blocksuite/affine-model'; +import { DefaultTheme, NoteDisplayMode } from '@blocksuite/affine-model'; import { type AssetsManager, ASTWalker, @@ -165,7 +162,7 @@ export class MixTextAdapter extends BaseAdapter { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -232,7 +229,7 @@ export class MixTextAdapter extends BaseAdapter { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -285,7 +282,7 @@ export class MixTextAdapter extends BaseAdapter { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, diff --git a/packages/blocks/src/_common/adapters/notion-html/notion-html.ts b/packages/blocks/src/_common/adapters/notion-html/notion-html.ts index dcff0db6fefc..9f17e4128aee 100644 --- a/packages/blocks/src/_common/adapters/notion-html/notion-html.ts +++ b/packages/blocks/src/_common/adapters/notion-html/notion-html.ts @@ -1,9 +1,6 @@ import type { ExtensionType } from '@blocksuite/block-std'; -import { - DEFAULT_NOTE_BACKGROUND_COLOR, - NoteDisplayMode, -} from '@blocksuite/affine-model'; +import { DefaultTheme, NoteDisplayMode } from '@blocksuite/affine-model'; import { type AdapterContext, type BlockNotionHtmlAdapterMatcher, @@ -166,7 +163,7 @@ export class NotionHtmlAdapter extends BaseAdapter { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -197,7 +194,7 @@ export class NotionHtmlAdapter extends BaseAdapter { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -258,7 +255,7 @@ export class NotionHtmlAdapter extends BaseAdapter { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, diff --git a/packages/blocks/src/_common/adapters/notion-text.ts b/packages/blocks/src/_common/adapters/notion-text.ts index d3b6bdb9473c..b226f0bd8f0b 100644 --- a/packages/blocks/src/_common/adapters/notion-text.ts +++ b/packages/blocks/src/_common/adapters/notion-text.ts @@ -2,7 +2,7 @@ import type { AffineTextAttributes } from '@blocksuite/affine-shared/types'; import type { ExtensionType } from '@blocksuite/block-std'; import type { DeltaInsert } from '@blocksuite/inline'; -import { DEFAULT_NOTE_BACKGROUND_COLOR } from '@blocksuite/affine-model'; +import { DefaultTheme } from '@blocksuite/affine-model'; import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions'; import { type AssetsManager, @@ -128,7 +128,7 @@ export class NotionTextAdapter extends BaseAdapter { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: 'both', diff --git a/packages/blocks/src/_common/adapters/plain-text/plain-text.ts b/packages/blocks/src/_common/adapters/plain-text/plain-text.ts index ad74c6299800..3f8181df8da3 100644 --- a/packages/blocks/src/_common/adapters/plain-text/plain-text.ts +++ b/packages/blocks/src/_common/adapters/plain-text/plain-text.ts @@ -1,9 +1,6 @@ import type { ExtensionType } from '@blocksuite/block-std'; -import { - DEFAULT_NOTE_BACKGROUND_COLOR, - NoteDisplayMode, -} from '@blocksuite/affine-model'; +import { DefaultTheme, NoteDisplayMode } from '@blocksuite/affine-model'; import { type AdapterContext, type BlockPlainTextAdapterMatcher, @@ -160,7 +157,7 @@ export class PlainTextAdapter extends BaseAdapter { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -227,7 +224,7 @@ export class PlainTextAdapter extends BaseAdapter<PlainText> { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, @@ -270,7 +267,7 @@ export class PlainTextAdapter extends BaseAdapter<PlainText> { flavour: 'affine:note', props: { xywh: '[0,0,800,95]', - background: DEFAULT_NOTE_BACKGROUND_COLOR, + background: DefaultTheme.noteBackgrounColor, index: 'a0', hidden: false, displayMode: NoteDisplayMode.DocAndEdgeless, diff --git a/packages/blocks/src/note-block/note-edgeless-block.ts b/packages/blocks/src/note-block/note-edgeless-block.ts index d6835d7ccec1..ae9a75fcb733 100644 --- a/packages/blocks/src/note-block/note-edgeless-block.ts +++ b/packages/blocks/src/note-block/note-edgeless-block.ts @@ -4,7 +4,7 @@ import type { BlockModel } from '@blocksuite/store'; import { MoreIndicatorIcon } from '@blocksuite/affine-components/icons'; import { - DEFAULT_NOTE_BACKGROUND_COLOR, + DefaultTheme, NoteDisplayMode, StrokeStyle, } from '@blocksuite/affine-model'; @@ -24,6 +24,7 @@ import { Point, WithDisposable, } from '@blocksuite/global/utils'; +import { computed } from '@preact/signals-core'; import { css, html, nothing } from 'lit'; import { property, query, state } from 'lit/decorators.js'; import { classMap } from 'lit/directives/class-map.js'; @@ -143,6 +144,16 @@ export class EdgelessNoteBlockComponent extends toGfxBlockComponent( } `; + private _backgroundColor$ = computed(() => { + const themeProvider = this.std.get(ThemeProvider); + const theme = themeProvider.theme$.value; + return themeProvider.generateColorProperty( + this.model.background$.value, + DefaultTheme.noteBackgrounColor, + theme + ); + }); + private get _isShowCollapsedContent() { return this.model.edgeless.collapse && (this._isResizing || this._isHover); } @@ -404,9 +415,6 @@ export class EdgelessNoteBlockComponent extends toGfxBlockComponent( }; const extra = this._editing ? ACTIVE_NOTE_EXTRA_PADDING : 0; - const backgroundColor = this.std - .get(ThemeProvider) - .generateColorProperty(model.background, DEFAULT_NOTE_BACKGROUND_COLOR); const backgroundStyle = { position: 'absolute', @@ -418,7 +426,7 @@ export class EdgelessNoteBlockComponent extends toGfxBlockComponent( transition: this._editing ? 'left 0.3s, top 0.3s, width 0.3s, height 0.3s' : 'none', - backgroundColor, + backgroundColor: this._backgroundColor$.value, border: `${borderSize}px ${ borderStyle === StrokeStyle.Dash ? 'dashed' : borderStyle } var(--affine-black-10)`, diff --git a/packages/blocks/src/root-block/edgeless/components/auto-complete/auto-complete-panel.ts b/packages/blocks/src/root-block/edgeless/components/auto-complete/auto-complete-panel.ts index 9ddd91c28c66..59817ceb28f9 100644 --- a/packages/blocks/src/root-block/edgeless/components/auto-complete/auto-complete-panel.ts +++ b/packages/blocks/src/root-block/edgeless/components/auto-complete/auto-complete-panel.ts @@ -15,11 +15,8 @@ import { SmallNoteIcon, } from '@blocksuite/affine-components/icons'; import { - DEFAULT_NOTE_BACKGROUND_COLOR, DEFAULT_NOTE_WIDTH, - DEFAULT_SHAPE_FILL_COLOR, - DEFAULT_SHAPE_STROKE_COLOR, - DEFAULT_TEXT_COLOR, + DefaultTheme, FontFamily, FontStyle, FontWeight, @@ -281,7 +278,7 @@ export class EdgelessAutoCompletePanel extends WithDisposable(LitElement) { textAlign: 'left', fontSize: 24, fontFamily: FontFamily.Inter, - color: DEFAULT_TEXT_COLOR, + color: DefaultTheme.textColor, fontWeight: FontWeight.Regular, fontStyle: FontStyle.Normal, }); @@ -472,7 +469,7 @@ export class EdgelessAutoCompletePanel extends WithDisposable(LitElement) { .getColorValue( this.edgeless.std.get(EditPropsStore).lastProps$.value['affine:note'] .background, - DEFAULT_NOTE_BACKGROUND_COLOR, + DefaultTheme.noteBackgrounColor, true ); this._overlay = new AutoCompleteNoteOverlay(this.gfx, xywh, background); @@ -513,10 +510,10 @@ export class EdgelessAutoCompletePanel extends WithDisposable(LitElement) { const stroke = this.edgeless.std .get(ThemeProvider) - .getColorValue(strokeColor, DEFAULT_SHAPE_STROKE_COLOR, true); + .getColorValue(strokeColor, DefaultTheme.shapeStrokeColor, true); const fill = this.edgeless.std .get(ThemeProvider) - .getColorValue(fillColor, DEFAULT_SHAPE_FILL_COLOR, true); + .getColorValue(fillColor, DefaultTheme.shapeFillColor, true); const options = { seed: 666, diff --git a/packages/blocks/src/root-block/edgeless/components/auto-complete/edgeless-auto-complete.ts b/packages/blocks/src/root-block/edgeless/components/auto-complete/edgeless-auto-complete.ts index 03e544a365bc..9b897f189c94 100644 --- a/packages/blocks/src/root-block/edgeless/components/auto-complete/edgeless-auto-complete.ts +++ b/packages/blocks/src/root-block/edgeless/components/auto-complete/edgeless-auto-complete.ts @@ -22,7 +22,7 @@ import { } from '@blocksuite/affine-components/icons'; import { DEFAULT_NOTE_HEIGHT, - DEFAULT_SHAPE_STROKE_COLOR, + DefaultTheme, LayoutType, MindmapElementModel, ShapeElementModel, @@ -638,7 +638,7 @@ export class EdgelessAutoComplete extends WithDisposable(LitElement) { this._autoCompleteOverlay.stroke = surface.renderer.getColorValue( current.strokeColor, - DEFAULT_SHAPE_STROKE_COLOR, + DefaultTheme.shapeStrokeColor, true ); this._autoCompleteOverlay.linePoints = path; diff --git a/packages/blocks/src/root-block/edgeless/components/color-picker/button.ts b/packages/blocks/src/root-block/edgeless/components/color-picker/button.ts index 2c87711d9de8..5c85d45224f2 100644 --- a/packages/blocks/src/root-block/edgeless/components/color-picker/button.ts +++ b/packages/blocks/src/root-block/edgeless/components/color-picker/button.ts @@ -1,5 +1,7 @@ import type { EditorMenuButton } from '@blocksuite/affine-components/toolbar'; +import type { ColorScheme, Palette } from '@blocksuite/affine-model'; +import { resolveColor } from '@blocksuite/affine-model'; import { WithDisposable } from '@blocksuite/global/utils'; import { html, LitElement } from 'lit'; import { property, query, state } from 'lit/decorators.js'; @@ -8,12 +10,7 @@ import { ifDefined } from 'lit/directives/if-defined.js'; import { styleMap } from 'lit/directives/style-map.js'; import type { ColorEvent } from '../panel/color-panel.js'; -import type { - ModeType, - PickColorDetail, - PickColorEvent, - PickColorType, -} from './types.js'; +import type { ModeType, PickColorEvent, PickColorType } from './types.js'; import { keepColor, preprocessColor, rgbaToHex8 } from './utils.js'; @@ -21,7 +18,7 @@ type Type = 'normal' | 'custom'; export class EdgelessColorPickerButton extends WithDisposable(LitElement) { #select = (e: ColorEvent) => { - this.#pick({ palette: e.detail }); + this.#pick(e.detail); }; switchToCustomTab = (e: MouseEvent) => { @@ -71,14 +68,16 @@ export class EdgelessColorPickerButton extends WithDisposable(LitElement) { } get isCustomColor() { - return !this.palettes.includes(this.color); + return !this.palettes + .map(({ value }) => resolveColor(value, this.theme)) + .includes(this.color); } get tabContentPadding() { return `${this.tabType === 'custom' ? 0 : 8}px`; } - #pick(detail: PickColorDetail) { + #pick(detail: Palette) { this.pick?.({ type: 'start' }); this.pick?.({ type: 'pick', detail }); this.pick?.({ type: 'end' }); @@ -128,6 +127,7 @@ export class EdgelessColorPickerButton extends WithDisposable(LitElement) { role="listbox" class=${ifDefined(this.colorPanelClass)} .value=${this.color} + .theme=${this.theme} .palettes=${this.palettes} .hollowCircle=${this.hollowCircle} .openColorPicker=${this.switchToCustomTab} @@ -190,7 +190,7 @@ export class EdgelessColorPickerButton extends WithDisposable(LitElement) { accessor menuButton!: EditorMenuButton; @property({ attribute: false }) - accessor palettes: string[] = []; + accessor palettes: Palette[] = []; @property({ attribute: false }) accessor pick!: (event: PickColorEvent) => void; @@ -198,6 +198,9 @@ export class EdgelessColorPickerButton extends WithDisposable(LitElement) { @state() accessor tabType: Type = 'normal'; + @property({ attribute: false }) + accessor theme!: ColorScheme; + @property() accessor tooltip: string | undefined = undefined; } diff --git a/packages/blocks/src/root-block/edgeless/components/color-picker/color-picker.ts b/packages/blocks/src/root-block/edgeless/components/color-picker/color-picker.ts index a6dd7a9fd195..02a04cb12790 100644 --- a/packages/blocks/src/root-block/edgeless/components/color-picker/color-picker.ts +++ b/packages/blocks/src/root-block/edgeless/components/color-picker/color-picker.ts @@ -1,3 +1,5 @@ +import type { Color } from '@blocksuite/affine-model'; + import { on, once, stopPropagation } from '@blocksuite/affine-shared/utils'; import { SignalWatcher, WithDisposable } from '@blocksuite/global/utils'; import { batch, computed, signal } from '@preact/signals-core'; @@ -112,15 +114,15 @@ export class EdgelessColorPicker extends SignalWatcher( #pick() { const hsva = this.hsva$.peek(); const type = this.modeType$.peek(); - const detail = { [type]: hsvaToHex8(hsva) }; + const value = { [type]: hsvaToHex8(hsva) }; + const key = 'Custom'; if (type !== 'normal') { const another = type === 'light' ? 'dark' : 'light'; const { hsva } = this[`${another}$`].peek(); - detail[another] = hsvaToHex8(hsva); + value[another] = hsvaToHex8(hsva); } - - this.pick?.({ type: 'pick', detail }); + this.pick?.({ type: 'pick', detail: { key, value: value as Color } }); } #pickEnd() { diff --git a/packages/blocks/src/root-block/edgeless/components/color-picker/types.ts b/packages/blocks/src/root-block/edgeless/components/color-picker/types.ts index 820a6306cf99..f9d853486774 100644 --- a/packages/blocks/src/root-block/edgeless/components/color-picker/types.ts +++ b/packages/blocks/src/root-block/edgeless/components/color-picker/types.ts @@ -1,6 +1,6 @@ // https://www.w3.org/TR/css-color-4/ -import type { ColorScheme } from '@blocksuite/affine-model'; +import type { ColorScheme, Palette } from '@blocksuite/affine-model'; // Red, green, blue. All in the range [0, 1]. export type Rgb = { @@ -48,8 +48,6 @@ export type ModeRgba = { type: ModeType; rgba: Rgba }; export type PickColorType = 'palette' | ModeType; -export type PickColorDetail = Partial<Record<PickColorType, string>>; - export type PickColorEvent = | { type: 'start' | 'end' } - | { type: 'pick'; detail: PickColorDetail }; + | { type: 'pick'; detail: Palette }; diff --git a/packages/blocks/src/root-block/edgeless/components/color-picker/utils.ts b/packages/blocks/src/root-block/edgeless/components/color-picker/utils.ts index 573563be9f5f..bc657afe69da 100644 --- a/packages/blocks/src/root-block/edgeless/components/color-picker/utils.ts +++ b/packages/blocks/src/root-block/edgeless/components/color-picker/utils.ts @@ -6,7 +6,6 @@ import type { Hsv, Hsva, ModeType, - PickColorDetail, PickColorType, Point, Rgb, @@ -270,12 +269,13 @@ export const preprocessColor = (style: CSSStyleDeclaration) => { * * ```json * { 'fillColor': '--affine-palette-shape-yellow' } + * { 'fillColor': '#ffffff' } * { 'fillColor': { normal: '#ffffffff' }} * { 'fillColor': { light: '#fff000ff', 'dark': '#0000fff00' }} * ``` */ -export const packColor = (key: string, detail: PickColorDetail) => { - return { [key]: detail.palette ?? detail }; +export const packColor = (key: string, color: Color) => { + return { [key]: typeof color === 'object' ? { ...color } : color }; }; /** @@ -299,10 +299,14 @@ export const packColorsWithColorScheme = ( let type: PickColorType = 'palette'; if (typeof oldColor === 'object') { - type = colorScheme in oldColor ? colorScheme : 'normal'; - colors[0].value = oldColor.normal ?? value; - colors[1].value = oldColor.light ?? value; - colors[2].value = oldColor.dark ?? value; + if ('normal' in oldColor) { + type = 'normal'; + colors[0].value = oldColor.normal ?? value; + } else { + type = colorScheme; + colors[1].value = oldColor.light ?? value; + colors[2].value = oldColor.dark ?? value; + } } return { type, colors }; diff --git a/packages/blocks/src/root-block/edgeless/components/panel/color-panel.ts b/packages/blocks/src/root-block/edgeless/components/panel/color-panel.ts index 7d33780eaa41..d8716372cf0a 100644 --- a/packages/blocks/src/root-block/edgeless/components/panel/color-panel.ts +++ b/packages/blocks/src/root-block/edgeless/components/panel/color-panel.ts @@ -1,12 +1,16 @@ -import { Black, ColorScheme, PALETTES, White } from '@blocksuite/affine-model'; +import type { Color, ColorScheme, Palette } from '@blocksuite/affine-model'; + +import { isTransparent, resolveColor } from '@blocksuite/affine-model'; import { unsafeCSSVarV2 } from '@blocksuite/affine-shared/theme'; import { css, html, LitElement, nothing, svg, type TemplateResult } from 'lit'; import { property } from 'lit/decorators.js'; import { classMap } from 'lit/directives/class-map.js'; +import { ifDefined } from 'lit/directives/if-defined.js'; import { repeat } from 'lit/directives/repeat.js'; +import isEqual from 'lodash.isequal'; export class ColorEvent extends Event { - detail: string; + detail: Palette; constructor( type: string, @@ -14,21 +18,13 @@ export class ColorEvent extends Event { detail, composed, bubbles, - }: { detail: string; composed: boolean; bubbles: boolean } + }: { detail: Palette; composed: boolean; bubbles: boolean } ) { super(type, { bubbles, composed }); this.detail = detail; } } -export const GET_DEFAULT_LINE_COLOR = (theme: ColorScheme) => { - return theme === ColorScheme.Dark ? White : Black; -}; - -export function isTransparent(color: string) { - return color.toLowerCase().endsWith('transparent'); -} - function TransparentIcon(hollowCircle = false) { const CircleIcon: TemplateResult | typeof nothing = hollowCircle ? svg`<circle cx="10" cy="10" r="8" fill="white" />` @@ -167,18 +163,14 @@ export class EdgelessColorButton extends LitElement { `; get preprocessColor() { - const color = this.color; - return color.startsWith('--') ? `var(${color})` : color; + const value = resolveColor(this.color, this.theme); + return value.startsWith('--') ? `var(${value})` : value; } override render() { - const { color, preprocessColor, hollowCircle, letter } = this; + const { label, preprocessColor, hollowCircle } = this; const additionIcon = AdditionIcon(preprocessColor, !!hollowCircle); - return html`<div - class="color-unit" - aria-label=${color} - data-letter=${letter ? 'A' : nothing} - > + return html`<div class="color-unit" aria-label=${ifDefined(label)}> ${additionIcon} </div>`; } @@ -187,13 +179,16 @@ export class EdgelessColorButton extends LitElement { accessor active: boolean = false; @property({ attribute: false }) - accessor color!: string; + accessor color!: Color; @property({ attribute: false }) accessor hollowCircle: boolean = false; @property({ attribute: false }) - accessor letter: boolean | undefined = undefined; + accessor label: string | undefined = undefined; + + @property({ attribute: false }) + accessor theme!: ColorScheme; } export class EdgelessColorPanel extends LitElement { @@ -221,35 +216,40 @@ export class EdgelessColorPanel extends LitElement { } `; - onSelect(value: string) { + onSelect(palette: Palette) { this.dispatchEvent( new ColorEvent('select', { - detail: value, + detail: palette, composed: true, bubbles: true, }) ); - this.value = value; } override render() { return html` ${repeat( this.palettes, - color => color, - color => - html`<edgeless-color-button + palette => palette.key, + palette => { + const resolvedColor = resolveColor(palette.value, this.theme); + return html`<edgeless-color-button class=${classMap({ large: true, - black: color.startsWith('--') && color.endsWith('black'), + black: palette.key.toLowerCase().endsWith('black'), })} - .color=${color} - .letter=${this.showLetterMark} + .label=${palette.key} + .color=${palette.value} + .theme=${this.theme} .hollowCircle=${this.hollowCircle} - ?active=${color === this.value} - @click=${() => this.onSelect(color)} + ?active=${isEqual(resolvedColor, this.value)} + @click=${() => { + this.onSelect(palette); + this.value = resolvedColor; + }} > - </edgeless-color-button>` + </edgeless-color-button>`; + } )} <slot name="custom"></slot> `; @@ -265,10 +265,10 @@ export class EdgelessColorPanel extends LitElement { accessor openColorPicker!: (e: MouseEvent) => void; @property({ type: Array }) - accessor palettes: readonly string[] = PALETTES; + accessor palettes: readonly Palette[] = []; @property({ attribute: false }) - accessor showLetterMark = false; + accessor theme!: ColorScheme; @property({ attribute: false }) accessor value: string | null = null; diff --git a/packages/blocks/src/root-block/edgeless/components/panel/stroke-style-panel.ts b/packages/blocks/src/root-block/edgeless/components/panel/stroke-style-panel.ts index cf17a3758d1f..4e7fa3750c16 100644 --- a/packages/blocks/src/root-block/edgeless/components/panel/stroke-style-panel.ts +++ b/packages/blocks/src/root-block/edgeless/components/panel/stroke-style-panel.ts @@ -1,4 +1,8 @@ -import { PALETTES, type StrokeStyle } from '@blocksuite/affine-model'; +import { + type ColorScheme, + DefaultTheme, + type StrokeStyle, +} from '@blocksuite/affine-model'; import { WithDisposable } from '@blocksuite/global/utils'; import { css, html, LitElement } from 'lit'; import { property } from 'lit/decorators.js'; @@ -39,8 +43,9 @@ export class StrokeStylePanel extends WithDisposable(LitElement) { <edgeless-color-panel role="listbox" aria-label="Border colors" - .palettes=${PALETTES} .value=${this.strokeColor} + .theme=${this.theme} + .palettes=${DefaultTheme.palettes} .hollowCircle=${this.hollowCircle} @select=${(e: ColorEvent) => this.setStrokeColor(e)} > @@ -65,6 +70,9 @@ export class StrokeStylePanel extends WithDisposable(LitElement) { @property({ attribute: false }) accessor strokeWidth!: number; + + @property({ attribute: false }) + accessor theme!: ColorScheme; } declare global { diff --git a/packages/blocks/src/root-block/edgeless/components/toolbar/brush/brush-menu.ts b/packages/blocks/src/root-block/edgeless/components/toolbar/brush/brush-menu.ts index 65ea683099cb..8dfb5e3771b1 100644 --- a/packages/blocks/src/root-block/edgeless/components/toolbar/brush/brush-menu.ts +++ b/packages/blocks/src/root-block/edgeless/components/toolbar/brush/brush-menu.ts @@ -1,6 +1,6 @@ import type { GfxToolsFullOptionValue } from '@blocksuite/block-std/gfx'; -import { STROKE_COLORS } from '@blocksuite/affine-model'; +import { DefaultTheme } from '@blocksuite/affine-model'; import { EditPropsStore, ThemeProvider, @@ -10,12 +10,9 @@ import { computed } from '@preact/signals-core'; import { css, html, LitElement } from 'lit'; import { property } from 'lit/decorators.js'; +import type { ColorEvent } from '../../panel/color-panel.js'; import type { LineWidthEvent } from '../../panel/line-width-panel.js'; -import { - type ColorEvent, - GET_DEFAULT_LINE_COLOR, -} from '../../panel/color-panel.js'; import { EdgelessToolbarToolMixin } from '../mixins/tool.mixin.js'; export class EdgelessBrushMenu extends EdgelessToolbarToolMixin( @@ -48,14 +45,13 @@ export class EdgelessBrushMenu extends EdgelessToolbarToolMixin( }; }); + private _theme$ = computed(() => { + return this.edgeless.std.get(ThemeProvider).theme$.value; + }); + type: GfxToolsFullOptionValue['type'] = 'brush'; override render() { - const theme = this.edgeless.std.get(ThemeProvider).theme; - const color = this.edgeless.std - .get(ThemeProvider) - .getColorValue(this._props$.value.color, GET_DEFAULT_LINE_COLOR(theme)); - return html` <edgeless-slide-menu> <div class="menu-content"> @@ -68,12 +64,14 @@ export class EdgelessBrushMenu extends EdgelessToolbarToolMixin( <menu-divider .vertical=${true}></menu-divider> <edgeless-color-panel class="one-way" - .value=${color} - .palettes=${STROKE_COLORS} + .value=${this._props$.value.color} + .theme=${this._theme$.value} + .palettes=${DefaultTheme.globalToolbarPalettes} .hasTransparent=${!this.edgeless.doc.awarenessStore.getFlag( 'enable_color_picker' )} - @select=${(e: ColorEvent) => this.onChange({ color: e.detail })} + @select=${(e: ColorEvent) => + this.onChange({ color: e.detail.value })} ></edgeless-color-panel> </div> </edgeless-slide-menu> diff --git a/packages/blocks/src/root-block/edgeless/components/toolbar/connector/connector-menu.ts b/packages/blocks/src/root-block/edgeless/components/toolbar/connector/connector-menu.ts index b48ac21bfc53..4bc1843d45a1 100644 --- a/packages/blocks/src/root-block/edgeless/components/toolbar/connector/connector-menu.ts +++ b/packages/blocks/src/root-block/edgeless/components/toolbar/connector/connector-menu.ts @@ -5,10 +5,7 @@ import { ConnectorLWithArrowIcon, ConnectorXWithArrowIcon, } from '@blocksuite/affine-components/icons'; -import { - ConnectorMode, - DEFAULT_CONNECTOR_COLOR, -} from '@blocksuite/affine-model'; +import { ConnectorMode, DefaultTheme } from '@blocksuite/affine-model'; import { EditPropsStore, ThemeProvider, @@ -105,6 +102,10 @@ export class EdgelessConnectorMenu extends EdgelessToolbarToolMixin( return { mode, stroke, strokeWidth }; }); + private _theme$ = computed(() => { + return this.edgeless.std.get(ThemeProvider).theme$.value; + }); + override type: GfxToolsFullOptionValue['type'] = 'connector'; override render() { @@ -113,9 +114,6 @@ export class EdgelessConnectorMenu extends EdgelessToolbarToolMixin( mode, this.onChange ); - const color = this.edgeless.std - .get(ThemeProvider) - .getColorValue(stroke, DEFAULT_CONNECTOR_COLOR); return html` <edgeless-slide-menu> @@ -131,11 +129,14 @@ export class EdgelessConnectorMenu extends EdgelessToolbarToolMixin( <div class="submenu-divider"></div> <edgeless-color-panel class="one-way" - .value=${color} + .value=${stroke} + .theme=${this._theme$.value} + .palettes=${DefaultTheme.globalToolbarPalettes} .hasTransparent=${!this.edgeless.doc.awarenessStore.getFlag( 'enable_color_picker' )} - @select=${(e: ColorEvent) => this.onChange({ stroke: e.detail })} + @select=${(e: ColorEvent) => + this.onChange({ stroke: e.detail.value })} ></edgeless-color-panel> </div> </edgeless-slide-menu> diff --git a/packages/blocks/src/root-block/edgeless/components/toolbar/edgeless-toolbar.ts b/packages/blocks/src/root-block/edgeless/components/toolbar/edgeless-toolbar.ts index 15b0d532793b..ea19445e7f8c 100644 --- a/packages/blocks/src/root-block/edgeless/components/toolbar/edgeless-toolbar.ts +++ b/packages/blocks/src/root-block/edgeless/components/toolbar/edgeless-toolbar.ts @@ -24,6 +24,7 @@ import { debounce } from '@blocksuite/global/utils'; import { Slot } from '@blocksuite/store'; import { autoPlacement, offset } from '@floating-ui/dom'; import { ContextProvider } from '@lit/context'; +import { computed } from '@preact/signals-core'; import { baseTheme, cssVar } from '@toeverything/theme'; import { css, html, nothing, unsafeCSS } from 'lit'; import { query, state } from 'lit/decorators.js'; @@ -222,6 +223,10 @@ export class EdgelessToolbarWidget extends WidgetComponent< } `; + private _appTheme$ = computed(() => { + return this.std.get(ThemeProvider).app$.value; + }); + private _moreQuickToolsMenu: MenuHandler | null = null; private _moreQuickToolsMenuRef: HTMLElement | null = null; @@ -625,9 +630,8 @@ export class EdgelessToolbarWidget extends WidgetComponent< return nothing; } - const appTheme = this.std.get(ThemeProvider).app$.value; return html` - <div class="edgeless-toolbar-wrapper" data-app-theme=${appTheme}> + <div class="edgeless-toolbar-wrapper" data-app-theme=${this._appTheme$}> <div class="edgeless-toolbar-toggle-control" data-enable=${this._enableAutoHide} diff --git a/packages/blocks/src/root-block/edgeless/components/toolbar/shape/shape-menu.ts b/packages/blocks/src/root-block/edgeless/components/toolbar/shape/shape-menu.ts index 6cbc89b660e2..cc291a0c5548 100644 --- a/packages/blocks/src/root-block/edgeless/components/toolbar/shape/shape-menu.ts +++ b/packages/blocks/src/root-block/edgeless/components/toolbar/shape/shape-menu.ts @@ -5,14 +5,12 @@ import { ScribbledStyleIcon, } from '@blocksuite/affine-components/icons'; import { - DEFAULT_SHAPE_FILL_COLOR, - LIGHT_PALETTES, - MEDIUM_PALETTES, - SHAPE_FILL_COLORS, + DefaultTheme, + isTransparent, + type Palette, type ShapeName, ShapeStyle, ShapeType, - StrokeColor, } from '@blocksuite/affine-model'; import { EditPropsStore, @@ -24,8 +22,8 @@ import { css, html, LitElement } from 'lit'; import { property } from 'lit/decorators.js'; import type { EdgelessRootBlockComponent } from '../../../edgeless-root-block.js'; +import type { ColorEvent } from '../../panel/color-panel.js'; -import { type ColorEvent, isTransparent } from '../../panel/color-panel.js'; import { ShapeComponentConfig } from './shape-menu-config.js'; export class EdgelessShapeMenu extends SignalWatcher( @@ -78,20 +76,13 @@ export class EdgelessShapeMenu extends SignalWatcher( }; }); - private _setFillColor = (fillColor: string) => { - const filled = !isTransparent(fillColor); - let strokeColor = fillColor; // white or black - - if (filled) { - const index = LIGHT_PALETTES.findIndex(color => color === fillColor); - if (index !== -1) { - strokeColor = MEDIUM_PALETTES[index]; - } - } - - if (strokeColor.endsWith('transparent')) { - strokeColor = StrokeColor.Grey; - } + private _setFillColor = ({ key, value }: Palette) => { + const filled = !isTransparent(value); + const fillColor = value; + const strokeColor = filled + ? DefaultTheme.globalToolbarPalettes.find(palette => palette.key === key) + ?.value + : DefaultTheme.StrokeColor.Grey; const { shapeName } = this._props$.value; this.edgeless.std @@ -114,6 +105,10 @@ export class EdgelessShapeMenu extends SignalWatcher( this.onChange(shapeName); }; + private _theme$ = computed(() => { + return this.edgeless.std.get(ThemeProvider).theme$.value; + }); + override connectedCallback(): void { super.connectedCallback(); @@ -130,9 +125,6 @@ export class EdgelessShapeMenu extends SignalWatcher( override render() { const { fillColor, shapeStyle, shapeName } = this._props$.value; - const color = this.edgeless.std - .get(ThemeProvider) - .getColorValue(fillColor, DEFAULT_SHAPE_FILL_COLOR); return html` <edgeless-slide-menu> @@ -181,8 +173,9 @@ export class EdgelessShapeMenu extends SignalWatcher( <menu-divider .vertical=${true}></menu-divider> <edgeless-color-panel class="one-way" - .value=${color} - .palettes=${SHAPE_FILL_COLORS} + .value=${fillColor} + .theme=${this._theme$.value} + .palettes=${DefaultTheme.globalToolbarShapeFillPalettes} .hasTransparent=${!this.edgeless.doc.awarenessStore.getFlag( 'enable_color_picker' )} diff --git a/packages/blocks/src/root-block/edgeless/components/toolbar/text/text-menu.ts b/packages/blocks/src/root-block/edgeless/components/toolbar/text/text-menu.ts index 4e0e46e02d97..7ad9013185c8 100644 --- a/packages/blocks/src/root-block/edgeless/components/toolbar/text/text-menu.ts +++ b/packages/blocks/src/root-block/edgeless/components/toolbar/text/text-menu.ts @@ -1,6 +1,8 @@ import type { GfxToolsFullOptionValue } from '@blocksuite/block-std/gfx'; -import { STROKE_COLORS } from '@blocksuite/affine-model'; +import { DefaultTheme } from '@blocksuite/affine-model'; +import { ThemeProvider } from '@blocksuite/affine-shared/services'; +import { computed } from '@preact/signals-core'; import { css, html, LitElement, nothing } from 'lit'; import { property } from 'lit/decorators.js'; @@ -17,6 +19,10 @@ export class EdgelessTextMenu extends EdgelessToolbarToolMixin(LitElement) { } `; + private _theme$ = computed(() => { + return this.edgeless.std.get(ThemeProvider).theme$.value; + }); + override type: GfxToolsFullOptionValue['type'] = 'text'; override render() { @@ -28,7 +34,8 @@ export class EdgelessTextMenu extends EdgelessToolbarToolMixin(LitElement) { <edgeless-color-panel class="one-way" .value=${this.color} - .palettes=${STROKE_COLORS} + .theme=${this._theme$.value} + .palettes=${DefaultTheme.globalToolbarPalettes} @select=${(e: ColorEvent) => this.onChange({ color: e.detail })} ></edgeless-color-panel> </div> diff --git a/packages/blocks/src/root-block/edgeless/gfx-tool/shape-tool.ts b/packages/blocks/src/root-block/edgeless/gfx-tool/shape-tool.ts index ac589da9ad18..0073e77551e2 100644 --- a/packages/blocks/src/root-block/edgeless/gfx-tool/shape-tool.ts +++ b/packages/blocks/src/root-block/edgeless/gfx-tool/shape-tool.ts @@ -6,11 +6,7 @@ import { CanvasElementType, type SurfaceBlockComponent, } from '@blocksuite/affine-block-surface'; -import { - DEFAULT_SHAPE_FILL_COLOR, - DEFAULT_SHAPE_STROKE_COLOR, - getShapeType, -} from '@blocksuite/affine-model'; +import { DefaultTheme, getShapeType } from '@blocksuite/affine-model'; import { EditPropsStore, TelemetryProvider, @@ -203,10 +199,14 @@ export class ShapeTool extends BaseTool<ShapeToolOption> { options.stroke = this.std .get(ThemeProvider) - .getColorValue(attributes.strokeColor, DEFAULT_SHAPE_STROKE_COLOR, true); + .getColorValue( + attributes.strokeColor, + DefaultTheme.shapeStrokeColor, + true + ); options.fill = this.std .get(ThemeProvider) - .getColorValue(attributes.fillColor, DEFAULT_SHAPE_FILL_COLOR, true); + .getColorValue(attributes.fillColor, DefaultTheme.shapeFillColor, true); switch (attributes.strokeStyle!) { case 'dash': diff --git a/packages/blocks/src/root-block/edgeless/utils/consts.ts b/packages/blocks/src/root-block/edgeless/utils/consts.ts index 9a4b9dad1472..1f9646826e7c 100644 --- a/packages/blocks/src/root-block/edgeless/utils/consts.ts +++ b/packages/blocks/src/root-block/edgeless/utils/consts.ts @@ -1,9 +1,7 @@ import { - Black, DEFAULT_ROUGHNESS, LineWidth, StrokeStyle, - White, } from '@blocksuite/affine-model'; export const BOOKMARK_MIN_WIDTH = 450; @@ -52,10 +50,6 @@ export const SurfaceColor = '#6046FE'; export const NoteColor = '#1E96EB'; export const BlendColor = '#7D91FF'; -export const SHAPE_TEXT_COLOR_PURE_WHITE = White; -export const SHAPE_TEXT_COLOR_PURE_BLACK = Black; -export const SHAPE_FILL_COLOR_BLACK = Black; - export const AI_CHAT_BLOCK_MIN_WIDTH = 260; export const AI_CHAT_BLOCK_MIN_HEIGHT = 160; export const AI_CHAT_BLOCK_MAX_WIDTH = 320; diff --git a/packages/blocks/src/root-block/edgeless/utils/tool-overlay.ts b/packages/blocks/src/root-block/edgeless/utils/tool-overlay.ts index dbef4ef51a5c..c98ee717ccb1 100644 --- a/packages/blocks/src/root-block/edgeless/utils/tool-overlay.ts +++ b/packages/blocks/src/root-block/edgeless/utils/tool-overlay.ts @@ -9,9 +9,7 @@ import { } from '@blocksuite/affine-block-surface'; import { type Color, - DEFAULT_NOTE_BACKGROUND_COLOR, - DEFAULT_SHAPE_FILL_COLOR, - DEFAULT_SHAPE_STROKE_COLOR, + DefaultTheme, shapeMethods, type ShapeStyle, } from '@blocksuite/affine-model'; @@ -288,10 +286,10 @@ export class ShapeOverlay extends ToolOverlay { const { shapeStyle, fillColor, strokeColor } = style; const fill = this.gfx.std .get(ThemeProvider) - .getColorValue(fillColor, DEFAULT_SHAPE_FILL_COLOR, true); + .getColorValue(fillColor, DefaultTheme.shapeFillColor, true); const stroke = this.gfx.std .get(ThemeProvider) - .getColorValue(strokeColor, DEFAULT_SHAPE_STROKE_COLOR, true); + .getColorValue(strokeColor, DefaultTheme.shapeStrokeColor, true); options.fill = fill; options.stroke = stroke; @@ -358,7 +356,7 @@ export class NoteOverlay extends ToolOverlay { this.globalAlpha = 0; this.backgroundColor = gfx.std .get(ThemeProvider) - .getColorValue(background, DEFAULT_NOTE_BACKGROUND_COLOR, true); + .getColorValue(background, DefaultTheme.noteBackgrounColor, true); this.disposables.add( effect(() => { // when change note child type, update overlay text diff --git a/packages/blocks/src/root-block/widgets/element-toolbar/change-brush-button.ts b/packages/blocks/src/root-block/widgets/element-toolbar/change-brush-button.ts index d2f258a47f83..b27f6fe2c706 100644 --- a/packages/blocks/src/root-block/widgets/element-toolbar/change-brush-button.ts +++ b/packages/blocks/src/root-block/widgets/element-toolbar/change-brush-button.ts @@ -4,10 +4,14 @@ import type { ColorScheme, } from '@blocksuite/affine-model'; -import { LineWidth, PALETTES } from '@blocksuite/affine-model'; +import { + DefaultTheme, + LineWidth, + resolveColor, +} from '@blocksuite/affine-model'; import { countBy, maxBy, WithDisposable } from '@blocksuite/global/utils'; import { html, LitElement, nothing } from 'lit'; -import { property, query, state } from 'lit/decorators.js'; +import { property, query } from 'lit/decorators.js'; import { when } from 'lit/directives/when.js'; import type { EdgelessColorPickerButton } from '../../edgeless/components/color-picker/button.js'; @@ -20,19 +24,18 @@ import { packColor, packColorsWithColorScheme, } from '../../edgeless/components/color-picker/utils.js'; -import { GET_DEFAULT_LINE_COLOR } from '../../edgeless/components/panel/color-panel.js'; function getMostCommonColor( elements: BrushElementModel[], colorScheme: ColorScheme ): string { - const colors = countBy(elements, (ele: BrushElementModel) => { - return typeof ele.color === 'object' - ? (ele.color[colorScheme] ?? ele.color.normal ?? null) - : ele.color; - }); + const colors = countBy(elements, (ele: BrushElementModel) => + resolveColor(ele.color, colorScheme) + ); const max = maxBy(Object.entries(colors), ([_k, count]) => count); - return max ? (max[0] as string) : GET_DEFAULT_LINE_COLOR(colorScheme); + return max + ? (max[0] as string) + : resolveColor(DefaultTheme.black, colorScheme); } function getMostCommonSize(elements: BrushElementModel[]): LineWidth { @@ -46,29 +49,29 @@ function notEqual<K extends keyof BrushProps>(key: K, value: BrushProps[K]) { } export class EdgelessChangeBrushButton extends WithDisposable(LitElement) { - private _setBrushColor = ({ detail: color }: ColorEvent) => { + private _setBrushColor = ({ detail }: ColorEvent) => { + const color = detail.value; this._setBrushProp('color', color); - this._selectedColor = color; }; private _setLineWidth = ({ detail: lineWidth }: LineWidthEvent) => { this._setBrushProp('lineWidth', lineWidth); - this._selectedSize = lineWidth; }; - pickColor = (event: PickColorEvent) => { - if (event.type === 'pick') { - this.elements.forEach(ele => - this.service.updateElement( - ele.id, - packColor('color', { ...event.detail }) - ) - ); + pickColor = (e: PickColorEvent) => { + const field = 'color'; + + if (e.type === 'pick') { + const color = e.detail.value; + this.elements.forEach(ele => { + const props = packColor(field, color); + this.service.updateElement(ele.id, props); + }); return; } this.elements.forEach(ele => - ele[event.type === 'start' ? 'stash' : 'pop']('color') + ele[e.type === 'start' ? 'stash' : 'pop'](field) ); }; @@ -76,17 +79,6 @@ export class EdgelessChangeBrushButton extends WithDisposable(LitElement) { return this.edgeless.doc; } - get selectedColor() { - const colorScheme = this.edgeless.surface.renderer.getColorScheme(); - return ( - this._selectedColor ?? getMostCommonColor(this.elements, colorScheme) - ); - } - - get selectedSize() { - return this._selectedSize ?? getMostCommonSize(this.elements); - } - get service() { return this.edgeless.service; } @@ -110,7 +102,8 @@ export class EdgelessChangeBrushButton extends WithDisposable(LitElement) { override render() { const colorScheme = this.edgeless.surface.renderer.getColorScheme(); const elements = this.elements; - const { selectedSize, selectedColor } = this; + const selectedColor = getMostCommonColor(elements, colorScheme); + const selectedSize = getMostCommonSize(elements); return html` <edgeless-line-width-panel @@ -138,7 +131,8 @@ export class EdgelessChangeBrushButton extends WithDisposable(LitElement) { .color=${selectedColor} .colors=${colors} .colorType=${type} - .palettes=${PALETTES} + .theme=${colorScheme} + .palettes=${DefaultTheme.palettes} > </edgeless-color-picker-button> `; @@ -156,6 +150,8 @@ export class EdgelessChangeBrushButton extends WithDisposable(LitElement) { > <edgeless-color-panel .value=${selectedColor} + .theme=${colorScheme} + .palettes=${DefaultTheme.palettes} @select=${this._setBrushColor} > </edgeless-color-panel> @@ -165,12 +161,6 @@ export class EdgelessChangeBrushButton extends WithDisposable(LitElement) { `; } - @state() - private accessor _selectedColor: string | null = null; - - @state() - private accessor _selectedSize: LineWidth | null = null; - @query('edgeless-color-picker-button.color') accessor colorButton!: EdgelessColorPickerButton; diff --git a/packages/blocks/src/root-block/widgets/element-toolbar/change-connector-button.ts b/packages/blocks/src/root-block/widgets/element-toolbar/change-connector-button.ts index dcce3106ef23..cc2dbf383d04 100644 --- a/packages/blocks/src/root-block/widgets/element-toolbar/change-connector-button.ts +++ b/packages/blocks/src/root-block/widgets/element-toolbar/change-connector-button.ts @@ -27,9 +27,11 @@ import { ConnectorMode, DEFAULT_FRONT_END_POINT_STYLE, DEFAULT_REAR_END_POINT_STYLE, + DefaultTheme, PointStyle, + resolveColor, } from '@blocksuite/affine-model'; -import { LineWidth, PALETTES, StrokeStyle } from '@blocksuite/affine-model'; +import { LineWidth, StrokeStyle } from '@blocksuite/affine-model'; import { countBy, maxBy, WithDisposable } from '@blocksuite/global/utils'; import { html, LitElement, nothing, type TemplateResult } from 'lit'; import { property, query } from 'lit/decorators.js'; @@ -41,16 +43,13 @@ import { when } from 'lit/directives/when.js'; import type { EdgelessColorPickerButton } from '../../edgeless/components/color-picker/button.js'; import type { PickColorEvent } from '../../edgeless/components/color-picker/types.js'; +import type { ColorEvent } from '../../edgeless/components/panel/color-panel.js'; import type { EdgelessRootBlockComponent } from '../../edgeless/edgeless-root-block.js'; import { packColor, packColorsWithColorScheme, } from '../../edgeless/components/color-picker/utils.js'; -import { - type ColorEvent, - GET_DEFAULT_LINE_COLOR, -} from '../../edgeless/components/panel/color-panel.js'; import { type LineStyleEvent, LineStylesPanel, @@ -60,14 +59,14 @@ import { mountConnectorLabelEditor } from '../../edgeless/utils/text.js'; function getMostCommonColor( elements: ConnectorElementModel[], colorScheme: ColorScheme -): string | null { - const colors = countBy(elements, (ele: ConnectorElementModel) => { - return typeof ele.stroke === 'object' - ? (ele.stroke[colorScheme] ?? ele.stroke.normal ?? null) - : ele.stroke; - }); +): string { + const colors = countBy(elements, (ele: ConnectorElementModel) => + resolveColor(ele.stroke, colorScheme) + ); const max = maxBy(Object.entries(colors), ([_k, count]) => count); - return max ? (max[0] as string) : null; + return max + ? (max[0] as string) + : resolveColor(DefaultTheme.connectorColor, colorScheme); } function getMostCommonMode( @@ -86,10 +85,10 @@ function getMostCommonLineWidth(elements: ConnectorElementModel[]): LineWidth { export function getMostCommonLineStyle( elements: ConnectorElementModel[] -): StrokeStyle | null { +): StrokeStyle { const sizes = countBy(elements, ele => ele.strokeStyle); const max = maxBy(Object.entries(sizes), ([_k, count]) => count); - return max ? (max[0] as StrokeStyle) : null; + return max ? (max[0] as StrokeStyle) : StrokeStyle.Solid; } function getMostCommonRough(elements: ConnectorElementModel[]): boolean { @@ -110,15 +109,16 @@ function getMostCommonRough(elements: ConnectorElementModel[]): boolean { function getMostCommonEndpointStyle( elements: ConnectorElementModel[], - endpoint: ConnectorEndpoint -): PointStyle | null { + endpoint: ConnectorEndpoint, + fallback: PointStyle +): PointStyle { const field = endpoint === ConnectorEndpoint.Front ? 'frontEndpointStyle' : 'rearEndpointStyle'; const modes = countBy(elements, ele => ele[field]); const max = maxBy(Object.entries(modes), ([_k, count]) => count); - return max ? (max[0] as PointStyle) : null; + return max ? (max[0] as PointStyle) : fallback; } function notEqual< @@ -221,19 +221,33 @@ const MODE_CHOOSE: [ConnectorMode, () => TemplateResult<1>][] = [ ] as const; export class EdgelessChangeConnectorButton extends WithDisposable(LitElement) { - pickColor = (event: PickColorEvent) => { - if (event.type === 'pick') { - this.elements.forEach(ele => - this.service.updateElement( - ele.id, - packColor('stroke', { ...event.detail }) - ) - ); + private _setConnectorColor = (e: ColorEvent) => { + const stroke = e.detail.value; + this._setConnectorProp('stroke', stroke); + }; + + private _setConnectorStroke = ({ type, value }: LineStyleEvent) => { + if (type === 'size') { + this._setConnectorStrokeWidth(value); + return; + } + this._setConnectorStrokeStyle(value); + }; + + pickColor = (e: PickColorEvent) => { + const field = 'stroke'; + + if (e.type === 'pick') { + const color = e.detail.value; + this.elements.forEach(ele => { + const props = packColor(field, color); + this.service.updateElement(ele.id, props); + }); return; } this.elements.forEach(ele => - ele[event.type === 'start' ? 'stash' : 'pop']('stroke') + ele[e.type === 'start' ? 'stash' : 'pop'](field) ); }; @@ -270,10 +284,6 @@ export class EdgelessChangeConnectorButton extends WithDisposable(LitElement) { ); } - private _setConnectorColor(stroke: string) { - this._setConnectorProp('stroke', stroke); - } - private _setConnectorMode(mode: ConnectorMode) { this._setConnectorProp('mode', mode); } @@ -304,14 +314,6 @@ export class EdgelessChangeConnectorButton extends WithDisposable(LitElement) { this._setConnectorProp('rough', rough); } - private _setConnectorStroke({ type, value }: LineStyleEvent) { - if (type === 'size') { - this._setConnectorStrokeWidth(value); - return; - } - this._setConnectorStrokeStyle(value); - } - private _setConnectorStrokeStyle(strokeStyle: StrokeStyle) { this._setConnectorProp('strokeStyle', strokeStyle); } @@ -333,20 +335,21 @@ export class EdgelessChangeConnectorButton extends WithDisposable(LitElement) { override render() { const colorScheme = this.edgeless.surface.renderer.getColorScheme(); const elements = this.elements; - const selectedColor = - getMostCommonColor(elements, colorScheme) ?? - GET_DEFAULT_LINE_COLOR(colorScheme); + const selectedColor = getMostCommonColor(elements, colorScheme); const selectedMode = getMostCommonMode(elements); - const selectedLineSize = getMostCommonLineWidth(elements) ?? LineWidth.Four; + const selectedLineSize = getMostCommonLineWidth(elements); const selectedRough = getMostCommonRough(elements); - const selectedLineStyle = - getMostCommonLineStyle(elements) ?? StrokeStyle.Solid; - const selectedStartPointStyle = - getMostCommonEndpointStyle(elements, ConnectorEndpoint.Front) ?? - DEFAULT_FRONT_END_POINT_STYLE; - const selectedEndPointStyle = - getMostCommonEndpointStyle(elements, ConnectorEndpoint.Rear) ?? - DEFAULT_REAR_END_POINT_STYLE; + const selectedLineStyle = getMostCommonLineStyle(elements); + const selectedStartPointStyle = getMostCommonEndpointStyle( + elements, + ConnectorEndpoint.Front, + DEFAULT_FRONT_END_POINT_STYLE + ); + const selectedEndPointStyle = getMostCommonEndpointStyle( + elements, + ConnectorEndpoint.Rear, + DEFAULT_REAR_END_POINT_STYLE + ); return join( [ @@ -367,7 +370,8 @@ export class EdgelessChangeConnectorButton extends WithDisposable(LitElement) { .color=${selectedColor} .colors=${colors} .colorType=${type} - .palettes=${PALETTES} + .theme=${colorScheme} + .palettes=${DefaultTheme.palettes} .hollowCircle=${true} > <div @@ -383,7 +387,7 @@ export class EdgelessChangeConnectorButton extends WithDisposable(LitElement) { ${LineStylesPanel({ selectedLineSize: selectedLineSize, selectedLineStyle: selectedLineStyle, - onClick: (e: LineStyleEvent) => this._setConnectorStroke(e), + onClick: this._setConnectorStroke, })} </div> <editor-toolbar-separator @@ -408,13 +412,12 @@ export class EdgelessChangeConnectorButton extends WithDisposable(LitElement) { `} > <stroke-style-panel + .theme=${colorScheme} .strokeWidth=${selectedLineSize} .strokeStyle=${selectedLineStyle} .strokeColor=${selectedColor} - .setStrokeStyle=${(e: LineStyleEvent) => - this._setConnectorStroke(e)} - .setStrokeColor=${(e: ColorEvent) => - this._setConnectorColor(e.detail)} + .setStrokeStyle=${this._setConnectorStroke} + .setStrokeColor=${this._setConnectorColor} > </stroke-style-panel> </editor-menu-button> diff --git a/packages/blocks/src/root-block/widgets/element-toolbar/change-frame-button.ts b/packages/blocks/src/root-block/widgets/element-toolbar/change-frame-button.ts index d8b4b26a0eff..d1138c789ed0 100644 --- a/packages/blocks/src/root-block/widgets/element-toolbar/change-frame-button.ts +++ b/packages/blocks/src/root-block/widgets/element-toolbar/change-frame-button.ts @@ -8,9 +8,10 @@ import { renderToolbarSeparator } from '@blocksuite/affine-components/toolbar'; import { type ColorScheme, DEFAULT_NOTE_HEIGHT, + DefaultTheme, type FrameBlockModel, NoteDisplayMode, - PALETTES, + resolveColor, } from '@blocksuite/affine-model'; import { matchFlavours } from '@blocksuite/affine-shared/utils'; import { GfxExtensionIdentifier } from '@blocksuite/block-std/gfx'; @@ -41,30 +42,36 @@ import { mountFrameTitleEditor } from '../../edgeless/utils/text.js'; function getMostCommonColor( elements: FrameBlockModel[], colorScheme: ColorScheme -): string | null { +): string { const colors = countBy(elements, (ele: FrameBlockModel) => { - return typeof ele.background === 'object' - ? (ele.background[colorScheme] ?? ele.background.normal ?? null) - : ele.background; + return resolveColor(ele.background, colorScheme); }); const max = maxBy(Object.entries(colors), ([_k, count]) => count); - return max ? (max[0] as string) : null; + return max ? (max[0] as string) : 'transparent'; } export class EdgelessChangeFrameButton extends WithDisposable(LitElement) { - pickColor = (event: PickColorEvent) => { - if (event.type === 'pick') { - this.frames.forEach(ele => - this.service.updateElement( - ele.id, - packColor('background', { ...event.detail }) - ) - ); + private _setFrameBackground = (e: ColorEvent) => { + const background = e.detail.value; + this.frames.forEach(frame => { + this.service.updateElement(frame.id, { background }); + }); + }; + + pickColor = (e: PickColorEvent) => { + const field = 'background'; + + if (e.type === 'pick') { + const color = e.detail.value; + this.frames.forEach(ele => { + const props = packColor(field, color); + this.service.updateElement(ele.id, props); + }); return; } this.frames.forEach(ele => - ele[event.type === 'start' ? 'stash' : 'pop']('background') + ele[e.type === 'start' ? 'stash' : 'pop'](field) ); }; @@ -115,18 +122,12 @@ export class EdgelessChangeFrameButton extends WithDisposable(LitElement) { toast(this.edgeless.host, 'Frame has been inserted into doc'); } - private _setFrameBackground(color: string) { - this.frames.forEach(frame => { - this.service.updateElement(frame.id, { background: color }); - }); - } - protected override render() { const { frames } = this; const len = frames.length; const onlyOne = len === 1; const colorScheme = this.edgeless.surface.renderer.getColorScheme(); - const background = getMostCommonColor(frames, colorScheme) ?? 'transparent'; + const background = getMostCommonColor(frames, colorScheme); return join( [ @@ -199,7 +200,8 @@ export class EdgelessChangeFrameButton extends WithDisposable(LitElement) { .color=${background} .colors=${colors} .colorType=${type} - .palettes=${PALETTES} + .theme=${colorScheme} + .palettes=${DefaultTheme.palettes} > </edgeless-color-picker-button> `; @@ -220,8 +222,9 @@ export class EdgelessChangeFrameButton extends WithDisposable(LitElement) { > <edgeless-color-panel .value=${background} - .palettes=${PALETTES} - @select=${(e: ColorEvent) => this._setFrameBackground(e.detail)} + .theme=${colorScheme} + .palettes=${DefaultTheme.palettes} + @select=${this._setFrameBackground} > </edgeless-color-panel> </editor-menu-button> diff --git a/packages/blocks/src/root-block/widgets/element-toolbar/change-note-button.ts b/packages/blocks/src/root-block/widgets/element-toolbar/change-note-button.ts index 30387ecb3a28..ed9898891de1 100644 --- a/packages/blocks/src/root-block/widgets/element-toolbar/change-note-button.ts +++ b/packages/blocks/src/root-block/widgets/element-toolbar/change-note-button.ts @@ -13,10 +13,10 @@ import { } from '@blocksuite/affine-components/toolbar'; import { type ColorScheme, - DEFAULT_NOTE_BACKGROUND_COLOR, - NOTE_BACKGROUND_PALETTES, + DefaultTheme, type NoteBlockModel, NoteDisplayMode, + resolveColor, type StrokeStyle, } from '@blocksuite/affine-model'; import { ThemeProvider } from '@blocksuite/affine-shared/services'; @@ -68,17 +68,24 @@ const DisplayModeMap = { function getMostCommonBackground( elements: NoteBlockModel[], colorScheme: ColorScheme -): string | null { - const colors = countBy(elements, (ele: NoteBlockModel) => { - return typeof ele.background === 'object' - ? (ele.background[colorScheme] ?? ele.background.normal ?? null) - : ele.background; - }); +): string { + const colors = countBy(elements, (ele: NoteBlockModel) => + resolveColor(ele.background, colorScheme) + ); const max = maxBy(Object.entries(colors), ([_k, count]) => count); - return max ? (max[0] as string) : null; + return max + ? (max[0] as string) + : resolveColor(DefaultTheme.noteBackgrounColor, colorScheme); } export class EdgelessChangeNoteButton extends WithDisposable(LitElement) { + private _setBackground = (e: ColorEvent) => { + const background = e.detail.value; + this.notes.forEach(element => { + this.edgeless.service.updateElement(element.id, { background }); + }); + }; + private _setBorderRadius = (borderRadius: number) => { this.notes.forEach(note => { const props = { @@ -108,18 +115,19 @@ export class EdgelessChangeNoteButton extends WithDisposable(LitElement) { }); }; - pickColor = (event: PickColorEvent) => { - if (event.type === 'pick') { + pickColor = (e: PickColorEvent) => { + const field = 'background'; + + if (e.type === 'pick') { + const color = e.detail.value; this.notes.forEach(element => { - const props = packColor('background', { ...event.detail }); + const props = packColor(field, color); this.edgeless.service.updateElement(element.id, props); }); return; } - this.notes.forEach(ele => - ele[event.type === 'start' ? 'stash' : 'pop']('background') - ); + this.notes.forEach(ele => ele[e.type === 'start' ? 'stash' : 'pop'](field)); }; private get _advancedVisibilityEnabled() { @@ -141,12 +149,6 @@ export class EdgelessChangeNoteButton extends WithDisposable(LitElement) { this.edgeless.slots.toggleNoteSlicer.emit(); } - private _setBackground(background: string) { - this.notes.forEach(element => { - this.edgeless.service.updateElement(element.id, { background }); - }); - } - private _setCollapse() { this.notes.forEach(note => { const { collapse, collapsedHeight } = note.edgeless; @@ -258,9 +260,7 @@ export class EdgelessChangeNoteButton extends WithDisposable(LitElement) { const { shadowType, borderRadius, borderSize, borderStyle } = edgeless.style; const colorScheme = this.edgeless.surface.renderer.getColorScheme(); - const background = - getMostCommonBackground(this.notes, colorScheme) ?? - DEFAULT_NOTE_BACKGROUND_COLOR; + const background = getMostCommonBackground(this.notes, colorScheme); const { collapse } = edgeless; const scale = edgeless.scale ?? 1; @@ -316,7 +316,8 @@ export class EdgelessChangeNoteButton extends WithDisposable(LitElement) { .colorPanelClass=${'small'} .colorType=${type} .colors=${colors} - .palettes=${NOTE_BACKGROUND_PALETTES} + .theme=${colorScheme} + .palettes=${DefaultTheme.notePalettes} > </edgeless-color-picker-button> `; @@ -338,8 +339,9 @@ export class EdgelessChangeNoteButton extends WithDisposable(LitElement) { <edgeless-color-panel class="small" .value=${background} - .palettes=${NOTE_BACKGROUND_PALETTES} - @select=${(e: ColorEvent) => this._setBackground(e.detail)} + .theme=${colorScheme} + .palettes=${DefaultTheme.notePalettes} + @select=${this._setBackground} > </edgeless-color-panel> </editor-menu-button> diff --git a/packages/blocks/src/root-block/widgets/element-toolbar/change-shape-button.ts b/packages/blocks/src/root-block/widgets/element-toolbar/change-shape-button.ts index 93e7b50a411a..5fbaec0a9827 100644 --- a/packages/blocks/src/root-block/widgets/element-toolbar/change-shape-button.ts +++ b/packages/blocks/src/root-block/widgets/element-toolbar/change-shape-button.ts @@ -1,4 +1,5 @@ import type { + Color, ColorScheme, ShapeElementModel, ShapeProps, @@ -13,15 +14,15 @@ import { } from '@blocksuite/affine-components/icons'; import { renderToolbarSeparator } from '@blocksuite/affine-components/toolbar'; import { - DEFAULT_SHAPE_FILL_COLOR, - DEFAULT_SHAPE_STROKE_COLOR, + DefaultTheme, FontFamily, getShapeName, getShapeRadius, getShapeType, + isTransparent, LineWidth, MindmapElementModel, - PALETTES, + resolveColor, ShapeStyle, StrokeStyle, } from '@blocksuite/affine-model'; @@ -33,9 +34,11 @@ import { choose } from 'lit/directives/choose.js'; import { join } from 'lit/directives/join.js'; import { styleMap } from 'lit/directives/style-map.js'; import { when } from 'lit/directives/when.js'; +import isEqual from 'lodash.isequal'; import type { EdgelessColorPickerButton } from '../../edgeless/components/color-picker/button.js'; import type { PickColorEvent } from '../../edgeless/components/color-picker/types.js'; +import type { ColorEvent } from '../../edgeless/components/panel/color-panel.js'; import type { EdgelessShapePanel } from '../../edgeless/components/panel/shape-panel.js'; import type { EdgelessRootBlockComponent } from '../../edgeless/edgeless-root-block.js'; import type { ShapeToolOption } from '../../edgeless/gfx-tool/shape-tool.js'; @@ -44,20 +47,10 @@ import { packColor, packColorsWithColorScheme, } from '../../edgeless/components/color-picker/utils.js'; -import { - type ColorEvent, - GET_DEFAULT_LINE_COLOR, - isTransparent, -} from '../../edgeless/components/panel/color-panel.js'; import { type LineStyleEvent, LineStylesPanel, } from '../../edgeless/components/panel/line-styles-panel.js'; -import { - SHAPE_FILL_COLOR_BLACK, - SHAPE_TEXT_COLOR_PURE_BLACK, - SHAPE_TEXT_COLOR_PURE_WHITE, -} from '../../edgeless/utils/consts.js'; import { mountShapeTextEditor } from '../../edgeless/utils/text.js'; const changeShapeButtonStyles = [ @@ -89,62 +82,56 @@ const changeShapeButtonStyles = [ function getMostCommonFillColor( elements: ShapeElementModel[], colorScheme: ColorScheme -): string | null { - const colors = countBy(elements, (ele: ShapeElementModel) => { - if (ele.filled) { - return typeof ele.fillColor === 'object' - ? (ele.fillColor[colorScheme] ?? ele.fillColor.normal ?? null) - : ele.fillColor; - } - return 'transparent'; - }); +): string { + const colors = countBy(elements, (ele: ShapeElementModel) => + ele.filled ? resolveColor(ele.fillColor, colorScheme) : 'transparent' + ); const max = maxBy(Object.entries(colors), ([_k, count]) => count); - return max ? (max[0] as string) : null; + return max + ? (max[0] as string) + : resolveColor(DefaultTheme.shapeFillColor, colorScheme); } function getMostCommonStrokeColor( elements: ShapeElementModel[], colorScheme: ColorScheme -): string | null { - const colors = countBy(elements, (ele: ShapeElementModel) => { - return typeof ele.strokeColor === 'object' - ? (ele.strokeColor[colorScheme] ?? ele.strokeColor.normal ?? null) - : ele.strokeColor; - }); +): string { + const colors = countBy(elements, (ele: ShapeElementModel) => + resolveColor(ele.strokeColor, colorScheme) + ); const max = maxBy(Object.entries(colors), ([_k, count]) => count); - return max ? (max[0] as string) : null; + return max + ? (max[0] as string) + : resolveColor(DefaultTheme.shapeStrokeColor, colorScheme); } function getMostCommonShape( elements: ShapeElementModel[] ): ShapeToolOption['shapeName'] | null { - const shapeTypes = countBy(elements, (ele: ShapeElementModel) => { - return getShapeName(ele.shapeType, ele.radius); - }); + const shapeTypes = countBy(elements, (ele: ShapeElementModel) => + getShapeName(ele.shapeType, ele.radius) + ); const max = maxBy(Object.entries(shapeTypes), ([_k, count]) => count); return max ? (max[0] as ShapeToolOption['shapeName']) : null; } function getMostCommonLineSize(elements: ShapeElementModel[]): LineWidth { - const sizes = countBy(elements, (ele: ShapeElementModel) => { - return ele.strokeWidth; - }); + const sizes = countBy(elements, (ele: ShapeElementModel) => ele.strokeWidth); const max = maxBy(Object.entries(sizes), ([_k, count]) => count); return max ? (Number(max[0]) as LineWidth) : LineWidth.Four; } -function getMostCommonLineStyle( - elements: ShapeElementModel[] -): StrokeStyle | null { +function getMostCommonLineStyle(elements: ShapeElementModel[]): StrokeStyle { const sizes = countBy(elements, (ele: ShapeElementModel) => ele.strokeStyle); const max = maxBy(Object.entries(sizes), ([_k, count]) => count); - return max ? (max[0] as StrokeStyle) : null; + return max ? (max[0] as StrokeStyle) : StrokeStyle.Solid; } function getMostCommonShapeStyle(elements: ShapeElementModel[]): ShapeStyle { - const roughnesses = countBy(elements, (ele: ShapeElementModel) => { - return ele.shapeStyle; - }); + const roughnesses = countBy( + elements, + (ele: ShapeElementModel) => ele.shapeStyle + ); const max = maxBy(Object.entries(roughnesses), ([_k, count]) => count); return max ? (max[0] as ShapeStyle) : ShapeStyle.Scribbled; } @@ -152,62 +139,54 @@ function getMostCommonShapeStyle(elements: ShapeElementModel[]): ShapeStyle { export class EdgelessChangeShapeButton extends WithDisposable(LitElement) { static override styles = [changeShapeButtonStyles]; - get service() { - return this.edgeless.service; - } + private _setShapeFillColor = (e: ColorEvent) => { + const fillColor = e.detail.value; + const filled = !isTransparent(fillColor); + const color = this._getTextColor(fillColor, filled); + this.elements.forEach(ele => + this.service.updateElement(ele.id, { filled, fillColor, color }) + ); + }; - #pickColor<K extends keyof Pick<ShapeProps, 'fillColor' | 'strokeColor'>>( - key: K - ) { - return (event: PickColorEvent) => { - if (event.type === 'pick') { - this.elements.forEach(ele => { - const props = packColor(key, { ...event.detail }); - // If `filled` can be set separately, this logic can be removed - if (key === 'fillColor' && !ele.filled) { - Object.assign(props, { filled: true }); - } - this.service.updateElement(ele.id, props); - }); - return; - } + private _setShapeStrokeColor = (e: ColorEvent) => { + const strokeColor = e.detail.value; + this.elements.forEach(ele => + this.service.updateElement(ele.id, { strokeColor }) + ); + }; - this.elements.forEach(ele => - ele[event.type === 'start' ? 'stash' : 'pop'](key) - ); - }; + private _setShapeStyles = ({ type, value }: LineStyleEvent) => { + if (type === 'size') { + this._setShapeStrokeWidth(value); + return; + } + if (type === 'lineStyle') { + this._setShapeStrokeStyle(value); + } + }; + + get service() { + return this.edgeless.service; } private _addText() { mountShapeTextEditor(this.elements[0], this.edgeless); } - private _getTextColor(fillColor: string) { - const colorScheme = this.edgeless.surface.renderer.getColorScheme(); + private _getTextColor(fillColor: Color, isNotTransparent = false) { // When the shape is filled with black color, the text color should be white. // When the shape is transparent, the text color should be set according to the theme. // Otherwise, the text color should be black. - const textColor = isTransparent(fillColor) - ? GET_DEFAULT_LINE_COLOR(colorScheme) - : fillColor === SHAPE_FILL_COLOR_BLACK - ? SHAPE_TEXT_COLOR_PURE_WHITE - : SHAPE_TEXT_COLOR_PURE_BLACK; - return textColor; - } + if (isNotTransparent) { + if (isEqual(fillColor, DefaultTheme.black)) { + return DefaultTheme.white; + } else if (isEqual(fillColor, DefaultTheme.white)) { + return DefaultTheme.black; + } + } - private _setShapeFillColor(fillColor: string) { - const filled = !isTransparent(fillColor); - const color = this._getTextColor(fillColor); - this.elements.forEach(ele => - this.service.updateElement(ele.id, { filled, fillColor, color }) - ); - } - - private _setShapeStrokeColor(strokeColor: string) { - this.elements.forEach(ele => - this.service.updateElement(ele.id, { strokeColor }) - ); + return DefaultTheme.black; } private _setShapeStrokeStyle(strokeStyle: StrokeStyle) { @@ -231,16 +210,6 @@ export class EdgelessChangeShapeButton extends WithDisposable(LitElement) { }); } - private _setShapeStyles({ type, value }: LineStyleEvent) { - if (type === 'size') { - this._setShapeStrokeWidth(value); - return; - } - if (type === 'lineStyle') { - this._setShapeStrokeStyle(value); - } - } - private _showAddButtonOrTextMenu() { if (this.elements.length === 1 && !this.elements[0].text) { return 'button'; @@ -267,20 +236,38 @@ export class EdgelessChangeShapeButton extends WithDisposable(LitElement) { ); } + pickColor<K extends keyof Pick<ShapeProps, 'fillColor' | 'strokeColor'>>( + field: K + ) { + return (e: PickColorEvent) => { + if (e.type === 'pick') { + const color = e.detail.value; + this.elements.forEach(ele => { + const props = packColor(field, color); + // If `filled` can be set separately, this logic can be removed + if (field === 'fillColor' && !ele.filled) { + Object.assign(props, { filled: true }); + } + this.service.updateElement(ele.id, props); + }); + return; + } + + this.elements.forEach(ele => + ele[e.type === 'start' ? 'stash' : 'pop'](field) + ); + }; + } + override render() { const colorScheme = this.edgeless.surface.renderer.getColorScheme(); const elements = this.elements; const selectedShape = getMostCommonShape(elements); - const selectedFillColor = - getMostCommonFillColor(elements, colorScheme) ?? DEFAULT_SHAPE_FILL_COLOR; - const selectedStrokeColor = - getMostCommonStrokeColor(elements, colorScheme) ?? - DEFAULT_SHAPE_STROKE_COLOR; - const selectedLineSize = getMostCommonLineSize(elements) ?? LineWidth.Four; - const selectedLineStyle = - getMostCommonLineStyle(elements) ?? StrokeStyle.Solid; - const selectedShapeStyle = - getMostCommonShapeStyle(elements) ?? ShapeStyle.Scribbled; + const selectedFillColor = getMostCommonFillColor(elements, colorScheme); + const selectedStrokeColor = getMostCommonStrokeColor(elements, colorScheme); + const selectedLineSize = getMostCommonLineSize(elements); + const selectedLineStyle = getMostCommonLineStyle(elements); + const selectedShapeStyle = getMostCommonShapeStyle(elements); return join( [ @@ -337,11 +324,12 @@ export class EdgelessChangeShapeButton extends WithDisposable(LitElement) { <edgeless-color-picker-button class="fill-color" .label=${'Fill color'} - .pick=${this.#pickColor('fillColor')} + .pick=${this.pickColor('fillColor')} .color=${selectedFillColor} .colors=${colors} .colorType=${type} - .palettes=${PALETTES} + .theme=${colorScheme} + .palettes=${DefaultTheme.palettes} > </edgeless-color-picker-button> `; @@ -364,8 +352,9 @@ export class EdgelessChangeShapeButton extends WithDisposable(LitElement) { role="listbox" aria-label="Fill colors" .value=${selectedFillColor} - .palettes=${PALETTES} - @select=${(e: ColorEvent) => this._setShapeFillColor(e.detail)} + .theme=${colorScheme} + .palettes=${DefaultTheme.palettes} + @select=${this._setShapeFillColor} > </edgeless-color-panel> </editor-menu-button> @@ -385,11 +374,12 @@ export class EdgelessChangeShapeButton extends WithDisposable(LitElement) { <edgeless-color-picker-button class="border-style" .label=${'Border style'} - .pick=${this.#pickColor('strokeColor')} + .pick=${this.pickColor('strokeColor')} .color=${selectedStrokeColor} .colors=${colors} .colorType=${type} - .palettes=${PALETTES} + .theme=${colorScheme} + .palettes=${DefaultTheme.palettes} .hollowCircle=${true} > <div @@ -405,7 +395,7 @@ export class EdgelessChangeShapeButton extends WithDisposable(LitElement) { ${LineStylesPanel({ selectedLineSize: selectedLineSize, selectedLineStyle: selectedLineStyle, - onClick: (e: LineStyleEvent) => this._setShapeStyles(e), + onClick: this._setShapeStyles, })} </div> <editor-toolbar-separator @@ -431,14 +421,13 @@ export class EdgelessChangeShapeButton extends WithDisposable(LitElement) { `} > <stroke-style-panel + .theme=${colorScheme} .hollowCircle=${true} .strokeWidth=${selectedLineSize} .strokeStyle=${selectedLineStyle} .strokeColor=${selectedStrokeColor} - .setStrokeStyle=${(e: LineStyleEvent) => - this._setShapeStyles(e)} - .setStrokeColor=${(e: ColorEvent) => - this._setShapeStrokeColor(e.detail)} + .setStrokeStyle=${this._setShapeStyles} + .setStrokeColor=${this._setShapeStrokeColor} > </stroke-style-panel> </editor-menu-button> diff --git a/packages/blocks/src/root-block/widgets/element-toolbar/change-text-menu.ts b/packages/blocks/src/root-block/widgets/element-toolbar/change-text-menu.ts index a6b6254e56af..4e149d4438e9 100644 --- a/packages/blocks/src/root-block/widgets/element-toolbar/change-text-menu.ts +++ b/packages/blocks/src/root-block/widgets/element-toolbar/change-text-menu.ts @@ -12,16 +12,17 @@ import { import { renderToolbarSeparator } from '@blocksuite/affine-components/toolbar'; import { type ColorScheme, + DefaultTheme, FontFamily, FontStyle, FontWeight, + resolveColor, TextAlign, type TextStyleProps, } from '@blocksuite/affine-model'; import { ConnectorElementModel, EdgelessTextBlockModel, - PALETTES, ShapeElementModel, TextElementModel, } from '@blocksuite/affine-model'; @@ -41,16 +42,13 @@ import type { EdgelessColorPickerButton, PickColorEvent, } from '../../edgeless/components/color-picker/index.js'; +import type { ColorEvent } from '../../edgeless/components/panel/color-panel.js'; import type { EdgelessRootBlockComponent } from '../../edgeless/edgeless-root-block.js'; import { packColor, packColorsWithColorScheme, } from '../../edgeless/components/color-picker/utils.js'; -import { - type ColorEvent, - GET_DEFAULT_LINE_COLOR, -} from '../../edgeless/components/panel/color-panel.js'; const FONT_SIZE_LIST = [ { value: 16 }, @@ -123,12 +121,12 @@ function getMostCommonColor( const colors = countBy(elements, (ele: BlockSuite.EdgelessTextModelType) => { const color = ele instanceof ConnectorElementModel ? ele.labelStyle.color : ele.color; - return typeof color === 'object' - ? (color[colorScheme] ?? color.normal ?? null) - : color; + return resolveColor(color, colorScheme); }); const max = maxBy(Object.entries(colors), ([_k, count]) => count); - return max ? (max[0] as string) : GET_DEFAULT_LINE_COLOR(colorScheme); + return max + ? (max[0] as string) + : resolveColor(DefaultTheme.textColor, colorScheme); } function getMostCommonFontFamily(elements: BlockSuite.EdgelessTextModelType[]) { @@ -227,7 +225,8 @@ export class EdgelessChangeTextMenu extends WithDisposable(LitElement) { }); }; - private _setTextColor = ({ detail: color }: ColorEvent) => { + private _setTextColor = (e: ColorEvent) => { + const color = e.detail.value; const props = { color }; this.elements.forEach(element => { this.service.updateElement(element.id, buildProps(element, props)); @@ -303,10 +302,11 @@ export class EdgelessChangeTextMenu extends WithDisposable(LitElement) { // no need to update the bound of edgeless text block, which updates itself using ResizeObserver }; - pickColor = (event: PickColorEvent) => { - if (event.type === 'pick') { + pickColor = (e: PickColorEvent) => { + if (e.type === 'pick') { + const color = e.detail.value; this.elements.forEach(element => { - const props = packColor('color', { ...event.detail }); + const props = packColor('color', color); this.service.updateElement(element.id, buildProps(element, props)); this._updateElementBound(element); }); @@ -316,7 +316,7 @@ export class EdgelessChangeTextMenu extends WithDisposable(LitElement) { const key = this.elementType === 'connector' ? 'labelStyle' : 'color'; this.elements.forEach(ele => { // @ts-expect-error: FIXME - ele[event.type === 'start' ? 'stash' : 'pop'](key); + ele[e.type === 'start' ? 'stash' : 'pop'](key); }); }; @@ -388,7 +388,8 @@ export class EdgelessChangeTextMenu extends WithDisposable(LitElement) { .color=${selectedColor} .colors=${colors} .colorType=${type} - .palettes=${PALETTES} + .theme=${colorScheme} + .palettes=${DefaultTheme.palettes} > </edgeless-color-picker-button> `; @@ -409,6 +410,8 @@ export class EdgelessChangeTextMenu extends WithDisposable(LitElement) { > <edgeless-color-panel .value=${selectedColor} + .theme=${colorScheme} + .palettes=${DefaultTheme.palettes} @select=${this._setTextColor} ></edgeless-color-panel> </editor-menu-button> diff --git a/packages/blocks/src/root-block/widgets/frame-title/frame-title.ts b/packages/blocks/src/root-block/widgets/frame-title/frame-title.ts index 4bbce5327d1e..ff6512e15296 100644 --- a/packages/blocks/src/root-block/widgets/frame-title/frame-title.ts +++ b/packages/blocks/src/root-block/widgets/frame-title/frame-title.ts @@ -1,4 +1,8 @@ -import { ColorScheme, FrameBlockModel } from '@blocksuite/affine-model'; +import { + ColorScheme, + FrameBlockModel, + isTransparent, +} from '@blocksuite/affine-model'; import { ThemeProvider } from '@blocksuite/affine-shared/services'; import { type BlockStdScope, @@ -21,7 +25,6 @@ import { property, state } from 'lit/decorators.js'; import type { EdgelessRootService } from '../../edgeless/index.js'; import { parseStringToRgba } from '../../edgeless/components/color-picker/utils.js'; -import { isTransparent } from '../../edgeless/components/panel/color-panel.js'; import { frameTitleStyle, frameTitleStyleVars } from './styles.js'; export const AFFINE_FRAME_TITLE = 'affine-frame-title'; diff --git a/packages/blocks/src/root-block/widgets/pie-menu/base.ts b/packages/blocks/src/root-block/widgets/pie-menu/base.ts index 38dfb28d9139..339b683b7828 100644 --- a/packages/blocks/src/root-block/widgets/pie-menu/base.ts +++ b/packages/blocks/src/root-block/widgets/pie-menu/base.ts @@ -1,3 +1,4 @@ +import type { Color } from '@blocksuite/affine-model'; import type { TemplateResult } from 'lit'; import type { EdgelessRootBlockComponent } from '../../edgeless/edgeless-root-block.js'; @@ -69,10 +70,10 @@ export interface PieSubmenuNodeModel extends PieBaseNodeModel { export interface PieColorNodeModel extends PieBaseNodeModel { type: 'color'; - color: string; + color: Color; hollowCircle: boolean; text?: string; - onChange: (color: string, ctx: PieMenuContext) => void; + onChange: (color: Color, ctx: PieMenuContext) => void; } export type IPieNodeWithAction = diff --git a/packages/blocks/src/root-block/widgets/pie-menu/config.ts b/packages/blocks/src/root-block/widgets/pie-menu/config.ts index 03f1673b92bb..3e072e277ce9 100644 --- a/packages/blocks/src/root-block/widgets/pie-menu/config.ts +++ b/packages/blocks/src/root-block/widgets/pie-menu/config.ts @@ -24,17 +24,13 @@ import { ViewBarIcon, } from '@blocksuite/affine-components/icons'; import { + type Color, ConnectorMode, - LINE_COLORS, - SHAPE_FILL_COLORS, + DefaultTheme, ShapeStyle, ShapeType, - STROKE_COLORS, } from '@blocksuite/affine-model'; -import { - EditPropsStore, - type LastProps, -} from '@blocksuite/affine-shared/services'; +import { EditPropsStore } from '@blocksuite/affine-shared/services'; import { isControlledKeyboardEvent } from '@blocksuite/affine-shared/utils'; import { html } from 'lit'; import { styleMap } from 'lit/directives/style-map.js'; @@ -80,12 +76,12 @@ pie.expandableCommand({ pie.colorPicker({ label: 'Pen Color', active: getActiveConnectorStrokeColor, - onChange: (color: string, { rootComponent }: PieMenuContext) => { + onChange: (color: Color, { rootComponent }: PieMenuContext) => { rootComponent.std.get(EditPropsStore).recordLastProps('brush', { - color: color as LastProps['brush']['color'], + color: color, }); }, - colors: LINE_COLORS.map(color => ({ color })), + colors: DefaultTheme.palettes, }); }, }); @@ -216,12 +212,12 @@ pie.command({ pie.colorPicker({ label: 'Line Color', active: getActiveConnectorStrokeColor, - onChange: (color: string, { rootComponent }: PieMenuContext) => { + onChange: (color: Color, { rootComponent }: PieMenuContext) => { rootComponent.std.get(EditPropsStore).recordLastProps('connector', { - stroke: color as LastProps['connector']['stroke'], + stroke: color, }); }, - colors: LINE_COLORS.map(color => ({ color })), + colors: DefaultTheme.palettes, }); pie.endSubmenu(); @@ -312,26 +308,26 @@ pie.command({ pie.colorPicker({ label: 'Fill', active: getActiveShapeColor('fill'), - onChange: (color: string, { rootComponent }: PieMenuContext) => { + onChange: (color: Color, { rootComponent }: PieMenuContext) => { rootComponent.std.get(EditPropsStore).recordLastProps('shape:roundedRect', { - fillColor: color as LastProps['shape:roundedRect']['fillColor'], + fillColor: color, }); updateShapeOverlay(rootComponent); }, - colors: SHAPE_FILL_COLORS.map(color => ({ color })), + colors: DefaultTheme.palettes, }); pie.colorPicker({ label: 'Stroke', hollow: true, active: getActiveShapeColor('stroke'), - onChange: (color: string, { rootComponent }: PieMenuContext) => { + onChange: (color: Color, { rootComponent }: PieMenuContext) => { rootComponent.std.get(EditPropsStore).recordLastProps('shape:roundedRect', { - strokeColor: color as LastProps['shape:roundedRect']['strokeColor'], + strokeColor: color, }); updateShapeOverlay(rootComponent); }, - colors: STROKE_COLORS.map(color => ({ color, name: 'Color' })), + colors: DefaultTheme.palettes, }); pie.endSubmenu(); diff --git a/packages/blocks/src/root-block/widgets/pie-menu/pie-builder.ts b/packages/blocks/src/root-block/widgets/pie-menu/pie-builder.ts index 4e432730f9a2..0d7a8133a24c 100644 --- a/packages/blocks/src/root-block/widgets/pie-menu/pie-builder.ts +++ b/packages/blocks/src/root-block/widgets/pie-menu/pie-builder.ts @@ -1,3 +1,5 @@ +import type { Color, Palette } from '@blocksuite/affine-model'; + import { assertExists } from '@blocksuite/global/utils'; import { html } from 'lit'; @@ -16,11 +18,11 @@ import { calcNodeAngles, calcNodeWedges, isNodeWithChildren } from './utils.js'; export interface IPieColorPickerNodeProps { label: string; - active: (ctx: PieMenuContext) => string; + active: (ctx: PieMenuContext) => Color; onChange: PieColorNodeModel['onChange']; openOnHover?: PieSubmenuNodeModel['openOnHover']; hollow?: boolean; - colors: { color: string }[]; + colors: Palette[]; } type PieBuilderConstructorProps = Omit< @@ -131,17 +133,18 @@ export class PieMenuBuilder { label: props.label, role: 'color-picker', openOnHover: props.openOnHover ?? true, - children: props.colors.map(({ color }) => ({ + children: props.colors.map(palette => ({ icon: () => html`<edgeless-color-button class="large" - .color=${color} + .label=${palette.key} + .color=${palette.value} .hollowCircle=${hollow} ></edgeless-color-button>`, type: 'color', hollowCircle: hollow, - label: color, - color: color, + label: palette.key, + color: palette.value, onChange: props.onChange, })), }; diff --git a/packages/blocks/src/root-block/widgets/pie-menu/utils.ts b/packages/blocks/src/root-block/widgets/pie-menu/utils.ts index c349426a409e..b2612c8581b9 100644 --- a/packages/blocks/src/root-block/widgets/pie-menu/utils.ts +++ b/packages/blocks/src/root-block/widgets/pie-menu/utils.ts @@ -33,7 +33,7 @@ export function getActiveShapeColor(type: 'fill' | 'stroke') { 'shape:roundedRect' ]; const color = type == 'fill' ? props.fillColor : props.strokeColor; - return color.toString(); + return color; } return ''; }; @@ -46,7 +46,7 @@ export function getActiveConnectorStrokeColor({ const props = rootComponent.std.get(EditPropsStore).lastProps$.value.connector; const color = props.stroke; - return color.toString(); + return color; } return ''; } diff --git a/packages/blocks/src/surface-ref-block/portal/note.ts b/packages/blocks/src/surface-ref-block/portal/note.ts index 8058e2784081..27ead975c12f 100644 --- a/packages/blocks/src/surface-ref-block/portal/note.ts +++ b/packages/blocks/src/surface-ref-block/portal/note.ts @@ -2,7 +2,7 @@ import type { CanvasRenderer } from '@blocksuite/affine-block-surface'; import type { NoteBlockModel } from '@blocksuite/affine-model'; import { - DEFAULT_NOTE_BACKGROUND_COLOR, + DefaultTheme, NoteDisplayMode, NoteShadow, } from '@blocksuite/affine-model'; @@ -75,7 +75,7 @@ export class SurfaceRefNotePortal extends WithDisposable(ShadowlessElement) { const backgroundColor = this.host.std .get(ThemeProvider) - .generateColorProperty(model.background, DEFAULT_NOTE_BACKGROUND_COLOR); + .generateColorProperty(model.background, DefaultTheme.noteBackgrounColor); const [modelX, modelY, modelW, modelH] = deserializeXYWH(model.xywh); const style = { diff --git a/yarn.lock b/yarn.lock index c30ca876f720..ebc601e14f50 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1682,6 +1682,7 @@ __metadata: "@types/dompurify": "npm:^3.0.5" "@types/hast": "npm:^3.0.4" "@types/katex": "npm:^0.16.7" + "@types/lodash.isequal": "npm:^4.5.8" "@types/mdast": "npm:^4.0.4" collapse-white-space: "npm:^2.1.0" date-fns: "npm:^4.0.0" @@ -1692,6 +1693,7 @@ __metadata: html2canvas: "npm:^1.4.1" katex: "npm:^0.16.11" lit: "npm:^3.2.0" + lodash.isequal: "npm:^4.5.0" lz-string: "npm:^1.5.0" mdast-util-gfm-autolink-literal: "npm:^2.0.1" mdast-util-gfm-strikethrough: "npm:^2.0.0" @@ -4907,6 +4909,15 @@ __metadata: languageName: node linkType: hard +"@types/lodash.isequal@npm:^4.5.8": + version: 4.5.8 + resolution: "@types/lodash.isequal@npm:4.5.8" + dependencies: + "@types/lodash": "npm:*" + checksum: 10/f3180c2d2925514fff1908a1303c11468c9f39b47fd7b053416aad3f1447f8e4a9894dd0460187ac9ac19387e25aec8dd8214d13a50a0967e0dc9cca8e4c5353 + languageName: node + linkType: hard + "@types/lodash.ismatch@npm:^4.4.9": version: 4.4.9 resolution: "@types/lodash.ismatch@npm:4.4.9" @@ -10291,6 +10302,13 @@ __metadata: languageName: node linkType: hard +"lodash.isequal@npm:^4.5.0": + version: 4.5.0 + resolution: "lodash.isequal@npm:4.5.0" + checksum: 10/82fc58a83a1555f8df34ca9a2cd300995ff94018ac12cc47c349655f0ae1d4d92ba346db4c19bbfc90510764e0c00ddcc985a358bdcd4b3b965abf8f2a48a214 + languageName: node + linkType: hard + "lodash.ismatch@npm:^4.4.0": version: 4.4.0 resolution: "lodash.ismatch@npm:4.4.0"