Files
AFFiNE-Mirror/blocksuite/affine/data-view/src/view-presets/kanban/pc/cell.ts
T
2024-12-20 15:38:06 +08:00

189 lines
4.8 KiB
TypeScript

// related component
import { ShadowlessElement } from '@blocksuite/block-std';
import { SignalWatcher, WithDisposable } from '@blocksuite/global/utils';
import { css } from 'lit';
import { property, state } from 'lit/decorators.js';
import { createRef } from 'lit/directives/ref.js';
import { html } from 'lit/static-html.js';
import type {
CellRenderProps,
DataViewCellLifeCycle,
} from '../../../core/property/index.js';
import { renderUniLit } from '../../../core/utils/uni-component/uni-component.js';
import type { Property } from '../../../core/view-manager/property.js';
import type { KanbanSingleView } from '../kanban-view-manager.js';
import type { KanbanViewSelection } from '../types.js';
const styles = css`
affine-data-view-kanban-cell {
border-radius: 4px;
display: flex;
align-items: center;
padding: 4px;
min-height: 20px;
border: 1px solid transparent;
box-sizing: border-box;
}
affine-data-view-kanban-cell:hover {
background-color: var(--affine-hover-color);
}
affine-data-view-kanban-cell .icon {
display: flex;
align-items: center;
justify-content: center;
align-self: start;
margin-right: 12px;
height: var(--data-view-cell-text-line-height);
}
affine-data-view-kanban-cell .icon svg {
width: 16px;
height: 16px;
fill: var(--affine-icon-color);
color: var(--affine-icon-color);
}
.kanban-cell {
flex: 1;
display: block;
width: 196px;
}
`;
export class KanbanCell extends SignalWatcher(
WithDisposable(ShadowlessElement)
) {
static override styles = styles;
private _cell = createRef<DataViewCellLifeCycle>();
selectCurrentCell = (editing: boolean) => {
const selectionView = this.closest(
'affine-data-view-kanban'
)?.selectionController;
if (!selectionView) return;
if (selectionView) {
const selection = selectionView.selection;
if (selection && this.isSelected(selection) && editing) {
selectionView.selection = {
selectionType: 'cell',
groupKey: this.groupKey,
cardId: this.cardId,
columnId: this.column.id,
isEditing: true,
};
} else {
selectionView.selection = {
selectionType: 'cell',
groupKey: this.groupKey,
cardId: this.cardId,
columnId: this.column.id,
isEditing: false,
};
}
}
};
get cell(): DataViewCellLifeCycle | undefined {
return this._cell.value;
}
get selection() {
return this.closest('affine-data-view-kanban')?.selectionController;
}
override connectedCallback() {
super.connectedCallback();
this._disposables.addFromEvent(this, 'click', e => {
if (e.shiftKey) {
return;
}
e.stopPropagation();
const selectionElement = this.closest(
'affine-data-view-kanban'
)?.selectionController;
if (!selectionElement) return;
if (e.shiftKey) return;
if (!this.editing) {
this.selectCurrentCell(!this.column.readonly$.value);
}
});
}
isSelected(selection: KanbanViewSelection) {
if (
selection.selectionType !== 'cell' ||
selection.groupKey !== this.groupKey
) {
return;
}
return (
selection.cardId === this.cardId && selection.columnId === this.column.id
);
}
override render() {
const props: CellRenderProps = {
cell: this.column.cellGet(this.cardId),
isEditing: this.editing,
selectCurrentCell: this.selectCurrentCell,
};
const renderer = this.column.renderer$.value;
if (!renderer) return;
const { view, edit } = renderer;
this.view.lockRows(this.editing);
this.dataset['editing'] = `${this.editing}`;
this.style.border = this.isFocus
? '1px solid var(--affine-primary-color)'
: '';
this.style.boxShadow = this.editing
? '0px 0px 0px 2px rgba(30, 150, 235, 0.30)'
: '';
return html` ${this.renderIcon()}
${renderUniLit(this.editing && edit ? edit : view, props, {
ref: this._cell,
class: 'kanban-cell',
style: { display: 'block', flex: '1', overflow: 'hidden' },
})}`;
}
renderIcon() {
if (this.contentOnly) {
return;
}
return html` <uni-lit class="icon" .uni="${this.column.icon}"></uni-lit>`;
}
@property({ attribute: false })
accessor cardId!: string;
@property({ attribute: false })
accessor column!: Property;
@property({ attribute: false })
accessor contentOnly = false;
@state()
accessor editing = false;
@property({ attribute: false })
accessor groupKey!: string;
@state()
accessor isFocus = false;
@property({ attribute: false })
accessor view!: KanbanSingleView;
}
declare global {
interface HTMLElementTagNameMap {
'affine-data-view-kanban-cell': KanbanCell;
}
}