@streamscloud/kit 0.77.0 → 0.78.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/utils/color-helper.d.ts +10 -0
- package/dist/core/utils/color-helper.js +25 -1
- package/dist/ui/table/cmp.table-draggable.svelte +47 -335
- package/dist/ui/table/cmp.table-draggable.svelte.d.ts +21 -18
- package/dist/ui/table/cmp.table.svelte +14 -286
- package/dist/ui/table/cmp.table.svelte.d.ts +23 -17
- package/dist/ui/table/table-core.svelte +407 -0
- package/dist/ui/table/table-core.svelte.d.ts +88 -0
- package/dist/ui/table/table-localization.d.ts +1 -0
- package/dist/ui/table/table-localization.js +7 -0
- package/dist/ui/table/table-model.svelte.js +9 -1
- package/dist/ui/table/types.d.ts +6 -2
- package/package.json +1 -1
- package/dist/ui/table/_table-styles.scss +0 -187
- package/dist/ui/table/table-view.svelte.d.ts +0 -15
- package/dist/ui/table/table-view.svelte.js +0 -54
|
@@ -14,4 +14,14 @@ export declare class ColorHelper {
|
|
|
14
14
|
* Check whether a color value fully hides what is behind it (valid, 100% alpha).
|
|
15
15
|
*/
|
|
16
16
|
static isOpaque(value: string | null | undefined): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Mix `color` towards `target` by `amount` (`0` = `color`, `1` = `target`) through the LAB color space — the same result as colord's `mix`.
|
|
19
|
+
* Returns a hex in the `normalizeHex` contract, or `''` when either input is invalid.
|
|
20
|
+
*/
|
|
21
|
+
static mix(color: string | null | undefined, target: string | null | undefined, amount: number): string;
|
|
22
|
+
/**
|
|
23
|
+
* Strict hex check: `#RGB`, `#RRGGBB` or `#RRGGBBAA`, case-insensitive. Unlike `normalizeHex`, colour names and functional notations (`red`, `rgb(…)`)
|
|
24
|
+
* are rejected.
|
|
25
|
+
*/
|
|
26
|
+
static isHex(value: string | null | undefined): boolean;
|
|
17
27
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { colord, extend } from 'colord';
|
|
2
|
+
import mixPlugin from 'colord/plugins/mix';
|
|
2
3
|
import namesPlugin from 'colord/plugins/names';
|
|
3
|
-
extend([namesPlugin]);
|
|
4
|
+
extend([namesPlugin, mixPlugin]);
|
|
5
|
+
const HEX_PATTERN = /^#(?:[0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i;
|
|
4
6
|
export class ColorHelper {
|
|
5
7
|
/**
|
|
6
8
|
* Normalize a color value to a clean hex string.
|
|
@@ -43,4 +45,26 @@ export class ColorHelper {
|
|
|
43
45
|
const parsed = colord(value);
|
|
44
46
|
return parsed.isValid() && parsed.alpha() === 1;
|
|
45
47
|
}
|
|
48
|
+
/**
|
|
49
|
+
* Mix `color` towards `target` by `amount` (`0` = `color`, `1` = `target`) through the LAB color space — the same result as colord's `mix`.
|
|
50
|
+
* Returns a hex in the `normalizeHex` contract, or `''` when either input is invalid.
|
|
51
|
+
*/
|
|
52
|
+
static mix(color, target, amount) {
|
|
53
|
+
if (!color || !target || !Number.isFinite(amount)) {
|
|
54
|
+
return '';
|
|
55
|
+
}
|
|
56
|
+
const from = colord(color);
|
|
57
|
+
const to = colord(target);
|
|
58
|
+
if (!from.isValid() || !to.isValid()) {
|
|
59
|
+
return '';
|
|
60
|
+
}
|
|
61
|
+
return ColorHelper.normalizeHex(from.mix(to, amount).toHex());
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Strict hex check: `#RGB`, `#RRGGBB` or `#RRGGBBAA`, case-insensitive. Unlike `normalizeHex`, colour names and functional notations (`red`, `rgb(…)`)
|
|
65
|
+
* are rejected.
|
|
66
|
+
*/
|
|
67
|
+
static isHex(value) {
|
|
68
|
+
return !!value && HEX_PATTERN.test(value);
|
|
69
|
+
}
|
|
46
70
|
}
|
|
@@ -1,168 +1,58 @@
|
|
|
1
|
-
<script lang="ts" generics="T extends {id: string}">import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
import { TableLocalization } from './table-localization';
|
|
6
|
-
import { columnCellStyle, createTableView } from './table-view.svelte';
|
|
7
|
-
import IconReorderDotsHorizontal from '@fluentui/svg-icons/icons/re_order_dots_horizontal_20_regular.svg?raw';
|
|
8
|
-
import { flip } from 'svelte/animate';
|
|
9
|
-
import { dndzone } from 'svelte-dnd-action';
|
|
10
|
-
let { model, showAlternativeView = false, noItemsPlaceholderEnabled, noItemsPlaceholderDelay, on, alternativeView, customNoItemsPlaceholder } = $props();
|
|
11
|
-
const localization = new TableLocalization();
|
|
12
|
-
const view = createTableView(() => model, () => on, () => noItemsPlaceholderEnabled, () => noItemsPlaceholderDelay);
|
|
13
|
-
const flipDurationMs = 200;
|
|
14
|
-
let tableRef = $state.raw(null);
|
|
1
|
+
<script lang="ts" generics="T extends {id: string}">import { TABLE_ROW_FLIP_DURATION_MS, default as TableCore, styleTableRowClone } from './table-core.svelte';
|
|
2
|
+
import { fromAction } from 'svelte/attachments';
|
|
3
|
+
import { dragHandle, dragHandleZone } from 'svelte-dnd-action';
|
|
4
|
+
let { model, on, ...shared } = $props();
|
|
15
5
|
let dndItems = $state.raw(null);
|
|
16
|
-
const
|
|
17
|
-
const
|
|
6
|
+
const orderedItems = $derived(dndItems ?? model.items);
|
|
7
|
+
const rows = $derived(orderedItems.map((item, index) => ({ kind: 'item', key: item.id, item, index })));
|
|
8
|
+
let body = null;
|
|
9
|
+
const isSameOrder = (next) => next.length === model.items.length && next.every((item, index) => item.id === model.items[index].id);
|
|
18
10
|
const handleConsider = (e) => {
|
|
19
11
|
dndItems = e.detail.items;
|
|
20
12
|
};
|
|
21
13
|
const handleFinalize = (e) => {
|
|
22
|
-
|
|
23
|
-
|
|
14
|
+
const next = e.detail.items;
|
|
15
|
+
if (!isSameOrder(next)) {
|
|
16
|
+
model.items = next;
|
|
17
|
+
on?.itemsReordered?.(next);
|
|
18
|
+
}
|
|
24
19
|
dndItems = null;
|
|
25
20
|
};
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
};
|
|
30
|
-
const transformDraggedElement = (draggedRow) => {
|
|
31
|
-
if (!draggedRow) {
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
const referenceRow = tableRef.querySelector('tbody tr:not([data-is-dnd-shadow-item-internal])') ?? tableRef.querySelector('tbody tr');
|
|
35
|
-
const referenceColumns = referenceRow?.querySelectorAll('td') ?? [];
|
|
36
|
-
const draggedColumns = draggedRow.querySelectorAll('td');
|
|
37
|
-
if (!referenceRow || referenceColumns.length !== draggedColumns.length) {
|
|
38
|
-
console.error('DraggableTable: dragged row column count does not match the reference row');
|
|
39
|
-
return;
|
|
21
|
+
const transformDraggedElement = (clone, _data, rowIndex) => {
|
|
22
|
+
if (clone && body && rowIndex !== undefined) {
|
|
23
|
+
styleTableRowClone(clone, body, rowIndex);
|
|
40
24
|
}
|
|
41
|
-
for (let i = 0, length = referenceColumns.length; i < length; i++) {
|
|
42
|
-
draggedColumns[i].style.width = `${referenceColumns[i].clientWidth}px`;
|
|
43
|
-
draggedColumns[i].style.height = `${referenceColumns[i].clientHeight}px`;
|
|
44
|
-
}
|
|
45
|
-
// Clone is reparented to <body>, losing the .table-container --_table--* vars; cells collapse without this.
|
|
46
|
-
const cellStyle = window.getComputedStyle(referenceColumns[0]);
|
|
47
|
-
// Read off the table, not a cell: the drag-handle cell zeroes its own padding and per-column cellPadding overrides live on their td.
|
|
48
|
-
const tableStyle = window.getComputedStyle(tableRef);
|
|
49
|
-
draggedRow.style.setProperty('--_table--cell--font-size', cellStyle.fontSize);
|
|
50
|
-
draggedRow.style.setProperty('--_table--cell--padding-inline', tableStyle.getPropertyValue('--_table--cell--padding-inline'));
|
|
51
|
-
draggedRow.style.setProperty('--_table--cell--padding-block', tableStyle.getPropertyValue('--_table--cell--padding-block'));
|
|
52
|
-
draggedRow.style.setProperty('--_table--cell--vertical-align', cellStyle.verticalAlign);
|
|
53
25
|
};
|
|
26
|
+
const reorderZone = fromAction(dragHandleZone, () => ({
|
|
27
|
+
items: orderedItems,
|
|
28
|
+
dropFromOthersDisabled: true,
|
|
29
|
+
flipDurationMs: TABLE_ROW_FLIP_DURATION_MS,
|
|
30
|
+
dropTargetStyle: {},
|
|
31
|
+
transformDraggedElement,
|
|
32
|
+
type: 'table'
|
|
33
|
+
}));
|
|
34
|
+
const attachment = (node) => {
|
|
35
|
+
body = node;
|
|
36
|
+
node.addEventListener('consider', handleConsider);
|
|
37
|
+
node.addEventListener('finalize', handleFinalize);
|
|
38
|
+
reorderZone(node);
|
|
39
|
+
return () => {
|
|
40
|
+
node.removeEventListener('consider', handleConsider);
|
|
41
|
+
node.removeEventListener('finalize', handleFinalize);
|
|
42
|
+
body = null;
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
const reorder = { attachment, handleAttachment: fromAction(dragHandle) };
|
|
54
46
|
</script>
|
|
55
47
|
|
|
56
|
-
{
|
|
57
|
-
{#if customNoItemsPlaceholder}
|
|
58
|
-
{@render customNoItemsPlaceholder()}
|
|
59
|
-
{:else}
|
|
60
|
-
<EmptyState graphic="zero-content" title={localization.noItemsFoundTitle} description={localization.noItemsFoundBody} />
|
|
61
|
-
{/if}
|
|
62
|
-
{/snippet}
|
|
63
|
-
|
|
64
|
-
<div class="table-container table-container--{model.styles?.size ?? 'md'} table-container--{model.styles?.variant ?? 'plain'}">
|
|
65
|
-
{#if alternativeView && showAlternativeView}
|
|
66
|
-
{#if view.showNoItemsPlaceholder}
|
|
67
|
-
<div class="alternative-view__placeholder">{@render noItemsContent()}</div>
|
|
68
|
-
{:else}
|
|
69
|
-
{@render alternativeView()}
|
|
70
|
-
{/if}
|
|
71
|
-
{:else}
|
|
72
|
-
<table
|
|
73
|
-
class="table"
|
|
74
|
-
class:table--sticky-header={model.styles?.stickyHeader === true}
|
|
75
|
-
class:table--fixed={model.styles?.layout === 'fixed'}
|
|
76
|
-
bind:this={tableRef}>
|
|
77
|
-
<thead class="table__head">
|
|
78
|
-
<tr>
|
|
79
|
-
<th class="table__th table__drag-handle"> </th>
|
|
80
|
-
{#each model.columns as column (column)}
|
|
81
|
-
<TableHideableCell column={column}>
|
|
82
|
-
<th class="table__th" class:table__th--centered={column.centered} style={columnCellStyle(column)} title={column.title}>
|
|
83
|
-
<DynamicComponent model={column.headerView} />
|
|
84
|
-
</th>
|
|
85
|
-
</TableHideableCell>
|
|
86
|
-
{/each}
|
|
87
|
-
</tr>
|
|
88
|
-
</thead>
|
|
89
|
-
<tbody
|
|
90
|
-
use:dndzone={{
|
|
91
|
-
items: rows,
|
|
92
|
-
dropFromOthersDisabled: true,
|
|
93
|
-
flipDurationMs,
|
|
94
|
-
dropTargetStyle: {},
|
|
95
|
-
transformDraggedElement,
|
|
96
|
-
type: 'table'
|
|
97
|
-
}}
|
|
98
|
-
onconsider={handleConsider}
|
|
99
|
-
onfinalize={handleFinalize}>
|
|
100
|
-
{#if view.showNoItemsPlaceholder}
|
|
101
|
-
<tr class="table__tr table__tr--placeholder">
|
|
102
|
-
<td colspan={visibleColspan}>
|
|
103
|
-
<div class="table__placeholder">{@render noItemsContent()}</div>
|
|
104
|
-
</td>
|
|
105
|
-
</tr>
|
|
106
|
-
{:else}
|
|
107
|
-
{#each rows as item, itemIndex (item)}
|
|
108
|
-
{@const isSelected = model.selection.has(item.id)}
|
|
109
|
-
{@const isHighlighted = model.highlightedItemIds.includes(item.id)}
|
|
110
|
-
{@const flushBottom = model.styles?.variant === 'card' && itemIndex === rows.length - 1}
|
|
111
|
-
{@const zebra = model.styles?.zebra === true && itemIndex % 2 === 1 && !isSelected && !isHighlighted}
|
|
112
|
-
<tr
|
|
113
|
-
animate:flip={{ duration: flipDurationMs }}
|
|
114
|
-
class="table__tr"
|
|
115
|
-
id={item.id}
|
|
116
|
-
class:table__tr--selected={isSelected}
|
|
117
|
-
class:table__tr--highlighted={isHighlighted}
|
|
118
|
-
class:table__tr--zebra={zebra}>
|
|
119
|
-
<td
|
|
120
|
-
class="table__td table__drag-handle table__drag-handle--dragging"
|
|
121
|
-
class:table__td--flush={flushBottom}
|
|
122
|
-
onmousedown={startDrag}
|
|
123
|
-
ontouchstart={startDrag}>
|
|
124
|
-
<div class="table__cell">
|
|
125
|
-
<Icon src={IconReorderDotsHorizontal} />
|
|
126
|
-
</div>
|
|
127
|
-
</td>
|
|
128
|
-
{#each model.columns as column (column)}
|
|
129
|
-
<TableHideableCell column={column}>
|
|
130
|
-
<td
|
|
131
|
-
class="table__td"
|
|
132
|
-
class:table__td--centered={column.centered}
|
|
133
|
-
class:table__td--clickable={!!column.onClick}
|
|
134
|
-
class:table__td--flush={flushBottom}
|
|
135
|
-
style={columnCellStyle(column)}
|
|
136
|
-
onclick={() => column.onClick && column.onClick(item)}>
|
|
137
|
-
<div class="table__cell" class:table__cell--reveal-on-row-hover={column.revealOnRowHover}>
|
|
138
|
-
<TableCell model={model} item={item} column={column} itemIndex={itemIndex} on={{ itemsReordered: on?.itemsReordered }} />
|
|
139
|
-
</div>
|
|
140
|
-
</td>
|
|
141
|
-
</TableHideableCell>
|
|
142
|
-
{/each}
|
|
143
|
-
</tr>
|
|
144
|
-
{/each}
|
|
145
|
-
{/if}
|
|
146
|
-
</tbody>
|
|
147
|
-
</table>
|
|
148
|
-
{/if}
|
|
149
|
-
</div>
|
|
48
|
+
<TableCore {...shared} model={model} on={on} rows={rows} reorder={reorder} />
|
|
150
49
|
|
|
151
50
|
<!--
|
|
152
51
|
@component
|
|
153
52
|
Data table with drag-and-drop row reordering, plus everything `Table` offers (sorting, selection, column
|
|
154
|
-
visibility, group actions). A leading drag-handle column is rendered
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
### TableStyles (via `model.styles`)
|
|
158
|
-
| Field | Type | Effect |
|
|
159
|
-
|---|---|---|
|
|
160
|
-
| `size` | `'sm' \| 'md'` | Row height + cell padding + font-size preset (default `'md'`) |
|
|
161
|
-
| `variant` | `'plain' \| 'card'` | `'card'` wraps the table in a bordered rounded panel (default `'plain'`) |
|
|
162
|
-
| `zebra` | `boolean` | Alternates row backgrounds with `--sc-kit--color--bg--field-alt` |
|
|
163
|
-
| `stickyHeader` | `boolean` | Sticks `thead` to the scrolling ancestor |
|
|
164
|
-
| `actionsPopoverTopDirection` | `boolean` | Forces the per-row actions popover above instead of below |
|
|
165
|
-
| `layout` | `'auto' \| 'fixed'` | `'fixed'` honours `cssWidth` exactly; percent columns share what fixed ones leave, `minCssWidth` is ignored (default `'auto'`) |
|
|
53
|
+
visibility, group actions). A leading drag-handle column is rendered and a row is dragged by its handle only;
|
|
54
|
+
a drop that changes the order fires `on.itemsReordered` and preserves the current selection, a drop back in place
|
|
55
|
+
fires nothing. For non-reorderable tables use `Table` (it ships no dnd code).
|
|
166
56
|
|
|
167
57
|
### CSS Custom Properties
|
|
168
58
|
| Property | Description | Default |
|
|
@@ -173,7 +63,10 @@ preserve the current selection. For non-reorderable tables use `Table` (it ships
|
|
|
173
63
|
| `--sc-kit--table--cell--padding-block` | Cell block padding | `0` |
|
|
174
64
|
| `--sc-kit--table--cell--vertical-align` | Cell content alignment — `top` keeps inputs aligned when one cell grows | `middle` |
|
|
175
65
|
| `--sc-kit--table--head--height` | Header row height | per size (32 / 40 px) |
|
|
176
|
-
| `--sc-kit--table--head--background-color` | Header background | `--sc-kit--color--bg--field-alt` |
|
|
66
|
+
| `--sc-kit--table--head--background-color` | Header background | `--sc-kit--color--bg--field-alt`; with a `toolbar`, the card / panel background |
|
|
67
|
+
| `--sc-kit--table--toolbar--background-color` | Toolbar band background | `--sc-kit--color--bg--field-alt` |
|
|
68
|
+
| `--sc-kit--table--toolbar--padding-block` | Toolbar band block padding — `0` hands the band to the toolbar content | `--sc-kit--space--3` |
|
|
69
|
+
| `--sc-kit--table--toolbar--padding-inline` | Toolbar band inline padding | the cell inline padding |
|
|
177
70
|
| `--sc-kit--table--head--color` | Header text color | `--sc-kit--color--text--secondary` |
|
|
178
71
|
| `--sc-kit--table--head--font-size` | Header font size | `--sc-kit--font-size--sm` |
|
|
179
72
|
| `--sc-kit--table--head--font-weight` | Header font weight | `--sc-kit--font-weight--semibold` |
|
|
@@ -183,192 +76,11 @@ preserve the current selection. For non-reorderable tables use `Table` (it ships
|
|
|
183
76
|
| `--sc-kit--table--row--color` | Row background | `transparent` |
|
|
184
77
|
| `--sc-kit--table--row--alternative-color` | Hover / highlighted row background | `--sc-kit--color--bg--hover` |
|
|
185
78
|
| `--sc-kit--table--zebra--color` | Zebra-row background (when `zebra` on) | `light-dark(#fcfcfd, #232323)` |
|
|
79
|
+
| `--sc-kit--table--selected--color` | Selected row background | `--sc-kit--color--accent--softer` |
|
|
80
|
+
| `--sc-kit--table--selected--color--hover` | Selected row background on hover | `--sc-kit--color--accent--soft` |
|
|
186
81
|
| `--sc-kit--table--card--background` | Card variant background | `--sc-kit--color--bg--panel` |
|
|
187
82
|
| `--sc-kit--table--card--border-color` | Card variant border | `--sc-kit--color--border` |
|
|
188
83
|
| `--sc-kit--table--card--border-radius` | Card variant radius | `--sc-kit--radius--lg` |
|
|
189
84
|
| `--sc-kit--table--card--padding-bottom` | Card variant bottom padding | `--sc-kit--space--4` |
|
|
85
|
+
| `--sc-kit--table--min-width` | Table floor — past it the columns scroll horizontally inside the chrome, the toolbar stays. The column-floor substitute under `layout: 'fixed'` | `auto` |
|
|
190
86
|
-->
|
|
191
|
-
|
|
192
|
-
<style>.alternative-view__placeholder {
|
|
193
|
-
width: 100%;
|
|
194
|
-
display: flex;
|
|
195
|
-
align-items: center;
|
|
196
|
-
justify-content: center;
|
|
197
|
-
font-size: 80%;
|
|
198
|
-
user-select: none;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
.table-container {
|
|
202
|
-
--_table--row--height: var(--sc-kit--table--row--height, var(--_table--size-row-height));
|
|
203
|
-
--_table--cell--font-size: var(--sc-kit--table--cell--font-size, var(--_table--size-cell-font-size));
|
|
204
|
-
--_table--cell--padding-inline: var(--sc-kit--table--cell--padding-inline, var(--_table--size-cell-padding));
|
|
205
|
-
--_table--cell--padding-block: var(--sc-kit--table--cell--padding-block, 0);
|
|
206
|
-
--_table--cell--vertical-align: var(--sc-kit--table--cell--vertical-align, middle);
|
|
207
|
-
--_table--head--height: var(--sc-kit--table--head--height, var(--_table--size-head-height, var(--_table--row--height)));
|
|
208
|
-
--_table--head--background-color: var(--sc-kit--table--head--background-color, var(--sc-kit--color--bg--field-alt));
|
|
209
|
-
--_table--head--color: var(--sc-kit--table--head--color, var(--sc-kit--color--text--secondary));
|
|
210
|
-
--_table--head--font-weight: var(--sc-kit--table--head--font-weight, var(--sc-kit--font-weight--semibold));
|
|
211
|
-
--_table--head--letter-spacing: var(--sc-kit--table--head--letter-spacing, normal);
|
|
212
|
-
--_table--head--text-transform: var(--sc-kit--table--head--text-transform, none);
|
|
213
|
-
--_table--border-color: var(--sc-kit--table--border-color, var(--sc-kit--color--border));
|
|
214
|
-
--_table--row--color: var(--sc-kit--table--row--color, transparent);
|
|
215
|
-
--_table--row--alternative-color: var(--sc-kit--table--row--alternative-color, var(--sc-kit--color--bg--hover));
|
|
216
|
-
--_table--zebra--color: var(--sc-kit--table--zebra--color, light-dark(#fcfcfd, #232323));
|
|
217
|
-
--_table--selected--color: var(--sc-kit--table--selected--color, var(--sc-kit--color--accent--softer));
|
|
218
|
-
--_table--selected--color-hover: var(--sc-kit--table--selected--color--hover, var(--sc-kit--color--accent--soft));
|
|
219
|
-
--_table--card--background: var(--sc-kit--table--card--background, var(--sc-kit--color--bg--panel));
|
|
220
|
-
--_table--card--border-color: var(--sc-kit--table--card--border-color, var(--sc-kit--color--border));
|
|
221
|
-
--_table--card--border-radius: var(--sc-kit--table--card--border-radius, var(--sc-kit--radius--lg));
|
|
222
|
-
--_table--card--padding-bottom: var(--sc-kit--table--card--padding-bottom, var(--sc-kit--space--4));
|
|
223
|
-
display: flex;
|
|
224
|
-
overflow-x: auto;
|
|
225
|
-
height: 100%;
|
|
226
|
-
--_cross-browser-scrollbar--thumb-color: var(--scrollbar--thumb-color, light-dark(#d1d5db, #4b5563));
|
|
227
|
-
--_cross-browser-scrollbar--track-color: var(--scrollbar--track-color, transparent);
|
|
228
|
-
}
|
|
229
|
-
.table-container::-webkit-scrollbar {
|
|
230
|
-
width: 6px;
|
|
231
|
-
height: 6px;
|
|
232
|
-
}
|
|
233
|
-
.table-container::-webkit-scrollbar-track {
|
|
234
|
-
background: var(--_cross-browser-scrollbar--track-color);
|
|
235
|
-
border-radius: 100vw;
|
|
236
|
-
}
|
|
237
|
-
.table-container::-webkit-scrollbar-thumb {
|
|
238
|
-
background: var(--_cross-browser-scrollbar--thumb-color);
|
|
239
|
-
border-radius: 100vw;
|
|
240
|
-
}
|
|
241
|
-
@supports (scrollbar-color: transparent transparent) {
|
|
242
|
-
.table-container {
|
|
243
|
-
scrollbar-color: var(--_cross-browser-scrollbar--thumb-color) var(--_cross-browser-scrollbar--track-color);
|
|
244
|
-
scrollbar-width: thin;
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
.table-container--md {
|
|
248
|
-
--_table--size-row-height: 2.75rem;
|
|
249
|
-
--_table--size-head-height: 2.5rem;
|
|
250
|
-
--_table--size-cell-font-size: var(--sc-kit--font-size--md);
|
|
251
|
-
--_table--size-cell-padding: var(--sc-kit--space--4);
|
|
252
|
-
}
|
|
253
|
-
.table-container--sm {
|
|
254
|
-
--_table--size-row-height: 2.25rem;
|
|
255
|
-
--_table--size-head-height: 2rem;
|
|
256
|
-
--_table--size-cell-font-size: var(--sc-kit--font-size--sm);
|
|
257
|
-
--_table--size-cell-padding: var(--sc-kit--space--3);
|
|
258
|
-
}
|
|
259
|
-
.table-container--card {
|
|
260
|
-
background: var(--_table--card--background);
|
|
261
|
-
border: 1px solid var(--_table--card--border-color);
|
|
262
|
-
border-radius: var(--_table--card--border-radius);
|
|
263
|
-
padding-bottom: var(--_table--card--padding-bottom);
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
.table {
|
|
267
|
-
width: 100%;
|
|
268
|
-
table-layout: auto;
|
|
269
|
-
height: fit-content;
|
|
270
|
-
border-collapse: separate;
|
|
271
|
-
border-spacing: 0;
|
|
272
|
-
}
|
|
273
|
-
.table--fixed {
|
|
274
|
-
table-layout: fixed;
|
|
275
|
-
}
|
|
276
|
-
.table__head {
|
|
277
|
-
height: var(--_table--head--height);
|
|
278
|
-
max-height: var(--_table--head--height);
|
|
279
|
-
background: var(--_table--head--background-color);
|
|
280
|
-
color: var(--_table--head--color);
|
|
281
|
-
font-size: var(--sc-kit--table--head--font-size, var(--sc-kit--font-size--sm));
|
|
282
|
-
letter-spacing: var(--_table--head--letter-spacing);
|
|
283
|
-
text-transform: var(--_table--head--text-transform);
|
|
284
|
-
}
|
|
285
|
-
.table__th {
|
|
286
|
-
padding: 0 var(--_table--cell--padding-inline);
|
|
287
|
-
font-weight: var(--_table--head--font-weight);
|
|
288
|
-
text-align: left;
|
|
289
|
-
vertical-align: middle;
|
|
290
|
-
border-bottom: 1px solid var(--_table--border-color);
|
|
291
|
-
-webkit-user-drag: none;
|
|
292
|
-
user-select: none;
|
|
293
|
-
}
|
|
294
|
-
.table__th :global([contenteditable]) {
|
|
295
|
-
user-select: text;
|
|
296
|
-
}
|
|
297
|
-
.table__th--centered {
|
|
298
|
-
--_--table-header--justify-content: center;
|
|
299
|
-
}
|
|
300
|
-
.table__tr {
|
|
301
|
-
height: var(--_table--row--height);
|
|
302
|
-
max-height: var(--_table--row--height);
|
|
303
|
-
background: var(--_table--row--color);
|
|
304
|
-
}
|
|
305
|
-
.table__tr--zebra {
|
|
306
|
-
background: var(--_table--zebra--color);
|
|
307
|
-
}
|
|
308
|
-
.table__tr:hover, .table__tr--highlighted {
|
|
309
|
-
background: var(--_table--row--alternative-color);
|
|
310
|
-
}
|
|
311
|
-
.table__tr:hover, .table__tr:focus-within {
|
|
312
|
-
--_table--row-reveal--opacity: 1;
|
|
313
|
-
}
|
|
314
|
-
@media (any-hover: none) {
|
|
315
|
-
.table__tr {
|
|
316
|
-
--_table--row-reveal--opacity: 1;
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
.table__tr--selected {
|
|
320
|
-
background: var(--_table--selected--color);
|
|
321
|
-
}
|
|
322
|
-
.table__tr--selected:hover {
|
|
323
|
-
background: var(--_table--selected--color-hover);
|
|
324
|
-
}
|
|
325
|
-
.table__tr--placeholder {
|
|
326
|
-
background: var(--_table--row--color) !important;
|
|
327
|
-
}
|
|
328
|
-
.table__td {
|
|
329
|
-
padding: 0;
|
|
330
|
-
border-bottom: 1px solid var(--_table--border-color);
|
|
331
|
-
font-size: var(--_table--cell--font-size);
|
|
332
|
-
color: var(--sc-kit--color--text--primary);
|
|
333
|
-
vertical-align: var(--_table--cell--vertical-align);
|
|
334
|
-
}
|
|
335
|
-
.table__td--centered {
|
|
336
|
-
text-align: center;
|
|
337
|
-
}
|
|
338
|
-
.table__td--clickable {
|
|
339
|
-
cursor: pointer;
|
|
340
|
-
}
|
|
341
|
-
.table__td--flush {
|
|
342
|
-
border-bottom: none;
|
|
343
|
-
}
|
|
344
|
-
.table__cell {
|
|
345
|
-
padding: var(--_table--cell--padding-block) var(--_table--cell--padding-inline);
|
|
346
|
-
}
|
|
347
|
-
.table__cell--reveal-on-row-hover {
|
|
348
|
-
opacity: var(--_table--row-reveal--opacity, 0);
|
|
349
|
-
transition: opacity var(--sc-kit--duration--base) var(--sc-kit--ease--default);
|
|
350
|
-
}
|
|
351
|
-
.table__placeholder {
|
|
352
|
-
display: flex;
|
|
353
|
-
align-items: center;
|
|
354
|
-
justify-content: center;
|
|
355
|
-
font-size: 80%;
|
|
356
|
-
user-select: none;
|
|
357
|
-
}
|
|
358
|
-
.table--sticky-header thead {
|
|
359
|
-
position: sticky;
|
|
360
|
-
top: 0;
|
|
361
|
-
z-index: 1;
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
.table__drag-handle {
|
|
365
|
-
--_table--cell--padding-inline: 0;
|
|
366
|
-
width: 3.25rem;
|
|
367
|
-
cursor: grab;
|
|
368
|
-
text-align: center;
|
|
369
|
-
--sc-kit--icon--size: 1.25rem;
|
|
370
|
-
--sc-kit--icon--color: var(--sc-kit--color--text--muted);
|
|
371
|
-
}
|
|
372
|
-
.table__drag-handle--dragging {
|
|
373
|
-
cursor: grabbing;
|
|
374
|
-
}</style>
|
|
@@ -6,10 +6,7 @@ declare function $$render<T extends {
|
|
|
6
6
|
props: {
|
|
7
7
|
model: TableModel<T>;
|
|
8
8
|
showAlternativeView?: boolean;
|
|
9
|
-
/**
|
|
10
|
-
* is never rendered over a non-empty list. @default true */
|
|
11
|
-
noItemsPlaceholderEnabled?: boolean;
|
|
12
|
-
/** Anti-flicker delay in ms before the placeholder appears, once `noItemsPlaceholderEnabled`. `0` shows it as soon as the list is empty. @default 0 */
|
|
9
|
+
/** Anti-flicker delay in ms before the placeholder appears. `0` shows it as soon as the list is empty. @default 0 */
|
|
13
10
|
noItemsPlaceholderDelay?: number;
|
|
14
11
|
on?: {
|
|
15
12
|
selectionChanged?: (e: T[]) => void;
|
|
@@ -18,7 +15,16 @@ declare function $$render<T extends {
|
|
|
18
15
|
itemsReordered?: (e: T[]) => void;
|
|
19
16
|
};
|
|
20
17
|
alternativeView?: Snippet;
|
|
21
|
-
|
|
18
|
+
/**
|
|
19
|
+
* What an empty list shows: the built-in empty state when omitted, your own content as a snippet, nothing with `false` — pairs with your own loading /
|
|
20
|
+
* empty UI. Rows always win: the placeholder is never rendered over a non-empty list.
|
|
21
|
+
*/
|
|
22
|
+
noItemsPlaceholder?: Snippet | false;
|
|
23
|
+
/**
|
|
24
|
+
* Band inside the table chrome above the column header row — a title and actions. With a toolbar the column header always sticks under it and takes
|
|
25
|
+
* the row background; an empty list drops the column header, leaving the toolbar and the no-items placeholder.
|
|
26
|
+
*/
|
|
27
|
+
toolbar?: Snippet;
|
|
22
28
|
};
|
|
23
29
|
exports: {};
|
|
24
30
|
bindings: "";
|
|
@@ -47,18 +53,9 @@ interface $$IsomorphicComponent {
|
|
|
47
53
|
}
|
|
48
54
|
/**
|
|
49
55
|
* Data table with drag-and-drop row reordering, plus everything `Table` offers (sorting, selection, column
|
|
50
|
-
* visibility, group actions). A leading drag-handle column is rendered
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
* ### TableStyles (via `model.styles`)
|
|
54
|
-
* | Field | Type | Effect |
|
|
55
|
-
* |---|---|---|
|
|
56
|
-
* | `size` | `'sm' \| 'md'` | Row height + cell padding + font-size preset (default `'md'`) |
|
|
57
|
-
* | `variant` | `'plain' \| 'card'` | `'card'` wraps the table in a bordered rounded panel (default `'plain'`) |
|
|
58
|
-
* | `zebra` | `boolean` | Alternates row backgrounds with `--sc-kit--color--bg--field-alt` |
|
|
59
|
-
* | `stickyHeader` | `boolean` | Sticks `thead` to the scrolling ancestor |
|
|
60
|
-
* | `actionsPopoverTopDirection` | `boolean` | Forces the per-row actions popover above instead of below |
|
|
61
|
-
* | `layout` | `'auto' \| 'fixed'` | `'fixed'` honours `cssWidth` exactly; percent columns share what fixed ones leave, `minCssWidth` is ignored (default `'auto'`) |
|
|
56
|
+
* visibility, group actions). A leading drag-handle column is rendered and a row is dragged by its handle only;
|
|
57
|
+
* a drop that changes the order fires `on.itemsReordered` and preserves the current selection, a drop back in place
|
|
58
|
+
* fires nothing. For non-reorderable tables use `Table` (it ships no dnd code).
|
|
62
59
|
*
|
|
63
60
|
* ### CSS Custom Properties
|
|
64
61
|
* | Property | Description | Default |
|
|
@@ -69,7 +66,10 @@ interface $$IsomorphicComponent {
|
|
|
69
66
|
* | `--sc-kit--table--cell--padding-block` | Cell block padding | `0` |
|
|
70
67
|
* | `--sc-kit--table--cell--vertical-align` | Cell content alignment — `top` keeps inputs aligned when one cell grows | `middle` |
|
|
71
68
|
* | `--sc-kit--table--head--height` | Header row height | per size (32 / 40 px) |
|
|
72
|
-
* | `--sc-kit--table--head--background-color` | Header background | `--sc-kit--color--bg--field-alt` |
|
|
69
|
+
* | `--sc-kit--table--head--background-color` | Header background | `--sc-kit--color--bg--field-alt`; with a `toolbar`, the card / panel background |
|
|
70
|
+
* | `--sc-kit--table--toolbar--background-color` | Toolbar band background | `--sc-kit--color--bg--field-alt` |
|
|
71
|
+
* | `--sc-kit--table--toolbar--padding-block` | Toolbar band block padding — `0` hands the band to the toolbar content | `--sc-kit--space--3` |
|
|
72
|
+
* | `--sc-kit--table--toolbar--padding-inline` | Toolbar band inline padding | the cell inline padding |
|
|
73
73
|
* | `--sc-kit--table--head--color` | Header text color | `--sc-kit--color--text--secondary` |
|
|
74
74
|
* | `--sc-kit--table--head--font-size` | Header font size | `--sc-kit--font-size--sm` |
|
|
75
75
|
* | `--sc-kit--table--head--font-weight` | Header font weight | `--sc-kit--font-weight--semibold` |
|
|
@@ -79,10 +79,13 @@ interface $$IsomorphicComponent {
|
|
|
79
79
|
* | `--sc-kit--table--row--color` | Row background | `transparent` |
|
|
80
80
|
* | `--sc-kit--table--row--alternative-color` | Hover / highlighted row background | `--sc-kit--color--bg--hover` |
|
|
81
81
|
* | `--sc-kit--table--zebra--color` | Zebra-row background (when `zebra` on) | `light-dark(#fcfcfd, #232323)` |
|
|
82
|
+
* | `--sc-kit--table--selected--color` | Selected row background | `--sc-kit--color--accent--softer` |
|
|
83
|
+
* | `--sc-kit--table--selected--color--hover` | Selected row background on hover | `--sc-kit--color--accent--soft` |
|
|
82
84
|
* | `--sc-kit--table--card--background` | Card variant background | `--sc-kit--color--bg--panel` |
|
|
83
85
|
* | `--sc-kit--table--card--border-color` | Card variant border | `--sc-kit--color--border` |
|
|
84
86
|
* | `--sc-kit--table--card--border-radius` | Card variant radius | `--sc-kit--radius--lg` |
|
|
85
87
|
* | `--sc-kit--table--card--padding-bottom` | Card variant bottom padding | `--sc-kit--space--4` |
|
|
88
|
+
* | `--sc-kit--table--min-width` | Table floor — past it the columns scroll horizontally inside the chrome, the toolbar stays. The column-floor substitute under `layout: 'fixed'` | `auto` |
|
|
86
89
|
*/
|
|
87
90
|
declare const Cmp: $$IsomorphicComponent;
|
|
88
91
|
type Cmp<T extends {
|