mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-29 16:19:43 +08:00
508 lines
10 KiB
TypeScript
508 lines
10 KiB
TypeScript
import { isEqual, last } from '@blocksuite/global/utils';
|
|
|
|
import { ConnectorMode } from '../../consts/connector.js';
|
|
import { MindmapStyle } from '../../consts/mindmap.js';
|
|
import { StrokeStyle } from '../../consts/note.js';
|
|
import { FontFamily, FontWeight, TextResizing } from '../../consts/text.js';
|
|
import { type Color, DefaultTheme } from '../../themes/index.js';
|
|
import type { MindmapNode } from './mindmap.js';
|
|
|
|
export type CollapseButton = {
|
|
width: number;
|
|
height: number;
|
|
radius: number;
|
|
|
|
filled: boolean;
|
|
fillColor: Color;
|
|
|
|
strokeColor: Color;
|
|
strokeWidth: number;
|
|
};
|
|
|
|
export type ExpandButton = CollapseButton & {
|
|
fontFamily: FontFamily;
|
|
fontSize: number;
|
|
fontWeight: FontWeight;
|
|
|
|
color: Color;
|
|
};
|
|
|
|
export type NodeStyle = {
|
|
radius: number;
|
|
|
|
strokeWidth: number;
|
|
strokeColor: Color;
|
|
|
|
textResizing: TextResizing;
|
|
|
|
fontSize: number;
|
|
fontFamily: string;
|
|
fontWeight: FontWeight;
|
|
color: Color;
|
|
|
|
filled: boolean;
|
|
fillColor: Color;
|
|
|
|
padding: [number, number];
|
|
|
|
shadow?: {
|
|
blur: number;
|
|
offsetX: number;
|
|
offsetY: number;
|
|
color: Color;
|
|
};
|
|
};
|
|
|
|
export type ConnectorStyle = {
|
|
strokeStyle: StrokeStyle;
|
|
stroke: Color;
|
|
strokeWidth: number;
|
|
|
|
mode: ConnectorMode;
|
|
};
|
|
|
|
export abstract class MindmapStyleGetter {
|
|
abstract readonly root: NodeStyle;
|
|
|
|
abstract getNodeStyle(
|
|
node: MindmapNode,
|
|
path: number[]
|
|
): {
|
|
connector: ConnectorStyle;
|
|
collapseButton: CollapseButton;
|
|
expandButton: ExpandButton;
|
|
node: NodeStyle;
|
|
};
|
|
}
|
|
|
|
export class StyleOne extends MindmapStyleGetter {
|
|
private readonly _colorOrders = [
|
|
DefaultTheme.StrokeColorMap.Purple,
|
|
DefaultTheme.StrokeColorMap.Magenta,
|
|
DefaultTheme.StrokeColorMap.Orange,
|
|
DefaultTheme.StrokeColorMap.Yellow,
|
|
DefaultTheme.StrokeColorMap.Green,
|
|
'#7ae2d5',
|
|
];
|
|
|
|
readonly root = {
|
|
radius: 8,
|
|
|
|
textResizing: TextResizing.AUTO_WIDTH_AND_HEIGHT,
|
|
|
|
strokeWidth: 4,
|
|
strokeColor: '#53b2ef',
|
|
|
|
fontFamily: FontFamily.Poppins,
|
|
fontSize: 20,
|
|
fontWeight: FontWeight.SemiBold,
|
|
color: DefaultTheme.pureBlack,
|
|
|
|
filled: true,
|
|
fillColor: DefaultTheme.pureWhite,
|
|
|
|
padding: [11, 22] as [number, number],
|
|
|
|
shadow: {
|
|
offsetX: 0,
|
|
offsetY: 6,
|
|
blur: 12,
|
|
color: 'rgba(0, 0, 0, 0.14)',
|
|
},
|
|
};
|
|
|
|
private _getColor(number: number) {
|
|
return this._colorOrders[number % this._colorOrders.length];
|
|
}
|
|
|
|
getNodeStyle(_: MindmapNode, path: number[]) {
|
|
const color = this._getColor(path[1] ?? 0);
|
|
|
|
return {
|
|
connector: {
|
|
strokeStyle: StrokeStyle.Solid,
|
|
stroke: color,
|
|
strokeWidth: 3,
|
|
|
|
mode: ConnectorMode.Curve,
|
|
},
|
|
collapseButton: {
|
|
width: 16,
|
|
height: 16,
|
|
radius: 0.5,
|
|
|
|
filled: true,
|
|
fillColor: DefaultTheme.pureWhite,
|
|
|
|
strokeColor: color,
|
|
strokeWidth: 3,
|
|
},
|
|
expandButton: {
|
|
width: 24,
|
|
height: 24,
|
|
radius: 8,
|
|
|
|
filled: true,
|
|
fillColor: color,
|
|
|
|
strokeColor: color,
|
|
strokeWidth: 0,
|
|
|
|
padding: [4, 0],
|
|
|
|
color: DefaultTheme.pureWhite,
|
|
|
|
fontFamily: FontFamily.Inter,
|
|
fontWeight: FontWeight.Bold,
|
|
fontSize: 15,
|
|
},
|
|
node: {
|
|
radius: 8,
|
|
|
|
textResizing: TextResizing.AUTO_WIDTH_AND_HEIGHT,
|
|
|
|
strokeWidth: 3,
|
|
strokeColor: color,
|
|
|
|
fontFamily: FontFamily.Poppins,
|
|
fontSize: 16,
|
|
fontWeight: FontWeight.Medium,
|
|
color: DefaultTheme.pureBlack,
|
|
|
|
filled: true,
|
|
fillColor: DefaultTheme.pureWhite,
|
|
|
|
padding: [6, 22] as [number, number],
|
|
|
|
shadow: {
|
|
offsetX: 0,
|
|
offsetY: 6,
|
|
blur: 12,
|
|
color: 'rgba(0, 0, 0, 0.14)',
|
|
},
|
|
},
|
|
};
|
|
}
|
|
}
|
|
export const styleOne = new StyleOne();
|
|
|
|
export class StyleTwo extends MindmapStyleGetter {
|
|
private readonly _colorOrders = [
|
|
DefaultTheme.StrokeColorMap.Blue,
|
|
'#7ae2d5',
|
|
DefaultTheme.StrokeColorMap.Yellow,
|
|
];
|
|
|
|
readonly root = {
|
|
radius: 3,
|
|
|
|
textResizing: TextResizing.AUTO_WIDTH_AND_HEIGHT,
|
|
|
|
strokeWidth: 3,
|
|
strokeColor: DefaultTheme.black,
|
|
|
|
fontFamily: FontFamily.Poppins,
|
|
fontSize: 18,
|
|
fontWeight: FontWeight.SemiBold,
|
|
color: DefaultTheme.pureBlack,
|
|
|
|
filled: true,
|
|
fillColor: DefaultTheme.StrokeColorMap.Yellow,
|
|
|
|
padding: [11, 22] as [number, number],
|
|
|
|
shadow: {
|
|
blur: 0,
|
|
offsetX: 3,
|
|
offsetY: 3,
|
|
color: DefaultTheme.black,
|
|
},
|
|
};
|
|
|
|
private _getColor(number: number) {
|
|
return number >= this._colorOrders.length
|
|
? last(this._colorOrders)!
|
|
: this._colorOrders[number];
|
|
}
|
|
|
|
getNodeStyle(_: MindmapNode, path: number[]) {
|
|
const color = this._getColor(path.length - 2);
|
|
|
|
return {
|
|
connector: {
|
|
strokeStyle: StrokeStyle.Solid,
|
|
stroke: DefaultTheme.black,
|
|
strokeWidth: 3,
|
|
|
|
mode: ConnectorMode.Orthogonal,
|
|
},
|
|
collapseButton: {
|
|
width: 16,
|
|
height: 16,
|
|
radius: 0.5,
|
|
|
|
filled: true,
|
|
fillColor: DefaultTheme.white,
|
|
|
|
strokeColor: DefaultTheme.black,
|
|
strokeWidth: 3,
|
|
},
|
|
expandButton: {
|
|
width: 24,
|
|
height: 24,
|
|
radius: 2,
|
|
|
|
filled: true,
|
|
fillColor: DefaultTheme.black,
|
|
|
|
padding: [4, 0],
|
|
|
|
strokeColor: DefaultTheme.black,
|
|
strokeWidth: 0,
|
|
|
|
color: DefaultTheme.white,
|
|
|
|
fontFamily: FontFamily.Inter,
|
|
fontWeight: FontWeight.Bold,
|
|
fontSize: 15,
|
|
},
|
|
node: {
|
|
radius: 3,
|
|
|
|
textResizing: TextResizing.AUTO_WIDTH_AND_HEIGHT,
|
|
|
|
strokeWidth: 3,
|
|
strokeColor: DefaultTheme.black,
|
|
|
|
fontFamily: FontFamily.Poppins,
|
|
fontSize: 16,
|
|
fontWeight: FontWeight.SemiBold,
|
|
color: DefaultTheme.pureBlack,
|
|
|
|
filled: true,
|
|
fillColor: color,
|
|
|
|
padding: [6, 22] as [number, number],
|
|
|
|
shadow: {
|
|
blur: 0,
|
|
offsetX: 3,
|
|
offsetY: 3,
|
|
color: DefaultTheme.black,
|
|
},
|
|
},
|
|
};
|
|
}
|
|
}
|
|
export const styleTwo = new StyleTwo();
|
|
|
|
export class StyleThree extends MindmapStyleGetter {
|
|
private readonly _strokeColor = [
|
|
DefaultTheme.StrokeColorMap.Yellow,
|
|
DefaultTheme.StrokeColorMap.Green,
|
|
'#5cc7ba',
|
|
];
|
|
|
|
readonly root = {
|
|
radius: 10,
|
|
|
|
textResizing: TextResizing.AUTO_WIDTH_AND_HEIGHT,
|
|
|
|
strokeWidth: 0,
|
|
strokeColor: 'transparent',
|
|
|
|
fontFamily: FontFamily.Poppins,
|
|
fontSize: 16,
|
|
fontWeight: FontWeight.Medium,
|
|
color: DefaultTheme.pureBlack,
|
|
|
|
filled: true,
|
|
fillColor: DefaultTheme.StrokeColorMap.Yellow,
|
|
|
|
padding: [10, 22] as [number, number],
|
|
|
|
shadow: {
|
|
blur: 12,
|
|
offsetX: 0,
|
|
offsetY: 0,
|
|
color: 'rgba(66, 65, 73, 0.18)',
|
|
},
|
|
};
|
|
|
|
private _getColor(number: number) {
|
|
return this._strokeColor[number % this._strokeColor.length];
|
|
}
|
|
|
|
override getNodeStyle(_: MindmapNode, path: number[]) {
|
|
const strokeColor = this._getColor(path.length - 2);
|
|
const dotColor = this._getColor(path.length - 1);
|
|
|
|
return {
|
|
node: {
|
|
radius: 10,
|
|
|
|
textResizing: TextResizing.AUTO_WIDTH_AND_HEIGHT,
|
|
|
|
strokeWidth: 2,
|
|
strokeColor,
|
|
|
|
fontFamily: FontFamily.Poppins,
|
|
fontSize: 16,
|
|
fontWeight: FontWeight.Medium,
|
|
color: DefaultTheme.pureBlack,
|
|
|
|
filled: true,
|
|
fillColor: DefaultTheme.pureWhite,
|
|
|
|
padding: [6, 22] as [number, number],
|
|
|
|
shadow: {
|
|
blur: 12,
|
|
offsetX: 0,
|
|
offsetY: 0,
|
|
color: 'rgba(66, 65, 73, 0.18)',
|
|
},
|
|
},
|
|
collapseButton: {
|
|
width: 16,
|
|
height: 16,
|
|
radius: 0.5,
|
|
|
|
filled: true,
|
|
fillColor: DefaultTheme.pureWhite,
|
|
|
|
strokeColor: dotColor,
|
|
strokeWidth: 3,
|
|
},
|
|
expandButton: {
|
|
width: 24,
|
|
height: 24,
|
|
radius: 8,
|
|
|
|
filled: true,
|
|
fillColor: dotColor,
|
|
|
|
padding: [4, 0],
|
|
|
|
strokeColor: dotColor,
|
|
strokeWidth: 0,
|
|
|
|
color: DefaultTheme.pureWhite,
|
|
|
|
fontFamily: FontFamily.Inter,
|
|
fontWeight: FontWeight.Bold,
|
|
fontSize: 15,
|
|
},
|
|
connector: {
|
|
strokeStyle: StrokeStyle.Solid,
|
|
stroke: strokeColor,
|
|
strokeWidth: 2,
|
|
|
|
mode: ConnectorMode.Curve,
|
|
},
|
|
};
|
|
}
|
|
}
|
|
export const styleThree = new StyleThree();
|
|
|
|
export class StyleFour extends MindmapStyleGetter {
|
|
private readonly _colors = [
|
|
DefaultTheme.StrokeColorMap.Purple,
|
|
DefaultTheme.StrokeColorMap.Magenta,
|
|
DefaultTheme.StrokeColorMap.Orange,
|
|
DefaultTheme.StrokeColorMap.Yellow,
|
|
DefaultTheme.StrokeColorMap.Green,
|
|
DefaultTheme.StrokeColorMap.Blue,
|
|
];
|
|
|
|
readonly root = {
|
|
radius: 0,
|
|
|
|
textResizing: TextResizing.AUTO_WIDTH_AND_HEIGHT,
|
|
|
|
strokeWidth: 0,
|
|
strokeColor: 'transparent',
|
|
|
|
fontFamily: FontFamily.Kalam,
|
|
fontSize: 22,
|
|
fontWeight: FontWeight.Bold,
|
|
color: DefaultTheme.black,
|
|
|
|
filled: true,
|
|
fillColor: 'transparent',
|
|
|
|
padding: [0, 10] as [number, number],
|
|
};
|
|
|
|
private _getColor(order: number) {
|
|
return this._colors[order % this._colors.length];
|
|
}
|
|
|
|
getNodeStyle(_: MindmapNode, path: number[]) {
|
|
const stroke = this._getColor(path[1] ?? 0);
|
|
|
|
return {
|
|
connector: {
|
|
strokeStyle: StrokeStyle.Solid,
|
|
stroke,
|
|
strokeWidth: 3,
|
|
|
|
mode: ConnectorMode.Curve,
|
|
},
|
|
collapseButton: {
|
|
width: 16,
|
|
height: 16,
|
|
radius: 0.5,
|
|
|
|
filled: true,
|
|
fillColor: DefaultTheme.pureWhite,
|
|
|
|
strokeColor: stroke,
|
|
strokeWidth: 3,
|
|
},
|
|
expandButton: {
|
|
width: 24,
|
|
height: 24,
|
|
radius: 8,
|
|
|
|
filled: true,
|
|
fillColor: stroke,
|
|
|
|
padding: [4, 0],
|
|
|
|
strokeColor: stroke,
|
|
strokeWidth: 0,
|
|
|
|
color: DefaultTheme.pureWhite,
|
|
|
|
fontFamily: FontFamily.Inter,
|
|
fontWeight: FontWeight.Bold,
|
|
fontSize: 15,
|
|
},
|
|
node: {
|
|
...this.root,
|
|
|
|
fontSize: 18,
|
|
padding: [1.5, 10] as [number, number],
|
|
},
|
|
};
|
|
}
|
|
}
|
|
export const styleFour = new StyleFour();
|
|
|
|
export const mindmapStyleGetters: Record<MindmapStyle, MindmapStyleGetter> = {
|
|
[MindmapStyle.ONE]: styleOne,
|
|
[MindmapStyle.TWO]: styleTwo,
|
|
[MindmapStyle.THREE]: styleThree,
|
|
[MindmapStyle.FOUR]: styleFour,
|
|
};
|
|
|
|
export const applyNodeStyle = (node: MindmapNode, nodeStyle: NodeStyle) => {
|
|
Object.entries(nodeStyle).forEach(([key, value]) => {
|
|
const element = node.element as unknown as Record<string, unknown>;
|
|
if (!isEqual(element[key], value)) {
|
|
element[key] = value;
|
|
}
|
|
});
|
|
};
|