@x33025/sveltely 0.1.23 → 0.1.25
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/actions/LoaderOverlay.svelte +10 -3
- package/dist/components/Library/Accordion/Accordion.demo.svelte +21 -0
- package/dist/components/Library/Accordion/Accordion.demo.svelte.d.ts +9 -0
- package/dist/components/Library/Accordion/Accordion.svelte +78 -0
- package/dist/components/Library/Accordion/Accordion.svelte.d.ts +14 -0
- package/dist/components/Library/Accordion/Content.svelte +57 -0
- package/dist/components/Library/Accordion/Content.svelte.d.ts +8 -0
- package/dist/components/Library/Accordion/Header.svelte +98 -0
- package/dist/components/Library/Accordion/Header.svelte.d.ts +10 -0
- package/dist/components/Library/Accordion/context.d.ts +9 -0
- package/dist/components/Library/Accordion/context.js +6 -0
- package/dist/components/Library/Accordion/index.d.ts +9 -0
- package/dist/components/Library/Accordion/index.js +7 -0
- package/dist/components/Library/AnimatedNumber/AnimatedNumber.demo.svelte +3 -2
- package/dist/components/Library/ArticleEditor/ArticleEditor.svelte +1 -2
- package/dist/components/Library/ArticleEditor/Blocks/Table.svelte +133 -172
- package/dist/components/Library/Checkbox/Checkbox.demo.svelte +5 -4
- package/dist/components/Library/Checkbox/Checkbox.svelte +6 -5
- package/dist/components/Library/Checkbox/Checkbox.svelte.d.ts +2 -1
- package/dist/components/Library/ChipInput/ChipInput.demo.svelte +3 -2
- package/dist/components/Library/Dropdown/Dropdown.demo.svelte +20 -15
- package/dist/components/Library/Floating/Floating.svelte +5 -6
- package/dist/components/Library/Grid/Grid.demo.svelte +58 -0
- package/dist/components/Library/Grid/Grid.demo.svelte.d.ts +25 -0
- package/dist/components/Library/Grid/Grid.svelte +128 -25
- package/dist/components/Library/Grid/Grid.svelte.d.ts +38 -9
- package/dist/components/Library/Grid/GridItem.svelte +18 -14
- package/dist/components/Library/Grid/GridItem.svelte.d.ts +2 -1
- package/dist/components/Library/HStack/HStack.svelte +4 -4
- package/dist/components/Library/HStack/HStack.svelte.d.ts +2 -1
- package/dist/components/Library/Image/Image.demo.svelte +3 -1
- package/dist/components/Library/Image/Image.demo.svelte.d.ts +2 -0
- package/dist/components/Library/ImageMask/ImageMask.demo.svelte +8 -6
- package/dist/components/Library/Label/Label.demo.svelte +5 -5
- package/dist/components/Library/Label/Label.svelte +10 -26
- package/dist/components/Library/NavigationStack/Link.svelte +1 -4
- package/dist/components/Library/Notifications/Notifications.demo.svelte +63 -0
- package/dist/components/Library/Notifications/Notifications.demo.svelte.d.ts +9 -0
- package/dist/components/Library/Notifications/Notifications.svelte +155 -0
- package/dist/components/Library/Notifications/Notifications.svelte.d.ts +35 -0
- package/dist/components/Library/Notifications/index.d.ts +2 -0
- package/dist/components/Library/Notifications/index.js +1 -0
- package/dist/components/Library/Notifications/types.d.ts +8 -0
- package/dist/components/Library/Notifications/types.js +1 -0
- package/dist/components/Library/NumberField/NumberField.svelte +25 -19
- package/dist/components/Library/Pagination/Pagination.demo.svelte +3 -2
- package/dist/components/Library/Pagination/Pagination.svelte +6 -18
- package/dist/components/Library/Popover/PopoverDebugOverlay.svelte +3 -3
- package/dist/components/Library/Portal/Content.svelte +20 -0
- package/dist/components/Library/Portal/Content.svelte.d.ts +10 -0
- package/dist/components/Library/Portal/Portal.svelte +4 -0
- package/dist/components/Library/Portal/Portal.svelte.d.ts +1 -0
- package/dist/components/Library/Portal/index.d.ts +1 -0
- package/dist/components/Library/Portal/index.js +1 -0
- package/dist/components/Library/ScrollView/ScrollView.svelte +88 -9
- package/dist/components/Library/ScrollView/ScrollView.svelte.d.ts +9 -2
- package/dist/components/Library/ScrollView/index.d.ts +1 -1
- package/dist/components/Library/SearchField/SearchField.demo.svelte +3 -2
- package/dist/components/Library/SearchField/SearchField.svelte +5 -5
- package/dist/components/Library/SearchField/SearchField.svelte.d.ts +2 -1
- package/dist/components/Library/SegmentedPicker/SegmentedPicker.demo.svelte +3 -2
- package/dist/components/Library/Sheet/Sheet.demo.svelte +3 -2
- package/dist/components/Library/Sheet/Sheet.svelte +3 -3
- package/dist/components/Library/Slider/Slider.demo.svelte +3 -2
- package/dist/components/Library/Spinner/Spinner.demo.svelte +3 -2
- package/dist/components/Library/Switch/Switch.demo.svelte +5 -4
- package/dist/components/Library/Switch/Switch.svelte +6 -5
- package/dist/components/Library/Switch/Switch.svelte.d.ts +2 -1
- package/dist/components/Library/Table/Column.svelte +3 -0
- package/dist/components/Library/Table/Column.svelte.d.ts +1 -0
- package/dist/components/Library/Table/Table.demo.svelte +230 -17
- package/dist/components/Library/Table/Table.svelte +322 -78
- package/dist/components/Library/Table/Table.svelte.d.ts +5 -0
- package/dist/components/Library/Table/types.d.ts +1 -0
- package/dist/components/Library/TextField/TextField.svelte +20 -14
- package/dist/components/Library/TextShimmer/TextShimmer.demo.svelte +3 -2
- package/dist/components/Library/TimePicker/TimePicker.demo.svelte +3 -10
- package/dist/components/Library/TokenSearchField/TokenSearchField.demo.svelte +3 -2
- package/dist/components/Library/VStack/VStack.svelte +4 -4
- package/dist/components/Library/VStack/VStack.svelte.d.ts +2 -1
- package/dist/components/Local/ColorStyleControls.svelte +25 -72
- package/dist/components/Local/ComponentGrid.svelte +99 -27
- package/dist/components/Local/ComponentGrid.svelte.d.ts +2 -1
- package/dist/components/Local/ComponentPage.svelte +74 -0
- package/dist/components/Local/ComponentPage.svelte.d.ts +13 -0
- package/dist/components/Local/HeroCard.svelte +10 -6
- package/dist/components/Local/LayoutStyleControls.svelte +33 -25
- package/dist/components/Local/StyleControls.svelte +1 -1
- package/dist/index.d.ts +8 -3
- package/dist/index.js +4 -1
- package/dist/style/index.css +3 -4
- package/dist/style/layout.d.ts +15 -36
- package/dist/style/layout.js +35 -83
- package/dist/style/surface.d.ts +1 -0
- package/dist/style/surface.js +10 -0
- package/dist/style.css +3 -51
- package/dist/viewport/geometry.d.ts +8 -0
- package/dist/viewport/geometry.js +43 -0
- package/dist/viewport/index.d.ts +4 -0
- package/dist/viewport/index.js +4 -0
- package/dist/viewport/layout.d.ts +4 -0
- package/dist/viewport/layout.js +138 -0
- package/dist/viewport/placement.d.ts +4 -0
- package/dist/viewport/placement.js +14 -0
- package/dist/viewport/types.d.ts +81 -0
- package/dist/viewport/types.js +1 -0
- package/package.json +1 -1
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
import { extractLoaderProps, resolveLoaderOptions, type LoaderProps } from '../../../style/loader';
|
|
9
9
|
import { extractLayoutProps, layoutStyle, type LayoutProps } from '../../../style/layout';
|
|
10
10
|
import { extractStyleProps, surfaceStyle, type StyleProps } from '../../../style/surface';
|
|
11
|
+
import { tableViewportLayout, type ViewportGeometry, type ViewportOverscan } from '../../../viewport';
|
|
11
12
|
import ScrollView from '../ScrollView';
|
|
12
13
|
import { TABLE_CONTEXT } from './context';
|
|
13
14
|
import type {
|
|
@@ -31,6 +32,10 @@
|
|
|
31
32
|
columnHeaders?: TableColumnHeaderVisibility;
|
|
32
33
|
columnCustomization?: TableColumnCustomization;
|
|
33
34
|
emptyLabel?: string;
|
|
35
|
+
virtualized?: boolean;
|
|
36
|
+
rowHeight?: number;
|
|
37
|
+
headerHeight?: number;
|
|
38
|
+
overscan?: ViewportOverscan;
|
|
34
39
|
onSortOrderChange?: (sortOrder: TableSortDescriptor<T>[]) => void;
|
|
35
40
|
onSelectionChange?: (selection: TableSelection) => void;
|
|
36
41
|
} & LayoutProps &
|
|
@@ -48,12 +53,21 @@
|
|
|
48
53
|
columnHeaders = 'visible',
|
|
49
54
|
columnCustomization = $bindable<TableColumnCustomization>({}),
|
|
50
55
|
emptyLabel = 'No rows',
|
|
56
|
+
virtualized = false,
|
|
57
|
+
rowHeight = 42,
|
|
58
|
+
headerHeight = 38,
|
|
59
|
+
overscan = 160,
|
|
51
60
|
onSortOrderChange,
|
|
52
61
|
onSelectionChange,
|
|
53
62
|
...restProps
|
|
54
63
|
}: Props = $props();
|
|
55
64
|
|
|
56
65
|
let tableSortOrder = $state<TableSortDescriptor<T>[]>(sortOrder);
|
|
66
|
+
let scrollOffsetX = $state(0);
|
|
67
|
+
let viewport = $state<ViewportGeometry>({
|
|
68
|
+
offset: { x: 0, y: 0 },
|
|
69
|
+
viewport: { width: 0, height: 0 }
|
|
70
|
+
});
|
|
57
71
|
let dragSelection = $state<{
|
|
58
72
|
active: boolean;
|
|
59
73
|
pointerId: number;
|
|
@@ -88,18 +102,7 @@
|
|
|
88
102
|
typeof value === 'number' ? `${value}px` : value;
|
|
89
103
|
|
|
90
104
|
const tableShellStyle = $derived.by(() => {
|
|
91
|
-
|
|
92
|
-
const fallbackHeight = hasExplicitHeight ? undefined : (layoutProps.maxHeight ?? '100%');
|
|
93
|
-
|
|
94
|
-
return [
|
|
95
|
-
layoutStyle(layoutProps),
|
|
96
|
-
rootStyle,
|
|
97
|
-
layoutProps.height === undefined ? '' : `height: ${toCssSize(layoutProps.height)};`,
|
|
98
|
-
layoutProps.maxHeight === undefined ? '' : `max-height: ${toCssSize(layoutProps.maxHeight)};`,
|
|
99
|
-
fallbackHeight === undefined ? '' : `height: ${toCssSize(fallbackHeight)};`
|
|
100
|
-
]
|
|
101
|
-
.filter(Boolean)
|
|
102
|
-
.join(' ');
|
|
105
|
+
return [layoutStyle(layoutProps), rootStyle].filter(Boolean).join(' ');
|
|
103
106
|
});
|
|
104
107
|
|
|
105
108
|
const headerSpan = (value: TableColumn<T>['colspan'] | TableColumn<T>['rowspan']) =>
|
|
@@ -214,7 +217,18 @@
|
|
|
214
217
|
(column, index) => !column.hidden && !hidden.has(columnKey(column, index))
|
|
215
218
|
);
|
|
216
219
|
});
|
|
220
|
+
const tableMinWidth = $derived.by(() => {
|
|
221
|
+
const widths = visibleColumns
|
|
222
|
+
.map((column) => toCssSize(column.width ?? column.minWidth))
|
|
223
|
+
.filter((width): width is string => Boolean(width));
|
|
217
224
|
|
|
225
|
+
if (widths.length === 0) return '100%';
|
|
226
|
+
return `max(100%, calc(${widths.join(' + ')}))`;
|
|
227
|
+
});
|
|
228
|
+
const tableWidthStyle = $derived(`width: ${tableMinWidth};`);
|
|
229
|
+
const headerStyle = $derived(
|
|
230
|
+
`${tableWidthStyle} transform: translate3d(${-scrollOffsetX}px, 0, 0);`
|
|
231
|
+
);
|
|
218
232
|
const sortedRows = $derived.by(() => {
|
|
219
233
|
if (tableSortOrder.length === 0) return data;
|
|
220
234
|
|
|
@@ -243,6 +257,32 @@
|
|
|
243
257
|
return 0;
|
|
244
258
|
});
|
|
245
259
|
});
|
|
260
|
+
const engineColumns = $derived.by(() =>
|
|
261
|
+
visibleColumns.map((column, index) => ({
|
|
262
|
+
key: String(columnKey(column, index)),
|
|
263
|
+
width:
|
|
264
|
+
typeof column.width === 'number'
|
|
265
|
+
? column.width
|
|
266
|
+
: typeof column.minWidth === 'number'
|
|
267
|
+
? column.minWidth
|
|
268
|
+
: 160
|
|
269
|
+
}))
|
|
270
|
+
);
|
|
271
|
+
const engineLayout = $derived.by(() =>
|
|
272
|
+
tableViewportLayout({
|
|
273
|
+
rows: sortedRows,
|
|
274
|
+
columns: engineColumns,
|
|
275
|
+
viewport,
|
|
276
|
+
rowHeight,
|
|
277
|
+
headerHeight: 0,
|
|
278
|
+
overscan,
|
|
279
|
+
rowKey
|
|
280
|
+
})
|
|
281
|
+
);
|
|
282
|
+
const engineHeaderStyle = $derived.by(() => {
|
|
283
|
+
const width = `${engineLayout.content.width}px`;
|
|
284
|
+
return `width: ${width}; min-width: ${width}; height: ${headerHeight}px; transform: translate3d(${-scrollOffsetX}px, 0, 0);`;
|
|
285
|
+
});
|
|
246
286
|
|
|
247
287
|
const selectedKeys = $derived.by(() => {
|
|
248
288
|
if (selection instanceof Set) return new Set<TableRowKey>(selection);
|
|
@@ -391,6 +431,11 @@
|
|
|
391
431
|
if (selectionMode === 'multiple' || isInteractiveTarget(event.target)) return;
|
|
392
432
|
updateSelection(key);
|
|
393
433
|
};
|
|
434
|
+
|
|
435
|
+
const handleScroll = (geometry: ViewportGeometry) => {
|
|
436
|
+
viewport = geometry;
|
|
437
|
+
scrollOffsetX = geometry.offset.x;
|
|
438
|
+
};
|
|
394
439
|
</script>
|
|
395
440
|
|
|
396
441
|
{#if children}
|
|
@@ -403,22 +448,27 @@
|
|
|
403
448
|
onpointercancel={endDragSelection}
|
|
404
449
|
/>
|
|
405
450
|
|
|
406
|
-
<div
|
|
451
|
+
<div
|
|
452
|
+
class="table-shell"
|
|
453
|
+
class:table-shell-engine={virtualized}
|
|
454
|
+
style={tableShellStyle}
|
|
455
|
+
{...forwardedProps}
|
|
456
|
+
>
|
|
407
457
|
{#if columnHeaders === 'visible'}
|
|
408
|
-
<table
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
458
|
+
<div class="table-header-frame">
|
|
459
|
+
{#if virtualized}
|
|
460
|
+
<div
|
|
461
|
+
class="table-header-table table-engine-header"
|
|
462
|
+
style={engineHeaderStyle}
|
|
463
|
+
role={selectionMode === 'none' ? undefined : 'row'}
|
|
464
|
+
>
|
|
415
465
|
{#each visibleColumns as column, index (columnKey(column, index))}
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
style:
|
|
421
|
-
|
|
466
|
+
{@const layoutColumn = engineColumns[index]}
|
|
467
|
+
<div
|
|
468
|
+
class={`table-heading table-engine-heading table-align-${column.alignment ?? 'leading'}`}
|
|
469
|
+
style:width={`${layoutColumn.width}px`}
|
|
470
|
+
style:height={`${headerHeight}px`}
|
|
471
|
+
role={selectionMode === 'none' ? 'columnheader' : 'gridcell'}
|
|
422
472
|
aria-sort={tableSortOrder[0]?.key === columnSortKey(column, index)
|
|
423
473
|
? tableSortOrder[0].direction === 'ascending'
|
|
424
474
|
? 'ascending'
|
|
@@ -432,7 +482,13 @@
|
|
|
432
482
|
class="table-sort-button"
|
|
433
483
|
onclick={() => updateSort(column, index)}
|
|
434
484
|
>
|
|
435
|
-
<span>
|
|
485
|
+
<span>
|
|
486
|
+
{#if column.header}
|
|
487
|
+
{@render column.header(column, index)}
|
|
488
|
+
{:else}
|
|
489
|
+
{column.label}
|
|
490
|
+
{/if}
|
|
491
|
+
</span>
|
|
436
492
|
{#if sortDirection === 'ascending'}
|
|
437
493
|
<ArrowUpIcon class="table-sort-icon" size={12} strokeWidth={2.25} />
|
|
438
494
|
{:else if sortDirection === 'descending'}
|
|
@@ -445,61 +501,190 @@
|
|
|
445
501
|
/>
|
|
446
502
|
{/if}
|
|
447
503
|
</button>
|
|
504
|
+
{:else if column.header}
|
|
505
|
+
{@render column.header(column, index)}
|
|
448
506
|
{:else}
|
|
449
507
|
{column.label}
|
|
450
508
|
{/if}
|
|
451
|
-
</
|
|
509
|
+
</div>
|
|
452
510
|
{/each}
|
|
453
|
-
</
|
|
454
|
-
|
|
455
|
-
|
|
511
|
+
</div>
|
|
512
|
+
{:else}
|
|
513
|
+
<table
|
|
514
|
+
class="table-header-table table"
|
|
515
|
+
style={headerStyle}
|
|
516
|
+
role={selectionMode === 'none' ? undefined : 'grid'}
|
|
517
|
+
aria-multiselectable={selectionMode === 'multiple' ? 'true' : undefined}
|
|
518
|
+
>
|
|
519
|
+
<thead class="table-header">
|
|
520
|
+
<tr>
|
|
521
|
+
{#each visibleColumns as column, index (columnKey(column, index))}
|
|
522
|
+
<th
|
|
523
|
+
class={`table-heading table-align-${column.alignment ?? 'leading'}`}
|
|
524
|
+
colspan={headerSpan(column.colspan)}
|
|
525
|
+
rowspan={headerSpan(column.rowspan)}
|
|
526
|
+
style:min-width={toCssSize(column.minWidth)}
|
|
527
|
+
style:width={toCssSize(column.width)}
|
|
528
|
+
aria-sort={tableSortOrder[0]?.key === columnSortKey(column, index)
|
|
529
|
+
? tableSortOrder[0].direction === 'ascending'
|
|
530
|
+
? 'ascending'
|
|
531
|
+
: 'descending'
|
|
532
|
+
: undefined}
|
|
533
|
+
>
|
|
534
|
+
{#if column.sortable}
|
|
535
|
+
{@const sortDirection = activeSortDirection(column, index)}
|
|
536
|
+
<button
|
|
537
|
+
type="button"
|
|
538
|
+
class="table-sort-button"
|
|
539
|
+
onclick={() => updateSort(column, index)}
|
|
540
|
+
>
|
|
541
|
+
<span>
|
|
542
|
+
{#if column.header}
|
|
543
|
+
{@render column.header(column, index)}
|
|
544
|
+
{:else}
|
|
545
|
+
{column.label}
|
|
546
|
+
{/if}
|
|
547
|
+
</span>
|
|
548
|
+
{#if sortDirection === 'ascending'}
|
|
549
|
+
<ArrowUpIcon class="table-sort-icon" size={12} strokeWidth={2.25} />
|
|
550
|
+
{:else if sortDirection === 'descending'}
|
|
551
|
+
<ArrowDownIcon class="table-sort-icon" size={12} strokeWidth={2.25} />
|
|
552
|
+
{:else}
|
|
553
|
+
<ArrowUpDownIcon
|
|
554
|
+
class="table-sort-icon table-sort-icon-muted"
|
|
555
|
+
size={12}
|
|
556
|
+
strokeWidth={2.25}
|
|
557
|
+
/>
|
|
558
|
+
{/if}
|
|
559
|
+
</button>
|
|
560
|
+
{:else if column.header}
|
|
561
|
+
{@render column.header(column, index)}
|
|
562
|
+
{:else}
|
|
563
|
+
{column.label}
|
|
564
|
+
{/if}
|
|
565
|
+
</th>
|
|
566
|
+
{/each}
|
|
567
|
+
</tr>
|
|
568
|
+
</thead>
|
|
569
|
+
</table>
|
|
570
|
+
{/if}
|
|
571
|
+
</div>
|
|
456
572
|
{/if}
|
|
457
573
|
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
574
|
+
{#if virtualized}
|
|
575
|
+
{#snippet layout()}
|
|
576
|
+
{#each engineLayout.rows as placedRow (placedRow.key)}
|
|
577
|
+
{@const key = rowKey(placedRow.item, placedRow.index)}
|
|
578
|
+
<div
|
|
579
|
+
data-table-row-key={String(key)}
|
|
580
|
+
class="table-engine-row table-row"
|
|
581
|
+
class:table-row-selectable={selectionMode !== 'none'}
|
|
582
|
+
class:table-row-selected={isSelected(key)}
|
|
583
|
+
style:width={`${placedRow.rect.width}px`}
|
|
584
|
+
style:height={`${placedRow.rect.height}px`}
|
|
585
|
+
style:transform={`translate3d(${placedRow.rect.x}px, ${placedRow.rect.y}px, 0)`}
|
|
586
|
+
aria-selected={selectionMode === 'none' ? undefined : isSelected(key)}
|
|
587
|
+
role={selectionMode === 'none' ? 'row' : 'row'}
|
|
588
|
+
onclick={(event) => handleRowClick(event, key)}
|
|
589
|
+
onpointerdown={(event) => startDragSelection(event, key)}
|
|
590
|
+
onpointerenter={(event) => continueDragSelection(event, key)}
|
|
591
|
+
onpointerup={endDragSelection}
|
|
592
|
+
onpointercancel={endDragSelection}
|
|
593
|
+
></div>
|
|
594
|
+
{/each}
|
|
595
|
+
{#each engineLayout.cells as placedCell (placedCell.key)}
|
|
596
|
+
{@const column = visibleColumns[placedCell.item.columnIndex]}
|
|
597
|
+
{@const row = placedCell.item.row}
|
|
598
|
+
{@const index = placedCell.item.rowIndex}
|
|
599
|
+
{@const key = rowKey(row, index)}
|
|
600
|
+
<div
|
|
601
|
+
data-table-row-key={String(key)}
|
|
602
|
+
class={`table-engine-cell table-cell table-align-${column.alignment ?? 'leading'}`}
|
|
603
|
+
class:table-row-selectable={selectionMode !== 'none'}
|
|
604
|
+
style:width={`${placedCell.rect.width}px`}
|
|
605
|
+
style:height={`${placedCell.rect.height}px`}
|
|
606
|
+
style:transform={`translate3d(${placedCell.rect.x}px, ${placedCell.rect.y}px, 0)`}
|
|
607
|
+
aria-selected={selectionMode === 'none' ? undefined : isSelected(key)}
|
|
608
|
+
role={selectionMode === 'none' ? 'cell' : 'gridcell'}
|
|
609
|
+
onclick={(event) => handleRowClick(event, key)}
|
|
610
|
+
onpointerdown={(event) => startDragSelection(event, key)}
|
|
611
|
+
onpointerenter={(event) => continueDragSelection(event, key)}
|
|
612
|
+
onpointerup={endDragSelection}
|
|
613
|
+
onpointercancel={endDragSelection}
|
|
614
|
+
>
|
|
615
|
+
{#if column.cell}
|
|
616
|
+
{@render column.cell(row, index)}
|
|
617
|
+
{:else}
|
|
618
|
+
{displayValue(columnValue(column, row))}
|
|
619
|
+
{/if}
|
|
620
|
+
</div>
|
|
621
|
+
{/each}
|
|
622
|
+
{#if sortedRows.length === 0}
|
|
623
|
+
<div class="table-empty table-engine-empty">{emptyLabel}</div>
|
|
624
|
+
{/if}
|
|
625
|
+
{/snippet}
|
|
626
|
+
|
|
627
|
+
<ScrollView
|
|
628
|
+
axis="both"
|
|
629
|
+
loader={bodyLoaderOptions}
|
|
630
|
+
contentSize={engineLayout.content}
|
|
631
|
+
contentStyles={{ paddingX: 0, paddingY: 0 }}
|
|
632
|
+
onScroll={handleScroll}
|
|
633
|
+
{layout}
|
|
634
|
+
/>
|
|
635
|
+
{:else}
|
|
636
|
+
<ScrollView
|
|
637
|
+
axis="both"
|
|
638
|
+
loader={bodyLoaderOptions}
|
|
639
|
+
contentStyles={{ paddingX: 0, paddingY: 0 }}
|
|
640
|
+
onScroll={handleScroll}
|
|
463
641
|
>
|
|
464
|
-
<
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
{
|
|
489
|
-
|
|
490
|
-
{
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
642
|
+
<table
|
|
643
|
+
class="table-body-table table"
|
|
644
|
+
style={tableWidthStyle}
|
|
645
|
+
role={selectionMode === 'none' ? undefined : 'grid'}
|
|
646
|
+
aria-multiselectable={selectionMode === 'multiple' ? 'true' : undefined}
|
|
647
|
+
>
|
|
648
|
+
<tbody>
|
|
649
|
+
{#each sortedRows as row, index (rowKey(row, index))}
|
|
650
|
+
{@const key = rowKey(row, index)}
|
|
651
|
+
<tr
|
|
652
|
+
data-table-row-key={String(key)}
|
|
653
|
+
class="table-row"
|
|
654
|
+
class:table-row-selectable={selectionMode !== 'none'}
|
|
655
|
+
class:table-row-selected={isSelected(key)}
|
|
656
|
+
aria-selected={selectionMode === 'none' ? undefined : isSelected(key)}
|
|
657
|
+
onclick={(event) => handleRowClick(event, key)}
|
|
658
|
+
onpointerdown={(event) => startDragSelection(event, key)}
|
|
659
|
+
onpointerenter={(event) => continueDragSelection(event, key)}
|
|
660
|
+
onpointerup={endDragSelection}
|
|
661
|
+
onpointercancel={endDragSelection}
|
|
662
|
+
>
|
|
663
|
+
{#each visibleColumns as column, columnIndex (columnKey(column, columnIndex))}
|
|
664
|
+
<td
|
|
665
|
+
class={`table-cell table-align-${column.alignment ?? 'leading'}`}
|
|
666
|
+
colspan={bodySpan(column.colspan, row, index)}
|
|
667
|
+
rowspan={bodySpan(column.rowspan, row, index)}
|
|
668
|
+
style:min-width={toCssSize(column.minWidth)}
|
|
669
|
+
style:width={toCssSize(column.width)}
|
|
670
|
+
>
|
|
671
|
+
{#if column.cell}
|
|
672
|
+
{@render column.cell(row, index)}
|
|
673
|
+
{:else}
|
|
674
|
+
{displayValue(columnValue(column, row))}
|
|
675
|
+
{/if}
|
|
676
|
+
</td>
|
|
677
|
+
{/each}
|
|
678
|
+
</tr>
|
|
679
|
+
{:else}
|
|
680
|
+
<tr>
|
|
681
|
+
<td class="table-empty" colspan={Math.max(visibleColumns.length, 1)}>{emptyLabel}</td>
|
|
682
|
+
</tr>
|
|
683
|
+
{/each}
|
|
684
|
+
</tbody>
|
|
685
|
+
</table>
|
|
686
|
+
</ScrollView>
|
|
687
|
+
{/if}
|
|
503
688
|
</div>
|
|
504
689
|
|
|
505
690
|
<style>
|
|
@@ -512,8 +697,10 @@
|
|
|
512
697
|
flex-direction: column;
|
|
513
698
|
flex: 1 1 auto;
|
|
514
699
|
align-self: stretch;
|
|
700
|
+
min-width: 0;
|
|
515
701
|
min-height: 0;
|
|
516
702
|
width: 100%;
|
|
703
|
+
max-width: 100%;
|
|
517
704
|
overflow: hidden;
|
|
518
705
|
border: 1px solid var(--sveltely-border-color);
|
|
519
706
|
border-radius: var(--sveltely-border-radius);
|
|
@@ -524,7 +711,7 @@
|
|
|
524
711
|
|
|
525
712
|
.table {
|
|
526
713
|
width: 100%;
|
|
527
|
-
min-width:
|
|
714
|
+
min-width: 100%;
|
|
528
715
|
border-collapse: separate;
|
|
529
716
|
border-spacing: 0;
|
|
530
717
|
}
|
|
@@ -537,19 +724,37 @@
|
|
|
537
724
|
);
|
|
538
725
|
}
|
|
539
726
|
|
|
727
|
+
.table-header-frame {
|
|
728
|
+
width: 100%;
|
|
729
|
+
min-width: 0;
|
|
730
|
+
overflow: hidden;
|
|
731
|
+
border-bottom: 1px solid var(--sveltely-border-color);
|
|
732
|
+
}
|
|
733
|
+
|
|
540
734
|
.table-header-table {
|
|
541
735
|
flex: 0 0 auto;
|
|
542
|
-
|
|
736
|
+
will-change: transform;
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
.table-engine-header {
|
|
740
|
+
display: flex;
|
|
741
|
+
background: color-mix(
|
|
742
|
+
in oklab,
|
|
743
|
+
var(--sveltely-background-color) 92%,
|
|
744
|
+
var(--sveltely-control-active-color)
|
|
745
|
+
);
|
|
543
746
|
}
|
|
544
747
|
|
|
545
|
-
.table-header-
|
|
748
|
+
.table-header-frame + :global(.scroll-view) {
|
|
546
749
|
border-top-left-radius: 0;
|
|
547
750
|
border-top-right-radius: 0;
|
|
548
751
|
}
|
|
549
752
|
|
|
550
753
|
.table-shell > :global(.scroll-view) {
|
|
551
754
|
flex: 1 1 auto;
|
|
755
|
+
min-width: 0;
|
|
552
756
|
min-height: 0;
|
|
757
|
+
max-width: 100%;
|
|
553
758
|
}
|
|
554
759
|
|
|
555
760
|
.table-heading,
|
|
@@ -571,6 +776,45 @@
|
|
|
571
776
|
color: inherit;
|
|
572
777
|
}
|
|
573
778
|
|
|
779
|
+
.table-engine-heading,
|
|
780
|
+
.table-engine-cell {
|
|
781
|
+
display: flex;
|
|
782
|
+
align-items: center;
|
|
783
|
+
min-width: 0;
|
|
784
|
+
overflow: hidden;
|
|
785
|
+
text-overflow: ellipsis;
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
.table-engine-cell {
|
|
789
|
+
position: absolute;
|
|
790
|
+
left: 0;
|
|
791
|
+
top: 0;
|
|
792
|
+
z-index: 1;
|
|
793
|
+
background: transparent;
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
.table-engine-row {
|
|
797
|
+
position: absolute;
|
|
798
|
+
left: 0;
|
|
799
|
+
top: 0;
|
|
800
|
+
z-index: 0;
|
|
801
|
+
border-bottom: 1px solid var(--sveltely-border-color);
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
.table-engine-row.table-row-selectable {
|
|
805
|
+
cursor: default;
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
.table-engine-row.table-row-selectable:hover {
|
|
809
|
+
background: color-mix(in oklab, var(--sveltely-control-active-color) 8%, transparent);
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
.table-engine-empty {
|
|
813
|
+
position: absolute;
|
|
814
|
+
inset: 0 auto auto 0;
|
|
815
|
+
width: 100%;
|
|
816
|
+
}
|
|
817
|
+
|
|
574
818
|
.table-row:last-child .table-cell {
|
|
575
819
|
border-bottom: 0;
|
|
576
820
|
}
|
|
@@ -3,6 +3,7 @@ import { type Snippet } from 'svelte';
|
|
|
3
3
|
import { type LoaderProps } from '../../../style/loader';
|
|
4
4
|
import { type LayoutProps } from '../../../style/layout';
|
|
5
5
|
import { type StyleProps } from '../../../style/surface';
|
|
6
|
+
import { type ViewportOverscan } from '../../../viewport';
|
|
6
7
|
import type { TableColumn, TableColumnCustomization, TableColumnHeaderVisibility, TableSelection, TableSelectionMode, TableSortDescriptor } from './types';
|
|
7
8
|
declare function $$render<T extends Record<string, unknown>>(): {
|
|
8
9
|
props: {
|
|
@@ -15,6 +16,10 @@ declare function $$render<T extends Record<string, unknown>>(): {
|
|
|
15
16
|
columnHeaders?: TableColumnHeaderVisibility;
|
|
16
17
|
columnCustomization?: TableColumnCustomization;
|
|
17
18
|
emptyLabel?: string;
|
|
19
|
+
virtualized?: boolean;
|
|
20
|
+
rowHeight?: number;
|
|
21
|
+
headerHeight?: number;
|
|
22
|
+
overscan?: ViewportOverscan;
|
|
18
23
|
onSortOrderChange?: (sortOrder: TableSortDescriptor<T>[]) => void;
|
|
19
24
|
onSelectionChange?: (selection: TableSelection) => void;
|
|
20
25
|
} & LayoutProps & StyleProps & LoaderProps & Record<string, unknown>;
|
|
@@ -18,6 +18,7 @@ export type TableColumnCustomization = {
|
|
|
18
18
|
export type TableColumn<T> = {
|
|
19
19
|
key?: string;
|
|
20
20
|
label: string;
|
|
21
|
+
header?: Snippet<[column: TableColumn<T>, index: number]>;
|
|
21
22
|
value?: keyof T | ((row: T) => unknown);
|
|
22
23
|
cell?: Snippet<[row: T, index: number]>;
|
|
23
24
|
width?: number | string;
|
|
@@ -76,20 +76,22 @@
|
|
|
76
76
|
data-disabled={disabled ? 'true' : 'false'}
|
|
77
77
|
data-error={error ? 'true' : 'false'}
|
|
78
78
|
>
|
|
79
|
-
<
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
79
|
+
<div class="text-field-control">
|
|
80
|
+
<input
|
|
81
|
+
bind:value
|
|
82
|
+
{type}
|
|
83
|
+
{disabled}
|
|
84
|
+
{name}
|
|
85
|
+
{autocomplete}
|
|
86
|
+
{required}
|
|
87
|
+
{readonly}
|
|
88
|
+
{inputmode}
|
|
89
|
+
{placeholder}
|
|
90
|
+
aria-invalid={error ? 'true' : undefined}
|
|
91
|
+
aria-describedby={describedBy}
|
|
92
|
+
class="text-field-input"
|
|
93
|
+
/>
|
|
94
|
+
</div>
|
|
93
95
|
|
|
94
96
|
{#if help}
|
|
95
97
|
<span id="text-field-message" class="text-field-message">{help}</span>
|
|
@@ -107,6 +109,10 @@
|
|
|
107
109
|
font-size: var(--text-field-font-size, var(--sveltely-font-size));
|
|
108
110
|
}
|
|
109
111
|
|
|
112
|
+
.text-field-control {
|
|
113
|
+
display: contents;
|
|
114
|
+
}
|
|
115
|
+
|
|
110
116
|
.text-field-input {
|
|
111
117
|
width: 100%;
|
|
112
118
|
min-width: 0;
|
|
@@ -6,9 +6,10 @@
|
|
|
6
6
|
</script>
|
|
7
7
|
|
|
8
8
|
<script lang="ts">
|
|
9
|
+
import VStack from '../VStack';
|
|
9
10
|
import TextShimmer from './TextShimmer.svelte';
|
|
10
11
|
</script>
|
|
11
12
|
|
|
12
|
-
<
|
|
13
|
+
<VStack gap={5}>
|
|
13
14
|
<TextShimmer as="h2" text="Sveltely shimmer" />
|
|
14
|
-
</
|
|
15
|
+
</VStack>
|
|
@@ -8,19 +8,12 @@
|
|
|
8
8
|
</script>
|
|
9
9
|
|
|
10
10
|
<script lang="ts">
|
|
11
|
+
import VStack from '../VStack';
|
|
11
12
|
import TimePicker from './TimePicker.svelte';
|
|
12
13
|
|
|
13
14
|
let value = $state<Date | null>(new Date());
|
|
14
15
|
</script>
|
|
15
16
|
|
|
16
|
-
<
|
|
17
|
+
<VStack width="100%" height="100%" gap={10}>
|
|
17
18
|
<TimePicker bind:value />
|
|
18
|
-
</
|
|
19
|
-
|
|
20
|
-
<style>
|
|
21
|
-
.time-picker-demo {
|
|
22
|
-
width: 100%;
|
|
23
|
-
height: 100%;
|
|
24
|
-
min-height: 0;
|
|
25
|
-
}
|
|
26
|
-
</style>
|
|
19
|
+
</VStack>
|
|
@@ -7,15 +7,16 @@
|
|
|
7
7
|
</script>
|
|
8
8
|
|
|
9
9
|
<script lang="ts">
|
|
10
|
+
import VStack from '../VStack';
|
|
10
11
|
import TokenSearchField from './TokenSearchField.svelte';
|
|
11
12
|
|
|
12
13
|
let tokens = $state(['svelte', 'ui']);
|
|
13
14
|
let value = $state('');
|
|
14
15
|
</script>
|
|
15
16
|
|
|
16
|
-
<
|
|
17
|
+
<VStack width="28rem" gap={5}>
|
|
17
18
|
<TokenSearchField bind:tokens bind:value placeholder="Search keywords" />
|
|
18
19
|
<p class="text-xs text-[var(--sveltely-text-secondary-color)]">
|
|
19
20
|
Tokens: {tokens.join(', ') || 'empty'}
|
|
20
21
|
</p>
|
|
21
|
-
</
|
|
22
|
+
</VStack>
|