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.
Files changed (86) hide show
  1. package/components/cell.d.ts +8 -0
  2. package/components/cell.js +12 -1
  3. package/components/cell.js.map +1 -1
  4. package/components/column.d.ts +2 -2
  5. package/components/column.js.map +1 -1
  6. package/components/filter-row.d.ts +7 -2
  7. package/components/filter-row.js +87 -52
  8. package/components/filter-row.js.map +1 -1
  9. package/components/grid.d.ts +49 -3
  10. package/components/grid.js +102 -62
  11. package/components/grid.js.map +1 -1
  12. package/components/header-row.d.ts +1 -2
  13. package/components/header-row.js +4 -7
  14. package/components/header-row.js.map +1 -1
  15. package/components/header.d.ts +9 -0
  16. package/components/header.js +36 -23
  17. package/components/header.js.map +1 -1
  18. package/components/row.d.ts +4 -1
  19. package/components/row.js +12 -1
  20. package/components/row.js.map +1 -1
  21. package/components/virtualizer.d.ts +3 -1
  22. package/components/virtualizer.js +36 -7
  23. package/components/virtualizer.js.map +1 -1
  24. package/controllers/data-operation.d.ts +0 -4
  25. package/controllers/data-operation.js +7 -22
  26. package/controllers/data-operation.js.map +1 -1
  27. package/controllers/dom.d.ts +28 -9
  28. package/controllers/dom.js +70 -20
  29. package/controllers/dom.js.map +1 -1
  30. package/controllers/filter.d.ts +20 -4
  31. package/controllers/filter.js +39 -55
  32. package/controllers/filter.js.map +1 -1
  33. package/controllers/navigation.d.ts +10 -10
  34. package/controllers/navigation.js +68 -53
  35. package/controllers/navigation.js.map +1 -1
  36. package/controllers/resize.d.ts +8 -8
  37. package/controllers/resize.js +23 -14
  38. package/controllers/resize.js.map +1 -1
  39. package/controllers/sort.d.ts +12 -3
  40. package/controllers/sort.js +25 -32
  41. package/controllers/sort.js.map +1 -1
  42. package/controllers/state.d.ts +28 -18
  43. package/controllers/state.js +20 -26
  44. package/controllers/state.js.map +1 -1
  45. package/custom-elements.json +874 -243
  46. package/docs/igniteui-grid-lite.json +1339 -818
  47. package/index.d.ts +1 -1
  48. package/index.js.map +1 -1
  49. package/internal/a11y.d.ts +29 -0
  50. package/internal/a11y.js +24 -0
  51. package/internal/a11y.js.map +1 -0
  52. package/internal/constants.d.ts +3 -2
  53. package/internal/constants.js +1 -4
  54. package/internal/constants.js.map +1 -1
  55. package/internal/normalize-case.d.ts +5 -1
  56. package/internal/normalize-case.js +2 -1
  57. package/internal/normalize-case.js.map +1 -1
  58. package/internal/part-map.js +9 -17
  59. package/internal/part-map.js.map +1 -1
  60. package/internal/tags.d.ts +2 -2
  61. package/internal/tags.js +2 -2
  62. package/internal/tags.js.map +1 -1
  63. package/internal/types.d.ts +13 -1
  64. package/internal/types.js.map +1 -1
  65. package/internal/utils.d.ts +3 -0
  66. package/internal/utils.js +17 -4
  67. package/internal/utils.js.map +1 -1
  68. package/internal/watch.js +8 -9
  69. package/internal/watch.js.map +1 -1
  70. package/operations/base.js +2 -1
  71. package/operations/base.js.map +1 -1
  72. package/operations/filter/state.js +2 -5
  73. package/operations/filter/state.js.map +1 -1
  74. package/operations/filter/tree.d.ts +1 -2
  75. package/operations/filter/tree.js +2 -7
  76. package/operations/filter/tree.js.map +1 -1
  77. package/operations/filter.js +13 -1
  78. package/operations/filter.js.map +1 -1
  79. package/operations/sort.d.ts +0 -1
  80. package/operations/sort.js +7 -9
  81. package/operations/sort.js.map +1 -1
  82. package/package.json +2 -2
  83. package/styles/themes/grid.base.css.js +1 -1
  84. package/styles/themes/grid.base.css.js.map +1 -1
  85. package/styles/themes/shared/grid.common.css.js +1 -1
  86. package/styles/themes/shared/grid.common.css.js.map +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"dom.js","sourceRoot":"","sources":["../../src/controllers/dom.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAEjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAGzD,MAAM,iBAAiB;IAIrB,YAAY,IAAiB,EAAE,KAAyB;QAMjD,gBAAW,GAAc,EAAE,CAAC;QALjC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpB,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;IAIM,aAAa;QAClB,iBAAiB,EAAE,CAAC;QACpB,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAE1B,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,EAAE;YAClC,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,gBAAgB,CACvC,mBAAmB,EACnB,GAAG,EAAE;gBACH,IAAI,CAAC,eAAe,EAAE,CAAC;YACzB,CAAC,EACD,EAAE,IAAI,EAAE,IAAI,EAAE,CACf,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;IAEM,UAAU;QACf,IAAI,CAAC,eAAe,EAAE,CAAC;QACvB,IAAI,CAAC,kBAAkB,EAAE,CAAC;IAC5B,CAAC;IAEM,eAAe;QACpB,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW;YAClC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,WAAW;YAC3E,CAAC,CAAC,CAAC,CAAC;QACN,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,oBAAoB,EAAE,GAAG,IAAI,IAAI,CAAC,CAAC;IAClE,CAAC;IAES,kBAAkB;QAC1B,IAAI,CAAC,WAAW,GAAG,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC5D,CAAC;IAEM,kBAAkB,CAAC,KAAa;QACrC,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACpE,CAAC;CACF;AAED,SAAS,mBAAmB,CAC1B,IAAiB,EACjB,KAAyB;IAEzB,OAAO,IAAI,iBAAiB,CAAI,IAAI,EAAE,KAAK,CAAC,CAAC;AAC/C,CAAC;AAGD,OAAO,EAAE,mBAAmB,EAAE,CAAC","sourcesContent":["import type { ReactiveController } from 'lit';\nimport type { StyleInfo } from 'lit/directives/style-map.js';\nimport { registerGridIcons } from '../internal/icon-registry.js';\nimport type { GridHost } from '../internal/types.js';\nimport { applyColumnWidths } from '../internal/utils.js';\nimport type { StateController } from './state.js';\n\nclass GridDOMController<T extends object> implements ReactiveController {\n protected readonly _host: GridHost<T>;\n protected readonly _state: StateController<T>;\n\n constructor(host: GridHost<T>, state: StateController<T>) {\n this._host = host;\n this._state = state;\n this._host.addController(this);\n }\n\n public columnSizes: StyleInfo = {};\n\n public hostConnected(): void {\n registerGridIcons();\n this.setGridColumnSizes();\n\n this._host.updateComplete.then(() => {\n this._state.virtualizer?.addEventListener(\n 'visibilityChanged',\n () => {\n this.setScrollOffset();\n },\n { once: true }\n );\n });\n }\n\n public hostUpdate(): void {\n this.setScrollOffset();\n this.setGridColumnSizes();\n }\n\n public setScrollOffset(): void {\n const size = this._state.virtualizer\n ? this._state.virtualizer.offsetWidth - this._state.virtualizer.clientWidth\n : 0;\n this._host.style.setProperty('--scrollbar-offset', `${size}px`);\n }\n\n protected setGridColumnSizes(): void {\n this.columnSizes = applyColumnWidths(this._state.columns);\n }\n\n public getActiveRowStyles(index: number): StyleInfo {\n return this._state.active.row === index ? { 'z-index': '3' } : {};\n }\n}\n\nfunction createDomController<T extends object>(\n host: GridHost<T>,\n state: StateController<T>\n): GridDOMController<T> {\n return new GridDOMController<T>(host, state);\n}\n\nexport type { GridDOMController };\nexport { createDomController };\n"]}
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"]}
@@ -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
- constructor(state: StateController<T>);
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
- filterWithEvent(expression: FilterExpression<T>, type: 'add' | 'modify' | 'remove'): Promise<void>;
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 directly in the filter state without requiring column configuration.
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
  /**
@@ -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._stateController.filterRow;
15
+ return this._dom.filterRow;
15
16
  }
16
- get #virtualizer() {
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.#virtualizer?.scrollTo({ top: 0 });
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.host.requestUpdate();
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: operands[keys[0]],
63
- caseSensitive,
52
+ condition: Object.values(getFilterOperandsFor(column))[0],
53
+ caseSensitive: Boolean(column.filteringCaseSensitive),
64
54
  };
65
55
  }
66
- async removeAllExpressions(key) {
67
- const state = this.get(key)?.all ?? [];
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
- this.reset(key);
79
- this.#filter([]);
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
- if (!this.#emitFilteringEvent(expression, 'remove')) {
86
- return;
87
- }
88
- state?.remove(expression);
89
- if (state?.empty) {
90
- this.reset(state.key);
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
- if (!this.#emitFilteringEvent(expression, type)) {
98
- return;
99
- }
100
- this.#filter(expression);
101
- await this.host.updateComplete;
102
- this.#emitFilteredEvent({ key: expression.key, state: this.get(expression.key)?.all ?? [] });
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 = getFilterOperandsFor(column)[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 IgcGridLiteRow from '../components/row.js';
3
- import type { ActiveNode, Keys } from '../internal/types.js';
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 _navigationState: Map<import("../internal/types.js").NavigationState, ActiveNode<any>>;
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(): Exclude<keyof T & string, keyof T> | (Keys<T> & string) | (Keys<T> & number) | (Keys<T> & symbol) | (Keys<T> & `${string}.${string}`) | (Keys<T> & `${string}.${string}.${string}`);
14
- protected getPreviousColumn(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}`);
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, column?: Keys<T>, activate?: boolean): Promise<void>;
29
+ navigateTo(row: number, options?: NavigateToOptions<T>): Promise<void>;
30
30
  }
@@ -1,50 +1,60 @@
1
- import { NAVIGATION_STATE, SENTINEL_NODE } from '../internal/constants.js';
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._state.virtualizer;
4
+ return this._dom.virtualizer;
6
5
  }
7
6
  get nextNode() {
8
- const node = this._navigationState.get('current');
9
- return node === SENTINEL_NODE
7
+ return this._active === SENTINEL_NODE
10
8
  ? { column: this._firstColumn, row: 0 }
11
- : { ...node };
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._state.host.getColumn(0).field ?? '';
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 Array.from(this._virtualizer?.querySelectorAll(GRID_ROW_TAG) ?? []).find((row) => row.index === index);
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
- const row = this.queryRowByIndex(node.row);
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._navigationState.set('previous', this._active);
43
- this._navigationState.set('current', node);
32
+ this.#updateActiveRows(previous);
44
33
  this._state.host.requestUpdate();
45
34
  }
46
- constructor(_state) {
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.active = Object.assign(this.nextNode, { row: 0 });
62
- this._virtualizer?.element(this.active.row)?.scrollIntoView({ block: 'nearest' });
83
+ this.#moveToRow(0);
63
84
  }
64
85
  end() {
65
- this.active = Object.assign(this.nextNode, { row: this._state.host.totalItems - 1 });
66
- this._virtualizer?.element(this.active.row)?.scrollIntoView({ block: 'nearest' });
86
+ this.#moveToRow(this._state.host.totalItems - 1);
67
87
  }
68
88
  arrowDown() {
69
- const next = this.nextNode;
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
- const next = this.nextNode;
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
- const next = this.nextNode;
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
- const next = this.nextNode;
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
- if (this.handlers.has(event.key)) {
96
- event.preventDefault();
97
- this.handlers.get(event.key).call(this);
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":"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","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"]}
@@ -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, GridHost } from '../internal/types.js';
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 host: GridHost<T>;
7
- constructor(host: GridHost<T>);
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
- * Begins resizing a column by showing and positioning the resize indicator in relation to the column.
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.