svelte-tably 1.0.0-next.3 → 1.0.0-next.5
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/README.md +55 -39
- package/dist/Table/Column.svelte +8 -9
- package/dist/Table/Column.svelte.d.ts +6 -5
- package/dist/Table/Panel.svelte +10 -9
- package/dist/Table/Panel.svelte.d.ts +4 -4
- package/dist/Table/Table.svelte +88 -54
- package/dist/Table/Table.svelte.d.ts +49 -7
- package/dist/Table/index.d.ts +1 -12
- package/dist/Table/index.js +1 -31
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -23,52 +23,68 @@ A high performant dynamic table
|
|
|
23
23
|
|
|
24
24
|
### Usage Notes
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
Create a state for your data and a state for your active panel:
|
|
29
|
-
|
|
30
|
-
```markdown
|
|
26
|
+
```html
|
|
31
27
|
<script lang='ts'>
|
|
32
|
-
|
|
28
|
+
import Table from 'svelte-tably'
|
|
33
29
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
30
|
+
const data = $state([
|
|
31
|
+
{ name: 'John Doe', age: 30, email: 'johndoe@example.com' },
|
|
32
|
+
{ name: 'Jane Doe', age: 25, email: 'janedoe@example.com' },
|
|
33
|
+
])
|
|
34
|
+
|
|
35
|
+
let activePanel = $state('columns') as string | undefined
|
|
38
36
|
</script>
|
|
39
37
|
|
|
40
|
-
<Table {data}>
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
38
|
+
<Table {data} panel={activePanel}>
|
|
39
|
+
{#snippet content({ Column, Panel, state, data })}
|
|
40
|
+
<Column id='name' sticky>
|
|
41
|
+
{#snippet header()}
|
|
42
|
+
Name
|
|
43
|
+
{/snippet}
|
|
44
|
+
{#snippet row(row)}
|
|
45
|
+
{row.name}
|
|
46
|
+
{/snippet}
|
|
47
|
+
|
|
48
|
+
<!-- Optional per column. -->
|
|
49
|
+
{#snippet statusbar()}
|
|
50
|
+
{data.length}
|
|
51
|
+
{/snippet}
|
|
52
|
+
</Column>
|
|
53
|
+
<Column ...>
|
|
54
|
+
...
|
|
55
|
+
</Column>
|
|
56
|
+
<!-- If you want to sort/filter a virtual value, that does not exist in the data -->
|
|
57
|
+
<Column id='virtual' value={row => row.age > 18}>
|
|
58
|
+
...
|
|
59
|
+
{#snippet row(row, virtual)}
|
|
60
|
+
{virtual ? 'Adult' : 'Adolescent'}
|
|
61
|
+
{/snippet}
|
|
62
|
+
...
|
|
63
|
+
</Column>
|
|
64
|
+
|
|
65
|
+
<Panel id='columns'>
|
|
66
|
+
<!-- Anything you might like -->
|
|
67
|
+
</Panel>
|
|
68
|
+
<Panel ...>
|
|
69
|
+
...
|
|
70
|
+
</Panel>
|
|
63
71
|
{/snippet}
|
|
64
|
-
</Table.Email>
|
|
65
72
|
</Table>
|
|
66
73
|
```
|
|
67
74
|
|
|
68
|
-
|
|
75
|
+
#### Styling
|
|
76
|
+
|
|
77
|
+
For quick styling
|
|
78
|
+
|
|
79
|
+
| CSS Variable | Description | Default |
|
|
80
|
+
| - | - | - |
|
|
81
|
+
| --tably-bg | background-color | `hsl(0, 0%, 100%)` |
|
|
82
|
+
| --tably-color | color | `hsl(0, 0%, 0%)` |
|
|
83
|
+
| --tably-border | border | `hsl(0, 0%, 90%)` |
|
|
84
|
+
| --tably-padding-y | Padding above/below each column | `.5rem` |
|
|
85
|
+
| --tably-padding-x | Padding left of each column | `1rem` |
|
|
86
|
+
| --tably-radius | Table radius | `.25rem` |
|
|
87
|
+
|
|
88
|
+
Advanced styling can be done via `:global .svelte-tably`
|
|
69
89
|
|
|
70
|
-
Inside the column component, you need to define three snippets:
|
|
71
90
|
|
|
72
|
-
* `header`: the content of the column header
|
|
73
|
-
* `row`: the content of each row in the column
|
|
74
|
-
* `statusbar`: (optional) the content of the status bar for the column
|
package/dist/Table/Column.svelte
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
export interface Column<T = unknown, V = unknown> {
|
|
14
14
|
header: Snippet
|
|
15
15
|
row: Snippet<[item: T, value?: V]>
|
|
16
|
-
statusbar?: Snippet
|
|
16
|
+
statusbar?: Snippet
|
|
17
17
|
|
|
18
18
|
/** Default options for initial table */
|
|
19
19
|
defaults: {
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
|
|
31
31
|
</script>
|
|
32
32
|
|
|
33
|
-
<script lang='ts' generics='T extends Record<PropertyKey, any>, V'>
|
|
33
|
+
<script lang='ts' generics='T extends Record<PropertyKey, any>, V = unknown'>
|
|
34
34
|
|
|
35
35
|
import { onDestroy, type Snippet } from 'svelte'
|
|
36
36
|
import { getTableState } from './Table.svelte'
|
|
@@ -40,6 +40,8 @@
|
|
|
40
40
|
row: Column<T, V>['row']
|
|
41
41
|
statusbar?: Column<T, V>['statusbar']
|
|
42
42
|
|
|
43
|
+
id: string
|
|
44
|
+
|
|
43
45
|
// options
|
|
44
46
|
sticky?: boolean
|
|
45
47
|
sort?: boolean
|
|
@@ -49,17 +51,14 @@
|
|
|
49
51
|
}
|
|
50
52
|
|
|
51
53
|
let {
|
|
52
|
-
header, row, statusbar,
|
|
54
|
+
header, row, statusbar, id,
|
|
53
55
|
|
|
54
56
|
sticky = false,
|
|
55
57
|
sort = false,
|
|
56
58
|
show = true,
|
|
57
59
|
|
|
58
|
-
value, sorting
|
|
59
|
-
|
|
60
|
-
...rest
|
|
60
|
+
value, sorting
|
|
61
61
|
}: Props = $props()
|
|
62
|
-
const key = (rest as unknown as { __key: string }).__key
|
|
63
62
|
|
|
64
63
|
const column: Column<T, V> = $state({
|
|
65
64
|
header,
|
|
@@ -77,10 +76,10 @@
|
|
|
77
76
|
})
|
|
78
77
|
|
|
79
78
|
const table = getTableState()
|
|
80
|
-
table.addColumn(
|
|
79
|
+
table.addColumn(id, column as Column)
|
|
81
80
|
|
|
82
81
|
onDestroy(() => {
|
|
83
|
-
table.removeColumn(
|
|
82
|
+
table.removeColumn(id)
|
|
84
83
|
})
|
|
85
84
|
|
|
86
85
|
</script>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export interface Column<T = unknown, V = unknown> {
|
|
2
2
|
header: Snippet;
|
|
3
3
|
row: Snippet<[item: T, value?: V]>;
|
|
4
|
-
statusbar?: Snippet
|
|
4
|
+
statusbar?: Snippet;
|
|
5
5
|
/** Default options for initial table */
|
|
6
6
|
defaults: {
|
|
7
7
|
sticky?: boolean;
|
|
@@ -15,11 +15,12 @@ export interface Column<T = unknown, V = unknown> {
|
|
|
15
15
|
};
|
|
16
16
|
}
|
|
17
17
|
import { type Snippet } from 'svelte';
|
|
18
|
-
declare class __sveltets_Render<T extends Record<PropertyKey, any>, V> {
|
|
18
|
+
declare class __sveltets_Render<T extends Record<PropertyKey, any>, V = unknown> {
|
|
19
19
|
props(): {
|
|
20
20
|
header: Column<T_1, V_1>["header"];
|
|
21
21
|
row: Column<T_1, V_1>["row"];
|
|
22
22
|
statusbar?: Column<T_1, V_1>["statusbar"];
|
|
23
|
+
id: string;
|
|
23
24
|
sticky?: boolean;
|
|
24
25
|
sort?: boolean;
|
|
25
26
|
show?: boolean;
|
|
@@ -32,10 +33,10 @@ declare class __sveltets_Render<T extends Record<PropertyKey, any>, V> {
|
|
|
32
33
|
exports(): {};
|
|
33
34
|
}
|
|
34
35
|
interface $$IsomorphicComponent {
|
|
35
|
-
new <T extends Record<PropertyKey, any>, V>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<T, V>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<T, V>['props']>, ReturnType<__sveltets_Render<T, V>['events']>, ReturnType<__sveltets_Render<T, V>['slots']>> & {
|
|
36
|
+
new <T extends Record<PropertyKey, any>, V = unknown>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<T, V>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<T, V>['props']>, ReturnType<__sveltets_Render<T, V>['events']>, ReturnType<__sveltets_Render<T, V>['slots']>> & {
|
|
36
37
|
$$bindings?: ReturnType<__sveltets_Render<T, V>['bindings']>;
|
|
37
38
|
} & ReturnType<__sveltets_Render<T, V>['exports']>;
|
|
38
|
-
<T extends Record<PropertyKey, any>, V>(internal: unknown, props: ReturnType<__sveltets_Render<T, V>['props']> & {}): ReturnType<__sveltets_Render<T, V>['exports']>;
|
|
39
|
+
<T extends Record<PropertyKey, any>, V = unknown>(internal: unknown, props: ReturnType<__sveltets_Render<T, V>['props']> & {}): ReturnType<__sveltets_Render<T, V>['exports']>;
|
|
39
40
|
z_$$bindings?: ReturnType<__sveltets_Render<any, any>['bindings']>;
|
|
40
41
|
}
|
|
41
42
|
/**
|
|
@@ -46,5 +47,5 @@ interface $$IsomorphicComponent {
|
|
|
46
47
|
* <Component />
|
|
47
48
|
*/
|
|
48
49
|
declare const Column: $$IsomorphicComponent;
|
|
49
|
-
type Column<T extends Record<PropertyKey, any>, V> = InstanceType<typeof Column<T, V>>;
|
|
50
|
+
type Column<T extends Record<PropertyKey, any>, V = unknown> = InstanceType<typeof Column<T, V>>;
|
|
50
51
|
export default Column;
|
package/dist/Table/Panel.svelte
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
export interface Panel {
|
|
14
14
|
/** A darkened backdrop? */
|
|
15
15
|
backdrop: boolean
|
|
16
|
-
content: Snippet
|
|
16
|
+
content: Snippet
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
export class PanelTween {
|
|
@@ -29,9 +29,9 @@
|
|
|
29
29
|
this.#tween.set(value).then(() => this.transitioning = false)
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
constructor(cb: () => string | undefined) {
|
|
32
|
+
constructor(cb: () => string | undefined, added = 0) {
|
|
33
33
|
$effect.pre(() => {
|
|
34
|
-
this.target = cb() ? this.width : 0
|
|
34
|
+
this.target = cb() ? this.width + added : 0
|
|
35
35
|
})
|
|
36
36
|
}
|
|
37
37
|
}
|
|
@@ -46,28 +46,29 @@
|
|
|
46
46
|
import { sineInOut } from 'svelte/easing'
|
|
47
47
|
|
|
48
48
|
interface Props {
|
|
49
|
+
id: string
|
|
50
|
+
|
|
49
51
|
/** A darkened backdrop? */
|
|
50
52
|
backdrop?: boolean
|
|
51
|
-
children: Snippet
|
|
53
|
+
children: Snippet
|
|
52
54
|
}
|
|
53
55
|
|
|
54
56
|
let {
|
|
55
57
|
backdrop = true,
|
|
56
58
|
children,
|
|
57
|
-
|
|
59
|
+
id
|
|
58
60
|
}: Props = $props()
|
|
59
|
-
|
|
60
|
-
|
|
61
|
+
|
|
61
62
|
const panel: Panel = $state({
|
|
62
63
|
backdrop,
|
|
63
64
|
content: children
|
|
64
65
|
})
|
|
65
66
|
|
|
66
67
|
const table = getTableState()
|
|
67
|
-
table.panels[
|
|
68
|
+
table.panels[id] = panel
|
|
68
69
|
|
|
69
70
|
onDestroy(() => {
|
|
70
|
-
delete table.panels[
|
|
71
|
+
delete table.panels[id]
|
|
71
72
|
})
|
|
72
73
|
|
|
73
74
|
</script>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export interface Panel {
|
|
2
2
|
/** A darkened backdrop? */
|
|
3
3
|
backdrop: boolean;
|
|
4
|
-
content: Snippet
|
|
4
|
+
content: Snippet;
|
|
5
5
|
}
|
|
6
6
|
export declare class PanelTween {
|
|
7
7
|
#private;
|
|
@@ -10,14 +10,14 @@ export declare class PanelTween {
|
|
|
10
10
|
/** bind:clientWidth */
|
|
11
11
|
width: number;
|
|
12
12
|
set target(value: number);
|
|
13
|
-
constructor(cb: () => string | undefined);
|
|
13
|
+
constructor(cb: () => string | undefined, added?: number);
|
|
14
14
|
}
|
|
15
15
|
import { type Snippet } from 'svelte';
|
|
16
|
-
import { type TableState } from './Table.svelte';
|
|
17
16
|
interface Props {
|
|
17
|
+
id: string;
|
|
18
18
|
/** A darkened backdrop? */
|
|
19
19
|
backdrop?: boolean;
|
|
20
|
-
children: Snippet
|
|
20
|
+
children: Snippet;
|
|
21
21
|
}
|
|
22
22
|
/**
|
|
23
23
|
* This is a description, \
|
package/dist/Table/Table.svelte
CHANGED
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
<script module lang='ts'>
|
|
12
12
|
|
|
13
13
|
export interface TableState<T extends Record<PropertyKey, any> = Record<PropertyKey, any>> {
|
|
14
|
-
columns: Record<string,
|
|
15
|
-
panels: Record<string,
|
|
14
|
+
columns: Record<string, TColumn<T, unknown>>
|
|
15
|
+
panels: Record<string, TPanel>
|
|
16
16
|
sortby?: string
|
|
17
17
|
positions: {
|
|
18
18
|
sticky: string[]
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
toggle(key: string): void
|
|
22
22
|
}
|
|
23
23
|
readonly data: T[]
|
|
24
|
-
addColumn(key: string, options:
|
|
24
|
+
addColumn(key: string, options: TColumn<T, unknown>): void
|
|
25
25
|
removeColumn(key: string): void
|
|
26
26
|
}
|
|
27
27
|
|
|
@@ -34,28 +34,30 @@
|
|
|
34
34
|
<script lang='ts' generics='T extends Record<PropertyKey, unknown>'>
|
|
35
35
|
|
|
36
36
|
import { getContext, setContext, untrack, type Snippet } from 'svelte'
|
|
37
|
-
import { type Column } from './Column.svelte'
|
|
38
|
-
import { PanelTween, type Panel } from './Panel.svelte'
|
|
37
|
+
import Column, { type Column as TColumn } from './Column.svelte'
|
|
38
|
+
import Panel, { PanelTween, type Panel as TPanel } from './Panel.svelte'
|
|
39
39
|
import { fly } from 'svelte/transition'
|
|
40
40
|
import { sineInOut } from 'svelte/easing'
|
|
41
41
|
|
|
42
42
|
interface Props {
|
|
43
|
-
|
|
43
|
+
content: Snippet<[context: { Column: typeof Column<T>, Panel: typeof Panel, readonly state: TableState<T>, readonly data: T[] }]>
|
|
44
|
+
|
|
44
45
|
panel?: string
|
|
45
46
|
data?: T[]
|
|
46
47
|
id?: string
|
|
47
48
|
}
|
|
48
49
|
|
|
49
50
|
let {
|
|
50
|
-
|
|
51
|
-
|
|
51
|
+
content,
|
|
52
|
+
|
|
53
|
+
panel = $bindable(),
|
|
52
54
|
data: _data = [],
|
|
53
55
|
id = Array.from({length: 12}, () => String.fromCharCode(Math.floor(Math.random() * 26) + 97)).join('')
|
|
54
56
|
}: Props = $props()
|
|
55
57
|
|
|
56
58
|
const data = $derived(_data.toSorted())
|
|
57
59
|
|
|
58
|
-
const elements = $state({}) as Record<'headers' | 'statusbar' | '
|
|
60
|
+
const elements = $state({}) as Record<'headers' | 'statusbar' | 'rows', HTMLElement>
|
|
59
61
|
|
|
60
62
|
|
|
61
63
|
// * --- Virtualization --- *
|
|
@@ -66,12 +68,10 @@
|
|
|
66
68
|
let renderItemLength = $derived(Math.ceil(Math.max(30, viewportHeight / (_heightPerItem / 3))))
|
|
67
69
|
|
|
68
70
|
let heightPerItem = $derived.by(() => {
|
|
69
|
-
|
|
71
|
+
data
|
|
72
|
+
if(!elements.rows)
|
|
70
73
|
return 8
|
|
71
|
-
const
|
|
72
|
-
const result = ((
|
|
73
|
-
rows[rows.length - 1].offsetTop - rows[0].offsetTop
|
|
74
|
-
) / rows.length)
|
|
74
|
+
const result = elements.rows.scrollHeight / elements.rows.childNodes.length
|
|
75
75
|
_heightPerItem = result
|
|
76
76
|
return result
|
|
77
77
|
})
|
|
@@ -80,17 +80,17 @@
|
|
|
80
80
|
let spacing = untrack(() => (renderItemLength/3)) * heightPerItem
|
|
81
81
|
let scroll = scrollTop - spacing
|
|
82
82
|
let virtualTop = Math.max(scroll, 0)
|
|
83
|
-
virtualTop -= virtualTop %
|
|
83
|
+
virtualTop -= virtualTop % heightPerItem
|
|
84
84
|
return virtualTop
|
|
85
85
|
})
|
|
86
86
|
let virtualBottom = $derived.by(() => {
|
|
87
|
-
const virtualBottom = (
|
|
87
|
+
const virtualBottom = (heightPerItem * data.length) - virtualTop
|
|
88
88
|
return virtualBottom
|
|
89
89
|
})
|
|
90
90
|
|
|
91
91
|
/** The area of data that is rendered */
|
|
92
92
|
const area = $derived.by(() => {
|
|
93
|
-
const index = (virtualTop /
|
|
93
|
+
const index = (virtualTop / heightPerItem) || 0
|
|
94
94
|
return data.slice(
|
|
95
95
|
index,
|
|
96
96
|
index + untrack(() => renderItemLength)
|
|
@@ -142,7 +142,7 @@
|
|
|
142
142
|
|
|
143
143
|
// * --- *
|
|
144
144
|
|
|
145
|
-
const panelTween = new PanelTween(() => panel)
|
|
145
|
+
const panelTween = new PanelTween(() => panel, 24)
|
|
146
146
|
|
|
147
147
|
/** Order of columns */
|
|
148
148
|
const columns = $derived([...table.positions.sticky, ...table.positions.scroll].filter(key => !table.positions.hidden.includes(key)))
|
|
@@ -187,7 +187,7 @@
|
|
|
187
187
|
</svelte:head>
|
|
188
188
|
|
|
189
189
|
{#snippet columnsSnippet(
|
|
190
|
-
renderable: (column: string) => Snippet<[arg0?: any, arg1?: any
|
|
190
|
+
renderable: (column: string) => Snippet<[arg0?: any, arg1?: any]> | undefined,
|
|
191
191
|
arg: null | ((column: string) => any[]) = null,
|
|
192
192
|
isHeader = false
|
|
193
193
|
)}
|
|
@@ -196,7 +196,7 @@
|
|
|
196
196
|
{@const args = arg ? arg(column) : []}
|
|
197
197
|
{@const props = isHeader ? { 'data-column': column } : {}}
|
|
198
198
|
<div class='column sticky' {...props} use:observe={isHeader} class:border={i == table.positions.sticky.length - 1}>
|
|
199
|
-
{@render renderable(column)?.(args[0], args[1]
|
|
199
|
+
{@render renderable(column)?.(args[0], args[1])}
|
|
200
200
|
</div>
|
|
201
201
|
{/if}
|
|
202
202
|
{/each}
|
|
@@ -205,22 +205,22 @@
|
|
|
205
205
|
{@const args = arg ? arg(column) : []}
|
|
206
206
|
{@const props = isHeader ? { 'data-column': column } : {}}
|
|
207
207
|
<div class='column' {...props} use:observe={isHeader}>
|
|
208
|
-
{@render renderable(column)?.(args[0], args[1]
|
|
208
|
+
{@render renderable(column)?.(args[0], args[1])}
|
|
209
209
|
</div>
|
|
210
210
|
{/if}
|
|
211
211
|
{/each}
|
|
212
212
|
{/snippet}
|
|
213
213
|
|
|
214
|
-
<div id={id} class='table'>
|
|
214
|
+
<div id={id} class='table svelte-tably'>
|
|
215
215
|
|
|
216
216
|
<div class='headers' bind:this={elements.headers}>
|
|
217
217
|
{@render columnsSnippet((column) => table.columns[column]?.header, null, true)}
|
|
218
218
|
</div>
|
|
219
219
|
|
|
220
|
-
<div class='content' {onscroll} bind:clientHeight={viewportHeight}
|
|
220
|
+
<div class='content' {onscroll} bind:clientHeight={viewportHeight}>
|
|
221
221
|
<div class='virtual top' style='height: {virtualTop}px'></div>
|
|
222
222
|
|
|
223
|
-
<div class=
|
|
223
|
+
<div class='rows' bind:this={elements.rows}>
|
|
224
224
|
{#each area as item, i (item)}
|
|
225
225
|
<div class='row'>
|
|
226
226
|
{@render columnsSnippet(
|
|
@@ -239,25 +239,32 @@
|
|
|
239
239
|
</div>
|
|
240
240
|
|
|
241
241
|
<div class='statusbar' bind:this={elements.statusbar}>
|
|
242
|
-
{@render columnsSnippet((column) => table.columns[column]?.statusbar
|
|
242
|
+
{@render columnsSnippet((column) => table.columns[column]?.statusbar)}
|
|
243
243
|
</div>
|
|
244
244
|
|
|
245
|
-
<div class='panel' style='width: {panelTween.current
|
|
245
|
+
<div class='panel' style='width: {(panelTween.current)}px;' style:overflow={panelTween.transitioning ? 'hidden' : 'auto'}>
|
|
246
246
|
{#if panel && panel in table.panels}
|
|
247
247
|
<div
|
|
248
|
-
class=
|
|
248
|
+
class='panel-content'
|
|
249
249
|
bind:clientWidth={panelTween.width}
|
|
250
250
|
in:fly={{ x: 100, easing: sineInOut, duration:300 }}
|
|
251
251
|
out:fly={{ x:100, duration:200, easing: sineInOut }}
|
|
252
252
|
>
|
|
253
|
-
{@render table.panels[panel].content(
|
|
253
|
+
{@render table.panels[panel].content()}
|
|
254
254
|
</div>
|
|
255
255
|
{/if}
|
|
256
256
|
</div>
|
|
257
|
+
<button
|
|
258
|
+
class='backdrop'
|
|
259
|
+
aria-label='Panel backdrop'
|
|
260
|
+
tabindex='-1'
|
|
261
|
+
aria-hidden={panel && table.panels[panel]?.backdrop ? false : true}
|
|
262
|
+
onclick={() => panel = undefined}
|
|
263
|
+
></button>
|
|
257
264
|
</div>
|
|
258
265
|
|
|
259
266
|
|
|
260
|
-
{@render
|
|
267
|
+
{@render content?.({ Column, Panel, get state() { return table }, get data() { return data } })}
|
|
261
268
|
|
|
262
269
|
|
|
263
270
|
|
|
@@ -266,13 +273,47 @@
|
|
|
266
273
|
|
|
267
274
|
.table, .table * {
|
|
268
275
|
box-sizing: border-box;
|
|
276
|
+
background-color: inherit;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
.backdrop {
|
|
280
|
+
position: absolute;
|
|
281
|
+
left: 0px;
|
|
282
|
+
top: 0px;
|
|
283
|
+
bottom: 0px;
|
|
284
|
+
right: 0px;
|
|
285
|
+
background-color: hsla(0, 0%, 0%, .3);
|
|
286
|
+
z-index: 3;
|
|
287
|
+
opacity: 1;
|
|
288
|
+
transition: .15s ease;
|
|
289
|
+
border: none;
|
|
290
|
+
outline: none;
|
|
291
|
+
cursor: pointer;
|
|
292
|
+
|
|
293
|
+
&[aria-hidden='true'] {
|
|
294
|
+
opacity: 0;
|
|
295
|
+
pointer-events: none;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
.headers, .statusbar {
|
|
300
|
+
/* So that the scrollbar doesn't cause the headers/statusbar to shift */
|
|
301
|
+
padding-right: 11px;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
.table {
|
|
305
|
+
color: var(--tably-color, hsl(0, 0%, 0%));
|
|
306
|
+
background-color: var(--tably-bg, hsl(0, 0%, 100%));
|
|
307
|
+
|
|
308
|
+
--tably-padding-x: 1rem;
|
|
309
|
+
--tably-padding-y: .5rem;
|
|
310
|
+
--tably-radius: .25rem;
|
|
269
311
|
}
|
|
270
312
|
|
|
271
313
|
.sticky {
|
|
272
314
|
position: sticky;
|
|
273
315
|
left: 0px;
|
|
274
316
|
/* right: 100px; */
|
|
275
|
-
background-color: var(--tably-bg, hsl(0, 0%, 100%));
|
|
276
317
|
z-index: 1;
|
|
277
318
|
}
|
|
278
319
|
|
|
@@ -284,30 +325,25 @@
|
|
|
284
325
|
border-right: 1px solid var(--tably-border, hsl(0, 0%, 90%));
|
|
285
326
|
resize: horizontal;
|
|
286
327
|
overflow: hidden;
|
|
287
|
-
padding: var(--padding-y) 0;
|
|
328
|
+
padding: var(--tably-padding-y) 0;
|
|
288
329
|
}
|
|
289
330
|
|
|
290
331
|
.table {
|
|
291
|
-
--panel: 250px;
|
|
292
|
-
--padding-x: 1rem;
|
|
293
|
-
--padding-y: .5rem;
|
|
294
|
-
--gap: .25rem;
|
|
295
|
-
--header-height: 2.5rem;
|
|
296
|
-
|
|
297
332
|
display: grid;
|
|
298
333
|
height: 100%;
|
|
334
|
+
position: relative;
|
|
299
335
|
|
|
300
336
|
grid-template-areas:
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
337
|
+
'headers panel'
|
|
338
|
+
'rows panel'
|
|
339
|
+
'statusbar panel'
|
|
304
340
|
;
|
|
305
341
|
|
|
306
342
|
grid-template-columns: auto min-content;
|
|
307
343
|
grid-template-rows: auto 1fr auto;
|
|
308
344
|
|
|
309
345
|
border: 1px solid var(--tably-border, hsl(0, 0%, 90%));
|
|
310
|
-
border-radius: .25rem;
|
|
346
|
+
border-radius: var(--tably-radius, .25rem);
|
|
311
347
|
|
|
312
348
|
max-height: 100%;
|
|
313
349
|
}
|
|
@@ -320,7 +356,6 @@
|
|
|
320
356
|
|
|
321
357
|
.headers > .column {
|
|
322
358
|
width: auto !important;
|
|
323
|
-
background-color: var(--tably-bg, hsl(0, 0%, 100%));
|
|
324
359
|
border-bottom: 1px solid var(--tably-border, hsl(0, 0%, 90%));
|
|
325
360
|
}
|
|
326
361
|
|
|
@@ -346,9 +381,8 @@
|
|
|
346
381
|
}
|
|
347
382
|
|
|
348
383
|
.statusbar > .column {
|
|
349
|
-
background-color: var(--tably-bg-statusbar, hsl(0, 0%, 99%));
|
|
350
384
|
border-top: 1px solid var(--tably-border, hsl(0, 0%, 90%));
|
|
351
|
-
padding: calc(var(--padding-y) / 2) 0;
|
|
385
|
+
padding: calc(var(--tably-padding-y) / 2) 0;
|
|
352
386
|
}
|
|
353
387
|
|
|
354
388
|
.headers, .row, .statusbar {
|
|
@@ -358,36 +392,36 @@
|
|
|
358
392
|
|
|
359
393
|
& > .column {
|
|
360
394
|
display: flex;
|
|
361
|
-
padding-left: var(--padding-x);
|
|
395
|
+
padding-left: var(--tably-padding-x);
|
|
362
396
|
overflow: hidden;
|
|
363
397
|
}
|
|
364
398
|
|
|
365
399
|
& > *:last-child {
|
|
366
400
|
width: 100%;
|
|
367
|
-
padding-right: var(--padding-x);
|
|
401
|
+
padding-right: var(--tably-padding-x);
|
|
368
402
|
}
|
|
369
403
|
}
|
|
370
404
|
|
|
371
|
-
|
|
372
|
-
padding-top: calc(var(--padding-y) + var(--
|
|
405
|
+
.row:first-child > * {
|
|
406
|
+
padding-top: calc(var(--tably-padding-y) + calc(var(--tably-padding-y) / 2));
|
|
407
|
+
}
|
|
408
|
+
.row:last-child > * {
|
|
409
|
+
padding-bottom: calc(var(--tably-padding-y) + calc(var(--tably-padding-y) / 2));
|
|
373
410
|
}
|
|
374
|
-
.row:nth-last-child(1) > * {
|
|
375
|
-
padding-bottom: calc(var(--padding-y) + var(--gap));
|
|
376
|
-
} */
|
|
377
411
|
|
|
378
412
|
.row > * {
|
|
379
|
-
padding: var(--
|
|
413
|
+
padding: calc(var(--tably-padding-y) / 2) 0;
|
|
380
414
|
}
|
|
381
415
|
|
|
382
416
|
.panel {
|
|
383
417
|
position: relative;
|
|
384
418
|
grid-area: panel;
|
|
385
419
|
height: 100%;
|
|
386
|
-
background-color: var(--tably-bg, hsl(0, 0%, 100%));
|
|
387
420
|
|
|
388
421
|
border-left: 1px solid var(--tably-border, hsl(0, 0%, 90%));
|
|
389
422
|
scrollbar-gutter: stable both-edges;
|
|
390
423
|
scrollbar-width: thin;
|
|
424
|
+
z-index: 4;
|
|
391
425
|
|
|
392
426
|
> .panel-content {
|
|
393
427
|
position: absolute;
|
|
@@ -395,7 +429,7 @@
|
|
|
395
429
|
right: 0;
|
|
396
430
|
width: min-content;
|
|
397
431
|
overflow: auto;
|
|
398
|
-
padding: var(--padding-y) 0;
|
|
432
|
+
padding: var(--tably-padding-y) 0;
|
|
399
433
|
}
|
|
400
434
|
}
|
|
401
435
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
|
1
2
|
export interface TableState<T extends Record<PropertyKey, any> = Record<PropertyKey, any>> {
|
|
2
|
-
columns: Record<string,
|
|
3
|
-
panels: Record<string,
|
|
3
|
+
columns: Record<string, TColumn<T, unknown>>;
|
|
4
|
+
panels: Record<string, TPanel>;
|
|
4
5
|
sortby?: string;
|
|
5
6
|
positions: {
|
|
6
7
|
sticky: string[];
|
|
@@ -9,23 +10,64 @@ export interface TableState<T extends Record<PropertyKey, any> = Record<Property
|
|
|
9
10
|
toggle(key: string): void;
|
|
10
11
|
};
|
|
11
12
|
readonly data: T[];
|
|
12
|
-
addColumn(key: string, options:
|
|
13
|
+
addColumn(key: string, options: TColumn<T, unknown>): void;
|
|
13
14
|
removeColumn(key: string): void;
|
|
14
15
|
}
|
|
15
16
|
export declare function getTableState<T extends Record<PropertyKey, any> = Record<PropertyKey, any>>(): TableState<T>;
|
|
16
17
|
import { type Snippet } from 'svelte';
|
|
17
|
-
import { type Column } from './Column.svelte';
|
|
18
|
-
import { type Panel } from './Panel.svelte';
|
|
18
|
+
import Column, { type Column as TColumn } from './Column.svelte';
|
|
19
|
+
import Panel, { type Panel as TPanel } from './Panel.svelte';
|
|
19
20
|
declare class __sveltets_Render<T extends Record<PropertyKey, unknown>> {
|
|
20
21
|
props(): {
|
|
21
|
-
|
|
22
|
+
content: Snippet<[context: {
|
|
23
|
+
Column: {
|
|
24
|
+
(internal: unknown, props: {
|
|
25
|
+
header: Column<T_1, V>["header"];
|
|
26
|
+
row: Column<T_1, V>["row"];
|
|
27
|
+
statusbar?: Column<T_1, V>["statusbar"];
|
|
28
|
+
id: string;
|
|
29
|
+
sticky?: boolean;
|
|
30
|
+
sort?: boolean;
|
|
31
|
+
show?: boolean;
|
|
32
|
+
value?: Column<T_1, V>["options"]["value"];
|
|
33
|
+
sorting?: Column<T_1, V>["options"]["sorting"];
|
|
34
|
+
}): {};
|
|
35
|
+
new (options: import("svelte").ComponentConstructorOptions<{
|
|
36
|
+
header: Column<T_1, V>["header"];
|
|
37
|
+
row: Column<T_1, V>["row"];
|
|
38
|
+
statusbar?: Column<T_1, V>["statusbar"];
|
|
39
|
+
id: string;
|
|
40
|
+
sticky?: boolean;
|
|
41
|
+
sort?: boolean;
|
|
42
|
+
show?: boolean;
|
|
43
|
+
value?: Column<T_1, V>["options"]["value"];
|
|
44
|
+
sorting?: Column<T_1, V>["options"]["sorting"];
|
|
45
|
+
}>): SvelteComponent<{
|
|
46
|
+
header: Column<T_1, V>["header"];
|
|
47
|
+
row: Column<T_1, V>["row"];
|
|
48
|
+
statusbar?: Column<T_1, V>["statusbar"];
|
|
49
|
+
id: string;
|
|
50
|
+
sticky?: boolean;
|
|
51
|
+
sort?: boolean;
|
|
52
|
+
show?: boolean;
|
|
53
|
+
value?: Column<T_1, V>["options"]["value"];
|
|
54
|
+
sorting?: Column<T_1, V>["options"]["sorting"];
|
|
55
|
+
}, {}, {}> & {
|
|
56
|
+
$$bindings?: ReturnType<() => "">;
|
|
57
|
+
};
|
|
58
|
+
z_$$bindings?: ReturnType<() => "">;
|
|
59
|
+
};
|
|
60
|
+
Panel: typeof Panel;
|
|
61
|
+
readonly state: TableState<T>;
|
|
62
|
+
readonly data: T[];
|
|
63
|
+
}]>;
|
|
22
64
|
panel?: string;
|
|
23
65
|
data?: T[] | undefined;
|
|
24
66
|
id?: string;
|
|
25
67
|
};
|
|
26
68
|
events(): {};
|
|
27
69
|
slots(): {};
|
|
28
|
-
bindings(): "";
|
|
70
|
+
bindings(): "panel";
|
|
29
71
|
exports(): {};
|
|
30
72
|
}
|
|
31
73
|
interface $$IsomorphicComponent {
|
package/dist/Table/index.d.ts
CHANGED
|
@@ -1,12 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import Column from './Column.svelte';
|
|
3
|
-
import { default as _Panel } from './Panel.svelte';
|
|
4
|
-
declare const LATIN: readonly ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"];
|
|
5
|
-
type Capital = typeof LATIN[number];
|
|
6
|
-
declare const Table: typeof _Table & {
|
|
7
|
-
[key: `${Capital}${string}`]: typeof Column;
|
|
8
|
-
};
|
|
9
|
-
declare const Panel: {
|
|
10
|
-
[key: `${Capital}${string}`]: typeof _Panel;
|
|
11
|
-
};
|
|
12
|
-
export { Table, Panel };
|
|
1
|
+
export { default as Table } from './Table.svelte';
|
package/dist/Table/index.js
CHANGED
|
@@ -1,31 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import Column from './Column.svelte';
|
|
3
|
-
import { default as _Panel } from './Panel.svelte';
|
|
4
|
-
const LATIN = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
|
|
5
|
-
const Table = new Proxy(_Table, {
|
|
6
|
-
get(target, p, receiver) {
|
|
7
|
-
if (typeof p !== 'string' || !LATIN.includes(p[0])) {
|
|
8
|
-
return Reflect.get(target, p, receiver);
|
|
9
|
-
}
|
|
10
|
-
return new Proxy(Column, {
|
|
11
|
-
apply(_, __, [anchor, props]) {
|
|
12
|
-
Object.assign(props, { __key: p });
|
|
13
|
-
return Column(anchor, props);
|
|
14
|
-
},
|
|
15
|
-
});
|
|
16
|
-
}
|
|
17
|
-
});
|
|
18
|
-
const Panel = new Proxy(_Panel, {
|
|
19
|
-
get(target, p, receiver) {
|
|
20
|
-
if (typeof p !== 'string' || !LATIN.includes(p[0])) {
|
|
21
|
-
return Reflect.get(target, p, receiver);
|
|
22
|
-
}
|
|
23
|
-
return new Proxy(_Panel, {
|
|
24
|
-
apply(_, __, [anchor, props]) {
|
|
25
|
-
Object.assign(props, { __key: p });
|
|
26
|
-
return _Panel(anchor, props);
|
|
27
|
-
},
|
|
28
|
-
});
|
|
29
|
-
},
|
|
30
|
-
});
|
|
31
|
-
export { Table, Panel };
|
|
1
|
+
export { default as Table } from './Table.svelte';
|
package/dist/index.d.ts
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import { Table } from './Table/index.js';
|
|
2
|
+
export default Table;
|
package/dist/index.js
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import { Table } from './Table/index.js';
|
|
2
|
+
export default Table;
|