import { ShadowlessElement, WithDisposable } from '@blockeditor/lit'; import { css, nothing } from 'lit'; import { customElement, property } from 'lit/decorators.js'; import { repeat } from 'lit/directives/repeat.js'; import { styleMap } from 'lit/directives/style-map.js'; import { html } from 'lit/static-html.js'; import { positionToVRect } from '../../../_common/components/menu/index.js'; import { MoreHorizontalIcon, NewEditIcon, } from '../../../_common/icons/index.js'; import { getPageByElement, type TableViewSelection, } from '../../../_common/utils/index.js'; import { DEFAULT_COLUMN_MIN_WIDTH } from '../consts.js'; import type { DataViewTableManager } from '../table-view-manager.js'; import { openDetail, popRowMenu } from './menu.js'; @customElement('data-view-table-row') export class TableRow extends WithDisposable(ShadowlessElement) { static override styles = css` .data-view-table-row { width: 100%; } .affine-database-block-row { width: 100%; display: flex; flex-direction: row; border-bottom: 1px solid var(--affine-border-color); position: relative; } .affine-database-block-row.selected > .database-cell { background: transparent; } .database-cell { min-width: ${DEFAULT_COLUMN_MIN_WIDTH}px; } .row-ops { position: relative; width: 0; margin-top: 8px; height: max-content; visibility: hidden; display: flex; gap: 4px; cursor: pointer; justify-content: end; } .row-op:last-child { margin-right: 8px; } .affine-database-block-row:hover .row-ops { visibility: visible; } .affine-database-block-row .show-on-hover-row { visibility: hidden; opacity: 0; transition: opacity 150ms cubic-bezier(0.42, 0, 1, 1); } .affine-database-block-row:hover .show-on-hover-row { visibility: visible; opacity: 1; } .row-op { display: flex; padding: 4px; border-radius: 4px; box-shadow: 0px 0px 4px 0px rgba(66, 65, 73, 0.14); background-color: var(--affine-background-primary-color); position: relative; } .row-op:hover:before { content: ''; border-radius: 4px; position: absolute; left: 0; right: 0; top: 0; bottom: 0; background-color: var(--affine-hover-color); } .row-op svg { fill: var(--affine-icon-color); color: var(--affine-icon-color); width: 16px; height: 16px; } `; get selectionController() { return this.closest('affine-database-table')?.selectionController; } @property({ attribute: false }) view!: DataViewTableManager; @property({ attribute: false }) rowIndex!: number; @property({ attribute: false }) rowId!: string; public get groupKey() { return this.closest('affine-data-view-table-group')?.group?.key; } setSelection = (selection?: Omit) => { if (this.selectionController) { this.selectionController.selection = selection; } }; contextMenu = (e: MouseEvent) => { const selection = this.selectionController; if (!selection) { return; } e.preventDefault(); const ele = e.target as HTMLElement; const columnIndex = ele.closest('affine-database-cell-container')?.columnIndex ?? 0; selection.selection = { rowsSelection: { start: this.rowIndex, end: this.rowIndex, }, focus: { rowIndex: this.rowIndex, columnIndex: columnIndex, }, isEditing: false, }; const pageElement = getPageByElement(this); popRowMenu(pageElement, positionToVRect(e.x, e.y), this.rowId, selection); }; public override connectedCallback() { super.connectedCallback(); this.disposables.addFromEvent(this, 'contextmenu', this.contextMenu); // eslint-disable-next-line wc/no-self-class this.classList.add('affine-database-block-row', 'database-row'); } private _clickDragHandler = () => { const selectionController = this.selectionController; if (selectionController) { if ( selectionController.isRowSelection(this.groupKey, this.rowIndex) && selectionController.selection ) { selectionController.selection = { ...selectionController.selection, rowsSelection: undefined, }; } else { selectionController.selection = { groupKey: this.groupKey, rowsSelection: { start: this.rowIndex, end: this.rowIndex, }, focus: { rowIndex: this.rowIndex, columnIndex: 0, }, isEditing: false, }; } } }; protected override render(): unknown { const view = this.view; return html`
${repeat( view.columnManagerList, v => v.id, (column, i) => { const clickDetail = () => { if (!this.selectionController) { return; } this.setSelection({ rowsSelection: { start: this.rowIndex, end: this.rowIndex, }, focus: { rowIndex: this.rowIndex, columnIndex: i, }, isEditing: false, }); const pageElement = getPageByElement(this); openDetail(pageElement, this.rowId, this.selectionController); }; const openMenu = (e: MouseEvent) => { if (!this.selectionController) { return; } const ele = e.currentTarget as HTMLElement; this.setSelection({ rowsSelection: { start: this.rowIndex, end: this.rowIndex, }, focus: { rowIndex: this.rowIndex, columnIndex: i, }, isEditing: false, }); const pageElement = getPageByElement(this); popRowMenu(pageElement, ele, this.rowId, this.selectionController); }; return html`
${column.dataViewManager.header.titleColumn === column.id ? html`
${NewEditIcon}
${!view.readonly ? html`
${MoreHorizontalIcon}
` : nothing}
` : nothing} `; } )}
`; } } declare global { interface HTMLElementTagNameMap { 'data-view-table-row': TableRow; } }