import { css, html } from 'lit';
import { customElement, query, state } from 'lit/decorators.js';
import { styleMap } from 'lit/directives/style-map.js';
import { createIcon } from '../../../../_common/components/icon/uni-icon.js';
import { startDrag } from '../../../utils/drag.js';
import { BaseCellRenderer } from '../base-cell.js';
import { columnRenderer, createFromBaseCellRenderer } from '../renderer.js';
import { progressPureColumnConfig } from './define.js';
const styles = css`
affine-database-progress-cell-editing {
display: block;
width: 100%;
padding: 0 4px;
}
affine-database-progress-cell {
display: block;
width: 100%;
padding: 0 4px;
}
.affine-database-progress {
display: flex;
align-items: center;
height: var(--data-view-cell-text-line-height);
gap: 4px;
}
.affine-database-progress-bar {
position: relative;
width: 104px;
}
.affine-database-progress-bg {
overflow: hidden;
width: 100%;
height: 10px;
border-radius: 22px;
}
.affine-database-progress-fg {
height: 100%;
}
.affine-database-progress-drag-handle {
position: absolute;
top: 0;
left: 0;
transform: translate(0px, -1px);
width: 6px;
height: 12px;
border-radius: 2px;
opacity: 1;
cursor: ew-resize;
background: var(--affine-primary-color);
transition: opacity 0.2s ease-in-out;
}
.progress-number {
display: flex;
justify-content: center;
align-items: center;
height: 18px;
width: 25px;
color: var(--affine-text-secondary-color);
font-size: 14px;
}
`;
const progressColors = {
empty: 'var(--affine-black-10)',
processing: 'var(--affine-processing-color)',
success: 'var(--affine-success-color)',
};
@customElement('affine-database-progress-cell')
export class ProgressCell extends BaseCellRenderer {
static override styles = styles;
_bgClick(e: MouseEvent) {
if (this.column.readonly) {
return;
}
this.onChange(
Math.round(
(e.offsetX * 100) / (e.currentTarget as HTMLDivElement).offsetWidth
)
);
}
protected override render() {
const progress = this.value ?? 0;
let backgroundColor = progressColors.processing;
if (progress === 100) {
backgroundColor = progressColors.success;
}
const fgStyles = styleMap({
width: `${progress}%`,
backgroundColor,
});
const bgStyles = styleMap({
backgroundColor:
progress === 0 ? progressColors.empty : 'var(--affine-hover-color)',
});
return html` `;
}
}
@customElement('affine-database-progress-cell-editing')
export class ProgressCellEditing extends BaseCellRenderer {
static override styles = styles;
@state()
private tempValue?: number;
override onExitEditMode() {
this.onChange(this._value);
}
get _value() {
return this.tempValue ?? this.value ?? 0;
}
_onChange(value?: number) {
this.tempValue = value;
}
@query('.affine-database-progress-bg')
private _progressBg!: HTMLElement;
override firstUpdated() {
const disposables = this._disposables;
disposables.addFromEvent(this._progressBg, 'pointerdown', this.startDrag);
disposables.addFromEvent(window, 'keydown', evt => {
if (evt.key === 'ArrowDown') {
this._onChange(Math.max(0, this._value - 1));
return;
}
if (evt.key === 'ArrowUp') {
this._onChange(Math.min(100, this._value + 1));
return;
}
});
}
startDrag = (event: MouseEvent) => {
const bgRect = this._progressBg.getBoundingClientRect();
const min = bgRect.left;
const max = bgRect.right;
const setValue = (x: number) => {
this.tempValue = Math.round(
((Math.min(max, Math.max(min, x)) - min) / (max - min)) * 100
);
};
startDrag(event, {
onDrag: ({ x }) => {
setValue(x);
return;
},
onMove: ({ x }) => {
setValue(x);
return;
},
onDrop: () => {
//
},
onClear: () => {
//
},
});
};
override onCopy(_e: ClipboardEvent) {
_e.preventDefault();
}
override onPaste(_e: ClipboardEvent) {
_e.preventDefault();
}
override onCut(_e: ClipboardEvent) {
_e.preventDefault();
}
protected override render() {
const progress = this._value;
let backgroundColor = progressColors.processing;
if (progress === 100) {
backgroundColor = progressColors.success;
}
const fgStyles = styleMap({
width: `${progress}%`,
backgroundColor,
});
const bgStyles = styleMap({
backgroundColor:
progress === 0 ? progressColors.empty : 'var(--affine-hover-color)',
});
const handleStyles = styleMap({
left: `calc(${progress}% - 3px)`,
});
return html` `;
}
}
columnRenderer.register({
type: progressPureColumnConfig.type,
icon: createIcon('DatabaseProgress'),
cellRenderer: {
view: createFromBaseCellRenderer(ProgressCell),
edit: createFromBaseCellRenderer(ProgressCellEditing),
},
});
export const progressColumnConfig = progressPureColumnConfig;