Table column resizing & some bug-fixes for tables (#7591)

Signed-off-by: Victor Ilyushchenko <alt13ri@gmail.com>
This commit is contained in:
Victor Ilyushchenko 2025-01-07 08:56:31 +03:00 committed by GitHub
parent 54d9a6c847
commit 780b841ead
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 89 additions and 52 deletions

View File

@ -172,6 +172,7 @@ table.proseTable {
&__selected { &__selected {
left: 0; left: 0;
&::before { &::before {
right: 0; right: 0;
top: 0; top: 0;
@ -203,8 +204,7 @@ table.proseTable {
} }
&:hover { &:hover {
&:not(.table-row-handle__selected) { &:not(.table-row-handle__selected) {}
}
button { button {
opacity: 1; opacity: 1;
@ -213,6 +213,7 @@ table.proseTable {
&__selected { &__selected {
top: 0; top: 0;
&::before { &::before {
bottom: 0; bottom: 0;
left: 0; left: 0;
@ -246,6 +247,27 @@ table.proseTable {
} }
} }
.column-resize-handle {
position: absolute;
right: -1px;
top: -1px;
bottom: -1px;
width: 1px;
z-index: 100;
background-color: var(--primary-button-focused);
&::after {
content: '';
position: absolute;
top: 0;
left: -5px;
right: -5px;
bottom: 0;
cursor: col-resize;
z-index: 100;
}
}
.table-row-insert { .table-row-insert {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
@ -291,13 +313,13 @@ table.proseTable {
} }
&:hover+.table-insert-marker { &:hover+.table-insert-marker {
opacity: 1; display: block;
} }
} }
.table-insert-marker { .table-insert-marker {
background-color: var(--primary-button-focused); background-color: var(--primary-button-focused);
opacity: 0; display: none;
} }
} }
@ -526,7 +548,7 @@ pre.proseCodeBlock>pre.proseCode {
border-bottom: 2px solid rgba(255, 203, 0, .35); border-bottom: 2px solid rgba(255, 203, 0, .35);
padding-bottom: 2px; padding-bottom: 2px;
transition: background 0.2s ease, border 0.2s ease; transition: background 0.2s ease, border 0.2s ease;
&.active { &.active {
transition-delay: 150ms; transition-delay: 150ms;
background: rgba(255, 203, 0, .24); background: rgba(255, 203, 0, .24);

View File

@ -16,10 +16,10 @@
--> -->
<script lang="ts"> <script lang="ts">
import { IconAdd } from '@hcengineering/ui' import { IconAdd } from '@hcengineering/ui'
import { onDestroy } from 'svelte' import { onDestroy, onMount } from 'svelte'
import { NodeViewContent, NodeViewProps, NodeViewWrapper } from '../../node-view' import { NodeViewContent, NodeViewProps, NodeViewWrapper } from '../../node-view'
import { findTable, insertColumn, insertRow } from './utils' import { findTable, insertColumn, insertRow } from './utils'
import { TableMap } from '@tiptap/pm/tables' import { TableMap, updateColumnsOnResize } from '@tiptap/pm/tables'
import TableToolbar from './TableToolbar.svelte' import TableToolbar from './TableToolbar.svelte'
export let node: NodeViewProps['node'] export let node: NodeViewProps['node']
@ -66,58 +66,77 @@
} }
} }
function updateColumns (): void {
updateColumnsOnResize(node, colgroupElement, tableElement, 25)
}
$: if (node && colgroupElement && tableElement) {
updateColumns()
}
let tableElement: HTMLTableElement
let colgroupElement: HTMLTableColElement
onMount(() => {
updateColumns()
})
onDestroy(() => { onDestroy(() => {
editor.off('selectionUpdate', handleSelectionUpdate) editor.off('selectionUpdate', handleSelectionUpdate)
}) })
</script> </script>
<!-- prettier-ignore -->
<NodeViewWrapper class="table-node-wrapper" data-drag-handle> <NodeViewWrapper class="table-node-wrapper" data-drag-handle>
<div class="table-wrapper" class:table-selected={editable && focused}> <div class="table-wrapper" class:table-selected={editable && focused}>
<table class={className}> <div class="table-scroller">
<NodeViewContent as="tbody" /> <table class={className} bind:this={tableElement}>
</table> <colgroup bind:this={colgroupElement} />
<NodeViewContent as="tbody" />
{#if editable && focused} </table><!-- this comment is necessary to remove the whitespace character that Svelte adds between elements, which causes various problems in prosemirror
<div class="table-toolbar-container" contenteditable="false"> --></div><!-- https://github.com/sveltejs/svelte/issues/12765
<TableToolbar {editor} /> --><div class="table-toolbar-components" contenteditable="false">
</div> {#if editable && focused}
<div class="table-toolbar-container">
<!-- add col button --> <TableToolbar {editor} />
<div class="table-button-container table-button-container__col flex" contenteditable="false">
<div class="w-full h-full flex showOnHover">
<button class="table-button w-full h-full" on:click={handleAddColumn}>
<div class="table-button__dot" />
<div class="table-button__icon"><IconAdd size={'small'} /></div>
</button>
</div> </div>
</div> <!-- add col button -->
<div class="table-button-container table-button-container__col flex">
<!-- add row button --> <div class="w-full h-full flex showOnHover">
<div class="table-button-container table-button-container__row flex" contenteditable="false"> <button class="table-button w-full h-full" on:click={handleAddColumn}>
<div class="w-full h-full flex showOnHover"> <div class="table-button__dot" />
<button class="table-button w-full h-full" on:click={handleAddRow}> <div class="table-button__icon"><IconAdd size={'small'} /></div>
<div class="table-button__dot" /> </button>
<div class="table-button__icon"><IconAdd size={'small'} /></div> </div>
</button>
</div> </div>
</div> <!-- add row button -->
{/if} <div class="table-button-container table-button-container__row flex">
<div class="w-full h-full flex showOnHover">
<button class="table-button w-full h-full" on:click={handleAddRow}>
<div class="table-button__dot" />
<div class="table-button__icon"><IconAdd size={'small'} /></div>
</button>
</div>
</div>
{/if}
</div>
</div> </div>
</NodeViewWrapper> </NodeViewWrapper>
<style lang="scss"> <style lang="scss">
.table-wrapper { .table-wrapper {
position: relative; --table-offscreen-spacing: 2rem;
display: flex;
padding: 1.25rem 0;
&::before { width: max-content;
content: ''; max-width: calc(100% + var(--table-offscreen-spacing) * 2);
position: absolute; position: relative;
top: 0;
bottom: 0; margin: 0 calc(var(--table-offscreen-spacing) * -1);
left: 0;
right: 0; .table-scroller {
padding: 1.25rem var(--table-offscreen-spacing);
overflow-x: scroll;
scrollbar-width: auto;
} }
.table-button-container { .table-button-container {
@ -156,26 +175,22 @@
} }
&__col { &__col {
right: -1.25rem; right: -1.5rem;
top: 0; top: 0;
bottom: 0; bottom: 0;
margin: 1.25rem 0; margin: 1.25rem 0;
.table-button { .table-button {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
width: 1.25rem; width: 1.25rem;
} }
} }
&__row { &__row {
bottom: 0; bottom: -0.25rem;
left: 0; left: var(--table-offscreen-spacing);
right: 0; right: 0;
.table-button { .table-button {
border-top-left-radius: 0;
border-top-right-radius: 0;
height: 1.25rem; height: 1.25rem;
} }
} }

View File

@ -77,7 +77,7 @@ export const tableKitExtensions: KitExtension[] = [
[ [
10, 10,
Table.configure({ Table.configure({
resizable: false, resizable: true,
HTMLAttributes: { HTMLAttributes: {
class: 'proseTable' class: 'proseTable'
} }