feat(editor): add highlighter (#10573)

Closes: [BS-2909](https://linear.app/affine-design/issue/BS-2909/新增highlighter)

### What's Changed!

Currently the highlighter tool is very similar to brush, but for the future, it's a standalone module.

* Added `Highlighter` element model
* Added `Highlighter` tool
* Added `Highlighter` entry to the global toolbar
This commit is contained in:
fundon
2025-03-27 08:53:26 +00:00
parent 676a8d653f
commit 2c4278058b
36 changed files with 1667 additions and 483 deletions
@@ -203,6 +203,12 @@ export class EdgelessColorPanel extends LitElement {
box-sizing: border-box;
background: var(--affine-background-overlay-panel-color);
}
:host(.one-way.small) {
display: flex;
gap: 4px;
background: unset;
}
`;
select(palette: Palette) {
@@ -221,14 +227,13 @@ export class EdgelessColorPanel extends LitElement {
}
override render() {
const resolvedValue = this.resolvedValue;
return html`
${repeat(
this.palettes,
palette => palette.key,
palette => {
const resolvedColor = resolveColor(palette.value, this.theme);
const activated = isEqual(resolvedColor, resolvedValue);
const activated = isEqual(resolvedColor, this.resolvedValue);
return html`<edgeless-color-button
class=${classMap({ large: true })}
.label=${palette.key}
@@ -340,3 +340,29 @@ export const calcCustomButtonStyle = (
return { '--b': b, '--c': c };
};
export const adjustColorAlpha = (color: Color, a: number): Color => {
let newColor;
if (typeof color === 'object') {
if ('normal' in color) {
const rgba = parseStringToRgba(color.normal);
rgba.a = a;
newColor = { normal: rgbaToHex8(rgba) };
} else {
const newDarkRgba = parseStringToRgba(color.dark);
newDarkRgba.a = a;
const newLightRgba = parseStringToRgba(color.light);
newLightRgba.a = a;
newColor = {
dark: rgbaToHex8(newDarkRgba),
light: rgbaToHex8(newLightRgba),
};
}
} else {
const rgba = parseStringToRgba(color);
rgba.a = a;
newColor = rgbaToHex8(rgba);
}
return newColor;
};
@@ -1,4 +1,4 @@
import { LINE_WIDTHS, LineWidth } from '@blocksuite/affine-model';
import { BRUSH_LINE_WIDTHS, LineWidth } from '@blocksuite/affine-model';
import { on, once } from '@blocksuite/affine-shared/utils';
import { WithDisposable } from '@blocksuite/global/lit';
import { css, html, LitElement, nothing, type PropertyValues } from 'lit';
@@ -122,7 +122,7 @@ export class EdgelessLineWidthPanel extends WithDisposable(LitElement) {
this._updateLineWidthPanelByDragHandlePosition(x);
};
private _onSelect(lineWidth: LineWidth) {
private _onSelect(lineWidth: number) {
// If the selected size is the same as the previous one, do nothing.
if (lineWidth === this.selectedSize) return;
this.dispatchEvent(
@@ -136,7 +136,7 @@ export class EdgelessLineWidthPanel extends WithDisposable(LitElement) {
this.selectedSize = lineWidth;
}
private _updateLineWidthPanel(selectedSize: LineWidth) {
private _updateLineWidthPanel(selectedSize: number) {
if (!this._lineWidthOverlay) return;
const index = this.lineWidths.findIndex(w => w === selectedSize);
if (index === -1) return;
@@ -221,7 +221,7 @@ export class EdgelessLineWidthPanel extends WithDisposable(LitElement) {
itemSize: 16,
itemIconSize: 8,
dragHandleSize: 14,
count: LINE_WIDTHS.length,
count: BRUSH_LINE_WIDTHS.length,
};
@property({ attribute: false, type: Boolean })
@@ -231,10 +231,10 @@ export class EdgelessLineWidthPanel extends WithDisposable(LitElement) {
accessor hasTooltip = true;
@property({ attribute: false })
accessor lineWidths: LineWidth[] = LINE_WIDTHS;
accessor lineWidths: number[] = BRUSH_LINE_WIDTHS;
@property({ attribute: false })
accessor selectedSize: LineWidth = LineWidth.Two;
accessor selectedSize: number = LineWidth.Two;
}
declare global {