feat(editor): gfx connector package (#11091)

This commit is contained in:
Saul-Mirone
2025-03-22 14:39:05 +00:00
parent d398ee4dfa
commit 1f0fc9d47a
38 changed files with 284 additions and 137 deletions

View File

@@ -0,0 +1,65 @@
import { ShapeStyle } from '@blocksuite/affine-model';
import { css, html, LitElement } from 'lit';
import { property } from 'lit/decorators.js';
import { repeat } from 'lit/directives/repeat.js';
import { Subject } from 'rxjs';
import type { ShapeTool } from '../shape-tool';
import { ShapeComponentConfig } from '../toolbar/shape-menu-config';
export class EdgelessShapePanel extends LitElement {
static override styles = css`
:host {
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
}
`;
slots = {
select: new Subject<ShapeTool['activatedOption']['shapeName']>(),
};
private _onSelect(value: ShapeTool['activatedOption']['shapeName']) {
this.selectedShape = value;
this.slots.select.next(value);
}
override disconnectedCallback(): void {
this.slots.select.complete();
super.disconnectedCallback();
}
override render() {
return repeat(
ShapeComponentConfig,
item => item.name,
({ name, generalIcon, scribbledIcon, tooltip, disabled }) =>
html`<edgeless-tool-icon-button
.disabled=${disabled}
.tooltip=${tooltip}
.active=${this.selectedShape === name}
.activeMode=${'background'}
.iconSize=${'20px'}
@click=${() => {
if (disabled) return;
this._onSelect(name);
}}
>
${this.shapeStyle === ShapeStyle.General
? generalIcon
: scribbledIcon}
</edgeless-tool-icon-button>`
);
}
@property({ attribute: false })
accessor selectedShape:
| ShapeTool['activatedOption']['shapeName']
| null
| undefined = undefined;
@property({ attribute: false })
accessor shapeStyle: ShapeStyle = ShapeStyle.Scribbled;
}

View File

@@ -0,0 +1,59 @@
import { ShapeStyle } from '@blocksuite/affine-model';
import { StyleGeneralIcon, StyleScribbleIcon } from '@blocksuite/icons/lit';
import { css, html, LitElement } from 'lit';
import { property } from 'lit/decorators.js';
import { repeat } from 'lit/directives/repeat.js';
const SHAPE_STYLE_LIST = [
{
value: ShapeStyle.General,
icon: StyleGeneralIcon(),
},
{
value: ShapeStyle.Scribbled,
icon: StyleScribbleIcon(),
},
];
export class EdgelessShapeStylePanel extends LitElement {
static override styles = css`
:host {
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
}
`;
private _onSelect(value: ShapeStyle) {
this.value = value;
if (this.onSelect) {
this.onSelect(value);
}
}
override render() {
return repeat(
SHAPE_STYLE_LIST,
item => item.value,
({ value, icon }) =>
html`<edgeless-tool-icon-button
.tipPosition=${'top'}
.activeMode=${'background'}
aria-label=${value}
.tooltip=${value}
.active=${this.value === value}
.iconSize=${'20px'}
@click=${() => this._onSelect(value)}
>
${icon}
</edgeless-tool-icon-button>`
);
}
@property({ attribute: false })
accessor onSelect: undefined | ((value: ShapeStyle) => void) = undefined;
@property({ attribute: false })
accessor value!: ShapeStyle;
}

View File

@@ -1,3 +1,5 @@
import { EdgelessShapePanel } from './components/shape-panel';
import { EdgelessShapeStylePanel } from './components/shape-style-panel';
import {
EdgelessShapeMenu,
EdgelessShapeToolButton,
@@ -18,6 +20,8 @@ export function effects() {
'edgeless-toolbar-shape-draggable',
EdgelessToolbarShapeDraggable
);
customElements.define('edgeless-shape-panel', EdgelessShapePanel);
customElements.define('edgeless-shape-style-panel', EdgelessShapeStylePanel);
}
declare global {
@@ -27,5 +31,7 @@ declare global {
'edgeless-shape-tool-element': EdgelessShapeToolElement;
'edgeless-toolbar-shape-draggable': EdgelessToolbarShapeDraggable;
'edgeless-shape-tool-button': EdgelessShapeToolButton;
'edgeless-shape-panel': EdgelessShapePanel;
'edgeless-shape-style-panel': EdgelessShapeStylePanel;
}
}