refactor(editor): simplify color picker (#10776)

### What's Changed!

* Added `enableCustomColor` property into `EdgelessColorPickerButton` component
* Removed redundant code
This commit is contained in:
fundon
2025-03-12 05:17:04 +00:00
parent 4b5d1de206
commit d823792f85
8 changed files with 236 additions and 525 deletions

View File

@@ -3,10 +3,7 @@ import type {
EdgelessColorPickerButton, EdgelessColorPickerButton,
PickColorEvent, PickColorEvent,
} from '@blocksuite/affine-components/color-picker'; } from '@blocksuite/affine-components/color-picker';
import { import { packColor } from '@blocksuite/affine-components/color-picker';
packColor,
packColorsWithColorScheme,
} from '@blocksuite/affine-components/color-picker';
import type { import type {
BrushElementModel, BrushElementModel,
BrushProps, BrushProps,
@@ -18,11 +15,9 @@ import {
resolveColor, resolveColor,
} from '@blocksuite/affine-model'; } from '@blocksuite/affine-model';
import { FeatureFlagService } from '@blocksuite/affine-shared/services'; import { FeatureFlagService } from '@blocksuite/affine-shared/services';
import type { ColorEvent } from '@blocksuite/affine-shared/utils';
import { WithDisposable } from '@blocksuite/global/lit'; import { WithDisposable } from '@blocksuite/global/lit';
import { html, LitElement, nothing } from 'lit'; import { html, LitElement, nothing } from 'lit';
import { property, query } from 'lit/decorators.js'; import { property, query } from 'lit/decorators.js';
import { when } from 'lit/directives/when.js';
import countBy from 'lodash-es/countBy'; import countBy from 'lodash-es/countBy';
import maxBy from 'lodash-es/maxBy'; import maxBy from 'lodash-es/maxBy';
@@ -53,11 +48,6 @@ function notEqual<K extends keyof BrushProps>(key: K, value: BrushProps[K]) {
} }
export class EdgelessChangeBrushButton extends WithDisposable(LitElement) { export class EdgelessChangeBrushButton extends WithDisposable(LitElement) {
private readonly _setBrushColor = ({ detail }: ColorEvent) => {
const color = detail.value;
this._setBrushProp('color', color);
};
private readonly _setLineWidth = ({ detail: lineWidth }: LineWidthEvent) => { private readonly _setLineWidth = ({ detail: lineWidth }: LineWidthEvent) => {
this._setBrushProp('lineWidth', lineWidth); this._setBrushProp('lineWidth', lineWidth);
}; };
@@ -112,6 +102,9 @@ export class EdgelessChangeBrushButton extends WithDisposable(LitElement) {
const elements = this.elements; const elements = this.elements;
const selectedColor = getMostCommonColor(elements, colorScheme); const selectedColor = getMostCommonColor(elements, colorScheme);
const selectedSize = getMostCommonSize(elements); const selectedSize = getMostCommonSize(elements);
const enableCustomColor = this.edgeless.doc
.get(FeatureFlagService)
.getFlag('enable_color_picker');
return html` return html`
<edgeless-line-width-panel <edgeless-line-width-panel
@@ -122,51 +115,17 @@ export class EdgelessChangeBrushButton extends WithDisposable(LitElement) {
<editor-toolbar-separator></editor-toolbar-separator> <editor-toolbar-separator></editor-toolbar-separator>
${when(
this.edgeless.doc
.get(FeatureFlagService)
.getFlag('enable_color_picker'),
() => {
const { type, colors } = packColorsWithColorScheme(
colorScheme,
selectedColor,
elements[0].color
);
return html`
<edgeless-color-picker-button <edgeless-color-picker-button
class="color" class="color"
.label="${'Color'}" .label="${'Color'}"
.pick=${this.pickColor} .pick=${this.pickColor}
.color=${selectedColor} .color=${selectedColor}
.colors=${colors}
.colorType=${type}
.theme=${colorScheme} .theme=${colorScheme}
.originalColor=${elements[0].color}
.enableCustomColor=${enableCustomColor}
> >
</edgeless-color-picker-button> </edgeless-color-picker-button>
`; `;
},
() => html`
<editor-menu-button
.contentPadding=${'8px'}
.button=${html`
<editor-icon-button aria-label="Color" .tooltip=${'Color'}>
<edgeless-color-button
.color=${selectedColor}
></edgeless-color-button>
</editor-icon-button>
`}
>
<edgeless-color-panel
.value=${selectedColor}
.theme=${colorScheme}
@select=${this._setBrushColor}
>
</edgeless-color-panel>
</editor-menu-button>
`
)}
`;
} }
@query('edgeless-color-picker-button.color') @query('edgeless-color-picker-button.color')

View File

@@ -3,10 +3,7 @@ import type {
EdgelessColorPickerButton, EdgelessColorPickerButton,
PickColorEvent, PickColorEvent,
} from '@blocksuite/affine-components/color-picker'; } from '@blocksuite/affine-components/color-picker';
import { import { packColor } from '@blocksuite/affine-components/color-picker';
packColor,
packColorsWithColorScheme,
} from '@blocksuite/affine-components/color-picker';
import { renderToolbarSeparator } from '@blocksuite/affine-components/toolbar'; import { renderToolbarSeparator } from '@blocksuite/affine-components/toolbar';
import { import {
type ColorScheme, type ColorScheme,
@@ -24,7 +21,6 @@ import {
StrokeStyle, StrokeStyle,
} from '@blocksuite/affine-model'; } from '@blocksuite/affine-model';
import { FeatureFlagService } from '@blocksuite/affine-shared/services'; import { FeatureFlagService } from '@blocksuite/affine-shared/services';
import type { ColorEvent } from '@blocksuite/affine-shared/utils';
import { WithDisposable } from '@blocksuite/global/lit'; import { WithDisposable } from '@blocksuite/global/lit';
import { import {
AddTextIcon, AddTextIcon,
@@ -50,7 +46,6 @@ import { choose } from 'lit/directives/choose.js';
import { join } from 'lit/directives/join.js'; import { join } from 'lit/directives/join.js';
import { repeat } from 'lit/directives/repeat.js'; import { repeat } from 'lit/directives/repeat.js';
import { styleMap } from 'lit/directives/style-map.js'; import { styleMap } from 'lit/directives/style-map.js';
import { when } from 'lit/directives/when.js';
import countBy from 'lodash-es/countBy'; import countBy from 'lodash-es/countBy';
import maxBy from 'lodash-es/maxBy'; import maxBy from 'lodash-es/maxBy';
@@ -232,11 +227,6 @@ export class EdgelessChangeConnectorButton extends WithDisposable(LitElement) {
return this.edgeless.std.get(EdgelessCRUDIdentifier); return this.edgeless.std.get(EdgelessCRUDIdentifier);
} }
private readonly _setConnectorColor = (e: ColorEvent) => {
const stroke = e.detail.value;
this._setConnectorProp('stroke', stroke);
};
private readonly _setConnectorStroke = ({ type, value }: LineStyleEvent) => { private readonly _setConnectorStroke = ({ type, value }: LineStyleEvent) => {
if (type === 'size') { if (type === 'size') {
this._setConnectorStrokeWidth(value); this._setConnectorStrokeWidth(value);
@@ -358,30 +348,22 @@ export class EdgelessChangeConnectorButton extends WithDisposable(LitElement) {
ConnectorEndpoint.Rear, ConnectorEndpoint.Rear,
DEFAULT_REAR_END_POINT_STYLE DEFAULT_REAR_END_POINT_STYLE
); );
const enableCustomColor = this.edgeless.doc
.get(FeatureFlagService)
.getFlag('enable_color_picker');
return join( return join(
[ [
when( html`
this.edgeless.doc
.get(FeatureFlagService)
.getFlag('enable_color_picker'),
() => {
const { type, colors } = packColorsWithColorScheme(
colorScheme,
selectedColor,
elements[0].stroke
);
return html`
<edgeless-color-picker-button <edgeless-color-picker-button
class="stroke-color" class="stroke-color"
.label="${'Stroke style'}" .label="${'Stroke style'}"
.pick=${this.pickColor} .pick=${this.pickColor}
.color=${selectedColor} .color=${selectedColor}
.colors=${colors}
.colorType=${type}
.theme=${colorScheme} .theme=${colorScheme}
.hollowCircle=${true} .hollowCircle=${true}
.originalColor=${elements[0].stroke}
.enableCustomColor=${enableCustomColor}
> >
<div <div
slot="other" slot="other"
@@ -404,35 +386,7 @@ export class EdgelessChangeConnectorButton extends WithDisposable(LitElement) {
data-orientation="horizontal" data-orientation="horizontal"
></editor-toolbar-separator> ></editor-toolbar-separator>
</edgeless-color-picker-button> </edgeless-color-picker-button>
`; `,
},
() => html`
<editor-menu-button
.contentPadding=${'8px'}
.button=${html`
<editor-icon-button
aria-label="Stroke style"
.tooltip=${'Stroke style'}
.iconSize=${'20px'}
>
<edgeless-color-button
.color=${selectedColor}
></edgeless-color-button>
</editor-icon-button>
`}
>
<stroke-style-panel
.theme=${colorScheme}
.strokeWidth=${selectedLineSize}
.strokeStyle=${selectedLineStyle}
.strokeColor=${selectedColor}
.setStrokeStyle=${this._setConnectorStroke}
.setStrokeColor=${this._setConnectorColor}
>
</stroke-style-panel>
</editor-menu-button>
`
),
html` html`
<editor-menu-button <editor-menu-button

View File

@@ -4,10 +4,7 @@ import type {
EdgelessColorPickerButton, EdgelessColorPickerButton,
PickColorEvent, PickColorEvent,
} from '@blocksuite/affine-components/color-picker'; } from '@blocksuite/affine-components/color-picker';
import { import { packColor } from '@blocksuite/affine-components/color-picker';
packColor,
packColorsWithColorScheme,
} from '@blocksuite/affine-components/color-picker';
import { toast } from '@blocksuite/affine-components/toast'; import { toast } from '@blocksuite/affine-components/toast';
import { renderToolbarSeparator } from '@blocksuite/affine-components/toolbar'; import { renderToolbarSeparator } from '@blocksuite/affine-components/toolbar';
import { import {
@@ -19,7 +16,6 @@ import {
resolveColor, resolveColor,
} from '@blocksuite/affine-model'; } from '@blocksuite/affine-model';
import { FeatureFlagService } from '@blocksuite/affine-shared/services'; import { FeatureFlagService } from '@blocksuite/affine-shared/services';
import type { ColorEvent } from '@blocksuite/affine-shared/utils';
import { matchModels } from '@blocksuite/affine-shared/utils'; import { matchModels } from '@blocksuite/affine-shared/utils';
import { GfxExtensionIdentifier } from '@blocksuite/block-std/gfx'; import { GfxExtensionIdentifier } from '@blocksuite/block-std/gfx';
import { deserializeXYWH, serializeXYWH } from '@blocksuite/global/gfx'; import { deserializeXYWH, serializeXYWH } from '@blocksuite/global/gfx';
@@ -28,7 +24,6 @@ import { EditIcon, PageIcon, UngroupIcon } from '@blocksuite/icons/lit';
import { html, LitElement, nothing } from 'lit'; import { html, LitElement, nothing } from 'lit';
import { property, query } from 'lit/decorators.js'; import { property, query } from 'lit/decorators.js';
import { join } from 'lit/directives/join.js'; import { join } from 'lit/directives/join.js';
import { when } from 'lit/directives/when.js';
import countBy from 'lodash-es/countBy'; import countBy from 'lodash-es/countBy';
import maxBy from 'lodash-es/maxBy'; import maxBy from 'lodash-es/maxBy';
@@ -51,13 +46,6 @@ export class EdgelessChangeFrameButton extends WithDisposable(LitElement) {
return this.edgeless.std.get(EdgelessCRUDIdentifier); return this.edgeless.std.get(EdgelessCRUDIdentifier);
} }
private readonly _setFrameBackground = (e: ColorEvent) => {
const background = e.detail.value;
this.frames.forEach(frame => {
this.crud.updateElement(frame.id, { background });
});
};
pickColor = (e: PickColorEvent) => { pickColor = (e: PickColorEvent) => {
const field = 'background'; const field = 'background';
@@ -128,6 +116,9 @@ export class EdgelessChangeFrameButton extends WithDisposable(LitElement) {
const onlyOne = len === 1; const onlyOne = len === 1;
const colorScheme = this.edgeless.surface.renderer.getColorScheme(); const colorScheme = this.edgeless.surface.renderer.getColorScheme();
const background = getMostCommonColor(frames, colorScheme); const background = getMostCommonColor(frames, colorScheme);
const enableCustomColor = this.edgeless.doc
.get(FeatureFlagService)
.getFlag('enable_color_picker');
return join( return join(
[ [
@@ -183,53 +174,18 @@ export class EdgelessChangeFrameButton extends WithDisposable(LitElement) {
</editor-icon-button> </editor-icon-button>
`, `,
when( html`
this.edgeless.doc
.get(FeatureFlagService)
.getFlag('enable_color_picker'),
() => {
const { type, colors } = packColorsWithColorScheme(
colorScheme,
background,
this.frames[0].background
);
return html`
<edgeless-color-picker-button <edgeless-color-picker-button
class="background" class="background"
.label="${'Background'}" .label="${'Background'}"
.pick=${this.pickColor} .pick=${this.pickColor}
.color=${background} .color=${background}
.colors=${colors}
.colorType=${type}
.theme=${colorScheme} .theme=${colorScheme}
.originalColor=${this.frames[0].background}
.enableCustomColor=${enableCustomColor}
> >
</edgeless-color-picker-button> </edgeless-color-picker-button>
`; `,
},
() => html`
<editor-menu-button
.contentPadding=${'8px'}
.button=${html`
<editor-icon-button
aria-label="Background"
.tooltip=${'Background'}
>
<edgeless-color-button
.color=${background}
></edgeless-color-button>
</editor-icon-button>
`}
>
<edgeless-color-panel
.value=${background}
.theme=${colorScheme}
@select=${this._setFrameBackground}
>
</edgeless-color-panel>
</editor-menu-button>
`
),
].filter(button => button !== nothing), ].filter(button => button !== nothing),
renderToolbarSeparator renderToolbarSeparator
); );

View File

@@ -7,10 +7,7 @@ import type {
EdgelessColorPickerButton, EdgelessColorPickerButton,
PickColorEvent, PickColorEvent,
} from '@blocksuite/affine-components/color-picker'; } from '@blocksuite/affine-components/color-picker';
import { import { packColor } from '@blocksuite/affine-components/color-picker';
packColor,
packColorsWithColorScheme,
} from '@blocksuite/affine-components/color-picker';
import { import {
type EditorMenuButton, type EditorMenuButton,
renderToolbarSeparator, renderToolbarSeparator,
@@ -46,7 +43,6 @@ import { html, LitElement, nothing, type TemplateResult } from 'lit';
import { property, query } from 'lit/decorators.js'; import { property, query } from 'lit/decorators.js';
import { join } from 'lit/directives/join.js'; import { join } from 'lit/directives/join.js';
import { createRef, type Ref, ref } from 'lit/directives/ref.js'; import { createRef, type Ref, ref } from 'lit/directives/ref.js';
import { when } from 'lit/directives/when.js';
import countBy from 'lodash-es/countBy'; import countBy from 'lodash-es/countBy';
import maxBy from 'lodash-es/maxBy'; import maxBy from 'lodash-es/maxBy';
@@ -90,12 +86,6 @@ export class EdgelessChangeNoteButton extends WithDisposable(LitElement) {
return this.edgeless.std.get(EdgelessCRUDIdentifier); return this.edgeless.std.get(EdgelessCRUDIdentifier);
} }
private readonly _setBackground = (background: string) => {
this.notes.forEach(element => {
this.crud.updateElement(element.id, { background });
});
};
private readonly _setBorderRadius = (borderRadius: number) => { private readonly _setBorderRadius = (borderRadius: number) => {
this.notes.forEach(note => { this.notes.forEach(note => {
const props = { const props = {
@@ -348,6 +338,10 @@ export class EdgelessChangeNoteButton extends WithDisposable(LitElement) {
NoteConfigExtension.identifier NoteConfigExtension.identifier
)?.edgelessNoteHeader; )?.edgelessNoteHeader;
const enableCustomColor = this.edgeless.doc
.get(FeatureFlagService)
.getFlag('enable_color_picker');
const theme = this.edgeless.std.get(ThemeProvider).theme; const theme = this.edgeless.std.get(ThemeProvider).theme;
const buttonIconSize = { width: '20px', height: '20px' }; const buttonIconSize = { width: '20px', height: '20px' };
const buttons = [ const buttons = [
@@ -403,57 +397,20 @@ export class EdgelessChangeNoteButton extends WithDisposable(LitElement) {
isDocOnly isDocOnly
? nothing ? nothing
: when( : html`
this.edgeless.doc
.get(FeatureFlagService)
.getFlag('enable_color_picker'),
() => {
const { type, colors } = packColorsWithColorScheme(
colorScheme,
background,
note.background
);
return html`
<edgeless-color-picker-button <edgeless-color-picker-button
class="background" class="background"
.label=${'Background'} .label=${'Background'}
.pick=${this.pickColor} .pick=${this.pickColor}
.color=${background} .color=${background}
.colorPanelClass=${'small'} .colorPanelClass=${'small'}
.colorType=${type}
.colors=${colors}
.theme=${colorScheme} .theme=${colorScheme}
.palettes=${DefaultTheme.NoteBackgroundColorPalettes} .palettes=${DefaultTheme.NoteBackgroundColorPalettes}
.originalColor=${note.background}
.enableCustomColor=${enableCustomColor}
> >
</edgeless-color-picker-button> </edgeless-color-picker-button>
`; `,
},
() => html`
<editor-menu-button
.contentPadding=${'8px'}
.button=${html`
<editor-icon-button
aria-label="Background"
.tooltip=${'Background'}
>
<edgeless-color-button
.color=${background}
></edgeless-color-button>
</editor-icon-button>
`}
>
<edgeless-color-panel
class="small"
.value=${background}
.theme=${colorScheme}
.palettes=${DefaultTheme.NoteBackgroundColorPalettes}
@select=${this._setBackground}
>
</edgeless-color-panel>
</editor-menu-button>
`
),
isDocOnly isDocOnly
? nothing ? nothing

View File

@@ -3,10 +3,7 @@ import type {
EdgelessColorPickerButton, EdgelessColorPickerButton,
PickColorEvent, PickColorEvent,
} from '@blocksuite/affine-components/color-picker'; } from '@blocksuite/affine-components/color-picker';
import { import { packColor } from '@blocksuite/affine-components/color-picker';
packColor,
packColorsWithColorScheme,
} from '@blocksuite/affine-components/color-picker';
import { renderToolbarSeparator } from '@blocksuite/affine-components/toolbar'; import { renderToolbarSeparator } from '@blocksuite/affine-components/toolbar';
import type { import type {
Color, Color,
@@ -28,7 +25,6 @@ import {
StrokeStyle, StrokeStyle,
} from '@blocksuite/affine-model'; } from '@blocksuite/affine-model';
import { FeatureFlagService } from '@blocksuite/affine-shared/services'; import { FeatureFlagService } from '@blocksuite/affine-shared/services';
import type { ColorEvent } from '@blocksuite/affine-shared/utils';
import { WithDisposable } from '@blocksuite/global/lit'; import { WithDisposable } from '@blocksuite/global/lit';
import { import {
AddTextIcon, AddTextIcon,
@@ -42,7 +38,6 @@ import { cache } from 'lit/directives/cache.js';
import { choose } from 'lit/directives/choose.js'; import { choose } from 'lit/directives/choose.js';
import { join } from 'lit/directives/join.js'; import { join } from 'lit/directives/join.js';
import { styleMap } from 'lit/directives/style-map.js'; import { styleMap } from 'lit/directives/style-map.js';
import { when } from 'lit/directives/when.js';
import countBy from 'lodash-es/countBy'; import countBy from 'lodash-es/countBy';
import isEqual from 'lodash-es/isEqual'; import isEqual from 'lodash-es/isEqual';
import maxBy from 'lodash-es/maxBy'; import maxBy from 'lodash-es/maxBy';
@@ -143,22 +138,6 @@ function getMostCommonShapeStyle(elements: ShapeElementModel[]): ShapeStyle {
export class EdgelessChangeShapeButton extends WithDisposable(LitElement) { export class EdgelessChangeShapeButton extends WithDisposable(LitElement) {
static override styles = [changeShapeButtonStyles]; static override styles = [changeShapeButtonStyles];
private readonly _setShapeFillColor = (e: ColorEvent) => {
const fillColor = e.detail.value;
const filled = !isTransparent(fillColor);
const color = this._getTextColor(fillColor, filled);
this.elements.forEach(ele =>
this.crud.updateElement(ele.id, { filled, fillColor, color })
);
};
private readonly _setShapeStrokeColor = (e: ColorEvent) => {
const strokeColor = e.detail.value;
this.elements.forEach(ele =>
this.crud.updateElement(ele.id, { strokeColor })
);
};
private readonly _setShapeStyles = ({ type, value }: LineStyleEvent) => { private readonly _setShapeStyles = ({ type, value }: LineStyleEvent) => {
if (type === 'size') { if (type === 'size') {
this._setShapeStrokeWidth(value); this._setShapeStrokeWidth(value);
@@ -191,10 +170,15 @@ export class EdgelessChangeShapeButton extends WithDisposable(LitElement) {
return DefaultTheme.white; return DefaultTheme.white;
} else if (isEqual(fillColor, DefaultTheme.white)) { } else if (isEqual(fillColor, DefaultTheme.white)) {
return DefaultTheme.black; return DefaultTheme.black;
} else if (isEqual(fillColor, DefaultTheme.pureBlack)) {
return DefaultTheme.pureWhite;
} else if (isEqual(fillColor, DefaultTheme.pureWhite)) {
return DefaultTheme.pureBlack;
} }
} }
return DefaultTheme.black; // aka `DefaultTheme.pureBlack`
return DefaultTheme.shapeTextColor;
} }
private _setShapeStrokeStyle(strokeStyle: StrokeStyle) { private _setShapeStrokeStyle(strokeStyle: StrokeStyle) {
@@ -249,12 +233,14 @@ export class EdgelessChangeShapeButton extends WithDisposable(LitElement) {
) { ) {
return (e: PickColorEvent) => { return (e: PickColorEvent) => {
if (e.type === 'pick') { if (e.type === 'pick') {
const color = e.detail.value; const value = e.detail.value;
const filled = field === 'fillColor' && !isTransparent(value);
this.elements.forEach(ele => { this.elements.forEach(ele => {
const props = packColor(field, color); const props = packColor(field, value);
// If `filled` can be set separately, this logic can be removed // If `filled` can be set separately, this logic can be removed
if (field === 'fillColor' && !ele.filled) { if (field && !ele.filled) {
Object.assign(props, { filled: true }); const color = this._getTextColor(value, filled);
Object.assign(props, { filled, color });
} }
this.crud.updateElement(ele.id, props); this.crud.updateElement(ele.id, props);
}); });
@@ -277,6 +263,9 @@ export class EdgelessChangeShapeButton extends WithDisposable(LitElement) {
const selectedLineStyle = getMostCommonLineStyle(elements); const selectedLineStyle = getMostCommonLineStyle(elements);
const selectedShapeStyle = getMostCommonShapeStyle(elements); const selectedShapeStyle = getMostCommonShapeStyle(elements);
const iconSize = { width: '20px', height: '20px' }; const iconSize = { width: '20px', height: '20px' };
const enableCustomColor = this.edgeless.doc
.get(FeatureFlagService)
.getFlag('enable_color_picker');
return join( return join(
[ [
@@ -320,77 +309,29 @@ export class EdgelessChangeShapeButton extends WithDisposable(LitElement) {
</editor-menu-button> </editor-menu-button>
`, `,
when( html`
this.edgeless.doc
.get(FeatureFlagService)
.getFlag('enable_color_picker'),
() => {
const { type, colors } = packColorsWithColorScheme(
colorScheme,
selectedFillColor,
elements[0].fillColor
);
return html`
<edgeless-color-picker-button <edgeless-color-picker-button
class="fill-color" class="fill-color"
.label=${'Fill color'} .label="${'Fill color'}"
.pick=${this.pickColor('fillColor')} .pick=${this.pickColor('fillColor')}
.color=${selectedFillColor} .color=${selectedFillColor}
.colors=${colors}
.colorType=${type}
.theme=${colorScheme} .theme=${colorScheme}
.originalColor=${elements[0].fillColor}
.enableCustomColor=${enableCustomColor}
> >
</edgeless-color-picker-button> </edgeless-color-picker-button>
`; `,
},
() => html`
<editor-menu-button
.contentPadding=${'8px'}
.button=${html`
<editor-icon-button
aria-label="Fill color"
.tooltip=${'Fill color'}
>
<edgeless-color-button
.color=${selectedFillColor}
></edgeless-color-button>
</editor-icon-button>
`}
>
<edgeless-color-panel
role="listbox"
aria-label="Fill colors"
.value=${selectedFillColor}
.theme=${colorScheme}
@select=${this._setShapeFillColor}
>
</edgeless-color-panel>
</editor-menu-button>
`
),
when( html`
this.edgeless.doc
.get(FeatureFlagService)
.getFlag('enable_color_picker'),
() => {
const { type, colors } = packColorsWithColorScheme(
colorScheme,
selectedStrokeColor,
elements[0].strokeColor
);
return html`
<edgeless-color-picker-button <edgeless-color-picker-button
class="border-style" class="border-style"
.label=${'Border style'} .label="${'Border style'}"
.pick=${this.pickColor('strokeColor')} .pick=${this.pickColor('strokeColor')}
.color=${selectedStrokeColor} .color=${selectedStrokeColor}
.colors=${colors}
.colorType=${type}
.theme=${colorScheme} .theme=${colorScheme}
.hollowCircle=${true} .hollowCircle=${true}
.originalColor=${elements[0].strokeColor}
.enableCustomColor=${enableCustomColor}
> >
<div <div
slot="other" slot="other"
@@ -413,36 +354,7 @@ export class EdgelessChangeShapeButton extends WithDisposable(LitElement) {
data-orientation="horizontal" data-orientation="horizontal"
></editor-toolbar-separator> ></editor-toolbar-separator>
</edgeless-color-picker-button> </edgeless-color-picker-button>
`; `,
},
() => html`
<editor-menu-button
.contentPadding=${'8px'}
.button=${html`
<editor-icon-button
aria-label="Border style"
.tooltip=${'Border style'}
>
<edgeless-color-button
.color=${selectedStrokeColor}
.hollowCircle=${true}
></edgeless-color-button>
</editor-icon-button>
`}
>
<stroke-style-panel
.theme=${colorScheme}
.hollowCircle=${true}
.strokeWidth=${selectedLineSize}
.strokeStyle=${selectedLineStyle}
.strokeColor=${selectedStrokeColor}
.setStrokeStyle=${this._setShapeStyles}
.setStrokeColor=${this._setShapeStrokeColor}
>
</stroke-style-panel>
</editor-menu-button>
`
),
choose<string, TemplateResult<1> | typeof nothing>( choose<string, TemplateResult<1> | typeof nothing>(
this._showAddButtonOrTextMenu(), this._showAddButtonOrTextMenu(),

View File

@@ -8,10 +8,7 @@ import type {
EdgelessColorPickerButton, EdgelessColorPickerButton,
PickColorEvent, PickColorEvent,
} from '@blocksuite/affine-components/color-picker'; } from '@blocksuite/affine-components/color-picker';
import { import { packColor } from '@blocksuite/affine-components/color-picker';
packColor,
packColorsWithColorScheme,
} from '@blocksuite/affine-components/color-picker';
import { renderToolbarSeparator } from '@blocksuite/affine-components/toolbar'; import { renderToolbarSeparator } from '@blocksuite/affine-components/toolbar';
import { import {
type ColorScheme, type ColorScheme,
@@ -30,7 +27,6 @@ import {
type TextStyleProps, type TextStyleProps,
} from '@blocksuite/affine-model'; } from '@blocksuite/affine-model';
import { FeatureFlagService } from '@blocksuite/affine-shared/services'; import { FeatureFlagService } from '@blocksuite/affine-shared/services';
import type { ColorEvent } from '@blocksuite/affine-shared/utils';
import { Bound } from '@blocksuite/global/gfx'; import { Bound } from '@blocksuite/global/gfx';
import { WithDisposable } from '@blocksuite/global/lit'; import { WithDisposable } from '@blocksuite/global/lit';
import { import {
@@ -42,7 +38,6 @@ import { css, html, LitElement, nothing, type TemplateResult } from 'lit';
import { property, query } from 'lit/decorators.js'; import { property, query } from 'lit/decorators.js';
import { choose } from 'lit/directives/choose.js'; import { choose } from 'lit/directives/choose.js';
import { join } from 'lit/directives/join.js'; import { join } from 'lit/directives/join.js';
import { when } from 'lit/directives/when.js';
import countBy from 'lodash-es/countBy'; import countBy from 'lodash-es/countBy';
import maxBy from 'lodash-es/maxBy'; import maxBy from 'lodash-es/maxBy';
@@ -229,14 +224,6 @@ export class EdgelessChangeTextMenu extends WithDisposable(LitElement) {
}); });
}; };
private readonly _setTextColor = (e: ColorEvent) => {
const color = e.detail.value;
const props = { color };
this.elements.forEach(element => {
this.crud.updateElement(element.id, buildProps(element, props));
});
};
private readonly _updateElementBound = (element: SurfaceTextModel) => { private readonly _updateElementBound = (element: SurfaceTextModel) => {
const elementType = this.elementType; const elementType = this.elementType;
if (elementType === 'text' && element instanceof TextElementModel) { if (elementType === 'text' && element instanceof TextElementModel) {
@@ -346,6 +333,9 @@ export class EdgelessChangeTextMenu extends WithDisposable(LitElement) {
this.elementType === 'shape' this.elementType === 'shape'
? DefaultTheme.ShapeTextColorPalettes ? DefaultTheme.ShapeTextColorPalettes
: DefaultTheme.Palettes; : DefaultTheme.Palettes;
const enableCustomColor = this.edgeless.doc
.get(FeatureFlagService)
.getFlag('enable_color_picker');
return join( return join(
[ [
@@ -375,57 +365,22 @@ export class EdgelessChangeTextMenu extends WithDisposable(LitElement) {
</editor-menu-button> </editor-menu-button>
`, `,
when( html`
this.edgeless.doc
.get(FeatureFlagService)
.getFlag('enable_color_picker'),
() => {
const { type, colors } = packColorsWithColorScheme(
colorScheme,
selectedColor,
elements[0] instanceof ConnectorElementModel
? elements[0].labelStyle.color
: elements[0].color
);
return html`
<edgeless-color-picker-button <edgeless-color-picker-button
class="text-color" class="text-color"
.label="${'Text color'}" .label="${'Text color'}"
.pick=${this.pickColor} .pick=${this.pickColor}
.isText=${true} .isText=${true}
.color=${selectedColor} .color=${selectedColor}
.colors=${colors} .originalColor=${elements[0] instanceof ConnectorElementModel
.colorType=${type} ? elements[0].labelStyle.color
: elements[0].color}
.theme=${colorScheme} .theme=${colorScheme}
.palettes=${palettes} .palettes=${palettes}
.enableCustomColor=${enableCustomColor}
> >
</edgeless-color-picker-button> </edgeless-color-picker-button>
`; `,
},
() => html`
<editor-menu-button
.contentPadding=${'8px'}
.button=${html`
<editor-icon-button
aria-label="Text color"
.tooltip=${'Text color'}
>
<edgeless-text-color-icon
.color=${selectedColor}
></edgeless-text-color-icon>
</editor-icon-button>
`}
>
<edgeless-color-panel
.value=${selectedColor}
.theme=${colorScheme}
.palettes=${palettes}
@select=${this._setTextColor}
></edgeless-color-panel>
</editor-menu-button>
`
),
html` html`
<editor-menu-button <editor-menu-button

View File

@@ -1,4 +1,4 @@
import type { ColorScheme, Palette } from '@blocksuite/affine-model'; import type { Color, ColorScheme, Palette } from '@blocksuite/affine-model';
import { DefaultTheme, resolveColor } from '@blocksuite/affine-model'; import { DefaultTheme, resolveColor } from '@blocksuite/affine-model';
import type { ColorEvent } from '@blocksuite/affine-shared/utils'; import type { ColorEvent } from '@blocksuite/affine-shared/utils';
import { WithDisposable } from '@blocksuite/global/lit'; import { WithDisposable } from '@blocksuite/global/lit';
@@ -7,23 +7,28 @@ import { property, query, state } from 'lit/decorators.js';
import { choose } from 'lit/directives/choose.js'; import { choose } from 'lit/directives/choose.js';
import { ifDefined } from 'lit/directives/if-defined.js'; import { ifDefined } from 'lit/directives/if-defined.js';
import { styleMap } from 'lit/directives/style-map.js'; import { styleMap } from 'lit/directives/style-map.js';
import { when } from 'lit-html/directives/when.js';
import type { EditorMenuButton } from '../toolbar/menu-button.js'; import type { EditorMenuButton } from '../toolbar/menu-button';
import type { ModeType, PickColorEvent, PickColorType } from './types.js'; import type { PickColorEvent } from './types';
import { keepColor, preprocessColor, rgbaToHex8 } from './utils.js'; import {
keepColor,
packColorsWithColorScheme,
preprocessColor,
rgbaToHex8,
} from './utils.js';
type Type = 'normal' | 'custom'; type Type = 'normal' | 'custom';
export class EdgelessColorPickerButton extends WithDisposable(LitElement) { export class EdgelessColorPickerButton extends WithDisposable(LitElement) {
readonly #select = (e: ColorEvent) => { readonly #select = (e: ColorEvent) => {
e.stopPropagation();
this.#pick(e.detail); this.#pick(e.detail);
}; };
switchToCustomTab = (e: MouseEvent) => { switchToCustomTab = (e: MouseEvent) => {
e.stopPropagation(); e.stopPropagation();
if (this.colorType === 'palette') {
this.colorType = 'normal';
}
this.tabType = 'custom'; this.tabType = 'custom';
// refresh menu's position // refresh menu's position
this.menuButton.show(true); this.menuButton.show(true);
@@ -82,12 +87,16 @@ export class EdgelessColorPickerButton extends WithDisposable(LitElement) {
} }
override firstUpdated() { override firstUpdated() {
this.disposables.addFromEvent(this.menuButton, 'toggle', (e: Event) => { this.disposables.addFromEvent(
const opened = (e as CustomEvent<boolean>).detail; this.menuButton,
'toggle',
(e: CustomEvent<boolean>) => {
const opened = e.detail;
if (!opened && this.tabType !== 'normal') { if (!opened && this.tabType !== 'normal') {
this.tabType = 'normal'; this.tabType = 'normal';
} }
}); }
);
} }
override render() { override render() {
@@ -99,18 +108,20 @@ export class EdgelessColorPickerButton extends WithDisposable(LitElement) {
aria-label=${this.label} aria-label=${this.label}
.tooltip=${this.tooltip || this.label} .tooltip=${this.tooltip || this.label}
> >
${this.isText ${when(
? html` this.isText,
() => html`
<edgeless-text-color-icon <edgeless-text-color-icon
.color=${this.colorWithoutAlpha} .color=${this.colorWithoutAlpha}
></edgeless-text-color-icon> ></edgeless-text-color-icon>
` `,
: html` () => html`
<edgeless-color-button <edgeless-color-button
.color=${this.colorWithoutAlpha} .color=${this.colorWithoutAlpha}
.hollowCircle=${this.hollowCircle} .hollowCircle=${this.hollowCircle}
></edgeless-color-button> ></edgeless-color-button>
`} `
)}
</editor-icon-button> </editor-icon-button>
`} `}
> >
@@ -128,53 +139,60 @@ export class EdgelessColorPickerButton extends WithDisposable(LitElement) {
.theme=${this.theme} .theme=${this.theme}
.palettes=${this.palettes} .palettes=${this.palettes}
.hollowCircle=${this.hollowCircle} .hollowCircle=${this.hollowCircle}
.openColorPicker=${this.switchToCustomTab}
.hasTransparent=${false} .hasTransparent=${false}
@select=${this.#select} @select=${this.#select}
> >
${when(
this.enableCustomColor,
() => html`
<edgeless-color-custom-button <edgeless-color-custom-button
slot="custom" slot="custom"
style=${styleMap(this.customButtonStyle)} style=${styleMap(this.customButtonStyle)}
?active=${this.isCustomColor} ?active=${this.isCustomColor}
@click=${this.switchToCustomTab} @click=${this.switchToCustomTab}
></edgeless-color-custom-button> ></edgeless-color-custom-button>
`
)}
</edgeless-color-panel> </edgeless-color-panel>
</div> </div>
`, `,
], ],
[ [
'custom', 'custom',
() => html` () => {
const packed = packColorsWithColorScheme(
this.theme,
this.color,
this.originalColor
);
const type = packed.type === 'palette' ? 'normal' : packed.type;
const modes = packed.colors.map(
preprocessColor(window.getComputedStyle(this))
);
return html`
<edgeless-color-picker <edgeless-color-picker
class="custom" class="custom"
.pick=${this.pick} .pick=${this.pick}
.colors=${{ .colors=${{ type, modes }}
type:
this.colorType === 'palette' ? 'normal' : this.colorType,
modes: this.colors.map(
preprocessColor(window.getComputedStyle(this))
),
}}
></edgeless-color-picker> ></edgeless-color-picker>
`, `;
},
], ],
])} ])}
</editor-menu-button> </editor-menu-button>
`; `;
} }
@property()
accessor originalColor!: Color;
@property() @property()
accessor color!: string; accessor color!: string;
@property() @property()
accessor colorPanelClass: string | undefined = undefined; accessor colorPanelClass: string | undefined = undefined;
@property({ attribute: false })
accessor colors: { type: ModeType; value: string }[] = [];
@property()
accessor colorType: PickColorType = 'palette';
@property({ attribute: false }) @property({ attribute: false })
accessor hollowCircle: boolean = false; accessor hollowCircle: boolean = false;
@@ -201,4 +219,7 @@ export class EdgelessColorPickerButton extends WithDisposable(LitElement) {
@property() @property()
accessor tooltip: string | undefined = undefined; accessor tooltip: string | undefined = undefined;
@property()
accessor enableCustomColor: boolean = true;
} }

View File

@@ -253,9 +253,6 @@ export class EdgelessColorPanel extends LitElement {
@property({ attribute: false }) @property({ attribute: false })
accessor hollowCircle = false; accessor hollowCircle = false;
@property()
accessor openColorPicker!: (e: MouseEvent) => void;
@property({ type: Array }) @property({ type: Array })
accessor palettes: readonly Palette[] = DefaultTheme.Palettes; accessor palettes: readonly Palette[] = DefaultTheme.Palettes;