This commit is contained in:
2025-09-06 01:59:48 +10:00
parent 8a511e20e2
commit 2f3f853134
3 changed files with 44 additions and 26 deletions

View File

@@ -8,7 +8,8 @@
setRowHeight = () => {}, setRowHeight = () => {},
val, val,
active, active,
direction = 'col' // New prop: 'col' for right-side drag, 'row' for bottom-side direction = 'col', // New prop: 'col' for right-side drag, 'row' for bottom-side
resizeable = true
}: { }: {
width?: string; width?: string;
height?: string; height?: string;
@@ -16,6 +17,7 @@
setRowHeight?: (height: string) => void; setRowHeight?: (height: string) => void;
val: string; val: string;
active: boolean; active: boolean;
resizeable?: boolean;
direction?: 'col' | 'row'; direction?: 'col' | 'row';
} = $props(); } = $props();
@@ -66,27 +68,29 @@
{val} {val}
</span> </span>
<div {#if resizeable}
role="separator" <div
aria-label="Resize handle" role="separator"
onmousedown={handleMouseDown} aria-label="Resize handle"
class={clsx('resizer', { onmousedown={handleMouseDown}
'resizer-col': direction === 'col', class={clsx('resizer', {
'resizer-row': direction === 'row' 'resizer-col': direction === 'col',
})} 'resizer-row': direction === 'row'
></div> })}
></div>
{/if}
</div> </div>
<style> <style>
.placeholder { .placeholder {
font-size: 14px; font-size: 14px;
border: 1px solid var(--input); border: 1px solid var(--input);
overflow: visible; background-color: var(--color-background);
} }
.active { .active {
border: 1px solid var(--color-primary); border: 1px solid var(--color-primary);
background-color: color-mix(in oklab, var(--color-primary) 40%, transparent); background-color: color-mix(in oklab, var(--color-primary) 80%, var(--color-background) 80%);
} }
/* --- Resizer Styles --- */ /* --- Resizer Styles --- */

View File

@@ -36,10 +36,13 @@
} }
function handleKeydown(e: KeyboardEvent) { function handleKeydown(e: KeyboardEvent) {
if (e.key === 'Enter' || e.key === 'NumpadEnter' || e.key == 'Escape') { if (e.key === 'Enter' || e.key === 'NumpadEnter') {
e.preventDefault(); // avoid form submit/line break e.preventDefault(); // avoid form submit/line break
const el = (e.currentTarget as HTMLElement).querySelector('input') as HTMLInputElement | null; const el = (e.currentTarget as HTMLElement).querySelector('input') as HTMLInputElement | null;
el?.blur(); // triggers on:blur below el?.blur(); // triggers on:blur below
} else if (e.key == 'Escape') {
e.preventDefault();
stopediting();
} }
} }
</script> </script>
@@ -50,7 +53,7 @@
style="width: {width}; height: {height}" style="width: {width}; height: {height}"
class="relative rounded-none p-1 class="relative rounded-none p-1
!transition-none delay-0 duration-0 !transition-none delay-0 duration-0
focus:z-50" focus:z-20"
onblur={(e) => { onblur={(e) => {
raw_val = (e.target as HTMLInputElement).value; raw_val = (e.target as HTMLInputElement).value;
stopediting(); stopediting();
@@ -63,7 +66,7 @@
{onmousedown} {onmousedown}
style:width style:width
style:height style:height
class={clsx('placeholder bg-background p-1 dark:bg-input/30', { active, 'z-50': active })} class={clsx('placeholder bg-background p-1 dark:bg-input/30', { active, 'z-20': active })}
> >
{#if raw_val !== '' || val !== ''} {#if raw_val !== '' || val !== ''}
<span class="pointer-events-none select-none"> <span class="pointer-events-none select-none">

View File

@@ -202,9 +202,18 @@
}); });
</script> </script>
<div class="grid-wrapper"> <div class="grid-wrapper relative max-h-[100vh] max-w-full overflow-auto">
<div class="flex w-fit"> <div class="sticky top-0 z-40 flex w-fit">
<CellHeader height={default_row_height} width={default_col_width} val="" active={false} /> <div class="sticky top-0 left-0 z-50">
<CellHeader
resizeable={false}
height={default_row_height}
width={default_col_width}
val=""
active={false}
/>
</div>
{#each Array(cols) as _, j} {#each Array(cols) as _, j}
<CellHeader <CellHeader
height={default_row_height} height={default_row_height}
@@ -218,14 +227,16 @@
</div> </div>
{#each Array(rows) as _, i} {#each Array(rows) as _, i}
<div class="flex w-fit"> <div class="flex w-fit">
<CellHeader <div class="sticky left-0 z-30 flex w-fit">
direction="row" <CellHeader
width={default_col_width} direction="row"
height={getRowHeight(i)} width={default_col_width}
setRowHeight={(height) => setRowHeight(i, height)} height={getRowHeight(i)}
val={(i + 1).toString()} setRowHeight={(height) => setRowHeight(i, height)}
active={active_cell !== null && active_cell[0] === i} val={(i + 1).toString()}
/> active={active_cell !== null && active_cell[0] === i}
/>
</div>
{#each Array(cols) as _, j} {#each Array(cols) as _, j}
<Cell <Cell
height={getRowHeight(i)} height={getRowHeight(i)}