refactor(editor): update surface-ref placeholder (#11440)
Close [BS-2996](https://linear.app/affine-design/issue/BS-2996/删除的-inserted-frame-需要更新样式)
This commit is contained in:
@@ -1 +1,2 @@
|
|||||||
|
export { SurfaceRefPlaceHolder } from './placeholder';
|
||||||
export { SurfaceRefToolbarTitle } from './surface-ref-toolbar-title';
|
export { SurfaceRefToolbarTitle } from './surface-ref-toolbar-title';
|
||||||
|
|||||||
@@ -0,0 +1,122 @@
|
|||||||
|
import { unsafeCSSVarV2 } from '@blocksuite/affine-shared/theme';
|
||||||
|
import { SignalWatcher, WithDisposable } from '@blocksuite/global/lit';
|
||||||
|
import { DeleteIcon } from '@blocksuite/icons/lit';
|
||||||
|
import { ShadowlessElement } from '@blocksuite/std';
|
||||||
|
import { type GfxModel } from '@blocksuite/std/gfx';
|
||||||
|
import { css, html, nothing } from 'lit';
|
||||||
|
import { property } from 'lit/decorators.js';
|
||||||
|
import { classMap } from 'lit/directives/class-map.js';
|
||||||
|
|
||||||
|
import { SurfaceRefNotFoundBackground } from '../icons';
|
||||||
|
import { getReferenceModelTitle, TYPE_ICON_MAP } from '../utils';
|
||||||
|
|
||||||
|
export class SurfaceRefPlaceHolder extends SignalWatcher(
|
||||||
|
WithDisposable(ShadowlessElement)
|
||||||
|
) {
|
||||||
|
static override styles = css`
|
||||||
|
.surface-ref-placeholder {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 12px;
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.surface-ref-placeholder.not-found {
|
||||||
|
background: ${unsafeCSSVarV2('layer/background/secondary', '#F5F5F5')};
|
||||||
|
}
|
||||||
|
|
||||||
|
.surface-ref-placeholder-heading {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
align-self: stretch;
|
||||||
|
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 22px;
|
||||||
|
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
color: ${unsafeCSSVarV2('text/primary', '#141414')};
|
||||||
|
}
|
||||||
|
|
||||||
|
.surface-ref-placeholder-body {
|
||||||
|
position: relative;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 20px;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
color: ${unsafeCSSVarV2('text/disable', '#7a7a7a')};
|
||||||
|
}
|
||||||
|
|
||||||
|
.surface-ref-not-found-background {
|
||||||
|
position: absolute;
|
||||||
|
right: 12px;
|
||||||
|
bottom: -5px;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
@property({ attribute: false })
|
||||||
|
accessor referenceModel: GfxModel | null = null;
|
||||||
|
|
||||||
|
@property({ attribute: false })
|
||||||
|
accessor refFlavour = '';
|
||||||
|
|
||||||
|
@property({ attribute: false })
|
||||||
|
accessor inEdgeless = false;
|
||||||
|
|
||||||
|
override render() {
|
||||||
|
const { referenceModel, refFlavour, inEdgeless } = this;
|
||||||
|
|
||||||
|
// When surface ref is in page mode and reference exists, don't render placeholder
|
||||||
|
if (referenceModel && !inEdgeless) return nothing;
|
||||||
|
|
||||||
|
const modelNotFound = !referenceModel;
|
||||||
|
const matchedType = TYPE_ICON_MAP[refFlavour] ?? TYPE_ICON_MAP['edgeless'];
|
||||||
|
|
||||||
|
const title =
|
||||||
|
(referenceModel && getReferenceModelTitle(referenceModel)) ??
|
||||||
|
matchedType.name;
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<div
|
||||||
|
class=${classMap({
|
||||||
|
'surface-ref-placeholder': true,
|
||||||
|
'not-found': modelNotFound,
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
${modelNotFound
|
||||||
|
? html`<div class="surface-ref-not-found-background">
|
||||||
|
${SurfaceRefNotFoundBackground}
|
||||||
|
</div>`
|
||||||
|
: nothing}
|
||||||
|
<div class="surface-ref-placeholder-heading">
|
||||||
|
${modelNotFound ? DeleteIcon() : matchedType.icon}
|
||||||
|
<span class="surface-ref-title">
|
||||||
|
${modelNotFound
|
||||||
|
? `This ${matchedType.name} not available`
|
||||||
|
: `${title}`}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="surface-ref-placeholder-body">
|
||||||
|
<span class="surface-ref-text">
|
||||||
|
${modelNotFound
|
||||||
|
? `The ${matchedType.name.toLowerCase()} is deleted or not in this doc.`
|
||||||
|
: `The ${matchedType.name.toLowerCase()} is inserted but cannot display in edgeless mode. Switch to page mode to view the block.`}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
'surface-ref-placeholder': SurfaceRefPlaceHolder;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -66,3 +66,9 @@ export class SurfaceRefToolbarTitle extends ShadowlessElement {
|
|||||||
return html`${icon}<span>${title}</span>`;
|
return html`${icon}<span>${title}</span>`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
'surface-ref-toolbar-title': SurfaceRefToolbarTitle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ export const surfaceRefToolbarModuleConfig: ToolbarModuleConfig = {
|
|||||||
actions: [
|
actions: [
|
||||||
{
|
{
|
||||||
id: 'a.surface-ref-title',
|
id: 'a.surface-ref-title',
|
||||||
|
when: ctx =>
|
||||||
|
!!ctx.getCurrentBlockByType(SurfaceRefBlockComponent)?.referenceModel,
|
||||||
content: ctx => {
|
content: ctx => {
|
||||||
const surfaceRefBlock = ctx.getCurrentBlockByType(
|
const surfaceRefBlock = ctx.getCurrentBlockByType(
|
||||||
SurfaceRefBlockComponent
|
SurfaceRefBlockComponent
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { SurfaceRefToolbarTitle } from './components';
|
import { SurfaceRefPlaceHolder, SurfaceRefToolbarTitle } from './components';
|
||||||
import { SurfaceRefGenericBlockPortal } from './portal/generic-block';
|
import { SurfaceRefGenericBlockPortal } from './portal/generic-block';
|
||||||
import { SurfaceRefNotePortal } from './portal/note';
|
import { SurfaceRefNotePortal } from './portal/note';
|
||||||
import { SurfaceRefBlockComponent } from './surface-ref-block';
|
import { SurfaceRefBlockComponent } from './surface-ref-block';
|
||||||
@@ -16,10 +16,5 @@ export function effects() {
|
|||||||
);
|
);
|
||||||
customElements.define('surface-ref-note-portal', SurfaceRefNotePortal);
|
customElements.define('surface-ref-note-portal', SurfaceRefNotePortal);
|
||||||
customElements.define('surface-ref-toolbar-title', SurfaceRefToolbarTitle);
|
customElements.define('surface-ref-toolbar-title', SurfaceRefToolbarTitle);
|
||||||
}
|
customElements.define('surface-ref-placeholder', SurfaceRefPlaceHolder);
|
||||||
|
|
||||||
declare global {
|
|
||||||
interface HTMLElementTagNameMap {
|
|
||||||
'surface-ref-toolbar-title': SurfaceRefToolbarTitle;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,52 +1,11 @@
|
|||||||
import { isFrameBlock } from '@blocksuite/affine-block-frame';
|
import { type SurfaceRefBlockModel } from '@blocksuite/affine-model';
|
||||||
import {
|
|
||||||
GroupElementModel,
|
|
||||||
type SurfaceRefBlockModel,
|
|
||||||
} from '@blocksuite/affine-model';
|
|
||||||
import { unsafeCSSVarV2 } from '@blocksuite/affine-shared/theme';
|
import { unsafeCSSVarV2 } from '@blocksuite/affine-shared/theme';
|
||||||
import {
|
import { BlockComponent, BlockSelection } from '@blocksuite/std';
|
||||||
DeleteIcon,
|
import { GfxControllerIdentifier, type GfxModel } from '@blocksuite/std/gfx';
|
||||||
EdgelessIcon,
|
import { css, html } from 'lit';
|
||||||
FrameIcon,
|
|
||||||
GroupIcon,
|
|
||||||
MindmapIcon,
|
|
||||||
} from '@blocksuite/icons/lit';
|
|
||||||
import { BlockComponent } from '@blocksuite/std';
|
|
||||||
import {
|
|
||||||
GfxControllerIdentifier,
|
|
||||||
type GfxModel,
|
|
||||||
isPrimitiveModel,
|
|
||||||
} from '@blocksuite/std/gfx';
|
|
||||||
import { css, html, nothing } from 'lit';
|
|
||||||
import { state } from 'lit/decorators.js';
|
import { state } from 'lit/decorators.js';
|
||||||
import { classMap } from 'lit/directives/class-map.js';
|
import { classMap } from 'lit/directives/class-map.js';
|
||||||
|
|
||||||
import { SurfaceRefNotFoundBackground } from './icons';
|
|
||||||
|
|
||||||
const TYPE_ICON_MAP: {
|
|
||||||
[key: string]: {
|
|
||||||
name: string;
|
|
||||||
icon: typeof DeleteIcon;
|
|
||||||
};
|
|
||||||
} = {
|
|
||||||
'affine:frame': {
|
|
||||||
name: 'Frame',
|
|
||||||
icon: FrameIcon,
|
|
||||||
},
|
|
||||||
group: {
|
|
||||||
name: 'Group',
|
|
||||||
icon: GroupIcon,
|
|
||||||
},
|
|
||||||
mindmap: {
|
|
||||||
name: 'Mind map',
|
|
||||||
icon: MindmapIcon,
|
|
||||||
},
|
|
||||||
edgeless: {
|
|
||||||
name: 'Edgeless content',
|
|
||||||
icon: EdgelessIcon,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export class EdgelessSurfaceRefBlockComponent extends BlockComponent<SurfaceRefBlockModel> {
|
export class EdgelessSurfaceRefBlockComponent extends BlockComponent<SurfaceRefBlockModel> {
|
||||||
static override styles = css`
|
static override styles = css`
|
||||||
affine-edgeless-surface-ref {
|
affine-edgeless-surface-ref {
|
||||||
@@ -58,50 +17,11 @@ export class EdgelessSurfaceRefBlockComponent extends BlockComponent<SurfaceRefB
|
|||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
border: 1px solid
|
border: 1px solid
|
||||||
${unsafeCSSVarV2('layer/insideBorder/border', '#e6e6e6')};
|
${unsafeCSSVarV2('layer/insideBorder/border', '#e6e6e6')};
|
||||||
padding: 12px;
|
margin: 18px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.affine-edgeless-surface-ref-container.not-found {
|
.affine-edgeless-surface-ref-container.focused {
|
||||||
background: ${unsafeCSSVarV2('layer/background/secondary', '#F5F5F5')};
|
border-color: ${unsafeCSSVarV2('edgeless/frame/border/active')};
|
||||||
}
|
|
||||||
|
|
||||||
.affine-edgeless-surface-ref-container .not-found-background {
|
|
||||||
position: absolute;
|
|
||||||
right: 12px;
|
|
||||||
bottom: -5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.edgeless-surface-ref-content {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.edgeless-surface-ref-content > .surface-ref-heading {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 8px;
|
|
||||||
align-self: stretch;
|
|
||||||
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 500;
|
|
||||||
line-height: 22px;
|
|
||||||
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
color: ${unsafeCSSVarV2('text/primary', '#141414')};
|
|
||||||
}
|
|
||||||
|
|
||||||
.edgeless-surface-ref-content > .surface-ref-heading svg {
|
|
||||||
color: ${unsafeCSSVarV2('text/primary', '#141414')};
|
|
||||||
}
|
|
||||||
|
|
||||||
.edgeless-surface-ref-content > .surface-ref-body {
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 400;
|
|
||||||
line-height: 20px;
|
|
||||||
color: ${unsafeCSSVarV2('text/disable', '#7a7a7a')};
|
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@@ -113,6 +33,18 @@ export class EdgelessSurfaceRefBlockComponent extends BlockComponent<SurfaceRefB
|
|||||||
) as GfxModel;
|
) as GfxModel;
|
||||||
|
|
||||||
this._referenceModel = elementModel;
|
this._referenceModel = elementModel;
|
||||||
|
this._initSelection();
|
||||||
|
}
|
||||||
|
|
||||||
|
private _initSelection() {
|
||||||
|
const selection = this.std.selection;
|
||||||
|
this._disposables.add(
|
||||||
|
selection.slots.changed.subscribe(selList => {
|
||||||
|
this._focused = selList.some(
|
||||||
|
sel => sel.blockId === this.blockId && sel.is(BlockSelection)
|
||||||
|
);
|
||||||
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
get gfx() {
|
get gfx() {
|
||||||
@@ -122,60 +54,21 @@ export class EdgelessSurfaceRefBlockComponent extends BlockComponent<SurfaceRefB
|
|||||||
@state()
|
@state()
|
||||||
accessor _referenceModel: GfxModel | null = null;
|
accessor _referenceModel: GfxModel | null = null;
|
||||||
|
|
||||||
private _renderRefContent(referenceModel: GfxModel | null) {
|
@state()
|
||||||
const modelNotFound = !referenceModel;
|
accessor _focused = false;
|
||||||
const flavourOrType = modelNotFound
|
|
||||||
? (this.model.props.refFlavour ?? 'edgeless')
|
|
||||||
: isPrimitiveModel(referenceModel)
|
|
||||||
? referenceModel.type
|
|
||||||
: referenceModel.flavour;
|
|
||||||
const matchedType =
|
|
||||||
TYPE_ICON_MAP[flavourOrType] ?? TYPE_ICON_MAP['edgeless'];
|
|
||||||
|
|
||||||
const title = modelNotFound
|
|
||||||
? matchedType.name
|
|
||||||
: isFrameBlock(referenceModel)
|
|
||||||
? referenceModel.props.title.toString()
|
|
||||||
: referenceModel instanceof GroupElementModel
|
|
||||||
? referenceModel.title.toString()
|
|
||||||
: matchedType.name;
|
|
||||||
|
|
||||||
return html`
|
|
||||||
<div class="edgeless-surface-ref-content">
|
|
||||||
<div class="surface-ref-heading">
|
|
||||||
${modelNotFound
|
|
||||||
? DeleteIcon({ width: '16px', height: '16px' })
|
|
||||||
: matchedType.icon({ width: '16px', height: '16px' })}
|
|
||||||
<span class="surface-ref-title">
|
|
||||||
${modelNotFound
|
|
||||||
? `This ${matchedType.name} not available`
|
|
||||||
: `${title}`}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="surface-ref-body">
|
|
||||||
<span class="surface-ref-text">
|
|
||||||
${modelNotFound
|
|
||||||
? `The ${matchedType.name.toLowerCase()} is deleted or not in this doc.`
|
|
||||||
: `The ${matchedType.name.toLowerCase()} is inserted but cannot display in edgeless mode. Switch to page mode to view the block.`}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
${modelNotFound
|
|
||||||
? html`<div class="not-found-background">
|
|
||||||
${SurfaceRefNotFoundBackground}
|
|
||||||
</div>`
|
|
||||||
: nothing}
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
override renderBlock() {
|
override renderBlock() {
|
||||||
return html` <div
|
return html` <div
|
||||||
class=${classMap({
|
class=${classMap({
|
||||||
'affine-edgeless-surface-ref-container': true,
|
'affine-edgeless-surface-ref-container': true,
|
||||||
'not-found': !this._referenceModel,
|
focused: this._focused,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
${this._renderRefContent(this._referenceModel)}
|
<surface-ref-placeholder
|
||||||
|
.referenceModel=${this._referenceModel}
|
||||||
|
.refFlavour=${this.model.props.refFlavour$.value}
|
||||||
|
.inEdgeless=${true}
|
||||||
|
></surface-ref-placeholder>
|
||||||
</div>`;
|
</div>`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ import {
|
|||||||
type SerializedXYWH,
|
type SerializedXYWH,
|
||||||
} from '@blocksuite/global/gfx';
|
} from '@blocksuite/global/gfx';
|
||||||
import { assertType } from '@blocksuite/global/utils';
|
import { assertType } from '@blocksuite/global/utils';
|
||||||
import { DeleteIcon } from '@blocksuite/icons/lit';
|
|
||||||
import {
|
import {
|
||||||
BlockComponent,
|
BlockComponent,
|
||||||
BlockSelection,
|
BlockSelection,
|
||||||
@@ -55,20 +54,9 @@ import { classMap } from 'lit/directives/class-map.js';
|
|||||||
import { guard } from 'lit/directives/guard.js';
|
import { guard } from 'lit/directives/guard.js';
|
||||||
import { styleMap } from 'lit/directives/style-map.js';
|
import { styleMap } from 'lit/directives/style-map.js';
|
||||||
|
|
||||||
import { noContentPlaceholder } from './utils.js';
|
@Peekable({
|
||||||
|
enableOn: (block: SurfaceRefBlockComponent) => !!block.referenceModel,
|
||||||
const NO_CONTENT_TITLE = {
|
})
|
||||||
'affine:frame': 'Frame',
|
|
||||||
group: 'Group',
|
|
||||||
DEFAULT: 'Content',
|
|
||||||
} as Record<string, string>;
|
|
||||||
|
|
||||||
const NO_CONTENT_REASON = {
|
|
||||||
group: 'This content was ungrouped or deleted on edgeless mode',
|
|
||||||
DEFAULT: 'This content was deleted on edgeless mode',
|
|
||||||
} as Record<string, string>;
|
|
||||||
|
|
||||||
@Peekable()
|
|
||||||
export class SurfaceRefBlockComponent extends BlockComponent<SurfaceRefBlockModel> {
|
export class SurfaceRefBlockComponent extends BlockComponent<SurfaceRefBlockModel> {
|
||||||
static override styles = css`
|
static override styles = css`
|
||||||
affine-surface-ref {
|
affine-surface-ref {
|
||||||
@@ -101,70 +89,6 @@ export class SurfaceRefBlockComponent extends BlockComponent<SurfaceRefBlockMode
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ref-placeholder {
|
|
||||||
padding: 26px 0px 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.placeholder-image {
|
|
||||||
margin: 0 auto;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.placeholder-text {
|
|
||||||
margin: 12px auto 0;
|
|
||||||
text-align: center;
|
|
||||||
font-size: 28px;
|
|
||||||
font-weight: 600;
|
|
||||||
line-height: 36px;
|
|
||||||
font-family: var(--affine-font-family);
|
|
||||||
}
|
|
||||||
|
|
||||||
.placeholder-action {
|
|
||||||
margin: 32px auto 0;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.delete-button {
|
|
||||||
width: 204px;
|
|
||||||
padding: 4px 18px;
|
|
||||||
|
|
||||||
display: inline-flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
gap: 4px;
|
|
||||||
|
|
||||||
border-radius: 8px;
|
|
||||||
border: 1px solid var(--affine-border-color);
|
|
||||||
|
|
||||||
font-family: var(--affine-font-family);
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 500;
|
|
||||||
line-height: 20px;
|
|
||||||
|
|
||||||
background-color: transparent;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.delete-button > .icon > svg {
|
|
||||||
color: var(--affine-icon-color);
|
|
||||||
width: 16px;
|
|
||||||
height: 16px;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.placeholder-reason {
|
|
||||||
margin: 72px auto 0;
|
|
||||||
padding: 10px;
|
|
||||||
|
|
||||||
text-align: center;
|
|
||||||
font-size: 12px;
|
|
||||||
font-family: var(--affine-font-family);
|
|
||||||
line-height: 20px;
|
|
||||||
|
|
||||||
color: var(--affine-warning-color);
|
|
||||||
background-color: var(--affine-background-error-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.ref-content {
|
.ref-content {
|
||||||
position: relative;
|
position: relative;
|
||||||
background-color: var(--affine-background-primary-color);
|
background-color: var(--affine-background-primary-color);
|
||||||
@@ -206,10 +130,6 @@ export class SurfaceRefBlockComponent extends BlockComponent<SurfaceRefBlockMode
|
|||||||
return this._referencedModel;
|
return this._referencedModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _deleteThis() {
|
|
||||||
this.doc.deleteBlock(this.model);
|
|
||||||
}
|
|
||||||
|
|
||||||
private _focusBlock() {
|
private _focusBlock() {
|
||||||
this.selection.update(() => {
|
this.selection.update(() => {
|
||||||
return [this.selection.create(BlockSelection, { blockId: this.blockId })];
|
return [this.selection.create(BlockSelection, { blockId: this.blockId })];
|
||||||
@@ -474,27 +394,6 @@ export class SurfaceRefBlockComponent extends BlockComponent<SurfaceRefBlockMode
|
|||||||
</div>`;
|
</div>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _renderRefPlaceholder(model: SurfaceRefBlockModel) {
|
|
||||||
return html`<div class="ref-placeholder">
|
|
||||||
<div class="placeholder-image">${noContentPlaceholder}</div>
|
|
||||||
<div class="placeholder-text">
|
|
||||||
No Such
|
|
||||||
${NO_CONTENT_TITLE[model.props.refFlavour ?? 'DEFAULT'] ??
|
|
||||||
NO_CONTENT_TITLE.DEFAULT}
|
|
||||||
</div>
|
|
||||||
<div class="placeholder-action">
|
|
||||||
<button class="delete-button" type="button" @click=${this._deleteThis}>
|
|
||||||
<span class="icon">${DeleteIcon()}</span
|
|
||||||
><span>Delete this block</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="placeholder-reason">
|
|
||||||
${NO_CONTENT_REASON[model.props.refFlavour ?? 'DEFAULT'] ??
|
|
||||||
NO_CONTENT_REASON.DEFAULT}
|
|
||||||
</div>
|
|
||||||
</div>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
readonly open = ({
|
readonly open = ({
|
||||||
openMode,
|
openMode,
|
||||||
event,
|
event,
|
||||||
@@ -537,7 +436,10 @@ export class SurfaceRefBlockComponent extends BlockComponent<SurfaceRefBlockMode
|
|||||||
const { _referencedModel, model } = this;
|
const { _referencedModel, model } = this;
|
||||||
const isEmpty = !_referencedModel || !_referencedModel.xywh;
|
const isEmpty = !_referencedModel || !_referencedModel.xywh;
|
||||||
const content = isEmpty
|
const content = isEmpty
|
||||||
? this._renderRefPlaceholder(model)
|
? html`<surface-ref-placeholder
|
||||||
|
.referenceModel=${_referencedModel}
|
||||||
|
.refFlavour=${model.props.refFlavour$.value}
|
||||||
|
></surface-ref-placeholder>`
|
||||||
: this._renderRefContent(_referencedModel);
|
: this._renderRefContent(_referencedModel);
|
||||||
const edgelessTheme = this.std.get(ThemeProvider).edgeless$.value;
|
const edgelessTheme = this.std.get(ThemeProvider).edgeless$.value;
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,23 @@
|
|||||||
|
import { isFrameBlock } from '@blocksuite/affine-block-frame';
|
||||||
import type { SurfaceBlockComponent } from '@blocksuite/affine-block-surface';
|
import type { SurfaceBlockComponent } from '@blocksuite/affine-block-surface';
|
||||||
import { ExportManager } from '@blocksuite/affine-block-surface';
|
import { ExportManager } from '@blocksuite/affine-block-surface';
|
||||||
import type { SurfaceRefBlockComponent } from '@blocksuite/affine-block-surface-ref';
|
import type { SurfaceRefBlockComponent } from '@blocksuite/affine-block-surface-ref';
|
||||||
|
import {
|
||||||
|
GroupElementModel,
|
||||||
|
MindmapElementModel,
|
||||||
|
ShapeElementModel,
|
||||||
|
} from '@blocksuite/affine-model';
|
||||||
import { BlockSuiteError } from '@blocksuite/global/exceptions';
|
import { BlockSuiteError } from '@blocksuite/global/exceptions';
|
||||||
import { Bound } from '@blocksuite/global/gfx';
|
import { Bound } from '@blocksuite/global/gfx';
|
||||||
import { assertType } from '@blocksuite/global/utils';
|
import { assertType } from '@blocksuite/global/utils';
|
||||||
import { GfxControllerIdentifier } from '@blocksuite/std/gfx';
|
import {
|
||||||
import { html } from 'lit';
|
EdgelessIcon,
|
||||||
|
FrameIcon,
|
||||||
|
GroupIcon,
|
||||||
|
MindmapIcon,
|
||||||
|
} from '@blocksuite/icons/lit';
|
||||||
|
import { GfxControllerIdentifier, type GfxModel } from '@blocksuite/std/gfx';
|
||||||
|
import { html, type TemplateResult } from 'lit';
|
||||||
|
|
||||||
export const noContentPlaceholder = html`
|
export const noContentPlaceholder = html`
|
||||||
<svg
|
<svg
|
||||||
@@ -144,3 +156,43 @@ export const surfaceRefToBlob = async (
|
|||||||
export const writeImageBlobToClipboard = async (blob: Blob) => {
|
export const writeImageBlobToClipboard = async (blob: Blob) => {
|
||||||
await navigator.clipboard.write([new ClipboardItem({ [blob.type]: blob })]);
|
await navigator.clipboard.write([new ClipboardItem({ [blob.type]: blob })]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const TYPE_ICON_MAP: {
|
||||||
|
[key: string]: {
|
||||||
|
name: string;
|
||||||
|
icon: TemplateResult;
|
||||||
|
};
|
||||||
|
} = {
|
||||||
|
'affine:frame': {
|
||||||
|
name: 'Frame',
|
||||||
|
icon: FrameIcon(),
|
||||||
|
},
|
||||||
|
group: {
|
||||||
|
name: 'Group',
|
||||||
|
icon: GroupIcon(),
|
||||||
|
},
|
||||||
|
mindmap: {
|
||||||
|
name: 'Mind map',
|
||||||
|
icon: MindmapIcon(),
|
||||||
|
},
|
||||||
|
edgeless: {
|
||||||
|
name: 'Edgeless content',
|
||||||
|
icon: EdgelessIcon(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getReferenceModelTitle = (model: GfxModel) => {
|
||||||
|
if (model instanceof GroupElementModel) {
|
||||||
|
return model.title.toString();
|
||||||
|
}
|
||||||
|
if (isFrameBlock(model)) {
|
||||||
|
return model.props.title.toString();
|
||||||
|
}
|
||||||
|
if (model instanceof MindmapElementModel) {
|
||||||
|
const rootElement = model.tree.element;
|
||||||
|
if (rootElement instanceof ShapeElementModel) {
|
||||||
|
return rootElement.text?.toString() ?? '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user