mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-13 21:05:19 +00:00
refactor(editor): support virtual scroll for table view of database block (#11642)
close: BS-3378 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Introduced a modular virtualized table view with grouping, selection, drag-and-drop, clipboard support, and batch task management for optimized rendering. - Added comprehensive keyboard shortcuts, drag-to-fill functionality, and clipboard operations for efficient table editing. - Enabled dynamic column statistics, number formatting controls, and flexible switching between virtual and standard table views via a feature flag. - Provided detailed row and group header/footer components with context menus, row management actions, and column reordering/resizing. - Added a table view selector component to toggle between virtual and standard table views based on feature flags. - **Style** - Added extensive styling modules for virtual table elements including headers, footers, rows, cells, and interactive controls. - **Chores** - Registered numerous custom elements via modular effect functions to streamline component initialization. - Updated feature flag system to include virtual table scrolling toggle. - Added new dependencies to support styling and component functionality. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -14,7 +14,19 @@ import {
|
||||
} from '@blocksuite/icons/lit';
|
||||
import type { BlockModel } from '@blocksuite/store';
|
||||
import type { TemplateResult } from 'lit';
|
||||
|
||||
const icons: Record<string, TemplateResult> = {
|
||||
text: TextIcon(),
|
||||
quote: QuoteIcon(),
|
||||
h1: Heading1Icon(),
|
||||
h2: Heading2Icon(),
|
||||
h3: Heading3Icon(),
|
||||
h4: Heading4Icon(),
|
||||
h5: Heading5Icon(),
|
||||
h6: Heading6Icon(),
|
||||
bulleted: BulletedListIcon(),
|
||||
numbered: NumberedListIcon(),
|
||||
todo: CheckBoxCheckLinearIcon(),
|
||||
};
|
||||
export const getIcon = (
|
||||
model: BlockModel & {
|
||||
props: {
|
||||
@@ -24,27 +36,10 @@ export const getIcon = (
|
||||
): TemplateResult => {
|
||||
if (model.flavour === 'affine:paragraph') {
|
||||
const type = model.props.type as ParagraphType;
|
||||
return (
|
||||
{
|
||||
text: TextIcon(),
|
||||
quote: QuoteIcon(),
|
||||
h1: Heading1Icon(),
|
||||
h2: Heading2Icon(),
|
||||
h3: Heading3Icon(),
|
||||
h4: Heading4Icon(),
|
||||
h5: Heading5Icon(),
|
||||
h6: Heading6Icon(),
|
||||
} as Record<ParagraphType, TemplateResult>
|
||||
)[type];
|
||||
return icons[type] ?? TextIcon();
|
||||
}
|
||||
if (model.flavour === 'affine:list') {
|
||||
return (
|
||||
{
|
||||
bulleted: BulletedListIcon(),
|
||||
numbered: NumberedListIcon(),
|
||||
todo: CheckBoxCheckLinearIcon(),
|
||||
}[model.props.type ?? 'bulleted'] ?? BulletedListIcon()
|
||||
);
|
||||
return icons[model.props.type ?? 'bulleted'] ?? BulletedListIcon();
|
||||
}
|
||||
return TextIcon();
|
||||
};
|
||||
|
||||
@@ -71,11 +71,15 @@ export class DatabaseBlockDataSource extends DataSourceBase {
|
||||
|
||||
override featureFlags$: ReadonlySignal<DatabaseFlags> = computed(() => {
|
||||
const featureFlagService = this.doc.get(FeatureFlagService);
|
||||
const flag = featureFlagService.getFlag(
|
||||
const enableNumberFormat = featureFlagService.getFlag(
|
||||
'enable_database_number_formatting'
|
||||
);
|
||||
const enableTableVirtualScroll = featureFlagService.getFlag(
|
||||
'enable_table_virtual_scroll'
|
||||
);
|
||||
return {
|
||||
enable_number_formatting: flag ?? false,
|
||||
enable_number_formatting: enableNumberFormat ?? false,
|
||||
enable_table_virtual_scroll: enableTableVirtualScroll ?? false,
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import { BaseCellRenderer } from '@blocksuite/data-view';
|
||||
import { IS_MAC } from '@blocksuite/global/env';
|
||||
import { LinkedPageIcon } from '@blocksuite/icons/lit';
|
||||
import type { BlockSnapshot, DeltaInsert, Text } from '@blocksuite/store';
|
||||
import { signal } from '@preact/signals-core';
|
||||
import { computed, signal } from '@preact/signals-core';
|
||||
import { property } from 'lit/decorators.js';
|
||||
import { createRef, ref } from 'lit/directives/ref.js';
|
||||
import { html } from 'lit/static-html.js';
|
||||
@@ -217,17 +217,23 @@ export class HeaderAreaTextCell extends BaseCellRenderer<Text, string> {
|
||||
super.firstUpdated(props);
|
||||
this.richText.value?.updateComplete
|
||||
.then(() => {
|
||||
this.disposables.addFromEvent(
|
||||
this.richText.value,
|
||||
'copy',
|
||||
this._onCopy
|
||||
);
|
||||
this.disposables.addFromEvent(this.richText.value, 'cut', this._onCut);
|
||||
this.disposables.addFromEvent(
|
||||
this.richText.value,
|
||||
'paste',
|
||||
this._onPaste
|
||||
);
|
||||
if (this.richText.value) {
|
||||
this.disposables.addFromEvent(
|
||||
this.richText.value,
|
||||
'copy',
|
||||
this._onCopy
|
||||
);
|
||||
this.disposables.addFromEvent(
|
||||
this.richText.value,
|
||||
'cut',
|
||||
this._onCut
|
||||
);
|
||||
this.disposables.addFromEvent(
|
||||
this.richText.value,
|
||||
'paste',
|
||||
this._onPaste
|
||||
);
|
||||
}
|
||||
})
|
||||
.catch(console.error);
|
||||
}
|
||||
@@ -261,7 +267,14 @@ export class HeaderAreaTextCell extends BaseCellRenderer<Text, string> {
|
||||
class="${titleRichTextStyle}"
|
||||
></rich-text>`;
|
||||
}
|
||||
icon$ = computed(() => {
|
||||
const iconColumn = this.view.mainProperties$.value.iconColumn;
|
||||
if (!iconColumn) return;
|
||||
|
||||
const icon = this.view.cellValueGet(this.cell.rowId, iconColumn) as string;
|
||||
if (!icon) return;
|
||||
return icon;
|
||||
});
|
||||
renderIcon() {
|
||||
if (!this.showIcon) {
|
||||
return;
|
||||
@@ -271,10 +284,7 @@ export class HeaderAreaTextCell extends BaseCellRenderer<Text, string> {
|
||||
${LinkedPageIcon({})}
|
||||
</div>`;
|
||||
}
|
||||
const iconColumn = this.view.mainProperties$.value.iconColumn;
|
||||
if (!iconColumn) return;
|
||||
|
||||
const icon = this.view.cellValueGet(this.cell.rowId, iconColumn) as string;
|
||||
const icon = this.icon$.value;
|
||||
if (!icon) return;
|
||||
|
||||
return html` <div class="${headerAreaIconStyle}">${icon}</div>`;
|
||||
|
||||
Reference in New Issue
Block a user