import { LineWidth, StrokeStyle } from '@blocksuite/affine-model'; import { WithDisposable } from '@blocksuite/global/lit'; import { BanIcon, DashLineIcon, StraightLineIcon } from '@blocksuite/icons/lit'; import { css, html, LitElement } from 'lit'; import { property } from 'lit/decorators.js'; import { classMap } from 'lit/directives/class-map.js'; import { repeat } from 'lit/directives/repeat.js'; export type LineDetailType = | { type: 'size'; value: LineWidth; } | { type: 'style'; value: StrokeStyle; }; const LINE_STYLE_LIST = [ { key: 'Solid', value: StrokeStyle.Solid, icon: StraightLineIcon(), }, { key: 'Dash', value: StrokeStyle.Dash, icon: DashLineIcon(), }, { key: 'None', value: StrokeStyle.None, icon: BanIcon(), }, ]; export class EdgelessLineStylesPanel extends WithDisposable(LitElement) { static override styles = css` edgeless-line-width-panel { flex: 1; } `; select(detail: LineDetailType) { this.dispatchEvent( new CustomEvent('select', { detail, bubbles: true, composed: true, cancelable: true, }) ); } override render() { const { lineSize, lineStyle, lineStyles } = this; return html` ) => { e.stopPropagation(); this.select({ type: 'size', value: e.detail }); }} > ${repeat( LINE_STYLE_LIST.filter(item => lineStyles.includes(item.value)), item => item.value, ({ key, icon, value }) => { const active = lineStyle === value; const classInfo = { 'line-style-button': true, [`mode-${value}`]: true, }; if (active) classInfo['active'] = true; return html` this.select({ type: 'style', value })} > ${icon} `; } )} `; } @property({ attribute: false }) accessor lineStyle!: StrokeStyle; @property({ attribute: false }) accessor lineSize: LineWidth = LineWidth.Two; @property({ attribute: false }) accessor lineStyles: StrokeStyle[] = [ StrokeStyle.Solid, StrokeStyle.Dash, StrokeStyle.None, ]; } declare global { interface HTMLElementTagNameMap { 'edgeless-line-styles-panel': EdgelessLineStylesPanel; } }