@guiexpert/table 1.1.91 → 1.1.93
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 +5 -1
- package/css/main.css +79 -0
- package/css/table-classes.css +63 -0
- package/css/table-color-vars.css +16 -0
- package/index.cjs +58 -34
- package/index.d.ts +11 -0
- package/index.js +2425 -1243
- package/lib/table/aria/live-announcer.d.ts +9 -0
- package/lib/table/crud/crud-table-model-factory.d.ts +8 -0
- package/lib/table/data/common/event/ge-state-change-event.d.ts +30 -0
- package/lib/table/data/options/auto-restore-options.d.ts +14 -2
- package/lib/table/data/options/auto-restore-options.if.d.ts +94 -52
- package/lib/table/data/options/default-row-id.d.ts +4 -0
- package/lib/table/data/options/overlay-options.d.ts +30 -0
- package/lib/table/data/options/overlay-options.if.d.ts +79 -0
- package/lib/table/data/options/table-options.d.ts +3 -0
- package/lib/table/data/options/table-options.if.d.ts +35 -0
- package/lib/table/data/tablemodel/areamodel/area-model-array-of-arrays.d.ts +7 -0
- package/lib/table/data/tablemodel/areamodel/area-model-cell-groups.d.ts +31 -0
- package/lib/table/data/tablemodel/areamodel/area-model-object-array.d.ts +13 -0
- package/lib/table/data/tablemodel/areamodel/area-model-tree.d.ts +9 -0
- package/lib/table/data/tablemodel/areamodel/area-model.if.d.ts +19 -0
- package/lib/table/data/tablemodel/areamodel/cover-grid-body-model.d.ts +7 -0
- package/lib/table/data/tablemodel/cellgroup/cell-group.d.ts +2 -0
- package/lib/table/data/tablemodel/cellgroup/cell-group.if.d.ts +6 -0
- package/lib/table/data/tablemodel/column/column-visibility.d.ts +5 -0
- package/lib/table/ele-scope.d.ts +17 -0
- package/lib/table/event-adapter.d.ts +3 -0
- package/lib/table/event-listener.if.d.ts +8 -0
- package/lib/table/mouse-handler.d.ts +2 -0
- package/lib/table/overlay/calc-overlay-kind.d.ts +31 -0
- package/lib/table/overlay/ge-overlay-kind.type.d.ts +17 -0
- package/lib/table/overlay/table-overlay.d.ts +108 -0
- package/lib/table/render-scope.d.ts +26 -2
- package/lib/table/service/convenience-dom.service.d.ts +1 -1
- package/lib/table/state/state-storage.if.d.ts +39 -0
- package/lib/table/state/table-state-migration.d.ts +36 -0
- package/lib/table/state/table-state-part.d.ts +13 -0
- package/lib/table/state/table-state.if.d.ts +181 -0
- package/lib/table/state/table-state.service.d.ts +158 -0
- package/lib/table/table-api.d.ts +154 -0
- package/lib/table/table-scope.d.ts +78 -31
- package/package.json +1 -1
|
@@ -31,6 +31,7 @@ export declare class LiveAnnouncer {
|
|
|
31
31
|
static defaultDelayInMs: number;
|
|
32
32
|
private element?;
|
|
33
33
|
private timeout?;
|
|
34
|
+
private pendingText?;
|
|
34
35
|
constructor(document: Document | undefined, id: string, domService: DomServiceIf);
|
|
35
36
|
/**
|
|
36
37
|
* Speaks a message (replaces a message that is still waiting).
|
|
@@ -39,6 +40,14 @@ export declare class LiveAnnouncer {
|
|
|
39
40
|
* @param {number} [delayInMs=LiveAnnouncer.defaultDelayInMs] - wait this long before the text is written
|
|
40
41
|
*/
|
|
41
42
|
announce(text: string, delayInMs?: number): void;
|
|
43
|
+
/**
|
|
44
|
+
* Drops a message that is still waiting (not spoken yet) – only if it is `text` (or any message without `text`).
|
|
45
|
+
* Used when the reason for the message is gone, e.g. "Loading…" after the data arrived.
|
|
46
|
+
*
|
|
47
|
+
* @param {string} [text] - only this message is dropped
|
|
48
|
+
* @since 1.1.92
|
|
49
|
+
*/
|
|
50
|
+
cancel(text?: string): void;
|
|
42
51
|
/**
|
|
43
52
|
* The live region element (created on the first call).
|
|
44
53
|
*
|
|
@@ -56,6 +56,7 @@ export declare class CrudTableModelFactory implements ActionEventListenerIf {
|
|
|
56
56
|
* list is loaded again (`fetchList`);
|
|
57
57
|
* - `DELETE`: `deleteItem(id)` → the row is removed.
|
|
58
58
|
*
|
|
59
|
+
* While a request runs, the table shows its loading overlay ({@link TableApi.showLoadingOverlay}, since 1.1.92).
|
|
59
60
|
* A failed request is logged with `console.error`; the table stays unchanged.
|
|
60
61
|
*/
|
|
61
62
|
onActionEvent(actionEvent: ActionEventIf): void;
|
|
@@ -67,6 +68,13 @@ export declare class CrudTableModelFactory implements ActionEventListenerIf {
|
|
|
67
68
|
private addRow;
|
|
68
69
|
/** Loads the list again (`fetchList`) – after a create whose response does not contain the new item. */
|
|
69
70
|
private reloadRows;
|
|
71
|
+
/**
|
|
72
|
+
* Shows the loading overlay of the table while `request` runs (also when it fails). Before the table exists
|
|
73
|
+
* (first `fetchList` in {@link createTableModel}) there is nothing to show it on.
|
|
74
|
+
*/
|
|
75
|
+
private whileLoading;
|
|
76
|
+
/** Requests on the way ({@link whileLoading}). */
|
|
77
|
+
private pendingRequests;
|
|
70
78
|
private getIdKey;
|
|
71
79
|
/** The action column carries the id as text (data-id) – compare as strings. */
|
|
72
80
|
private hasId;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { TableStateIf, TableStatePart } from '../../../state/table-state.if.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The state of a table changed ({@link EventListenerIf.onStateChanged}): a column was resized, moved, hidden,
|
|
5
|
+
* the table was sorted, scrolled, a node expanded, a row checked or selected … Reported once after the changes
|
|
6
|
+
* settled ({@link TableOptionsIf.stateChangedDebounceDelay}, default 300 ms) and only if a part really changed;
|
|
7
|
+
* not while the table is built.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* const listener = new EventAdapter();
|
|
11
|
+
* listener.onStateChanged = (evt: GeStateChangeEvent) => {
|
|
12
|
+
* if (!evt.changedParts.includes("scroll")) { // e.g. ignore pure scrolling
|
|
13
|
+
* void fetch("/api/prefs/orders", { method: "PUT", body: JSON.stringify(evt.state) });
|
|
14
|
+
* }
|
|
15
|
+
* };
|
|
16
|
+
*
|
|
17
|
+
* @category State
|
|
18
|
+
* @since 1.1.92
|
|
19
|
+
*/
|
|
20
|
+
export declare class GeStateChangeEvent {
|
|
21
|
+
/** The whole state of the table now (all parts). */
|
|
22
|
+
readonly state: TableStateIf;
|
|
23
|
+
/** The parts that changed since the last event. */
|
|
24
|
+
readonly changedParts: TableStatePart[];
|
|
25
|
+
constructor(
|
|
26
|
+
/** The whole state of the table now (all parts). */
|
|
27
|
+
state: TableStateIf,
|
|
28
|
+
/** The parts that changed since the last event. */
|
|
29
|
+
changedParts: TableStatePart[]);
|
|
30
|
+
}
|
|
@@ -2,7 +2,7 @@ import { AutoRestoreOptionsIf } from './auto-restore-options.if.js';
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Defaults for {@link TableOptionsIf.autoRestoreOptions}: everything off. Spread it and switch on what the table
|
|
5
|
-
* should remember in `localStorage` (one key per table).
|
|
5
|
+
* should remember in `localStorage` (one key per table) – see {@link AutoRestoreOptionsIf} for all flags.
|
|
6
6
|
*
|
|
7
7
|
* @example
|
|
8
8
|
* const tableOptions: TableOptionsIf = {
|
|
@@ -11,7 +11,8 @@ import { AutoRestoreOptionsIf } from './auto-restore-options.if.js';
|
|
|
11
11
|
* ...new AutoRestoreOptions<Order>(),
|
|
12
12
|
* getStorageKeyFn: () => "orders-table", // unique per table
|
|
13
13
|
* autoRestoreSortingState: true,
|
|
14
|
-
* autoRestoreScrollPosition: true
|
|
14
|
+
* autoRestoreScrollPosition: true,
|
|
15
|
+
* autoRestoreColumnLayout: true // widths, order, visibility (since 1.1.92)
|
|
15
16
|
* }
|
|
16
17
|
* };
|
|
17
18
|
*
|
|
@@ -37,7 +38,18 @@ export declare class AutoRestoreOptions<T> implements AutoRestoreOptionsIf<T> {
|
|
|
37
38
|
autoRestoreScrollPosition: boolean;
|
|
38
39
|
autoRestoreCheckedState: boolean;
|
|
39
40
|
autoRestoreSelectedState: boolean;
|
|
41
|
+
/** @since 1.1.92 */
|
|
42
|
+
autoRestoreColumnLayout: boolean;
|
|
43
|
+
/** @since 1.1.92 */
|
|
44
|
+
autoRestoreHeaderGroupState: boolean;
|
|
45
|
+
/** @since 1.1.92 */
|
|
46
|
+
autoRestoreCustomState: boolean;
|
|
40
47
|
getStorageKeyFn: undefined;
|
|
48
|
+
/** @deprecated since 1.1.92 – never used by the table. */
|
|
41
49
|
isSame: (r1: T, r2: T, options: AutoRestoreOptionsIf<T>) => boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Default: the property `id`, then `uuid`, then the JSON of the row. The table itself uses only `id` / `uuid` of
|
|
52
|
+
* this default (since 1.1.92): rows without them are not stored – the JSON would write whole rows into the storage.
|
|
53
|
+
*/
|
|
42
54
|
getRowId: (row: T) => string | number;
|
|
43
55
|
}
|
|
@@ -1,81 +1,123 @@
|
|
|
1
|
+
import { StateStorageIf } from '../../state/state-storage.if.js';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
|
-
* `IsSameFn`
|
|
3
|
-
* two instances of a generic type `T`, in conjunction with supplied options of type `AutoRestoreOptionsIf<T>`.
|
|
4
|
+
* `IsSameFn` compares two rows with the help of {@link AutoRestoreOptionsIf.getRowId}.
|
|
4
5
|
*
|
|
5
|
-
*
|
|
6
|
-
* This helps in preserving specific states of the application, like sorting or selected state, across different stages or conditions
|
|
7
|
-
* based on the developer's implementation. By default, this function uses strict equality check (`===`) if not provided.
|
|
8
|
-
*
|
|
9
|
-
* @typedef
|
|
10
|
-
* @typeparam T - The type of the objects that the function is comparing.
|
|
11
|
-
*
|
|
12
|
-
* @param {T} r1 - The first object instance of type `T`.
|
|
13
|
-
* @param {T} r2 - The second object instance of type `T`.
|
|
14
|
-
* @param {AutoRestoreOptionsIf<T>} optionsIf - The options that dictate the behavior of auto-restoring.
|
|
15
|
-
*
|
|
16
|
-
* @returns {boolean} - Returns `true` if the two instances are considered the same, `false` otherwise.
|
|
6
|
+
* @deprecated since 1.1.92 – never used by the table; rows are compared by {@link AutoRestoreOptionsIf.getRowId}.
|
|
17
7
|
*
|
|
8
|
+
* @typeparam T - The type of the rows.
|
|
18
9
|
* @category Options
|
|
19
10
|
*/
|
|
20
11
|
export type IsSameFn<T> = (r1: T, r2: T, optionsIf: AutoRestoreOptionsIf<T>) => boolean;
|
|
21
12
|
/**
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
13
|
+
* Returns a unique, stable id for a row – used to remember expanded tree nodes, checked and selected rows and the
|
|
14
|
+
* first visible row ({@link AutoRestoreOptionsIf}, {@link TableStateIf}).
|
|
15
|
+
*
|
|
16
|
+
* Tree tables get the object of the node (`treeRow.data`). Models without row objects (e.g. an own `AreaModel`
|
|
17
|
+
* that computes its values) get `undefined` and the displayed row index – declare the second parameter to support
|
|
18
|
+
* them: `(_row, rowIndex) => rowIndex`.
|
|
27
19
|
*
|
|
20
|
+
* @example
|
|
21
|
+
* const getRowId: GetRowIdFn<Order> = (order: Order) => order.id;
|
|
22
|
+
*
|
|
23
|
+
* @typeparam T - The type of the rows.
|
|
28
24
|
* @category Options
|
|
29
25
|
*/
|
|
30
|
-
export type GetRowIdFn<T> = ((row: T) => string | number);
|
|
26
|
+
export type GetRowIdFn<T> = ((row: T, rowIndex?: number) => string | number);
|
|
31
27
|
/**
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
* @typedef
|
|
28
|
+
* Returns the storage key of a table – one key per table, e.g. `() => "orders"`. The state is stored under
|
|
29
|
+
* `<key>tableState`.
|
|
35
30
|
*
|
|
36
31
|
* @category Options
|
|
37
32
|
*/
|
|
38
33
|
export type GetStorageKeyFn = (() => string);
|
|
39
34
|
/**
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
* @
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
* @
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
* @
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
35
|
+
* What a table remembers between page loads, and where. Everything is off by default ({@link AutoRestoreOptions});
|
|
36
|
+
* nothing is stored without {@link getStorageKeyFn} (the table warns once if a flag is set without it).
|
|
37
|
+
*
|
|
38
|
+
* The state is stored as one JSON value under `<key>tableState` in {@link storage} (default `localStorage`) –
|
|
39
|
+
* the same format as {@link TableApi.getState}. Columns are stored by property and rows by {@link getRowId}, so a
|
|
40
|
+
* moved column or new data never hits the wrong column or row. The stored state holds no cell values, but row ids
|
|
41
|
+
* can be personal data (e.g. an e-mail address as id) – prefer technical ids. The tree, checked rows, the selection
|
|
42
|
+
* and the first visible row need row ids; tree, checked and selected rows are computed only when their flag is set.
|
|
43
|
+
*
|
|
44
|
+
* | Flag | Remembers | since |
|
|
45
|
+
* |---|---|---|
|
|
46
|
+
* | {@link autoRestoreSortingState} | sorted columns | |
|
|
47
|
+
* | {@link autoRestoreScrollPosition} | scroll position | |
|
|
48
|
+
* | {@link autoRestoreCollapsedExpandedState} | expanded tree nodes | |
|
|
49
|
+
* | {@link autoRestoreColumnLayout} | width, order, visibility of the columns | 1.1.92 |
|
|
50
|
+
* | {@link autoRestoreHeaderGroupState} | collapsed header groups | 1.1.92 |
|
|
51
|
+
* | {@link autoRestoreCheckedState} | checked rows | 1.1.92 (declared before, without effect) |
|
|
52
|
+
* | {@link autoRestoreSelectedState} | selection | 1.1.92 (declared before, without effect) |
|
|
53
|
+
* | {@link autoRestoreCustomState} | your data ({@link TableApi.setCustomState}) | 1.1.92 |
|
|
54
|
+
*
|
|
55
|
+
* Before 1.1.92 sorting, scroll position and tree were stored under three keys (`<key>sortingState`,
|
|
56
|
+
* `<key>scrollState`, `<key>collapsedExpandedState`); they are read once and removed with the next save.
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* const tableOptions: TableOptionsIf = {
|
|
60
|
+
* ...new TableOptions(),
|
|
61
|
+
* autoRestoreOptions: {
|
|
62
|
+
* ...new AutoRestoreOptions<Order>(),
|
|
63
|
+
* getStorageKeyFn: () => "orders",
|
|
64
|
+
* getRowId: (order: Order) => order.id,
|
|
65
|
+
* autoRestoreColumnLayout: true,
|
|
66
|
+
* autoRestoreSortingState: true,
|
|
67
|
+
* autoRestoreCheckedState: true
|
|
68
|
+
* }
|
|
69
|
+
* };
|
|
70
|
+
*
|
|
71
|
+
* @typeparam T - The type of the rows.
|
|
72
|
+
* @see Training: [Remember the state](https://gui.expert/training/persist-state/)
|
|
69
73
|
*
|
|
70
74
|
* @category Options
|
|
71
75
|
*/
|
|
72
76
|
export interface AutoRestoreOptionsIf<T> {
|
|
77
|
+
/** Remember the sorted columns (by property). */
|
|
73
78
|
autoRestoreSortingState: boolean;
|
|
79
|
+
/** Remember expanded and collapsed nodes of a tree table (by {@link getRowId}). */
|
|
74
80
|
autoRestoreCollapsedExpandedState?: boolean;
|
|
81
|
+
/** Remember the scroll position (and the id of the first visible row). */
|
|
75
82
|
autoRestoreScrollPosition?: boolean;
|
|
83
|
+
/** Remember the checked rows (by {@link getRowId}). Since 1.1.92 (before: declared without effect). */
|
|
76
84
|
autoRestoreCheckedState?: boolean;
|
|
85
|
+
/**
|
|
86
|
+
* Remember the selection: rows by {@link getRowId}, columns by property. Restored in the current row order.
|
|
87
|
+
* Since 1.1.92 (before: declared without effect).
|
|
88
|
+
*/
|
|
77
89
|
autoRestoreSelectedState?: boolean;
|
|
90
|
+
/**
|
|
91
|
+
* Remember width, order and visibility of the columns (by property). Widths are stored only for columns that were
|
|
92
|
+
* resized, so `%` and weight columns stay responsive.
|
|
93
|
+
* @since 1.1.92
|
|
94
|
+
*/
|
|
95
|
+
autoRestoreColumnLayout?: boolean;
|
|
96
|
+
/**
|
|
97
|
+
* Remember collapsed and expanded header groups ({@link CellGroupIf.toggle}).
|
|
98
|
+
* @since 1.1.92
|
|
99
|
+
*/
|
|
100
|
+
autoRestoreHeaderGroupState?: boolean;
|
|
101
|
+
/**
|
|
102
|
+
* Remember the data set with {@link TableApi.setCustomState} (e.g. a filter text).
|
|
103
|
+
* @since 1.1.92
|
|
104
|
+
*/
|
|
105
|
+
autoRestoreCustomState?: boolean;
|
|
106
|
+
/**
|
|
107
|
+
* A unique, stable id per row (tree: per node). With the default of {@link AutoRestoreOptions} the table uses the
|
|
108
|
+
* property `id`, then `uuid`; rows without them are not stored (since 1.1.92 – the JSON of the row would write
|
|
109
|
+
* personal data into the storage; the table warns once).
|
|
110
|
+
*/
|
|
78
111
|
getRowId?: undefined | GetRowIdFn<T>;
|
|
112
|
+
/** The storage key of this table, e.g. `() => "orders"`. Without it nothing is stored. */
|
|
79
113
|
getStorageKeyFn?: undefined | GetStorageKeyFn;
|
|
114
|
+
/**
|
|
115
|
+
* @deprecated since 1.1.92 – never used; rows are compared by {@link getRowId}.
|
|
116
|
+
*/
|
|
80
117
|
isSame?: undefined | IsSameFn<T>;
|
|
118
|
+
/**
|
|
119
|
+
* Where the state is stored. Default: `localStorage`; `sessionStorage` or an own {@link StateStorageIf} also work.
|
|
120
|
+
* @since 1.1.92
|
|
121
|
+
*/
|
|
122
|
+
storage?: StateStorageIf;
|
|
81
123
|
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** Marks a function as the default `getRowId` of {@link AutoRestoreOptions}. */
|
|
2
|
+
export declare function markDefaultGetRowId<F extends object>(fn: F): F;
|
|
3
|
+
/** true for the default `getRowId` of {@link AutoRestoreOptions} (also after spreading the options). */
|
|
4
|
+
export declare function isDefaultGetRowId(fn: unknown): boolean;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { OverlayOptionsIf } from './overlay-options.if.js';
|
|
2
|
+
import { GeOverlayKind } from '../../overlay/ge-overlay-kind.type.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The defaults of {@link OverlayOptionsIf}: English texts, an automatic "No rows to show", a loading overlay that
|
|
6
|
+
* blocks the body and appears right away.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* const overlayOptions = OverlayOptions.create({ noRowsText: "Keine Daten" });
|
|
10
|
+
* console.log(overlayOptions.loadingText); // "Loading…"
|
|
11
|
+
*
|
|
12
|
+
* @since 1.1.92
|
|
13
|
+
* @category Overlays
|
|
14
|
+
*/
|
|
15
|
+
export declare class OverlayOptions implements OverlayOptionsIf {
|
|
16
|
+
loadingText: string;
|
|
17
|
+
noRowsText: string;
|
|
18
|
+
noMatchesText: string;
|
|
19
|
+
autoNoRows: boolean;
|
|
20
|
+
blockInteractionWhileLoading: boolean;
|
|
21
|
+
loadingDelayInMs: number;
|
|
22
|
+
getOverlayElement?: (kind: GeOverlayKind, text: string) => HTMLElement | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* The defaults with the given fields on top (`undefined` fields keep their default).
|
|
25
|
+
*
|
|
26
|
+
* @param {Partial<OverlayOptionsIf>} [partial] - e.g. `tableOptions.overlayOptions`
|
|
27
|
+
* @returns {OverlayOptions} a new object
|
|
28
|
+
*/
|
|
29
|
+
static create(partial?: Partial<OverlayOptionsIf>): OverlayOptions;
|
|
30
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { GeOverlayKind } from '../../overlay/ge-overlay-kind.type.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Texts and behaviour of the overlays over the table body: "Loading…" ({@link TableApi.showLoadingOverlay}),
|
|
5
|
+
* "No rows to show" (empty body) and "No matching rows" (the external filter hides all rows).
|
|
6
|
+
*
|
|
7
|
+
* Set it with {@link TableOptionsIf.overlayOptions} – every field is optional there, missing ones keep their
|
|
8
|
+
* default ({@link OverlayOptions}). The overlays are plain HTML and CSS (spinner: `@keyframes`), colours come from
|
|
9
|
+
* the CSS variables `--ge-table-overlay-bg`, `--ge-table-overlay-color`, `--ge-table-spinner-color`,
|
|
10
|
+
* `--ge-table-spinner-track-color` and `--ge-table-spinner-size`.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* const tableOptions: TableOptionsIf = {
|
|
14
|
+
* ...new TableOptions(),
|
|
15
|
+
* overlayOptions: {
|
|
16
|
+
* loadingText: "Lädt…",
|
|
17
|
+
* noRowsText: "Keine Daten",
|
|
18
|
+
* noMatchesText: "Keine Treffer",
|
|
19
|
+
* loadingDelayInMs: 200, // fast answers show no spinner at all
|
|
20
|
+
* },
|
|
21
|
+
* };
|
|
22
|
+
*
|
|
23
|
+
* @since 1.1.92
|
|
24
|
+
* @see Training: [Live data](https://gui.expert/training/live-data/)
|
|
25
|
+
* @category Overlays
|
|
26
|
+
*/
|
|
27
|
+
export interface OverlayOptionsIf {
|
|
28
|
+
/** Text of the loading overlay. Default: `"Loading…"`. */
|
|
29
|
+
loadingText: string;
|
|
30
|
+
/** Text of the overlay of an empty body. Default: `"No rows to show"`. */
|
|
31
|
+
noRowsText: string;
|
|
32
|
+
/** Text when the external filter hides all rows. Default: `"No matching rows"`. */
|
|
33
|
+
noMatchesText: string;
|
|
34
|
+
/**
|
|
35
|
+
* `true` (default): an empty body shows "No rows to show" (or "No matching rows") by itself, after every
|
|
36
|
+
* repaint. `false`: only {@link TableApi.showNoRowsOverlay} shows it.
|
|
37
|
+
*/
|
|
38
|
+
autoNoRows: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* `true` (default): while "Loading…" is shown, the table ignores mouse events on the body (click, double click,
|
|
41
|
+
* hover, context menu – the page still sees them) and the keyboard cannot start editing or toggle rows in the body;
|
|
42
|
+
* navigation, copying and the header still work.
|
|
43
|
+
* `false`: the loading overlay is only a picture, the table stays usable.
|
|
44
|
+
* "No rows" / "No matching rows" never block.
|
|
45
|
+
*/
|
|
46
|
+
blockInteractionWhileLoading: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Waits this long (ms) before the loading overlay appears. Answers that come faster show no spinner at all
|
|
49
|
+
* (no flashing); meanwhile an automatic "No rows to show" stays as it is. Default: `0` (right away).
|
|
50
|
+
*/
|
|
51
|
+
loadingDelayInMs: number;
|
|
52
|
+
/**
|
|
53
|
+
* Own content of an overlay instead of the built-in one (spinner + text). Called once each time the overlay
|
|
54
|
+
* of a kind appears; return `undefined` to keep the built-in content for that kind. The table removes the
|
|
55
|
+
* element again when the overlay disappears or changes and in {@link TableApi.destroy}.
|
|
56
|
+
*
|
|
57
|
+
* The overlay is hidden from screen readers (`aria-hidden`, the table announces its text instead):
|
|
58
|
+
* put no buttons or links into it.
|
|
59
|
+
*
|
|
60
|
+
* @param {GeOverlayKind} kind - `"loading"`, `"noRows"` or `"noMatches"`
|
|
61
|
+
* @param {string} text - the text the built-in content would show
|
|
62
|
+
* @returns {HTMLElement | undefined} the element to show, or `undefined` for the default
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* const tableOptions: TableOptionsIf = {
|
|
66
|
+
* ...new TableOptions(),
|
|
67
|
+
* overlayOptions: {
|
|
68
|
+
* getOverlayElement: (kind: GeOverlayKind, text: string) => {
|
|
69
|
+
* if (kind !== "noRows") return undefined; // built-in spinner and texts for the others
|
|
70
|
+
* const div = document.createElement("div");
|
|
71
|
+
* div.className = "my-empty-state";
|
|
72
|
+
* div.textContent = `📭 ${text}`;
|
|
73
|
+
* return div;
|
|
74
|
+
* },
|
|
75
|
+
* },
|
|
76
|
+
* };
|
|
77
|
+
*/
|
|
78
|
+
getOverlayElement?: (kind: GeOverlayKind, text: string) => HTMLElement | undefined;
|
|
79
|
+
}
|
|
@@ -11,6 +11,7 @@ import { FocusModelIf } from '../../focus/focus-model.if.js';
|
|
|
11
11
|
import { ShortcutActionIdMapping } from '../../action/shortcut-actionid-mapping.type.js';
|
|
12
12
|
import { HeaderGroupOptions } from './header-group-options.js';
|
|
13
13
|
import { AriaTextsIf } from '../../aria/aria-texts.if.js';
|
|
14
|
+
import { OverlayOptionsIf } from './overlay-options.if.js';
|
|
14
15
|
|
|
15
16
|
/**
|
|
16
17
|
* All default options of a table – see {@link TableOptionsIf} for the meaning of each field.
|
|
@@ -77,4 +78,6 @@ export declare class TableOptions implements TableOptionsIf {
|
|
|
77
78
|
ariaDescribedBy?: string;
|
|
78
79
|
/** Own screen reader texts; missing functions use the English defaults ({@link AriaTexts}). @since 1.1.91 */
|
|
79
80
|
ariaTexts?: Partial<AriaTextsIf>;
|
|
81
|
+
/** Texts and behaviour of the "Loading…" / "No rows" overlays; missing fields use {@link OverlayOptions}. @since 1.1.92 */
|
|
82
|
+
overlayOptions?: Partial<OverlayOptionsIf>;
|
|
80
83
|
}
|
|
@@ -11,6 +11,8 @@ import { FocusModelIf } from '../../focus/focus-model.if.js';
|
|
|
11
11
|
import { ShortcutActionIdMapping } from '../../action/shortcut-actionid-mapping.type.js';
|
|
12
12
|
import { HeaderGroupOptionsIf } from './header-group-options.if.js';
|
|
13
13
|
import { AriaTextsIf } from '../../aria/aria-texts.if.js';
|
|
14
|
+
import { TableStateIf } from '../../state/table-state.if.js';
|
|
15
|
+
import { OverlayOptionsIf } from './overlay-options.if.js';
|
|
14
16
|
|
|
15
17
|
/**
|
|
16
18
|
* Represents the options for configuring a table.
|
|
@@ -301,4 +303,37 @@ export interface TableOptionsIf {
|
|
|
301
303
|
* @since 1.1.91
|
|
302
304
|
*/
|
|
303
305
|
ariaTexts?: Partial<AriaTextsIf>;
|
|
306
|
+
/**
|
|
307
|
+
* Texts and behaviour of the overlays over the body: "Loading…" ({@link TableApi.showLoadingOverlay}),
|
|
308
|
+
* "No rows to show" (empty body, automatic) and "No matching rows" (the filter hides all rows).
|
|
309
|
+
* Fields you leave out keep their default ({@link OverlayOptions}).
|
|
310
|
+
*
|
|
311
|
+
* @example
|
|
312
|
+
* const tableOptions: TableOptionsIf = {
|
|
313
|
+
* ...new TableOptions(),
|
|
314
|
+
* overlayOptions: { noRowsText: "No orders yet", blockInteractionWhileLoading: false },
|
|
315
|
+
* };
|
|
316
|
+
*
|
|
317
|
+
* @since 1.1.92
|
|
318
|
+
*/
|
|
319
|
+
overlayOptions?: Partial<OverlayOptionsIf>;
|
|
320
|
+
/**
|
|
321
|
+
* The state the table starts with: column layout, sorting, tree, checked and selected rows … – e.g. loaded from
|
|
322
|
+
* your server ({@link TableApi.getState}, {@link EventListenerIf.onStateChanged}). A state stored by
|
|
323
|
+
* {@link autoRestoreOptions} wins over it, part by part.
|
|
324
|
+
*
|
|
325
|
+
* @example
|
|
326
|
+
* const saved = (await (await fetch("/api/prefs/orders")).json()) as TableStateIf | null;
|
|
327
|
+
* const tableOptions: TableOptionsIf = { ...new TableOptions(), initialState: saved ?? undefined };
|
|
328
|
+
*
|
|
329
|
+
* @since 1.1.92
|
|
330
|
+
*/
|
|
331
|
+
initialState?: Partial<TableStateIf>;
|
|
332
|
+
/**
|
|
333
|
+
* Delay in ms between the last change of the state (resize, sort, scroll …) and
|
|
334
|
+
* {@link EventListenerIf.onStateChanged} / the save of {@link autoRestoreOptions}. Default 300.
|
|
335
|
+
*
|
|
336
|
+
* @since 1.1.92
|
|
337
|
+
*/
|
|
338
|
+
stateChangedDebounceDelay?: number;
|
|
304
339
|
}
|
|
@@ -18,6 +18,13 @@ export declare class AreaModelArrayOfArrays<T> extends AbstractAreaModel<T[][]>
|
|
|
18
18
|
constructor(areaIdent: AreaIdent, arr: T[][], defaultRowHeight: number, columnDefs?: ColumnDefIf[]);
|
|
19
19
|
externalFilterChanged(predictFn: FilterFunction<any>): void;
|
|
20
20
|
getRowCount(): number;
|
|
21
|
+
/**
|
|
22
|
+
* The number of all rows, without the external filter.
|
|
23
|
+
*
|
|
24
|
+
* @returns {number} the length of the array
|
|
25
|
+
* @since 1.1.92
|
|
26
|
+
*/
|
|
27
|
+
getUnfilteredRowCount(): number;
|
|
21
28
|
getValueAt(rowIndex: number, columnIndex: number): any;
|
|
22
29
|
setValue(rowIndex: number, columnIndex: number, value: any): boolean;
|
|
23
30
|
getRowByIndex(rowIndex: number): any;
|
|
@@ -10,6 +10,7 @@ import { CheckedType } from '../../common/checked-type.js';
|
|
|
10
10
|
import { CellGroupExt } from '../cellgroup/cell-group-ext.js';
|
|
11
11
|
import { MouseTargetData } from '../../event/mouse-target-data.js';
|
|
12
12
|
import { HeaderGroupOptionsIf } from '../../options/header-group-options.if.js';
|
|
13
|
+
import { TableHeaderGroupStateIf } from '../../../state/table-state.if.js';
|
|
13
14
|
|
|
14
15
|
/** @category Header groups */
|
|
15
16
|
export declare class AreaModelCellGroups implements AreaModelIf {
|
|
@@ -56,4 +57,34 @@ export declare class AreaModelCellGroups implements AreaModelIf {
|
|
|
56
57
|
setRowChecked(_rowIndex: number, _checked: boolean): void;
|
|
57
58
|
setValue(_rowIndex: number, _columnIndex: number, _value: any): boolean;
|
|
58
59
|
toggleHeaderGroup(mouseTargetData: MouseTargetData): ColumnDefIf[];
|
|
60
|
+
/**
|
|
61
|
+
* The header groups the user can collapse (`toggle: true`, not `visibility: "always"`) with their id
|
|
62
|
+
* ({@link CellGroupIf.id}, otherwise the path of the labels, e.g. `"Customer"` or `"2026/Q1"`; a second group with
|
|
63
|
+
* the same path gets `#2`) and their state.
|
|
64
|
+
*
|
|
65
|
+
* @returns {TableHeaderGroupStateIf[]} id and `closed` per group, in header order
|
|
66
|
+
* @example
|
|
67
|
+
* const header = tableApi.getTableModel().getAreaModel("header") as AreaModelCellGroups;
|
|
68
|
+
* console.log(header.getToggleGroupStates()); // [{ id: "Customer", closed: false }]
|
|
69
|
+
* @since 1.1.92
|
|
70
|
+
*/
|
|
71
|
+
getToggleGroupStates(): TableHeaderGroupStateIf[];
|
|
72
|
+
/**
|
|
73
|
+
* Collapses or expands a header group by its id (see {@link getToggleGroupStates}) and returns the column
|
|
74
|
+
* definitions to use from now on – like a click on its toggle. {@link TableApi.setHeaderGroupCollapsed} does this
|
|
75
|
+
* and repaints.
|
|
76
|
+
*
|
|
77
|
+
* @param {string} id - the id of the group
|
|
78
|
+
* @param {boolean} closed - true = collapse
|
|
79
|
+
* @returns {ColumnDefIf[] | undefined} the merged column definitions, `undefined` if there is no such group
|
|
80
|
+
* @since 1.1.92
|
|
81
|
+
*/
|
|
82
|
+
setGroupClosed(id: string, closed: boolean): ColumnDefIf[] | undefined;
|
|
83
|
+
/** The toggleable groups by id (header order). */
|
|
84
|
+
private getToggleGroups;
|
|
85
|
+
/**
|
|
86
|
+
* Keep the existing ColumnDef objects (width, classes, renderers, sorting …) – only their visibility
|
|
87
|
+
* comes from the rebuilt groups. Fresh defs would reset every width to the default (100 px).
|
|
88
|
+
*/
|
|
89
|
+
private mergeColumnDefs;
|
|
59
90
|
}
|
|
@@ -267,6 +267,19 @@ export declare class AreaModelObjectArray<T> extends AbstractAreaModel<T> implem
|
|
|
267
267
|
* console.log(`The table has ${rowCount} rows`);
|
|
268
268
|
*/
|
|
269
269
|
getRowCount(): number;
|
|
270
|
+
/**
|
|
271
|
+
* The number of all rows, without the external filter (the filter only shrinks {@link getRowCount}).
|
|
272
|
+
*
|
|
273
|
+
* @returns {number} `getAllRows().length`
|
|
274
|
+
*
|
|
275
|
+
* @example
|
|
276
|
+
* if (bodyAreaModel.getRowCount() === 0 && bodyAreaModel.getUnfilteredRowCount() > 0) {
|
|
277
|
+
* console.log("The filter hides all rows");
|
|
278
|
+
* }
|
|
279
|
+
*
|
|
280
|
+
* @since 1.1.92
|
|
281
|
+
*/
|
|
282
|
+
getUnfilteredRowCount(): number;
|
|
270
283
|
/**
|
|
271
284
|
* Gets the value at the specified row and column indices.
|
|
272
285
|
* This method handles tree rows and nested properties.
|
|
@@ -113,6 +113,15 @@ export declare class AreaModelTree<S> extends AbstractAreaModel<TreeRow<S>> {
|
|
|
113
113
|
*/
|
|
114
114
|
getFilteredFlattenRows(): TreeRowIf<S>[];
|
|
115
115
|
getRowCount(): number;
|
|
116
|
+
/**
|
|
117
|
+
* The number of rows the tree shows without the external filter: all nodes whose parents are expanded
|
|
118
|
+
* (collapsed children do not count). `0` only for a tree without rows.
|
|
119
|
+
*
|
|
120
|
+
* @returns {number} displayed rows before filtering
|
|
121
|
+
*
|
|
122
|
+
* @since 1.1.92
|
|
123
|
+
*/
|
|
124
|
+
getUnfilteredRowCount(): number;
|
|
116
125
|
getValueAt(rowIndex: number, columnIndex: number): any;
|
|
117
126
|
getRowHeight(_rowIndex: number): number;
|
|
118
127
|
/**
|
|
@@ -261,6 +261,25 @@ export interface AreaModelIf {
|
|
|
261
261
|
* }
|
|
262
262
|
*/
|
|
263
263
|
getRowCount(): number;
|
|
264
|
+
/**
|
|
265
|
+
* The number of rows the area would show **without** the external filter. Optional: the table uses it to tell
|
|
266
|
+
* "No rows to show" (no rows at all) from "No matching rows" (the filter hides all rows) – see
|
|
267
|
+
* {@link OverlayOptionsIf}. Models without it always get "No rows to show".
|
|
268
|
+
*
|
|
269
|
+
* @returns {number} e.g. all rows of an object array; for a tree the displayed rows before filtering
|
|
270
|
+
*
|
|
271
|
+
* @example
|
|
272
|
+
* class OrdersBodyModel extends AreaModel {
|
|
273
|
+
* private all: string[][] = [];
|
|
274
|
+
* private shown: string[][] = [];
|
|
275
|
+
* override getRowCount(): number { return this.shown.length; }
|
|
276
|
+
* getUnfilteredRowCount(): number { return this.all.length; }
|
|
277
|
+
* override getValueAt(rowIndex: number, columnIndex: number): any { return this.shown[rowIndex]?.[columnIndex]; }
|
|
278
|
+
* }
|
|
279
|
+
*
|
|
280
|
+
* @since 1.1.92
|
|
281
|
+
*/
|
|
282
|
+
getUnfilteredRowCount?(): number;
|
|
264
283
|
/**
|
|
265
284
|
* Returns the value of the cell at the specified row and column indices.
|
|
266
285
|
* This is one of the most important methods in the area model, as it provides
|
|
@@ -23,6 +23,13 @@ export declare class CoverGridBodyModel<T> implements AreaModelIf {
|
|
|
23
23
|
constructor(items: T[], cellRenderer: CellRendererIf, coverWidth?: number, coverHeight?: number, width?: number, firstRowPaddingTop?: number);
|
|
24
24
|
setParentWidth(widthInPixel: number): void;
|
|
25
25
|
getRowCount(): number;
|
|
26
|
+
/**
|
|
27
|
+
* The number of grid rows without the external filter (`0` without items).
|
|
28
|
+
*
|
|
29
|
+
* @returns {number} grid rows for all items
|
|
30
|
+
* @since 1.1.92
|
|
31
|
+
*/
|
|
32
|
+
getUnfilteredRowCount(): number;
|
|
26
33
|
getColumnCount(): number;
|
|
27
34
|
getValueAt(rowIndex: number, columnIndex: number): T | undefined;
|
|
28
35
|
getTextValueAt(_rowIndex: number, _columnIndex: number): string;
|
|
@@ -9,5 +9,7 @@ export declare class CellGroup implements CellGroupIf {
|
|
|
9
9
|
visibility: "always" | "inverted" | "normal" | undefined;
|
|
10
10
|
children: CellGroupIf[] | undefined;
|
|
11
11
|
impl: string;
|
|
12
|
+
/** See {@link CellGroupIf.id}. @since 1.1.92 */
|
|
13
|
+
id?: string;
|
|
12
14
|
constructor(data: any, property?: string | undefined, toggle?: boolean | undefined, closed?: boolean, visibility?: "always" | "inverted" | "normal" | undefined, children?: CellGroupIf[] | undefined);
|
|
13
15
|
}
|
|
@@ -17,6 +17,12 @@
|
|
|
17
17
|
* @category Header groups
|
|
18
18
|
*/
|
|
19
19
|
export interface CellGroupIf {
|
|
20
|
+
/**
|
|
21
|
+
* A stable id of the group, used to remember whether it is collapsed ({@link TableHeaderGroupStateIf},
|
|
22
|
+
* {@link TableApi.setHeaderGroupCollapsed}). Default: the path of the labels, e.g. `"Customer"` or `"2026/Q1"`.
|
|
23
|
+
* @since 1.1.92
|
|
24
|
+
*/
|
|
25
|
+
id?: string;
|
|
20
26
|
/** The label of the group or column. */
|
|
21
27
|
data: any;
|
|
22
28
|
/** Set on leaves only: the property shown in this column. */
|
|
@@ -4,3 +4,8 @@ import { ColumnDefIf } from './column-def.if.js';
|
|
|
4
4
|
export declare function setApiColumnVisibility(columnDef: ColumnDefIf, visible: boolean): void;
|
|
5
5
|
/** Sets the header group visibility of a column and rebuilds its `isVisible`. */
|
|
6
6
|
export declare function setGroupColumnVisibility(columnDef: ColumnDefIf, isVisible: (() => boolean) | undefined): void;
|
|
7
|
+
/**
|
|
8
|
+
* Whether the column is shown apart from a collapsed header group: hidden with `setColumnVisible(…, false)` or by its
|
|
9
|
+
* own `isVisible` (e.g. `FalseFn` in the code) → false.
|
|
10
|
+
*/
|
|
11
|
+
export declare function isApiColumnVisible(columnDef: ColumnDefIf): boolean;
|