donteatfriedrice
2025-04-18 02:44:21 +00:00
parent dd51180acb
commit a555df0200
8 changed files with 44 additions and 62 deletions

View File

@@ -17,7 +17,7 @@ import {
ZERO_WIDTH_FOR_EMPTY_LINE,
} from '@blocksuite/std/inline';
import type { DeltaInsert } from '@blocksuite/store';
import { shift } from '@floating-ui/dom';
import { flip, offset, shift } from '@floating-ui/dom';
import { baseTheme } from '@toeverything/theme';
import { css, html, nothing, unsafeCSS } from 'lit';
import { property } from 'lit/decorators.js';
@@ -28,6 +28,8 @@ import type { FootNoteNodeConfigProvider } from './footnote-config';
// Virtual padding for the footnote popup overflow detection offsets.
const POPUP_SHIFT_PADDING = 8;
// The offset between the footnote node and the popup.
const POPUP_OFFSET = 4;
export class AffineFootnoteNode extends WithDisposable(ShadowlessElement) {
static override styles = css`
@@ -203,12 +205,16 @@ export class AffineFootnoteNode extends WithDisposable(ShadowlessElement) {
return {
template: this._FootNotePopup(footnote, abortController),
container: this,
container: this.std.host,
computePosition: {
referenceElement: this,
placement: 'top',
autoUpdate: true,
middleware: [shift({ padding: POPUP_SHIFT_PADDING })],
middleware: [
shift({ padding: POPUP_SHIFT_PADDING }),
flip(),
offset(POPUP_OFFSET),
],
},
};
},

View File

@@ -9,48 +9,42 @@ export class FootNotePopupChip extends LitElement {
border-radius: 4px;
max-width: 173px;
height: 24px;
padding: 2px 4px;
padding: 4px;
align-items: center;
gap: 4px;
gap: 8px;
box-sizing: border-box;
cursor: default;
transition: width 0.3s ease-in-out;
}
.prefix-icon,
.suffix-icon {
.prefix-icon {
display: flex;
align-items: center;
justify-content: center;
width: 16px;
height: 16px;
width: 16px;
color: ${unsafeCSSVarV2('icon/primary')};
border-radius: 4px;
svg,
object {
img {
width: 16px;
height: 16px;
fill: ${unsafeCSSVarV2('icon/primary')};
}
}
.suffix-icon:hover {
background-color: ${unsafeCSSVarV2('layer/background/hoverOverlay')};
cursor: pointer;
}
.popup-chip-label {
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
text-align: left;
height: 20px;
line-height: 20px;
height: 22px;
line-height: 22px;
color: ${unsafeCSSVarV2('text/primary')};
font-size: 12px;
font-weight: 400;
font-size: var(--affine-font-sm);
font-weight: 500;
}
`;
@@ -63,11 +57,6 @@ export class FootNotePopupChip extends LitElement {
</div>`
: nothing}
<div class="popup-chip-label" title=${this.tooltip}>${this.label}</div>
${this.suffixIcon
? html`<div class="suffix-icon" @click=${this.onSuffixClick}>
${this.suffixIcon}
</div>`
: nothing}
</div>
`;
}
@@ -78,9 +67,6 @@ export class FootNotePopupChip extends LitElement {
@property({ attribute: false })
accessor label: string = '';
@property({ attribute: false })
accessor suffixIcon: TemplateResult | undefined = undefined;
@property({ attribute: false })
accessor tooltip: string = '';
@@ -89,7 +75,4 @@ export class FootNotePopupChip extends LitElement {
@property({ attribute: false })
accessor onPrefixClick: (() => void) | undefined = undefined;
@property({ attribute: false })
accessor onSuffixClick: (() => void) | undefined = undefined;
}

View File

@@ -12,10 +12,9 @@ import {
} from '@blocksuite/affine-shared/services';
import { unsafeCSSVar, unsafeCSSVarV2 } from '@blocksuite/affine-shared/theme';
import { SignalWatcher, WithDisposable } from '@blocksuite/global/lit';
import { DualLinkIcon, LinkIcon } from '@blocksuite/icons/lit';
import type { BlockStdScope } from '@blocksuite/std';
import { computed, signal } from '@preact/signals-core';
import { css, html, LitElement, type TemplateResult } from 'lit';
import { css, html, LitElement } from 'lit';
import { property } from 'lit/decorators.js';
import type { FootNotePopupClickHandler } from './footnote-config';
@@ -56,36 +55,11 @@ export class FootNotePopup extends SignalWatcher(WithDisposable(LitElement)) {
}
const favicon = this._linkPreview$.value?.favicon;
if (!favicon) {
return undefined;
}
const titleIconType =
favicon.split('.').pop() === 'svg'
? 'svg+xml'
: favicon.split('.').pop();
const titleIcon = html`<object
type="image/${titleIconType}"
data=${favicon}
draggable="false"
>
${WebIcon16}
</object>`;
return titleIcon;
return favicon ? html`<img src=${favicon} alt="favicon" />` : WebIcon16;
}
return undefined;
});
private readonly _suffixIcon = (): TemplateResult | undefined => {
const referenceType = this.footnote.reference.type;
if (referenceType === 'doc') {
return DualLinkIcon({ width: '16px', height: '16px' });
} else if (referenceType === 'url') {
return LinkIcon({ width: '16px', height: '16px' });
}
return undefined;
};
private readonly _popupLabel$ = computed(() => {
const referenceType = this.footnote.reference.type;
let label = '';
@@ -157,7 +131,6 @@ export class FootNotePopup extends SignalWatcher(WithDisposable(LitElement)) {
<footnote-popup-chip
.prefixIcon=${this._prefixIcon$.value}
.label=${this._popupLabel$.value}
.suffixIcon=${this._suffixIcon()}
.onClick=${this._onChipClick}
.tooltip=${this._tooltip$.value}
></footnote-popup-chip>