import { ShadowlessElement, WithDisposable } from '@blockeditor/lit'; import type { PropertyValues } from 'lit'; import { css, html } from 'lit'; import { customElement, property } from 'lit/decorators.js'; import { repeat } from 'lit/directives/repeat.js'; import { popFilterableSimpleMenu } from '../../_common/components/menu/index.js'; import { PlusIcon } from '../../_common/icons/index.js'; import { GroupTitle } from '../common/group-by/group-title.js'; import type { GroupData } from '../common/group-by/helper.js'; import { LEFT_TOOL_BAR_WIDTH } from './consts.js'; import type { DataViewTable } from './table-view.js'; import type { DataViewTableManager } from './table-view-manager.js'; const styles = css` affine-data-view-table-group .group-header-op { visibility: visible; } .data-view-table-group-add-row { display: flex; width: 100%; height: 28px; position: relative; z-index: 0; cursor: pointer; transition: opacity 0.2s ease-in-out; padding: 4px 8px; border-bottom: 1px solid var(--affine-border-color); } @media print { .data-view-table-group-add-row { display: none; } } .data-view-table-group-add-row-button { position: sticky; left: ${8 + LEFT_TOOL_BAR_WIDTH}px; display: flex; align-items: center; justify-content: center; gap: 10px; user-select: none; font-size: 12px; line-height: 20px; color: var(--affine-text-secondary-color); } `; @customElement('affine-data-view-table-group') export class TableGroup extends WithDisposable(ShadowlessElement) { static override styles = styles; @property({ attribute: false }) view!: DataViewTableManager; @property({ attribute: false }) viewEle!: DataViewTable; @property({ attribute: false }) group?: GroupData; get rows() { return this.group?.rows ?? this.view.rows; } protected override updated(_changedProperties: PropertyValues) { super.updated(_changedProperties); this.querySelectorAll('data-view-table-row').forEach(ele => { ele.requestUpdate(); }); } private clickAddRow = () => { this.view.rowAdd('end', this.group?.key); requestAnimationFrame(() => { const selectionController = this.viewEle.selectionController; selectionController.selection = { groupKey: this.group?.key, focus: { rowIndex: this.rows.length - 1, columnIndex: 0, }, isEditing: true, }; }); }; private clickAddRowInStart = () => { this.view.rowAdd('start', this.group?.key); requestAnimationFrame(() => { const selectionController = this.viewEle.selectionController; selectionController.selection = { groupKey: this.group?.key, focus: { rowIndex: 0, columnIndex: 0, }, isEditing: true, }; }); }; private clickGroupOptions = (e: MouseEvent) => { const group = this.group; if (!group) { return; } const ele = e.currentTarget as HTMLElement; popFilterableSimpleMenu(ele, [ { type: 'action', name: 'Ungroup', hide: () => group.value == null, select: () => { group.rows.forEach(id => { group.helper.removeFromGroup(id, group.key); }); }, }, { type: 'action', name: 'Delete Cards', select: () => { this.view.rowDelete(group.rows); }, }, ]); }; private renderRows(ids: string[]) { return html`
${repeat( ids, id => id, (id, idx) => { return html``; } )}
${this.view.readonly ? null : html`
${PlusIcon}New Record
`} `; } override render() { if (!this.group) { return this.renderRows(this.view.rows); } return html`
${GroupTitle(this.group, { readonly: this.view.readonly, clickAdd: this.clickAddRowInStart, clickOps: this.clickGroupOptions, })}
${this.renderRows(this.group.rows)} `; } } declare global { interface HTMLElementTagNameMap { 'affine-data-view-table-group': TableGroup; } }