Skip to content

Commit 160c7d9

Browse files
authored
Merge pull request #403 from appwrite/fix-add-sticky-support-and-scrollbar
fix/add native scrollbar and sticky column support
2 parents a4067bf + ca72286 commit 160c7d9

6 files changed

Lines changed: 373 additions & 69 deletions

File tree

v2/pink-sb/src/lib/spreadsheet/Cell.svelte

Lines changed: 72 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
type SpreadsheetRootProps
1111
} from './index.js';
1212
import { tick, onDestroy, createEventDispatcher, type ComponentType } from 'svelte';
13+
import { readable } from 'svelte/store';
1314
import { getRowContext } from './context.js';
15+
import type { SpreadsheetDOMProps, SpreadsheetRowState } from './index.js';
1416
1517
export let root: SpreadsheetRootProps;
1618
export let value: string | undefined = undefined;
@@ -22,6 +24,10 @@
2224
export let isHeader = false;
2325
export let isEditable = true;
2426
export let openEditOnTap = false;
27+
let className = '';
28+
export { className as class };
29+
let inlineStyle: string | undefined = undefined;
30+
export { inlineStyle as style };
2531
2632
let width = 0;
2733
let startX = 0;
@@ -34,6 +40,15 @@
3440
let originalValue = value;
3541
let rowIndex: number = -1;
3642
let rowId: string | undefined = undefined;
43+
let rowState: SpreadsheetRowState = {
44+
rowId: undefined,
45+
rowIndex: undefined,
46+
hovered: false,
47+
focused: false,
48+
selected: false,
49+
isHeader,
50+
isEmptyRow: false
51+
};
3752
3853
/* edit slot close() triggers blur which calls commitChange, this prevents that */
3954
let isClosingFloatingEditor = false;
@@ -50,7 +65,9 @@
5065
$: hasKeyboardNavigation = root.keyboardNavigation ?? false;
5166
$: isAction = options?.isAction ?? false;
5267
$: isSelect = (root.allowSelection && column?.includes('__select_')) || false;
53-
$: isFixed = isSelect || isAction || options?.fixed;
68+
$: stickySide = root.getStickySide(column, isSelect, isAction);
69+
$: stickyOffset = root.getStickyOffset(column, isSelect, isAction);
70+
$: isFixed = stickySide !== null;
5471
$: endsBeforeFixedRight = column === root.lastColumnBeforeAction;
5572
$: resizable = (options?.resizable ?? true) && column !== root.lastResizableColumnId;
5673
$: isEditing = root.currentlyEditingCellId === id;
@@ -195,10 +212,25 @@
195212
}
196213
});
197214
215+
const rowContext = getRowContext() ?? readable(null);
216+
217+
$: currentRowContext = rowContext ? $rowContext : null;
218+
$: rowId = currentRowContext?.id ?? undefined;
219+
$: rowIndex = currentRowContext?.index ?? -1;
220+
$: rowState = {
221+
rowId,
222+
rowIndex: currentRowContext?.isHeader ? undefined : rowIndex > 0 ? rowIndex - 1 : undefined,
223+
hovered: currentRowContext?.hovered ?? false,
224+
focused: currentRowContext?.focused ?? false,
225+
selected: currentRowContext?.selected ?? false,
226+
isHeader: currentRowContext?.isHeader ?? isHeader,
227+
isEmptyRow: currentRowContext?.isEmptyRow ?? isEmptyCell
228+
};
229+
$: cellProps = root.getCellProps(rowId, column, rowState) as SpreadsheetDOMProps | undefined;
230+
$: mergedClassName = [className, cellProps?.class].filter(Boolean).join(' ');
231+
$: mergedStyle = [inlineStyle, cellProps?.style].filter(Boolean).join('; ');
232+
198233
$: if (hasKeyboardNavigation && typeof cellEl !== 'undefined' && !isEmptyCell) {
199-
const rowContext = getRowContext();
200-
rowId = rowContext?.id ?? undefined;
201-
rowIndex = rowContext?.index ?? -1;
202234
root.registerForNavigation(cellEl, rowIndex, columnIndex);
203235
}
204236
@@ -303,6 +335,10 @@
303335
data-header={isHeader}
304336
data-loading={isLoading}
305337
data-column-id={column}
338+
data-sticky-side={stickySide}
339+
data-row-hovered={rowState.hovered}
340+
data-row-focused={rowState.focused}
341+
data-row-selected={rowState.selected}
306342
data-editing-mode={isEditing}
307343
data-edit-on-tap={openEditOnTap}
308344
data-empty-cell={isEmptyCell}
@@ -320,8 +356,14 @@
320356
class:no-end-border={endsBeforeFixedRight}
321357
class:dragging-column={isDragging}
322358
class:drag-over={isDraggedOver && !isDragging}
323-
style:left={isSelect ? '0' : undefined}
324-
style:right={isAction ? '0' : undefined}
359+
class={mergedClassName}
360+
style:left={stickySide === 'left' && stickyOffset !== null
361+
? `${stickyOffset}px`
362+
: undefined}
363+
style:right={stickySide === 'right' && stickyOffset !== null
364+
? `${stickyOffset}px`
365+
: undefined}
366+
style={mergedStyle}
325367
on:contextmenu={isEmptyCell ? undefined : handleContextMenu}
326368
use:clickOutside={handleClickOutside}
327369
on:click={handleCellClick}
@@ -403,11 +445,23 @@
403445
font-size: var(--font-size-s);
404446
padding: var(--space-4) var(--space-6);
405447
background: var(--bgcolor-neutral-primary);
448+
transition: background-color 125ms ease-in-out;
406449
407450
&[data-select='false'] {
408451
box-shadow: 0 -1px 0 0 var(--border-neutral) inset;
409452
}
410453
454+
&[data-row-selected='true']:not([data-header='true']) {
455+
background: var(--overlay-neutral-pressed-solid);
456+
}
457+
458+
&[data-row-hovered='true'][data-row-focused='false']:not([data-row-selected='true']):not(
459+
[data-header='true']
460+
) {
461+
cursor: pointer;
462+
background: var(--overlay-neutral-hover-solid);
463+
}
464+
411465
&:not([data-header='true'])[data-allow-focus='true']:focus {
412466
left: -1px;
413467
z-index: 10;
@@ -475,6 +529,12 @@
475529
&:has(textarea) {
476530
min-height: 120px;
477531
padding-block: 9px;
532+
resize: none;
533+
overflow: auto;
534+
535+
&::after {
536+
display: none;
537+
}
478538
}
479539
480540
&:not(:has(textarea)) {
@@ -577,18 +637,19 @@
577637
z-index: 10;
578638
}
579639
580-
&[data-select='true'] {
581-
left: 0;
640+
&[data-sticky-side='left'] {
582641
border-right: var(--border-width-s) solid var(--border-neutral);
583-
border-bottom: var(--border-width-s) solid var(--border-neutral);
584642
}
585643
586-
&[data-action='true'] {
587-
right: 0;
644+
&[data-sticky-side='right'] {
588645
display: inline-flex;
589646
justify-content: center;
590647
border-left: var(--border-width-s) solid var(--border-neutral);
591648
}
649+
650+
&[data-select='true'] {
651+
border-bottom: var(--border-width-s) solid var(--border-neutral);
652+
}
592653
}
593654
594655
&.space-between {

0 commit comments

Comments
 (0)