mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-26 23:02:57 +08:00
feat(editor): gfx connector package (#11091)
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
import { html } from 'lit';
|
||||
|
||||
export const NoteNoShadowIcon = html`
|
||||
<svg
|
||||
width="60"
|
||||
height="72"
|
||||
viewBox="0 0 60 72"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<rect width="60" height="72" />
|
||||
<rect
|
||||
x="0.5"
|
||||
y="0.5"
|
||||
width="58.0769"
|
||||
height="71"
|
||||
stroke="black"
|
||||
stroke-opacity="0.1"
|
||||
/>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M21.9576 26.8962L38.6423 43.5809C42.5269 38.9268 42.2845 31.993 37.9149 27.6235C33.5454 23.254 26.6117 23.0115 21.9576 26.8962ZM37.1193 45.1038L20.4346 28.4192C16.55 33.0732 16.7924 40.007 21.162 44.3765C25.5315 48.746 32.4652 48.9885 37.1193 45.1038ZM19.639 26.1005C25.1063 20.6332 33.9706 20.6332 39.4379 26.1005C44.9053 31.5678 44.9053 40.4322 39.4379 45.8995C33.9706 51.3668 25.1063 51.3668 19.639 45.8995C14.1716 40.4322 14.1716 31.5678 19.639 26.1005Z"
|
||||
fill="black"
|
||||
fill-opacity="0.1"
|
||||
/>
|
||||
</svg>
|
||||
`;
|
||||
|
||||
export const NoteShadowSampleIcon = html`
|
||||
<svg
|
||||
width="60"
|
||||
height="72"
|
||||
viewBox="0 0 60 72"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<rect width="60" height="72" />
|
||||
<rect
|
||||
x="9.23071"
|
||||
y="12.0771"
|
||||
width="32.3077"
|
||||
height="4.61538"
|
||||
rx="2"
|
||||
fill="black"
|
||||
fill-opacity="0.1"
|
||||
/>
|
||||
<rect
|
||||
x="9.23071"
|
||||
y="25.8462"
|
||||
width="40.6154"
|
||||
height="2.76923"
|
||||
rx="1.38462"
|
||||
fill="black"
|
||||
fill-opacity="0.1"
|
||||
/>
|
||||
<rect
|
||||
x="9.23071"
|
||||
y="35.6152"
|
||||
width="40.6154"
|
||||
height="2.76923"
|
||||
rx="1.38462"
|
||||
fill="black"
|
||||
fill-opacity="0.1"
|
||||
/>
|
||||
<rect
|
||||
x="9.23071"
|
||||
y="45.3843"
|
||||
width="40.6154"
|
||||
height="2.76923"
|
||||
rx="1.38462"
|
||||
fill="black"
|
||||
fill-opacity="0.1"
|
||||
/>
|
||||
<rect
|
||||
x="9.23071"
|
||||
y="55.1533"
|
||||
width="13.8462"
|
||||
height="2.76923"
|
||||
rx="1.38462"
|
||||
fill="black"
|
||||
fill-opacity="0.1"
|
||||
/>
|
||||
</svg>
|
||||
`;
|
||||
@@ -0,0 +1,104 @@
|
||||
import { NoteDisplayMode } from '@blocksuite/affine-model';
|
||||
import { stopPropagation } from '@blocksuite/affine-shared/utils';
|
||||
import { WithDisposable } from '@blocksuite/global/lit';
|
||||
import { EdgelessIcon, PageIcon } from '@blocksuite/icons/lit';
|
||||
import { css, html, LitElement } from 'lit';
|
||||
import { property } from 'lit/decorators.js';
|
||||
import { repeat } from 'lit/directives/repeat.js';
|
||||
|
||||
export class NoteDisplayModePanel extends WithDisposable(LitElement) {
|
||||
static override styles = css`
|
||||
:host {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
min-width: 180px;
|
||||
width: var(--panel-width);
|
||||
gap: 4px;
|
||||
}
|
||||
.item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 30px;
|
||||
padding: 4px 12px;
|
||||
border-radius: 4px;
|
||||
gap: 4px;
|
||||
box-sizing: border-box;
|
||||
cursor: pointer;
|
||||
}
|
||||
.item-label {
|
||||
flex: 1 1 0;
|
||||
}
|
||||
.item-icon {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
color: var(--affine-icon-color);
|
||||
|
||||
svg {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
}
|
||||
.item:hover,
|
||||
.item.selected {
|
||||
background-color: var(--affine-hover-color);
|
||||
}
|
||||
`;
|
||||
|
||||
private _DisplayModeIcon(mode: NoteDisplayMode) {
|
||||
switch (mode) {
|
||||
case NoteDisplayMode.DocAndEdgeless:
|
||||
return html`${PageIcon()} ${EdgelessIcon()}`;
|
||||
case NoteDisplayMode.DocOnly:
|
||||
return html`${PageIcon()}`;
|
||||
case NoteDisplayMode.EdgelessOnly:
|
||||
return html`${EdgelessIcon()}`;
|
||||
}
|
||||
}
|
||||
|
||||
private _DisplayModeLabel(mode: NoteDisplayMode) {
|
||||
switch (mode) {
|
||||
case NoteDisplayMode.DocAndEdgeless:
|
||||
return 'In Both';
|
||||
case NoteDisplayMode.DocOnly:
|
||||
return 'In Page Only';
|
||||
case NoteDisplayMode.EdgelessOnly:
|
||||
return 'In Edgeless Only';
|
||||
}
|
||||
}
|
||||
|
||||
override render() {
|
||||
this.style.setProperty('--panel-width', `${this.panelWidth}px`);
|
||||
|
||||
return repeat(
|
||||
Object.keys(NoteDisplayMode),
|
||||
mode => mode,
|
||||
mode => {
|
||||
const displayMode =
|
||||
NoteDisplayMode[mode as keyof typeof NoteDisplayMode];
|
||||
const isSelected = displayMode === this.displayMode;
|
||||
return html`<div
|
||||
class="item ${isSelected ? 'selected' : ''} ${displayMode}"
|
||||
@click=${() => this.onSelect(displayMode)}
|
||||
@dblclick=${stopPropagation}
|
||||
@pointerdown=${stopPropagation}
|
||||
>
|
||||
<div class="item-label">${this._DisplayModeLabel(displayMode)}</div>
|
||||
<div class="item-icon">${this._DisplayModeIcon(displayMode)}</div>
|
||||
</div>`;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@property({ attribute: false })
|
||||
accessor displayMode!: NoteDisplayMode;
|
||||
|
||||
@property({ attribute: false })
|
||||
accessor onSelect!: (displayMode: NoteDisplayMode) => void;
|
||||
|
||||
@property({ attribute: false })
|
||||
accessor panelWidth = 240;
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
import { ColorScheme, NoteShadow } from '@blocksuite/affine-model';
|
||||
import { WithDisposable } from '@blocksuite/global/lit';
|
||||
import { css, html, LitElement } from 'lit';
|
||||
import { property } from 'lit/decorators.js';
|
||||
import { repeat } from 'lit/directives/repeat.js';
|
||||
import { styleMap } from 'lit/directives/style-map.js';
|
||||
|
||||
import { NoteNoShadowIcon, NoteShadowSampleIcon } from './icons';
|
||||
|
||||
const SHADOWS = [
|
||||
{
|
||||
type: NoteShadow.None,
|
||||
styles: {
|
||||
light: '',
|
||||
dark: '',
|
||||
},
|
||||
tooltip: 'No shadow',
|
||||
},
|
||||
{
|
||||
type: NoteShadow.Box,
|
||||
styles: {
|
||||
light:
|
||||
'0px 0.2px 4.8px 0px rgba(66, 65, 73, 0.2), 0px 0px 1.6px 0px rgba(66, 65, 73, 0.2)',
|
||||
dark: '0px 0.2px 6px 0px rgba(0, 0, 0, 0.44), 0px 0px 2px 0px rgba(0, 0, 0, 0.66)',
|
||||
},
|
||||
tooltip: 'Box shadow',
|
||||
},
|
||||
{
|
||||
type: NoteShadow.Sticker,
|
||||
styles: {
|
||||
light:
|
||||
'0px 9.6px 10.4px -4px rgba(66, 65, 73, 0.07), 0px 10.4px 7.2px -8px rgba(66, 65, 73, 0.22)',
|
||||
dark: '0px 9.6px 10.4px -4px rgba(0, 0, 0, 0.66), 0px 10.4px 7.2px -8px rgba(0, 0, 0, 0.44)',
|
||||
},
|
||||
tooltip: 'Sticker shadow',
|
||||
},
|
||||
{
|
||||
type: NoteShadow.Paper,
|
||||
styles: {
|
||||
light:
|
||||
'0px 0px 0px 4px rgba(255, 255, 255, 1), 0px 1.2px 2.4px 4.8px rgba(66, 65, 73, 0.16)',
|
||||
dark: '0px 1.2px 2.4px 4.8px rgba(0, 0, 0, 0.36), 0px 0px 0px 3.4px rgba(75, 75, 75, 1)',
|
||||
},
|
||||
tooltip: 'Paper shadow',
|
||||
},
|
||||
{
|
||||
type: NoteShadow.Float,
|
||||
styles: {
|
||||
light:
|
||||
'0px 5.2px 12px 0px rgba(66, 65, 73, 0.13), 0px 0px 0.4px 1px rgba(0, 0, 0, 0.06)',
|
||||
dark: '0px 5.2px 12px 0px rgba(0, 0, 0, 0.66), 0px 0px 0.4px 1px rgba(0, 0, 0, 0.44)',
|
||||
},
|
||||
tooltip: 'Floation shadow',
|
||||
},
|
||||
{
|
||||
type: NoteShadow.Film,
|
||||
styles: {
|
||||
light:
|
||||
'0px 0px 0px 1.4px rgba(0, 0, 0, 1), 2.4px 2.4px 0px 1px rgba(0, 0, 0, 1)',
|
||||
dark: '0px 0px 0px 1.4px rgba(178, 178, 178, 1), 2.4px 2.4px 0px 1px rgba(178, 178, 178, 1)',
|
||||
},
|
||||
tooltip: 'Film shadow',
|
||||
},
|
||||
];
|
||||
|
||||
export class EdgelessNoteShadowPanel extends WithDisposable(LitElement) {
|
||||
static override styles = css`
|
||||
:host {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.item {
|
||||
padding: 8px;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.item-icon {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.item:hover {
|
||||
background-color: var(--affine-hover-color);
|
||||
}
|
||||
`;
|
||||
|
||||
override render() {
|
||||
return repeat(
|
||||
SHADOWS,
|
||||
shadow => shadow,
|
||||
(shadow, index) =>
|
||||
html`<style>
|
||||
.item-icon svg rect:first-of-type {
|
||||
fill: ${this.background.startsWith('--')
|
||||
? `var(${this.background})`
|
||||
: this.background};
|
||||
}
|
||||
</style>
|
||||
<div
|
||||
class="item"
|
||||
@click=${() => this.onSelect(shadow.type)}
|
||||
style=${styleMap({
|
||||
border:
|
||||
this.value === shadow.type
|
||||
? '1px solid var(--affine-brand-color)'
|
||||
: 'none',
|
||||
})}
|
||||
>
|
||||
<edgeless-tool-icon-button
|
||||
class="item-icon"
|
||||
data-testid=${shadow.type.replace('--', '')}
|
||||
.tooltip=${shadow.tooltip}
|
||||
.tipPosition=${'bottom'}
|
||||
.iconContainerPadding=${0}
|
||||
style=${styleMap({
|
||||
boxShadow: `${this.theme === ColorScheme.Dark ? shadow.styles.dark : shadow.styles.light}`,
|
||||
})}
|
||||
>
|
||||
${index === 0 ? NoteNoShadowIcon : NoteShadowSampleIcon}
|
||||
</edgeless-tool-icon-button>
|
||||
</div>`
|
||||
);
|
||||
}
|
||||
|
||||
@property({ attribute: false })
|
||||
accessor background!: string;
|
||||
|
||||
@property({ attribute: false })
|
||||
accessor onSelect!: (value: string) => void;
|
||||
|
||||
@property({ attribute: false })
|
||||
accessor theme!: ColorScheme;
|
||||
|
||||
@property({ attribute: false })
|
||||
accessor value!: string;
|
||||
}
|
||||
Reference in New Issue
Block a user