svelte-tably 1.0.2-next.1 → 1.1.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/LICENSE +20 -20
- package/README.md +301 -301
- package/dist/column/Column.svelte +38 -38
- package/dist/column/Column.svelte.d.ts +1 -2
- package/dist/column/column-state.svelte.d.ts +6 -7
- package/dist/expandable/Expandable.svelte +24 -24
- package/dist/expandable/expandable-state.svelte.d.ts +2 -3
- package/dist/index.d.ts +7 -1
- package/dist/index.js +2 -1
- package/dist/panel/Panel.svelte +20 -20
- package/dist/panel/panel-state.svelte.d.ts +3 -4
- package/dist/row/Row.svelte +24 -24
- package/dist/row/row-state.svelte.d.ts +3 -4
- package/dist/table/Table.svelte +1169 -1146
- package/dist/table/Table.svelte.d.ts +3 -7
- package/dist/table/csv.d.ts +28 -0
- package/dist/table/csv.js +1 -0
- package/dist/table/data.svelte.d.ts +1 -1
- package/dist/table/table-state.svelte.d.ts +15 -9
- package/dist/table/table-state.svelte.js +91 -5
- package/package.json +1 -1
|
@@ -2,6 +2,7 @@ import { SvelteComponent } from "svelte";
|
|
|
2
2
|
import { type Snippet } from 'svelte';
|
|
3
3
|
import { TableState, type TableProps } from './table-state.svelte.js';
|
|
4
4
|
import { type RowColumnCtx } from '../column/column-state.svelte.js';
|
|
5
|
+
import type { CSVOptions } from './csv.js';
|
|
5
6
|
declare class __sveltets_Render<T extends Record<PropertyKey, unknown>> {
|
|
6
7
|
props(): TableProps<T> & {
|
|
7
8
|
content?: Snippet<[context: {
|
|
@@ -94,14 +95,9 @@ declare class __sveltets_Render<T extends Record<PropertyKey, unknown>> {
|
|
|
94
95
|
};
|
|
95
96
|
events(): {};
|
|
96
97
|
slots(): {};
|
|
97
|
-
bindings(): "selected" | "panel" | "data";
|
|
98
|
+
bindings(): "table" | "selected" | "panel" | "data";
|
|
98
99
|
exports(): {
|
|
99
|
-
toCSV: (
|
|
100
|
-
/** Semi-colons as separator? */
|
|
101
|
-
semicolon?: boolean;
|
|
102
|
-
/** Only selected rows */
|
|
103
|
-
selected?: boolean;
|
|
104
|
-
}) => Promise<string>;
|
|
100
|
+
toCSV: (options?: CSVOptions<T>) => Promise<string>;
|
|
105
101
|
};
|
|
106
102
|
}
|
|
107
103
|
interface $$IsomorphicComponent {
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export interface CSVOptions<T> {
|
|
2
|
+
/**
|
|
3
|
+
* Semi-colons as separator?
|
|
4
|
+
* @default false
|
|
5
|
+
*/
|
|
6
|
+
semicolon?: boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Export only selected rows in the visible data
|
|
9
|
+
* @default false
|
|
10
|
+
*/
|
|
11
|
+
selected?: boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Filters to apply to the data.
|
|
14
|
+
* - `true` to apply current filters e.g. currently visible content
|
|
15
|
+
* - `false` to ignore filters, export all data
|
|
16
|
+
* - Array of functions to filter data manually
|
|
17
|
+
* @default true
|
|
18
|
+
*/
|
|
19
|
+
filters?: true | false | ((item: T) => boolean)[];
|
|
20
|
+
/**
|
|
21
|
+
* Columns to export. By default exports all visible columns.
|
|
22
|
+
* - `true` to export all columns
|
|
23
|
+
* - `false` to export only visible columns
|
|
24
|
+
* - Array of column IDs to export specific columns
|
|
25
|
+
* @default false
|
|
26
|
+
*/
|
|
27
|
+
columns?: true | false | string[];
|
|
28
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -2,11 +2,11 @@ import { type Snippet } from 'svelte';
|
|
|
2
2
|
import { ColumnState, type RowColumnCtx } from '../column/column-state.svelte.js';
|
|
3
3
|
import { PanelState } from '../panel/panel-state.svelte.js';
|
|
4
4
|
import { Data } from './data.svelte.js';
|
|
5
|
-
import { type AnyRecord } from '../utility.svelte.js';
|
|
6
5
|
import type { ExpandableState } from '../expandable/expandable-state.svelte.js';
|
|
7
6
|
import type { ItemState } from 'runic-reorder';
|
|
8
7
|
import type { RowState } from '../row/row-state.svelte.js';
|
|
9
|
-
|
|
8
|
+
import { CSVOptions } from "./csv.js";
|
|
9
|
+
export type HeaderSelectCtx<T = any> = {
|
|
10
10
|
isSelected: boolean;
|
|
11
11
|
/** The list of selected items */
|
|
12
12
|
readonly selected: T[];
|
|
@@ -15,20 +15,20 @@ export type HeaderSelectCtx<T extends AnyRecord = any> = {
|
|
|
15
15
|
*/
|
|
16
16
|
readonly indeterminate: boolean;
|
|
17
17
|
};
|
|
18
|
-
export type RowSelectCtx<T extends
|
|
18
|
+
export type RowSelectCtx<T extends any = any> = {
|
|
19
19
|
readonly item: T;
|
|
20
20
|
readonly row: RowColumnCtx<T, unknown>;
|
|
21
21
|
data: T[];
|
|
22
22
|
isSelected: boolean;
|
|
23
23
|
};
|
|
24
|
-
export interface RowCtx<T extends
|
|
24
|
+
export interface RowCtx<T extends any> {
|
|
25
25
|
readonly rowHovered: boolean;
|
|
26
26
|
readonly index: number;
|
|
27
27
|
readonly itemState: ItemState<T> | undefined;
|
|
28
28
|
selected: boolean;
|
|
29
29
|
expanded: boolean;
|
|
30
30
|
}
|
|
31
|
-
type SelectOptions<T extends
|
|
31
|
+
type SelectOptions<T extends any> = {
|
|
32
32
|
/**
|
|
33
33
|
* The style, in which the selection is shown
|
|
34
34
|
*
|
|
@@ -49,8 +49,10 @@ type SelectOptions<T extends AnyRecord> = {
|
|
|
49
49
|
headerSnippet?: Snippet<[context: HeaderSelectCtx]>;
|
|
50
50
|
rowSnippet?: Snippet<[context: RowSelectCtx<T>]>;
|
|
51
51
|
};
|
|
52
|
-
export type TableProps<T extends
|
|
52
|
+
export type TableProps<T extends any> = {
|
|
53
53
|
id?: string;
|
|
54
|
+
/** Bindable to TableState; `bind:table` */
|
|
55
|
+
table?: TableState<T>;
|
|
54
56
|
data: T[];
|
|
55
57
|
selected?: T[];
|
|
56
58
|
/** Current visible panel */
|
|
@@ -72,9 +74,10 @@ export type TableProps<T extends AnyRecord> = {
|
|
|
72
74
|
/** Create missing columns automatically. */
|
|
73
75
|
auto?: boolean;
|
|
74
76
|
};
|
|
75
|
-
export declare class TableState<T
|
|
77
|
+
export declare class TableState<T> {
|
|
76
78
|
#private;
|
|
77
|
-
id: string;
|
|
79
|
+
id: string | undefined;
|
|
80
|
+
cssId: string;
|
|
78
81
|
dataState: Data<T>;
|
|
79
82
|
data: T[];
|
|
80
83
|
columns: Record<string, ColumnState<T, any>>;
|
|
@@ -101,7 +104,10 @@ export declare class TableState<T extends AnyRecord> {
|
|
|
101
104
|
auto: boolean;
|
|
102
105
|
};
|
|
103
106
|
add(state: ColumnState<T, any> | PanelState<T>): (() => void) | undefined;
|
|
104
|
-
static getContext<T
|
|
107
|
+
static getContext<T>(): TableState<T> | undefined;
|
|
108
|
+
/** Width of each column */
|
|
109
|
+
columnWidths: Record<string, number>;
|
|
110
|
+
toCSV(options?: CSVOptions<T>): Promise<string>;
|
|
105
111
|
constructor(tableProps: TableProps<T>);
|
|
106
112
|
}
|
|
107
113
|
export {};
|
|
@@ -5,6 +5,7 @@ import { Data } from './data.svelte.js';
|
|
|
5
5
|
export class TableState {
|
|
6
6
|
#props = {};
|
|
7
7
|
id = $state();
|
|
8
|
+
cssId = $state();
|
|
8
9
|
dataState = $state({});
|
|
9
10
|
data = $derived(this.dataState.current ?? []);
|
|
10
11
|
columns = $state({});
|
|
@@ -14,6 +15,13 @@ export class TableState {
|
|
|
14
15
|
/** Currently selected items */
|
|
15
16
|
get selected() { return this.#props.selected ??= []; }
|
|
16
17
|
set selected(items) { this.#props.selected = items; }
|
|
18
|
+
/** Saved positions */
|
|
19
|
+
#positions = $state({
|
|
20
|
+
fixed: [],
|
|
21
|
+
sticky: [],
|
|
22
|
+
hidden: [],
|
|
23
|
+
scroll: []
|
|
24
|
+
});
|
|
17
25
|
/** Column positions based on column ids */
|
|
18
26
|
positions = $state({
|
|
19
27
|
fixed: [],
|
|
@@ -41,16 +49,27 @@ export class TableState {
|
|
|
41
49
|
this.positions.scroll = this.positions.scroll.filter((column) => column !== state);
|
|
42
50
|
this.positions.hidden = this.positions.hidden.filter((column) => column !== state);
|
|
43
51
|
};
|
|
44
|
-
if (state.defaults.sortby)
|
|
52
|
+
if (state.defaults.sortby && !this.dataState.sortby) {
|
|
45
53
|
this.dataState.sortBy(key);
|
|
46
|
-
|
|
54
|
+
}
|
|
55
|
+
const saved = {
|
|
56
|
+
fixed: this.#positions.fixed.includes(key),
|
|
57
|
+
sticky: this.#positions.sticky.includes(key),
|
|
58
|
+
hidden: this.#positions.hidden.includes(key),
|
|
59
|
+
scroll: this.#positions.scroll.includes(key)
|
|
60
|
+
};
|
|
61
|
+
const isSaved = Object.values(saved).some(v => v);
|
|
62
|
+
if ((!isSaved && state.options.fixed)
|
|
63
|
+
|| saved.fixed) {
|
|
47
64
|
this.positions.fixed.push(state);
|
|
48
65
|
return clean;
|
|
49
66
|
}
|
|
50
|
-
if (state.defaults.show === false)
|
|
67
|
+
if ((!isSaved && state.defaults.show === false)
|
|
68
|
+
|| saved.hidden) {
|
|
51
69
|
this.positions.hidden.push(state);
|
|
52
70
|
}
|
|
53
|
-
if (state.defaults.sticky)
|
|
71
|
+
if ((!isSaved && state.defaults.sticky)
|
|
72
|
+
|| saved.sticky) {
|
|
54
73
|
this.positions.sticky.push(state);
|
|
55
74
|
}
|
|
56
75
|
else {
|
|
@@ -67,10 +86,77 @@ export class TableState {
|
|
|
67
86
|
static getContext() {
|
|
68
87
|
return getContext('svelte-tably');
|
|
69
88
|
}
|
|
89
|
+
/** Width of each column */
|
|
90
|
+
columnWidths = $state({});
|
|
91
|
+
#save() {
|
|
92
|
+
const content = {
|
|
93
|
+
columnWidths: this.columnWidths,
|
|
94
|
+
positions: {
|
|
95
|
+
fixed: this.positions.fixed.map(c => c.id),
|
|
96
|
+
sticky: this.positions.sticky.map(c => c.id),
|
|
97
|
+
hidden: this.positions.hidden.map(c => c.id),
|
|
98
|
+
scroll: this.positions.scroll.map(c => c.id)
|
|
99
|
+
},
|
|
100
|
+
sortby: this.dataState.sortby,
|
|
101
|
+
sortReverse: this.dataState.sortReverse
|
|
102
|
+
};
|
|
103
|
+
localStorage.setItem(`svelte-tably:${this.id}`, JSON.stringify(content));
|
|
104
|
+
}
|
|
105
|
+
#saving = false;
|
|
106
|
+
#scheduleSave() {
|
|
107
|
+
if (this.#saving)
|
|
108
|
+
return;
|
|
109
|
+
if (typeof localStorage === 'undefined')
|
|
110
|
+
return;
|
|
111
|
+
this.#saving = true;
|
|
112
|
+
setTimeout(() => {
|
|
113
|
+
this.#saving = false;
|
|
114
|
+
this.#save();
|
|
115
|
+
}, 1000);
|
|
116
|
+
}
|
|
117
|
+
#load() {
|
|
118
|
+
if (typeof localStorage === 'undefined')
|
|
119
|
+
return null;
|
|
120
|
+
const item = JSON.parse(localStorage.getItem(`svelte-tably:${this.id}`) || '{}');
|
|
121
|
+
item.columnWidths ??= {};
|
|
122
|
+
item.positions ??= {};
|
|
123
|
+
item.positions.fixed ??= [];
|
|
124
|
+
item.positions.sticky ??= [];
|
|
125
|
+
item.positions.hidden ??= [];
|
|
126
|
+
item.positions.scroll ??= [];
|
|
127
|
+
item.sortby ??= undefined;
|
|
128
|
+
item.sortReverse ??= false;
|
|
129
|
+
return item;
|
|
130
|
+
}
|
|
131
|
+
async toCSV(options = {}) {
|
|
132
|
+
options;
|
|
133
|
+
return '';
|
|
134
|
+
}
|
|
70
135
|
constructor(tableProps) {
|
|
71
136
|
this.#props = tableProps;
|
|
72
|
-
this.id = tableProps.id
|
|
137
|
+
this.id = tableProps.id;
|
|
138
|
+
this.cssId = Array.from({ length: 12 }, () => String.fromCharCode(Math.floor(Math.random() * 26) + 97)).join('');
|
|
73
139
|
this.dataState = new Data(this, tableProps);
|
|
140
|
+
if (this.id) {
|
|
141
|
+
// fetch from localstorage
|
|
142
|
+
const saved = this.#load();
|
|
143
|
+
if (saved) {
|
|
144
|
+
this.columnWidths = saved.columnWidths;
|
|
145
|
+
this.#positions = saved.positions;
|
|
146
|
+
this.dataState.sortby = saved.sortby;
|
|
147
|
+
this.dataState.sortReverse = saved.sortReverse;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
if (typeof window !== 'undefined') {
|
|
151
|
+
window.addEventListener('beforeunload', () => this.#save());
|
|
152
|
+
}
|
|
153
|
+
$effect(() => {
|
|
154
|
+
Object.keys(this.columnWidths);
|
|
155
|
+
Object.values(this.positions).map(v => v.length);
|
|
156
|
+
this.dataState.sortby;
|
|
157
|
+
this.dataState.sortReverse;
|
|
158
|
+
this.#scheduleSave();
|
|
159
|
+
});
|
|
74
160
|
setContext('svelte-tably', this);
|
|
75
161
|
}
|
|
76
162
|
}
|