feat: 모든 자산 목록 뷰에 마우스 드래그를 이용한 테이블 컬럼 너비 조절(Resizable Columns) 기능 추가
This commit is contained in:
@@ -670,7 +670,7 @@ export function createListView(container: HTMLElement, config: ListViewConfig) {
|
||||
thead.innerHTML = `<tr>${config.columns.map(col => {
|
||||
const isDateCol = col.header.includes('일') || col.header.includes('날짜') || col.header.includes('연월');
|
||||
const alignmentClass = col.align ? `text-${col.align}` : (isDateCol ? 'text-center' : '');
|
||||
return `<th class="${alignmentClass}" ${col.sortKey ? `data-sort="${col.sortKey}"` : ''} style="${col.width ? `width:${col.width};` : ''}">${col.header}</th>`;
|
||||
return `<th class="${alignmentClass}" ${col.sortKey ? `data-sort="${col.sortKey}"` : ''} style="${col.width ? `width:${col.width};` : ''}">${col.header}<div class="resizer"></div></th>`;
|
||||
}).join('')}</tr>`;
|
||||
|
||||
tbody.innerHTML = filtered.length === 0 ? `<tr><td colspan="${config.columns.length}" class="text-center empty-cell">${UI_TEXT.MESSAGES.NO_DATA}</td></tr>`
|
||||
@@ -698,8 +698,45 @@ export function createListView(container: HTMLElement, config: ListViewConfig) {
|
||||
|
||||
tbody.querySelectorAll('.asset-row').forEach((tr, idx) => { tr.addEventListener('click', () => config.onRowClick && config.onRowClick(filtered[idx])); });
|
||||
setupTableSorting(table, sortState, (key, dir) => { sortState = { key, direction: dir }; updateTable(); });
|
||||
makeColumnsResizable(table);
|
||||
};
|
||||
|
||||
function makeColumnsResizable(tableElement: HTMLTableElement) {
|
||||
const headers = tableElement.querySelectorAll('th');
|
||||
headers.forEach(th => {
|
||||
const resizer = th.querySelector('.resizer') as HTMLElement;
|
||||
if (!resizer) return;
|
||||
|
||||
let startX = 0;
|
||||
let startWidth = 0;
|
||||
|
||||
const onMouseMove = (e: MouseEvent) => {
|
||||
const dx = e.clientX - startX;
|
||||
const newWidth = Math.max(50, startWidth + dx);
|
||||
th.style.width = `${newWidth}px`;
|
||||
};
|
||||
|
||||
const onMouseUp = () => {
|
||||
resizer.classList.remove('resizing');
|
||||
document.removeEventListener('mousemove', onMouseMove);
|
||||
document.removeEventListener('mouseup', onMouseUp);
|
||||
};
|
||||
|
||||
resizer.addEventListener('mousedown', (e: MouseEvent) => {
|
||||
// Prevents header click sorting trigger from firing
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
|
||||
startX = e.clientX;
|
||||
startWidth = th.offsetWidth;
|
||||
|
||||
resizer.classList.add('resizing');
|
||||
document.addEventListener('mousemove', onMouseMove);
|
||||
document.addEventListener('mouseup', onMouseUp);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const switchView = () => {
|
||||
contentWrapper.innerHTML = '';
|
||||
const isAssetMode = !isServer || state.viewMode === 'list';
|
||||
|
||||
@@ -68,6 +68,25 @@ th {
|
||||
letter-spacing: -0.02em;
|
||||
box-shadow: inset 0 -1px 0 var(--hairline);
|
||||
text-align: center; /* Set default header alignment to center */
|
||||
position: relative; /* Essential for absolute positioning of resizer handles */
|
||||
}
|
||||
|
||||
.resizer {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
width: 6px;
|
||||
height: 100%;
|
||||
cursor: col-resize;
|
||||
user-select: none;
|
||||
z-index: 60; /* Higher than thead's sticky z-index (50) to catch mouse events */
|
||||
}
|
||||
|
||||
.resizer:hover,
|
||||
.resizer.resizing {
|
||||
background-color: var(--primary, #1e5149);
|
||||
opacity: 0.8;
|
||||
width: 3px;
|
||||
}
|
||||
|
||||
td {
|
||||
|
||||
Reference in New Issue
Block a user