apex-grid 3.2.0 → 3.4.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/CHANGELOG.md +120 -0
- package/README.md +229 -52
- package/components/cell.d.ts +16 -3
- package/components/cell.js +78 -8
- package/components/cell.js.map +1 -1
- package/components/filter-row.d.ts +3 -6
- package/components/filter-row.js +144 -115
- package/components/filter-row.js.map +1 -1
- package/components/grid.d.ts +421 -77
- package/components/grid.js +432 -13
- package/components/grid.js.map +1 -1
- package/components/group-header-row.d.ts +34 -0
- package/components/group-header-row.js +125 -0
- package/components/group-header-row.js.map +1 -0
- package/components/header-row.d.ts +13 -2
- package/components/header-row.js +33 -18
- package/components/header-row.js.map +1 -1
- package/components/header.d.ts +11 -0
- package/components/header.js +209 -8
- package/components/header.js.map +1 -1
- package/components/paginator.d.ts +6 -1
- package/components/paginator.js +17 -11
- package/components/paginator.js.map +1 -1
- package/components/row.d.ts +28 -0
- package/components/row.js +100 -3
- package/components/row.js.map +1 -1
- package/components/toolbar.d.ts +8 -1
- package/components/toolbar.js +25 -7
- package/components/toolbar.js.map +1 -1
- package/controllers/data-operation.js +1 -0
- package/controllers/data-operation.js.map +1 -1
- package/controllers/dom.d.ts +24 -6
- package/controllers/dom.js +62 -5
- package/controllers/dom.js.map +1 -1
- package/controllers/editing.d.ts +68 -1
- package/controllers/editing.js +129 -44
- package/controllers/editing.js.map +1 -1
- package/controllers/expansion.js +4 -4
- package/controllers/expansion.js.map +1 -1
- package/controllers/filter.d.ts +1 -1
- package/controllers/filter.js +27 -5
- package/controllers/filter.js.map +1 -1
- package/controllers/history.d.ts +86 -0
- package/controllers/history.js +125 -0
- package/controllers/history.js.map +1 -0
- package/controllers/navigation.d.ts +49 -2
- package/controllers/navigation.js +145 -3
- package/controllers/navigation.js.map +1 -1
- package/controllers/pagination.js +1 -1
- package/controllers/pagination.js.map +1 -1
- package/controllers/reorder.js +3 -1
- package/controllers/reorder.js.map +1 -1
- package/controllers/row-pin.d.ts +59 -0
- package/controllers/row-pin.js +75 -0
- package/controllers/row-pin.js.map +1 -0
- package/controllers/row-reorder.d.ts +161 -0
- package/controllers/row-reorder.js +332 -0
- package/controllers/row-reorder.js.map +1 -0
- package/controllers/selection.js +3 -3
- package/controllers/selection.js.map +1 -1
- package/controllers/sort.js +13 -3
- package/controllers/sort.js.map +1 -1
- package/controllers/state.d.ts +33 -0
- package/controllers/state.js +37 -2
- package/controllers/state.js.map +1 -1
- package/controllers/tree.d.ts +8 -0
- package/controllers/tree.js +0 -0
- package/controllers/tree.js.map +1 -1
- package/custom-elements.json +4667 -926
- package/docs/assets/hierarchy.js +1 -1
- package/docs/assets/highlight.css +28 -0
- package/docs/assets/navigation.js +1 -1
- package/docs/assets/search.js +1 -1
- package/docs/functions/custom.html +3 -0
- package/docs/functions/interpolate.html +4 -0
- package/docs/functions/localize.html +8 -0
- package/docs/functions/max.html +3 -0
- package/docs/functions/min.html +3 -0
- package/docs/functions/pattern.html +3 -0
- package/docs/functions/required.html +3 -0
- package/docs/hierarchy.html +1 -1
- package/docs/index.html +245 -54
- package/docs/interfaces/ApexCellValidationFailedEvent.html +13 -0
- package/docs/interfaces/ApexCellValueChangedEvent.html +1 -1
- package/docs/interfaces/ApexCellValueChangingEvent.html +2 -2
- package/docs/interfaces/ApexColumnGroupContext.html +6 -0
- package/docs/interfaces/ApexColumnMovedEvent.html +2 -2
- package/docs/interfaces/ApexColumnMovingEvent.html +1 -1
- package/docs/interfaces/ApexDetailContext.html +2 -2
- package/docs/interfaces/ApexGridEventMap.html +37 -9
- package/docs/interfaces/ApexHistoryChangedEvent.html +6 -0
- package/docs/interfaces/ApexPageChangedEvent.html +1 -1
- package/docs/interfaces/ApexRowMovingEvent.html +9 -0
- package/docs/interfaces/ApexRowPinningEvent.html +8 -0
- package/docs/interfaces/ApexStateChangedEvent.html +4 -0
- package/docs/interfaces/BaseApexCellContext.html +1 -1
- package/docs/interfaces/BaseApexEditorContext.html +1 -1
- package/docs/interfaces/BaseColumnConfiguration.html +42 -17
- package/docs/interfaces/CSVExportOptions.html +2 -2
- package/docs/interfaces/ColumnGroupConfiguration.html +12 -0
- package/docs/interfaces/ColumnLayoutState.html +2 -0
- package/docs/interfaces/ColumnSchema.html +22 -0
- package/docs/interfaces/DataPipelineConfiguration.html +2 -2
- package/docs/interfaces/EditingHistoryConfiguration.html +10 -0
- package/docs/interfaces/ExportFormat.html +2 -2
- package/docs/interfaces/ExportOptions.html +1 -1
- package/docs/interfaces/FilterStateSnapshot.html +4 -0
- package/docs/interfaces/GetStateOptions.html +4 -0
- package/docs/interfaces/GridCapabilities.html +8 -0
- package/docs/interfaces/GridEditingConfiguration.html +4 -2
- package/docs/interfaces/GridRowPinningConfiguration.html +5 -0
- package/docs/interfaces/GridRowReorderingConfiguration.html +22 -0
- package/docs/interfaces/GridSchema.html +19 -0
- package/docs/interfaces/GridState.html +41 -0
- package/docs/interfaces/GridTreeConfiguration.html +2 -2
- package/docs/interfaces/PaginationConfiguration.html +1 -1
- package/docs/interfaces/PaginationState.html +1 -1
- package/docs/interfaces/SetStateOptions.html +9 -0
- package/docs/interfaces/SetStateResult.html +11 -0
- package/docs/interfaces/SortStateSnapshot.html +2 -0
- package/docs/interfaces/ValidatorContext.html +8 -0
- package/docs/media/_tokens.scss +70 -81
- package/docs/media/package.json +2 -2
- package/docs/media/state-persistence.html +189 -0
- package/docs/modules.html +1 -1
- package/docs/types/DataPipelineParams.html +2 -2
- package/docs/types/EditMode.html +2 -2
- package/docs/types/GridLocaleKey.html +3 -0
- package/docs/types/GridLocaleText.html +5 -0
- package/docs/types/LocaleParams.html +2 -0
- package/docs/types/PaginationMode.html +1 -1
- package/docs/types/RowDropPosition.html +2 -0
- package/docs/types/RowPinPosition.html +2 -0
- package/docs/types/RowRef.html +3 -0
- package/docs/types/Validator.html +4 -0
- package/docs/variables/EN_LOCALE.html +9 -0
- package/docs/variables/esLocale.html +8 -0
- package/i18n/en.d.ts +245 -0
- package/i18n/en.js +219 -0
- package/i18n/en.js.map +1 -0
- package/i18n/es.d.ts +18 -0
- package/i18n/es.js +219 -0
- package/i18n/es.js.map +1 -0
- package/i18n/index.d.ts +3 -0
- package/i18n/index.js +4 -0
- package/i18n/index.js.map +1 -0
- package/i18n/localize.d.ts +23 -0
- package/i18n/localize.js +15 -0
- package/i18n/localize.js.map +1 -0
- package/index.d.ts +8 -2
- package/index.js +2 -0
- package/index.js.map +1 -1
- package/internal/column-types.js +1 -1
- package/internal/column-types.js.map +1 -1
- package/internal/feature-module.d.ts +46 -0
- package/internal/feature-module.js +11 -0
- package/internal/feature-module.js.map +1 -1
- package/internal/flip.js +1 -1
- package/internal/flip.js.map +1 -1
- package/internal/icons.d.ts +9 -7
- package/internal/icons.js +75 -35
- package/internal/icons.js.map +1 -1
- package/internal/index.d.ts +5 -3
- package/internal/index.js +2 -1
- package/internal/index.js.map +1 -1
- package/internal/state-schema.d.ts +85 -0
- package/internal/state-schema.js +27 -0
- package/internal/state-schema.js.map +1 -0
- package/internal/state-snapshot.d.ts +152 -0
- package/internal/state-snapshot.js +115 -0
- package/internal/state-snapshot.js.map +1 -0
- package/internal/tags.d.ts +1 -0
- package/internal/tags.js +1 -0
- package/internal/tags.js.map +1 -1
- package/internal/types.d.ts +162 -2
- package/internal/types.js.map +1 -1
- package/internal/utils.d.ts +12 -0
- package/internal/utils.js +17 -0
- package/internal/utils.js.map +1 -1
- package/internal/validators.d.ts +31 -0
- package/internal/validators.js +44 -0
- package/internal/validators.js.map +1 -0
- package/package.json +1 -1
- package/styles/_tokens.css.js +1 -1
- package/styles/_tokens.css.js.map +1 -1
- package/styles/body-cell/body-cell.css.js +1 -1
- package/styles/body-cell/body-cell.css.js.map +1 -1
- package/styles/body-row/body-row.css.js +1 -1
- package/styles/body-row/body-row.css.js.map +1 -1
- package/styles/filter-row/filter-row.css.js +1 -1
- package/styles/filter-row/filter-row.css.js.map +1 -1
- package/styles/grid/_grid.base.css.js +1 -1
- package/styles/grid/_grid.base.css.js.map +1 -1
- package/styles/grid/grid.css.js +1 -1
- package/styles/grid/grid.css.js.map +1 -1
- package/styles/group-header-row/group-header-row.css.d.ts +1 -0
- package/styles/group-header-row/group-header-row.css.js +3 -0
- package/styles/group-header-row/group-header-row.css.js.map +1 -0
- package/styles/header-cell/header-cell.css.js +1 -1
- package/styles/header-cell/header-cell.css.js.map +1 -1
- package/styles/header-row/header-row.base.css.js +1 -1
- package/styles/header-row/header-row.base.css.js.map +1 -1
- package/styles/toolbar/toolbar.css.js +1 -1
- package/styles/toolbar/toolbar.css.js.map +1 -1
- package/docs/classes/ApexGrid.html +0 -399
package/controllers/sort.js
CHANGED
|
@@ -75,8 +75,10 @@ export class SortController {
|
|
|
75
75
|
#announce(expression, column) {
|
|
76
76
|
const label = column.headerText ?? String(column.key);
|
|
77
77
|
const message = expression.direction === 'none'
|
|
78
|
-
?
|
|
79
|
-
:
|
|
78
|
+
? this.host.localize('announce.sortCleared', { label })
|
|
79
|
+
: this.host.localize(expression.direction === 'ascending'
|
|
80
|
+
? 'announce.sortedAscending'
|
|
81
|
+
: 'announce.sortedDescending', { label });
|
|
80
82
|
this.host.announce(message);
|
|
81
83
|
}
|
|
82
84
|
#captureRowRects() {
|
|
@@ -108,8 +110,16 @@ export class SortController {
|
|
|
108
110
|
reset(key) {
|
|
109
111
|
key ? this.state.delete(key) : this.state.clear();
|
|
110
112
|
}
|
|
113
|
+
get #rowReorder() {
|
|
114
|
+
return this.host.stateController.rowReorder;
|
|
115
|
+
}
|
|
111
116
|
_sort(expressions) {
|
|
112
|
-
|
|
117
|
+
const exprs = asArray(expressions);
|
|
118
|
+
const reorder = this.#rowReorder;
|
|
119
|
+
if (reorder?.hasManualOrder && exprs.some((expr) => expr.direction !== 'none')) {
|
|
120
|
+
reorder.clearManualOrder(true);
|
|
121
|
+
}
|
|
122
|
+
for (const expr of exprs) {
|
|
113
123
|
this.#setExpression(expr);
|
|
114
124
|
}
|
|
115
125
|
this.host.requestUpdate(PIPELINE);
|
package/controllers/sort.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sort.js","sourceRoot":"","sources":["../../src/controllers/sort.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAuB,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAO5F,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAG/C,MAAM,OAAO,cAAc;IACzB,YAAsB,IAAiB;QAAjB,SAAI,GAAJ,IAAI,CAAa;QAIhC,UAAK,GAAiB,IAAI,GAAG,EAAE,CAAC;QAHrC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IAChC,CAAC;IAID,IAAI,eAAe;QACjB,OAAO,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC;IAC9C,CAAC;IAED,IAAI,eAAe;QACjB,OAAO,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC;IAC9C,CAAC;IAED,mBAAmB,CAAC,OAA8C;QAChE,MAAM,IAAI,GAA0D;YAClE,aAAa,EAAE,KAAK;YACpB,QAAQ,EAAE,SAAS;SACpB,CAAC;QAEF,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,SAAS,EAAE,CAAC;YAC7C,OAAO,IAAkC,CAAC;QAC5C,CAAC;QAED,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE;YACzB,aAAa,EAAE,OAAO,CAAC,aAAa;YACpC,QAAQ,EAAE,OAAO,CAAC,QAAQ;SAC3B,CAA+B,CAAC;IACnC,CAAC;IAED,wBAAwB,CAAC,GAAY;QACnC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC;QAE/C,OAAO;YACL,GAAG;YACH,SAAS,EAAE,WAAW;YACtB,GAAG,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC;SAChB,CAAC;IACzB,CAAC;IAED,QAAQ,CAAC,GAAsB;QAC7B,OAAO,IAAI,CAAC,eAAe;YACzB,CAAC,CAAC,GAAG,KAAK,WAAW;gBACnB,CAAC,CAAC,YAAY;gBACd,CAAC,CAAC,GAAG,KAAK,YAAY;oBACpB,CAAC,CAAC,MAAM;oBACR,CAAC,CAAC,WAAW;YACjB,CAAC,CAAC,GAAG,KAAK,WAAW;gBACnB,CAAC,CAAC,YAAY;gBACd,CAAC,CAAC,WAAW,CAAC;IACpB,CAAC;IAED,iBAAiB,CAAC,MAAyB;QACzC,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;IACtE,CAAC;IAED,gBAAgB,CAAC,MAAyB;QACxC,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;IACnD,CAAC;IAED,cAAc,CAAC,UAA6B;QAC1C,UAAU,CAAC,SAAS,KAAK,MAAM;YAC7B,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC;YAC5B,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,EAAE,EAAE,GAAG,UAAU,EAAE,CAAC,CAAC;IACxD,CAAC;IAEM,KAAK,CAAC,mBAAmB,CAAC,MAA8B,EAAE,QAAQ,GAAG,KAAK;QAC/E,MAAM,UAAU,GAAG,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;QAElD,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,EAAE,CAAC;YACxC,OAAO;QACT,CAAC;QAQD,IAAI,CAAC,IAAI,CAAC,eAAe,IAAI,CAAC,QAAQ,EAAE,CAAC;YACvC,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,CAAC;QAMD,MAAM,WAAW,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAE5C,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QAEvB,MAAM,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC;QAI/B,MAAM,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC;QAC/B,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QACnC,IAAI,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC;IACpC,CAAC;IAED,SAAS,CAAC,UAA6B,EAAE,MAA8B;QACrE,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,IAAI,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACtD,MAAM,OAAO,GACX,UAAU,CAAC,SAAS,KAAK,MAAM;YAC7B,CAAC,CAAC,mBAAmB,KAAK,EAAE;YAC5B,CAAC,CAAC,aAAa,KAAK,IAAI,UAAU,CAAC,SAAS,EAAE,CAAC;QACnD,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC9B,CAAC;IAED,gBAAgB;QACd,MAAM,OAAO,GAAwB,EAAE,CAAC;QACxC,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACjC,MAAM,EAAE,GAAG,GAA6B,CAAC;YACzC,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,qBAAqB,EAAE,EAAE,CAAC,CAAC;QACpE,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,YAAY,CAAC,MAAwC;QAGnD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;QAC5B,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;QACzC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,GAA6B,CAAC,CAAC;QACtD,CAAC;QACD,aAAa,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,GAAG,CAAC,CAAC;IACjE,CAAC;IAEM,iBAAiB,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAA0B;QACrE,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACxB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC;YAElC,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE;gBACzB,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC;gBACxC,GAAG,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC;aACrC,CAAC,CAAC;QACL,CAAC;QAGD,OAAO,IAAI,CAAC,wBAAwB,CAAC,GAAG,CAAC,CAAC;IAC5C,CAAC;IAEM,KAAK,CAAC,GAAa;QACxB,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACpD,CAAC;IAES,KAAK,CAAC,WAAoD;QAClE,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC;YACxC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;IACpC,CAAC;IAEM,IAAI,CAAC,WAAoD;QAC9D,IAAI,CAAC,KAAK,CACR,OAAO,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAChC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,wBAAwB,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CACzF,CACF,CAAC;IACJ,CAAC;IAEM,aAAa,KAAI,CAAC;CAC1B","sourcesContent":["import type { ReactiveController } from 'lit';\nimport { PIPELINE } from '../internal/constants.js';\nimport { awaitChildUpdates, type KeyedFlipEntry, playKeyedFlip } from '../internal/flip.js';\nimport type {\n ColumnConfiguration,\n ColumnSortConfiguration,\n GridHost,\n Keys,\n} from '../internal/types.js';\nimport { asArray } from '../internal/utils.js';\nimport type { SortExpression, SortingDirection, SortState } from '../operations/sort/types.js';\n\nexport class SortController<T extends object> implements ReactiveController {\n constructor(protected host: GridHost<T>) {\n this.host.addController(this);\n }\n\n public state: SortState<T> = new Map();\n\n get #isMultipleSort() {\n return this.host.sortConfiguration.multiple;\n }\n\n get #isTriStateSort() {\n return this.host.sortConfiguration.triState;\n }\n\n #resolveSortOptions(options?: boolean | ColumnSortConfiguration<T>) {\n const expr: Pick<SortExpression<T>, 'caseSensitive' | 'comparer'> = {\n caseSensitive: false,\n comparer: undefined,\n };\n\n if (!options || typeof options === 'boolean') {\n return expr as Partial<SortExpression<T>>;\n }\n\n return Object.assign(expr, {\n caseSensitive: options.caseSensitive,\n comparer: options.comparer,\n }) as Partial<SortExpression<T>>;\n }\n\n #createDefaultExpression(key: Keys<T>) {\n const options = this.host.getColumn(key)?.sort;\n\n return {\n key,\n direction: 'ascending',\n ...this.#resolveSortOptions(options),\n } as SortExpression<T>;\n }\n\n #orderBy(dir?: SortingDirection): SortingDirection {\n return this.#isTriStateSort\n ? dir === 'ascending'\n ? 'descending'\n : dir === 'descending'\n ? 'none'\n : 'ascending'\n : dir === 'ascending'\n ? 'descending'\n : 'ascending';\n }\n\n #emitSortingEvent(detail: SortExpression<T>) {\n return this.host.emitEvent('sorting', { detail, cancelable: true });\n }\n\n #emitSortedEvent(detail: SortExpression<T>) {\n return this.host.emitEvent('sorted', { detail });\n }\n\n #setExpression(expression: SortExpression<T>) {\n expression.direction === 'none'\n ? this.reset(expression.key)\n : this.state.set(expression.key, { ...expression });\n }\n\n public async sortFromHeaderClick(column: ColumnConfiguration<T>, additive = false) {\n const expression = this.prepareExpression(column);\n\n if (!this.#emitSortingEvent(expression)) {\n return;\n }\n\n // A plain click sorts by this column alone, clearing any other sorted\n // columns. Only a Ctrl/Cmd+click while multi-sort is enabled keeps the\n // existing sort keys and appends this column as an additional, lower-\n // priority sort. Without this gate every plain click would accumulate a\n // key, so a second column added behind a unique primary column would not\n // change the visible order at all.\n if (!this.#isMultipleSort || !additive) {\n this.reset();\n }\n\n // Capture visible-row rects keyed by data identity BEFORE the pipeline\n // runs. After the new render the virtualizer will have repositioned\n // rows; we use those captured rects as the \"First\" of a FLIP and\n // animate each row from its old viewport position back to identity.\n const beforeRects = this.#captureRowRects();\n\n this._sort(expression);\n\n await this.host.updateComplete;\n // Wait for body row updates so the new data is committed to each row\n // element before measuring the \"Last\" rect — otherwise the captured-\n // before and measured-after rects match and the animation no-ops.\n await awaitChildUpdates(this.host.rows);\n this.#playRowFlip(beforeRects);\n this.#announce(expression, column);\n this.#emitSortedEvent(expression);\n }\n\n #announce(expression: SortExpression<T>, column: ColumnConfiguration<T>) {\n const label = column.headerText ?? String(column.key);\n const message =\n expression.direction === 'none'\n ? `Sort cleared on ${label}`\n : `Sorted by ${label} ${expression.direction}`;\n this.host.announce(message);\n }\n\n #captureRowRects(): KeyedFlipEntry<T>[] {\n const entries: KeyedFlipEntry<T>[] = [];\n for (const row of this.host.rows) {\n const el = row as unknown as HTMLElement;\n entries.push({ key: row.data, rect: el.getBoundingClientRect() });\n }\n return entries;\n }\n\n #playRowFlip(before: ReadonlyArray<KeyedFlipEntry<T>>) {\n // After sort, the same data may be rendered by a different `<apex-grid-row>`\n // DOM element (virtualizer recycles rows). Resolve by data identity.\n const rows = this.host.rows;\n const byData = new Map<T, HTMLElement>();\n for (const row of rows) {\n byData.set(row.data, row as unknown as HTMLElement);\n }\n playKeyedFlip(before, (data) => byData.get(data) ?? null, 'y');\n }\n\n public prepareExpression({ key, sort: options }: ColumnConfiguration<T>): SortExpression<T> {\n if (this.state.has(key)) {\n const expr = this.state.get(key)!;\n\n return Object.assign(expr, {\n direction: this.#orderBy(expr.direction),\n ...this.#resolveSortOptions(options),\n });\n }\n\n // Initial state\n return this.#createDefaultExpression(key);\n }\n\n public reset(key?: Keys<T>) {\n key ? this.state.delete(key) : this.state.clear();\n }\n\n protected _sort(expressions: SortExpression<T> | SortExpression<T>[]) {\n for (const expr of asArray(expressions)) {\n this.#setExpression(expr);\n }\n\n this.host.requestUpdate(PIPELINE);\n }\n\n public sort(expressions: SortExpression<T> | SortExpression<T>[]) {\n this._sort(\n asArray(expressions).map((expr) =>\n Object.assign(this.state.get(expr.key) ?? this.#createDefaultExpression(expr.key), expr)\n )\n );\n }\n\n public hostConnected() {}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"sort.js","sourceRoot":"","sources":["../../src/controllers/sort.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ReactiveController } from 'lit';\nimport { PIPELINE } from '../internal/constants.js';\nimport { awaitChildUpdates, type KeyedFlipEntry, playKeyedFlip } from '../internal/flip.js';\nimport type {\n ColumnConfiguration,\n ColumnSortConfiguration,\n GridHost,\n Keys,\n} from '../internal/types.js';\nimport { asArray } from '../internal/utils.js';\nimport type { SortExpression, SortingDirection, SortState } from '../operations/sort/types.js';\n\nexport class SortController<T extends object> implements ReactiveController {\n constructor(protected host: GridHost<T>) {\n this.host.addController(this);\n }\n\n public state: SortState<T> = new Map();\n\n get #isMultipleSort() {\n return this.host.sortConfiguration.multiple;\n }\n\n get #isTriStateSort() {\n return this.host.sortConfiguration.triState;\n }\n\n #resolveSortOptions(options?: boolean | ColumnSortConfiguration<T>) {\n const expr: Pick<SortExpression<T>, 'caseSensitive' | 'comparer'> = {\n caseSensitive: false,\n comparer: undefined,\n };\n\n if (!options || typeof options === 'boolean') {\n return expr as Partial<SortExpression<T>>;\n }\n\n return Object.assign(expr, {\n caseSensitive: options.caseSensitive,\n comparer: options.comparer,\n }) as Partial<SortExpression<T>>;\n }\n\n #createDefaultExpression(key: Keys<T>) {\n const options = this.host.getColumn(key)?.sort;\n\n return {\n key,\n direction: 'ascending',\n ...this.#resolveSortOptions(options),\n } as SortExpression<T>;\n }\n\n #orderBy(dir?: SortingDirection): SortingDirection {\n return this.#isTriStateSort\n ? dir === 'ascending'\n ? 'descending'\n : dir === 'descending'\n ? 'none'\n : 'ascending'\n : dir === 'ascending'\n ? 'descending'\n : 'ascending';\n }\n\n #emitSortingEvent(detail: SortExpression<T>) {\n return this.host.emitEvent('sorting', { detail, cancelable: true });\n }\n\n #emitSortedEvent(detail: SortExpression<T>) {\n return this.host.emitEvent('sorted', { detail });\n }\n\n #setExpression(expression: SortExpression<T>) {\n expression.direction === 'none'\n ? this.reset(expression.key)\n : this.state.set(expression.key, { ...expression });\n }\n\n public async sortFromHeaderClick(column: ColumnConfiguration<T>, additive = false) {\n const expression = this.prepareExpression(column);\n\n if (!this.#emitSortingEvent(expression)) {\n return;\n }\n\n // A plain click sorts by this column alone, clearing any other sorted\n // columns. Only a Ctrl/Cmd+click while multi-sort is enabled keeps the\n // existing sort keys and appends this column as an additional, lower-\n // priority sort. Without this gate every plain click would accumulate a\n // key, so a second column added behind a unique primary column would not\n // change the visible order at all.\n if (!this.#isMultipleSort || !additive) {\n this.reset();\n }\n\n // Capture visible-row rects keyed by data identity BEFORE the pipeline\n // runs. After the new render the virtualizer will have repositioned\n // rows; we use those captured rects as the \"First\" of a FLIP and\n // animate each row from its old viewport position back to identity.\n const beforeRects = this.#captureRowRects();\n\n this._sort(expression);\n\n await this.host.updateComplete;\n // Wait for body row updates so the new data is committed to each row\n // element before measuring the \"Last\" rect — otherwise the captured-\n // before and measured-after rects match and the animation no-ops.\n await awaitChildUpdates(this.host.rows);\n this.#playRowFlip(beforeRects);\n this.#announce(expression, column);\n this.#emitSortedEvent(expression);\n }\n\n #announce(expression: SortExpression<T>, column: ColumnConfiguration<T>) {\n const label = column.headerText ?? String(column.key);\n const message =\n expression.direction === 'none'\n ? this.host.localize('announce.sortCleared', { label })\n : this.host.localize(\n expression.direction === 'ascending'\n ? 'announce.sortedAscending'\n : 'announce.sortedDescending',\n { label }\n );\n this.host.announce(message);\n }\n\n #captureRowRects(): KeyedFlipEntry<T>[] {\n const entries: KeyedFlipEntry<T>[] = [];\n for (const row of this.host.rows) {\n const el = row as unknown as HTMLElement;\n entries.push({ key: row.data, rect: el.getBoundingClientRect() });\n }\n return entries;\n }\n\n #playRowFlip(before: ReadonlyArray<KeyedFlipEntry<T>>) {\n // After sort, the same data may be rendered by a different `<apex-grid-row>`\n // DOM element (virtualizer recycles rows). Resolve by data identity.\n const rows = this.host.rows;\n const byData = new Map<T, HTMLElement>();\n for (const row of rows) {\n byData.set(row.data, row as unknown as HTMLElement);\n }\n playKeyedFlip(before, (data) => byData.get(data) ?? null, 'y');\n }\n\n public prepareExpression({ key, sort: options }: ColumnConfiguration<T>): SortExpression<T> {\n if (this.state.has(key)) {\n const expr = this.state.get(key)!;\n\n return Object.assign(expr, {\n direction: this.#orderBy(expr.direction),\n ...this.#resolveSortOptions(options),\n });\n }\n\n // Initial state\n return this.#createDefaultExpression(key);\n }\n\n public reset(key?: Keys<T>) {\n key ? this.state.delete(key) : this.state.clear();\n }\n\n get #rowReorder() {\n // @ts-expect-error - protected member access\n return this.host.stateController.rowReorder as\n | { hasManualOrder: boolean; clearManualOrder(announce?: boolean): void }\n | undefined;\n }\n\n protected _sort(expressions: SortExpression<T> | SortExpression<T>[]) {\n const exprs = asArray(expressions);\n // Applying a sort is mutually exclusive with a manual row order (F5):\n // a real sort (any non-`none` direction) clears it, with an announcement.\n const reorder = this.#rowReorder;\n if (reorder?.hasManualOrder && exprs.some((expr) => expr.direction !== 'none')) {\n reorder.clearManualOrder(true);\n }\n\n for (const expr of exprs) {\n this.#setExpression(expr);\n }\n\n this.host.requestUpdate(PIPELINE);\n }\n\n public sort(expressions: SortExpression<T> | SortExpression<T>[]) {\n this._sort(\n asArray(expressions).map((expr) =>\n Object.assign(this.state.get(expr.key) ?? this.#createDefaultExpression(expr.key), expr)\n )\n );\n }\n\n public hostConnected() {}\n}\n"]}
|
package/controllers/state.d.ts
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import type { ReactiveController } from 'lit';
|
|
2
|
+
import type { GridLocaleKey, LocaleParams } from '../i18n/index.js';
|
|
2
3
|
import { type CellDecoration, type CellDecoratorContext, type CellInteraction, type GridFeatureModule, type PresentedRow, type RowPresenterContext } from '../internal/feature-module.js';
|
|
3
4
|
import type { ActiveNode, GridHost } from '../internal/types.js';
|
|
4
5
|
import { EditingController } from './editing.js';
|
|
5
6
|
import { ExpansionController } from './expansion.js';
|
|
6
7
|
import { FilterController } from './filter.js';
|
|
8
|
+
import { HistoryController } from './history.js';
|
|
7
9
|
import { NavigationController } from './navigation.js';
|
|
8
10
|
import { PaginationController } from './pagination.js';
|
|
9
11
|
import { ReorderController } from './reorder.js';
|
|
10
12
|
import { ResizeController } from './resize.js';
|
|
13
|
+
import { RowPinController } from './row-pin.js';
|
|
14
|
+
import { RowReorderController } from './row-reorder.js';
|
|
11
15
|
import { SelectionController } from './selection.js';
|
|
12
16
|
import { SortController } from './sort.js';
|
|
13
17
|
import { TreeController } from './tree.js';
|
|
@@ -22,9 +26,12 @@ export declare class StateController<T extends object> implements ReactiveContro
|
|
|
22
26
|
pagination: PaginationController<T>;
|
|
23
27
|
reordering: ReorderController<T>;
|
|
24
28
|
editing: EditingController<T>;
|
|
29
|
+
history: HistoryController<T>;
|
|
25
30
|
selection: SelectionController<T>;
|
|
26
31
|
expansion: ExpansionController<T>;
|
|
27
32
|
tree: TreeController<T>;
|
|
33
|
+
rowPin: RowPinController<T>;
|
|
34
|
+
rowReorder: RowReorderController<T>;
|
|
28
35
|
/**
|
|
29
36
|
* Optional feature controllers contributed by {@link GridFeatureModule}s,
|
|
30
37
|
* keyed by module id. Empty for the community `<apex-grid>` element; populated
|
|
@@ -44,6 +51,12 @@ export declare class StateController<T extends object> implements ReactiveContro
|
|
|
44
51
|
* so two identical sort announcements wouldn't otherwise be read aloud.
|
|
45
52
|
*/
|
|
46
53
|
setAnnouncement(message: string): void;
|
|
54
|
+
/**
|
|
55
|
+
* Resolves a built-in locale key to its display string, honoring the host
|
|
56
|
+
* grid's {@link ApexGrid.localeText} overrides. Thin proxy to
|
|
57
|
+
* {@link ApexGrid.localize} so components can localize via `this.state`.
|
|
58
|
+
*/
|
|
59
|
+
localize(key: GridLocaleKey, params?: LocaleParams, fallback?: string): string;
|
|
47
60
|
get active(): ActiveNode<T>;
|
|
48
61
|
set active(node: ActiveNode<T>);
|
|
49
62
|
get headerRow(): import("../components/header-row.js").default<T>;
|
|
@@ -82,6 +95,14 @@ export declare class StateController<T extends object> implements ReactiveContro
|
|
|
82
95
|
* decoration. Called by feature modules after mutating decoration state.
|
|
83
96
|
*/
|
|
84
97
|
bumpDecoration(): void;
|
|
98
|
+
/**
|
|
99
|
+
* Whether any feature module implementing {@link ColumnMenuProvider} offers a
|
|
100
|
+
* column header menu. The header uses this to show its kebab button even on
|
|
101
|
+
* columns that are neither sortable nor resizable, so a module (the enterprise
|
|
102
|
+
* context menu) can surface pin / hide / group / chart actions. Always `false`
|
|
103
|
+
* for the community grid (no modules).
|
|
104
|
+
*/
|
|
105
|
+
get hasColumnMenu(): boolean;
|
|
85
106
|
/**
|
|
86
107
|
* Collects per-cell decoration contributed by feature modules implementing
|
|
87
108
|
* {@link CellDecorator}, merging their attribute maps (later modules win on a
|
|
@@ -95,6 +116,18 @@ export declare class StateController<T extends object> implements ReactiveContro
|
|
|
95
116
|
* (no modules); the grid only calls this when modules are registered.
|
|
96
117
|
*/
|
|
97
118
|
handleCellInteraction(interaction: CellInteraction<T>): void;
|
|
119
|
+
/**
|
|
120
|
+
* Collects per-module snapshot state from feature controllers implementing
|
|
121
|
+
* {@link SerializableModule}, keyed by module id. Returns an empty object for
|
|
122
|
+
* the community grid (no modules). Used by `ApexGrid.getState`.
|
|
123
|
+
*/
|
|
124
|
+
serializeModuleState(): Record<string, unknown>;
|
|
125
|
+
/**
|
|
126
|
+
* Dispatches previously-serialized state back to the matching feature modules
|
|
127
|
+
* (by id) that implement {@link SerializableModule}. Missing ids and unknown
|
|
128
|
+
* modules are ignored. Used by `ApexGrid.setState`.
|
|
129
|
+
*/
|
|
130
|
+
restoreModuleState(data: Record<string, unknown> | undefined): void;
|
|
98
131
|
hostConnected(): void;
|
|
99
132
|
hostUpdate(): void;
|
|
100
133
|
}
|
package/controllers/state.js
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import { createContext } from '@lit/context';
|
|
2
|
-
import { isCellDecorator, isCellInteractionHandler, isRowPresenter, isRowTransformer, } from '../internal/feature-module.js';
|
|
2
|
+
import { isCellDecorator, isCellInteractionHandler, isColumnMenuProvider, isRowPresenter, isRowTransformer, isSerializableModule, } from '../internal/feature-module.js';
|
|
3
3
|
import { EditingController } from './editing.js';
|
|
4
4
|
import { ExpansionController } from './expansion.js';
|
|
5
5
|
import { FilterController } from './filter.js';
|
|
6
|
+
import { HistoryController } from './history.js';
|
|
6
7
|
import { NavigationController } from './navigation.js';
|
|
7
8
|
import { PaginationController } from './pagination.js';
|
|
8
9
|
import { ReorderController } from './reorder.js';
|
|
9
10
|
import { ResizeController } from './resize.js';
|
|
11
|
+
import { RowPinController } from './row-pin.js';
|
|
12
|
+
import { RowReorderController } from './row-reorder.js';
|
|
10
13
|
import { SelectionController } from './selection.js';
|
|
11
14
|
import { SortController } from './sort.js';
|
|
12
15
|
import { TreeController } from './tree.js';
|
|
@@ -22,6 +25,9 @@ export class StateController {
|
|
|
22
25
|
this.announcement = this.#announceToken ? message : `${message} `;
|
|
23
26
|
this.host.requestUpdate();
|
|
24
27
|
}
|
|
28
|
+
localize(key, params, fallback) {
|
|
29
|
+
return this.host.localize(key, params, fallback);
|
|
30
|
+
}
|
|
25
31
|
get active() {
|
|
26
32
|
return this.navigation.active;
|
|
27
33
|
}
|
|
@@ -61,10 +67,13 @@ export class StateController {
|
|
|
61
67
|
this.resizing = new ResizeController(this.host);
|
|
62
68
|
this.pagination = new PaginationController(this.host);
|
|
63
69
|
this.reordering = new ReorderController(this.host);
|
|
64
|
-
this.
|
|
70
|
+
this.history = new HistoryController(this.host);
|
|
71
|
+
this.editing = new EditingController(this.host, this.history);
|
|
65
72
|
this.selection = new SelectionController(this.host);
|
|
66
73
|
this.expansion = new ExpansionController(this.host);
|
|
67
74
|
this.tree = new TreeController(this.host);
|
|
75
|
+
this.rowPin = new RowPinController(this.host);
|
|
76
|
+
this.rowReorder = new RowReorderController(this.host);
|
|
68
77
|
for (const module of this.extraModules) {
|
|
69
78
|
if (this.modules.has(module.id))
|
|
70
79
|
continue;
|
|
@@ -101,6 +110,14 @@ export class StateController {
|
|
|
101
110
|
this.#decorationVersion += 1;
|
|
102
111
|
this.host.requestUpdate();
|
|
103
112
|
}
|
|
113
|
+
get hasColumnMenu() {
|
|
114
|
+
for (const controller of this.modules.values()) {
|
|
115
|
+
if (isColumnMenuProvider(controller) && controller.providesColumnMenu()) {
|
|
116
|
+
return true;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
104
121
|
decorateCell(ctx) {
|
|
105
122
|
let attributes = null;
|
|
106
123
|
for (const controller of this.modules.values()) {
|
|
@@ -121,6 +138,24 @@ export class StateController {
|
|
|
121
138
|
}
|
|
122
139
|
}
|
|
123
140
|
}
|
|
141
|
+
serializeModuleState() {
|
|
142
|
+
const out = {};
|
|
143
|
+
for (const [id, controller] of this.modules) {
|
|
144
|
+
if (isSerializableModule(controller)) {
|
|
145
|
+
out[id] = controller.serializeState();
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return out;
|
|
149
|
+
}
|
|
150
|
+
restoreModuleState(data) {
|
|
151
|
+
if (!data)
|
|
152
|
+
return;
|
|
153
|
+
for (const [id, controller] of this.modules) {
|
|
154
|
+
if (isSerializableModule(controller) && Object.hasOwn(data, id)) {
|
|
155
|
+
controller.restoreState(data[id]);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
124
159
|
hostConnected() { }
|
|
125
160
|
hostUpdate() {
|
|
126
161
|
this.headerRow?.requestUpdate();
|
package/controllers/state.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/controllers/state.ts"],"names":[],"mappings":"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","sourcesContent":["import { createContext } from '@lit/context';\nimport type { ReactiveController } from 'lit';\nimport {\n type CellDecoration,\n type CellDecoratorContext,\n type CellInteraction,\n type GridFeatureModule,\n isCellDecorator,\n isCellInteractionHandler,\n isRowPresenter,\n isRowTransformer,\n type PresentedRow,\n type RowPresenterContext,\n} from '../internal/feature-module.js';\nimport type { ActiveNode, GridHost } from '../internal/types.js';\nimport { EditingController } from './editing.js';\nimport { ExpansionController } from './expansion.js';\nimport { FilterController } from './filter.js';\nimport { NavigationController } from './navigation.js';\nimport { PaginationController } from './pagination.js';\nimport { ReorderController } from './reorder.js';\nimport { ResizeController } from './resize.js';\nimport { SelectionController } from './selection.js';\nimport { SortController } from './sort.js';\nimport { TreeController } from './tree.js';\n\nexport class StateController<T extends object> implements ReactiveController {\n public sorting!: SortController<T>;\n public filtering!: FilterController<T>;\n public navigation!: NavigationController<T>;\n public resizing!: ResizeController<T>;\n public pagination!: PaginationController<T>;\n public reordering!: ReorderController<T>;\n public editing!: EditingController<T>;\n public selection!: SelectionController<T>;\n public expansion!: ExpansionController<T>;\n public tree!: TreeController<T>;\n\n /**\n * Optional feature controllers contributed by {@link GridFeatureModule}s,\n * keyed by module id. Empty for the community `<apex-grid>` element; populated\n * by derived grids (e.g. `@apexcharts/grid-enterprise`) that pass modules to\n * the constructor.\n */\n public readonly modules = new Map<string, ReactiveController>();\n\n /**\n * Current message in the grid's polite live region. Bound by the host's\n * `renderLiveRegion()` template; mutated through {@link setAnnouncement}\n * so screen readers re-announce on every change.\n */\n public announcement = '';\n #announceToken = 0;\n\n /**\n * Updates the polite live region's text. Repeats are forced to fire by\n * appending a zero-width space — screen readers ignore unchanged content,\n * so two identical sort announcements wouldn't otherwise be read aloud.\n */\n public setAnnouncement(message: string): void {\n if (!message) {\n this.announcement = '';\n this.host.requestUpdate();\n return;\n }\n this.#announceToken = (this.#announceToken + 1) % 2;\n this.announcement = this.#announceToken ? message : `${message} `;\n this.host.requestUpdate();\n }\n\n public get active() {\n return this.navigation.active;\n }\n\n public set active(node: ActiveNode<T>) {\n this.navigation.active = node;\n }\n\n public get headerRow() {\n // @ts-expect-error - Protected member access\n return this.host.headerRow;\n }\n\n public get scrollContainer() {\n // @ts-expect-error - Protected member access\n return this.host.scrollContainer;\n }\n\n public get paginator() {\n // @ts-expect-error - Protected member access\n return this.host.paginator;\n }\n\n public get toolbar() {\n // @ts-expect-error - Protected member access\n return this.host.toolbar;\n }\n\n /**\n * Cumulative pin offsets (in px) keyed by column key. Populated by the\n * {@link GridDOMController} after each layout.\n */\n public get pinOffsets(): Map<unknown, number> {\n // @ts-expect-error - Protected member access\n const dom = this.host.DOM as { pinOffsets?: Map<unknown, number> } | undefined;\n return dom?.pinOffsets ?? new Map();\n }\n\n constructor(\n public host: GridHost<T>,\n private extraModules: ReadonlyArray<GridFeatureModule<T>> = []\n ) {\n this.host.addController(this);\n this.init();\n }\n\n protected init() {\n this.sorting = new SortController(this.host);\n this.filtering = new FilterController(this.host);\n this.navigation = new NavigationController(this.host);\n this.resizing = new ResizeController(this.host);\n this.pagination = new PaginationController(this.host);\n this.reordering = new ReorderController(this.host);\n this.editing = new EditingController(this.host);\n this.selection = new SelectionController(this.host);\n this.expansion = new ExpansionController(this.host);\n this.tree = new TreeController(this.host);\n\n for (const module of this.extraModules) {\n if (this.modules.has(module.id)) continue;\n this.modules.set(module.id, module.create(this.host, this));\n }\n }\n\n /**\n * Look up a feature controller contributed by a {@link GridFeatureModule},\n * by its module id. Returns `undefined` when no such module is registered.\n */\n public module<C extends ReactiveController>(id: string): C | undefined {\n return this.modules.get(id) as C | undefined;\n }\n\n /**\n * Runs the post-pipeline row transforms contributed by feature modules\n * implementing {@link RowTransformer}, in registration order. Returns the\n * input unchanged when no such module is registered — the community grid path\n * is a no-op pass-through.\n */\n public applyModuleTransforms(rows: T[]): T[] {\n let result = rows;\n for (const controller of this.modules.values()) {\n if (isRowTransformer<T>(controller)) {\n result = controller.processRows(result);\n }\n }\n return result;\n }\n\n /**\n * Asks feature modules implementing {@link RowPresenter} whether they render\n * the given row as full-width custom content (e.g. a group header). Returns\n * the first non-null result, or `null` when no module owns the row.\n */\n public presentRow(row: T, ctx: RowPresenterContext<T>): PresentedRow | null {\n for (const controller of this.modules.values()) {\n if (isRowPresenter<T>(controller)) {\n const presented = controller.presentRow(row, ctx);\n if (presented) return presented;\n }\n }\n return null;\n }\n\n /**\n * Monotonic token bumped by {@link bumpDecoration} whenever module-driven cell\n * decoration changes. Forwarded down to each cell as a reactive property so a\n * decoration-only change (e.g. dragging a selection range) re-renders cells\n * without re-running the data pipeline. Always `0` for the community grid.\n */\n #decorationVersion = 0;\n\n public get decorationVersion(): number {\n return this.#decorationVersion;\n }\n\n /**\n * Signals that {@link CellDecorator} output may have changed. Bumps the\n * {@link decorationVersion} and requests a host update so cells re-run their\n * decoration. Called by feature modules after mutating decoration state.\n */\n public bumpDecoration(): void {\n this.#decorationVersion += 1;\n this.host.requestUpdate();\n }\n\n /**\n * Collects per-cell decoration contributed by feature modules implementing\n * {@link CellDecorator}, merging their attribute maps (later modules win on a\n * key clash). Returns `null` when no module decorates the cell — the community\n * grid path, where each cell applies nothing.\n */\n public decorateCell(ctx: CellDecoratorContext<T>): CellDecoration | null {\n let attributes: Record<string, string | null | undefined> | null = null;\n for (const controller of this.modules.values()) {\n if (isCellDecorator<T>(controller)) {\n const decoration = controller.decorateCell(ctx);\n if (decoration) {\n attributes ??= {};\n Object.assign(attributes, decoration.attributes);\n }\n }\n }\n return attributes ? { attributes } : null;\n }\n\n /**\n * Forwards a body-cell pointer interaction to every feature module that\n * implements {@link CellInteractionHandler}. No-op for the community grid\n * (no modules); the grid only calls this when modules are registered.\n */\n public handleCellInteraction(interaction: CellInteraction<T>): void {\n for (const controller of this.modules.values()) {\n if (isCellInteractionHandler<T>(controller)) {\n controller.handleCellInteraction(interaction);\n }\n }\n }\n\n public hostConnected() {}\n\n public hostUpdate(): void {\n this.headerRow?.requestUpdate();\n this.scrollContainer?.requestUpdate();\n this.paginator?.requestUpdate();\n this.toolbar?.requestUpdate();\n }\n}\n\nexport const gridStateContext = createContext<StateController<any>>('gridStateController');\n"]}
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/controllers/state.ts"],"names":[],"mappings":"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","sourcesContent":["import { createContext } from '@lit/context';\nimport type { ReactiveController } from 'lit';\nimport type { GridLocaleKey, LocaleParams } from '../i18n/index.js';\nimport {\n type CellDecoration,\n type CellDecoratorContext,\n type CellInteraction,\n type GridFeatureModule,\n isCellDecorator,\n isCellInteractionHandler,\n isColumnMenuProvider,\n isRowPresenter,\n isRowTransformer,\n isSerializableModule,\n type PresentedRow,\n type RowPresenterContext,\n} from '../internal/feature-module.js';\nimport type { ActiveNode, GridHost } from '../internal/types.js';\nimport { EditingController } from './editing.js';\nimport { ExpansionController } from './expansion.js';\nimport { FilterController } from './filter.js';\nimport { HistoryController } from './history.js';\nimport { NavigationController } from './navigation.js';\nimport { PaginationController } from './pagination.js';\nimport { ReorderController } from './reorder.js';\nimport { ResizeController } from './resize.js';\nimport { RowPinController } from './row-pin.js';\nimport { RowReorderController } from './row-reorder.js';\nimport { SelectionController } from './selection.js';\nimport { SortController } from './sort.js';\nimport { TreeController } from './tree.js';\n\nexport class StateController<T extends object> implements ReactiveController {\n public sorting!: SortController<T>;\n public filtering!: FilterController<T>;\n public navigation!: NavigationController<T>;\n public resizing!: ResizeController<T>;\n public pagination!: PaginationController<T>;\n public reordering!: ReorderController<T>;\n public editing!: EditingController<T>;\n public history!: HistoryController<T>;\n public selection!: SelectionController<T>;\n public expansion!: ExpansionController<T>;\n public tree!: TreeController<T>;\n public rowPin!: RowPinController<T>;\n public rowReorder!: RowReorderController<T>;\n\n /**\n * Optional feature controllers contributed by {@link GridFeatureModule}s,\n * keyed by module id. Empty for the community `<apex-grid>` element; populated\n * by derived grids (e.g. `@apexcharts/grid-enterprise`) that pass modules to\n * the constructor.\n */\n public readonly modules = new Map<string, ReactiveController>();\n\n /**\n * Current message in the grid's polite live region. Bound by the host's\n * `renderLiveRegion()` template; mutated through {@link setAnnouncement}\n * so screen readers re-announce on every change.\n */\n public announcement = '';\n #announceToken = 0;\n\n /**\n * Updates the polite live region's text. Repeats are forced to fire by\n * appending a zero-width space — screen readers ignore unchanged content,\n * so two identical sort announcements wouldn't otherwise be read aloud.\n */\n public setAnnouncement(message: string): void {\n if (!message) {\n this.announcement = '';\n this.host.requestUpdate();\n return;\n }\n this.#announceToken = (this.#announceToken + 1) % 2;\n this.announcement = this.#announceToken ? message : `${message} `;\n this.host.requestUpdate();\n }\n\n /**\n * Resolves a built-in locale key to its display string, honoring the host\n * grid's {@link ApexGrid.localeText} overrides. Thin proxy to\n * {@link ApexGrid.localize} so components can localize via `this.state`.\n */\n public localize(key: GridLocaleKey, params?: LocaleParams, fallback?: string): string {\n return this.host.localize(key, params, fallback);\n }\n\n public get active() {\n return this.navigation.active;\n }\n\n public set active(node: ActiveNode<T>) {\n this.navigation.active = node;\n }\n\n public get headerRow() {\n // @ts-expect-error - Protected member access\n return this.host.headerRow;\n }\n\n public get scrollContainer() {\n // @ts-expect-error - Protected member access\n return this.host.scrollContainer;\n }\n\n public get paginator() {\n // @ts-expect-error - Protected member access\n return this.host.paginator;\n }\n\n public get toolbar() {\n // @ts-expect-error - Protected member access\n return this.host.toolbar;\n }\n\n /**\n * Cumulative pin offsets (in px) keyed by column key. Populated by the\n * {@link GridDOMController} after each layout.\n */\n public get pinOffsets(): Map<unknown, number> {\n // @ts-expect-error - Protected member access\n const dom = this.host.DOM as { pinOffsets?: Map<unknown, number> } | undefined;\n return dom?.pinOffsets ?? new Map();\n }\n\n constructor(\n public host: GridHost<T>,\n private extraModules: ReadonlyArray<GridFeatureModule<T>> = []\n ) {\n this.host.addController(this);\n this.init();\n }\n\n protected init() {\n this.sorting = new SortController(this.host);\n this.filtering = new FilterController(this.host);\n this.navigation = new NavigationController(this.host);\n this.resizing = new ResizeController(this.host);\n this.pagination = new PaginationController(this.host);\n this.reordering = new ReorderController(this.host);\n this.history = new HistoryController(this.host);\n this.editing = new EditingController(this.host, this.history);\n this.selection = new SelectionController(this.host);\n this.expansion = new ExpansionController(this.host);\n this.tree = new TreeController(this.host);\n this.rowPin = new RowPinController(this.host);\n this.rowReorder = new RowReorderController(this.host);\n\n for (const module of this.extraModules) {\n if (this.modules.has(module.id)) continue;\n this.modules.set(module.id, module.create(this.host, this));\n }\n }\n\n /**\n * Look up a feature controller contributed by a {@link GridFeatureModule},\n * by its module id. Returns `undefined` when no such module is registered.\n */\n public module<C extends ReactiveController>(id: string): C | undefined {\n return this.modules.get(id) as C | undefined;\n }\n\n /**\n * Runs the post-pipeline row transforms contributed by feature modules\n * implementing {@link RowTransformer}, in registration order. Returns the\n * input unchanged when no such module is registered — the community grid path\n * is a no-op pass-through.\n */\n public applyModuleTransforms(rows: T[]): T[] {\n let result = rows;\n for (const controller of this.modules.values()) {\n if (isRowTransformer<T>(controller)) {\n result = controller.processRows(result);\n }\n }\n return result;\n }\n\n /**\n * Asks feature modules implementing {@link RowPresenter} whether they render\n * the given row as full-width custom content (e.g. a group header). Returns\n * the first non-null result, or `null` when no module owns the row.\n */\n public presentRow(row: T, ctx: RowPresenterContext<T>): PresentedRow | null {\n for (const controller of this.modules.values()) {\n if (isRowPresenter<T>(controller)) {\n const presented = controller.presentRow(row, ctx);\n if (presented) return presented;\n }\n }\n return null;\n }\n\n /**\n * Monotonic token bumped by {@link bumpDecoration} whenever module-driven cell\n * decoration changes. Forwarded down to each cell as a reactive property so a\n * decoration-only change (e.g. dragging a selection range) re-renders cells\n * without re-running the data pipeline. Always `0` for the community grid.\n */\n #decorationVersion = 0;\n\n public get decorationVersion(): number {\n return this.#decorationVersion;\n }\n\n /**\n * Signals that {@link CellDecorator} output may have changed. Bumps the\n * {@link decorationVersion} and requests a host update so cells re-run their\n * decoration. Called by feature modules after mutating decoration state.\n */\n public bumpDecoration(): void {\n this.#decorationVersion += 1;\n this.host.requestUpdate();\n }\n\n /**\n * Whether any feature module implementing {@link ColumnMenuProvider} offers a\n * column header menu. The header uses this to show its kebab button even on\n * columns that are neither sortable nor resizable, so a module (the enterprise\n * context menu) can surface pin / hide / group / chart actions. Always `false`\n * for the community grid (no modules).\n */\n public get hasColumnMenu(): boolean {\n for (const controller of this.modules.values()) {\n if (isColumnMenuProvider(controller) && controller.providesColumnMenu()) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Collects per-cell decoration contributed by feature modules implementing\n * {@link CellDecorator}, merging their attribute maps (later modules win on a\n * key clash). Returns `null` when no module decorates the cell — the community\n * grid path, where each cell applies nothing.\n */\n public decorateCell(ctx: CellDecoratorContext<T>): CellDecoration | null {\n let attributes: Record<string, string | null | undefined> | null = null;\n for (const controller of this.modules.values()) {\n if (isCellDecorator<T>(controller)) {\n const decoration = controller.decorateCell(ctx);\n if (decoration) {\n attributes ??= {};\n Object.assign(attributes, decoration.attributes);\n }\n }\n }\n return attributes ? { attributes } : null;\n }\n\n /**\n * Forwards a body-cell pointer interaction to every feature module that\n * implements {@link CellInteractionHandler}. No-op for the community grid\n * (no modules); the grid only calls this when modules are registered.\n */\n public handleCellInteraction(interaction: CellInteraction<T>): void {\n for (const controller of this.modules.values()) {\n if (isCellInteractionHandler<T>(controller)) {\n controller.handleCellInteraction(interaction);\n }\n }\n }\n\n /**\n * Collects per-module snapshot state from feature controllers implementing\n * {@link SerializableModule}, keyed by module id. Returns an empty object for\n * the community grid (no modules). Used by `ApexGrid.getState`.\n */\n public serializeModuleState(): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const [id, controller] of this.modules) {\n if (isSerializableModule(controller)) {\n out[id] = controller.serializeState();\n }\n }\n return out;\n }\n\n /**\n * Dispatches previously-serialized state back to the matching feature modules\n * (by id) that implement {@link SerializableModule}. Missing ids and unknown\n * modules are ignored. Used by `ApexGrid.setState`.\n */\n public restoreModuleState(data: Record<string, unknown> | undefined): void {\n if (!data) return;\n for (const [id, controller] of this.modules) {\n if (isSerializableModule(controller) && Object.hasOwn(data, id)) {\n controller.restoreState(data[id]);\n }\n }\n }\n\n public hostConnected() {}\n\n public hostUpdate(): void {\n this.headerRow?.requestUpdate();\n this.scrollContainer?.requestUpdate();\n this.paginator?.requestUpdate();\n this.toolbar?.requestUpdate();\n }\n}\n\nexport const gridStateContext = createContext<StateController<any>>('gridStateController');\n"]}
|
package/controllers/tree.d.ts
CHANGED
|
@@ -78,6 +78,14 @@ export declare class TreeController<T extends object> implements ReactiveControl
|
|
|
78
78
|
* display-order with any synthesized parents inserted.
|
|
79
79
|
*/
|
|
80
80
|
process(input: ReadonlyArray<T>): T[];
|
|
81
|
+
/**
|
|
82
|
+
* Replaces the expansion state wholesale — used by `ApexGrid.setState` to
|
|
83
|
+
* restore a snapshot. Sets both the backing-row set and the synthesized-parent
|
|
84
|
+
* key set directly (no `treeRowExpanding`/`treeRowExpanded` events), marks
|
|
85
|
+
* `defaultExpanded` as already applied so the next pipeline pass treats the
|
|
86
|
+
* restored state as authoritative, and re-runs the pipeline.
|
|
87
|
+
*/
|
|
88
|
+
restoreExpansion(expanded: Iterable<T>, expandedKeys: Iterable<string>): void;
|
|
81
89
|
/**
|
|
82
90
|
* Resets cached metadata + defaults flag so the next pipeline pass
|
|
83
91
|
* re-applies `defaultExpanded`. Called from the data watcher when the
|
package/controllers/tree.js
CHANGED
|
Binary file
|
package/controllers/tree.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tree.js","sourceRoot":"","sources":["../../src/controllers/tree.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ReactiveController } from 'lit';\nimport { PIPELINE } from '../internal/constants.js';\nimport type { GridHost, Keys } from '../internal/types.js';\nimport { getDisplayColumns } from '../internal/utils.js';\n\n/**\n * Default pixel indentation per depth level for the tree group column.\n */\nexport const DEFAULT_TREE_INDENT = 20;\n\n/** Sentinel value used to mark synthesized parents (those that exist only as a path segment, with no backing row). */\nconst SYNTHESIZED = Symbol('synthesized-tree-row');\n\n/**\n * Internal tree node. Built from the flat data + `getDataPath` callback;\n * lives only for the duration of one pipeline pass.\n */\ninterface TreeNode<T extends object> {\n /** The backing row when one exists at this path, else `null` (synthesized parent). */\n data: T | null;\n /** Path segments from root to this node. */\n path: readonly string[];\n /** `path.join('\u0000')` — used as stable string identity for synthesized nodes. */\n key: string;\n depth: number;\n parent: TreeNode<T> | null;\n children: TreeNode<T>[];\n}\n\n/**\n * Tree metadata exposed to renderers. One entry per row that ends up in the\n * flat output.\n */\nexport interface TreeRowMeta {\n depth: number;\n hasChildren: boolean;\n /** Stable key for the row (path-joined string). Useful for keyed reconciliation. */\n key: string;\n /** Last path segment — used as the group-column label for synthesized parents. */\n label: string;\n}\n\n/**\n * Reactive controller backing tree (nested-row) data.\n *\n * @remarks\n * Tree mode keeps the data array flat. Each row's hierarchy is derived from a\n * user-supplied `getDataPath` callback (AG Grid's \"tree data\" pattern). The\n * controller:\n *\n * 1. Builds an in-memory tree from the post-sort, post-filter rows.\n * 2. Synthesizes parent nodes for any path level that lacks a backing row.\n * 3. Walks the tree honouring the current expansion set and emits a flat\n * list of rows in display order.\n * 4. Records per-row metadata (depth, hasChildren) that the cell renderer\n * reads to draw the chevron + indentation.\n *\n * Expansion state is split into two sets — `expanded` for rows that have\n * backing data (keyed by reference, so it survives sort/filter), and\n * `expandedKeys` for synthesized parents (keyed by their path string).\n */\nexport class TreeController<T extends object> implements ReactiveController {\n public expanded: Set<T> = new Set();\n public expandedKeys: Set<string> = new Set();\n\n #meta = new WeakMap<T, TreeRowMeta>();\n #syntheticMeta = new Map<string, TreeRowMeta>();\n /** Synthesized parent placeholder rows so consumers still get a `T`-shaped object. */\n #syntheticRows = new Map<string, T>();\n /** Whether `defaultExpanded` has been applied once for the current data set. */\n #defaultsApplied = false;\n /** Most recently built root node. Used to walk the full tree for expand-all. */\n #lastRoot: TreeNode<T> | null = null;\n\n constructor(protected host: GridHost<T>) {\n this.host.addController(this);\n }\n\n public hostConnected() {}\n\n /** Whether tree mode is enabled at the grid level. */\n public get enabled(): boolean {\n return Boolean(this.host.tree?.enabled && this.host.tree?.getDataPath);\n }\n\n /** The configured indentation, in pixels, per depth level. */\n public get childIndent(): number {\n return this.host.tree?.childIndent ?? DEFAULT_TREE_INDENT;\n }\n\n /**\n * The column key that displays the chevron + indentation. Resolves to the\n * configured `groupColumnKey`, falling back to the first visible data column.\n */\n public get groupColumnKey(): Keys<T> | undefined {\n const configured = this.host.tree?.groupColumnKey;\n if (configured) return configured;\n const displayed = getDisplayColumns(this.host.columns).find((column) => !column.hidden);\n return displayed?.key;\n }\n\n public isGroupColumn(key: Keys<T>): boolean {\n return this.enabled && this.groupColumnKey === key;\n }\n\n /**\n * Per-row metadata. Populated as a side effect of {@link process}; reading\n * before the first pipeline pass returns `undefined`.\n */\n public getMeta(row: T): TreeRowMeta | undefined {\n return this.#meta.get(row);\n }\n\n public getDepth(row: T): number {\n return this.#meta.get(row)?.depth ?? 0;\n }\n\n public hasChildren(row: T): boolean {\n return Boolean(this.#meta.get(row)?.hasChildren);\n }\n\n public isSynthesized(row: T): boolean {\n return (row as { [SYNTHESIZED]?: boolean })[SYNTHESIZED] === true;\n }\n\n /** Group-column label override for synthesized parent rows. */\n public getLabel(row: T): string | null {\n if (!this.isSynthesized(row)) return null;\n return this.#meta.get(row)?.label ?? null;\n }\n\n public isExpanded(row: T): boolean {\n if (this.isSynthesized(row)) {\n const key = this.#meta.get(row)?.key;\n return key ? this.expandedKeys.has(key) : false;\n }\n return this.expanded.has(row);\n }\n\n /** Toggles the expansion state of a tree row. */\n public async toggleRow(row: T): Promise<boolean> {\n if (!this.enabled) return false;\n if (!this.hasChildren(row)) return false;\n const wasExpanded = this.isExpanded(row);\n return wasExpanded ? this.collapseRow(row) : this.expandRow(row);\n }\n\n public async expandRow(row: T): Promise<boolean> {\n if (!this.enabled) return false;\n if (!this.hasChildren(row)) return false;\n if (this.isExpanded(row)) return true;\n return this.#commit((nextData, nextKeys) => {\n if (this.isSynthesized(row)) {\n const key = this.#meta.get(row)?.key;\n if (key) nextKeys.add(key);\n } else {\n nextData.add(row);\n }\n });\n }\n\n public async collapseRow(row: T): Promise<boolean> {\n if (!this.enabled) return false;\n if (!this.isExpanded(row)) return true;\n return this.#commit((nextData, nextKeys) => {\n if (this.isSynthesized(row)) {\n const key = this.#meta.get(row)?.key;\n if (key) nextKeys.delete(key);\n } else {\n nextData.delete(row);\n }\n });\n }\n\n /** Expands every parent in the current tree. */\n public async expandAll(): Promise<boolean> {\n if (!this.enabled) return false;\n const root = this.#lastRoot;\n if (!root) return false;\n return this.#commit((nextData, nextKeys) => {\n const visit = (node: TreeNode<T>) => {\n if (node !== root && node.children.length > 0) {\n if (node.data) nextData.add(node.data);\n else nextKeys.add(node.key);\n }\n for (const child of node.children) visit(child);\n };\n visit(root);\n });\n }\n\n /** Collapses every currently-expanded row. */\n public async collapseAll(): Promise<boolean> {\n if (!this.enabled) return false;\n if (this.expanded.size === 0 && this.expandedKeys.size === 0) return true;\n return this.#commit((nextData, nextKeys) => {\n nextData.clear();\n nextKeys.clear();\n });\n }\n\n /**\n * Pipeline entry point. Called by {@link DataOperationsController.apply}\n * after sort/filter/quickFilter. Builds the tree, applies the configured\n * defaults the first time we see this data, and returns rows in\n * display-order with any synthesized parents inserted.\n */\n public process(input: ReadonlyArray<T>): T[] {\n if (!this.enabled) return input as T[];\n\n const getDataPath = this.host.tree!.getDataPath;\n const root = this.#buildTree(input, getDataPath);\n this.#lastRoot = root;\n\n // Apply defaultExpanded once per data set.\n if (!this.#defaultsApplied) {\n this.#applyDefaults(root);\n this.#defaultsApplied = true;\n }\n\n this.#refreshMeta(root);\n return this.#flatten(root);\n }\n\n /**\n * Resets cached metadata + defaults flag so the next pipeline pass\n * re-applies `defaultExpanded`. Called from the data watcher when the\n * input array is replaced wholesale.\n */\n public resetForDataChange(): void {\n this.#defaultsApplied = false;\n // Don't clear `expanded`/`expandedKeys`; consumers may want them to\n // survive across pipeline passes. If a wholesale data swap orphans\n // references, those entries are simply ignored on the next pass.\n }\n\n // --- internals ---------------------------------------------------------\n\n #buildTree(rows: ReadonlyArray<T>, getDataPath: (row: T) => readonly string[]): TreeNode<T> {\n const root: TreeNode<T> = {\n data: null,\n path: [],\n key: '',\n depth: -1,\n parent: null,\n children: [],\n };\n const byKey = new Map<string, TreeNode<T>>();\n byKey.set('', root);\n\n for (const row of rows) {\n const fullPath = getDataPath(row);\n if (!fullPath || fullPath.length === 0) continue;\n\n let parent = root;\n for (let i = 0; i < fullPath.length; i++) {\n const sub = fullPath.slice(0, i + 1);\n const key = sub.join('\u0000');\n let node = byKey.get(key);\n if (!node) {\n node = {\n data: null,\n path: sub,\n key,\n depth: i,\n parent,\n children: [],\n };\n byKey.set(key, node);\n parent.children.push(node);\n }\n if (i === fullPath.length - 1) {\n // The terminal segment is the actual record. If we previously\n // saw a child path that synthesized this level, attach the data\n // now.\n node.data = row;\n }\n parent = node;\n }\n }\n\n return root;\n }\n\n #applyDefaults(root: TreeNode<T>): void {\n const setting = this.host.tree?.defaultExpanded;\n if (setting === undefined || setting === false) return;\n const expandToDepth = typeof setting === 'number' ? setting : Number.POSITIVE_INFINITY;\n const visit = (node: TreeNode<T>) => {\n if (node !== root && node.children.length > 0 && node.depth <= expandToDepth) {\n if (node.data) this.expanded.add(node.data);\n else this.expandedKeys.add(node.key);\n }\n for (const child of node.children) visit(child);\n };\n visit(root);\n }\n\n #refreshMeta(root: TreeNode<T>): void {\n // Recompute meta for every node in the tree, both synthesized and\n // backed. The metadata is fresh each pipeline pass since depth or\n // hasChildren may have changed (rows reordered, filter dropped a\n // descendant, etc.).\n const visit = (node: TreeNode<T>) => {\n if (node !== root) {\n const meta: TreeRowMeta = {\n depth: node.depth,\n hasChildren: node.children.length > 0,\n key: node.key,\n label: node.path[node.path.length - 1] ?? '',\n };\n if (node.data) {\n this.#meta.set(node.data, meta);\n } else {\n this.#syntheticMeta.set(node.key, meta);\n }\n }\n for (const child of node.children) visit(child);\n };\n visit(root);\n }\n\n #flatten(root: TreeNode<T>): T[] {\n const out: T[] = [];\n const walk = (node: TreeNode<T>) => {\n if (node !== root) {\n if (node.data) {\n out.push(node.data);\n } else {\n // Synthesize a `T`-shaped placeholder so callers don't trip on\n // `null` rows. The placeholder carries the SYNTHESIZED marker.\n let placeholder = this.#syntheticRows.get(node.key);\n if (!placeholder) {\n placeholder = Object.create(null) as T;\n Object.defineProperty(placeholder, SYNTHESIZED, {\n value: true,\n enumerable: false,\n });\n this.#syntheticRows.set(node.key, placeholder);\n }\n this.#meta.set(placeholder, this.#syntheticMeta.get(node.key)!);\n out.push(placeholder);\n }\n }\n const expanded =\n node === root ||\n (node.data ? this.expanded.has(node.data) : this.expandedKeys.has(node.key));\n if (expanded) {\n for (const child of node.children) walk(child);\n }\n };\n walk(root);\n return out;\n }\n\n async #commit(mutate: (nextData: Set<T>, nextKeys: Set<string>) => void): Promise<boolean> {\n const nextData = new Set(this.expanded);\n const nextKeys = new Set(this.expandedKeys);\n mutate(nextData, nextKeys);\n\n const dataChanged =\n nextData.size !== this.expanded.size || [...nextData].some((row) => !this.expanded.has(row));\n const keysChanged =\n nextKeys.size !== this.expandedKeys.size ||\n [...nextKeys].some((key) => !this.expandedKeys.has(key));\n if (!dataChanged && !keysChanged) return true;\n\n const added: T[] = [];\n const removed: T[] = [];\n for (const row of nextData) if (!this.expanded.has(row)) added.push(row);\n for (const row of this.expanded) if (!nextData.has(row)) removed.push(row);\n\n const proceed = this.host.emitEvent('treeRowExpanding', {\n detail: {\n added,\n removed,\n current: Array.from(this.expanded),\n next: Array.from(nextData),\n },\n cancelable: true,\n });\n if (!proceed) return false;\n\n this.expanded = nextData;\n this.expandedKeys = nextKeys;\n // Re-run the pipeline so the flat output reflects the new expansion set.\n this.host.requestUpdate(PIPELINE);\n\n this.host.emitEvent('treeRowExpanded', {\n detail: { added, removed, expanded: Array.from(this.expanded) },\n });\n return true;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"tree.js","sourceRoot":"","sources":["../../src/controllers/tree.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ReactiveController } from 'lit';\nimport { PIPELINE } from '../internal/constants.js';\nimport type { GridHost, Keys } from '../internal/types.js';\nimport { getDisplayColumns } from '../internal/utils.js';\n\n/**\n * Default pixel indentation per depth level for the tree group column.\n */\nexport const DEFAULT_TREE_INDENT = 20;\n\n/** Sentinel value used to mark synthesized parents (those that exist only as a path segment, with no backing row). */\nconst SYNTHESIZED = Symbol('synthesized-tree-row');\n\n/**\n * Internal tree node. Built from the flat data + `getDataPath` callback;\n * lives only for the duration of one pipeline pass.\n */\ninterface TreeNode<T extends object> {\n /** The backing row when one exists at this path, else `null` (synthesized parent). */\n data: T | null;\n /** Path segments from root to this node. */\n path: readonly string[];\n /** `path.join('\u0000')` — used as stable string identity for synthesized nodes. */\n key: string;\n depth: number;\n parent: TreeNode<T> | null;\n children: TreeNode<T>[];\n}\n\n/**\n * Tree metadata exposed to renderers. One entry per row that ends up in the\n * flat output.\n */\nexport interface TreeRowMeta {\n depth: number;\n hasChildren: boolean;\n /** Stable key for the row (path-joined string). Useful for keyed reconciliation. */\n key: string;\n /** Last path segment — used as the group-column label for synthesized parents. */\n label: string;\n}\n\n/**\n * Reactive controller backing tree (nested-row) data.\n *\n * @remarks\n * Tree mode keeps the data array flat. Each row's hierarchy is derived from a\n * user-supplied `getDataPath` callback (AG Grid's \"tree data\" pattern). The\n * controller:\n *\n * 1. Builds an in-memory tree from the post-sort, post-filter rows.\n * 2. Synthesizes parent nodes for any path level that lacks a backing row.\n * 3. Walks the tree honouring the current expansion set and emits a flat\n * list of rows in display order.\n * 4. Records per-row metadata (depth, hasChildren) that the cell renderer\n * reads to draw the chevron + indentation.\n *\n * Expansion state is split into two sets — `expanded` for rows that have\n * backing data (keyed by reference, so it survives sort/filter), and\n * `expandedKeys` for synthesized parents (keyed by their path string).\n */\nexport class TreeController<T extends object> implements ReactiveController {\n public expanded: Set<T> = new Set();\n public expandedKeys: Set<string> = new Set();\n\n #meta = new WeakMap<T, TreeRowMeta>();\n #syntheticMeta = new Map<string, TreeRowMeta>();\n /** Synthesized parent placeholder rows so consumers still get a `T`-shaped object. */\n #syntheticRows = new Map<string, T>();\n /** Whether `defaultExpanded` has been applied once for the current data set. */\n #defaultsApplied = false;\n /** Most recently built root node. Used to walk the full tree for expand-all. */\n #lastRoot: TreeNode<T> | null = null;\n\n constructor(protected host: GridHost<T>) {\n this.host.addController(this);\n }\n\n public hostConnected() {}\n\n /** Whether tree mode is enabled at the grid level. */\n public get enabled(): boolean {\n return Boolean(this.host.tree?.enabled && this.host.tree?.getDataPath);\n }\n\n /** The configured indentation, in pixels, per depth level. */\n public get childIndent(): number {\n return this.host.tree?.childIndent ?? DEFAULT_TREE_INDENT;\n }\n\n /**\n * The column key that displays the chevron + indentation. Resolves to the\n * configured `groupColumnKey`, falling back to the first visible data column.\n */\n public get groupColumnKey(): Keys<T> | undefined {\n const configured = this.host.tree?.groupColumnKey;\n if (configured) return configured;\n const displayed = getDisplayColumns(this.host.columns).find((column) => !column.hidden);\n return displayed?.key;\n }\n\n public isGroupColumn(key: Keys<T>): boolean {\n return this.enabled && this.groupColumnKey === key;\n }\n\n /**\n * Per-row metadata. Populated as a side effect of {@link process}; reading\n * before the first pipeline pass returns `undefined`.\n */\n public getMeta(row: T): TreeRowMeta | undefined {\n return this.#meta.get(row);\n }\n\n public getDepth(row: T): number {\n return this.#meta.get(row)?.depth ?? 0;\n }\n\n public hasChildren(row: T): boolean {\n return Boolean(this.#meta.get(row)?.hasChildren);\n }\n\n public isSynthesized(row: T): boolean {\n return (row as { [SYNTHESIZED]?: boolean })[SYNTHESIZED] === true;\n }\n\n /** Group-column label override for synthesized parent rows. */\n public getLabel(row: T): string | null {\n if (!this.isSynthesized(row)) return null;\n return this.#meta.get(row)?.label ?? null;\n }\n\n public isExpanded(row: T): boolean {\n if (this.isSynthesized(row)) {\n const key = this.#meta.get(row)?.key;\n return key ? this.expandedKeys.has(key) : false;\n }\n return this.expanded.has(row);\n }\n\n /** Toggles the expansion state of a tree row. */\n public async toggleRow(row: T): Promise<boolean> {\n if (!this.enabled) return false;\n if (!this.hasChildren(row)) return false;\n const wasExpanded = this.isExpanded(row);\n return wasExpanded ? this.collapseRow(row) : this.expandRow(row);\n }\n\n public async expandRow(row: T): Promise<boolean> {\n if (!this.enabled) return false;\n if (!this.hasChildren(row)) return false;\n if (this.isExpanded(row)) return true;\n return this.#commit((nextData, nextKeys) => {\n if (this.isSynthesized(row)) {\n const key = this.#meta.get(row)?.key;\n if (key) nextKeys.add(key);\n } else {\n nextData.add(row);\n }\n });\n }\n\n public async collapseRow(row: T): Promise<boolean> {\n if (!this.enabled) return false;\n if (!this.isExpanded(row)) return true;\n return this.#commit((nextData, nextKeys) => {\n if (this.isSynthesized(row)) {\n const key = this.#meta.get(row)?.key;\n if (key) nextKeys.delete(key);\n } else {\n nextData.delete(row);\n }\n });\n }\n\n /** Expands every parent in the current tree. */\n public async expandAll(): Promise<boolean> {\n if (!this.enabled) return false;\n const root = this.#lastRoot;\n if (!root) return false;\n return this.#commit((nextData, nextKeys) => {\n const visit = (node: TreeNode<T>) => {\n if (node !== root && node.children.length > 0) {\n if (node.data) nextData.add(node.data);\n else nextKeys.add(node.key);\n }\n for (const child of node.children) visit(child);\n };\n visit(root);\n });\n }\n\n /** Collapses every currently-expanded row. */\n public async collapseAll(): Promise<boolean> {\n if (!this.enabled) return false;\n if (this.expanded.size === 0 && this.expandedKeys.size === 0) return true;\n return this.#commit((nextData, nextKeys) => {\n nextData.clear();\n nextKeys.clear();\n });\n }\n\n /**\n * Pipeline entry point. Called by {@link DataOperationsController.apply}\n * after sort/filter/quickFilter. Builds the tree, applies the configured\n * defaults the first time we see this data, and returns rows in\n * display-order with any synthesized parents inserted.\n */\n public process(input: ReadonlyArray<T>): T[] {\n if (!this.enabled) return input as T[];\n\n const getDataPath = this.host.tree!.getDataPath;\n const root = this.#buildTree(input, getDataPath);\n this.#lastRoot = root;\n\n // Apply defaultExpanded once per data set.\n if (!this.#defaultsApplied) {\n this.#applyDefaults(root);\n this.#defaultsApplied = true;\n }\n\n this.#refreshMeta(root);\n return this.#flatten(root);\n }\n\n /**\n * Replaces the expansion state wholesale — used by `ApexGrid.setState` to\n * restore a snapshot. Sets both the backing-row set and the synthesized-parent\n * key set directly (no `treeRowExpanding`/`treeRowExpanded` events), marks\n * `defaultExpanded` as already applied so the next pipeline pass treats the\n * restored state as authoritative, and re-runs the pipeline.\n */\n public restoreExpansion(expanded: Iterable<T>, expandedKeys: Iterable<string>): void {\n this.expanded = new Set(expanded);\n this.expandedKeys = new Set(expandedKeys);\n this.#defaultsApplied = true;\n this.host.requestUpdate(PIPELINE);\n }\n\n /**\n * Resets cached metadata + defaults flag so the next pipeline pass\n * re-applies `defaultExpanded`. Called from the data watcher when the\n * input array is replaced wholesale.\n */\n public resetForDataChange(): void {\n this.#defaultsApplied = false;\n // Don't clear `expanded`/`expandedKeys`; consumers may want them to\n // survive across pipeline passes. If a wholesale data swap orphans\n // references, those entries are simply ignored on the next pass.\n }\n\n // --- internals ---------------------------------------------------------\n\n #buildTree(rows: ReadonlyArray<T>, getDataPath: (row: T) => readonly string[]): TreeNode<T> {\n const root: TreeNode<T> = {\n data: null,\n path: [],\n key: '',\n depth: -1,\n parent: null,\n children: [],\n };\n const byKey = new Map<string, TreeNode<T>>();\n byKey.set('', root);\n\n for (const row of rows) {\n const fullPath = getDataPath(row);\n if (!fullPath || fullPath.length === 0) continue;\n\n let parent = root;\n for (let i = 0; i < fullPath.length; i++) {\n const sub = fullPath.slice(0, i + 1);\n const key = sub.join('\u0000');\n let node = byKey.get(key);\n if (!node) {\n node = {\n data: null,\n path: sub,\n key,\n depth: i,\n parent,\n children: [],\n };\n byKey.set(key, node);\n parent.children.push(node);\n }\n if (i === fullPath.length - 1) {\n // The terminal segment is the actual record. If we previously\n // saw a child path that synthesized this level, attach the data\n // now.\n node.data = row;\n }\n parent = node;\n }\n }\n\n return root;\n }\n\n #applyDefaults(root: TreeNode<T>): void {\n const setting = this.host.tree?.defaultExpanded;\n if (setting === undefined || setting === false) return;\n const expandToDepth = typeof setting === 'number' ? setting : Number.POSITIVE_INFINITY;\n const visit = (node: TreeNode<T>) => {\n if (node !== root && node.children.length > 0 && node.depth <= expandToDepth) {\n if (node.data) this.expanded.add(node.data);\n else this.expandedKeys.add(node.key);\n }\n for (const child of node.children) visit(child);\n };\n visit(root);\n }\n\n #refreshMeta(root: TreeNode<T>): void {\n // Recompute meta for every node in the tree, both synthesized and\n // backed. The metadata is fresh each pipeline pass since depth or\n // hasChildren may have changed (rows reordered, filter dropped a\n // descendant, etc.).\n const visit = (node: TreeNode<T>) => {\n if (node !== root) {\n const meta: TreeRowMeta = {\n depth: node.depth,\n hasChildren: node.children.length > 0,\n key: node.key,\n label: node.path[node.path.length - 1] ?? '',\n };\n if (node.data) {\n this.#meta.set(node.data, meta);\n } else {\n this.#syntheticMeta.set(node.key, meta);\n }\n }\n for (const child of node.children) visit(child);\n };\n visit(root);\n }\n\n #flatten(root: TreeNode<T>): T[] {\n const out: T[] = [];\n const walk = (node: TreeNode<T>) => {\n if (node !== root) {\n if (node.data) {\n out.push(node.data);\n } else {\n // Synthesize a `T`-shaped placeholder so callers don't trip on\n // `null` rows. The placeholder carries the SYNTHESIZED marker.\n let placeholder = this.#syntheticRows.get(node.key);\n if (!placeholder) {\n placeholder = Object.create(null) as T;\n Object.defineProperty(placeholder, SYNTHESIZED, {\n value: true,\n enumerable: false,\n });\n this.#syntheticRows.set(node.key, placeholder);\n }\n this.#meta.set(placeholder, this.#syntheticMeta.get(node.key)!);\n out.push(placeholder);\n }\n }\n const expanded =\n node === root ||\n (node.data ? this.expanded.has(node.data) : this.expandedKeys.has(node.key));\n if (expanded) {\n for (const child of node.children) walk(child);\n }\n };\n walk(root);\n return out;\n }\n\n async #commit(mutate: (nextData: Set<T>, nextKeys: Set<string>) => void): Promise<boolean> {\n const nextData = new Set(this.expanded);\n const nextKeys = new Set(this.expandedKeys);\n mutate(nextData, nextKeys);\n\n const dataChanged =\n nextData.size !== this.expanded.size || [...nextData].some((row) => !this.expanded.has(row));\n const keysChanged =\n nextKeys.size !== this.expandedKeys.size ||\n [...nextKeys].some((key) => !this.expandedKeys.has(key));\n if (!dataChanged && !keysChanged) return true;\n\n const added: T[] = [];\n const removed: T[] = [];\n for (const row of nextData) if (!this.expanded.has(row)) added.push(row);\n for (const row of this.expanded) if (!nextData.has(row)) removed.push(row);\n\n const proceed = this.host.emitEvent('treeRowExpanding', {\n detail: {\n added,\n removed,\n current: Array.from(this.expanded),\n next: Array.from(nextData),\n },\n cancelable: true,\n });\n if (!proceed) return false;\n\n this.expanded = nextData;\n this.expandedKeys = nextKeys;\n // Re-run the pipeline so the flat output reflects the new expansion set.\n this.host.requestUpdate(PIPELINE);\n\n this.host.emitEvent('treeRowExpanded', {\n detail: { added, removed, expanded: Array.from(this.expanded) },\n });\n return true;\n }\n}\n"]}
|