igniteui-grid-lite 0.9.0 → 0.10.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/components/cell.d.ts +8 -0
- package/components/cell.js +12 -1
- package/components/cell.js.map +1 -1
- package/components/column.d.ts +2 -2
- package/components/column.js.map +1 -1
- package/components/filter-row.d.ts +7 -2
- package/components/filter-row.js +87 -52
- package/components/filter-row.js.map +1 -1
- package/components/grid.d.ts +49 -3
- package/components/grid.js +102 -62
- package/components/grid.js.map +1 -1
- package/components/header-row.d.ts +1 -2
- package/components/header-row.js +4 -7
- package/components/header-row.js.map +1 -1
- package/components/header.d.ts +9 -0
- package/components/header.js +36 -23
- package/components/header.js.map +1 -1
- package/components/row.d.ts +4 -1
- package/components/row.js +12 -1
- package/components/row.js.map +1 -1
- package/components/virtualizer.d.ts +3 -1
- package/components/virtualizer.js +36 -7
- package/components/virtualizer.js.map +1 -1
- package/controllers/data-operation.d.ts +0 -4
- package/controllers/data-operation.js +7 -22
- package/controllers/data-operation.js.map +1 -1
- package/controllers/dom.d.ts +28 -9
- package/controllers/dom.js +70 -20
- package/controllers/dom.js.map +1 -1
- package/controllers/filter.d.ts +20 -4
- package/controllers/filter.js +39 -55
- package/controllers/filter.js.map +1 -1
- package/controllers/navigation.d.ts +10 -10
- package/controllers/navigation.js +68 -53
- package/controllers/navigation.js.map +1 -1
- package/controllers/resize.d.ts +8 -8
- package/controllers/resize.js +23 -14
- package/controllers/resize.js.map +1 -1
- package/controllers/sort.d.ts +12 -3
- package/controllers/sort.js +25 -32
- package/controllers/sort.js.map +1 -1
- package/controllers/state.d.ts +28 -18
- package/controllers/state.js +20 -26
- package/controllers/state.js.map +1 -1
- package/custom-elements.json +874 -243
- package/docs/igniteui-grid-lite.json +1339 -818
- package/index.d.ts +1 -1
- package/index.js.map +1 -1
- package/internal/a11y.d.ts +29 -0
- package/internal/a11y.js +24 -0
- package/internal/a11y.js.map +1 -0
- package/internal/constants.d.ts +3 -2
- package/internal/constants.js +1 -4
- package/internal/constants.js.map +1 -1
- package/internal/normalize-case.d.ts +5 -1
- package/internal/normalize-case.js +2 -1
- package/internal/normalize-case.js.map +1 -1
- package/internal/part-map.js +9 -17
- package/internal/part-map.js.map +1 -1
- package/internal/tags.d.ts +2 -2
- package/internal/tags.js +2 -2
- package/internal/tags.js.map +1 -1
- package/internal/types.d.ts +13 -1
- package/internal/types.js.map +1 -1
- package/internal/utils.d.ts +3 -0
- package/internal/utils.js +17 -4
- package/internal/utils.js.map +1 -1
- package/internal/watch.js +8 -9
- package/internal/watch.js.map +1 -1
- package/operations/base.js +2 -1
- package/operations/base.js.map +1 -1
- package/operations/filter/state.js +2 -5
- package/operations/filter/state.js.map +1 -1
- package/operations/filter/tree.d.ts +1 -2
- package/operations/filter/tree.js +2 -7
- package/operations/filter/tree.js.map +1 -1
- package/operations/filter.js +13 -1
- package/operations/filter.js.map +1 -1
- package/operations/sort.d.ts +0 -1
- package/operations/sort.js +7 -9
- package/operations/sort.js.map +1 -1
- package/package.json +2 -2
- package/styles/themes/grid.base.css.js +1 -1
- package/styles/themes/grid.base.css.js.map +1 -1
- package/styles/themes/shared/grid.common.css.js +1 -1
- package/styles/themes/shared/grid.common.css.js.map +1 -1
package/controllers/dom.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dom.js","sourceRoot":"","sources":["../../src/controllers/dom.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"dom.js","sourceRoot":"","sources":["../../src/controllers/dom.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ReactiveController } from 'lit';\nimport type { StyleInfo } from 'lit/directives/style-map.js';\nimport type IgcFilterRow from '../components/filter-row.js';\nimport type IgcGridLiteHeaderRow from '../components/header-row.js';\nimport type IgcGridLiteRow from '../components/row.js';\nimport type IgcVirtualizer from '../components/virtualizer.js';\nimport { registerGridIcons } from '../internal/icon-registry.js';\nimport {\n GRID_FILTER_ROW_TAG,\n GRID_HEADER_ROW_TAG,\n GRID_ROW_TAG,\n GRID_VIRTUALIZER_TAG,\n} from '../internal/tags.js';\nimport type { ColumnConfiguration, GridHost } from '../internal/types.js';\nimport { applyColumnWidths } from '../internal/utils.js';\n\nconst SCROLLBAR_OFFSET_VAR = '--scrollbar-offset';\nconst VISIBILITY_CHANGED = 'visibilityChanged';\n\n/**\n * Owns the DOM concerns of the grid: element queries into the render root, the\n * derived column track sizes, and the scrollbar offset measurement.\n */\nclass GridDOMController<T extends object> implements ReactiveController {\n protected readonly _host: GridHost<T>;\n\n /** The virtualizer currently being tracked for scrollbar changes. */\n #observed?: IgcVirtualizer;\n #resizeObserver?: ResizeObserver;\n\n /** Last written offset in pixels. -1 means not measured yet. */\n #scrollOffset = -1;\n #pendingFrame?: number;\n\n /** The column configuration `columnSizes` was derived from. */\n #columns?: ColumnConfiguration<T>[];\n\n #onScrollbarChange = (): void => {\n if (this.#pendingFrame !== undefined) {\n return;\n }\n\n this.#pendingFrame = requestAnimationFrame(() => {\n this.#pendingFrame = undefined;\n this.#applyScrollOffset();\n });\n };\n\n constructor(host: GridHost<T>) {\n this._host = host;\n this._host.addController(this);\n }\n\n public columnSizes: StyleInfo = {};\n\n /** Returns the header row element of the grid. */\n public get headerRow(): IgcGridLiteHeaderRow<T> | null {\n return this._host.renderRoot.querySelector<IgcGridLiteHeaderRow<T>>(GRID_HEADER_ROW_TAG);\n }\n\n /** Returns the filter row element of the grid. */\n public get filterRow(): IgcFilterRow<T> | null {\n return this._host.renderRoot.querySelector<IgcFilterRow<T>>(GRID_FILTER_ROW_TAG);\n }\n\n /** Returns the data row elements of the grid. */\n public get rows(): IgcGridLiteRow<T>[] {\n return Array.from(this._host.renderRoot.querySelectorAll<IgcGridLiteRow<T>>(GRID_ROW_TAG));\n }\n\n /** Returns the virtualizer element of the grid. */\n public get virtualizer(): IgcVirtualizer | null {\n return this._host.renderRoot.querySelector(GRID_VIRTUALIZER_TAG);\n }\n\n public hostConnected(): void {\n registerGridIcons();\n\n // The virtualizer is part of the host template. Observe it after the first render.\n this._host.updateComplete.then(() => {\n this.#observeVirtualizer();\n });\n }\n\n public hostDisconnected(): void {\n if (this.#pendingFrame !== undefined) {\n cancelAnimationFrame(this.#pendingFrame);\n this.#pendingFrame = undefined;\n }\n\n this.#resizeObserver?.disconnect();\n this.#resizeObserver = undefined;\n\n this.#observed?.removeEventListener(VISIBILITY_CHANGED, this.#onScrollbarChange);\n this.#observed = undefined;\n }\n\n /**\n * Watches the virtualizer for changes that can toggle its scrollbar: a new\n * visible range, or a content box resize (the scrollbar itself shrinks the\n * content box). Measurement here prevents a forced layout on each host update.\n */\n #observeVirtualizer(): void {\n const virtualizer = this.virtualizer;\n\n if (!virtualizer || virtualizer === this.#observed) {\n return;\n }\n\n this.#observed = virtualizer;\n virtualizer.addEventListener(VISIBILITY_CHANGED, this.#onScrollbarChange);\n\n this.#resizeObserver = new ResizeObserver(this.#onScrollbarChange);\n this.#resizeObserver.observe(virtualizer);\n }\n\n /** Writes the scrollbar offset CSS variable only when the measurement changed. */\n #applyScrollOffset(): void {\n const virtualizer = this.#observed;\n const offset = virtualizer ? virtualizer.offsetWidth - virtualizer.clientWidth : 0;\n\n if (offset === this.#scrollOffset) {\n return;\n }\n\n this.#scrollOffset = offset;\n this._host.style.setProperty(SCROLLBAR_OFFSET_VAR, `${offset}px`);\n }\n\n /** Scrolls the data area back to the top. */\n public resetScrollPosition(): void {\n this.virtualizer?.scrollTo({ top: 0 });\n }\n\n /**\n * Re-derives the column track sizes. Column configurations are immutable: an\n * unchanged array identity means the current sizes are still correct.\n */\n public setColumns(columns: ColumnConfiguration<T>[]): void {\n if (columns === this.#columns) {\n return;\n }\n\n this.#columns = columns;\n this.columnSizes = applyColumnWidths(columns);\n }\n}\n\nfunction createDomController<T extends object>(host: GridHost<T>): GridDOMController<T> {\n return new GridDOMController<T>(host);\n}\n\nexport type { GridDOMController };\nexport { createDomController };\n"]}
|
package/controllers/filter.d.ts
CHANGED
|
@@ -3,27 +3,43 @@ import type IgcFilterRow from '../components/filter-row.js';
|
|
|
3
3
|
import type { ColumnConfiguration, Keys } from '../internal/types.js';
|
|
4
4
|
import { FilterState } from '../operations/filter/state.js';
|
|
5
5
|
import type { FilterExpression } from '../operations/filter/types.js';
|
|
6
|
+
import type { GridDOMController } from './dom.js';
|
|
6
7
|
import type { StateController } from './state.js';
|
|
8
|
+
/** The kind of modification a `filtering` event describes. */
|
|
9
|
+
export type FilterEventType = 'add' | 'modify' | 'remove';
|
|
7
10
|
export declare class FilterController<T extends object> implements ReactiveController {
|
|
8
11
|
#private;
|
|
9
12
|
private readonly _stateController;
|
|
10
|
-
|
|
13
|
+
private readonly _dom;
|
|
14
|
+
constructor(state: StateController<T>, dom: GridDOMController<T>);
|
|
11
15
|
state: FilterState<T>;
|
|
12
16
|
get host(): import("../internal/types.js").GridHost<T>;
|
|
13
17
|
get filterRow(): IgcFilterRow<T> | null;
|
|
14
18
|
hostConnected(): void;
|
|
15
|
-
hostUpdate(): void;
|
|
16
19
|
get(key: Keys<T>): import("../operations/filter/tree.js").FilterExpressionTree<T> | undefined;
|
|
17
20
|
reset(key?: Keys<T>): void;
|
|
18
21
|
setActiveColumn(column?: ColumnConfiguration<T>): void;
|
|
19
22
|
getDefaultExpression(column: ColumnConfiguration<T>): FilterExpression<T>;
|
|
20
23
|
removeAllExpressions(key: Keys<T>): Promise<void>;
|
|
21
24
|
removeExpression(expression: FilterExpression<T>): Promise<void>;
|
|
22
|
-
|
|
25
|
+
/**
|
|
26
|
+
* Emits `filtering` for `expression` and, if it passes, applies it.
|
|
27
|
+
*
|
|
28
|
+
* @remarks
|
|
29
|
+
* `target` is the stored expression the change applies to. Callers pass a
|
|
30
|
+
* candidate copy as `expression`, so a canceled event does not touch the stored
|
|
31
|
+
* state. On commit the candidate is merged back into `target`. This keeps the
|
|
32
|
+
* object identity that the expression tree and the chip selection use.
|
|
33
|
+
*/
|
|
34
|
+
filterWithEvent(expression: FilterExpression<T>, type: FilterEventType, target?: FilterExpression<T>): Promise<void>;
|
|
23
35
|
filter(expression: FilterExpression<T> | FilterExpression<T>[]): void;
|
|
24
36
|
/**
|
|
25
|
-
* Stores expressions
|
|
37
|
+
* Stores expressions in the filter state without requiring column configuration.
|
|
26
38
|
* Used when setting initial filter expressions before columns are available.
|
|
39
|
+
*
|
|
40
|
+
* @remarks
|
|
41
|
+
* Copies are stored. `resolveConditions` later rewrites each stored expression,
|
|
42
|
+
* and those writes must not reach the caller's objects.
|
|
27
43
|
*/
|
|
28
44
|
setRaw(expressions: FilterExpression<T>[]): void;
|
|
29
45
|
/**
|
package/controllers/filter.js
CHANGED
|
@@ -1,28 +1,22 @@
|
|
|
1
1
|
import { PIPELINE } from '../internal/constants.js';
|
|
2
|
-
import { asArray, getFilterOperandsFor, isString } from '../internal/utils.js';
|
|
2
|
+
import { asArray, getFilterOperandsFor, isString, resolveCondition } from '../internal/utils.js';
|
|
3
3
|
import { FilterState } from '../operations/filter/state.js';
|
|
4
4
|
export class FilterController {
|
|
5
|
-
constructor(state) {
|
|
5
|
+
constructor(state, dom) {
|
|
6
6
|
this.state = new FilterState();
|
|
7
7
|
this._stateController = state;
|
|
8
|
+
this._dom = dom;
|
|
8
9
|
this._stateController.host.addController(this);
|
|
9
10
|
}
|
|
10
11
|
get host() {
|
|
11
12
|
return this._stateController.host;
|
|
12
13
|
}
|
|
13
14
|
get filterRow() {
|
|
14
|
-
return this.
|
|
15
|
+
return this._dom.filterRow;
|
|
15
16
|
}
|
|
16
|
-
|
|
17
|
-
return this._stateController.virtualizer;
|
|
18
|
-
}
|
|
19
|
-
#emitFilteringEvent(expression, type) {
|
|
17
|
+
#emitFilteringEvent(key, expressions, type) {
|
|
20
18
|
return this.host.emitEvent('filtering', {
|
|
21
|
-
detail: {
|
|
22
|
-
key: expression.key,
|
|
23
|
-
expressions: [expression],
|
|
24
|
-
type,
|
|
25
|
-
},
|
|
19
|
+
detail: { key, expressions, type },
|
|
26
20
|
cancelable: true,
|
|
27
21
|
});
|
|
28
22
|
}
|
|
@@ -33,80 +27,70 @@ export class FilterController {
|
|
|
33
27
|
for (const expr of asArray(expression)) {
|
|
34
28
|
this.state.set(expr);
|
|
35
29
|
}
|
|
36
|
-
this
|
|
30
|
+
this._dom.resetScrollPosition();
|
|
31
|
+
this._stateController.updateObservers();
|
|
37
32
|
this.host.requestUpdate(PIPELINE);
|
|
38
33
|
}
|
|
39
34
|
hostConnected() { }
|
|
40
|
-
hostUpdate() {
|
|
41
|
-
this.filterRow?.requestUpdate();
|
|
42
|
-
}
|
|
43
35
|
get(key) {
|
|
44
36
|
return this.state.get(key);
|
|
45
37
|
}
|
|
46
38
|
reset(key) {
|
|
47
|
-
key ? this.state.delete(key) : this.state.clear();
|
|
39
|
+
key !== undefined ? this.state.delete(key) : this.state.clear();
|
|
40
|
+
this._stateController.updateObservers();
|
|
48
41
|
}
|
|
49
42
|
setActiveColumn(column) {
|
|
50
43
|
if (column?.filterable && this.filterRow?.active) {
|
|
51
44
|
this.filterRow.column = column;
|
|
52
45
|
this.filterRow.expression = this.getDefaultExpression(column);
|
|
53
|
-
this.
|
|
46
|
+
this._stateController.updateObservers();
|
|
54
47
|
}
|
|
55
48
|
}
|
|
56
49
|
getDefaultExpression(column) {
|
|
57
|
-
const caseSensitive = Boolean(column.filteringCaseSensitive);
|
|
58
|
-
const operands = getFilterOperandsFor(column);
|
|
59
|
-
const keys = Object.keys(operands);
|
|
60
50
|
return {
|
|
61
51
|
key: column.field,
|
|
62
|
-
condition:
|
|
63
|
-
caseSensitive,
|
|
52
|
+
condition: Object.values(getFilterOperandsFor(column))[0],
|
|
53
|
+
caseSensitive: Boolean(column.filteringCaseSensitive),
|
|
64
54
|
};
|
|
65
55
|
}
|
|
66
|
-
async
|
|
67
|
-
|
|
68
|
-
if (!this.host.emitEvent('filtering', {
|
|
69
|
-
detail: {
|
|
70
|
-
key,
|
|
71
|
-
expressions: state,
|
|
72
|
-
type: 'remove',
|
|
73
|
-
},
|
|
74
|
-
cancelable: true,
|
|
75
|
-
})) {
|
|
56
|
+
async #applyWithEvents(key, expressions, type, commit) {
|
|
57
|
+
if (!this.#emitFilteringEvent(key, expressions, type)) {
|
|
76
58
|
return;
|
|
77
59
|
}
|
|
78
|
-
|
|
79
|
-
this
|
|
80
|
-
await this.host.updateComplete;
|
|
60
|
+
commit();
|
|
61
|
+
await this.host._pipelineComplete;
|
|
81
62
|
this.#emitFilteredEvent({ key, state: this.get(key)?.all ?? [] });
|
|
82
63
|
}
|
|
64
|
+
async removeAllExpressions(key) {
|
|
65
|
+
await this.#applyWithEvents(key, this.get(key)?.all ?? [], 'remove', () => {
|
|
66
|
+
this.reset(key);
|
|
67
|
+
this.#filter([]);
|
|
68
|
+
});
|
|
69
|
+
}
|
|
83
70
|
async removeExpression(expression) {
|
|
84
71
|
const state = this.get(expression.key);
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
this
|
|
91
|
-
}
|
|
92
|
-
this.#filter([]);
|
|
93
|
-
await this.host.updateComplete;
|
|
94
|
-
this.#emitFilteredEvent({ key: expression.key, state: state?.all ?? [] });
|
|
72
|
+
await this.#applyWithEvents(expression.key, [expression], 'remove', () => {
|
|
73
|
+
state?.remove(expression);
|
|
74
|
+
if (state?.empty) {
|
|
75
|
+
this.reset(state.key);
|
|
76
|
+
}
|
|
77
|
+
this.#filter([]);
|
|
78
|
+
});
|
|
95
79
|
}
|
|
96
|
-
async filterWithEvent(expression, type) {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
80
|
+
async filterWithEvent(expression, type, target = expression) {
|
|
81
|
+
await this.#applyWithEvents(expression.key, [expression], type, () => {
|
|
82
|
+
if (target !== expression) {
|
|
83
|
+
Object.assign(target, expression);
|
|
84
|
+
}
|
|
85
|
+
this.#filter(target);
|
|
86
|
+
});
|
|
103
87
|
}
|
|
104
88
|
filter(expression) {
|
|
105
89
|
this.#filter(asArray(expression).map((expr) => Object.assign(this.getDefaultExpression(this.host.getColumn(expr.key)), expr)));
|
|
106
90
|
}
|
|
107
91
|
setRaw(expressions) {
|
|
108
92
|
for (const expr of expressions) {
|
|
109
|
-
this.state.set(expr);
|
|
93
|
+
this.state.set({ ...expr });
|
|
110
94
|
}
|
|
111
95
|
}
|
|
112
96
|
resolveConditions() {
|
|
@@ -117,7 +101,7 @@ export class FilterController {
|
|
|
117
101
|
const defaults = this.getDefaultExpression(column);
|
|
118
102
|
for (const expr of tree.all) {
|
|
119
103
|
if (isString(expr.condition)) {
|
|
120
|
-
expr.condition =
|
|
104
|
+
expr.condition = resolveCondition(column, expr.condition);
|
|
121
105
|
}
|
|
122
106
|
if (expr.caseSensitive === undefined) {
|
|
123
107
|
expr.caseSensitive = defaults.caseSensitive;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filter.js","sourceRoot":"","sources":["../../src/controllers/filter.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ReactiveController } from 'lit';\nimport type IgcFilterRow from '../components/filter-row.js';\nimport type { IgcFilteredEvent } from '../components/grid.js';\nimport { PIPELINE } from '../internal/constants.js';\nimport type { ColumnConfiguration, Keys } from '../internal/types.js';\nimport { asArray, getFilterOperandsFor, isString } from '../internal/utils.js';\nimport { FilterState } from '../operations/filter/state.js';\nimport type { FilterExpression } from '../operations/filter/types.js';\nimport type { StateController } from './state.js';\n\nexport class FilterController<T extends object> implements ReactiveController {\n private readonly _stateController: StateController<T>;\n\n constructor(state: StateController<T>) {\n this._stateController = state;\n this._stateController.host.addController(this);\n }\n\n public state: FilterState<T> = new FilterState();\n\n public get host() {\n return this._stateController.host;\n }\n\n public get filterRow(): IgcFilterRow<T> | null {\n return this._stateController.filterRow;\n }\n\n get #virtualizer() {\n return this._stateController.virtualizer;\n }\n\n #emitFilteringEvent(expression: FilterExpression<T>, type: 'add' | 'modify' | 'remove') {\n return this.host.emitEvent('filtering', {\n detail: {\n key: expression.key,\n expressions: [expression],\n type,\n },\n cancelable: true,\n });\n }\n\n #emitFilteredEvent(detail?: IgcFilteredEvent<T>) {\n return this.host.emitEvent('filtered', { detail });\n }\n\n #filter(expression: FilterExpression<T> | FilterExpression<T>[]) {\n for (const expr of asArray(expression)) {\n this.state.set(expr);\n }\n\n // HACK: In the case where the scrollTop is a large and amount and a big chunk of data is filtered out\n // HACK: the virtualizer can't recalculate its scroll position correctly. Thus, we reset the scrollTop state.\n this.#virtualizer?.scrollTo({ top: 0 });\n this.host.requestUpdate(PIPELINE);\n }\n\n public hostConnected() {}\n\n public hostUpdate(): void {\n this.filterRow?.requestUpdate();\n }\n\n public get(key: Keys<T>) {\n return this.state.get(key);\n }\n\n public reset(key?: Keys<T>) {\n key ? this.state.delete(key) : this.state.clear();\n }\n\n public setActiveColumn(column?: ColumnConfiguration<T>) {\n if (column?.filterable && this.filterRow?.active) {\n this.filterRow.column = column;\n this.filterRow.expression = this.getDefaultExpression(column);\n this.host.requestUpdate();\n }\n }\n\n public getDefaultExpression(column: ColumnConfiguration<T>) {\n const caseSensitive = Boolean(column.filteringCaseSensitive);\n const operands = getFilterOperandsFor(column);\n const keys = Object.keys(operands) as (keyof typeof operands)[];\n\n // XXX: Types\n return {\n key: column.field,\n condition: operands[keys[0]],\n caseSensitive,\n } as unknown as FilterExpression<T>;\n }\n\n public async removeAllExpressions(key: Keys<T>) {\n const state = this.get(key)?.all ?? [];\n\n if (\n !this.host.emitEvent('filtering', {\n detail: {\n key,\n expressions: state,\n type: 'remove',\n },\n cancelable: true,\n })\n ) {\n return;\n }\n\n this.reset(key);\n this.#filter([]);\n\n await this.host.updateComplete;\n this.#emitFilteredEvent({ key, state: this.get(key)?.all ?? [] });\n }\n\n public async removeExpression(expression: FilterExpression<T>) {\n const state = this.get(expression.key);\n\n if (!this.#emitFilteringEvent(expression, 'remove')) {\n return;\n }\n\n state?.remove(expression);\n\n if (state?.empty) {\n this.reset(state.key);\n }\n\n this.#filter([]);\n\n await this.host.updateComplete;\n this.#emitFilteredEvent({ key: expression.key, state: state?.all ?? [] });\n }\n\n public async filterWithEvent(expression: FilterExpression<T>, type: 'add' | 'modify' | 'remove') {\n if (!this.#emitFilteringEvent(expression, type)) {\n return;\n }\n\n this.#filter(expression);\n\n await this.host.updateComplete;\n this.#emitFilteredEvent({ key: expression.key, state: this.get(expression.key)?.all ?? [] });\n }\n\n public filter(expression: FilterExpression<T> | FilterExpression<T>[]) {\n this.#filter(\n asArray(expression).map((expr) =>\n Object.assign(this.getDefaultExpression(this.host.getColumn(expr.key)!), expr)\n )\n );\n }\n\n /**\n * Stores expressions directly in the filter state without requiring column configuration.\n * Used when setting initial filter expressions before columns are available.\n */\n public setRaw(expressions: FilterExpression<T>[]) {\n for (const expr of expressions) {\n this.state.set(expr);\n }\n }\n\n /**\n * Resolves any string conditions in the current filter state using available column configuration.\n * Called after columns become available to finalize deferred expressions.\n */\n public resolveConditions() {\n for (const tree of this.state.values) {\n const column = this.host.getColumn(tree.key);\n if (!column) continue;\n const defaults = this.getDefaultExpression(column);\n for (const expr of tree.all) {\n if (isString(expr.condition)) {\n (expr as any).condition = (getFilterOperandsFor(column) as any)[expr.condition as string];\n }\n if (expr.caseSensitive === undefined) {\n expr.caseSensitive = defaults.caseSensitive;\n }\n }\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"filter.js","sourceRoot":"","sources":["../../src/controllers/filter.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ReactiveController } from 'lit';\nimport type IgcFilterRow from '../components/filter-row.js';\nimport type { IgcFilteredEvent } from '../components/grid.js';\nimport { PIPELINE } from '../internal/constants.js';\nimport type { ColumnConfiguration, Keys } from '../internal/types.js';\nimport { asArray, getFilterOperandsFor, isString, resolveCondition } from '../internal/utils.js';\nimport { FilterState } from '../operations/filter/state.js';\nimport type { FilterExpression } from '../operations/filter/types.js';\nimport type { GridDOMController } from './dom.js';\nimport type { StateController } from './state.js';\n\n/** The kind of modification a `filtering` event describes. */\nexport type FilterEventType = 'add' | 'modify' | 'remove';\n\nexport class FilterController<T extends object> implements ReactiveController {\n private readonly _stateController: StateController<T>;\n private readonly _dom: GridDOMController<T>;\n\n constructor(state: StateController<T>, dom: GridDOMController<T>) {\n this._stateController = state;\n this._dom = dom;\n this._stateController.host.addController(this);\n }\n\n public state: FilterState<T> = new FilterState();\n\n public get host() {\n return this._stateController.host;\n }\n\n public get filterRow(): IgcFilterRow<T> | null {\n return this._dom.filterRow;\n }\n\n #emitFilteringEvent(key: Keys<T>, expressions: FilterExpression<T>[], type: FilterEventType) {\n return this.host.emitEvent('filtering', {\n detail: { key, expressions, type },\n cancelable: true,\n });\n }\n\n #emitFilteredEvent(detail?: IgcFilteredEvent<T>) {\n return this.host.emitEvent('filtered', { detail });\n }\n\n #filter(expression: FilterExpression<T> | FilterExpression<T>[]) {\n for (const expr of asArray(expression)) {\n this.state.set(expr);\n }\n\n // HACK: In the case where the scrollTop is a large and amount and a big chunk of data is filtered out\n // HACK: the virtualizer can't recalculate its scroll position correctly. Thus, we reset the scrollTop state.\n this._dom.resetScrollPosition();\n this._stateController.updateObservers();\n this.host.requestUpdate(PIPELINE);\n }\n\n public hostConnected() {}\n\n public get(key: Keys<T>) {\n return this.state.get(key);\n }\n\n public reset(key?: Keys<T>) {\n key !== undefined ? this.state.delete(key) : this.state.clear();\n\n // The filter row renders its chips from this state.\n this._stateController.updateObservers();\n }\n\n public setActiveColumn(column?: ColumnConfiguration<T>) {\n if (column?.filterable && this.filterRow?.active) {\n this.filterRow.column = column;\n this.filterRow.expression = this.getDefaultExpression(column);\n\n // The header row marks the filtered column.\n this._stateController.updateObservers();\n }\n }\n\n public getDefaultExpression(column: ColumnConfiguration<T>) {\n // XXX: Types\n return {\n key: column.field,\n condition: Object.values(getFilterOperandsFor(column))[0],\n caseSensitive: Boolean(column.filteringCaseSensitive),\n } as unknown as FilterExpression<T>;\n }\n\n /**\n * Emits `filtering` and, if it passes, runs `commit`, waits for the pipeline\n * and emits `filtered` with the resulting state of the column.\n */\n async #applyWithEvents(\n key: Keys<T>,\n expressions: FilterExpression<T>[],\n type: FilterEventType,\n commit: () => void\n ) {\n if (!this.#emitFilteringEvent(key, expressions, type)) {\n return;\n }\n\n commit();\n\n await this.host._pipelineComplete;\n this.#emitFilteredEvent({ key, state: this.get(key)?.all ?? [] });\n }\n\n public async removeAllExpressions(key: Keys<T>) {\n await this.#applyWithEvents(key, this.get(key)?.all ?? [], 'remove', () => {\n this.reset(key);\n this.#filter([]);\n });\n }\n\n public async removeExpression(expression: FilterExpression<T>) {\n const state = this.get(expression.key);\n\n await this.#applyWithEvents(expression.key, [expression], 'remove', () => {\n state?.remove(expression);\n\n if (state?.empty) {\n this.reset(state.key);\n }\n\n this.#filter([]);\n });\n }\n\n /**\n * Emits `filtering` for `expression` and, if it passes, applies it.\n *\n * @remarks\n * `target` is the stored expression the change applies to. Callers pass a\n * candidate copy as `expression`, so a canceled event does not touch the stored\n * state. On commit the candidate is merged back into `target`. This keeps the\n * object identity that the expression tree and the chip selection use.\n */\n public async filterWithEvent(\n expression: FilterExpression<T>,\n type: FilterEventType,\n target: FilterExpression<T> = expression\n ) {\n await this.#applyWithEvents(expression.key, [expression], type, () => {\n if (target !== expression) {\n Object.assign(target, expression);\n }\n\n this.#filter(target);\n });\n }\n\n public filter(expression: FilterExpression<T> | FilterExpression<T>[]) {\n this.#filter(\n asArray(expression).map((expr) =>\n Object.assign(this.getDefaultExpression(this.host.getColumn(expr.key)!), expr)\n )\n );\n }\n\n /**\n * Stores expressions in the filter state without requiring column configuration.\n * Used when setting initial filter expressions before columns are available.\n *\n * @remarks\n * Copies are stored. `resolveConditions` later rewrites each stored expression,\n * and those writes must not reach the caller's objects.\n */\n public setRaw(expressions: FilterExpression<T>[]) {\n for (const expr of expressions) {\n this.state.set({ ...expr });\n }\n }\n\n /**\n * Resolves any string conditions in the current filter state using available column configuration.\n * Called after columns become available to finalize deferred expressions.\n */\n public resolveConditions() {\n for (const tree of this.state.values) {\n const column = this.host.getColumn(tree.key);\n if (!column) continue;\n const defaults = this.getDefaultExpression(column);\n for (const expr of tree.all) {\n if (isString(expr.condition)) {\n (expr as any).condition = resolveCondition(column, expr.condition);\n }\n if (expr.caseSensitive === undefined) {\n expr.caseSensitive = defaults.caseSensitive;\n }\n }\n }\n }\n}\n"]}
|
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
import type { ReactiveController } from 'lit';
|
|
2
|
-
import type
|
|
3
|
-
import type {
|
|
2
|
+
import type { ActiveNode, NavigateToOptions } from '../internal/types.js';
|
|
3
|
+
import type { GridDOMController } from './dom.js';
|
|
4
4
|
import type { StateController } from './state.js';
|
|
5
5
|
export declare class NavigationController<T extends object> implements ReactiveController {
|
|
6
|
+
#private;
|
|
6
7
|
protected _state: StateController<T>;
|
|
8
|
+
protected _dom: GridDOMController<T>;
|
|
7
9
|
protected handlers: Map<string, (() => void) | (() => void) | (() => void) | (() => void) | (() => void) | (() => void)>;
|
|
8
10
|
protected get _virtualizer(): import("../components/virtualizer.js").default | null;
|
|
9
|
-
protected
|
|
10
|
-
protected _active: Readonly<ActiveNode<any>>;
|
|
11
|
+
protected _active: ActiveNode<T>;
|
|
11
12
|
protected get nextNode(): ActiveNode<T>;
|
|
13
|
+
/** Rows render only the visible columns, so navigation walks the same sequence. */
|
|
12
14
|
protected get _columns(): import("../index.js").ColumnConfiguration<T>[];
|
|
13
|
-
protected get _firstColumn():
|
|
14
|
-
protected
|
|
15
|
-
protected getNextColumn(key: Keys<T>): Exclude<keyof T & string, keyof T> | (Keys<T> & string) | (Keys<T> & number) | (Keys<T> & symbol) | (Keys<T> & `${string}.${string}`) | (Keys<T> & `${string}.${string}.${string}`);
|
|
16
|
-
protected queryRowByIndex(index: number): IgcGridLiteRow<T>;
|
|
15
|
+
protected get _firstColumn(): import("../index.js").Keys<any>;
|
|
16
|
+
protected queryRowByIndex(index: number): import("../components/row.js").default<T> | undefined;
|
|
17
17
|
protected scrollToCell(node: ActiveNode<T>): void;
|
|
18
18
|
get active(): ActiveNode<T>;
|
|
19
19
|
set active(node: ActiveNode<T>);
|
|
20
|
-
constructor(_state: StateController<T>);
|
|
20
|
+
constructor(_state: StateController<T>, _dom: GridDOMController<T>);
|
|
21
21
|
protected home(): void;
|
|
22
22
|
protected end(): void;
|
|
23
23
|
protected arrowDown(): void;
|
|
@@ -26,5 +26,5 @@ export declare class NavigationController<T extends object> implements ReactiveC
|
|
|
26
26
|
protected arrowRight(): void;
|
|
27
27
|
hostDisconnected(): void;
|
|
28
28
|
navigate(event: KeyboardEvent): void;
|
|
29
|
-
navigateTo(row: number,
|
|
29
|
+
navigateTo(row: number, options?: NavigateToOptions<T>): Promise<void>;
|
|
30
30
|
}
|
|
@@ -1,50 +1,60 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { GRID_ROW_TAG } from '../internal/tags.js';
|
|
1
|
+
import { SENTINEL_NODE } from '../internal/constants.js';
|
|
3
2
|
export class NavigationController {
|
|
4
3
|
get _virtualizer() {
|
|
5
|
-
return this.
|
|
4
|
+
return this._dom.virtualizer;
|
|
6
5
|
}
|
|
7
6
|
get nextNode() {
|
|
8
|
-
|
|
9
|
-
return node === SENTINEL_NODE
|
|
7
|
+
return this._active === SENTINEL_NODE
|
|
10
8
|
? { column: this._firstColumn, row: 0 }
|
|
11
|
-
: { ...
|
|
9
|
+
: { ...this._active };
|
|
12
10
|
}
|
|
13
11
|
get _columns() {
|
|
14
|
-
return this._state.columns;
|
|
12
|
+
return this._state.columns.filter((column) => !column.hidden);
|
|
15
13
|
}
|
|
16
14
|
get _firstColumn() {
|
|
17
|
-
return this.
|
|
18
|
-
}
|
|
19
|
-
getPreviousColumn(key) {
|
|
20
|
-
return this._columns[Math.max(this._columns.indexOf(this._state.host.getColumn(key)) - 1, 0)]
|
|
21
|
-
.field;
|
|
22
|
-
}
|
|
23
|
-
getNextColumn(key) {
|
|
24
|
-
return this._columns[Math.min(this._columns.indexOf(this._state.host.getColumn(key)) + 1, this._columns.length - 1)].field;
|
|
15
|
+
return this._columns.at(0)?.field ?? SENTINEL_NODE.column;
|
|
25
16
|
}
|
|
26
17
|
queryRowByIndex(index) {
|
|
27
|
-
return
|
|
18
|
+
return this._dom.rows.find((row) => row.index === index);
|
|
19
|
+
}
|
|
20
|
+
#queryCell(node) {
|
|
21
|
+
return this.queryRowByIndex(node.row)?.cells.find((cell) => cell.column.field === node.column);
|
|
28
22
|
}
|
|
29
23
|
scrollToCell(node) {
|
|
30
|
-
|
|
31
|
-
if (row) {
|
|
32
|
-
row.cells
|
|
33
|
-
.find((cell) => cell.column.field === node.column)
|
|
34
|
-
?.scrollIntoView({ block: 'nearest' });
|
|
35
|
-
}
|
|
24
|
+
this.#queryCell(node)?.scrollIntoView({ block: 'nearest' });
|
|
36
25
|
}
|
|
37
26
|
get active() {
|
|
38
27
|
return this._active;
|
|
39
28
|
}
|
|
40
29
|
set active(node) {
|
|
30
|
+
const previous = this._active;
|
|
41
31
|
this._active = node ?? SENTINEL_NODE;
|
|
42
|
-
this
|
|
43
|
-
this._navigationState.set('current', node);
|
|
32
|
+
this.#updateActiveRows(previous);
|
|
44
33
|
this._state.host.requestUpdate();
|
|
45
34
|
}
|
|
46
|
-
|
|
35
|
+
#updateActiveRows(previous) {
|
|
36
|
+
for (const row of this._dom.rows) {
|
|
37
|
+
if (row.index === previous.row || row.index === this._active.row) {
|
|
38
|
+
row.activeNode = this._active;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
async #focusActiveCell() {
|
|
43
|
+
const node = this._active;
|
|
44
|
+
let row = this.queryRowByIndex(node.row);
|
|
45
|
+
if (!row) {
|
|
46
|
+
await this._virtualizer?.layoutComplete;
|
|
47
|
+
row = this.queryRowByIndex(node.row);
|
|
48
|
+
}
|
|
49
|
+
await row?.updateComplete;
|
|
50
|
+
if (node !== this._active) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
this.#queryCell(node)?.focus({ preventScroll: true });
|
|
54
|
+
}
|
|
55
|
+
constructor(_state, _dom) {
|
|
47
56
|
this._state = _state;
|
|
57
|
+
this._dom = _dom;
|
|
48
58
|
this.handlers = new Map(Object.entries({
|
|
49
59
|
ArrowDown: this.arrowDown,
|
|
50
60
|
ArrowUp: this.arrowUp,
|
|
@@ -53,53 +63,57 @@ export class NavigationController {
|
|
|
53
63
|
Home: this.home,
|
|
54
64
|
End: this.end,
|
|
55
65
|
}));
|
|
56
|
-
this._navigationState = NAVIGATION_STATE;
|
|
57
66
|
this._active = SENTINEL_NODE;
|
|
58
67
|
this._state.host.addController(this);
|
|
59
68
|
}
|
|
69
|
+
#moveToRow(row) {
|
|
70
|
+
const clamped = Math.min(Math.max(row, 0), this._state.host.totalItems - 1);
|
|
71
|
+
this.active = Object.assign(this.nextNode, { row: clamped });
|
|
72
|
+
this._virtualizer?.element(clamped)?.scrollIntoView({ block: 'nearest' });
|
|
73
|
+
}
|
|
74
|
+
#moveToColumn(offset) {
|
|
75
|
+
const next = this.nextNode;
|
|
76
|
+
const columns = this._columns;
|
|
77
|
+
const index = columns.findIndex((column) => column.field === next.column);
|
|
78
|
+
const target = Math.min(Math.max(index + offset, 0), columns.length - 1);
|
|
79
|
+
this.active = Object.assign(next, { column: columns[target].field });
|
|
80
|
+
this.scrollToCell(this.active);
|
|
81
|
+
}
|
|
60
82
|
home() {
|
|
61
|
-
this
|
|
62
|
-
this._virtualizer?.element(this.active.row)?.scrollIntoView({ block: 'nearest' });
|
|
83
|
+
this.#moveToRow(0);
|
|
63
84
|
}
|
|
64
85
|
end() {
|
|
65
|
-
this
|
|
66
|
-
this._virtualizer?.element(this.active.row)?.scrollIntoView({ block: 'nearest' });
|
|
86
|
+
this.#moveToRow(this._state.host.totalItems - 1);
|
|
67
87
|
}
|
|
68
88
|
arrowDown() {
|
|
69
|
-
|
|
70
|
-
this.active = Object.assign(next, {
|
|
71
|
-
row: Math.min(next.row + 1, this._state.host.totalItems - 1),
|
|
72
|
-
});
|
|
73
|
-
this._virtualizer?.element(next.row)?.scrollIntoView({ block: 'nearest' });
|
|
89
|
+
this.#moveToRow(this.nextNode.row + 1);
|
|
74
90
|
}
|
|
75
91
|
arrowUp() {
|
|
76
|
-
|
|
77
|
-
this.active = Object.assign(next, { row: Math.max(0, next.row - 1) });
|
|
78
|
-
this._virtualizer?.element(next.row)?.scrollIntoView({ block: 'nearest' });
|
|
92
|
+
this.#moveToRow(this.nextNode.row - 1);
|
|
79
93
|
}
|
|
80
94
|
arrowLeft() {
|
|
81
|
-
|
|
82
|
-
this.active = Object.assign(next, { column: this.getPreviousColumn(next.column) });
|
|
83
|
-
this.scrollToCell(this.active);
|
|
95
|
+
this.#moveToColumn(-1);
|
|
84
96
|
}
|
|
85
97
|
arrowRight() {
|
|
86
|
-
|
|
87
|
-
this.active = Object.assign(next, { column: this.getNextColumn(next.column) });
|
|
88
|
-
this.scrollToCell(this.active);
|
|
98
|
+
this.#moveToColumn(1);
|
|
89
99
|
}
|
|
90
100
|
hostDisconnected() {
|
|
91
101
|
this.active = SENTINEL_NODE;
|
|
92
|
-
this._navigationState = NAVIGATION_STATE;
|
|
93
102
|
}
|
|
94
103
|
navigate(event) {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
104
|
+
const handler = this.handlers.get(event.key);
|
|
105
|
+
if (!handler || this._columns.length === 0 || this._state.host.totalItems === 0) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
event.preventDefault();
|
|
109
|
+
handler.call(this);
|
|
110
|
+
this.#focusActiveCell();
|
|
111
|
+
}
|
|
112
|
+
async navigateTo(row, options) {
|
|
113
|
+
const { column, activate } = options ?? {};
|
|
114
|
+
if (activate) {
|
|
115
|
+
this.active = Object.assign(this.nextNode, column ? { row, column } : { row });
|
|
98
116
|
}
|
|
99
|
-
}
|
|
100
|
-
async navigateTo(row, column, activate = false) {
|
|
101
|
-
if (activate)
|
|
102
|
-
this.active = Object.assign(this.nextNode, { row, column });
|
|
103
117
|
let item = this.queryRowByIndex(row);
|
|
104
118
|
let completePromise;
|
|
105
119
|
if (!item) {
|
|
@@ -108,8 +122,9 @@ export class NavigationController {
|
|
|
108
122
|
}
|
|
109
123
|
item?.scrollIntoView({ block: 'nearest' });
|
|
110
124
|
await completePromise;
|
|
111
|
-
if (column)
|
|
125
|
+
if (column) {
|
|
112
126
|
this.scrollToCell({ row, column });
|
|
127
|
+
}
|
|
113
128
|
}
|
|
114
129
|
}
|
|
115
130
|
//# sourceMappingURL=navigation.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"navigation.js","sourceRoot":"","sources":["../../src/controllers/navigation.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ReactiveController } from 'lit';\nimport type IgcGridLiteRow from '../components/row.js';\nimport { NAVIGATION_STATE, SENTINEL_NODE } from '../internal/constants.js';\nimport { GRID_ROW_TAG } from '../internal/tags.js';\nimport type { ActiveNode, Keys } from '../internal/types.js';\nimport type { StateController } from './state.js';\n\nexport class NavigationController<T extends object> implements ReactiveController {\n protected handlers = new Map(\n Object.entries({\n ArrowDown: this.arrowDown,\n ArrowUp: this.arrowUp,\n ArrowLeft: this.arrowLeft,\n ArrowRight: this.arrowRight,\n Home: this.home,\n End: this.end,\n })\n );\n\n protected get _virtualizer() {\n return this._state.virtualizer;\n }\n\n protected _navigationState = NAVIGATION_STATE;\n protected _active = SENTINEL_NODE;\n\n protected get nextNode() {\n const node = this._navigationState.get('current')!;\n return node === SENTINEL_NODE\n ? { column: this._firstColumn, row: 0 }\n : ({ ...node } as ActiveNode<T>);\n }\n\n protected get _columns() {\n return this._state.columns;\n }\n\n protected get _firstColumn() {\n return this._state.host.getColumn(0)!.field ?? '';\n }\n\n protected getPreviousColumn(key: Keys<T>) {\n return this._columns[Math.max(this._columns.indexOf(this._state.host.getColumn(key)!) - 1, 0)]\n .field;\n }\n\n protected getNextColumn(key: Keys<T>) {\n return this._columns[\n Math.min(\n this._columns.indexOf(this._state.host.getColumn(key)!) + 1,\n this._columns.length - 1\n )\n ].field;\n }\n\n protected queryRowByIndex(index: number) {\n return Array.from(this._virtualizer?.querySelectorAll(GRID_ROW_TAG) ?? []).find(\n (row) => row.index === index\n ) as unknown as IgcGridLiteRow<T>;\n }\n\n protected scrollToCell(node: ActiveNode<T>) {\n const row = this.queryRowByIndex(node.row);\n\n if (row) {\n row.cells\n .find((cell) => cell.column.field === node.column)\n ?.scrollIntoView({ block: 'nearest' });\n }\n }\n\n public get active(): ActiveNode<T> {\n return this._active as ActiveNode<T>;\n }\n\n public set active(node: ActiveNode<T>) {\n this._active = node ?? SENTINEL_NODE;\n this._navigationState.set('previous', this._active);\n this._navigationState.set('current', node);\n this._state.host.requestUpdate();\n }\n\n constructor(protected _state: StateController<T>) {\n this._state.host.addController(this);\n }\n\n protected home() {\n this.active = Object.assign(this.nextNode, { row: 0 });\n this._virtualizer?.element(this.active.row)?.scrollIntoView({ block: 'nearest' });\n }\n\n protected end() {\n this.active = Object.assign(this.nextNode, { row: this._state.host.totalItems - 1 });\n this._virtualizer?.element(this.active.row)?.scrollIntoView({ block: 'nearest' });\n }\n\n protected arrowDown() {\n const next = this.nextNode;\n\n this.active = Object.assign(next, {\n row: Math.min(next.row + 1, this._state.host.totalItems - 1),\n });\n this._virtualizer?.element(next.row)?.scrollIntoView({ block: 'nearest' });\n }\n\n protected arrowUp() {\n const next = this.nextNode;\n this.active = Object.assign(next, { row: Math.max(0, next.row - 1) });\n this._virtualizer?.element(next.row)?.scrollIntoView({ block: 'nearest' });\n }\n\n protected arrowLeft() {\n const next = this.nextNode;\n this.active = Object.assign(next, { column: this.getPreviousColumn(next.column) });\n this.scrollToCell(this.active);\n }\n\n protected arrowRight() {\n const next = this.nextNode;\n this.active = Object.assign(next, { column: this.getNextColumn(next.column) });\n this.scrollToCell(this.active);\n }\n\n public hostDisconnected() {\n this.active = SENTINEL_NODE as ActiveNode<T>;\n this._navigationState = NAVIGATION_STATE;\n }\n\n public navigate(event: KeyboardEvent) {\n if (this.handlers.has(event.key)) {\n event.preventDefault();\n this.handlers.get(event.key)!.call(this);\n }\n }\n\n public async navigateTo(row: number, column?: Keys<T>, activate = false) {\n if (activate) this.active = Object.assign(this.nextNode, { row, column });\n\n // attempt to resolve row in DOM first as a check if layout change will be needed\n let item: Pick<HTMLElement, 'scrollIntoView'> | undefined = this.queryRowByIndex(row);\n let completePromise: Promise<void> | undefined;\n\n if (!item) {\n item = this._virtualizer?.element(row);\n completePromise = item && this._virtualizer?.layoutComplete;\n }\n\n item?.scrollIntoView({ block: 'nearest' });\n await completePromise;\n if (column) this.scrollToCell({ row, column });\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"navigation.js","sourceRoot":"","sources":["../../src/controllers/navigation.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAKzD,MAAM,OAAO,oBAAoB;IAY/B,IAAc,YAAY;QACxB,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC;IAC/B,CAAC;IAID,IAAc,QAAQ;QACpB,OAAO,IAAI,CAAC,OAAO,KAAK,aAAa;YACnC,CAAC,CAAE,EAAE,MAAM,EAAE,IAAI,CAAC,YAAY,EAAE,GAAG,EAAE,CAAC,EAAoB;YAC1D,CAAC,CAAE,EAAE,GAAG,IAAI,CAAC,OAAO,EAAoB,CAAC;IAC7C,CAAC;IAGD,IAAc,QAAQ;QACpB,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAChE,CAAC;IAED,IAAc,YAAY;QACxB,OAAO,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,aAAa,CAAC,MAAM,CAAC;IAC5D,CAAC;IAES,eAAe,CAAC,KAAa;QACrC,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC;IAC3D,CAAC;IAGD,UAAU,CAAC,IAAmB;QAC5B,OAAO,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,KAAK,IAAI,CAAC,MAAM,CAAC,CAAC;IACjG,CAAC;IAES,YAAY,CAAC,IAAmB;QACxC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,cAAc,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;IAC9D,CAAC;IAED,IAAW,MAAM;QACf,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,IAAW,MAAM,CAAC,IAAmB;QACnC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC;QAE9B,IAAI,CAAC,OAAO,GAAG,IAAI,IAAI,aAAa,CAAC;QACrC,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QACjC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;IACnC,CAAC;IAMD,iBAAiB,CAAC,QAAuB;QACvC,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACjC,IAAI,GAAG,CAAC,KAAK,KAAK,QAAQ,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,KAAK,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;gBACjE,GAAG,CAAC,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC;YAChC,CAAC;QACH,CAAC;IACH,CAAC;IAGD,KAAK,CAAC,gBAAgB;QACpB,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC;QAC1B,IAAI,GAAG,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAGzC,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,MAAM,IAAI,CAAC,YAAY,EAAE,cAAc,CAAC;YACxC,GAAG,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACvC,CAAC;QAED,MAAM,GAAG,EAAE,cAAc,CAAC;QAG1B,IAAI,IAAI,KAAK,IAAI,CAAC,OAAO,EAAE,CAAC;YAC1B,OAAO;QACT,CAAC;QAED,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IACxD,CAAC;IAED,YACY,MAA0B,EAC1B,IAA0B;QAD1B,WAAM,GAAN,MAAM,CAAoB;QAC1B,SAAI,GAAJ,IAAI,CAAsB;QA5F5B,aAAQ,GAAG,IAAI,GAAG,CAC1B,MAAM,CAAC,OAAO,CAAC;YACb,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,GAAG,EAAE,IAAI,CAAC,GAAG;SACd,CAAC,CACH,CAAC;QAMQ,YAAO,GAAG,aAA8B,CAAC;QA+EjD,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IACvC,CAAC;IAGD,UAAU,CAAC,GAAW;QACpB,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC;QAE5E,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;QAC7D,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,OAAO,CAAC,EAAE,cAAc,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;IAC5E,CAAC;IAMD,aAAa,CAAC,MAAc;QAC1B,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC3B,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC;QAE9B,MAAM,KAAK,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,KAAK,IAAI,CAAC,MAAM,CAAC,CAAC;QAC1E,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,MAAM,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAEzE,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;QACrE,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACjC,CAAC;IAES,IAAI;QACZ,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IACrB,CAAC;IAES,GAAG;QACX,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC;IACnD,CAAC;IAES,SAAS;QACjB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;IACzC,CAAC;IAES,OAAO;QACf,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;IACzC,CAAC;IAES,SAAS;QACjB,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;IACzB,CAAC;IAES,UAAU;QAClB,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IACxB,CAAC;IAEM,gBAAgB;QACrB,IAAI,CAAC,MAAM,GAAG,aAA8B,CAAC;IAC/C,CAAC;IAEM,QAAQ,CAAC,KAAoB;QAClC,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAG7C,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,KAAK,CAAC,EAAE,CAAC;YAChF,OAAO;QACT,CAAC;QAED,KAAK,CAAC,cAAc,EAAE,CAAC;QACvB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnB,IAAI,CAAC,gBAAgB,EAAE,CAAC;IAC1B,CAAC;IAEM,KAAK,CAAC,UAAU,CAAC,GAAW,EAAE,OAA8B;QACjE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,IAAI,EAAE,CAAC;QAE3C,IAAI,QAAQ,EAAE,CAAC;YAEb,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;QACjF,CAAC;QAGD,IAAI,IAAI,GAAoD,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;QACtF,IAAI,eAA0C,CAAC;QAE/C,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,IAAI,GAAG,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;YACvC,eAAe,GAAG,IAAI,IAAI,IAAI,CAAC,YAAY,EAAE,cAAc,CAAC;QAC9D,CAAC;QAED,IAAI,EAAE,cAAc,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;QAC3C,MAAM,eAAe,CAAC;QAEtB,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,CAAC,YAAY,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC;QACrC,CAAC;IACH,CAAC;CACF","sourcesContent":["import type { ReactiveController } from 'lit';\nimport { SENTINEL_NODE } from '../internal/constants.js';\nimport type { ActiveNode, NavigateToOptions } from '../internal/types.js';\nimport type { GridDOMController } from './dom.js';\nimport type { StateController } from './state.js';\n\nexport class NavigationController<T extends object> implements ReactiveController {\n protected handlers = new Map(\n Object.entries({\n ArrowDown: this.arrowDown,\n ArrowUp: this.arrowUp,\n ArrowLeft: this.arrowLeft,\n ArrowRight: this.arrowRight,\n Home: this.home,\n End: this.end,\n })\n );\n\n protected get _virtualizer() {\n return this._dom.virtualizer;\n }\n\n protected _active = SENTINEL_NODE as ActiveNode<T>;\n\n protected get nextNode() {\n return this._active === SENTINEL_NODE\n ? ({ column: this._firstColumn, row: 0 } as ActiveNode<T>)\n : ({ ...this._active } as ActiveNode<T>);\n }\n\n /** Rows render only the visible columns, so navigation walks the same sequence. */\n protected get _columns() {\n return this._state.columns.filter((column) => !column.hidden);\n }\n\n protected get _firstColumn() {\n return this._columns.at(0)?.field ?? SENTINEL_NODE.column;\n }\n\n protected queryRowByIndex(index: number) {\n return this._dom.rows.find((row) => row.index === index);\n }\n\n /** The rendered cell at `node`, if its row and column are in the DOM. */\n #queryCell(node: ActiveNode<T>) {\n return this.queryRowByIndex(node.row)?.cells.find((cell) => cell.column.field === node.column);\n }\n\n protected scrollToCell(node: ActiveNode<T>) {\n this.#queryCell(node)?.scrollIntoView({ block: 'nearest' });\n }\n\n public get active(): ActiveNode<T> {\n return this._active;\n }\n\n public set active(node: ActiveNode<T>) {\n const previous = this._active;\n\n this._active = node ?? SENTINEL_NODE;\n this.#updateActiveRows(previous);\n this._state.host.requestUpdate();\n }\n\n /**\n * Sends the new active node only to the rows that enter or leave the active\n * state. The other rendered rows have no changes and are not re-rendered.\n */\n #updateActiveRows(previous: ActiveNode<T>): void {\n for (const row of this._dom.rows) {\n if (row.index === previous.row || row.index === this._active.row) {\n row.activeNode = this._active;\n }\n }\n }\n\n /** Moves DOM focus onto the active cell when it is rendered (roving focus). */\n async #focusActiveCell(): Promise<void> {\n const node = this._active;\n let row = this.queryRowByIndex(node.row);\n\n // The target row is not rendered yet. Wait for the virtualizer layout pass.\n if (!row) {\n await this._virtualizer?.layoutComplete;\n row = this.queryRowByIndex(node.row);\n }\n\n await row?.updateComplete;\n\n // A newer navigation replaced this one during the render wait.\n if (node !== this._active) {\n return;\n }\n\n this.#queryCell(node)?.focus({ preventScroll: true });\n }\n\n constructor(\n protected _state: StateController<T>,\n protected _dom: GridDOMController<T>\n ) {\n this._state.host.addController(this);\n }\n\n /** Activates `row` (clamped to the data range) and scrolls it into view. */\n #moveToRow(row: number) {\n const clamped = Math.min(Math.max(row, 0), this._state.host.totalItems - 1);\n\n this.active = Object.assign(this.nextNode, { row: clamped });\n this._virtualizer?.element(clamped)?.scrollIntoView({ block: 'nearest' });\n }\n\n /**\n * Steps the active column by `offset`, clamping at the visible ends. A hidden\n * or missing key (index -1) lands on the first visible column.\n */\n #moveToColumn(offset: -1 | 1) {\n const next = this.nextNode;\n const columns = this._columns;\n\n const index = columns.findIndex((column) => column.field === next.column);\n const target = Math.min(Math.max(index + offset, 0), columns.length - 1);\n\n this.active = Object.assign(next, { column: columns[target].field });\n this.scrollToCell(this.active);\n }\n\n protected home() {\n this.#moveToRow(0);\n }\n\n protected end() {\n this.#moveToRow(this._state.host.totalItems - 1);\n }\n\n protected arrowDown() {\n this.#moveToRow(this.nextNode.row + 1);\n }\n\n protected arrowUp() {\n this.#moveToRow(this.nextNode.row - 1);\n }\n\n protected arrowLeft() {\n this.#moveToColumn(-1);\n }\n\n protected arrowRight() {\n this.#moveToColumn(1);\n }\n\n public hostDisconnected() {\n this.active = SENTINEL_NODE as ActiveNode<T>;\n }\n\n public navigate(event: KeyboardEvent) {\n const handler = this.handlers.get(event.key);\n\n // Nothing to move to without a visible column or a data row.\n if (!handler || this._columns.length === 0 || this._state.host.totalItems === 0) {\n return;\n }\n\n event.preventDefault();\n handler.call(this);\n this.#focusActiveCell();\n }\n\n public async navigateTo(row: number, options?: NavigateToOptions<T>) {\n const { column, activate } = options ?? {};\n\n if (activate) {\n // Without an explicit column, activation keeps the one from `nextNode`.\n this.active = Object.assign(this.nextNode, column ? { row, column } : { row });\n }\n\n // Resolve the row in the DOM first. A missing row means a layout pass is necessary.\n let item: Pick<HTMLElement, 'scrollIntoView'> | undefined = this.queryRowByIndex(row);\n let completePromise: Promise<void> | undefined;\n\n if (!item) {\n item = this._virtualizer?.element(row);\n completePromise = item && this._virtualizer?.layoutComplete;\n }\n\n item?.scrollIntoView({ block: 'nearest' });\n await completePromise;\n\n if (column) {\n this.scrollToCell({ row, column });\n }\n }\n}\n"]}
|
package/controllers/resize.d.ts
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { nothing, type ReactiveController } from 'lit';
|
|
2
2
|
import type IgcGridLiteHeader from '../components/header.js';
|
|
3
|
-
import type { ColumnConfiguration
|
|
3
|
+
import type { ColumnConfiguration } from '../internal/types.js';
|
|
4
|
+
import type { GridDOMController } from './dom.js';
|
|
5
|
+
import type { StateController } from './state.js';
|
|
4
6
|
export declare class ResizeController<T extends object> implements ReactiveController {
|
|
5
7
|
#private;
|
|
6
|
-
protected
|
|
7
|
-
|
|
8
|
+
protected _state: StateController<T>;
|
|
9
|
+
protected _dom: GridDOMController<T>;
|
|
10
|
+
constructor(_state: StateController<T>, _dom: GridDOMController<T>);
|
|
8
11
|
indicatorActive: boolean;
|
|
9
12
|
indicatorOffset: number;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
*
|
|
13
|
-
* @param header the
|
|
14
|
-
*/
|
|
13
|
+
protected get host(): import("../internal/types.js").GridHost<T>;
|
|
14
|
+
/** Starts a column resize: shows the indicator and aligns it with the header. */
|
|
15
15
|
start(header: IgcGridLiteHeader<T>): void;
|
|
16
16
|
/**
|
|
17
17
|
* Stops and resets the resizing state.
|