Skip to content

Commit

Permalink
feat(DataGrid): ✨ Add resizable columns
Browse files Browse the repository at this point in the history
Now you can set resizable columns or all columns resizable prop
  • Loading branch information
gzimbron committed Feb 16, 2024
1 parent c32bcab commit 5af397a
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 12 deletions.
19 changes: 16 additions & 3 deletions packages/svelte-datagrid/src/lib/actions/dragAndDrop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,23 @@ export const dragAndDrop: Action<HTMLElement, ActionParams> = (
{ draggable, dragEnd, dragStart }: ActionParams = {}
) => {
if (draggable) {
node.draggable = true;

node.addEventListener('dragstart', (e) => {
const div = e.target as HTMLElement;
const isRezisable = div.classList.contains('resizable');

if (isRezisable) {
const resizableWidth = parseInt(
window.getComputedStyle(div, '::after').width.replace('px', '')
);

const clickPosition = e.clientX - div.getBoundingClientRect().left;

if (clickPosition >= div.offsetWidth - resizableWidth - 2) {
e.preventDefault();
return;
}
}

dragStart && dragStart(e);
node.classList.add('dragging');
});
Expand All @@ -27,7 +41,6 @@ export const dragAndDrop: Action<HTMLElement, ActionParams> = (

return {
destroy() {
node.draggable = false;
node.removeEventListener('dragstart', () => {});
node.removeEventListener('dragend', () => {});
}
Expand Down
58 changes: 58 additions & 0 deletions packages/svelte-datagrid/src/lib/actions/resizeColumn.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import type { Action } from 'svelte/action';

interface ActionParams {
resizable?: boolean;
startResize?: () => void;
endResize?: () => void;
onResize?: (data: number) => void;
}

export const reziseColumn: Action<HTMLElement, ActionParams> = (
node,
{ resizable, onResize, startResize, endResize }: ActionParams = {}
) => {
if (!resizable) return;

let lastX = 0;

const mouseMoveEvent = (e: MouseEvent) => {
if (!onResize) return;
if (e.clientX === lastX) return;
lastX = e.clientX;
onResize(lastX - node.getBoundingClientRect().left);
};

const mouseDownEvent = (e: MouseEvent) => {
if (e.button !== 0) {
return;
}
lastX = e.clientX;

// get node width and style ::after
const nodeAfterWidth = parseInt(
window.getComputedStyle(node, ':after').width.replace('px', '')
);
const clickPosition = e.clientX - node.getBoundingClientRect().left;

if (clickPosition < node.offsetWidth - nodeAfterWidth - 2) return;

startResize && startResize();

document.addEventListener('mousemove', mouseMoveEvent);
document.addEventListener('mouseup', mouseUpEvent);
};

const mouseUpEvent = () => {
endResize && endResize();
document.removeEventListener('mousemove', mouseMoveEvent);
};

node.addEventListener('mousedown', mouseDownEvent);

return {
destroy() {
document.removeEventListener('mousedown', mouseDownEvent);
node.removeEventListener('mouseup', () => mouseUpEvent);
}
};
};
77 changes: 69 additions & 8 deletions packages/svelte-datagrid/src/lib/components/Datagrid.svelte
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<script lang="ts" generics="T">
import { reziseColumn } from '$lib/actions/resizeColumn.js';
import { MIN_ROW_HEIGHT } from '$lib/configurations.js';
import type { GridProps } from '$lib/DataGridProps.js';
Expand All @@ -14,6 +16,7 @@
calculateXPositions,
getRowTop,
getVisibleRowsIndexes,
MIN_COLUMN_WIDTH,
updateColumnWidths
} from '$lib/functions/calculateFunctions.js';
Expand Down Expand Up @@ -55,6 +58,11 @@
*/
extraRows?: number;
/**
* Set all columns draggable by default, ignoring the `draggable` property of each column
*/
allColumnsResizable?: boolean;
/**
* Set all columns draggable by default, ignoring the `draggable` property of each column
*/
Expand Down Expand Up @@ -91,12 +99,19 @@
export let extraRows = 0;
export let rowsPerPage = calculateDefaultRowsPerPage(rows.length);
export let allColumnsDraggable = false;
export let allColumnsResizable = false;
export let animationParams: FlipParams = {
duration: 150,
delay: 0,
easing: quadIn
};
const NO_TRANSITION_EFFECT = {
duration: 0,
delay: 0,
easing: undefined
};
if (!columns || columns.length < 1) {
throw new Error('Columns are required');
}
Expand All @@ -105,11 +120,11 @@
throw new Error('Rows are required');
}
export const scrollToRow = (rowIndex: number) => {
export const scrollToRow = (rowIndex: number, behavior: ScrollBehavior = 'smooth') => {
if (!gridBody) return;
gridBody.scrollTo({
top: rowIndex * rowHeight,
behavior: 'smooth'
behavior
});
};
Expand All @@ -128,6 +143,7 @@
let isResizing = false;
let isDragging = false;
let columnDragging = -1;
let columnResizing = -1;
let yScrollPercent = 0;
let xScrollPercent = 0;
Expand Down Expand Up @@ -238,6 +254,12 @@
class:resizing={isResizing || isDragging}
class:isDragging
>
{#if columnResizing != -1}
<div
class="resizingbar"
style:left="{columnWidths[columnResizing] + xPositions[columnResizing]}px"
></div>
{/if}
<div class="svelte-grid-head" role="rowgroup">
<div role="row" class="header-row" style:left="{scrollLeft * -1}px">
{#each columns as column, i (i)}
Expand All @@ -249,9 +271,27 @@
role="columnheader"
style:width="{columnWidths[i]}px"
style:left="{xPositions[i]}px"
class:draggable={allColumnsDraggable || column.draggable}
class:dragging={false}
animate:flip={animationParams}
draggable={!isResizing && (allColumnsDraggable || column.draggable)}
class:draggable={!isResizing && (allColumnsDraggable || column.draggable)}
class:resizable={!isResizing && (allColumnsResizable || column.resizable)}
class:dragging={isDragging && columnDragging == i}
animate:flip={isResizing ? NO_TRANSITION_EFFECT : animationParams}
use:reziseColumn={{
resizable: allColumnsResizable || column.resizable,
startResize() {
columnResizing = i;
isResizing = true;
},
endResize() {
columnResizing = -1;
isResizing = false;
},
onResize(data) {
if (data < MIN_COLUMN_WIDTH) return;

columnWidths[i] = data;
}
}}
use:dragAndDrop={{
draggable: allColumnsDraggable || column.draggable,
dragStart: () => {
Expand Down Expand Up @@ -319,7 +359,7 @@
style="width:{columnWidths[j]}px"
style:left="{xPositions[j]}px"
class:draggableColumnCell={allColumnsDraggable || column.draggable}
animate:flip={animationParams}
animate:flip={isResizing ? NO_TRANSITION_EFFECT : animationParams}
>
<div class="cell-container" class:cell-default={!column.cellComponent}>
{#if column.cellComponent}
Expand All @@ -343,6 +383,15 @@
</div>

<style lang="postcss">
.resizingbar {
position: absolute;
top: 0;
width: 2px;
height: 100%;
background-color: var(--header-border-color, #666);
transform: translate(-50%, 0);
z-index: 3;
}
.resizing * {
user-select: none;
}
Expand All @@ -369,17 +418,29 @@
background-color: var(--no-draggable-fg, rgba(66, 66, 66, 0.5));
}
.draggable :hover {
.columnheader.resizable:hover::after {
content: '';
cursor: ew-resize;
position: absolute;
top: 0;
right: 0;
width: 2px;
height: 100%;
z-index: 3;
}
.columnheader.draggable:not(.dragging):hover {
content: '';
position: absolute;
background-color: var(--draggable-bg, rgba(33, 248, 255, 0.5));
top: 0;
right: 0;
width: 100%;
height: 100%;
cursor: move;
}
.columnheader.dragging {
.columnheader.dragging:hover {
border: var(--border, 1px solid #666);
background-color: var(--dragging-bg, rgba(33, 255, 151, 0.5));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@
width: 100%;
height: 100%;
background: var(--textbox-cell-bg, var(--cell-bg, white));
z-index: 3;
z-index: 2;
}
input {
height: 100%;
Expand Down
1 change: 1 addition & 0 deletions packages/svelte-datagrid/src/lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export type GridColumn<T> = {
cellComponent?: CustomCellComponent<T>;
options?: GridColumnOption[];
draggable?: boolean;
resizable?: boolean;
};

export type GridColumnOption = {
Expand Down

0 comments on commit 5af397a

Please sign in to comment.