From e2fcdfbf3c95e726d260b05d74cbaa37db677496 Mon Sep 17 00:00:00 2001 From: Ghislain B Date: Tue, 19 Sep 2023 01:12:07 -0400 Subject: [PATCH 01/21] feat(core)!: use new SlickGrid ESM version (#1070) * feat(core)!: use new SlickGrid ESM version - use new SlickGrid ESM build - all Cypress E2E tests are now passing - all Jest unit tests are now passing --- .../src/examples/example03.ts | 12 +- .../src/examples/example05.ts | 2 +- .../src/examples/example06.ts | 2 +- .../src/examples/example07.ts | 5 +- .../src/examples/example11.ts | 10 +- .../src/examples/example12.ts | 11 +- .../src/examples/example14.ts | 9 +- .../src/examples/example18.ts | 6 +- package.json | 2 +- packages/common/package.json | 4 +- .../common/src/aggregators/avgAggregator.ts | 9 +- .../common/src/aggregators/cloneAggregator.ts | 7 +- .../common/src/aggregators/countAggregator.ts | 7 +- .../src/aggregators/distinctAggregator.ts | 5 +- .../common/src/aggregators/maxAggregator.ts | 7 +- .../common/src/aggregators/minAggregator.ts | 7 +- .../common/src/aggregators/sumAggregator.ts | 9 +- .../__tests__/autocompleterEditor.spec.ts | 33 +- .../editors/__tests__/checkboxEditor.spec.ts | 29 +- .../src/editors/__tests__/dateEditor.spec.ts | 28 +- .../editors/__tests__/dualInputEditor.spec.ts | 31 +- .../src/editors/__tests__/floatEditor.spec.ts | 37 +- .../src/editors/__tests__/inputEditor.spec.ts | 29 +- .../__tests__/inputPasswordEditor.spec.ts | 29 +- .../editors/__tests__/integerEditor.spec.ts | 31 +- .../editors/__tests__/longTextEditor.spec.ts | 29 +- .../__tests__/multipleSelectEditor.spec.ts | 2 +- .../editors/__tests__/selectEditor.spec.ts | 28 +- .../__tests__/singleSelectEditor.spec.ts | 2 +- .../editors/__tests__/sliderEditor.spec.ts | 31 +- .../common/src/editors/autocompleterEditor.ts | 17 +- packages/common/src/editors/checkboxEditor.ts | 12 +- packages/common/src/editors/dateEditor.ts | 13 +- .../common/src/editors/dualInputEditor.ts | 16 +- packages/common/src/editors/inputEditor.ts | 13 +- packages/common/src/editors/longTextEditor.ts | 13 +- packages/common/src/editors/selectEditor.ts | 15 +- packages/common/src/editors/sliderEditor.ts | 17 +- .../src/enums/columnReorderFunction.type.ts | 5 +- .../src/enums/usabilityOverrideFn.type.ts | 4 +- .../__tests__/extensionUtility.spec.ts | 2 +- .../__tests__/slickAutoTooltip.spec.ts | 37 +- .../slickCellExcelCopyManager.spec.ts | 31 +- .../slickCellExternalCopyManager.spec.ts | 46 +- .../__tests__/slickCellMenu.plugin.spec.ts | 15 +- .../__tests__/slickCellRangeDecorator.spec.ts | 13 +- .../__tests__/slickCellRangeSelector.spec.ts | 20 +- .../__tests__/slickCellSelectionModel.spec.ts | 18 +- .../slickCheckboxSelectColumn.spec.ts | 29 +- .../__tests__/slickColumnPicker.spec.ts | 81 ++- .../__tests__/slickContextMenu.spec.ts | 19 +- .../__tests__/slickDraggableGrouping.spec.ts | 18 +- .../__tests__/slickGridMenu.spec.ts | 20 +- .../slickGroupItemMetadataProvider.spec.ts | 23 +- .../__tests__/slickHeaderButtons.spec.ts | 57 +- .../__tests__/slickHeaderMenu.spec.ts | 163 +++-- .../__tests__/slickRowMoveManager.spec.ts | 14 +- .../__tests__/slickRowSelectionModel.spec.ts | 66 +- .../common/src/extensions/menuBaseClass.ts | 12 +- .../common/src/extensions/slickAutoTooltip.ts | 26 +- .../extensions/slickCellExcelCopyManager.ts | 26 +- .../slickCellExternalCopyManager.ts | 58 +- .../common/src/extensions/slickCellMenu.ts | 3 +- .../src/extensions/slickCellRangeDecorator.ts | 34 +- .../src/extensions/slickCellRangeSelector.ts | 67 +- .../src/extensions/slickCellSelectionModel.ts | 66 +- .../extensions/slickCheckboxSelectColumn.ts | 42 +- .../src/extensions/slickColumnPicker.ts | 19 +- .../src/extensions/slickDraggableGrouping.ts | 43 +- .../common/src/extensions/slickGridMenu.ts | 17 +- .../slickGroupItemMetadataProvider.ts | 64 +- .../src/extensions/slickHeaderButtons.ts | 13 +- .../common/src/extensions/slickHeaderMenu.ts | 2 +- .../src/extensions/slickRowMoveManager.ts | 36 +- .../src/extensions/slickRowSelectionModel.ts | 74 +-- .../__tests__/autocompleterFilter.spec.ts | 4 +- .../__tests__/compoundDateFilter.spec.ts | 2 +- .../__tests__/compoundInputFilter.spec.ts | 2 +- .../compoundInputNumberFilter.spec.ts | 2 +- .../compoundInputPasswordFilter.spec.ts | 2 +- .../__tests__/compoundSliderFilter.spec.ts | 11 +- .../filters/__tests__/dateRangeFilter.spec.ts | 2 +- .../src/filters/__tests__/inputFilter.spec.ts | 2 +- .../filters/__tests__/inputMaskFilter.spec.ts | 2 +- .../__tests__/inputNumberFilter.spec.ts | 2 +- .../__tests__/inputPasswordFilter.spec.ts | 2 +- .../__tests__/multipleSelectFilter.spec.ts | 2 +- .../__tests__/nativeSelectFilter.spec.ts | 2 +- .../filters/__tests__/selectFilter.spec.ts | 2 +- .../__tests__/singleSelectFilter.spec.ts | 2 +- .../__tests__/singleSliderFilter.spec.ts | 11 +- .../__tests__/sliderRangeFilter.spec.ts | 11 +- .../common/src/filters/autocompleterFilter.ts | 6 +- packages/common/src/filters/dateFilter.ts | 8 +- packages/common/src/filters/inputFilter.ts | 4 +- .../common/src/filters/nativeSelectFilter.ts | 6 +- packages/common/src/filters/selectFilter.ts | 4 +- packages/common/src/filters/sliderFilter.ts | 11 +- .../__tests__/currencyFormatter.spec.ts | 2 +- .../__tests__/decimalFormatter.spec.ts | 2 +- .../dollarColoredBoldFormatter.spec.ts | 2 +- .../__tests__/dollarColoredFormatter.spec.ts | 2 +- .../__tests__/dollarFormatter.spec.ts | 2 +- .../__tests__/formatterUtilities.spec.ts | 2 +- .../__tests__/hyperlinkFormatter.spec.ts | 49 +- .../percentCompleteFormatter.spec.ts | 2 +- .../__tests__/percentFormatter.spec.ts | 2 +- .../__tests__/percentSymbolFormatter.spec.ts | 2 +- .../translateBooleanFormatter.spec.ts | 6 +- .../__tests__/translateFormatter.spec.ts | 6 +- .../__tests__/treeExportFormatter.spec.ts | 2 +- .../__tests__/treeFormatter.spec.ts | 8 +- .../src/formatters/formatterUtilities.ts | 10 +- .../src/formatters/hyperlinkFormatter.ts | 2 +- .../formatters/translateBooleanFormatter.ts | 2 +- .../src/formatters/translateFormatter.ts | 2 +- packages/common/src/global-grid-options.ts | 2 +- .../avgTotalsCurrencyFormatters.spec.ts | 2 +- .../avgTotalsDollarFormatters.spec.ts | 2 +- .../__tests__/avgTotalsFormatter.spec.ts | 2 +- .../avgTotalsPercentageFormatter.spec.ts | 2 +- .../__tests__/maxTotalsFormatter.spec.ts | 2 +- .../__tests__/minTotalsFormatter.spec.ts | 2 +- .../__tests__/sumTotalsBoldFormatter.spec.ts | 2 +- .../sumTotalsColoredFormatter.spec.ts | 2 +- .../sumTotalsCurrencyColoredFormatter.spec.ts | 2 +- .../sumTotalsCurrencyFormatter.spec.ts | 2 +- .../sumTotalsDollarBoldFormatter.spec.ts | 2 +- ...umTotalsDollarColoredBoldFormatter.spec.ts | 2 +- .../sumTotalsDollarColoredFormatter.spec.ts | 2 +- .../sumTotalsDollarFormatter.spec.ts | 2 +- .../__tests__/sumTotalsFormatter.spec.ts | 2 +- .../avgTotalsCurrencyFormatter.ts | 4 +- .../avgTotalsDollarFormatter.ts | 4 +- .../grouping-formatters/avgTotalsFormatter.ts | 4 +- .../avgTotalsPercentageFormatter.ts | 4 +- .../grouping-formatters/maxTotalsFormatter.ts | 4 +- .../grouping-formatters/minTotalsFormatter.ts | 4 +- .../sumTotalsBoldFormatter.ts | 4 +- .../sumTotalsColoredFormatter.ts | 4 +- .../sumTotalsCurrencyColoredFormatter.ts | 4 +- .../sumTotalsCurrencyFormatter.ts | 4 +- .../sumTotalsDollarBoldFormatter.ts | 4 +- .../sumTotalsDollarColoredBoldFormatter.ts | 4 +- .../sumTotalsDollarColoredFormatter.ts | 4 +- .../sumTotalsDollarFormatter.ts | 4 +- .../grouping-formatters/sumTotalsFormatter.ts | 4 +- packages/common/src/index.ts | 2 + .../autocompleterOption.interface.ts | 2 +- .../interfaces/backendService.interface.ts | 4 +- .../src/interfaces/cellArgs.interface.ts | 4 +- .../interfaces/cellMenuOption.interface.ts | 10 +- .../collectionOverrideArgs.interface.ts | 6 +- .../common/src/interfaces/column.interface.ts | 47 +- .../src/interfaces/columnEditor.interface.ts | 1 + .../src/interfaces/columnPicker.interface.ts | 44 +- .../src/interfaces/columnSort.interface.ts | 2 +- .../interfaces/contextMenuOption.interface.ts | 4 +- .../customTooltipOption.interface.ts | 8 +- .../interfaces/dataViewOption.interface.ts | 2 +- .../common/src/interfaces/drag.interface.ts | 4 +- .../interfaces/draggableGrouping.interface.ts | 4 +- .../common/src/interfaces/editor.interface.ts | 3 +- .../interfaces/editorArguments.interface.ts | 6 +- .../excelCopyBufferOption.interface.ts | 9 +- .../interfaces/externalResource.interface.ts | 4 +- .../common/src/interfaces/filter.interface.ts | 4 +- .../interfaces/filterArguments.interface.ts | 4 +- .../interfaces/filterCallback.interface.ts | 4 +- .../interfaces/filterChangedArgs.interface.ts | 5 +- .../src/interfaces/formatter.interface.ts | 6 +- .../src/interfaces/gridMenu.interface.ts | 4 +- ...idMenuCommandItemCallbackArgs.interface.ts | 6 +- .../interfaces/gridMenuOption.interface.ts | 4 +- .../src/interfaces/gridOption.interface.ts | 29 +- .../groupTotalsFormatter.interface.ts | 5 +- .../interfaces/headerButtonItem.interface.ts | 9 +- .../headerButtonOnCommandArgs.interface.ts | 6 +- .../src/interfaces/headerMenu.interface.ts | 5 +- .../interfaces/headerMenuOption.interface.ts | 4 +- packages/common/src/interfaces/index.ts | 8 +- .../src/interfaces/itemMetadata.interface.ts | 2 +- .../interfaces/menuCallbackArgs.interface.ts | 5 +- .../interfaces/menuCommandItem.interface.ts | 7 +- .../menuFromCellCallbackArgs.interface.ts | 5 +- .../interfaces/multiColumnSort.interface.ts | 5 +- .../src/interfaces/onEventArgs.interface.ts | 7 +- .../src/interfaces/pagingInfo.interface.ts | 2 +- .../src/interfaces/resizer.interface.ts | 9 +- .../src/interfaces/rowDetailView.interface.ts | 144 +++-- .../interfaces/rowMoveManager.interface.ts | 12 +- .../selectableOverrideCallback.interface.ts | 4 +- .../interfaces/singleColumnSort.interface.ts | 5 +- .../src/interfaces/slickDataView.interface.ts | 286 --------- .../interfaces/slickEventHandler.interface.ts | 2 +- .../src/interfaces/slickGrid.interface.ts | 586 ------------------ .../slickGridUniversal.interface.ts | 5 + .../interfaces/slickNamespace.interface.ts | 207 ------- .../src/interfaces/slickPlugin.interface.ts | 7 + .../interfaces/slickRemoteModel.interface.ts | 2 +- .../src/interfaces/slickResizer.interface.ts | 16 +- .../slickRowDetailView.interface.ts | 31 +- .../__tests__/extension.service.spec.ts | 40 +- .../services/__tests__/filter.service.spec.ts | 167 +++-- .../services/__tests__/grid.service.spec.ts | 10 +- .../__tests__/gridEvent.service.spec.ts | 32 +- .../__tests__/gridState.service.spec.ts | 40 +- .../groupingAndColspan.service.spec.ts | 47 +- .../__tests__/pagination.service.spec.ts | 15 +- .../__tests__/resizer.service.spec.ts | 10 +- .../services/__tests__/shared.service.spec.ts | 2 +- .../services/__tests__/sort.service.spec.ts | 65 +- .../__tests__/treeData.service.spec.ts | 26 +- packages/common/src/services/domUtilities.ts | 6 +- .../src/services/excelExport.service.ts | 4 +- .../common/src/services/extension.service.ts | 1 + .../common/src/services/filter.service.ts | 53 +- packages/common/src/services/grid.service.ts | 22 +- .../common/src/services/gridEvent.service.ts | 37 +- .../common/src/services/gridState.service.ts | 26 +- .../services/groupingAndColspan.service.ts | 26 +- .../common/src/services/pagination.service.ts | 16 +- .../common/src/services/resizer.service.ts | 25 +- .../common/src/services/shared.service.ts | 11 +- packages/common/src/services/sort.service.ts | 61 +- .../common/src/services/textExport.service.ts | 4 +- .../common/src/services/treeData.service.ts | 23 +- .../src/compositeEditor.factory.spec.ts | 16 +- .../src/compositeEditor.factory.ts | 9 +- .../slick-composite-editor.component.spec.ts | 55 +- .../src/slick-composite-editor.component.ts | 37 +- .../src/slick-footer.component.ts | 12 +- .../src/slick-footer.spec.ts | 32 +- .../src/__tests__/slickCustomTooltip.spec.ts | 66 +- .../src/slickCustomTooltip.ts | 29 +- .../src/slick-empty-warning.component.ts | 8 +- .../src/slick-empty-warning.spec.ts | 2 +- .../src/excelExport.service.spec.ts | 2 +- .../excel-export/src/excelExport.service.ts | 12 +- packages/excel-export/src/excelUtils.spec.ts | 6 +- packages/excel-export/src/excelUtils.ts | 10 +- .../__tests__/graphql.service.spec.ts | 2 +- .../graphql/src/services/graphql.service.ts | 10 +- .../__tests__/grid-odata.service.spec.ts | 2 +- .../odata/src/services/grid-odata.service.ts | 10 +- .../slick-pagination-without-i18n.spec.ts | 2 +- .../src/__tests__/slick-pagination.spec.ts | 2 +- .../src/slick-pagination.component.ts | 4 +- .../src/slickRowDetailView.spec.ts | 92 ++- .../src/slickRowDetailView.ts | 74 ++- .../src/textExport.service.spec.ts | 2 +- .../text-export/src/textExport.service.ts | 12 +- packages/vanilla-bundle/package.json | 2 +- .../__tests__/slick-vanilla-grid.spec.ts | 85 ++- .../components/slick-vanilla-grid-bundle.ts | 85 ++- packages/vanilla-bundle/src/index.ts | 2 +- .../slickerGridInstance.interface.ts | 10 +- .../__tests__/vanilla-force-bundle.spec.ts | 61 +- .../src/vanilla-force-bundle.ts | 7 +- pnpm-lock.yaml | 56 +- test/cypress.config.ts | 1 - test/cypress/support/commands.ts | 2 +- test/cypress/support/drag.ts | 10 +- test/jest-pretest.ts | 5 - test/mockSlickEvent.ts | 48 +- 265 files changed, 2140 insertions(+), 3280 deletions(-) delete mode 100644 packages/common/src/interfaces/slickDataView.interface.ts delete mode 100644 packages/common/src/interfaces/slickGrid.interface.ts create mode 100644 packages/common/src/interfaces/slickGridUniversal.interface.ts delete mode 100644 packages/common/src/interfaces/slickNamespace.interface.ts create mode 100644 packages/common/src/interfaces/slickPlugin.interface.ts diff --git a/examples/vite-demo-vanilla-bundle/src/examples/example03.ts b/examples/vite-demo-vanilla-bundle/src/examples/example03.ts index 169066cc0..ff6b98145 100644 --- a/examples/vite-demo-vanilla-bundle/src/examples/example03.ts +++ b/examples/vite-demo-vanilla-bundle/src/examples/example03.ts @@ -13,20 +13,17 @@ import { GroupingGetterFunction, GroupTotalFormatters, SlickDraggableGrouping, - SlickNamespace, SortComparers, SortDirectionNumber, } from '@slickgrid-universal/common'; import { ExcelExportService } from '@slickgrid-universal/excel-export'; import { TextExportService } from '@slickgrid-universal/text-export'; import { Slicker, SlickVanillaGridBundle } from '@slickgrid-universal/vanilla-bundle'; +import { SlickGlobalEditorLock } from 'slickgrid'; import { ExampleGridOptions } from './example-grid-options'; import './example03.scss?inline'; -// using external SlickGrid JS libraries -declare const Slick: SlickNamespace; - interface ReportItem { title: string; duration: number; @@ -44,7 +41,7 @@ export default class Example3 { dataset: any[]; editCommandQueue: EditCommand[] = []; excelExportService: ExcelExportService; - sgb: SlickVanillaGridBundle; + sgb: SlickVanillaGridBundle; durationOrderByCount = false; draggableGroupingPlugin: SlickDraggableGrouping; loadingClass = ''; @@ -374,6 +371,9 @@ export default class Example3 { if (this.sgb) { this.sgb.dataset = tmpArray; } + // const item = this.sgb.dataView?.getItemById(0); + // const item = this.sgb?.dataView?.getItemById(0); + // console.log('item', item); return tmpArray; } @@ -504,7 +504,7 @@ export default class Example3 { undo() { const command = this.editCommandQueue.pop(); - if (command && Slick.GlobalEditorLock.cancelCurrentEdit()) { + if (command && SlickGlobalEditorLock.cancelCurrentEdit()) { command.undo(); this.sgb?.slickGrid?.gotoCell(command.row, command.cell, false); } diff --git a/examples/vite-demo-vanilla-bundle/src/examples/example05.ts b/examples/vite-demo-vanilla-bundle/src/examples/example05.ts index e60265f4e..d08d83b39 100644 --- a/examples/vite-demo-vanilla-bundle/src/examples/example05.ts +++ b/examples/vite-demo-vanilla-bundle/src/examples/example05.ts @@ -318,7 +318,7 @@ export default class Example5 { updateFirstRow() { // to update any of the grid rows, we CANNOT simply pass a new updated object // we MUST read it from the DataView first (that will include all mutated Tree Data props, like `__treeLevel`, `__parentId`, ...) and then update it - const item = this.sgb.dataView?.getItemById(0); + const item = this.sgb.dataView?.getItemById(0); // option 1 /* diff --git a/examples/vite-demo-vanilla-bundle/src/examples/example06.ts b/examples/vite-demo-vanilla-bundle/src/examples/example06.ts index 81feab588..3a9c07280 100644 --- a/examples/vite-demo-vanilla-bundle/src/examples/example06.ts +++ b/examples/vite-demo-vanilla-bundle/src/examples/example06.ts @@ -233,7 +233,7 @@ export default class Example6 { if (value === null || value === undefined || dataContext === undefined) { return ''; } - const dataView = grid.getData() as SlickDataView; + const dataView = grid.getData(); const data = dataView.getItems(); const identifierPropName = dataView.getIdPropertyName() || 'id'; const idx = dataView.getIdxById(dataContext[identifierPropName]) as number; diff --git a/examples/vite-demo-vanilla-bundle/src/examples/example07.ts b/examples/vite-demo-vanilla-bundle/src/examples/example07.ts index 009d70cc4..b27b0f6c0 100644 --- a/examples/vite-demo-vanilla-bundle/src/examples/example07.ts +++ b/examples/vite-demo-vanilla-bundle/src/examples/example07.ts @@ -7,6 +7,7 @@ import { Formatters, GridOption, OperatorType, + SlickEventData, } from '@slickgrid-universal/common'; import { ExcelExportService } from '@slickgrid-universal/excel-export'; import { Slicker, SlickVanillaGridBundle } from '@slickgrid-universal/vanilla-bundle'; @@ -487,7 +488,7 @@ export default class Example7 { return collection.sort((item1, item2) => item1.value - item2.value); } - onBeforeMoveRow(e: Event, data: { rows: number[]; insertBefore: number; }) { + onBeforeMoveRow(e: MouseEvent | TouchEvent | SlickEventData, data: { rows: number[]; insertBefore: number; }) { for (const rowIdx of data.rows) { // no point in moving before or after itself if (rowIdx === data.insertBefore || (rowIdx === data.insertBefore - 1 && ((data.insertBefore - 1) !== this.sgb.dataView?.getItemCount()))) { @@ -498,7 +499,7 @@ export default class Example7 { return true; } - onMoveRows(_e: Event, args: { rows: number[]; insertBefore: number; }) { + onMoveRows(_e: MouseEvent | TouchEvent | SlickEventData, args: { rows: number[]; insertBefore: number; }) { // rows and insertBefore references, // note that these references are assuming that the dataset isn't filtered at all // which is not always the case so we will recalcualte them and we won't use these reference afterward diff --git a/examples/vite-demo-vanilla-bundle/src/examples/example11.ts b/examples/vite-demo-vanilla-bundle/src/examples/example11.ts index 08a7489c8..e138f57f9 100644 --- a/examples/vite-demo-vanilla-bundle/src/examples/example11.ts +++ b/examples/vite-demo-vanilla-bundle/src/examples/example11.ts @@ -15,7 +15,6 @@ import { Formatters, GridOption, OperatorType, - SlickNamespace, SortComparers, // utilities @@ -26,6 +25,7 @@ import { import { ExcelExportService } from '@slickgrid-universal/excel-export'; import { Slicker, SlickVanillaGridBundle } from '@slickgrid-universal/vanilla-bundle'; import moment from 'moment-mini'; +import { SlickGlobalEditorLock } from 'slickgrid'; import exampleModal from './example11-modal.html?raw'; import Example11Modal from './example11-modal'; @@ -34,8 +34,6 @@ import { ExampleGridOptions } from './example-grid-options'; import { loadComponent } from './utilities'; import './example11.scss'; -// using external SlickGrid JS libraries -declare const Slick: SlickNamespace; const LOCAL_STORAGE_KEY = 'gridViewPreset'; // you can create custom validator to pass to an inline editor @@ -263,7 +261,7 @@ export default class Example11 { excludeFromExport: true, formatter: () => `  `, - onCellClick: (event, args) => { + onCellClick: (event: Event, args) => { const dataContext = args.dataContext; if ((event.target as HTMLElement).classList.contains('mdi-close')) { if (confirm(`Do you really want to delete row (${args.row + 1}) with "${dataContext.title}"`)) { @@ -553,7 +551,7 @@ export default class Example11 { undoLastEdit(showLastEditor = false) { const lastEdit = this.editQueue.pop(); const lastEditCommand = lastEdit?.editCommand; - if (lastEdit && lastEditCommand && Slick.GlobalEditorLock.cancelCurrentEdit()) { + if (lastEdit && lastEditCommand && SlickGlobalEditorLock.cancelCurrentEdit()) { lastEditCommand.undo(); // remove unsaved css class from that cell @@ -571,7 +569,7 @@ export default class Example11 { undoAllEdits() { for (const lastEdit of this.editQueue) { const lastEditCommand = lastEdit?.editCommand; - if (lastEditCommand && Slick.GlobalEditorLock.cancelCurrentEdit()) { + if (lastEditCommand && SlickGlobalEditorLock.cancelCurrentEdit()) { lastEditCommand.undo(); // remove unsaved css class from that cell diff --git a/examples/vite-demo-vanilla-bundle/src/examples/example12.ts b/examples/vite-demo-vanilla-bundle/src/examples/example12.ts index 28ec84c15..dd155abd9 100644 --- a/examples/vite-demo-vanilla-bundle/src/examples/example12.ts +++ b/examples/vite-demo-vanilla-bundle/src/examples/example12.ts @@ -13,8 +13,6 @@ import { Formatters, GridOption, LongTextEditorOption, - OnCompositeEditorChangeEventArgs, - SlickNamespace, SliderOption, SortComparers, @@ -25,14 +23,11 @@ import { ExcelExportService } from '@slickgrid-universal/excel-export'; import { SlickerGridInstance } from '@slickgrid-universal/vanilla-bundle'; import { VanillaForceGridBundle, Slicker } from '@slickgrid-universal/vanilla-force-bundle'; import { CompositeEditor, SlickCompositeEditorComponent } from '@slickgrid-universal/composite-editor-component'; - +import { OnCompositeEditorChangeEventArgs, SlickGlobalEditorLock } from 'slickgrid'; import { ExampleGridOptions } from './example-grid-options'; import countriesJson from './data/countries.json?raw'; import './example12.scss'; -// using external SlickGrid JS libraries -declare const Slick: SlickNamespace; - // you can create custom validator to pass to an inline editor const myCustomTitleValidator = (value, args) => { if ((value === null || value === undefined || !value.length) && (args.compositeEditorOptions && args.compositeEditorOptions.modalType === 'create' || args.compositeEditorOptions.modalType === 'edit')) { @@ -709,7 +704,7 @@ export default class Example12 { undoLastEdit(showLastEditor = false) { const lastEdit = this.editQueue.pop(); const lastEditCommand = lastEdit?.editCommand; - if (lastEdit && lastEditCommand && Slick.GlobalEditorLock.cancelCurrentEdit()) { + if (lastEdit && lastEditCommand && SlickGlobalEditorLock.cancelCurrentEdit()) { lastEditCommand.undo(); // remove unsaved css class from that cell @@ -729,7 +724,7 @@ export default class Example12 { undoAllEdits() { for (const lastEdit of this.editQueue) { const lastEditCommand = lastEdit?.editCommand; - if (lastEditCommand && Slick.GlobalEditorLock.cancelCurrentEdit()) { + if (lastEditCommand && SlickGlobalEditorLock.cancelCurrentEdit()) { lastEditCommand.undo(); // remove unsaved css class from that cell diff --git a/examples/vite-demo-vanilla-bundle/src/examples/example14.ts b/examples/vite-demo-vanilla-bundle/src/examples/example14.ts index 1044b4a94..d46765301 100644 --- a/examples/vite-demo-vanilla-bundle/src/examples/example14.ts +++ b/examples/vite-demo-vanilla-bundle/src/examples/example14.ts @@ -12,7 +12,6 @@ import { Formatters, GridOption, LongTextEditorOption, - SlickNamespace, SliderRangeOption, SortComparers, @@ -23,6 +22,7 @@ import { } from '@slickgrid-universal/common'; import { ExcelExportService } from '@slickgrid-universal/excel-export'; import { Slicker, SlickVanillaGridBundle } from '@slickgrid-universal/vanilla-bundle'; +import { SlickGlobalEditorLock } from 'slickgrid'; import countriesJson from './data/countries.json?raw'; import { ExampleGridOptions } from './example-grid-options'; @@ -30,9 +30,6 @@ import './example14.scss'; const NB_ITEMS = 400; -// using external SlickGrid JS libraries -declare const Slick: SlickNamespace; - // you can create custom validator to pass to an inline editor const myCustomTitleValidator = (value) => { if ((value === null || value === undefined || !value.length)) { @@ -716,7 +713,7 @@ export default class Example14 { undoLastEdit(showLastEditor = false) { const lastEdit = this.editQueue.pop(); const lastEditCommand = lastEdit?.editCommand; - if (lastEdit && lastEditCommand && Slick.GlobalEditorLock.cancelCurrentEdit()) { + if (lastEdit && lastEditCommand && SlickGlobalEditorLock.cancelCurrentEdit()) { lastEditCommand.undo(); // remove unsaved css class from that cell @@ -736,7 +733,7 @@ export default class Example14 { undoAllEdits() { for (const lastEdit of this.editQueue) { const lastEditCommand = lastEdit?.editCommand; - if (lastEditCommand && Slick.GlobalEditorLock.cancelCurrentEdit()) { + if (lastEditCommand && SlickGlobalEditorLock.cancelCurrentEdit()) { lastEditCommand.undo(); // remove unsaved css class from that cell diff --git a/examples/vite-demo-vanilla-bundle/src/examples/example18.ts b/examples/vite-demo-vanilla-bundle/src/examples/example18.ts index ccbcc6756..ccc08c407 100644 --- a/examples/vite-demo-vanilla-bundle/src/examples/example18.ts +++ b/examples/vite-demo-vanilla-bundle/src/examples/example18.ts @@ -238,8 +238,10 @@ export default class Example18 { itemTmp.amount = itemTmp.price * itemTmp.quantity; itemTmp.trsnType = (Math.round(Math.random() * 100)) % 2 ? 'Buy' : 'Sell'; itemTmp.execution = new Date(); - itemTmp.historic.push(itemTmp.price); - itemTmp.historic = itemTmp.historic.slice(-20); // keep a max of X historic values + if (itemTmp.price !== undefined) { + itemTmp.historic.push(itemTmp.price); + itemTmp.historic = itemTmp.historic.slice(-20); // keep a max of X historic values + } if (!changes[rowNumber]) { changes[rowNumber] = {}; diff --git a/package.json b/package.json index 468a82f9d..09b4f41d6 100644 --- a/package.json +++ b/package.json @@ -85,7 +85,7 @@ "rimraf": "^5.0.5", "rxjs": "^7.8.1", "servor": "^4.0.2", - "slickgrid": "^4.1.3", + "slickgrid": "^5.0.0-alpha.2", "sortablejs": "^1.15.0", "ts-jest": "^29.1.1", "ts-node": "^10.9.1", diff --git a/packages/common/package.json b/packages/common/package.json index c0af8083a..7aba0bc6b 100644 --- a/packages/common/package.json +++ b/packages/common/package.json @@ -80,8 +80,8 @@ "dompurify": "^3.0.6", "flatpickr": "^4.6.13", "moment-mini": "^2.29.4", - "multiple-select-vanilla": "^0.6.3", - "slickgrid": "^4.1.3", + "multiple-select-vanilla": "^0.4.10", + "slickgrid": "^5.0.0-alpha.2", "sortablejs": "^1.15.0", "un-flatten-tree": "^2.0.12" }, diff --git a/packages/common/src/aggregators/avgAggregator.ts b/packages/common/src/aggregators/avgAggregator.ts index 050744e22..3836f3104 100644 --- a/packages/common/src/aggregators/avgAggregator.ts +++ b/packages/common/src/aggregators/avgAggregator.ts @@ -1,4 +1,5 @@ import { isNumber } from '@slickgrid-universal/utils'; +import type { SlickGroupTotals } from 'slickgrid'; import type { Aggregator } from './../interfaces/aggregator.interface'; @@ -74,15 +75,15 @@ export class AvgAggregator implements Aggregator { } } - storeResult(groupTotals: any) { + storeResult(groupTotals: SlickGroupTotals & { [type: string]: Record; }) { let sum = this._sum; let itemCount = this._nonNullCount; this.addGroupTotalPropertiesWhenNotExist(groupTotals); // when dealing with Tree Data, we also need to take the parent's total and add it to the final sum if (this._isTreeAggregator) { - sum += groupTotals['sum'][this._field]; - itemCount += groupTotals['count'][this._field]; + sum += groupTotals['sum'][this._field] as number; + itemCount += groupTotals['count'][this._field] as number; groupTotals['sum'][this._field] = sum; groupTotals['count'][this._field] = itemCount; @@ -104,4 +105,4 @@ export class AvgAggregator implements Aggregator { groupTotals['count'] = {}; } } -} +} \ No newline at end of file diff --git a/packages/common/src/aggregators/cloneAggregator.ts b/packages/common/src/aggregators/cloneAggregator.ts index a957c1a2f..7874f3ceb 100644 --- a/packages/common/src/aggregators/cloneAggregator.ts +++ b/packages/common/src/aggregators/cloneAggregator.ts @@ -1,10 +1,11 @@ +import type { SlickGroupTotals } from 'slickgrid'; import type { Aggregator } from './../interfaces/aggregator.interface'; export class CloneAggregator implements Aggregator { private _isInitialized = false; private _field: number | string; - private _data: any; - private _type = 'clone'; + private _data = ''; + private _type = 'clone' as const; constructor(field: number | string) { this._field = field; @@ -37,7 +38,7 @@ export class CloneAggregator implements Aggregator { } } - storeResult(groupTotals: any) { + storeResult(groupTotals: SlickGroupTotals & { clone: Record; }) { if (!groupTotals || groupTotals[this._type] === undefined) { groupTotals[this._type] = {}; } diff --git a/packages/common/src/aggregators/countAggregator.ts b/packages/common/src/aggregators/countAggregator.ts index ab9a24c85..d7e1d062a 100644 --- a/packages/common/src/aggregators/countAggregator.ts +++ b/packages/common/src/aggregators/countAggregator.ts @@ -1,4 +1,5 @@ import { isNumber } from '@slickgrid-universal/utils'; +import type { SlickGroupTotals } from 'slickgrid'; import type { Aggregator } from './../interfaces/aggregator.interface'; @@ -61,7 +62,7 @@ export class CountAggregator implements Aggregator { } } - storeResult(groupTotals: any) { + storeResult(groupTotals: SlickGroupTotals & { [type: string]: Record; }) { if (!groupTotals || groupTotals[this._type] === undefined) { groupTotals[this._type] = {}; } @@ -69,10 +70,10 @@ export class CountAggregator implements Aggregator { if (this._isTreeAggregator) { // when dealing with Tree Data, we also need to take the parent's total and add it to the final count - itemCount += groupTotals[this._type][this._field]; + itemCount += groupTotals[this._type][this._field] as number; } else { itemCount = groupTotals.group.rows.length; } groupTotals[this._type][this._field] = itemCount; } -} +} \ No newline at end of file diff --git a/packages/common/src/aggregators/distinctAggregator.ts b/packages/common/src/aggregators/distinctAggregator.ts index 1fe77a030..91dce7855 100644 --- a/packages/common/src/aggregators/distinctAggregator.ts +++ b/packages/common/src/aggregators/distinctAggregator.ts @@ -1,10 +1,11 @@ +import type { SlickGroupTotals } from 'slickgrid'; import type { Aggregator } from './../interfaces/aggregator.interface'; export class DistinctAggregator implements Aggregator { private _isInitialized = false; private _field: number | string; private _distinctValues: any[] = []; - private _type = 'distinct'; + private _type = 'distinct' as const; constructor(field: number | string) { this._field = field; @@ -37,7 +38,7 @@ export class DistinctAggregator implements Aggregator { } } - storeResult(groupTotals: any) { + storeResult(groupTotals: SlickGroupTotals & { distinct: Record; }) { if (!groupTotals || groupTotals[this._type] === undefined) { groupTotals[this._type] = {}; } diff --git a/packages/common/src/aggregators/maxAggregator.ts b/packages/common/src/aggregators/maxAggregator.ts index 005855519..1826bfa02 100644 --- a/packages/common/src/aggregators/maxAggregator.ts +++ b/packages/common/src/aggregators/maxAggregator.ts @@ -1,3 +1,4 @@ +import type { SlickGroupTotals } from 'slickgrid'; import { isNumber } from '@slickgrid-universal/utils'; import type { Aggregator } from './../interfaces/aggregator.interface'; @@ -65,13 +66,13 @@ export class MaxAggregator implements Aggregator { } } - storeResult(groupTotals: any) { + storeResult(groupTotals: SlickGroupTotals & { [type: string]: Record; }) { let max = this._max; this.addGroupTotalPropertiesWhenNotExist(groupTotals); // when dealing with Tree Data, we also need to take the parent's total and add it to the final max if (this._isTreeAggregator && max !== null) { - const parentMax = groupTotals[this._type][this._field]; + const parentMax = groupTotals[this._type][this._field] as number; if (isNumber(parentMax) && parentMax > max) { max = parentMax; } @@ -92,4 +93,4 @@ export class MaxAggregator implements Aggregator { } } } -} +} \ No newline at end of file diff --git a/packages/common/src/aggregators/minAggregator.ts b/packages/common/src/aggregators/minAggregator.ts index 2340ef3b3..09391565e 100644 --- a/packages/common/src/aggregators/minAggregator.ts +++ b/packages/common/src/aggregators/minAggregator.ts @@ -1,3 +1,4 @@ +import type { SlickGroupTotals } from 'slickgrid'; import { isNumber } from '@slickgrid-universal/utils'; import type { Aggregator } from './../interfaces/aggregator.interface'; @@ -65,13 +66,13 @@ export class MinAggregator implements Aggregator { } } - storeResult(groupTotals: any) { + storeResult(groupTotals: SlickGroupTotals & { [type: string]: Record; }) { let min = this._min; this.addGroupTotalPropertiesWhenNotExist(groupTotals); // when dealing with Tree Data, we also need to take the parent's total and add it to the final min if (this._isTreeAggregator && min !== null) { - const parentMin = groupTotals[this._type][this._field]; + const parentMin = groupTotals[this._type][this._field] as number; if (isNumber(parentMin) && parentMin < min) { min = parentMin; } @@ -92,4 +93,4 @@ export class MinAggregator implements Aggregator { } } } -} +} \ No newline at end of file diff --git a/packages/common/src/aggregators/sumAggregator.ts b/packages/common/src/aggregators/sumAggregator.ts index 8ab7d65ac..f7340fda4 100644 --- a/packages/common/src/aggregators/sumAggregator.ts +++ b/packages/common/src/aggregators/sumAggregator.ts @@ -1,3 +1,4 @@ +import type { SlickGroupTotals } from 'slickgrid'; import { isNumber } from '@slickgrid-universal/utils'; import type { Aggregator } from './../interfaces/aggregator.interface'; @@ -70,7 +71,7 @@ export class SumAggregator implements Aggregator { } } - storeResult(groupTotals: any) { + storeResult(groupTotals: SlickGroupTotals & { [type: string]: Record; }) { if (!groupTotals || groupTotals[this._type] === undefined) { groupTotals[this._type] = {}; } @@ -80,8 +81,8 @@ export class SumAggregator implements Aggregator { // when dealing with Tree Data, we also need to take the parent's total and add it to the final sum if (this._isTreeAggregator) { - sum += groupTotals[this._type][this._field]; - itemCount += groupTotals['count'][this._field]; + sum += groupTotals[this._type][this._field] as number; + itemCount += groupTotals['count'][this._field] as number; groupTotals['count'][this._field] = itemCount; } groupTotals[this._type][this._field] = sum; @@ -95,4 +96,4 @@ export class SumAggregator implements Aggregator { groupTotals['count'] = {}; } } -} +} \ No newline at end of file diff --git a/packages/common/src/editors/__tests__/autocompleterEditor.spec.ts b/packages/common/src/editors/__tests__/autocompleterEditor.spec.ts index f6c7be07d..bc2d516e9 100644 --- a/packages/common/src/editors/__tests__/autocompleterEditor.spec.ts +++ b/packages/common/src/editors/__tests__/autocompleterEditor.spec.ts @@ -1,11 +1,12 @@ import 'jest-extended'; +import { SlickDataView, SlickEvent } from 'slickgrid'; + import { Editors } from '../index'; import { AutocompleterEditor } from '../autocompleterEditor'; import { KeyCode, FieldType } from '../../enums/index'; -import { AutocompleterOption, Column, ColumnEditor, EditorArguments, GridOption, SlickDataView, SlickGrid, SlickNamespace } from '../../interfaces/index'; +import { AutocompleterOption, Column, ColumnEditor, EditorArguments, GridOption, type SlickGridUniversal } from '../../interfaces/index'; import { TranslateServiceStub } from '../../../../../test/translateServiceStub'; -declare const Slick: SlickNamespace; const KEY_CHAR_A = 97; const containerId = 'demo-container'; @@ -35,9 +36,9 @@ const gridStub = { getEditorLock: () => getEditorLockMock, getHeaderRowColumn: jest.fn(), render: jest.fn(), - onBeforeEditCell: new Slick.Event(), - onCompositeEditorChange: new Slick.Event(), -} as unknown as SlickGrid; + onBeforeEditCell: new SlickEvent(), + onCompositeEditorChange: new SlickEvent(), +} as unknown as SlickGridUniversal; describe('AutocompleterEditor', () => { let divContainer: HTMLDivElement; @@ -767,7 +768,7 @@ describe('AutocompleterEditor', () => { jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); editor = new AutocompleterEditor(editorArguments); editor.setValue({ value: 'male', label: 'Male' }, true); @@ -783,7 +784,7 @@ describe('AutocompleterEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onBeforeEditSpy = jest.spyOn(gridStub.onBeforeEditCell, 'notify').mockReturnValue({ getReturnValue: () => undefined - }); + } as any); editor = new AutocompleterEditor(editorArguments); const disableSpy = jest.spyOn(editor, 'disable'); @@ -799,10 +800,10 @@ describe('AutocompleterEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onBeforeEditSpy = jest.spyOn(gridStub.onBeforeEditCell, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); editor = new AutocompleterEditor(editorArguments); editor.loadValue(mockItemData); @@ -825,10 +826,10 @@ describe('AutocompleterEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onBeforeEditSpy = jest.spyOn(gridStub.onBeforeEditCell, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); gridOptionMock.compositeEditorOptions = { excludeDisabledFieldFormValues: true }; @@ -851,7 +852,7 @@ describe('AutocompleterEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); gridOptionMock.compositeEditorOptions = { excludeDisabledFieldFormValues: true }; @@ -875,7 +876,7 @@ describe('AutocompleterEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); gridOptionMock.compositeEditorOptions = { excludeDisabledFieldFormValues: true }; @@ -899,10 +900,10 @@ describe('AutocompleterEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onBeforeEditSpy = jest.spyOn(gridStub.onBeforeEditCell, 'notify').mockReturnValue({ getReturnValue: () => undefined - }); + } as any); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); gridOptionMock.autoCommitEdit = true; (mockColumn.internalColumnEditor as ColumnEditor).collection = ['male', 'female']; mockItemData = { id: 123, gender: 'female', isActive: true }; @@ -927,7 +928,7 @@ describe('AutocompleterEditor', () => { jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); mockColumn.internalColumnEditor = { collection: ['Other', 'Male', 'Female'], collectionOverride: (inputCollection) => inputCollection.filter(item => item !== 'other') diff --git a/packages/common/src/editors/__tests__/checkboxEditor.spec.ts b/packages/common/src/editors/__tests__/checkboxEditor.spec.ts index 6f2028a1a..f393b03f1 100644 --- a/packages/common/src/editors/__tests__/checkboxEditor.spec.ts +++ b/packages/common/src/editors/__tests__/checkboxEditor.spec.ts @@ -1,8 +1,9 @@ +import { SlickEvent, type SlickDataView } from 'slickgrid'; + import { Editors } from '../index'; import { CheckboxEditor } from '../checkboxEditor'; -import { AutocompleterOption, Column, ColumnEditor, EditorArguments, GridOption, SlickDataView, SlickGrid, SlickNamespace } from '../../interfaces/index'; +import { AutocompleterOption, Column, ColumnEditor, EditorArguments, GridOption, type SlickGridUniversal } from '../../interfaces/index'; -declare const Slick: SlickNamespace; const KEY_CHAR_SPACE = 32; const containerId = 'demo-container'; @@ -30,9 +31,9 @@ const gridStub = { getEditorLock: () => getEditorLockMock, getHeaderRowColumn: jest.fn(), render: jest.fn(), - onBeforeEditCell: new Slick.Event(), - onCompositeEditorChange: new Slick.Event(), -} as unknown as SlickGrid; + onBeforeEditCell: new SlickEvent(), + onCompositeEditorChange: new SlickEvent(), +} as unknown as SlickGridUniversal; describe('CheckboxEditor', () => { let divContainer: HTMLDivElement; @@ -419,7 +420,7 @@ describe('CheckboxEditor', () => { jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); editor = new CheckboxEditor(editorArguments); editor.setValue(true, true); @@ -435,7 +436,7 @@ describe('CheckboxEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onBeforeEditSpy = jest.spyOn(gridStub.onBeforeEditCell, 'notify').mockReturnValue({ getReturnValue: () => undefined - }); + } as any); editor = new CheckboxEditor(editorArguments); const disableSpy = jest.spyOn(editor, 'disable'); @@ -451,10 +452,10 @@ describe('CheckboxEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onBeforeEditSpy = jest.spyOn(gridStub.onBeforeEditCell, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); editor = new CheckboxEditor(editorArguments); editor.loadValue(mockItemData); @@ -477,10 +478,10 @@ describe('CheckboxEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onBeforeEditSpy = jest.spyOn(gridStub.onBeforeEditCell, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); gridOptionMock.compositeEditorOptions = { excludeDisabledFieldFormValues: true }; @@ -503,7 +504,7 @@ describe('CheckboxEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); gridOptionMock.compositeEditorOptions = { excludeDisabledFieldFormValues: true }; @@ -528,10 +529,10 @@ describe('CheckboxEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onBeforeEditSpy = jest.spyOn(gridStub.onBeforeEditCell, 'notify').mockReturnValue({ getReturnValue: () => undefined - }); + } as any); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); gridOptionMock.autoCommitEdit = true; mockItemData = { id: 1, title: 'task 1', isActive: true }; diff --git a/packages/common/src/editors/__tests__/dateEditor.spec.ts b/packages/common/src/editors/__tests__/dateEditor.spec.ts index 69632315f..0e6939ebe 100644 --- a/packages/common/src/editors/__tests__/dateEditor.spec.ts +++ b/packages/common/src/editors/__tests__/dateEditor.spec.ts @@ -1,12 +1,12 @@ import * as moment from 'moment-mini'; +import { SlickEvent, type SlickDataView } from 'slickgrid'; import { Editors } from '../index'; import { DateEditor } from '../dateEditor'; import { FieldType } from '../../enums/index'; -import { Column, ColumnEditor, EditorArguments, GridOption, SlickDataView, SlickGrid, SlickNamespace } from '../../interfaces/index'; +import { Column, ColumnEditor, EditorArguments, GridOption, type SlickGridUniversal } from '../../interfaces/index'; import { TranslateServiceStub } from '../../../../../test/translateServiceStub'; -declare const Slick: SlickNamespace; const containerId = 'demo-container'; // define a
container to simulate the grid container @@ -36,9 +36,9 @@ const gridStub = { navigateNext: jest.fn(), navigatePrev: jest.fn(), render: jest.fn(), - onBeforeEditCell: new Slick.Event(), - onCompositeEditorChange: new Slick.Event(), -} as unknown as SlickGrid; + onBeforeEditCell: new SlickEvent(), + onCompositeEditorChange: new SlickEvent(), +} as unknown as SlickGridUniversal; describe('DateEditor', () => { let translateService: TranslateServiceStub; @@ -525,7 +525,7 @@ describe('DateEditor', () => { jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); mockColumn.type = FieldType.dateIso; editor = new DateEditor(editorArguments); editor.setValue('2001-01-02', true); @@ -542,7 +542,7 @@ describe('DateEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onBeforeEditSpy = jest.spyOn(gridStub.onBeforeEditCell, 'notify').mockReturnValue({ getReturnValue: () => undefined - }); + } as any); editor = new DateEditor(editorArguments); const disableSpy = jest.spyOn(editor, 'disable'); @@ -558,10 +558,10 @@ describe('DateEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onBeforeEditSpy = jest.spyOn(gridStub.onBeforeEditCell, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); editor = new DateEditor(editorArguments); editor.loadValue(mockItemData); @@ -584,10 +584,10 @@ describe('DateEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onBeforeEditSpy = jest.spyOn(gridStub.onBeforeEditCell, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); gridOptionMock.compositeEditorOptions = { excludeDisabledFieldFormValues: true }; @@ -610,7 +610,7 @@ describe('DateEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); gridOptionMock.compositeEditorOptions = { excludeDisabledFieldFormValues: true }; @@ -636,10 +636,10 @@ describe('DateEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onBeforeEditSpy = jest.spyOn(gridStub.onBeforeEditCell, 'notify').mockReturnValue({ getReturnValue: () => undefined - }); + } as any); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); gridOptionMock.autoCommitEdit = true; mockItemData = { id: 1, startDate: '2001-01-02', isActive: true }; diff --git a/packages/common/src/editors/__tests__/dualInputEditor.spec.ts b/packages/common/src/editors/__tests__/dualInputEditor.spec.ts index b9357fc91..8d8e7a173 100644 --- a/packages/common/src/editors/__tests__/dualInputEditor.spec.ts +++ b/packages/common/src/editors/__tests__/dualInputEditor.spec.ts @@ -1,9 +1,10 @@ +import { SlickEvent, type SlickDataView } from 'slickgrid'; + import { Editors } from '../index'; import { DualInputEditor } from '../dualInputEditor'; import { KeyCode } from '../../enums/index'; -import { Column, ColumnEditor, ColumnEditorDualInput, EditorArguments, GridOption, SlickDataView, SlickGrid, SlickNamespace } from '../../interfaces/index'; +import { Column, ColumnEditor, ColumnEditorDualInput, EditorArguments, GridOption, type SlickGridUniversal } from '../../interfaces/index'; -declare const Slick: SlickNamespace; const KEY_CHAR_0 = 48; const containerId = 'demo-container'; @@ -34,10 +35,10 @@ const gridStub = { getHeaderRowColumn: jest.fn(), getOptions: () => gridOptionMock, render: jest.fn(), - onValidationError: new Slick.Event(), - onBeforeEditCell: new Slick.Event(), - onCompositeEditorChange: new Slick.Event(), -} as unknown as SlickGrid; + onValidationError: new SlickEvent(), + onBeforeEditCell: new SlickEvent(), + onCompositeEditorChange: new SlickEvent(), +} as unknown as SlickGridUniversal; describe('DualInputEditor', () => { let divContainer: HTMLDivElement; @@ -866,7 +867,7 @@ describe('DualInputEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onBeforeEditSpy = jest.spyOn(gridStub.onBeforeEditCell, 'notify').mockReturnValue({ getReturnValue: () => undefined - }); + } as any); editor = new DualInputEditor(editorArguments); const disableSpy = jest.spyOn(editor, 'disable'); @@ -882,10 +883,10 @@ describe('DualInputEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onBeforeEditSpy = jest.spyOn(gridStub.onBeforeEditCell, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); editor = new DualInputEditor(editorArguments); editor.loadValue(mockItemData); @@ -910,10 +911,10 @@ describe('DualInputEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onBeforeEditSpy = jest.spyOn(gridStub.onBeforeEditCell, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); gridOptionMock.compositeEditorOptions = { excludeDisabledFieldFormValues: true }; @@ -942,10 +943,10 @@ describe('DualInputEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onBeforeEditSpy = jest.spyOn(gridStub.onBeforeEditCell, 'notify').mockReturnValue({ getReturnValue: () => undefined - }); + } as any); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); gridOptionMock.autoCommitEdit = true; mockItemData = { id: 1, from: 4, to: 5, isActive: true }; @@ -970,10 +971,10 @@ describe('DualInputEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onBeforeEditSpy = jest.spyOn(gridStub.onBeforeEditCell, 'notify').mockReturnValue({ getReturnValue: () => undefined - }); + } as any); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); gridOptionMock.autoCommitEdit = true; mockItemData = { id: 1, from: 4, to: 5, isActive: true }; diff --git a/packages/common/src/editors/__tests__/floatEditor.spec.ts b/packages/common/src/editors/__tests__/floatEditor.spec.ts index 1f153c8ef..8aa94db48 100644 --- a/packages/common/src/editors/__tests__/floatEditor.spec.ts +++ b/packages/common/src/editors/__tests__/floatEditor.spec.ts @@ -1,9 +1,10 @@ +import { SlickEvent, type SlickDataView } from 'slickgrid'; + import { Editors } from '../index'; import { FloatEditor } from '../floatEditor'; import { KeyCode } from '../../enums/index'; -import { Column, ColumnEditor, EditorArguments, GridOption, SlickDataView, SlickGrid, SlickNamespace } from '../../interfaces/index'; +import { Column, ColumnEditor, EditorArguments, GridOption, type SlickGridUniversal } from '../../interfaces/index'; -declare const Slick: SlickNamespace; const KEY_CHAR_0 = 48; const containerId = 'demo-container'; @@ -34,9 +35,9 @@ const gridStub = { getHeaderRowColumn: jest.fn(), getOptions: () => gridOptionMock, render: jest.fn(), - onBeforeEditCell: new Slick.Event(), - onCompositeEditorChange: new Slick.Event(), -} as unknown as SlickGrid; + onBeforeEditCell: new SlickEvent(), + onCompositeEditorChange: new SlickEvent(), +} as unknown as SlickGridUniversal; describe('FloatEditor', () => { let divContainer: HTMLDivElement; @@ -652,7 +653,7 @@ describe('FloatEditor', () => { jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); editor = new FloatEditor(editorArguments); editor.setValue(123, true); @@ -668,7 +669,7 @@ describe('FloatEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onBeforeEditSpy = jest.spyOn(gridStub.onBeforeEditCell, 'notify').mockReturnValue({ getReturnValue: () => undefined - }); + } as any); editor = new FloatEditor(editorArguments); const disableSpy = jest.spyOn(editor, 'disable'); @@ -684,10 +685,10 @@ describe('FloatEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onBeforeEditSpy = jest.spyOn(gridStub.onBeforeEditCell, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); editor = new FloatEditor(editorArguments); editor.loadValue(mockItemData); @@ -710,10 +711,10 @@ describe('FloatEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onBeforeEditSpy = jest.spyOn(gridStub.onBeforeEditCell, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); gridOptionMock.compositeEditorOptions = { excludeDisabledFieldFormValues: true }; @@ -736,7 +737,7 @@ describe('FloatEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); gridOptionMock.compositeEditorOptions = { excludeDisabledFieldFormValues: true }; @@ -761,10 +762,10 @@ describe('FloatEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onBeforeEditSpy = jest.spyOn(gridStub.onBeforeEditCell, 'notify').mockReturnValue({ getReturnValue: () => undefined - }); + } as any); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); gridOptionMock.autoCommitEdit = true; mockItemData = { id: 1, price: 35, isActive: true }; @@ -789,10 +790,10 @@ describe('FloatEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onBeforeEditSpy = jest.spyOn(gridStub.onBeforeEditCell, 'notify').mockReturnValue({ getReturnValue: () => undefined - }); + } as any); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); gridOptionMock.autoCommitEdit = true; mockItemData = { id: 1, price: 35, isActive: true }; @@ -818,10 +819,10 @@ describe('FloatEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onBeforeEditSpy = jest.spyOn(gridStub.onBeforeEditCell, 'notify').mockReturnValue({ getReturnValue: () => undefined - }); + } as any); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); gridOptionMock.autoCommitEdit = true; mockItemData = { id: 1, price: 35, isActive: true }; diff --git a/packages/common/src/editors/__tests__/inputEditor.spec.ts b/packages/common/src/editors/__tests__/inputEditor.spec.ts index 03a0b7d32..c4169fa5d 100644 --- a/packages/common/src/editors/__tests__/inputEditor.spec.ts +++ b/packages/common/src/editors/__tests__/inputEditor.spec.ts @@ -1,9 +1,10 @@ +import { SlickEvent, type SlickDataView } from 'slickgrid'; + import { Editors } from '../index'; import { InputEditor } from '../inputEditor'; import { KeyCode } from '../../enums/index'; -import { AutocompleterOption, Column, ColumnEditor, EditorArguments, GridOption, SlickDataView, SlickGrid, SlickNamespace } from '../../interfaces/index'; +import { AutocompleterOption, Column, ColumnEditor, EditorArguments, GridOption, type SlickGridUniversal } from '../../interfaces/index'; -declare const Slick: SlickNamespace; jest.useFakeTimers(); const KEY_CHAR_A = 97; @@ -34,9 +35,9 @@ const gridStub = { getHeaderRowColumn: jest.fn(), getOptions: () => gridOptionMock, render: jest.fn(), - onBeforeEditCell: new Slick.Event(), - onCompositeEditorChange: new Slick.Event(), -} as unknown as SlickGrid; + onBeforeEditCell: new SlickEvent(), + onCompositeEditorChange: new SlickEvent(), +} as unknown as SlickGridUniversal; describe('InputEditor (TextEditor)', () => { let divContainer: HTMLDivElement; @@ -547,7 +548,7 @@ describe('InputEditor (TextEditor)', () => { jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); editor = new InputEditor(editorArguments, 'text'); editor.setValue('task 1', true); @@ -563,7 +564,7 @@ describe('InputEditor (TextEditor)', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onBeforeEditSpy = jest.spyOn(gridStub.onBeforeEditCell, 'notify').mockReturnValue({ getReturnValue: () => undefined - }); + } as any); editor = new InputEditor(editorArguments, 'text'); const disableSpy = jest.spyOn(editor, 'disable'); @@ -579,10 +580,10 @@ describe('InputEditor (TextEditor)', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onBeforeEditSpy = jest.spyOn(gridStub.onBeforeEditCell, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); editor = new InputEditor(editorArguments, 'text'); editor.loadValue(mockItemData); @@ -605,10 +606,10 @@ describe('InputEditor (TextEditor)', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onBeforeEditSpy = jest.spyOn(gridStub.onBeforeEditCell, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); gridOptionMock.compositeEditorOptions = { excludeDisabledFieldFormValues: true }; @@ -631,7 +632,7 @@ describe('InputEditor (TextEditor)', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); gridOptionMock.compositeEditorOptions = { excludeDisabledFieldFormValues: true }; @@ -656,10 +657,10 @@ describe('InputEditor (TextEditor)', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onBeforeEditSpy = jest.spyOn(gridStub.onBeforeEditCell, 'notify').mockReturnValue({ getReturnValue: () => undefined - }); + } as any); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); gridOptionMock.autoCommitEdit = true; mockItemData = { id: 1, title: 'task 2', isActive: true }; diff --git a/packages/common/src/editors/__tests__/inputPasswordEditor.spec.ts b/packages/common/src/editors/__tests__/inputPasswordEditor.spec.ts index d45f59d34..e1b331558 100644 --- a/packages/common/src/editors/__tests__/inputPasswordEditor.spec.ts +++ b/packages/common/src/editors/__tests__/inputPasswordEditor.spec.ts @@ -1,9 +1,10 @@ +import { SlickEvent, type SlickDataView } from 'slickgrid'; + import { Editors } from '../index'; import { InputPasswordEditor } from '../inputPasswordEditor'; import { KeyCode } from '../../enums/index'; -import { AutocompleterOption, Column, ColumnEditor, EditorArguments, GridOption, SlickDataView, SlickGrid, SlickNamespace } from '../../interfaces/index'; +import { AutocompleterOption, Column, ColumnEditor, EditorArguments, GridOption, type SlickGridUniversal } from '../../interfaces/index'; -declare const Slick: SlickNamespace; jest.useFakeTimers(); const KEY_CHAR_A = 97; @@ -34,9 +35,9 @@ const gridStub = { getHeaderRowColumn: jest.fn(), getOptions: () => gridOptionMock, render: jest.fn(), - onBeforeEditCell: new Slick.Event(), - onCompositeEditorChange: new Slick.Event(), -} as unknown as SlickGrid; + onBeforeEditCell: new SlickEvent(), + onCompositeEditorChange: new SlickEvent(), +} as unknown as SlickGridUniversal; describe('InputPasswordEditor', () => { let divContainer: HTMLDivElement; @@ -549,7 +550,7 @@ describe('InputPasswordEditor', () => { jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); editor = new InputPasswordEditor(editorArguments); editor.setValue('task 1', true); @@ -565,7 +566,7 @@ describe('InputPasswordEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onBeforeEditSpy = jest.spyOn(gridStub.onBeforeEditCell, 'notify').mockReturnValue({ getReturnValue: () => undefined - }); + } as any); editor = new InputPasswordEditor(editorArguments); const disableSpy = jest.spyOn(editor, 'disable'); @@ -581,10 +582,10 @@ describe('InputPasswordEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onBeforeEditSpy = jest.spyOn(gridStub.onBeforeEditCell, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); editor = new InputPasswordEditor(editorArguments); editor.loadValue(mockItemData); @@ -607,10 +608,10 @@ describe('InputPasswordEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onBeforeEditSpy = jest.spyOn(gridStub.onBeforeEditCell, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); gridOptionMock.compositeEditorOptions = { excludeDisabledFieldFormValues: true }; @@ -633,7 +634,7 @@ describe('InputPasswordEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); gridOptionMock.compositeEditorOptions = { excludeDisabledFieldFormValues: true }; @@ -658,10 +659,10 @@ describe('InputPasswordEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onBeforeEditSpy = jest.spyOn(gridStub.onBeforeEditCell, 'notify').mockReturnValue({ getReturnValue: () => undefined - }); + } as any); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); gridOptionMock.autoCommitEdit = true; mockItemData = { id: 1, title: 'task 2', isActive: true }; diff --git a/packages/common/src/editors/__tests__/integerEditor.spec.ts b/packages/common/src/editors/__tests__/integerEditor.spec.ts index a289b1a44..ef8771b80 100644 --- a/packages/common/src/editors/__tests__/integerEditor.spec.ts +++ b/packages/common/src/editors/__tests__/integerEditor.spec.ts @@ -1,9 +1,10 @@ +import { SlickEvent, type SlickDataView } from 'slickgrid'; + import { Editors } from '../index'; import { IntegerEditor } from '../integerEditor'; import { KeyCode } from '../../enums/index'; -import { Column, ColumnEditor, EditorArguments, GridOption, SlickDataView, SlickGrid, SlickNamespace } from '../../interfaces/index'; +import { Column, ColumnEditor, EditorArguments, GridOption, type SlickGridUniversal } from '../../interfaces/index'; -declare const Slick: SlickNamespace; const KEY_CHAR_0 = 48; const containerId = 'demo-container'; @@ -34,9 +35,9 @@ const gridStub = { getHeaderRowColumn: jest.fn(), getOptions: () => gridOptionMock, render: jest.fn(), - onBeforeEditCell: new Slick.Event(), - onCompositeEditorChange: new Slick.Event(), -} as unknown as SlickGrid; + onBeforeEditCell: new SlickEvent(), + onCompositeEditorChange: new SlickEvent(), +} as unknown as SlickGridUniversal; describe('IntegerEditor', () => { let divContainer: HTMLDivElement; @@ -585,7 +586,7 @@ describe('IntegerEditor', () => { jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); editor = new IntegerEditor(editorArguments); editor.setValue(123, true); @@ -601,7 +602,7 @@ describe('IntegerEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onBeforeEditSpy = jest.spyOn(gridStub.onBeforeEditCell, 'notify').mockReturnValue({ getReturnValue: () => undefined - }); + } as any); editor = new IntegerEditor(editorArguments); const disableSpy = jest.spyOn(editor, 'disable'); @@ -617,10 +618,10 @@ describe('IntegerEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onBeforeEditSpy = jest.spyOn(gridStub.onBeforeEditCell, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); editor = new IntegerEditor(editorArguments); editor.loadValue(mockItemData); @@ -643,7 +644,7 @@ describe('IntegerEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); gridOptionMock.compositeEditorOptions = { excludeDisabledFieldFormValues: true }; @@ -667,7 +668,7 @@ describe('IntegerEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); gridOptionMock.compositeEditorOptions = { excludeDisabledFieldFormValues: true }; @@ -692,10 +693,10 @@ describe('IntegerEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onBeforeEditSpy = jest.spyOn(gridStub.onBeforeEditCell, 'notify').mockReturnValue({ getReturnValue: () => undefined - }); + } as any); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); gridOptionMock.autoCommitEdit = true; mockItemData = { id: 1, price: 35, isActive: true }; @@ -721,10 +722,10 @@ describe('IntegerEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onBeforeEditSpy = jest.spyOn(gridStub.onBeforeEditCell, 'notify').mockReturnValue({ getReturnValue: () => undefined - }); + } as any); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); gridOptionMock.autoCommitEdit = true; mockItemData = { id: 1, price: 35, isActive: true }; diff --git a/packages/common/src/editors/__tests__/longTextEditor.spec.ts b/packages/common/src/editors/__tests__/longTextEditor.spec.ts index 1c64775d4..46cc7fa61 100644 --- a/packages/common/src/editors/__tests__/longTextEditor.spec.ts +++ b/packages/common/src/editors/__tests__/longTextEditor.spec.ts @@ -1,14 +1,15 @@ +import { SlickEvent, type SlickDataView } from 'slickgrid'; + import { Editors } from '../index'; import { LongTextEditor } from '../longTextEditor'; import { KeyCode } from '../../enums/index'; -import { AutocompleterOption, Column, ColumnEditor, EditorArguments, GridOption, SlickDataView, SlickGrid, SlickNamespace } from '../../interfaces/index'; +import { AutocompleterOption, Column, ColumnEditor, EditorArguments, GridOption, type SlickGridUniversal } from '../../interfaces/index'; import { TranslateServiceStub } from '../../../../../test/translateServiceStub'; import * as domUtilities from '../../services/domUtilities'; const mockGetHtmlElementOffset = jest.fn(); // @ts-ignore:2540 domUtilities.getHtmlElementOffset = mockGetHtmlElementOffset; -declare const Slick: SlickNamespace; const KEY_CHAR_A = 97; const containerId = 'demo-container'; @@ -40,9 +41,9 @@ const gridStub = { navigateNext: jest.fn(), navigatePrev: jest.fn(), render: jest.fn(), - onBeforeEditCell: new Slick.Event(), - onCompositeEditorChange: new Slick.Event(), -} as unknown as SlickGrid; + onBeforeEditCell: new SlickEvent(), + onCompositeEditorChange: new SlickEvent(), +} as unknown as SlickGridUniversal; describe('LongTextEditor', () => { let divContainer: HTMLDivElement; @@ -836,7 +837,7 @@ describe('LongTextEditor', () => { jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); editor = new LongTextEditor(editorArguments); editor.setValue('task 2', true); @@ -852,7 +853,7 @@ describe('LongTextEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onBeforeEditSpy = jest.spyOn(gridStub.onBeforeEditCell, 'notify').mockReturnValue({ getReturnValue: () => undefined - }); + } as any); editor = new LongTextEditor(editorArguments); const disableSpy = jest.spyOn(editor, 'disable'); @@ -868,10 +869,10 @@ describe('LongTextEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onBeforeEditSpy = jest.spyOn(gridStub.onBeforeEditCell, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); editor = new LongTextEditor(editorArguments); editor.loadValue(mockItemData); @@ -894,10 +895,10 @@ describe('LongTextEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onBeforeEditSpy = jest.spyOn(gridStub.onBeforeEditCell, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); gridOptionMock.compositeEditorOptions = { excludeDisabledFieldFormValues: true }; @@ -920,7 +921,7 @@ describe('LongTextEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); gridOptionMock.compositeEditorOptions = { excludeDisabledFieldFormValues: true }; @@ -945,10 +946,10 @@ describe('LongTextEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onBeforeEditSpy = jest.spyOn(gridStub.onBeforeEditCell, 'notify').mockReturnValue({ getReturnValue: () => undefined - }); + } as any); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); gridOptionMock.autoCommitEdit = true; mockItemData = { id: 1, title: 'task 2', isActive: true }; diff --git a/packages/common/src/editors/__tests__/multipleSelectEditor.spec.ts b/packages/common/src/editors/__tests__/multipleSelectEditor.spec.ts index 0de93314e..b814a3606 100644 --- a/packages/common/src/editors/__tests__/multipleSelectEditor.spec.ts +++ b/packages/common/src/editors/__tests__/multipleSelectEditor.spec.ts @@ -36,7 +36,7 @@ const gridStub = { navigateNext: jest.fn(), navigatePrev: jest.fn(), render: jest.fn(), -} as unknown as SlickGrid; +} as unknown as SlickGridUniversal; describe('MultipleSelectEditor', () => { let translateService: TranslateServiceStub; diff --git a/packages/common/src/editors/__tests__/selectEditor.spec.ts b/packages/common/src/editors/__tests__/selectEditor.spec.ts index 311750b7e..d98e24b1d 100644 --- a/packages/common/src/editors/__tests__/selectEditor.spec.ts +++ b/packages/common/src/editors/__tests__/selectEditor.spec.ts @@ -1,13 +1,13 @@ // import 3rd party lib multiple-select for the tests import 'multiple-select-vanilla'; +import { SlickEvent, type SlickDataView } from 'slickgrid'; import { Editors } from '../index'; import { SelectEditor } from '../selectEditor'; import { FieldType, OperatorType } from '../../enums/index'; -import { AutocompleterOption, Column, ColumnEditor, EditorArguments, GridOption, SlickDataView, SlickGrid, SlickNamespace } from '../../interfaces/index'; +import { AutocompleterOption, Column, ColumnEditor, EditorArguments, GridOption, type SlickGridUniversal } from '../../interfaces/index'; import { TranslateServiceStub } from '../../../../../test/translateServiceStub'; -declare const Slick: SlickNamespace; const containerId = 'demo-container'; // define a
container to simulate the grid container @@ -37,9 +37,9 @@ const gridStub = { navigateNext: jest.fn(), navigatePrev: jest.fn(), render: jest.fn(), - onBeforeEditCell: new Slick.Event(), - onCompositeEditorChange: new Slick.Event(), -} as unknown as SlickGrid; + onBeforeEditCell: new SlickEvent(), + onCompositeEditorChange: new SlickEvent(), +} as unknown as SlickGridUniversal; describe('SelectEditor', () => { let translateService: TranslateServiceStub; @@ -912,7 +912,7 @@ describe('SelectEditor', () => { jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); editor = new SelectEditor(editorArguments, true); editor.setValue(['male'], true); editor.msInstance?.close(); @@ -929,7 +929,7 @@ describe('SelectEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onBeforeEditSpy = jest.spyOn(gridStub.onBeforeEditCell, 'notify').mockReturnValue({ getReturnValue: () => undefined - }); + } as any); editor = new SelectEditor(editorArguments, true); const disableSpy = jest.spyOn(editor, 'disable'); @@ -945,10 +945,10 @@ describe('SelectEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onBeforeEditSpy = jest.spyOn(gridStub.onBeforeEditCell, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); editor = new SelectEditor(editorArguments, true); editor.loadValue(mockItemData); @@ -972,10 +972,10 @@ describe('SelectEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onBeforeEditSpy = jest.spyOn(gridStub.onBeforeEditCell, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); gridOptionMock.compositeEditorOptions = { excludeDisabledFieldFormValues: true }; @@ -1002,10 +1002,10 @@ describe('SelectEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onBeforeEditSpy = jest.spyOn(gridStub.onBeforeEditCell, 'notify').mockReturnValue({ getReturnValue: () => undefined - }); + } as any); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); gridOptionMock.autoCommitEdit = true; mockItemData = { id: 1, gender: ['male'], isActive: true }; @@ -1032,7 +1032,7 @@ describe('SelectEditor', () => { jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); mockColumn.internalColumnEditor = { collection: [{ value: 'male', label: 'male' }, { value: 'female', label: 'female' }, { value: 'other', label: 'other' }], collectionOverride: (inputCollection) => inputCollection.filter(item => item.value !== 'other') diff --git a/packages/common/src/editors/__tests__/singleSelectEditor.spec.ts b/packages/common/src/editors/__tests__/singleSelectEditor.spec.ts index aa39d9e8f..169afffb9 100644 --- a/packages/common/src/editors/__tests__/singleSelectEditor.spec.ts +++ b/packages/common/src/editors/__tests__/singleSelectEditor.spec.ts @@ -34,7 +34,7 @@ const gridStub = { navigateNext: jest.fn(), navigatePrev: jest.fn(), render: jest.fn(), -} as unknown as SlickGrid; +} as unknown as SlickGridUniversal; describe('SingleSelectEditor', () => { let translateService: TranslateServiceStub; diff --git a/packages/common/src/editors/__tests__/sliderEditor.spec.ts b/packages/common/src/editors/__tests__/sliderEditor.spec.ts index 24eee5583..114595d38 100644 --- a/packages/common/src/editors/__tests__/sliderEditor.spec.ts +++ b/packages/common/src/editors/__tests__/sliderEditor.spec.ts @@ -1,8 +1,9 @@ +import { SlickEvent, type SlickDataView } from 'slickgrid'; + import { Editors } from '../index'; import { SliderEditor } from '../sliderEditor'; -import { Column, ColumnEditor, EditorArguments, GridOption, SlickDataView, SlickGrid, SlickNamespace } from '../../interfaces/index'; +import { Column, ColumnEditor, EditorArguments, GridOption, type SlickGridUniversal } from '../../interfaces/index'; -declare const Slick: SlickNamespace; jest.useFakeTimers(); const containerId = 'demo-container'; @@ -30,10 +31,10 @@ const gridStub = { getHeaderRowColumn: jest.fn(), getOptions: () => gridOptionMock, render: jest.fn(), - onBeforeEditCell: new Slick.Event(), - onMouseEnter: new Slick.Event(), - onCompositeEditorChange: new Slick.Event(), -} as unknown as SlickGrid; + onBeforeEditCell: new SlickEvent(), + onMouseEnter: new SlickEvent(), + onCompositeEditorChange: new SlickEvent(), +} as unknown as SlickGridUniversal; describe('SliderEditor', () => { let divContainer: HTMLDivElement; @@ -232,7 +233,7 @@ describe('SliderEditor', () => { expect(editor.isValueChanged()).toBe(true); expect(editorNumberElm.textContent).toBe('17'); - expect(cellMouseEnterSpy).toHaveBeenCalledWith({ grid: gridStub }, expect.anything()); + expect(cellMouseEnterSpy).toHaveBeenCalledWith({ column: mockColumn, grid: gridStub }, expect.anything()); }); describe('isValueChanged method', () => { @@ -533,7 +534,7 @@ describe('SliderEditor', () => { jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); editor = new SliderEditor(editorArguments); editor.setValue(95, true); @@ -549,7 +550,7 @@ describe('SliderEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onBeforeEditSpy = jest.spyOn(gridStub.onBeforeEditCell, 'notify').mockReturnValue({ getReturnValue: () => undefined - }); + } as any); editor = new SliderEditor(editorArguments); const disableSpy = jest.spyOn(editor, 'disable'); @@ -565,10 +566,10 @@ describe('SliderEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onBeforeEditSpy = jest.spyOn(gridStub.onBeforeEditCell, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); editor = new SliderEditor(editorArguments); editor.loadValue(mockItemData); @@ -591,10 +592,10 @@ describe('SliderEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onBeforeEditSpy = jest.spyOn(gridStub.onBeforeEditCell, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); gridOptionMock.compositeEditorOptions = { excludeDisabledFieldFormValues: true }; @@ -620,10 +621,10 @@ describe('SliderEditor', () => { const getCellSpy = jest.spyOn(gridStub, 'getActiveCell').mockReturnValue(activeCellMock); const onBeforeEditSpy = jest.spyOn(gridStub.onBeforeEditCell, 'notify').mockReturnValue({ getReturnValue: () => undefined - }); + } as any); const onCompositeEditorSpy = jest.spyOn(gridStub.onCompositeEditorChange, 'notify').mockReturnValue({ getReturnValue: () => false - }); + } as any); gridOptionMock.autoCommitEdit = true; mockItemData = { id: 1, price: 93, isActive: true }; diff --git a/packages/common/src/editors/autocompleterEditor.ts b/packages/common/src/editors/autocompleterEditor.ts index 67943b183..155119a1b 100644 --- a/packages/common/src/editors/autocompleterEditor.ts +++ b/packages/common/src/editors/autocompleterEditor.ts @@ -1,3 +1,4 @@ +import { SlickEventData } from 'slickgrid'; import * as autocompleter_ from 'autocompleter'; const autocomplete = (autocompleter_ && autocompleter_['default'] || autocompleter_) as (settings: AutocompleteSettings) => AutocompleteResult; // patch for rollup @@ -19,9 +20,8 @@ import type { EditorValidator, EditorValidationResult, GridOption, - SlickGrid, - SlickNamespace, Locale, + SlickGridUniversal, } from '../interfaces/index'; import { textValidator } from '../editorValidators/textValidator'; import { addAutocompleteLoadingByOverridingFetch } from '../commonEditorFilter'; @@ -34,9 +34,6 @@ import type { TranslaterService } from '../services/translater.service'; // minimum length of chars to type before starting to start querying const MIN_LENGTH = 3; -// using external non-typed js libraries -declare const Slick: SlickNamespace; - /* * An example of a 'detached' editor. * KeyDown events are also handled to provide handling for Tab, Shift-Tab, Esc and Ctrl-Enter. @@ -67,7 +64,7 @@ export class AutocompleterEditor implements Ed disabled = false; /** SlickGrid Grid object */ - grid: SlickGrid; + grid: SlickGridUniversal; /** The property name for labels in the collection */ labelName!: string; @@ -129,7 +126,7 @@ export class AutocompleterEditor implements Ed /** Get Column Editor object */ get columnEditor(): ColumnEditor { - return this.columnDef?.internalColumnEditor || {}; + return this.columnDef?.internalColumnEditor || {} as ColumnEditor; } /** Getter for the Custom Structure if exist */ @@ -156,7 +153,7 @@ export class AutocompleterEditor implements Ed /** Getter for the Grid Options pulled through the Grid Object */ get gridOptions(): GridOption { - return this.grid?.getOptions?.() ?? {}; + return this.grid?.getOptions() ?? {}; } /** Kraaden AutoComplete instance */ @@ -461,7 +458,7 @@ export class AutocompleterEditor implements Ed } grid.onCompositeEditorChange.notify( { ...activeCell, item, grid, column, formValues: compositeEditorOptions.formValues, editors: compositeEditorOptions.editors, triggeredBy }, - { ...new Slick.EventData(), ...event } + { ...new SlickEventData(), ...event as Event } ); } @@ -491,7 +488,7 @@ export class AutocompleterEditor implements Ed // if user wants to hook to the "select", he can do via this "onSelect" // its signature is purposely similar to the "onSelect" callback + some extra arguments (row, cell, column, dataContext) if (typeof this.editorOptions.onSelectItem === 'function') { - const { row, cell } = this.grid.getActiveCell(); + const { row, cell } = this.grid.getActiveCell() || {}; this.editorOptions.onSelectItem(item, row, cell, this.args.column, this.args.item); } diff --git a/packages/common/src/editors/checkboxEditor.ts b/packages/common/src/editors/checkboxEditor.ts index 3bbb35c1d..5c53ee3ce 100644 --- a/packages/common/src/editors/checkboxEditor.ts +++ b/packages/common/src/editors/checkboxEditor.ts @@ -1,14 +1,12 @@ import { setDeepValue, toSentenceCase } from '@slickgrid-universal/utils'; +import { SlickEventData } from 'slickgrid'; import { Constants } from './../constants'; -import type { Column, ColumnEditor, CompositeEditorOption, Editor, EditorArguments, EditorValidator, EditorValidationResult, GridOption, SlickGrid, SlickNamespace } from './../interfaces/index'; +import type { Column, ColumnEditor, CompositeEditorOption, Editor, EditorArguments, EditorValidator, EditorValidationResult, GridOption, SlickGridUniversal, } from './../interfaces/index'; import { createDomElement } from '../services/domUtilities'; import { getDescendantProperty, } from '../services/utilities'; import { BindingEventService } from '../services/bindingEvent.service'; -// using external non-typed js libraries -declare const Slick: SlickNamespace; - /* * An example of a 'detached' editor. * KeyDown events are also handled to provide handling for Tab, Shift-Tab, Esc and Ctrl-Enter. @@ -24,7 +22,7 @@ export class CheckboxEditor implements Editor { disabled = false; /** SlickGrid Grid object */ - grid: SlickGrid; + grid: SlickGridUniversal; /** Grid options */ gridOptions: GridOption; @@ -46,7 +44,7 @@ export class CheckboxEditor implements Editor { /** Get Column Editor object */ get columnEditor(): ColumnEditor { - return this.columnDef && this.columnDef.internalColumnEditor || {}; + return this.columnDef?.internalColumnEditor || {} as ColumnEditor; } /** Getter for the item data context object */ @@ -320,7 +318,7 @@ export class CheckboxEditor implements Editor { } grid.onCompositeEditorChange.notify( { ...activeCell, item, grid, column, formValues: compositeEditorOptions.formValues, editors: compositeEditorOptions.editors, triggeredBy }, - { ...new Slick.EventData(), ...event } + { ...new SlickEventData(), ...event as Event } ); } } diff --git a/packages/common/src/editors/dateEditor.ts b/packages/common/src/editors/dateEditor.ts index d620f8e58..9df090737 100644 --- a/packages/common/src/editors/dateEditor.ts +++ b/packages/common/src/editors/dateEditor.ts @@ -1,6 +1,7 @@ import { setDeepValue } from '@slickgrid-universal/utils'; import * as flatpickr_ from 'flatpickr'; import * as moment_ from 'moment-mini'; +import { SlickEventData } from 'slickgrid'; import type { BaseOptions as FlatpickrBaseOptions } from 'flatpickr/dist/types/options'; import type { Instance as FlatpickrInstance, FlatpickrFn } from 'flatpickr/dist/types/instance'; const flatpickr: FlatpickrFn = (flatpickr_ && flatpickr_['default'] || flatpickr_) as any; // patch for rollup @@ -18,8 +19,7 @@ import type { EditorValidationResult, FlatpickrOption, GridOption, - SlickGrid, - SlickNamespace, + SlickGridUniversal, } from './../interfaces/index'; import { getEditorOptionByName } from './editorUtilities'; import { createDomElement, destroyObjectDomElementProps, emptyElement, } from '../services/domUtilities'; @@ -27,9 +27,6 @@ import { getDescendantProperty, mapFlatpickrDateFormatWithFieldType, mapMomentDa import { BindingEventService } from '../services/bindingEvent.service'; import type { TranslaterService } from '../services/translater.service'; -// using external non-typed js libraries -declare const Slick: SlickNamespace; - /* * An example of a date picker editor using Flatpickr * https://chmln.github.io/flatpickr @@ -52,7 +49,7 @@ export class DateEditor implements Editor { disabled = false; /** SlickGrid Grid object */ - grid: SlickGrid; + grid: SlickGridUniversal; /** Grid options */ gridOptions: GridOption; @@ -80,7 +77,7 @@ export class DateEditor implements Editor { /** Get Column Editor object */ get columnEditor(): ColumnEditor { - return this.columnDef && this.columnDef.internalColumnEditor || {}; + return this.columnDef?.internalColumnEditor || {} as ColumnEditor; } /** Getter for the item data context object */ @@ -465,7 +462,7 @@ export class DateEditor implements Editor { } grid.onCompositeEditorChange.notify( { ...activeCell, item, grid, column, formValues: compositeEditorOptions.formValues, editors: compositeEditorOptions.editors, triggeredBy }, - new Slick.EventData() + new SlickEventData() ); } } \ No newline at end of file diff --git a/packages/common/src/editors/dualInputEditor.ts b/packages/common/src/editors/dualInputEditor.ts index fb5983867..d2c541ccd 100644 --- a/packages/common/src/editors/dualInputEditor.ts +++ b/packages/common/src/editors/dualInputEditor.ts @@ -1,4 +1,5 @@ import { setDeepValue, toSentenceCase } from '@slickgrid-universal/utils'; +import { SlickEventData, SlickEventHandler } from 'slickgrid'; import { KeyCode } from '../enums/keyCode.enum'; import type { @@ -12,18 +13,13 @@ import type { EditorValidator, EditorValidationResult, GridOption, - SlickEventHandler, - SlickGrid, - SlickNamespace, + SlickGridUniversal, } from '../interfaces/index'; import { getDescendantProperty } from '../services/utilities'; import { floatValidator, integerValidator, textValidator } from '../editorValidators'; import { BindingEventService } from '../services/bindingEvent.service'; import { createDomElement } from '../services/domUtilities'; -// using external non-typed js libraries -declare const Slick: SlickNamespace; - /* * An example of a 'detached' editor. * KeyDown events are also handled to provide handling for Tab, Shift-Tab, Esc and Ctrl-Enter. @@ -48,7 +44,7 @@ export class DualInputEditor implements Editor { disabled = false; /** SlickGrid Grid object */ - grid: SlickGrid; + grid: SlickGridUniversal; /** Grid options */ gridOptions: GridOption; @@ -59,7 +55,7 @@ export class DualInputEditor implements Editor { } this.grid = args.grid; this.gridOptions = (this.grid.getOptions() || {}) as GridOption; - this._eventHandler = new Slick.EventHandler(); + this._eventHandler = new SlickEventHandler(); this._bindEventService = new BindingEventService(); this.init(); @@ -73,7 +69,7 @@ export class DualInputEditor implements Editor { /** Get Column Editor object */ get columnEditor(): ColumnEditor { - return this.columnDef && this.columnDef.internalColumnEditor || {}; + return this.columnDef?.internalColumnEditor || {} as ColumnEditor; } /** Getter for the item data context object */ @@ -547,7 +543,7 @@ export class DualInputEditor implements Editor { } grid.onCompositeEditorChange.notify( { ...activeCell, item, grid, column, formValues: compositeEditorOptions.formValues, editors: compositeEditorOptions.editors, triggeredBy }, - { ...new Slick.EventData(), ...event } + { ...new SlickEventData(), ...event as Event } ); } diff --git a/packages/common/src/editors/inputEditor.ts b/packages/common/src/editors/inputEditor.ts index afbff2aa2..6639152b5 100644 --- a/packages/common/src/editors/inputEditor.ts +++ b/packages/common/src/editors/inputEditor.ts @@ -1,4 +1,5 @@ import { setDeepValue, toSentenceCase } from '@slickgrid-universal/utils'; +import { SlickEventData } from 'slickgrid'; import { KeyCode } from '../enums/keyCode.enum'; import type { @@ -10,17 +11,13 @@ import type { EditorValidator, EditorValidationResult, GridOption, - SlickGrid, - SlickNamespace, + SlickGridUniversal, } from '../interfaces/index'; import { getDescendantProperty } from '../services/utilities'; import { textValidator } from '../editorValidators/textValidator'; import { BindingEventService } from '../services/bindingEvent.service'; import { createDomElement } from '../services/domUtilities'; -// using external non-typed js libraries -declare const Slick: SlickNamespace; - /* * An example of a 'detached' editor. * KeyDown events are also handled to provide handling for Tab, Shift-Tab, Esc and Ctrl-Enter. @@ -38,7 +35,7 @@ export class InputEditor implements Editor { disabled = false; /** SlickGrid Grid object */ - grid: SlickGrid; + grid: SlickGridUniversal; /** Grid options */ gridOptions: GridOption; @@ -61,7 +58,7 @@ export class InputEditor implements Editor { /** Get Column Editor object */ get columnEditor(): ColumnEditor { - return this.columnDef && this.columnDef.internalColumnEditor || {}; + return this.columnDef?.internalColumnEditor || {} as ColumnEditor; } /** Getter for the item data context object */ @@ -331,7 +328,7 @@ export class InputEditor implements Editor { } grid.onCompositeEditorChange.notify( { ...activeCell, item, grid, column, formValues: compositeEditorOptions.formValues, editors: compositeEditorOptions.editors, triggeredBy }, - { ...new Slick.EventData(), ...event } + { ...new SlickEventData(), ...event as Event } ); } diff --git a/packages/common/src/editors/longTextEditor.ts b/packages/common/src/editors/longTextEditor.ts index d418be899..1f745ef11 100644 --- a/packages/common/src/editors/longTextEditor.ts +++ b/packages/common/src/editors/longTextEditor.ts @@ -1,4 +1,5 @@ import { setDeepValue, toSentenceCase } from '@slickgrid-universal/utils'; +import { SlickEventData } from 'slickgrid'; import { Constants } from './../constants'; import { KeyCode } from '../enums/keyCode.enum'; @@ -15,8 +16,7 @@ import type { HtmlElementPosition, Locale, LongTextEditorOption, - SlickGrid, - SlickNamespace, + SlickGridUniversal, } from '../interfaces/index'; import { createDomElement, getHtmlElementOffset, } from '../services/domUtilities'; import { getDescendantProperty, getTranslationPrefix, } from '../services/utilities'; @@ -24,9 +24,6 @@ import { BindingEventService } from '../services/bindingEvent.service'; import type { TranslaterService } from '../services/translater.service'; import { textValidator } from '../editorValidators/textValidator'; -// using external non-typed js libraries -declare const Slick: SlickNamespace; - /* * An example of a 'detached' editor. * The UI is added onto document BODY and .position(), .show() and .hide() are implemented. @@ -46,7 +43,7 @@ export class LongTextEditor implements Editor { disabled = false; /** SlickGrid Grid object */ - grid: SlickGrid; + grid: SlickGridUniversal; /** Grid options */ gridOptions: GridOption; @@ -79,7 +76,7 @@ export class LongTextEditor implements Editor { /** Get Column Editor object */ get columnEditor(): ColumnEditor { - return this.columnDef?.internalColumnEditor ?? {}; + return this.columnDef?.internalColumnEditor ?? {} as ColumnEditor; } /** Getter for the item data context object */ @@ -483,7 +480,7 @@ export class LongTextEditor implements Editor { } grid.onCompositeEditorChange.notify( { ...activeCell, item, grid, column, formValues: compositeEditorOptions.formValues, editors: compositeEditorOptions.editors, triggeredBy }, - { ...new Slick.EventData(), ...event } + { ...new SlickEventData(), ...event as Event } ); } diff --git a/packages/common/src/editors/selectEditor.ts b/packages/common/src/editors/selectEditor.ts index 732c758c6..03c5e6790 100644 --- a/packages/common/src/editors/selectEditor.ts +++ b/packages/common/src/editors/selectEditor.ts @@ -1,6 +1,7 @@ -import { multipleSelect, MultipleSelectInstance, MultipleSelectOption, OptionRowData } from 'multiple-select-vanilla'; import { setDeepValue } from '@slickgrid-universal/utils'; import { dequal } from 'dequal/lite'; +import { multipleSelect, MultipleSelectInstance, MultipleSelectOption, OptionRowData } from 'multiple-select-vanilla'; +import { SlickEventData } from 'slickgrid'; import { Constants } from '../constants'; import { FieldType } from './../enums/index'; @@ -18,15 +19,11 @@ import type { GridOption, Locale, SelectOption, - SlickGrid, - SlickNamespace, + SlickGridUniversal, } from './../interfaces/index'; import { buildMultipleSelectDataCollection, CollectionService, emptyElement, findOrDefault, sanitizeTextByAvailableSanitizer, type TranslaterService } from '../services/index'; import { getDescendantProperty, getTranslationPrefix, } from '../services/utilities'; -// using external non-typed js libraries -declare const Slick: SlickNamespace; - /** * Slickgrid editor class for multiple/single select lists */ @@ -88,7 +85,7 @@ export class SelectEditor implements Editor { enableTranslateLabel = false; /** SlickGrid Grid object */ - grid: SlickGrid; + grid: SlickGridUniversal; /** Final collection displayed in the UI, that is after processing filter/sort/override */ finalCollection: any[] = []; @@ -179,7 +176,7 @@ export class SelectEditor implements Editor { /** Get Column Editor object */ get columnEditor(): ColumnEditor | undefined { - return this.columnDef?.internalColumnEditor ?? {}; + return this.columnDef?.internalColumnEditor ?? {} as ColumnEditor; } /** Getter for item data context object */ @@ -776,7 +773,7 @@ export class SelectEditor implements Editor { } grid.onCompositeEditorChange.notify( { ...activeCell, item, grid, column, formValues: compositeEditorOptions.formValues, editors: compositeEditorOptions.editors, triggeredBy }, - new Slick.EventData() + new SlickEventData() ); } } diff --git a/packages/common/src/editors/sliderEditor.ts b/packages/common/src/editors/sliderEditor.ts index eca841d7b..8d079526c 100644 --- a/packages/common/src/editors/sliderEditor.ts +++ b/packages/common/src/editors/sliderEditor.ts @@ -1,4 +1,5 @@ import { setDeepValue, toSentenceCase } from '@slickgrid-universal/utils'; +import { SlickEventData } from 'slickgrid'; import { Constants } from '../constants'; import type { @@ -11,8 +12,7 @@ import type { EditorValidator, EditorValidationResult, GridOption, - SlickGrid, - SlickNamespace, + SlickGridUniversal, SliderOption, } from '../interfaces/index'; import { getEditorOptionByName } from './editorUtilities'; @@ -21,9 +21,6 @@ import { sliderValidator } from '../editorValidators/sliderValidator'; import { BindingEventService } from '../services/bindingEvent.service'; import { createDomElement } from '../services/domUtilities'; -// using external non-typed js libraries -declare const Slick: SlickNamespace; - /* * An example of a 'detached' editor. * KeyDown events are also handled to provide handling for Tab, Shift-Tab, Esc and Ctrl-Enter. @@ -44,7 +41,7 @@ export class SliderEditor implements Editor { disabled = false; /** SlickGrid Grid object */ - grid: SlickGrid; + grid: SlickGridUniversal; /** Grid options */ gridOptions: GridOption; @@ -66,7 +63,7 @@ export class SliderEditor implements Editor { /** Get Column Editor object */ get columnEditor(): ColumnEditor { - return this.columnDef && this.columnDef.internalColumnEditor || {}; + return this.columnDef?.internalColumnEditor ?? {} as ColumnEditor; } /** Getter for the item data context object */ @@ -383,8 +380,8 @@ export class SliderEditor implements Editor { // trigger mouse enter event on the editor for optionally hooked SlickCustomTooltip if (!this.args?.compositeEditorOptions) { this.grid.onMouseEnter.notify( - { grid: this.grid }, - { ...new Slick.EventData(), target: event?.target } + { column: this.columnDef, grid: this.grid }, + { ...new SlickEventData(), ...{ target: event?.target } as Event } ); } } @@ -411,7 +408,7 @@ export class SliderEditor implements Editor { } grid.onCompositeEditorChange.notify( { ...activeCell, item, grid, column, formValues: compositeEditorOptions.formValues, editors: compositeEditorOptions.editors, triggeredBy }, - { ...new Slick.EventData(), ...event } + { ...new SlickEventData(), ...event as Event } ); } diff --git a/packages/common/src/enums/columnReorderFunction.type.ts b/packages/common/src/enums/columnReorderFunction.type.ts index a73ba8fa7..328eff997 100644 --- a/packages/common/src/enums/columnReorderFunction.type.ts +++ b/packages/common/src/enums/columnReorderFunction.type.ts @@ -1,3 +1,4 @@ -import type { Column, SlickEvent, SlickGrid } from '../interfaces/index'; +import type { SlickEvent } from 'slickgrid'; +import type { Column, SlickGridUniversal } from '../interfaces/index'; -export type ColumnReorderFunction = (grid: SlickGrid, headers: any, headerColumnWidthDiff: any, setColumns: (cols: Column[]) => void, setupColumnResize: () => void, columns: Column[], getColumnIndex: (columnId: string) => number, uid: string, trigger: (slickEvent: SlickEvent, data?: any) => void) => void; +export type ColumnReorderFunction = (grid: SlickGridUniversal, headers: any, headerColumnWidthDiff: any, setColumns: (cols: Column[]) => void, setupColumnResize: () => void, columns: Column[], getColumnIndex: (columnId: string) => number, uid: string, trigger: (slickEvent: SlickEvent, data?: any) => void) => void; diff --git a/packages/common/src/enums/usabilityOverrideFn.type.ts b/packages/common/src/enums/usabilityOverrideFn.type.ts index 51c5b6832..6f3b90d37 100644 --- a/packages/common/src/enums/usabilityOverrideFn.type.ts +++ b/packages/common/src/enums/usabilityOverrideFn.type.ts @@ -1,3 +1,3 @@ -import type { SlickGrid } from '../interfaces/slickGrid.interface'; +import { SlickGridUniversal } from '../interfaces/index'; -export type UsabilityOverrideFn = (row: number, dataContext: any, grid: SlickGrid) => boolean; \ No newline at end of file +export type UsabilityOverrideFn = (row: number, dataContext: any, grid: SlickGridUniversal) => boolean; \ No newline at end of file diff --git a/packages/common/src/extensions/__tests__/extensionUtility.spec.ts b/packages/common/src/extensions/__tests__/extensionUtility.spec.ts index 92be37cb9..25320efd2 100644 --- a/packages/common/src/extensions/__tests__/extensionUtility.spec.ts +++ b/packages/common/src/extensions/__tests__/extensionUtility.spec.ts @@ -9,7 +9,7 @@ const gridStub = { setColumns: jest.fn(), setOptions: jest.fn(), registerPlugin: jest.fn(), -} as unknown as SlickGrid; +} as unknown as SlickGridUniversal; const backendUtilityServiceStub = { executeBackendProcessesCallback: jest.fn(), diff --git a/packages/common/src/extensions/__tests__/slickAutoTooltip.spec.ts b/packages/common/src/extensions/__tests__/slickAutoTooltip.spec.ts index a99be7193..f1bab972c 100644 --- a/packages/common/src/extensions/__tests__/slickAutoTooltip.spec.ts +++ b/packages/common/src/extensions/__tests__/slickAutoTooltip.spec.ts @@ -1,9 +1,9 @@ -import { AutoTooltipOption, Column, SlickGrid, SlickNamespace } from '../../interfaces/index'; +import { SlickEvent, SlickEventData } from 'slickgrid'; + +import { AutoTooltipOption, Column, type SlickGridUniversal } from '../../interfaces/index'; import { SharedService } from '../../services/shared.service'; import { SlickAutoTooltip } from '../slickAutoTooltip'; -declare const Slick: SlickNamespace; - let addonOptions: AutoTooltipOption = { enableForCells: true, enableForHeaderCells: true, @@ -16,9 +16,9 @@ const gridStub = { getCellFromEvent: jest.fn(), getOptions: jest.fn(), registerPlugin: jest.fn(), - onHeaderMouseEnter: new Slick.Event(), - onMouseEnter: new Slick.Event(), -} as unknown as SlickGrid; + onHeaderMouseEnter: new SlickEvent(), + onMouseEnter: new SlickEvent(), +} as unknown as SlickGridUniversal; const mockColumns = [ // The column definitions { name: 'Short', field: 'short', width: 100 }, @@ -58,6 +58,7 @@ describe('AutoTooltip Plugin', () => { }); afterEach(() => { + plugin.destroy(); plugin.dispose(); }); @@ -70,7 +71,7 @@ describe('AutoTooltip Plugin', () => { Object.defineProperty(mockNodeElm, 'clientWidth', { writable: true, configurable: true, value: 150 }); Object.defineProperty(mockNodeElm, 'scrollWidth', { writable: true, configurable: true, value: 100 }); - gridStub.onMouseEnter.notify({ grid: gridStub }, new Slick.EventData()); + gridStub.onMouseEnter.notify({ column: mockColumns[0], grid: gridStub }, new SlickEventData()); expect(mockNodeElm.title).toBe(''); }); @@ -84,8 +85,8 @@ describe('AutoTooltip Plugin', () => { Object.defineProperty(mockNodeElm, 'clientWidth', { writable: true, configurable: true, value: 150 }); Object.defineProperty(mockNodeElm, 'scrollWidth', { writable: true, configurable: true, value: 100 }); - const eventData = new Slick.EventData(); - gridStub.onMouseEnter.notify({ grid: gridStub }, new Slick.EventData()); + const eventData = new SlickEventData(); + gridStub.onMouseEnter.notify({ column: mockColumns[0], grid: gridStub }, new SlickEventData()); gridStub.onHeaderMouseEnter.notify({ column: mockColumns[4], grid: gridStub }, eventData); expect(mockNodeElm.title).toBe(''); @@ -110,7 +111,7 @@ describe('AutoTooltip Plugin', () => { Object.defineProperty(mockNodeElm, 'clientWidth', { writable: true, configurable: true, value: 150 }); Object.defineProperty(mockNodeElm, 'scrollWidth', { writable: true, configurable: true, value: 100 }); - gridStub.onMouseEnter.notify({ grid: gridStub }, new Slick.EventData()); + gridStub.onMouseEnter.notify({ column: mockColumns[0], grid: gridStub }, new SlickEventData()); expect(mockNodeElm.title).toBe(''); }); @@ -124,7 +125,7 @@ describe('AutoTooltip Plugin', () => { Object.defineProperty(mockNodeElm, 'clientWidth', { writable: true, configurable: true, value: 140 }); Object.defineProperty(mockNodeElm, 'scrollWidth', { writable: true, configurable: true, value: 175 }); - gridStub.onMouseEnter.notify({ grid: gridStub }, new Slick.EventData()); + gridStub.onMouseEnter.notify({ column: mockColumns[0], grid: gridStub }, new SlickEventData()); expect(mockNodeElm.title).toBe('my super very lon...'); }); @@ -143,7 +144,7 @@ describe('AutoTooltip Plugin', () => { Object.defineProperty(mockNodeElm, 'clientWidth', { writable: true, configurable: true, value: 175 }); Object.defineProperty(mockNodeElm, 'scrollWidth', { writable: true, configurable: true, value: 50 }); - const eventData = new Slick.EventData(); + const eventData = new SlickEventData(); Object.defineProperty(eventData, 'target', { writable: true, configurable: true, value: mockNodeElm }); gridStub.onHeaderMouseEnter.notify({ column: mockColumns[0], grid: gridStub }, eventData); @@ -165,9 +166,9 @@ describe('AutoTooltip Plugin', () => { Object.defineProperty(mockNodeElm, 'clientWidth', { writable: true, configurable: true, value: 144 }); Object.defineProperty(mockHeaderColElm, 'clientWidth', { writable: true, configurable: true, value: 130 }); - const eventData = new Slick.EventData(); + const eventData = new SlickEventData(); Object.defineProperty(eventData, 'target', { writable: true, configurable: true, value: mockHeaderColElm }); - gridStub.onMouseEnter.notify({ grid: gridStub }, eventData); + gridStub.onMouseEnter.notify({ column: mockColumns[0], grid: gridStub }, eventData); gridStub.onHeaderMouseEnter.notify({ column: mockColumns[4], grid: gridStub }, eventData); expect(mockNodeElm.title).toBe('Long header creates tooltip'); @@ -188,9 +189,9 @@ describe('AutoTooltip Plugin', () => { Object.defineProperty(mockNodeElm, 'clientWidth', { writable: true, configurable: true, value: 144 }); Object.defineProperty(mockHeaderColElm, 'clientWidth', { writable: true, configurable: true, value: 130 }); - const eventData = new Slick.EventData(); + const eventData = new SlickEventData(); Object.defineProperty(eventData, 'target', { writable: true, configurable: true, value: mockHeaderColElm }); - gridStub.onMouseEnter.notify({ grid: gridStub }, eventData); + gridStub.onMouseEnter.notify({ column: mockColumns[0], grid: gridStub }, eventData); gridStub.onHeaderMouseEnter.notify({ column: mockColumns[5], grid: gridStub }, eventData); expect(mockNodeElm.title).toBe(''); @@ -212,9 +213,9 @@ describe('AutoTooltip Plugin', () => { Object.defineProperty(mockHeaderColElm, 'clientWidth', { writable: true, configurable: true, value: 50 }); Object.defineProperty(mockHeaderColElm, 'scrollWidth', { writable: true, configurable: true, value: 175 }); - const eventData = new Slick.EventData(); + const eventData = new SlickEventData(); Object.defineProperty(eventData, 'target', { writable: true, configurable: true, value: mockNodeElm }); - gridStub.onMouseEnter.notify({ grid: gridStub }, eventData); + gridStub.onMouseEnter.notify({ column: mockColumns[0], grid: gridStub }, eventData); gridStub.onHeaderMouseEnter.notify({ column: mockColumns[4], grid: gridStub }, eventData); expect(mockNodeElm.title).toBe('Long header creat...'); diff --git a/packages/common/src/extensions/__tests__/slickCellExcelCopyManager.spec.ts b/packages/common/src/extensions/__tests__/slickCellExcelCopyManager.spec.ts index 6c78d6f29..505bf8395 100644 --- a/packages/common/src/extensions/__tests__/slickCellExcelCopyManager.spec.ts +++ b/packages/common/src/extensions/__tests__/slickCellExcelCopyManager.spec.ts @@ -1,11 +1,12 @@ -import { CellRange, EditCommand, Formatter, GridOption, SlickGrid, SlickNamespace, } from '../../interfaces/index'; +import { SlickEvent, SlickEventData } from 'slickgrid'; + +import { CellRange, EditCommand, Formatter, GridOption, type SlickGridUniversal } from '../../interfaces/index'; import { Formatters } from '../../formatters'; import { SharedService } from '../../services/shared.service'; import { SlickCellExcelCopyManager } from '../slickCellExcelCopyManager'; import { SlickCellSelectionModel } from '../slickCellSelectionModel'; import { SlickCellExternalCopyManager } from '../slickCellExternalCopyManager'; -declare const Slick: SlickNamespace; jest.mock('flatpickr', () => { }); const getEditorLockMock = { @@ -21,8 +22,8 @@ const gridStub = { focus: jest.fn(), registerPlugin: jest.fn(), setSelectionModel: jest.fn(), - onKeyDown: new Slick.Event(), -} as unknown as SlickGrid; + onKeyDown: new SlickEvent(), +} as unknown as SlickGridUniversal; const mockCellExternalCopyManager = { constructor: jest.fn(), @@ -31,9 +32,9 @@ const mockCellExternalCopyManager = { getHeaderValueForColumn: jest.fn(), getDataItemValueForColumn: jest.fn(), setDataItemValueForColumn: jest.fn(), - onCopyCells: new Slick.Event(), - onCopyCancelled: new Slick.Event(), - onPasteCells: new Slick.Event(), + onCopyCells: new SlickEvent(), + onCopyCancelled: new SlickEvent(), + onPasteCells: new SlickEvent(), } as unknown as SlickCellExternalCopyManager; const mockCellSelectionModel = { @@ -44,7 +45,7 @@ const mockCellSelectionModel = { setSelectedRanges: jest.fn(), getSelectedRows: jest.fn(), setSelectedRows: jest.fn(), - onSelectedRangesChanged: new Slick.Event(), + onSelectedRangesChanged: new SlickEvent(), } as unknown as SlickCellSelectionModel; jest.mock('../slickCellSelectionModel', () => ({ @@ -125,11 +126,11 @@ describe('CellExcelCopyManager', () => { const mockOnPasteCell = jest.fn(); plugin.init(gridStub, { onCopyCells: mockOnCopy, onCopyCancelled: mockOnCopyCancel, onPasteCells: mockOnPasteCell }); - mockCellExternalCopyManager.onCopyCells.notify(mockSelectRangeEvent, new Slick.EventData(), gridStub); + mockCellExternalCopyManager.onCopyCells.notify(mockSelectRangeEvent, new SlickEventData(), gridStub); expect(handlerSpy).toHaveBeenCalledTimes(3); expect(handlerSpy).toHaveBeenCalledWith( - { notify: expect.anything(), subscribe: expect.anything(), unsubscribe: expect.anything(), }, + expect.any(SlickEvent), expect.anything() ); expect(mockOnCopy).toHaveBeenCalledWith(expect.anything(), mockSelectRangeEvent); @@ -144,11 +145,11 @@ describe('CellExcelCopyManager', () => { const mockOnPasteCell = jest.fn(); plugin.init(gridStub, { onCopyCells: mockOnCopy, onCopyCancelled: mockOnCopyCancel, onPasteCells: mockOnPasteCell }); - mockCellExternalCopyManager.onCopyCancelled.notify(mockSelectRangeEvent, new Slick.EventData(), gridStub); + mockCellExternalCopyManager.onCopyCancelled.notify(mockSelectRangeEvent, new SlickEventData(), gridStub); expect(handlerSpy).toHaveBeenCalledTimes(3); expect(handlerSpy).toHaveBeenCalledWith( - { notify: expect.anything(), subscribe: expect.anything(), unsubscribe: expect.anything(), }, + expect.any(SlickEvent), expect.anything() ); expect(mockOnCopy).not.toHaveBeenCalledWith(expect.anything(), mockSelectRangeEvent); @@ -163,11 +164,11 @@ describe('CellExcelCopyManager', () => { const mockOnPasteCell = jest.fn(); plugin.init(gridStub, { onCopyCells: mockOnCopy, onCopyCancelled: mockOnCopyCancel, onPasteCells: mockOnPasteCell }); - mockCellExternalCopyManager.onPasteCells.notify(mockSelectRangeEvent, new Slick.EventData(), gridStub); + mockCellExternalCopyManager.onPasteCells.notify(mockSelectRangeEvent, new SlickEventData(), gridStub); expect(handlerSpy).toHaveBeenCalledTimes(3); expect(handlerSpy).toHaveBeenCalledWith( - { notify: expect.anything(), subscribe: expect.anything(), unsubscribe: expect.anything(), }, + expect.any(SlickEvent), expect.anything() ); expect(mockOnCopy).not.toHaveBeenCalledWith(expect.anything(), mockSelectRangeEvent); @@ -294,7 +295,7 @@ describe('CellExcelCopyManager', () => { it('should expect "addItem" method to be called after calling "newRowCreator" callback', () => { plugin.init(gridStub); const mockGetData = { addItem: jest.fn() }; - const getDataSpy = jest.spyOn(gridStub, 'getData').mockReturnValue(mockGetData); + const getDataSpy = jest.spyOn(gridStub, 'getData').mockReturnValue(mockGetData as any); const addItemSpy = jest.spyOn(mockGetData, 'addItem'); plugin.addonOptions!.newRowCreator!(2); diff --git a/packages/common/src/extensions/__tests__/slickCellExternalCopyManager.spec.ts b/packages/common/src/extensions/__tests__/slickCellExternalCopyManager.spec.ts index f925dac18..67c97341e 100644 --- a/packages/common/src/extensions/__tests__/slickCellExternalCopyManager.spec.ts +++ b/packages/common/src/extensions/__tests__/slickCellExternalCopyManager.spec.ts @@ -1,11 +1,11 @@ import 'jest-extended'; +import { type SelectionModel, SlickEvent, SlickEventData, SlickRange } from 'slickgrid'; -import { Column, GridOption, SlickGrid, SlickNamespace, } from '../../interfaces/index'; +import { Column, GridOption, type SlickGridUniversal } from '../../interfaces/index'; import { SlickCellSelectionModel } from '../slickCellSelectionModel'; import { SlickCellExternalCopyManager } from '../slickCellExternalCopyManager'; import { InputEditor } from '../../editors/inputEditor'; -declare const Slick: SlickNamespace; jest.mock('flatpickr', () => { }); const mockGetSelectionModel = { @@ -30,9 +30,9 @@ const gridStub = { setSelectionModel: jest.fn(), updateCell: jest.fn(), render: jest.fn(), - onCellChange: new Slick.Event(), - onKeyDown: new Slick.Event(), -} as unknown as SlickGrid; + onCellChange: new SlickEvent(), + onKeyDown: new SlickEvent(), +} as unknown as SlickGridUniversal; const mockCellSelectionModel = { constructor: jest.fn(), @@ -42,7 +42,7 @@ const mockCellSelectionModel = { setSelectedRanges: jest.fn(), getSelectedRows: jest.fn(), setSelectedRows: jest.fn(), - onSelectedRangesChanged: new Slick.Event(), + onSelectedRangesChanged: new SlickEvent(), } as unknown as SlickCellSelectionModel; const mockTextEditor = { @@ -103,11 +103,11 @@ describe('CellExternalCopyManager', () => { }); it('should throw an error initializing the plugin without a selection model', (done) => { - jest.spyOn(gridStub, 'getSelectionModel').mockReturnValue(null); + jest.spyOn(gridStub, 'getSelectionModel').mockReturnValue(null as any); try { plugin.init(gridStub); } catch (error) { - expect(error.message).toBe('Selection model is mandatory for this plugin. Please set a selection model on the grid before adding this plugin: grid.setSelectionModel(new Slick.CellSelectionModel())'); + expect(error.message).toBe('Selection model is mandatory for this plugin. Please set a selection model on the grid before adding this plugin: grid.setSelectionModel(new SlickCellSelectionModel())'); done(); } }); @@ -117,8 +117,8 @@ describe('CellExternalCopyManager', () => { const gridFocusSpy = jest.spyOn(gridStub, 'focus'); plugin.init(gridStub); - const eventData = { ...new Slick.EventData(), preventDefault: jest.fn() }; - mockCellSelectionModel.onSelectedRangesChanged.notify([{ fromCell: 0, fromRow: 0, toCell: 0, toRow: 0 }], eventData, gridStub); + const eventData = { ...new SlickEventData(), preventDefault: jest.fn() } as unknown as SlickEventData; + mockCellSelectionModel.onSelectedRangesChanged.notify([new SlickRange(0, 0, 0, 0)], eventData, gridStub); expect(gridFocusSpy).toHaveBeenCalled(); }); @@ -212,7 +212,7 @@ describe('CellExternalCopyManager', () => { const mockOnCopySuccess = jest.fn(); const clearSpy = jest.spyOn(plugin, 'clearCopySelection'); - jest.spyOn(gridStub.getSelectionModel(), 'getSelectedRanges').mockReturnValue([{ fromRow: 0, fromCell: 1, toRow: 2, toCell: 2 }]); + jest.spyOn(gridStub.getSelectionModel() as SelectionModel, 'getSelectedRanges').mockReturnValue([new SlickRange(0, 1, 2, 2)]); plugin.init(gridStub, { clearCopySelectionDelay: 1, clipboardPasteDelay: 2, includeHeaderWhenCopying: true, onCopyCancelled: mockOnCopyCancelled, onCopyInit: mockOnCopyInit, onCopyCells: mockOnCopyCells, onCopySuccess: mockOnCopySuccess }); @@ -231,7 +231,7 @@ describe('CellExternalCopyManager', () => { expect(clearSpy).toHaveBeenCalled(); expect(mockOnCopyInit).toHaveBeenCalled(); - expect(mockOnCopyCancelled).toHaveBeenCalledWith(expect.any(Object), { ranges: [{ fromCell: 1, fromRow: 0, toCell: 2, toRow: 2 }] }); + expect(mockOnCopyCancelled).toHaveBeenCalledWith(expect.any(Object), { ranges: [new SlickRange(0, 1, 2, 2)] }); expect(mockOnCopyCells).toHaveBeenCalledWith(expect.any(Object), { ranges: expect.toBeArray() }); const getActiveCellSpy = jest.spyOn(gridStub, 'getActiveCell'); @@ -256,7 +256,7 @@ describe('CellExternalCopyManager', () => { const mockClipboard = () => ({ setData: mockSetData }); Object.defineProperty(window, 'clipboardData', { writable: true, configurable: true, value: mockClipboard() }); const clearSpy = jest.spyOn(plugin, 'clearCopySelection'); - jest.spyOn(gridStub.getSelectionModel(), 'getSelectedRanges').mockReturnValue([{ fromRow: 0, fromCell: 1, toRow: 1, toCell: 2 }]); + jest.spyOn(gridStub.getSelectionModel() as SelectionModel, 'getSelectedRanges').mockReturnValue([new SlickRange(0, 1, 1, 2)]); plugin.init(gridStub, { clipboardPasteDelay: 1, clearCopySelectionDelay: 1, includeHeaderWhenCopying: true, onCopyInit: mockOnCopyInit, onCopyCells: mockOnCopyCells }); @@ -294,7 +294,7 @@ describe('CellExternalCopyManager', () => { clipCommand = cmd; cmd.execute(); }; - jest.spyOn(gridStub.getSelectionModel() as SelectionModel, 'getSelectedRanges').mockReturnValueOnce([new Slick.Range(0, 1, 1, 2)]).mockReturnValueOnce(null as any); + jest.spyOn(gridStub.getSelectionModel() as SelectionModel, 'getSelectedRanges').mockReturnValueOnce([new SlickRange(0, 1, 1, 2)]).mockReturnValueOnce(null as any); plugin.init(gridStub, { clipboardPasteDelay: 1, clearCopySelectionDelay: 1, includeHeaderWhenCopying: true, clipboardCommandHandler }); const keyDownCtrlCopyEvent = new Event('keydown'); @@ -314,7 +314,7 @@ describe('CellExternalCopyManager', () => { Object.defineProperty(keyDownCtrlPasteEvent, 'isPropagationStopped', { writable: true, configurable: true, value: jest.fn() }); Object.defineProperty(keyDownCtrlPasteEvent, 'isImmediatePropagationStopped', { writable: true, configurable: true, value: jest.fn() }); gridStub.onKeyDown.notify({ cell: 0, row: 0, grid: gridStub }, keyDownCtrlPasteEvent, gridStub); - document.querySelector('textarea').value = `Doe\tserialized output`; + document.querySelector('textarea')!.value = `Doe\tserialized output`; setTimeout(() => { expect(getActiveCellSpy).toHaveBeenCalled(); @@ -329,7 +329,7 @@ describe('CellExternalCopyManager', () => { }); it('should Copy, Paste and run Execute clip command with only 1 cell to copy', (done) => { - jest.spyOn(gridStub.getSelectionModel() as SelectionModel, 'getSelectedRanges').mockReturnValueOnce([new Slick.Range(0, 1, 1, 2)]).mockReturnValueOnce([new Slick.Range(0, 1, 1, 2)]); + jest.spyOn(gridStub.getSelectionModel() as SelectionModel, 'getSelectedRanges').mockReturnValueOnce([new SlickRange(0, 1, 1, 2)]).mockReturnValueOnce([new SlickRange(0, 1, 1, 2)]); let clipCommand; const clipboardCommandHandler = (cmd) => { clipCommand = cmd; @@ -355,7 +355,7 @@ describe('CellExternalCopyManager', () => { Object.defineProperty(keyDownCtrlPasteEvent, 'isPropagationStopped', { writable: true, configurable: true, value: jest.fn() }); Object.defineProperty(keyDownCtrlPasteEvent, 'isImmediatePropagationStopped', { writable: true, configurable: true, value: jest.fn() }); gridStub.onKeyDown.notify({ cell: 0, row: 0, grid: gridStub }, keyDownCtrlPasteEvent, gridStub); - document.querySelector('textarea').value = `Smith`; + document.querySelector('textarea')!.value = `Smith`; setTimeout(() => { expect(getActiveCellSpy).toHaveBeenCalled(); @@ -379,7 +379,7 @@ describe('CellExternalCopyManager', () => { it('should Copy, Paste but not execute run clipCommandHandler when defined', (done) => { const mockClipboardCommandHandler = jest.fn(); - jest.spyOn(gridStub.getSelectionModel(), 'getSelectedRanges').mockReturnValueOnce([{ fromRow: 0, fromCell: 1, toRow: 2, toCell: 2 }]).mockReturnValueOnce(null); + jest.spyOn(gridStub.getSelectionModel() as SelectionModel, 'getSelectedRanges').mockReturnValueOnce([new SlickRange(0, 1, 2, 2)]).mockReturnValueOnce(null as any); plugin.init(gridStub, { clearCopySelectionDelay: 1, clipboardPasteDelay: 1, includeHeaderWhenCopying: true, clipboardCommandHandler: mockClipboardCommandHandler }); @@ -398,7 +398,7 @@ describe('CellExternalCopyManager', () => { Object.defineProperty(keyDownCtrlPasteEvent, 'isPropagationStopped', { writable: true, configurable: true, value: jest.fn() }); Object.defineProperty(keyDownCtrlPasteEvent, 'isImmediatePropagationStopped', { writable: true, configurable: true, value: jest.fn() }); gridStub.onKeyDown.notify({ cell: 0, row: 0, grid: gridStub }, keyDownCtrlPasteEvent, gridStub); - document.querySelector('textarea').value = `Doe\tserialized output`; + document.querySelector('textarea')!.value = `Doe\tserialized output`; setTimeout(() => { expect(getActiveCellSpy).toHaveBeenCalled(); @@ -409,7 +409,7 @@ describe('CellExternalCopyManager', () => { it('should Copy, Paste without completing it because it does not know where to paste it', (done) => { const mockClipboardCommandHandler = jest.fn(); - jest.spyOn(gridStub.getSelectionModel(), 'getSelectedRanges').mockReturnValueOnce([{ fromRow: 0, fromCell: 1, toRow: 2, toCell: 2 }]).mockReturnValueOnce(null); + jest.spyOn(gridStub.getSelectionModel() as SelectionModel, 'getSelectedRanges').mockReturnValueOnce([new SlickRange(0, 1, 2, 2)]).mockReturnValueOnce(null as any); plugin.init(gridStub, { clearCopySelectionDelay: 1, clipboardPasteDelay: 1, includeHeaderWhenCopying: true, clipboardCommandHandler: mockClipboardCommandHandler }); @@ -428,7 +428,7 @@ describe('CellExternalCopyManager', () => { Object.defineProperty(keyDownCtrlPasteEvent, 'isPropagationStopped', { writable: true, configurable: true, value: jest.fn() }); Object.defineProperty(keyDownCtrlPasteEvent, 'isImmediatePropagationStopped', { writable: true, configurable: true, value: jest.fn() }); gridStub.onKeyDown.notify({ cell: 0, row: 0, grid: gridStub }, keyDownCtrlPasteEvent, gridStub); - document.querySelector('textarea').value = `Doe\tserialized output`; + document.querySelector('textarea')!.value = `Doe\tserialized output`; setTimeout(() => { expect(getActiveCellSpy).toHaveBeenCalled(); @@ -442,7 +442,7 @@ describe('CellExternalCopyManager', () => { const mockOnPasteCells = jest.fn(); const renderSpy = jest.spyOn(gridStub, 'render'); const setDataSpy = jest.spyOn(gridStub, 'setData'); - jest.spyOn(gridStub.getSelectionModel(), 'getSelectedRanges').mockReturnValueOnce([{ fromRow: 0, fromCell: 1, toRow: 2, toCell: 2 }]).mockReturnValueOnce(null); + jest.spyOn(gridStub.getSelectionModel() as SelectionModel, 'getSelectedRanges').mockReturnValueOnce([new SlickRange(0, 1, 2, 2)]).mockReturnValueOnce(null as any); let clipCommand; const clipboardCommandHandler = (cmd) => { clipCommand = cmd; @@ -480,7 +480,7 @@ describe('CellExternalCopyManager', () => { expect(getDataItemSpy).toHaveBeenCalled(); expect(setData2Spy).toHaveBeenCalledWith([{ firstName: 'John', lastName: 'Doe', age: 30 }, { firstName: 'Jane', lastName: 'Doe' }]); expect(render2Spy).toHaveBeenCalled(); - expect(mockOnPasteCells).toHaveBeenCalledWith(expect.toBeObject(), { ranges: [{ fromCell: 0, fromRow: 3, toCell: 1, toRow: 3 }] }); + expect(mockOnPasteCells).toHaveBeenCalledWith(expect.toBeObject(), { ranges: [new SlickRange(3, 0, 3, 1)] }); done(); }, 2); }); diff --git a/packages/common/src/extensions/__tests__/slickCellMenu.plugin.spec.ts b/packages/common/src/extensions/__tests__/slickCellMenu.plugin.spec.ts index 2012c3cb3..aa308dcb3 100644 --- a/packages/common/src/extensions/__tests__/slickCellMenu.plugin.spec.ts +++ b/packages/common/src/extensions/__tests__/slickCellMenu.plugin.spec.ts @@ -1,14 +1,13 @@ import { BasePubSubService } from '@slickgrid-universal/event-pub-sub'; import { deepCopy } from '@slickgrid-universal/utils'; +import { SlickEvent, SlickEventData } from 'slickgrid'; -import { CellMenu, Column, ElementPosition, GridOption, MenuCommandItem, MenuOptionItem, SlickGrid, SlickNamespace, } from '../../interfaces/index'; +import { CellMenu, Column, ElementPosition, GridOption, MenuCommandItem, MenuOptionItem, type SlickGridUniversal } from '../../interfaces/index'; import { SlickCellMenu } from '../slickCellMenu'; import { BackendUtilityService, SharedService, } from '../../services'; import { ExtensionUtility } from '../../extensions/extensionUtility'; import { TranslateServiceStub } from '../../../../../test/translateServiceStub'; -declare const Slick: SlickNamespace; - const removeExtraSpaces = (textS) => `${textS}`.replace(/[\n\r]\s+/g, ''); const gridOptionsMock = { @@ -71,10 +70,10 @@ const gridStub = { setOptions: jest.fn(), setSortColumns: jest.fn(), updateColumnHeader: jest.fn(), - onClick: new Slick.Event(), - onScroll: new Slick.Event(), - onSort: new Slick.Event(), -} as unknown as SlickGrid; + onClick: new SlickEvent(), + onScroll: new SlickEvent(), + onSort: new SlickEvent(), +} as unknown as SlickGridUniversal; const pubSubServiceStub = { publish: jest.fn(), @@ -201,7 +200,7 @@ describe('CellMenu Plugin', () => { beforeEach(() => { slickCellElm = document.createElement('div'); slickCellElm.className = 'slick-cell'; - eventData = { ...new Slick.EventData(), preventDefault: jest.fn() }; + eventData = { ...new SlickEventData(), preventDefault: jest.fn() }; eventData.target = slickCellElm; jest.spyOn(SharedService.prototype, 'slickGrid', 'get').mockReturnValue(gridStub); diff --git a/packages/common/src/extensions/__tests__/slickCellRangeDecorator.spec.ts b/packages/common/src/extensions/__tests__/slickCellRangeDecorator.spec.ts index 672a2ac57..2f5e71ec1 100644 --- a/packages/common/src/extensions/__tests__/slickCellRangeDecorator.spec.ts +++ b/packages/common/src/extensions/__tests__/slickCellRangeDecorator.spec.ts @@ -1,16 +1,15 @@ import 'jest-extended'; -import { GridOption, SlickGrid, SlickNamespace, } from '../../interfaces/index'; +import { GridOption, type SlickGridUniversal } from '../../interfaces/index'; import { SlickCellRangeDecorator } from '../slickCellRangeDecorator'; -declare const Slick: SlickNamespace; jest.mock('flatpickr', () => { }); const gridStub = { getActiveCell: jest.fn(), getActiveCanvasNode: jest.fn(), getCellNodeBox: jest.fn(), -} as unknown as SlickGrid; +} as unknown as SlickGridUniversal; describe('CellRangeDecorator Plugin', () => { const mockEventCallback = () => { }; @@ -47,9 +46,11 @@ describe('CellRangeDecorator Plugin', () => { }); it('should dispose of the addon', () => { - const disposeSpy = jest.spyOn(plugin, 'dispose'); + plugin.init(); + const disposeSpy = jest.spyOn(plugin, 'destroy'); const hideSpy = jest.spyOn(plugin, 'hide'); - plugin.dispose(); + + plugin.destroy(); expect(disposeSpy).toHaveBeenCalled(); expect(hideSpy).toHaveBeenCalled(); }); @@ -70,7 +71,7 @@ describe('CellRangeDecorator Plugin', () => { it('should Show range when called and calculate new position when getCellNodeBox returns a cell position', () => { const divContainer = document.createElement('div'); jest.spyOn(gridStub, 'getActiveCanvasNode').mockReturnValue(divContainer); - jest.spyOn(gridStub, 'getCellNodeBox').mockReturnValue({ top: 25, left: 26, right: 27, bottom: 12, height: 33, width: 44, visible: true }); + jest.spyOn(gridStub, 'getCellNodeBox').mockReturnValue({ top: 25, left: 26, right: 27, bottom: 12 }); plugin = new SlickCellRangeDecorator(gridStub, { offset: { top: 20, left: 5, width: 12, height: 33 } }); plugin.show({ fromCell: 1, fromRow: 2, toCell: 3, toRow: 4 }); diff --git a/packages/common/src/extensions/__tests__/slickCellRangeSelector.spec.ts b/packages/common/src/extensions/__tests__/slickCellRangeSelector.spec.ts index e835e3baa..522c73b06 100644 --- a/packages/common/src/extensions/__tests__/slickCellRangeSelector.spec.ts +++ b/packages/common/src/extensions/__tests__/slickCellRangeSelector.spec.ts @@ -1,9 +1,9 @@ import 'jest-extended'; +import { SlickEvent } from 'slickgrid'; -import { GridOption, SlickGrid, SlickNamespace, } from '../../interfaces/index'; +import { GridOption, type SlickGridUniversal } from '../../interfaces/index'; import { SlickCellRangeSelector } from '../slickCellRangeSelector'; -declare const Slick: SlickNamespace; const GRID_UID = 'slickgrid_12345'; jest.mock('flatpickr', () => { }); @@ -40,12 +40,12 @@ const gridStub = { getUID: () => GRID_UID, focus: jest.fn(), scrollCellIntoView: jest.fn(), - onDragInit: new Slick.Event(), - onDragStart: new Slick.Event(), - onDrag: new Slick.Event(), - onDragEnd: new Slick.Event(), - onScroll: new Slick.Event(), -} as unknown as SlickGrid; + onDragInit: new SlickEvent(), + onDragStart: new SlickEvent(), + onDrag: new SlickEvent(), + onDragEnd: new SlickEvent(), + onScroll: new SlickEvent(), +} as unknown as SlickGridUniversal; describe('CellRangeSelector Plugin', () => { let plugin: SlickCellRangeSelector; @@ -316,7 +316,7 @@ describe('CellRangeSelector Plugin', () => { jest.spyOn(gridStub, 'getCellFromEvent').mockReturnValue({ cell: 2, row: 3 }); jest.spyOn(gridStub, 'canCellBeSelected').mockReturnValueOnce(true).mockReturnValueOnce(false); jest.spyOn(gridStub, 'getCellFromPoint').mockReturnValue({ cell: 4, row: 5 }); - jest.spyOn(gridStub, 'getCellNodeBox').mockReturnValue({ right: 2, bottom: 3, left: 4, top: 5, height: 20, width: 33, visible: true }); + jest.spyOn(gridStub, 'getCellNodeBox').mockReturnValue({ right: 2, bottom: 3, left: 4, top: 5 }); const focusSpy = jest.spyOn(gridStub, 'focus'); const onBeforeCellRangeSpy = jest.spyOn(plugin.onBeforeCellRangeSelected, 'notify').mockReturnValue({ getReturnValue: () => true @@ -370,7 +370,7 @@ describe('CellRangeSelector Plugin', () => { jest.spyOn(gridStub, 'getCellFromEvent').mockReturnValue({ cell: 2, row: 3 }); jest.spyOn(gridStub, 'canCellBeSelected').mockReturnValueOnce(true); jest.spyOn(gridStub, 'getCellFromPoint').mockReturnValue({ cell: 4, row: 5 }); - jest.spyOn(gridStub, 'getCellNodeBox').mockReturnValue({ right: 2, bottom: 3, left: 4, top: 5, height: 20, width: 33, visible: true }); + jest.spyOn(gridStub, 'getCellNodeBox').mockReturnValue({ right: 2, bottom: 3, left: 4, top: 5 }); const focusSpy = jest.spyOn(gridStub, 'focus'); const onBeforeCellRangeSpy = jest.spyOn(plugin.onBeforeCellRangeSelected, 'notify').mockReturnValue({ getReturnValue: () => true diff --git a/packages/common/src/extensions/__tests__/slickCellSelectionModel.spec.ts b/packages/common/src/extensions/__tests__/slickCellSelectionModel.spec.ts index 1d692a59a..c565333fb 100644 --- a/packages/common/src/extensions/__tests__/slickCellSelectionModel.spec.ts +++ b/packages/common/src/extensions/__tests__/slickCellSelectionModel.spec.ts @@ -1,10 +1,10 @@ import 'jest-extended'; +import { SlickEvent, SlickRange } from 'slickgrid'; -import { GridOption, SlickGrid, SlickNamespace, SlickRange, } from '../../interfaces/index'; +import { GridOption, type SlickGridUniversal } from '../../interfaces/index'; import { SlickCellRangeSelector } from '../slickCellRangeSelector'; import { SlickCellSelectionModel } from '../slickCellSelectionModel'; -declare const Slick: SlickNamespace; const GRID_UID = 'slickgrid_12345'; const NB_ITEMS = 200; const CALCULATED_PAGE_ROW_COUNT = 23; // pageRowCount with our mocked sizes is 23 => ((600 - 17) / 25) @@ -59,11 +59,11 @@ const gridStub = { scrollCellIntoView: jest.fn(), scrollRowIntoView: jest.fn(), unregisterPlugin: jest.fn(), - onActiveCellChanged: new Slick.Event(), - onKeyDown: new Slick.Event(), - onCellRangeSelected: new Slick.Event(), - onBeforeCellRangeSelected: new Slick.Event(), -} as unknown as SlickGrid; + onActiveCellChanged: new SlickEvent(), + onKeyDown: new SlickEvent(), + onCellRangeSelected: new SlickEvent(), + onBeforeCellRangeSelected: new SlickEvent(), +} as unknown as SlickGridUniversal; describe('CellSelectionModel Plugin', () => { let plugin: SlickCellSelectionModel; @@ -159,7 +159,7 @@ describe('CellSelectionModel Plugin', () => { jest.spyOn(plugin, 'getSelectedRanges').mockReturnValue([ { fromCell: 1, fromRow: 2, toCell: 3, toRow: 4 }, { fromCell: 2, fromRow: 3, toCell: 3, toRow: 4 } - ]); + ] as unknown as SlickRange[]); const setSelectedRangesSpy = jest.spyOn(plugin, 'setSelectedRanges'); plugin.refreshSelections(); @@ -190,7 +190,7 @@ describe('CellSelectionModel Plugin', () => { const setSelectRangeSpy = jest.spyOn(plugin, 'setSelectedRanges'); plugin.init(gridStub); - plugin.cellRangeSelector.onCellRangeSelected.notify({ range: { fromCell: 1, fromRow: 2, toCell: 3, toRow: 4 } }, mouseEvent, gridStub); + plugin.cellRangeSelector.onCellRangeSelected.notify({ range: { fromCell: 1, fromRow: 2, toCell: 3, toRow: 4 } as SlickRange }, mouseEvent, gridStub); expect(setActiveCellSpy).toHaveBeenCalledWith(2, 1, false, false, true); expect(setSelectRangeSpy).toHaveBeenCalledWith([{ fromCell: 1, fromRow: 2, toCell: 3, toRow: 4 }]); diff --git a/packages/common/src/extensions/__tests__/slickCheckboxSelectColumn.spec.ts b/packages/common/src/extensions/__tests__/slickCheckboxSelectColumn.spec.ts index 46c2f5f4a..8b8904f54 100644 --- a/packages/common/src/extensions/__tests__/slickCheckboxSelectColumn.spec.ts +++ b/packages/common/src/extensions/__tests__/slickCheckboxSelectColumn.spec.ts @@ -1,13 +1,12 @@ import 'jest-extended'; import { BasePubSubService } from '@slickgrid-universal/event-pub-sub'; +import { type OnSelectedRowsChangedEventArgs, SlickEvent } from 'slickgrid'; import { SlickCheckboxSelectColumn } from '../slickCheckboxSelectColumn'; -import { Column, OnSelectedRowsChangedEventArgs, SlickGrid, SlickNamespace, } from '../../interfaces/index'; +import { Column, SlickGridUniversal } from '../../interfaces/index'; import { SlickRowSelectionModel } from '../../extensions/slickRowSelectionModel'; import { KeyCode } from '../../enums'; -declare const Slick: SlickNamespace; - const addVanillaEventPropagation = function (event, commandKey = '', keyName = '', target?: HTMLElement, which: string | number = '') { Object.defineProperty(event, 'isPropagationStopped', { writable: true, configurable: true, value: jest.fn() }); Object.defineProperty(event, 'isImmediatePropagationStopped', { writable: true, configurable: true, value: jest.fn() }); @@ -33,8 +32,8 @@ const dataViewStub = { getItemByIdx: jest.fn(), getItemCount: jest.fn(), getIdPropertyName: () => 'id', - onPagingInfoChanged: new Slick.Event(), - onSelectedRowIdsChanged: new Slick.Event(), + onPagingInfoChanged: new SlickEvent(), + onSelectedRowIdsChanged: new SlickEvent(), setSelectedIds: jest.fn(), }; @@ -59,19 +58,19 @@ const gridStub = { setSelectionModel: jest.fn(), setSelectedRows: jest.fn(), updateColumnHeader: jest.fn(), - onClick: new Slick.Event(), - onHeaderClick: new Slick.Event(), - onHeaderRowCellRendered: new Slick.Event(), - onKeyDown: new Slick.Event(), - onSelectedRowsChanged: new Slick.Event(), -} as unknown as SlickGrid; + onClick: new SlickEvent(), + onHeaderClick: new SlickEvent(), + onHeaderRowCellRendered: new SlickEvent(), + onKeyDown: new SlickEvent(), + onSelectedRowsChanged: new SlickEvent(), +} as unknown as SlickGridUniversal; const mockAddon = jest.fn().mockImplementation(() => ({ init: jest.fn(), dispose: jest.fn(), getColumnDefinition: jest.fn(), - onBeforeMoveRows: new Slick.Event(), - onMoveRows: new Slick.Event(), + onBeforeMoveRows: new SlickEvent(), + onMoveRows: new SlickEvent(), })); const mockRowSelectionModel = { @@ -82,7 +81,7 @@ const mockRowSelectionModel = { setSelectedRows: jest.fn(), getSelectedRanges: jest.fn(), setSelectedRanges: jest.fn(), - onSelectedRangesChanged: new Slick.Event(), + onSelectedRangesChanged: new SlickEvent(), } as unknown as SlickRowSelectionModel; const pubSubServiceStub = { @@ -97,8 +96,6 @@ jest.mock('../../extensions/slickRowSelectionModel', () => ({ })); describe('SlickCheckboxSelectColumn Plugin', () => { - Slick.RowMoveManager = mockAddon; - let mockColumns: Column[]; let plugin: SlickCheckboxSelectColumn; diff --git a/packages/common/src/extensions/__tests__/slickColumnPicker.spec.ts b/packages/common/src/extensions/__tests__/slickColumnPicker.spec.ts index cbf2c1ab8..efafee961 100644 --- a/packages/common/src/extensions/__tests__/slickColumnPicker.spec.ts +++ b/packages/common/src/extensions/__tests__/slickColumnPicker.spec.ts @@ -1,13 +1,13 @@ import { BasePubSubService } from '@slickgrid-universal/event-pub-sub'; +import { SlickEvent, SlickEventData } from 'slickgrid'; -import { Column, ColumnPicker, GridOption, SlickGrid, SlickNamespace } from '../../interfaces/index'; +import { Column, ColumnPicker, GridOption, SlickGridUniversal } from '../../interfaces/index'; import { SlickColumnPicker } from '../slickColumnPicker'; import { ExtensionUtility } from '../extensionUtility'; import { SharedService } from '../../services/shared.service'; import { TranslateServiceStub } from '../../../../../test/translateServiceStub'; import { BackendUtilityService } from '../../services/backendUtility.service'; -declare const Slick: SlickNamespace; const gridUid = 'slickgrid_124343'; const gridStub = { @@ -20,9 +20,9 @@ const gridStub = { setColumns: jest.fn(), setOptions: jest.fn(), setSelectedRows: jest.fn(), - onColumnsReordered: new Slick.Event(), - onHeaderContextMenu: new Slick.Event(), -} as unknown as SlickGrid; + onColumnsReordered: new SlickEvent(), + onHeaderContextMenu: new SlickEvent(), +} as unknown as SlickGridUniversal; const pubSubServiceStub = { publish: jest.fn(), @@ -32,7 +32,7 @@ const pubSubServiceStub = { } as BasePubSubService; describe('ColumnPickerControl', () => { - const eventData = { ...new Slick.EventData(), preventDefault: jest.fn() }; + const eventData = { ...new SlickEventData(), preventDefault: jest.fn() }; const columnsMock: Column[] = [ { id: 'field1', field: 'field1', name: 'Field 1', width: 100, nameKey: 'TITLE' }, { id: 'field2', field: 'field2', name: 'Field 2', width: 75 }, @@ -100,9 +100,9 @@ describe('ColumnPickerControl', () => { gridOptionsMock.enableRowSelection = true; control.columns = columnsMock; - const eventData = { ...new Slick.EventData(), preventDefault: jest.fn() }; - gridStub.onHeaderContextMenu.notify({ column: columnsMock[1], grid: gridStub }, eventData, gridStub); - const inputElm = control.menuElement!.querySelector('input[type="checkbox"]') as HTMLInputElement; + const eventData = { ...new SlickEventData(), preventDefault: jest.fn() } as any; + gridStub.onHeaderContextMenu.notify({ column: columnsMock[1], grid: gridStub }, eventData as any, gridStub); + const inputElm = control.menuElement.querySelector('input[type="checkbox"]') as HTMLInputElement; inputElm.dispatchEvent(new Event('click', { bubbles: true, cancelable: true, composed: false })); expect(control.menuElement!.style.display).toBe('block'); @@ -120,9 +120,8 @@ describe('ColumnPickerControl', () => { gridOptionsMock.enableRowSelection = true; control.columns = columnsMock; - const eventData = { ...new Slick.EventData(), preventDefault: jest.fn() }; - gridStub.onHeaderContextMenu.notify({ column: columnsMock[1], grid: gridStub }, eventData, gridStub); - control.menuElement!.dispatchEvent(new Event('mousedown', { bubbles: true })); + const eventData = { ...new SlickEventData(), preventDefault: jest.fn() } as any; + gridStub.onHeaderContextMenu.notify({ column: columnsMock[1], grid: gridStub }, eventData as any, gridStub); // click inside menu shouldn't close it expect(control.menuElement!.style.display).toBe('block'); @@ -144,8 +143,8 @@ describe('ColumnPickerControl', () => { control.columns = columnsMock; control.init(); - gridStub.onHeaderContextMenu.notify({ column: columnsMock[1], grid: gridStub }, eventData, gridStub); - control.menuElement!.querySelector('input[type="checkbox"]')!.dispatchEvent(new Event('click', { bubbles: true })); + gridStub.onHeaderContextMenu.notify({ column: columnsMock[1], grid: gridStub }, eventData as any, gridStub); + control.menuElement.querySelector('input[type="checkbox"]')!.dispatchEvent(new Event('click', { bubbles: true })); expect(handlerSpy).toHaveBeenCalledTimes(2); expect(readjustSpy).toHaveBeenCalledWith(0, columnsMock, columnsMock); @@ -162,9 +161,9 @@ describe('ColumnPickerControl', () => { control.columns = columnsMock; control.init(); - gridStub.onHeaderContextMenu.notify({ column: columnsMock[1], grid: gridStub }, eventData, gridStub); - control.menuElement!.querySelector('input[type="checkbox"]')!.dispatchEvent(new Event('click', { bubbles: true })); - const liElmList = control.menuElement!.querySelectorAll('li'); + gridStub.onHeaderContextMenu.notify({ column: columnsMock[1], grid: gridStub }, eventData as any, gridStub); + control.menuElement.querySelector('input[type="checkbox"]')!.dispatchEvent(new Event('click', { bubbles: true })); + const liElmList = control.menuElement.querySelectorAll('li'); expect(handlerSpy).toHaveBeenCalledTimes(2); expect(readjustSpy).toHaveBeenCalledWith(0, columnsMock, columnsMock); @@ -182,10 +181,10 @@ describe('ColumnPickerControl', () => { control.columns = columnsMock; control.init(); - gridStub.onHeaderContextMenu.notify({ column: columnsMock[1], grid: gridStub }, eventData, gridStub); - control.menuElement!.querySelector('input[type="checkbox"]')!.dispatchEvent(new Event('click', { bubbles: true })); - const inputForcefitElm = control.menuElement!.querySelector('#slickgrid_124343-colpicker-forcefit') as HTMLInputElement; - const labelSyncElm = control.menuElement!.querySelector('label[for=slickgrid_124343-colpicker-forcefit]') as HTMLDivElement; + gridStub.onHeaderContextMenu.notify({ column: columnsMock[1], grid: gridStub }, eventData as any, gridStub); + control.menuElement.querySelector('input[type="checkbox"]')!.dispatchEvent(new Event('click', { bubbles: true })); + const inputForcefitElm = control.menuElement.querySelector('#slickgrid_124343-colpicker-forcefit') as HTMLInputElement; + const labelSyncElm = control.menuElement.querySelector('label[for=slickgrid_124343-colpicker-forcefit]') as HTMLDivElement; expect(handlerSpy).toHaveBeenCalledTimes(2); expect(control.getAllColumns()).toEqual(columnsMock); @@ -204,10 +203,10 @@ describe('ColumnPickerControl', () => { control.columns = columnsMock; control.init(); - gridStub.onHeaderContextMenu.notify({ column: columnsMock[1], grid: gridStub }, eventData, gridStub); - control.menuElement!.querySelector('input[type="checkbox"]')!.dispatchEvent(new Event('click', { bubbles: true })); - const inputSyncElm = control.menuElement!.querySelector('#slickgrid_124343-colpicker-syncresize') as HTMLInputElement; - const labelSyncElm = control.menuElement!.querySelector('label[for=slickgrid_124343-colpicker-syncresize]') as HTMLDivElement; + gridStub.onHeaderContextMenu.notify({ column: columnsMock[1], grid: gridStub }, eventData as any, gridStub); + control.menuElement.querySelector('input[type="checkbox"]')!.dispatchEvent(new Event('click', { bubbles: true })); + const inputSyncElm = control.menuElement.querySelector('#slickgrid_124343-colpicker-syncresize') as HTMLInputElement; + const labelSyncElm = control.menuElement.querySelector('label[for=slickgrid_124343-colpicker-syncresize]') as HTMLDivElement; expect(handlerSpy).toHaveBeenCalledTimes(2); expect(control.getAllColumns()).toEqual(columnsMock); @@ -227,8 +226,8 @@ describe('ColumnPickerControl', () => { control.columns = columnsMock; control.init(); - gridStub.onHeaderContextMenu.notify({ column: columnsMock[1], grid: gridStub }, eventData, gridStub); - control.menuElement!.querySelector('input[type="checkbox"]')!.dispatchEvent(new Event('click', { bubbles: true })); + gridStub.onHeaderContextMenu.notify({ column: columnsMock[1], grid: gridStub }, eventData as any, gridStub); + control.menuElement.querySelector('input[type="checkbox"]')!.dispatchEvent(new Event('click', { bubbles: true })); const expectedCallbackArgs = { columnId: 'field1', @@ -257,9 +256,9 @@ describe('ColumnPickerControl', () => { control.columns = columnsMock; control.init(); - gridStub.onHeaderContextMenu.notify({ column: columnsMock[1], grid: gridStub }, eventData, gridStub); - const inputForcefitElm = control.menuElement!.querySelector('#slickgrid_124343-colpicker-forcefit') as HTMLInputElement; - const labelSyncElm = control.menuElement!.querySelector('label[for=slickgrid_124343-colpicker-forcefit]') as HTMLDivElement; + gridStub.onHeaderContextMenu.notify({ column: columnsMock[1], grid: gridStub }, eventData as any, gridStub); + const inputForcefitElm = control.menuElement.querySelector('#slickgrid_124343-colpicker-forcefit') as HTMLInputElement; + const labelSyncElm = control.menuElement.querySelector('label[for=slickgrid_124343-colpicker-forcefit]') as HTMLDivElement; inputForcefitElm.dispatchEvent(new Event('click', { bubbles: true })); expect(handlerSpy).toHaveBeenCalledTimes(2); @@ -283,9 +282,9 @@ describe('ColumnPickerControl', () => { control.columns = columnsMock; control.init(); - gridStub.onHeaderContextMenu.notify({ column: columnsMock[1], grid: gridStub }, eventData, gridStub); - const inputSyncElm = control.menuElement!.querySelector('#slickgrid_124343-colpicker-syncresize') as HTMLInputElement; - const labelSyncElm = control.menuElement!.querySelector('label[for=slickgrid_124343-colpicker-syncresize]') as HTMLDivElement; + gridStub.onHeaderContextMenu.notify({ column: columnsMock[1], grid: gridStub }, eventData as any, gridStub); + const inputSyncElm = control.menuElement.querySelector('#slickgrid_124343-colpicker-syncresize') as HTMLInputElement; + const labelSyncElm = control.menuElement.querySelector('label[for=slickgrid_124343-colpicker-syncresize]') as HTMLDivElement; inputSyncElm.dispatchEvent(new Event('click', { bubbles: true })); expect(handlerSpy).toHaveBeenCalledTimes(2); @@ -316,10 +315,10 @@ describe('ColumnPickerControl', () => { control.columns = columnsUnorderedMock; control.init(); - gridStub.onHeaderContextMenu.notify({ column: columnsMock[1], grid: gridStub }, eventData, gridStub); - gridStub.onColumnsReordered.notify({ impactedColumns: columnsUnorderedMock, grid: gridStub }, eventData, gridStub); - control.menuElement!.querySelector('input[type="checkbox"]')!.dispatchEvent(new Event('click', { bubbles: true })); - const col4 = control.menuElement!.querySelector('li.hidden input[data-columnid=field4]'); + gridStub.onHeaderContextMenu.notify({ column: columnsMock[1], grid: gridStub }, eventData as any, gridStub); + gridStub.onColumnsReordered.notify({ impactedColumns: columnsUnorderedMock, grid: gridStub }, eventData as any, gridStub); + control.menuElement.querySelector('input[type="checkbox"]')!.dispatchEvent(new Event('click', { bubbles: true })); + const col4 = control.menuElement.querySelector('li.hidden input[data-columnid=field4]'); expect(handlerSpy).toHaveBeenCalledTimes(2); expect(control.getAllColumns()).toEqual(columnsMock); @@ -344,10 +343,10 @@ describe('ColumnPickerControl', () => { control.init(); control.translateColumnPicker(); - gridStub.onHeaderContextMenu.notify({ column: columnsMock[1], grid: gridStub }, eventData, gridStub); - control.menuElement!.querySelector('input[type="checkbox"]')!.dispatchEvent(new Event('click', { bubbles: true })); - const labelForcefitElm = control.menuElement!.querySelector('label[for=slickgrid_124343-colpicker-forcefit]') as HTMLDivElement; - const labelSyncElm = control.menuElement!.querySelector('label[for=slickgrid_124343-colpicker-syncresize]') as HTMLDivElement; + gridStub.onHeaderContextMenu.notify({ column: columnsMock[1], grid: gridStub }, eventData as any, gridStub); + control.menuElement.querySelector('input[type="checkbox"]')!.dispatchEvent(new Event('click', { bubbles: true })); + const labelForcefitElm = control.menuElement.querySelector('label[for=slickgrid_124343-colpicker-forcefit]') as HTMLDivElement; + const labelSyncElm = control.menuElement.querySelector('label[for=slickgrid_124343-colpicker-syncresize]') as HTMLDivElement; expect(handlerSpy).toHaveBeenCalledTimes(2); expect(labelForcefitElm.textContent).toBe('Ajustement forcé des colonnes'); diff --git a/packages/common/src/extensions/__tests__/slickContextMenu.spec.ts b/packages/common/src/extensions/__tests__/slickContextMenu.spec.ts index 09b26dc8e..43404e914 100644 --- a/packages/common/src/extensions/__tests__/slickContextMenu.spec.ts +++ b/packages/common/src/extensions/__tests__/slickContextMenu.spec.ts @@ -1,16 +1,15 @@ import { BasePubSubService } from '@slickgrid-universal/event-pub-sub'; import { deepCopy } from '@slickgrid-universal/utils'; +import { type SlickDataView, SlickEvent, SlickEventData } from 'slickgrid'; import { DelimiterType, FileType } from '../../enums/index'; -import { ContextMenu, Column, ElementPosition, GridOption, MenuCommandItem, MenuOptionItem, SlickDataView, SlickGrid, SlickNamespace, } from '../../interfaces/index'; +import { ContextMenu, Column, ElementPosition, GridOption, MenuCommandItem, MenuOptionItem, SlickGridUniversal, } from '../../interfaces/index'; import { BackendUtilityService, ExcelExportService, SharedService, TextExportService, TreeDataService, } from '../../services/index'; import { ExtensionUtility } from '../../extensions/extensionUtility'; import { Formatters } from '../../formatters'; import { TranslateServiceStub } from '../../../../../test/translateServiceStub'; import { SlickContextMenu } from '../slickContextMenu'; -declare const Slick: SlickNamespace; - const removeExtraSpaces = (textS) => `${textS}`.replace(/[\n\r]\s+/g, ''); const commandItemsMock = [ @@ -112,11 +111,11 @@ const gridStub = { setOptions: jest.fn(), setSortColumns: jest.fn(), updateColumnHeader: jest.fn(), - onClick: new Slick.Event(), - onContextMenu: new Slick.Event(), - onScroll: new Slick.Event(), - onSort: new Slick.Event(), -} as unknown as SlickGrid; + onClick: new SlickEvent(), + onContextMenu: new SlickEvent(), + onScroll: new SlickEvent(), + onSort: new SlickEvent(), +} as unknown as SlickGridUniversal; const dataViewStub = { collapseAllGroups: jest.fn(), @@ -221,7 +220,7 @@ describe('ContextMenu Plugin', () => { beforeEach(() => { slickCellElm = document.createElement('div'); slickCellElm.className = 'slick-cell'; - eventData = { ...new Slick.EventData(), preventDefault: jest.fn() }; + eventData = { ...new SlickEventData(), preventDefault: jest.fn() }; eventData.target = slickCellElm; jest.spyOn(SharedService.prototype, 'slickGrid', 'get').mockReturnValue(gridStub); @@ -760,7 +759,7 @@ describe('ContextMenu Plugin', () => { beforeEach(() => { slickCellElm = document.createElement('div'); slickCellElm.className = 'slick-cell'; - eventData = { ...new Slick.EventData(), preventDefault: jest.fn() }; + eventData = { ...new SlickEventData(), preventDefault: jest.fn() }; eventData.target = slickCellElm; jest.spyOn(SharedService.prototype, 'slickGrid', 'get').mockReturnValue(gridStub); diff --git a/packages/common/src/extensions/__tests__/slickDraggableGrouping.spec.ts b/packages/common/src/extensions/__tests__/slickDraggableGrouping.spec.ts index c10be847b..f34539c20 100644 --- a/packages/common/src/extensions/__tests__/slickDraggableGrouping.spec.ts +++ b/packages/common/src/extensions/__tests__/slickDraggableGrouping.spec.ts @@ -28,18 +28,18 @@ jest.mock('sortablejs', () => sortableMock); import 'jest-extended'; import { SortableOptions } from 'sortablejs'; import { EventPubSubService } from '@slickgrid-universal/event-pub-sub'; +import { SlickEvent, SlickEventData } from 'slickgrid'; import { Aggregators } from '../../aggregators/aggregators.index'; import { SlickDraggableGrouping } from '../slickDraggableGrouping'; import { ExtensionUtility } from '../../extensions/extensionUtility'; -import { Column, DraggableGroupingOption, GridOption, SlickGrid, SlickNamespace } from '../../interfaces/index'; +import { Column, DraggableGroupingOption, GridOption, SlickGridUniversal } from '../../interfaces/index'; import { BackendUtilityService, createDomElement, } from '../../services'; import { SharedService } from '../../services/shared.service'; import { TranslateServiceStub } from '../../../../../test/translateServiceStub'; import { SortDirectionNumber } from '../../enums'; import { deepCopy } from '@slickgrid-universal/utils'; -declare const Slick: SlickNamespace; const GRID_UID = 'slickgrid12345'; let addonOptions: DraggableGroupingOption = { @@ -85,11 +85,11 @@ const gridStub = { invalidate: jest.fn(), registerPlugin: jest.fn(), updateColumnHeader: jest.fn(), - onColumnsReordered: new Slick.Event(), - onHeaderCellRendered: new Slick.Event(), - onHeaderMouseEnter: new Slick.Event(), - onMouseEnter: new Slick.Event(), -} as unknown as SlickGrid; + onColumnsReordered: new SlickEvent(), + onHeaderCellRendered: new SlickEvent(), + onHeaderMouseEnter: new SlickEvent(), + onMouseEnter: new SlickEvent(), +} as unknown as SlickGridUniversal; const mockColumns = [ { id: 'firstName', name: 'First Name', field: 'firstName', width: 100 }, @@ -225,8 +225,8 @@ describe('Draggable Grouping Plugin', () => { jest.spyOn(SharedService.prototype, 'gridOptions', 'get').mockReturnValue({ ...gridOptionsMock, enableTranslate: true }); translateService.use('fr'); plugin.init(gridStub, { ...addonOptions, groupIconCssClass: 'mdi mdi-drag' }); - const eventData = { ...new Slick.EventData(), preventDefault: jest.fn() }; - gridStub.onHeaderCellRendered.notify({ column: mockColumns[2], node: headerDiv, grid: gridStub }, eventData, gridStub); + const eventData = { ...new SlickEventData(), preventDefault: jest.fn() }; + gridStub.onHeaderCellRendered.notify({ column: mockColumns[2], node: headerDiv, grid: gridStub }, eventData as any, gridStub); const groupableElm = headerDiv.querySelector('.slick-column-groupable') as HTMLSpanElement; expect(headerDiv.style.cursor).toBe('pointer'); diff --git a/packages/common/src/extensions/__tests__/slickGridMenu.spec.ts b/packages/common/src/extensions/__tests__/slickGridMenu.spec.ts index d4d368296..a447e6d1e 100644 --- a/packages/common/src/extensions/__tests__/slickGridMenu.spec.ts +++ b/packages/common/src/extensions/__tests__/slickGridMenu.spec.ts @@ -1,14 +1,14 @@ import 'jest-extended'; import { BasePubSubService } from '@slickgrid-universal/event-pub-sub'; +import { type SlickDataView, SlickEvent, SlickEventData } from 'slickgrid'; import { DelimiterType, FileType } from '../../enums/index'; -import { Column, DOMEvent, GridMenu, GridOption, SlickDataView, SlickGrid, SlickNamespace, } from '../../interfaces/index'; +import { Column, DOMEvent, GridMenu, GridOption, SlickGridUniversal } from '../../interfaces/index'; import { SlickGridMenu } from '../slickGridMenu'; import { BackendUtilityService, ExcelExportService, FilterService, SharedService, SortService, TextExportService, } from '../../services'; import { TranslateServiceStub } from '../../../../../test/translateServiceStub'; import { ExtensionUtility } from '../../extensions/extensionUtility'; -declare const Slick: SlickNamespace; jest.mock('flatpickr', () => { }); const gridId = 'grid1'; @@ -62,10 +62,10 @@ const gridStub = { setPreHeaderPanelVisibility: jest.fn(), setOptions: jest.fn(), scrollColumnIntoView: jest.fn(), - onBeforeDestroy: new Slick.Event(), - onColumnsReordered: new Slick.Event(), - onSetOptions: new Slick.Event(), -} as unknown as SlickGrid; + onBeforeDestroy: new SlickEvent(), + onColumnsReordered: new SlickEvent(), + onSetOptions: new SlickEvent(), +} as unknown as SlickGridUniversal; // define a
container to simulate the grid container const template = @@ -86,7 +86,7 @@ const template = describe('GridMenuControl', () => { let control: SlickGridMenu; - const eventData = { ...new Slick.EventData(), preventDefault: jest.fn() }; + const eventData = { ...new SlickEventData(), preventDefault: jest.fn() }; const columnsMock: Column[] = [ { id: 'field1', field: 'field1', name: 'Field 1', width: 100, nameKey: 'TITLE' }, { id: 'field2', field: 'field2', name: 'Field 2', width: 75 }, @@ -293,10 +293,10 @@ describe('GridMenuControl', () => { jest.spyOn(SharedService.prototype, 'slickGrid', 'get').mockReturnValue(gridStub); control.initEventHandlers(); - gridStub.onSetOptions.notify({ grid: gridStub, optionsBefore: { frozenColumn: -1 }, optionsAfter: { frozenColumn: 2 } }, new Slick.EventData(), gridStub); + gridStub.onSetOptions.notify({ grid: gridStub, optionsBefore: { frozenColumn: -1 }, optionsAfter: { frozenColumn: 2 } }, new SlickEventData(), gridStub); expect(recreateSpy).toHaveBeenCalledTimes(1); - gridStub.onSetOptions.notify({ grid: gridStub, optionsBefore: { frozenColumn: 2 }, optionsAfter: { frozenColumn: -1 } }, new Slick.EventData(), gridStub); + gridStub.onSetOptions.notify({ grid: gridStub, optionsBefore: { frozenColumn: 2 }, optionsAfter: { frozenColumn: -1 } }, new SlickEventData(), gridStub); expect(recreateSpy).toHaveBeenCalledTimes(2); }); @@ -1482,7 +1482,7 @@ describe('GridMenuControl', () => { control.init(); const buttonElm = document.querySelector('.slick-grid-menu-button') as HTMLDivElement; buttonElm.dispatchEvent(new Event('click', { bubbles: true, cancelable: true, composed: false })); - gridStub.onColumnsReordered.notify({ impactedColumns: columnsUnorderedMock, grid: gridStub }, eventData, gridStub); + gridStub.onColumnsReordered.notify({ impactedColumns: columnsUnorderedMock, grid: gridStub }, eventData as any, gridStub); control.menuElement!.querySelector('input[type="checkbox"]')!.dispatchEvent(new Event('click', { bubbles: true })); expect(handlerSpy).toHaveBeenCalledTimes(3); diff --git a/packages/common/src/extensions/__tests__/slickGroupItemMetadataProvider.spec.ts b/packages/common/src/extensions/__tests__/slickGroupItemMetadataProvider.spec.ts index b78b2e736..f7661ae83 100644 --- a/packages/common/src/extensions/__tests__/slickGroupItemMetadataProvider.spec.ts +++ b/packages/common/src/extensions/__tests__/slickGroupItemMetadataProvider.spec.ts @@ -1,9 +1,9 @@ +import { type SlickDataView, SlickEvent, SlickGroup } from 'slickgrid'; + import { KeyCode } from '../../enums/index'; -import { Column, GridOption, GroupItemMetadataProviderOption, SlickDataView, SlickGrid, SlickNamespace } from '../../interfaces'; +import { Column, GridOption, GroupItemMetadataProviderOption, SlickGridUniversal } from '../../interfaces'; import { SlickGroupItemMetadataProvider } from '../slickGroupItemMetadataProvider'; -declare const Slick: SlickNamespace; - const gridOptionMock = { enablePagination: true, backendServiceApi: { @@ -26,7 +26,7 @@ const dataViewStub = { reSort: jest.fn(), sort: jest.fn(), setItems: jest.fn(), - onRowCountChanged: new Slick.Event(), + onRowCountChanged: new SlickEvent(), } as unknown as SlickDataView; const gridStub = { @@ -45,10 +45,10 @@ const gridStub = { setColumns: jest.fn(), setOptions: jest.fn(), setSortColumns: jest.fn(), - onClick: new Slick.Event(), - onKeyDown: new Slick.Event(), - onSort: new Slick.Event(), -} as unknown as SlickGrid; + onClick: new SlickEvent(), + onKeyDown: new SlickEvent(), + onSort: new SlickEvent(), +} as unknown as SlickGridUniversal; describe('GroupItemMetadataProvider Service', () => { let service: SlickGroupItemMetadataProvider; @@ -63,6 +63,7 @@ describe('GroupItemMetadataProvider Service', () => { }); afterEach(() => { + service?.destroy(); service?.dispose(); }); @@ -178,7 +179,7 @@ describe('GroupItemMetadataProvider Service', () => { selectable: false, focusable: mockOptions.groupFocusable, cssClasses: `${mockOptions.groupCssClass} slick-group-level-2`, - formatter: false, + formatter: undefined, columns: { 0: { colspan: '*', @@ -224,7 +225,7 @@ describe('GroupItemMetadataProvider Service', () => { let stopPropagationSpy; let expandGroupSpy; let clickEvent: Event; - const group = new Slick.Group(); + const group = new SlickGroup(); const mockRange = { top: 10, bottom: 25 } as any; beforeEach(() => { @@ -286,7 +287,7 @@ describe('GroupItemMetadataProvider Service', () => { let stopPropagationSpy; let expandGroupSpy; let keyDownEvent: Event; - const group = new Slick.Group(); + const group = new SlickGroup(); const mockActiveCell = { row: 0, cell: 3 }; const mockRange = { top: 10, bottom: 25 } as any; diff --git a/packages/common/src/extensions/__tests__/slickHeaderButtons.spec.ts b/packages/common/src/extensions/__tests__/slickHeaderButtons.spec.ts index 6fc659294..94f8b71b2 100644 --- a/packages/common/src/extensions/__tests__/slickHeaderButtons.spec.ts +++ b/packages/common/src/extensions/__tests__/slickHeaderButtons.spec.ts @@ -1,14 +1,13 @@ import { BasePubSubService } from '@slickgrid-universal/event-pub-sub'; +import { SlickEvent, SlickEventData } from 'slickgrid'; -import { Column, GridOption, SlickGrid, SlickNamespace, } from '../../interfaces/index'; +import { Column, GridOption, SlickGridUniversal } from '../../interfaces/index'; import { SlickHeaderButtons } from '../slickHeaderButtons'; import { BackendUtilityService } from '../../services'; import { SharedService } from '../../services/shared.service'; import { ExtensionUtility } from '../../extensions/extensionUtility'; import { TranslateServiceStub } from '../../../../../test/translateServiceStub'; -declare const Slick: SlickNamespace; - const removeExtraSpaces = (textS) => `${textS}`.replace(/[\n\r]\s+/g, ''); const gridStub = { @@ -20,11 +19,11 @@ const gridStub = { registerPlugin: jest.fn(), setColumns: jest.fn(), updateColumnHeader: jest.fn(), - onBeforeHeaderCellDestroy: new Slick.Event(), - onHeaderCellRendered: new Slick.Event(), - onHeaderMouseEnter: new Slick.Event(), - onMouseEnter: new Slick.Event(), -} as unknown as SlickGrid; + onBeforeHeaderCellDestroy: new SlickEvent(), + onHeaderCellRendered: new SlickEvent(), + onHeaderMouseEnter: new SlickEvent(), + onMouseEnter: new SlickEvent(), +} as unknown as SlickGridUniversal; const pubSubServiceStub = { publish: jest.fn(), @@ -125,14 +124,14 @@ describe('HeaderButton Plugin', () => { plugin.init(); columnsMock[0].header!.buttons![1].itemVisibilityOverride = () => undefined as any; - const eventData = { ...new Slick.EventData(), preventDefault: jest.fn() }; - gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData, gridStub); + const eventData = { ...new SlickEventData(), preventDefault: jest.fn() }; + gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData as any, gridStub); // add Header Buttons which are visible (only 1x) expect(removeExtraSpaces(headerDiv.innerHTML)).toBe(removeExtraSpaces( `
  • `)); - gridStub.onBeforeHeaderCellDestroy.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData, gridStub); + gridStub.onBeforeHeaderCellDestroy.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData as any, gridStub); expect(headerDiv.innerHTML).toBe(''); }); @@ -144,8 +143,8 @@ describe('HeaderButton Plugin', () => { plugin.init(); columnsMock[0].header!.buttons![1].itemVisibilityOverride = () => false; - const eventData = { ...new Slick.EventData(), preventDefault: jest.fn() }; - gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData, gridStub); + const eventData = { ...new SlickEventData(), preventDefault: jest.fn() }; + gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData as any, gridStub); // add Header Buttons which are visible (only 1x) expect(removeExtraSpaces(headerDiv.innerHTML)).toBe(removeExtraSpaces( @@ -161,8 +160,8 @@ describe('HeaderButton Plugin', () => { columnsMock[0].header!.buttons![1].itemVisibilityOverride = () => true; columnsMock[0].header!.buttons![1].itemUsabilityOverride = () => true; - const eventData = { ...new Slick.EventData(), preventDefault: jest.fn() }; - gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData, gridStub); + const eventData = { ...new SlickEventData(), preventDefault: jest.fn() }; + gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData as any, gridStub); // add Header Buttons which are visible (2x buttons) expect(removeExtraSpaces(headerDiv.innerHTML)).toBe(removeExtraSpaces( @@ -179,8 +178,8 @@ describe('HeaderButton Plugin', () => { columnsMock[0].header!.buttons![1].itemVisibilityOverride = () => true; columnsMock[0].header!.buttons![1].itemUsabilityOverride = () => false; - const eventData = { ...new Slick.EventData(), preventDefault: jest.fn() }; - gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData, gridStub); + const eventData = { ...new SlickEventData(), preventDefault: jest.fn() }; + gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData as any, gridStub); // add Header Buttons which are visible (2x buttons) expect(removeExtraSpaces(headerDiv.innerHTML)).toBe(removeExtraSpaces( @@ -197,8 +196,8 @@ describe('HeaderButton Plugin', () => { columnsMock[0].header!.buttons![1].itemVisibilityOverride = undefined as any; columnsMock[0].header!.buttons![1].disabled = true; - const eventData = { ...new Slick.EventData(), preventDefault: jest.fn() }; - gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData, gridStub); + const eventData = { ...new SlickEventData(), preventDefault: jest.fn() }; + gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData as any, gridStub); // add Header Buttons which are visible (2x buttons) expect(removeExtraSpaces(headerDiv.innerHTML)).toBe(removeExtraSpaces( @@ -215,8 +214,8 @@ describe('HeaderButton Plugin', () => { columnsMock[0].header!.buttons![1].itemVisibilityOverride = undefined as any; columnsMock[0].header!.buttons![1].showOnHover = true; - const eventData = { ...new Slick.EventData(), preventDefault: jest.fn() }; - gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData, gridStub); + const eventData = { ...new SlickEventData(), preventDefault: jest.fn() }; + gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData as any, gridStub); // add Header Buttons which are visible (2x buttons) expect(removeExtraSpaces(headerDiv.innerHTML)).toBe(removeExtraSpaces( @@ -233,8 +232,8 @@ describe('HeaderButton Plugin', () => { plugin.init(); columnsMock[0].header!.buttons![1].handler = handlerMock; - const eventData = { ...new Slick.EventData(), preventDefault: jest.fn() }; - gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData, gridStub); + const eventData = { ...new SlickEventData(), preventDefault: jest.fn() }; + gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData as any, gridStub); headerDiv.querySelector('.slick-header-button.mdi-lightbulb-on')!.dispatchEvent(new Event('click', { bubbles: true, cancelable: true, composed: false })); // add Header Buttons which are visible (2x buttons) @@ -253,8 +252,8 @@ describe('HeaderButton Plugin', () => { plugin.init(); columnsMock[0].header!.buttons![1].action = actionMock; - const eventData = { ...new Slick.EventData(), preventDefault: jest.fn() }; - gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData, gridStub); + const eventData = { ...new SlickEventData(), preventDefault: jest.fn() }; + gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData as any, gridStub); headerDiv.querySelector('.slick-header-button.mdi-lightbulb-on')!.dispatchEvent(new Event('click', { bubbles: true, cancelable: true, composed: false })); // add Header Buttons which are visible (2x buttons) @@ -274,8 +273,8 @@ describe('HeaderButton Plugin', () => { plugin.init(); plugin.addonOptions.onCommand = onCommandMock; - const eventData = { ...new Slick.EventData(), preventDefault: jest.fn() }; - gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData, gridStub); + const eventData = { ...new SlickEventData(), preventDefault: jest.fn() }; + gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData as any, gridStub); headerDiv.querySelector('.slick-header-button.mdi-lightbulb-on')!.dispatchEvent(new Event('click', { bubbles: true, cancelable: true, composed: false })); // add Header Buttons which are visible (2x buttons) @@ -297,8 +296,8 @@ describe('HeaderButton Plugin', () => { delete columnsMock[0].header!.buttons![1].showOnHover; columnsMock[0].header!.buttons![1].disabled = true; - const eventData = { ...new Slick.EventData(), preventDefault: jest.fn() }; - gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData, gridStub); + const eventData = { ...new SlickEventData(), preventDefault: jest.fn() }; + gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData as any, gridStub); // add Header Buttons which are visible (2x buttons) expect(removeExtraSpaces(headerDiv.innerHTML)).toBe(removeExtraSpaces( diff --git a/packages/common/src/extensions/__tests__/slickHeaderMenu.spec.ts b/packages/common/src/extensions/__tests__/slickHeaderMenu.spec.ts index c87647c0f..fdc02867f 100644 --- a/packages/common/src/extensions/__tests__/slickHeaderMenu.spec.ts +++ b/packages/common/src/extensions/__tests__/slickHeaderMenu.spec.ts @@ -1,13 +1,12 @@ import { BasePubSubService } from '@slickgrid-universal/event-pub-sub'; +import { type SlickDataView, SlickEvent, SlickEventData } from 'slickgrid'; -import { Column, ColumnSort, ElementPosition, GridOption, MenuCommandItem, SlickDataView, SlickEventData, SlickGrid, SlickNamespace, } from '../../interfaces/index'; +import { Column, ColumnSort, ElementPosition, GridOption, MenuCommandItem, SlickGridUniversal } from '../../interfaces/index'; import { SlickHeaderMenu } from '../slickHeaderMenu'; import { BackendUtilityService, FilterService, SharedService, SortService } from '../../services'; import { ExtensionUtility } from '../../extensions/extensionUtility'; import { TranslateServiceStub } from '../../../../../test/translateServiceStub'; -declare const Slick: SlickNamespace; - const removeExtraSpaces = (textS) => `${textS}`.replace(/[\n\r]\s+/g, ''); const mockEventCallback = () => { }; @@ -58,13 +57,13 @@ const gridStub = { setOptions: jest.fn(), setSortColumns: jest.fn(), updateColumnHeader: jest.fn(), - onBeforeSetColumns: new Slick.Event(), - onBeforeHeaderCellDestroy: new Slick.Event(), - onHeaderCellRendered: new Slick.Event(), - onHeaderMouseEnter: new Slick.Event(), - onMouseEnter: new Slick.Event(), - onSort: new Slick.Event(), -} as unknown as SlickGrid; + onBeforeSetColumns: new SlickEvent(), + onBeforeHeaderCellDestroy: new SlickEvent(), + onHeaderCellRendered: new SlickEvent(), + onHeaderMouseEnter: new SlickEvent(), + onMouseEnter: new SlickEvent(), + onSort: new SlickEvent(), +} as unknown as SlickGridUniversal; const dataViewStub = { refresh: jest.fn(), @@ -216,8 +215,8 @@ describe('HeaderMenu Plugin', () => { plugin.init({ buttonCssClass: 'mdi mdi-chevron-down' }); (columnsMock[0].header!.menu!.commandItems![1] as MenuCommandItem).itemVisibilityOverride = () => undefined as any; - const eventData = { ...new Slick.EventData(), preventDefault: jest.fn() }; - gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData, gridStub); + const eventData = { ...new SlickEventData(), preventDefault: jest.fn() }; + gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData as any, gridStub); expect(removeExtraSpaces(headerDiv.innerHTML)).toBe(removeExtraSpaces( `
    `)); @@ -228,8 +227,8 @@ describe('HeaderMenu Plugin', () => { plugin.init({ tooltip: 'some tooltip text' }); (columnsMock[0].header!.menu!.commandItems![1] as MenuCommandItem).itemVisibilityOverride = () => undefined as any; - const eventData = { ...new Slick.EventData(), preventDefault: jest.fn() }; - gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData, gridStub); + const eventData = { ...new SlickEventData(), preventDefault: jest.fn() }; + gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData as any, gridStub); expect(removeExtraSpaces(headerDiv.innerHTML)).toBe(removeExtraSpaces( `
    `)); @@ -240,14 +239,14 @@ describe('HeaderMenu Plugin', () => { plugin.init(); (columnsMock[0].header!.menu!.commandItems![1] as MenuCommandItem).itemVisibilityOverride = () => undefined as any; - const eventData = { ...new Slick.EventData(), preventDefault: jest.fn() }; - gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData, gridStub); + const eventData = { ...new SlickEventData(), preventDefault: jest.fn() }; + gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData as any, gridStub); // add Header Menu which is visible expect(removeExtraSpaces(headerDiv.innerHTML)).toBe(removeExtraSpaces( `
    `)); - gridStub.onBeforeHeaderCellDestroy.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData, gridStub); + gridStub.onBeforeHeaderCellDestroy.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData as any, gridStub); expect(headerDiv.innerHTML).toBe(''); }); @@ -256,8 +255,8 @@ describe('HeaderMenu Plugin', () => { plugin.init(); (columnsMock[0].header!.menu!.commandItems![1] as MenuCommandItem).itemVisibilityOverride = () => false; - const eventData = { ...new Slick.EventData(), preventDefault: jest.fn() }; - gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData, gridStub); + const eventData = { ...new SlickEventData(), preventDefault: jest.fn() }; + gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData as any, gridStub); // add Header Menu which is visible expect(removeExtraSpaces(headerDiv.innerHTML)).toBe(removeExtraSpaces( @@ -270,8 +269,8 @@ describe('HeaderMenu Plugin', () => { (columnsMock[0].header!.menu!.commandItems![1] as MenuCommandItem).itemVisibilityOverride = () => true; (columnsMock[0].header!.menu!.commandItems![1] as MenuCommandItem).itemUsabilityOverride = () => true; - const eventData = { ...new Slick.EventData(), preventDefault: jest.fn() }; - gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData, gridStub); + const eventData = { ...new SlickEventData(), preventDefault: jest.fn() }; + gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData as any, gridStub); const headerButtonElm = headerDiv.querySelector('.slick-header-menu-button') as HTMLDivElement; // add Header Menu which is visible @@ -295,8 +294,8 @@ describe('HeaderMenu Plugin', () => { (columnsMock[0].header!.menu!.commandItems![1] as MenuCommandItem).itemUsabilityOverride = () => false; const publishSpy = jest.spyOn(pubSubServiceStub, 'publish'); - const eventData = { ...new Slick.EventData(), preventDefault: jest.fn() }; - gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData, gridStub); + const eventData = { ...new SlickEventData(), preventDefault: jest.fn() }; + gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData as any, gridStub); const headerButtonElm = headerDiv.querySelector('.slick-header-menu-button:nth-child(1)') as HTMLDivElement; headerButtonElm.dispatchEvent(new Event('click', { bubbles: true, cancelable: true, composed: false })); const commandElm = gridContainerDiv.querySelector('.slick-menu-item.slick-menu-item-disabled') as HTMLDivElement; @@ -319,8 +318,8 @@ describe('HeaderMenu Plugin', () => { (columnsMock[0].header!.menu!.commandItems![1] as MenuCommandItem).itemVisibilityOverride = undefined; (columnsMock[0].header!.menu!.commandItems![1] as MenuCommandItem).disabled = true; - const eventData = { ...new Slick.EventData(), preventDefault: jest.fn() }; - gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData, gridStub); + const eventData = { ...new SlickEventData(), preventDefault: jest.fn() }; + gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData as any, gridStub); const headerButtonElm = headerDiv.querySelector('.slick-header-menu-button') as HTMLDivElement; headerButtonElm.dispatchEvent(new Event('click', { bubbles: true, cancelable: true, composed: false })); const commandElm = gridContainerDiv.querySelector('.slick-menu-item.slick-menu-item-disabled') as HTMLDivElement; @@ -339,8 +338,8 @@ describe('HeaderMenu Plugin', () => { plugin.init(); (columnsMock[0].header!.menu!.commandItems![1] as MenuCommandItem).hidden = true; - const eventData = { ...new Slick.EventData(), preventDefault: jest.fn() }; - gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData, gridStub); + const eventData = { ...new SlickEventData(), preventDefault: jest.fn() }; + gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData as any, gridStub); const headerButtonElm = headerDiv.querySelector('.slick-header-menu-button') as HTMLDivElement; headerButtonElm.dispatchEvent(new Event('click', { bubbles: true, cancelable: true, composed: false })); const commandElm = gridContainerDiv.querySelector('.slick-menu-item.slick-menu-item-hidden') as HTMLDivElement; @@ -359,8 +358,8 @@ describe('HeaderMenu Plugin', () => { plugin.init(); (columnsMock[0].header!.menu!.commandItems![1] as MenuCommandItem).tooltip = 'Some Tooltip'; - const eventData = { ...new Slick.EventData(), preventDefault: jest.fn() }; - gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData, gridStub); + const eventData = { ...new SlickEventData(), preventDefault: jest.fn() }; + gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData as any, gridStub); const headerButtonElm = headerDiv.querySelector('.slick-header-menu-button') as HTMLDivElement; headerButtonElm.dispatchEvent(new Event('click', { bubbles: true, cancelable: true, composed: false })); const commandElm = gridContainerDiv.querySelector('.slick-menu-item[data-command="show-negative-numbers"]') as HTMLDivElement; @@ -381,8 +380,8 @@ describe('HeaderMenu Plugin', () => { plugin.init(); (columnsMock[0].header!.menu!.commandItems![1] as MenuCommandItem).action = actionMock; - const eventData = { ...new Slick.EventData(), preventDefault: jest.fn() }; - gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData, gridStub); + const eventData = { ...new SlickEventData(), preventDefault: jest.fn() }; + gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData as any, gridStub); const headerButtonElm = headerDiv.querySelector('.slick-header-menu-button') as HTMLDivElement; headerButtonElm.dispatchEvent(new Event('click', { bubbles: true, cancelable: true, composed: false })); const commandElm = gridContainerDiv.querySelector('.slick-menu-item[data-command="show-negative-numbers"]') as HTMLDivElement; @@ -407,8 +406,8 @@ describe('HeaderMenu Plugin', () => { plugin.init(); plugin.addonOptions.onCommand = onCommandMock; - const eventData = { ...new Slick.EventData(), preventDefault: jest.fn() }; - gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData, gridStub); + const eventData = { ...new SlickEventData(), preventDefault: jest.fn() }; + gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData as any, gridStub); const headerButtonElm = headerDiv.querySelector('.slick-header-menu-button') as HTMLDivElement; headerButtonElm.dispatchEvent(new Event('click', { bubbles: true, cancelable: true, composed: false })); const commandElm = gridContainerDiv.querySelector('.slick-menu-item[data-command="show-negative-numbers"]') as HTMLDivElement; @@ -435,9 +434,9 @@ describe('HeaderMenu Plugin', () => { (columnsMock[0].header!.menu!.commandItems![1] as MenuCommandItem).itemUsabilityOverride = () => true; (columnsMock[0].header!.menu!.commandItems![1] as MenuCommandItem).disabled = true; - const eventData = { ...new Slick.EventData(), preventDefault: jest.fn() }; - gridStub.onBeforeSetColumns.notify({ previousColumns: [], newColumns: columnsMock, grid: gridStub }, eventData, gridStub); - gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData, gridStub); + const eventData = { ...new SlickEventData(), preventDefault: jest.fn() }; + gridStub.onBeforeSetColumns.notify({ previousColumns: [], newColumns: columnsMock, grid: gridStub }, eventData as any, gridStub); + gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData as any, gridStub); const headerButtonElm = headerDiv.querySelector('.slick-header-menu-button') as HTMLDivElement; headerButtonElm.dispatchEvent(new Event('click', { bubbles: true, cancelable: true, composed: false })); const commandElm = gridContainerDiv.querySelector('.slick-menu-item[data-command="show-negative-numbers"]') as HTMLDivElement; @@ -455,9 +454,9 @@ describe('HeaderMenu Plugin', () => { plugin.dispose(); plugin.init({ autoAlign: true }); - const eventData = { ...new Slick.EventData(), preventDefault: jest.fn() }; - gridStub.onBeforeSetColumns.notify({ previousColumns: [], newColumns: columnsMock, grid: gridStub }, eventData, gridStub); - gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData, gridStub); + const eventData = { ...new SlickEventData(), preventDefault: jest.fn() }; + gridStub.onBeforeSetColumns.notify({ previousColumns: [], newColumns: columnsMock, grid: gridStub }, eventData as any, gridStub); + gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData as any, gridStub); const buttonElm = headerDiv.querySelector('.slick-header-menu-button') as HTMLDivElement; buttonElm.dispatchEvent(new Event('click')); const commandElm = gridContainerDiv.querySelector('.slick-menu-item[data-command="show-negative-numbers"]') as HTMLDivElement; @@ -484,8 +483,8 @@ describe('HeaderMenu Plugin', () => { (columnsMock[0].header!.menu!.commandItems![1] as MenuCommandItem).itemVisibilityOverride = () => false; (columnsMock[0].header!.menu!.commandItems![1] as MenuCommandItem).itemUsabilityOverride = () => false; - const eventData = { ...new Slick.EventData(), preventDefault: jest.fn() }; - gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData, gridStub); + const eventData = { ...new SlickEventData(), preventDefault: jest.fn() }; + gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData as any, gridStub); const headerButtonElm = headerDiv.querySelector('.slick-header-menu-button:nth-child(1)') as HTMLDivElement; headerButtonElm.dispatchEvent(new Event('click', { bubbles: true, cancelable: true, composed: false })); const commandElm = gridContainerDiv.querySelector('.slick-menu-item.slick-menu-item-disabled') as HTMLDivElement; @@ -502,9 +501,9 @@ describe('HeaderMenu Plugin', () => { (columnsMock[0].header!.menu!.commandItems![1] as MenuCommandItem).itemUsabilityOverride = () => true; (columnsMock[0].header!.menu!.commandItems![1] as MenuCommandItem).disabled = true; - const eventData = { ...new Slick.EventData(), preventDefault: jest.fn() }; - gridStub.onBeforeSetColumns.notify({ previousColumns: [], newColumns: columnsMock, grid: gridStub }, eventData, gridStub); - gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData, gridStub); + const eventData = { ...new SlickEventData(), preventDefault: jest.fn() }; + gridStub.onBeforeSetColumns.notify({ previousColumns: [], newColumns: columnsMock, grid: gridStub }, eventData as any, gridStub); + gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData as any, gridStub); const headerButtonElm = headerDiv.querySelector('.slick-header-menu-button') as HTMLDivElement; expect(headerButtonElm).toBeFalsy(); @@ -517,9 +516,9 @@ describe('HeaderMenu Plugin', () => { plugin.dispose(); plugin.init(); - const eventData = { ...new Slick.EventData(), preventDefault: jest.fn() }; - gridStub.onBeforeSetColumns.notify({ previousColumns: [], newColumns: columnsMock, grid: gridStub }, eventData, gridStub); - gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData, gridStub); + const eventData = { ...new SlickEventData(), preventDefault: jest.fn() }; + gridStub.onBeforeSetColumns.notify({ previousColumns: [], newColumns: columnsMock, grid: gridStub }, eventData as any, gridStub); + gridStub.onHeaderCellRendered.notify({ column: columnsMock[0], node: headerDiv, grid: gridStub }, eventData as any, gridStub); const headerButtonElm = headerDiv.querySelector('.slick-header-menu-button') as HTMLDivElement; headerButtonElm.dispatchEvent(new Event('click', { bubbles: true, cancelable: true, composed: false })); const commandElm = gridContainerDiv.querySelector('.slick-menu-item[data-command="show-negative-numbers"]') as HTMLDivElement; @@ -799,7 +798,7 @@ describe('HeaderMenu Plugin', () => { columnsMock[2].header!.menu = undefined; headerDiv = document.createElement('div'); headerDiv.className = 'slick-header-column'; - eventData = { ...new Slick.EventData(), preventDefault: jest.fn() }; + eventData = { ...new SlickEventData(), preventDefault: jest.fn() } as unknown as SlickEventData; }); afterEach(() => { @@ -819,8 +818,8 @@ describe('HeaderMenu Plugin', () => { }); plugin.init({ onBeforeMenuShow: () => false }); - gridStub.onBeforeSetColumns.notify({ previousColumns: [], newColumns: originalColumnDefinitions, grid: gridStub }, eventData, gridStub); - gridStub.onHeaderCellRendered.notify({ column: originalColumnDefinitions[0], node: headerDiv, grid: gridStub }, eventData, gridStub); + gridStub.onBeforeSetColumns.notify({ previousColumns: [], newColumns: originalColumnDefinitions, grid: gridStub }, eventData as any, gridStub); + gridStub.onHeaderCellRendered.notify({ column: originalColumnDefinitions[0], node: headerDiv, grid: gridStub }, eventData as any, gridStub); const headerButtonElm = headerDiv.querySelector('.slick-header-menu-button') as HTMLDivElement; headerButtonElm.dispatchEvent(new Event('click', { bubbles: true, cancelable: true, composed: false })); @@ -841,8 +840,8 @@ describe('HeaderMenu Plugin', () => { plugin.init({ onAfterMenuShow: () => false }); const onAfterSpy = jest.spyOn(plugin.addonOptions, 'onAfterMenuShow').mockReturnValue(false); - gridStub.onBeforeSetColumns.notify({ previousColumns: [], newColumns: columnsMock, grid: gridStub }, eventData, gridStub); - gridStub.onHeaderCellRendered.notify({ column: columnsMock[1], node: headerDiv, grid: gridStub }, eventData, gridStub); + gridStub.onBeforeSetColumns.notify({ previousColumns: [], newColumns: columnsMock, grid: gridStub }, eventData as any, gridStub); + gridStub.onHeaderCellRendered.notify({ column: columnsMock[1], node: headerDiv, grid: gridStub }, eventData as any, gridStub); const headerButtonElm = headerDiv.querySelector('.slick-header-menu-button') as HTMLDivElement; headerButtonElm.dispatchEvent(new Event('click', { bubbles: true, cancelable: true, composed: false })); const clearFilterSpy = jest.spyOn(filterServiceStub, 'clearFilterByColumnId'); @@ -874,10 +873,10 @@ describe('HeaderMenu Plugin', () => { }); // calling `onBeforeSetColumns` 2x times shouldn't duplicate any column menus - gridStub.onBeforeSetColumns.notify({ previousColumns: [], newColumns: columnsMock, grid: gridStub }, eventData, gridStub); - gridStub.onBeforeSetColumns.notify({ previousColumns: [], newColumns: columnsMock, grid: gridStub }, eventData, gridStub); - gridStub.onHeaderCellRendered.notify({ column: columnsMock[1], node: headerDiv, grid: gridStub }, eventData, gridStub); - gridStub.onHeaderCellRendered.notify({ column: columnsMock[1], node: headerDiv, grid: gridStub }, eventData, gridStub); + gridStub.onBeforeSetColumns.notify({ previousColumns: [], newColumns: columnsMock, grid: gridStub }, eventData as any, gridStub); + gridStub.onBeforeSetColumns.notify({ previousColumns: [], newColumns: columnsMock, grid: gridStub }, eventData as any, gridStub); + gridStub.onHeaderCellRendered.notify({ column: columnsMock[1], node: headerDiv, grid: gridStub }, eventData as any, gridStub); + gridStub.onHeaderCellRendered.notify({ column: columnsMock[1], node: headerDiv, grid: gridStub }, eventData as any, gridStub); const headerButtonElm = headerDiv.querySelector('.slick-header-menu-button') as HTMLDivElement; headerButtonElm.dispatchEvent(new Event('click', { bubbles: true, cancelable: true, composed: false })); const pubSubSpy = jest.spyOn(pubSubServiceStub, 'publish'); @@ -908,10 +907,10 @@ describe('HeaderMenu Plugin', () => { }); // calling `onBeforeSetColumns` 2x times shouldn't duplicate hide column menu - gridStub.onBeforeSetColumns.notify({ previousColumns: [], newColumns: columnsMock, grid: gridStub }, eventData, gridStub); - gridStub.onBeforeSetColumns.notify({ previousColumns: [], newColumns: columnsMock, grid: gridStub }, eventData, gridStub); - gridStub.onHeaderCellRendered.notify({ column: columnsMock[1], node: headerDiv, grid: gridStub }, eventData, gridStub); - gridStub.onHeaderCellRendered.notify({ column: columnsMock[1], node: headerDiv, grid: gridStub }, eventData, gridStub); + gridStub.onBeforeSetColumns.notify({ previousColumns: [], newColumns: columnsMock, grid: gridStub }, eventData as any, gridStub); + gridStub.onBeforeSetColumns.notify({ previousColumns: [], newColumns: columnsMock, grid: gridStub }, eventData as any, gridStub); + gridStub.onHeaderCellRendered.notify({ column: columnsMock[1], node: headerDiv, grid: gridStub }, eventData as any, gridStub); + gridStub.onHeaderCellRendered.notify({ column: columnsMock[1], node: headerDiv, grid: gridStub }, eventData as any, gridStub); const headerButtonElm = headerDiv.querySelector('.slick-header-menu-button') as HTMLDivElement; headerButtonElm.dispatchEvent(new Event('click', { bubbles: true, cancelable: true, composed: false })); const autosizeSpy = jest.spyOn(gridStub, 'autosizeColumns'); @@ -939,9 +938,9 @@ describe('HeaderMenu Plugin', () => { }); // calling `onBeforeSetColumns` 2x times shouldn't duplicate clear filter menu - gridStub.onBeforeSetColumns.notify({ previousColumns: [], newColumns: columnsMock, grid: gridStub }, eventData, gridStub); - gridStub.onBeforeSetColumns.notify({ previousColumns: [], newColumns: columnsMock, grid: gridStub }, eventData, gridStub); - gridStub.onHeaderCellRendered.notify({ column: columnsMock[1], node: headerDiv, grid: gridStub }, eventData, gridStub); + gridStub.onBeforeSetColumns.notify({ previousColumns: [], newColumns: columnsMock, grid: gridStub }, eventData as any, gridStub); + gridStub.onBeforeSetColumns.notify({ previousColumns: [], newColumns: columnsMock, grid: gridStub }, eventData as any, gridStub); + gridStub.onHeaderCellRendered.notify({ column: columnsMock[1], node: headerDiv, grid: gridStub }, eventData as any, gridStub); const headerButtonElm = headerDiv.querySelector('.slick-header-menu-button') as HTMLDivElement; headerButtonElm.dispatchEvent(new Event('click', { bubbles: true, cancelable: true, composed: false })); const clearFilterSpy = jest.spyOn(filterServiceStub, 'clearFilterByColumnId'); @@ -966,10 +965,10 @@ describe('HeaderMenu Plugin', () => { }); // calling `onBeforeSetColumns` 2x times shouldn't duplicate clear sort menu - const eventData = { ...new Slick.EventData(), preventDefault: jest.fn() }; - gridStub.onBeforeSetColumns.notify({ previousColumns: [], newColumns: columnsMock, grid: gridStub }, eventData, gridStub); - gridStub.onBeforeSetColumns.notify({ previousColumns: [], newColumns: columnsMock, grid: gridStub }, eventData, gridStub); - gridStub.onHeaderCellRendered.notify({ column: columnsMock[1], node: headerDiv, grid: gridStub }, eventData, gridStub); + const eventData = { ...new SlickEventData(), preventDefault: jest.fn() }; + gridStub.onBeforeSetColumns.notify({ previousColumns: [], newColumns: columnsMock, grid: gridStub }, eventData as any, gridStub); + gridStub.onBeforeSetColumns.notify({ previousColumns: [], newColumns: columnsMock, grid: gridStub }, eventData as any, gridStub); + gridStub.onHeaderCellRendered.notify({ column: columnsMock[1], node: headerDiv, grid: gridStub }, eventData as any, gridStub); const headerButtonElm = headerDiv.querySelector('.slick-header-menu-button') as HTMLDivElement; headerButtonElm.dispatchEvent(new Event('click', { bubbles: true, cancelable: true, composed: false })); const clearSortSpy = jest.spyOn(sortServiceStub, 'clearSortByColumnId'); @@ -1008,9 +1007,9 @@ describe('HeaderMenu Plugin', () => { }); // calling `onBeforeSetColumns` 2x times shouldn't duplicate clear sort menu - gridStub.onBeforeSetColumns.notify({ previousColumns: [], newColumns: columnsMock, grid: gridStub }, eventData, gridStub); - gridStub.onBeforeSetColumns.notify({ previousColumns: [], newColumns: columnsMock, grid: gridStub }, eventData, gridStub); - gridStub.onHeaderCellRendered.notify({ column: columnsMock[1], node: headerDiv, grid: gridStub }, eventData, gridStub); + gridStub.onBeforeSetColumns.notify({ previousColumns: [], newColumns: columnsMock, grid: gridStub }, eventData as any, gridStub); + gridStub.onBeforeSetColumns.notify({ previousColumns: [], newColumns: columnsMock, grid: gridStub }, eventData as any, gridStub); + gridStub.onHeaderCellRendered.notify({ column: columnsMock[1], node: headerDiv, grid: gridStub }, eventData as any, gridStub); const headerButtonElm = headerDiv.querySelector('.slick-header-menu-button') as HTMLDivElement; headerButtonElm.dispatchEvent(new Event('click', { bubbles: true, cancelable: true, composed: false })); @@ -1044,8 +1043,8 @@ describe('HeaderMenu Plugin', () => { headerMenu: { hideFreezeColumnsCommand: false, hideColumnHideCommand: true, hideColumnResizeByContentCommand: true, } }); - gridStub.onBeforeSetColumns.notify({ previousColumns: [], newColumns: columnsMock, grid: gridStub }, eventData, gridStub); - gridStub.onHeaderCellRendered.notify({ column: columnsMock[2], node: headerDiv, grid: gridStub }, eventData, gridStub); + gridStub.onBeforeSetColumns.notify({ previousColumns: [], newColumns: columnsMock, grid: gridStub }, eventData as any, gridStub); + gridStub.onHeaderCellRendered.notify({ column: columnsMock[2], node: headerDiv, grid: gridStub }, eventData as any, gridStub); const headerButtonElm = headerDiv.querySelector('.slick-header-menu-button') as HTMLDivElement; headerButtonElm.dispatchEvent(new Event('click', { bubbles: true, cancelable: true, composed: false })); @@ -1072,8 +1071,8 @@ describe('HeaderMenu Plugin', () => { headerMenu: { hideFreezeColumnsCommand: false, hideColumnHideCommand: true, hideColumnResizeByContentCommand: true, } }); - gridStub.onBeforeSetColumns.notify({ previousColumns: [], newColumns: originalColumnDefinitions, grid: gridStub }, eventData, gridStub); - gridStub.onHeaderCellRendered.notify({ column: originalColumnDefinitions[0], node: headerDiv, grid: gridStub }, eventData, gridStub); + gridStub.onBeforeSetColumns.notify({ previousColumns: [], newColumns: originalColumnDefinitions, grid: gridStub }, eventData as any, gridStub); + gridStub.onHeaderCellRendered.notify({ column: originalColumnDefinitions[0], node: headerDiv, grid: gridStub }, eventData as any, gridStub); const headerButtonElm = headerDiv.querySelector('.slick-header-menu-button') as HTMLDivElement; headerButtonElm.dispatchEvent(new Event('click', { bubbles: true, cancelable: true, composed: false })); @@ -1099,8 +1098,8 @@ describe('HeaderMenu Plugin', () => { headerMenu: { hideFreezeColumnsCommand: true, hideColumnHideCommand: true, hideColumnResizeByContentCommand: true, } }); - gridStub.onBeforeSetColumns.notify({ previousColumns: [], newColumns: columnsMock, grid: gridStub }, eventData, gridStub); - gridStub.onHeaderCellRendered.notify({ column: columnsMock[1], node: headerDiv, grid: gridStub }, eventData, gridStub); + gridStub.onBeforeSetColumns.notify({ previousColumns: [], newColumns: columnsMock, grid: gridStub }, eventData as any, gridStub); + gridStub.onHeaderCellRendered.notify({ column: columnsMock[1], node: headerDiv, grid: gridStub }, eventData as any, gridStub); const headerButtonElm = headerDiv.querySelector('.slick-header-menu-button') as HTMLDivElement; headerButtonElm.dispatchEvent(new Event('click', { bubbles: true, cancelable: true, composed: false })); @@ -1131,8 +1130,8 @@ describe('HeaderMenu Plugin', () => { headerMenu: { hideFreezeColumnsCommand: true, hideColumnHideCommand: true, hideColumnResizeByContentCommand: true, } }); - gridStub.onBeforeSetColumns.notify({ previousColumns: [], newColumns: columnsMock, grid: gridStub }, eventData, gridStub); - gridStub.onHeaderCellRendered.notify({ column: columnsMock[1], node: headerDiv, grid: gridStub }, eventData, gridStub); + gridStub.onBeforeSetColumns.notify({ previousColumns: [], newColumns: columnsMock, grid: gridStub }, eventData as any, gridStub); + gridStub.onHeaderCellRendered.notify({ column: columnsMock[1], node: headerDiv, grid: gridStub }, eventData as any, gridStub); const headerButtonElm = headerDiv.querySelector('.slick-header-menu-button') as HTMLDivElement; headerButtonElm.dispatchEvent(new Event('click', { bubbles: true, cancelable: true, composed: false })); @@ -1164,8 +1163,8 @@ describe('HeaderMenu Plugin', () => { headerMenu: { hideFreezeColumnsCommand: true, hideColumnHideCommand: true, hideColumnResizeByContentCommand: true, } }); - gridStub.onBeforeSetColumns.notify({ previousColumns: [], newColumns: columnsMock, grid: gridStub }, eventData, gridStub); - gridStub.onHeaderCellRendered.notify({ column: columnsMock[1], node: headerDiv, grid: gridStub }, eventData, gridStub); + gridStub.onBeforeSetColumns.notify({ previousColumns: [], newColumns: columnsMock, grid: gridStub }, eventData as any, gridStub); + gridStub.onHeaderCellRendered.notify({ column: columnsMock[1], node: headerDiv, grid: gridStub }, eventData as any, gridStub); const headerButtonElm = headerDiv.querySelector('.slick-header-menu-button') as HTMLDivElement; headerButtonElm.dispatchEvent(new Event('click', { bubbles: true, cancelable: true, composed: false })); gridContainerDiv.querySelector('[data-command="sort-desc"]')!.dispatchEvent(new Event('click')); @@ -1188,8 +1187,8 @@ describe('HeaderMenu Plugin', () => { headerMenu: { hideFreezeColumnsCommand: true, hideColumnHideCommand: true, hideColumnResizeByContentCommand: true, } }); - gridStub.onBeforeSetColumns.notify({ previousColumns: [], newColumns: columnsMock, grid: gridStub }, eventData, gridStub); - gridStub.onHeaderCellRendered.notify({ column: columnsMock[1], node: headerDiv, grid: gridStub }, eventData, gridStub); + gridStub.onBeforeSetColumns.notify({ previousColumns: [], newColumns: columnsMock, grid: gridStub }, eventData as any, gridStub); + gridStub.onHeaderCellRendered.notify({ column: columnsMock[1], node: headerDiv, grid: gridStub }, eventData as any, gridStub); const headerButtonElm = headerDiv.querySelector('.slick-header-menu-button') as HTMLDivElement; headerButtonElm.dispatchEvent(new Event('click', { bubbles: true, cancelable: true, composed: false })); gridContainerDiv.querySelector('[data-command="sort-desc"]')!.dispatchEvent(new Event('click')); diff --git a/packages/common/src/extensions/__tests__/slickRowMoveManager.spec.ts b/packages/common/src/extensions/__tests__/slickRowMoveManager.spec.ts index 7df6f47f5..f86585102 100644 --- a/packages/common/src/extensions/__tests__/slickRowMoveManager.spec.ts +++ b/packages/common/src/extensions/__tests__/slickRowMoveManager.spec.ts @@ -1,10 +1,10 @@ import { BasePubSubService } from '@slickgrid-universal/event-pub-sub'; import 'jest-extended'; +import { SlickEvent } from 'slickgrid'; -import { Column, DragRowMove, GridOption, OnDragEventArgs, SlickGrid, SlickNamespace, } from '../../interfaces/index'; +import { Column, DragRowMove, GridOption, SlickGridUniversal } from '../../interfaces/index'; import { SlickRowMoveManager } from '../slickRowMoveManager'; -declare const Slick: SlickNamespace; const GRID_UID = 'slickgrid_12345'; jest.mock('flatpickr', () => { }); @@ -52,11 +52,11 @@ const gridStub = { scrollCellIntoView: jest.fn(), scrollRowIntoView: jest.fn(), unregisterPlugin: jest.fn(), - onDrag: new Slick.Event(), - onDragInit: new Slick.Event(), - onDragEnd: new Slick.Event(), - onDragStart: new Slick.Event(), -} as unknown as SlickGrid; + onDrag: new SlickEvent(), + onDragInit: new SlickEvent(), + onDragEnd: new SlickEvent(), + onDragStart: new SlickEvent(), +} as unknown as SlickGridUniversal; const pubSubServiceStub = { publish: jest.fn(), diff --git a/packages/common/src/extensions/__tests__/slickRowSelectionModel.spec.ts b/packages/common/src/extensions/__tests__/slickRowSelectionModel.spec.ts index d114391fc..ef71f97ff 100644 --- a/packages/common/src/extensions/__tests__/slickRowSelectionModel.spec.ts +++ b/packages/common/src/extensions/__tests__/slickRowSelectionModel.spec.ts @@ -1,10 +1,10 @@ import 'jest-extended'; +import { SlickEvent, SlickRange } from 'slickgrid'; -import { Column, GridOption, SlickGrid, SlickNamespace, SlickRange, } from '../../interfaces/index'; +import { Column, GridOption, SlickGridUniversal, } from '../../interfaces/index'; import { SlickCellRangeSelector } from '../slickCellRangeSelector'; import { SlickRowSelectionModel } from '../slickRowSelectionModel'; -declare const Slick: SlickNamespace; const GRID_UID = 'slickgrid_12345'; jest.mock('flatpickr', () => { }); @@ -50,12 +50,12 @@ const gridStub = { scrollCellIntoView: jest.fn(), scrollRowIntoView: jest.fn(), unregisterPlugin: jest.fn(), - onActiveCellChanged: new Slick.Event(), - onClick: new Slick.Event(), - onKeyDown: new Slick.Event(), - onSelectedRangesChanged: new Slick.Event(), - onBeforeCellRangeSelected: new Slick.Event(), -} as unknown as SlickGrid; + onActiveCellChanged: new SlickEvent(), + onClick: new SlickEvent(), + onKeyDown: new SlickEvent(), + onSelectedRangesChanged: new SlickEvent(), + onBeforeCellRangeSelected: new SlickEvent(), +} as unknown as SlickGridUniversal; describe('SlickRowSelectionModel Plugin', () => { let plugin: SlickRowSelectionModel; @@ -188,10 +188,10 @@ describe('SlickRowSelectionModel Plugin', () => { it('should call "setSelectedRanges" with valid ranges input and expect to "onSelectedRangesChanged" to be triggered', () => { const onSelectedRangeSpy = jest.spyOn(plugin.onSelectedRangesChanged, 'notify'); - plugin.setSelectedRanges([{ fromCell: 0, fromRow: 0, toCell: 2, toRow: 0, }]); + plugin.setSelectedRanges([new SlickRange(0, 0, 0, 2)]); expect(onSelectedRangeSpy).toHaveBeenCalledWith( - [{ fromCell: 0, fromRow: 0, toCell: 2, toRow: 0, }], + [new SlickRange(0, 0, 0, 2)], expect.objectContaining({ detail: { caller: 'SlickRowSelectionModel.setSelectedRanges' } })); @@ -216,8 +216,8 @@ describe('SlickRowSelectionModel Plugin', () => { jest.spyOn(gridStub, 'getDataLength').mockReturnValue(6); jest.spyOn(gridStub, 'getColumns').mockReturnValue(mockColumns); const mockRanges = [ - { fromCell: 2, fromRow: 3, toCell: 3, toRow: 4 }, - { fromCell: 1, fromRow: 2, toCell: 3, toRow: 4 } + new SlickRange(3, 2, 4, 3), + new SlickRange(2, 1, 4, 3) ] as unknown as SlickRange[]; plugin.init(gridStub); plugin.setSelectedRanges(mockRanges); @@ -246,8 +246,8 @@ describe('SlickRowSelectionModel Plugin', () => { jest.spyOn(gridStub, 'getDataLength').mockReturnValue(6); jest.spyOn(gridStub, 'getColumns').mockReturnValue(mockColumns); const mockRanges = [ - { fromCell: 1, fromRow: 2, toCell: 3, toRow: 4 }, - { fromCell: 2, fromRow: 3, toCell: 3, toRow: 4 } + new SlickRange(2, 1, 4, 3), + new SlickRange(3, 2, 4, 3) ] as unknown as SlickRange[]; plugin.init(gridStub); plugin.setSelectedRanges(mockRanges); @@ -271,8 +271,8 @@ describe('SlickRowSelectionModel Plugin', () => { jest.spyOn(gridStub, 'getColumns').mockReturnValue(mockColumns); jest.spyOn(plugin, 'getSelectedRows').mockReturnValue([3, 3]); const mockRanges = [ - { fromCell: 1, fromRow: 2, toCell: 3, toRow: 4 }, - { fromCell: 2, fromRow: 3, toCell: 3, toRow: 4 } + new SlickRange(2, 1, 4, 3), + new SlickRange(3, 2, 4, 3) ] as unknown as SlickRange[]; plugin.init(gridStub); plugin.setSelectedRanges(mockRanges); @@ -293,8 +293,8 @@ describe('SlickRowSelectionModel Plugin', () => { jest.spyOn(gridStub, 'getColumns').mockReturnValue(mockColumns); jest.spyOn(plugin, 'getSelectedRows').mockReturnValue([]); const mockRanges = [ - { fromCell: 1, fromRow: 2, toCell: 3, toRow: 4 }, - { fromCell: 2, fromRow: 3, toCell: 3, toRow: 4 } + new SlickRange(2, 1, 4, 3), + new SlickRange(3, 2, 4, 3) ] as unknown as SlickRange[]; plugin.init(gridStub); plugin.setSelectedRanges(mockRanges); @@ -318,8 +318,8 @@ describe('SlickRowSelectionModel Plugin', () => { jest.spyOn(gridStub, 'getDataLength').mockReturnValue(6); jest.spyOn(gridStub, 'getColumns').mockReturnValue(mockColumns); const mockRanges = [ - { fromCell: 1, fromRow: 2, toCell: 3, toRow: 4 }, - { fromCell: 2, fromRow: 3, toCell: 3, toRow: 4 } + new SlickRange(2, 1, 4, 3), + new SlickRange(3, 2, 4, 3) ] as unknown as SlickRange[]; plugin.init(gridStub); plugin.setSelectedRanges(mockRanges); @@ -338,8 +338,8 @@ describe('SlickRowSelectionModel Plugin', () => { jest.spyOn(gridStub, 'getDataLength').mockReturnValue(6); jest.spyOn(gridStub, 'getColumns').mockReturnValue(mockColumns); const mockRanges = [ - { fromCell: 1, fromRow: 2, toCell: 3, toRow: 4 }, - { fromCell: 2, fromRow: 3, toCell: 3, toRow: 4 } + new SlickRange(2, 1, 4, 3), + new SlickRange(3, 2, 4, 3) ] as unknown as SlickRange[]; plugin.init(gridStub); plugin.setSelectedRanges(mockRanges); @@ -357,8 +357,8 @@ describe('SlickRowSelectionModel Plugin', () => { jest.spyOn(gridStub, 'getDataLength').mockReturnValue(6); jest.spyOn(gridStub, 'getColumns').mockReturnValue(mockColumns); const mockRanges = [ - { fromCell: 1, fromRow: 2, toCell: 3, toRow: 4 }, - { fromCell: 2, fromRow: 3, toCell: 3, toRow: 4 } + new SlickRange(2, 1, 4, 3), + new SlickRange(3, 2, 4, 3) ] as unknown as SlickRange[]; plugin.init(gridStub); plugin.setSelectedRanges(mockRanges); @@ -386,8 +386,8 @@ describe('SlickRowSelectionModel Plugin', () => { jest.spyOn(gridStub, 'getColumns').mockReturnValue(mockColumns); const setActiveCellSpy = jest.spyOn(gridStub, 'setActiveCell'); const mockRanges = [ - { fromCell: 1, fromRow: 2, toCell: 3, toRow: 4 }, - { fromCell: 2, fromRow: 3, toCell: 3, toRow: 4 } + new SlickRange(2, 1, 4, 3), + new SlickRange(3, 2, 4, 3) ] as unknown as SlickRange[]; plugin.init(gridStub); plugin.setSelectedRanges(mockRanges); @@ -413,8 +413,8 @@ describe('SlickRowSelectionModel Plugin', () => { jest.spyOn(gridStub, 'getColumns').mockReturnValue(mockColumns); const setActiveCellSpy = jest.spyOn(gridStub, 'setActiveCell'); const mockRanges = [ - { fromCell: 1, fromRow: 2, toCell: 3, toRow: 4 }, - { fromCell: 2, fromRow: 3, toCell: 3, toRow: 4 } + new SlickRange(2, 1, 4, 3), + new SlickRange(3, 2, 4, 3) ] as unknown as SlickRange[]; plugin.init(gridStub); plugin.setSelectedRanges(mockRanges); @@ -445,8 +445,8 @@ describe('SlickRowSelectionModel Plugin', () => { jest.spyOn(gridStub, 'getDataLength').mockReturnValue(6); jest.spyOn(gridStub, 'getColumns').mockReturnValue(mockColumns); const mockRanges = [ - { fromCell: 1, fromRow: 2, toCell: 3, toRow: 4 }, - { fromCell: 2, fromRow: 3, toCell: 3, toRow: 4 } + new SlickRange(2, 1, 4, 3), + new SlickRange(3, 2, 4, 3) ] as unknown as SlickRange[]; plugin.init(gridStub); plugin.setSelectedRanges(mockRanges); @@ -490,7 +490,7 @@ describe('SlickRowSelectionModel Plugin', () => { plugin.init(gridStub); const scrollEvent = addVanillaEventPropagation(new Event('scroll')); - plugin.getCellRangeSelector()!.onCellRangeSelected.notify({ range: { fromCell: 2, fromRow: 3, toCell: 4, toRow: 5 } }, scrollEvent, gridStub); + plugin.getCellRangeSelector()!.onCellRangeSelected.notify({ range: new SlickRange(3, 2, 5, 4) }, scrollEvent, gridStub); expect(setSelectedRangeSpy).toHaveBeenCalledWith([{ fromCell: 0, fromRow: 3, toCell: 2, toRow: 5, @@ -512,7 +512,7 @@ describe('SlickRowSelectionModel Plugin', () => { }); plugin.init(gridStub); const scrollEvent = addVanillaEventPropagation(new Event('scroll')); - plugin.getCellRangeSelector()!.onCellRangeSelected.notify({ range: { fromCell: 2, fromRow: 3, toCell: 4, toRow: 5 } }, scrollEvent, gridStub); + plugin.getCellRangeSelector()!.onCellRangeSelected.notify({ range: new SlickRange(3, 2, 5, 4) }, scrollEvent, gridStub); expect(setSelectedRangeSpy).toHaveBeenCalledWith([{ fromCell: 0, fromRow: 3, toCell: 2, toRow: 5, @@ -526,7 +526,7 @@ describe('SlickRowSelectionModel Plugin', () => { plugin.init(gridStub); const scrollEvent = addVanillaEventPropagation(new Event('scroll')); - plugin.getCellRangeSelector()!.onCellRangeSelected.notify({ range: { fromCell: 2, fromRow: 3, toCell: 4, toRow: 5 } }, scrollEvent, gridStub); + plugin.getCellRangeSelector()!.onCellRangeSelected.notify({ range: new SlickRange(3, 2, 5, 4) }, scrollEvent, gridStub); expect(setSelectedRangeSpy).not.toHaveBeenCalled(); }); diff --git a/packages/common/src/extensions/menuBaseClass.ts b/packages/common/src/extensions/menuBaseClass.ts index 600f5b751..3017df8f0 100644 --- a/packages/common/src/extensions/menuBaseClass.ts +++ b/packages/common/src/extensions/menuBaseClass.ts @@ -1,5 +1,6 @@ import type { BasePubSubService } from '@slickgrid-universal/event-pub-sub'; import { hasData } from '@slickgrid-universal/utils'; +import { SlickEventHandler } from 'slickgrid'; import type { CellMenu, @@ -15,18 +16,13 @@ import type { HeaderMenuCommandItem, MenuCommandItem, MenuOptionItem, - SlickEventHandler, - SlickGrid, - SlickNamespace, + SlickGridUniversal, } from '../interfaces/index'; import { BindingEventService } from '../services/bindingEvent.service'; import type { ExtensionUtility } from '../extensions/extensionUtility'; import type { SharedService } from '../services/shared.service'; import { createDomElement, emptyElement } from '../services/domUtilities'; -// using external SlickGrid JS libraries -declare const Slick: SlickNamespace; - export type MenuType = 'command' | 'option'; export type ExtendableItemTypes = HeaderButtonItem | MenuCommandItem | MenuOptionItem | 'divider'; @@ -56,7 +52,7 @@ export class MenuBaseClass(); + onCopyCancelled = new SlickEvent<{ ranges: CellRange[]; }>(); + onPasteCells = new SlickEvent<{ ranges: CellRange[]; }>(); + protected _addonOptions!: ExcelCopyBufferOption; protected _bodyElement = document.body; protected _clearCopyTI?: NodeJS.Timeout; @@ -31,16 +35,12 @@ export class SlickCellExternalCopyManager { protected _copiedCellStyleLayerKey = 'copy-manager'; protected _copiedRanges: CellRange[] | null = null; protected _eventHandler: SlickEventHandler; - protected _grid!: SlickGrid; + protected _grid!: SlickGridUniversal; protected _onCopyInit?: () => void; protected _onCopySuccess?: (rowCount: number) => void; - pluginName: 'CellExternalCopyManager' = 'CellExternalCopyManager' as const; - onCopyCells = new Slick.Event(); - onCopyCancelled = new Slick.Event(); - onPasteCells = new Slick.Event(); constructor() { - this._eventHandler = new Slick.EventHandler() as SlickEventHandler; + this._eventHandler = new SlickEventHandler(); } get addonOptions() { @@ -51,7 +51,7 @@ export class SlickCellExternalCopyManager { return this._eventHandler; } - init(grid: SlickGrid, options?: ExcelCopyBufferOption) { + init(grid: SlickGridUniversal, options?: ExcelCopyBufferOption) { this._grid = grid; this._addonOptions = { ...this._addonOptions, ...options }; this._copiedCellStyleLayerKey = this._addonOptions.copiedCellStyleLayerKey || 'copy-manager'; @@ -65,7 +65,7 @@ export class SlickCellExternalCopyManager { // we need a cell selection model const cellSelectionModel = grid.getSelectionModel(); if (!cellSelectionModel) { - throw new Error(`Selection model is mandatory for this plugin. Please set a selection model on the grid before adding this plugin: grid.setSelectionModel(new Slick.CellSelectionModel())`); + throw new Error(`Selection model is mandatory for this plugin. Please set a selection model on the grid before adding this plugin: grid.setSelectionModel(new SlickCellSelectionModel())`); } // we give focus on the grid when a selection is done on it (unless it's an editor, if so the editor should have already set focus to the grid prior to editing a cell). @@ -174,7 +174,7 @@ export class SlickCellExternalCopyManager { return textAreaElm; } - protected decodeTabularData(grid: SlickGrid, textAreaElement: HTMLTextAreaElement) { + protected decodeTabularData(grid: SlickGridUniversal, textAreaElement: HTMLTextAreaElement) { const columns = grid.getColumns(); const clipText = textAreaElement.value; const clipRows = clipText.split(/[\n\f\r]/); @@ -214,12 +214,12 @@ export class SlickCellExternalCopyManager { destH = selectedRange.toRow - selectedRange.fromRow + 1; destW = selectedRange.toCell - selectedRange.fromCell + 1; } - const availableRows = (this._grid.getData() as any[]).length - activeRow; + const availableRows = this._grid.getData().length - activeRow; let addRows = 0; // ignore new rows if we don't have a "newRowCreator" if ((availableRows < destH) && typeof this._addonOptions.newRowCreator === 'function') { - const d: any[] = this._grid.getData(); + const d = this._grid.getData(); for (addRows = 1; addRows <= (destH - availableRows); addRows++) { d.push({}); } @@ -283,12 +283,12 @@ export class SlickCellExternalCopyManager { } } - const bRange = { - fromCell: activeCell, - fromRow: activeRow, - toCell: activeCell + clipCommand.w - 1, - toRow: activeRow + clipCommand.h - 1 - }; + const bRange = new SlickRange( + activeRow, + activeCell, + activeRow + clipCommand.h - 1, + activeCell + clipCommand.w - 1 + ); this.markCopySelection([bRange]); this._grid.getSelectionModel()?.setSelectedRanges([bRange]); this.onPasteCells.notify({ ranges: [bRange] }); @@ -320,22 +320,22 @@ export class SlickCellExternalCopyManager { } } - const bRange = { - fromCell: activeCell, - fromRow: activeRow, - toCell: activeCell + clipCommand.w - 1, - toRow: activeRow + clipCommand.h - 1 - }; + const bRange = new SlickRange( + activeRow, + activeCell, + activeRow + clipCommand.h - 1, + activeCell + clipCommand.w - 1 + ); this.markCopySelection([bRange]); this._grid.getSelectionModel()?.setSelectedRanges([bRange]); this.onPasteCells.notify({ ranges: [bRange] }); if (typeof this._addonOptions.onPasteCells === 'function') { - this._addonOptions.onPasteCells(new Slick.EventData(), { ranges: [bRange] }); + this._addonOptions.onPasteCells(new SlickEventData(), { ranges: [bRange] }); } if (addRows > 1) { - const data = this._grid.getData() as any[]; + const data = this._grid.getData(); for (; addRows > 1; addRows--) { data.splice(data.length - 1, 1); } diff --git a/packages/common/src/extensions/slickCellMenu.ts b/packages/common/src/extensions/slickCellMenu.ts index b976ec112..0a8fc14de 100644 --- a/packages/common/src/extensions/slickCellMenu.ts +++ b/packages/common/src/extensions/slickCellMenu.ts @@ -32,6 +32,8 @@ import { MenuFromCellBaseClass } from './menuFromCellBaseClass'; * }]; */ export class SlickCellMenu extends MenuFromCellBaseClass { + pluginName: 'CellMenu' = 'CellMenu' as const; + protected _defaults = { autoAdjustDrop: true, // dropup/dropdown autoAlignSide: true, // left/right @@ -40,7 +42,6 @@ export class SlickCellMenu extends MenuFromCellBaseClass { hideMenuOnScroll: true, subMenuOpenByEvent: 'mouseover', } as unknown as CellMenuOption; - pluginName: 'CellMenu' = 'CellMenu' as const; /** Constructor of the SlickGrid 3rd party plugin, it can optionally receive options */ constructor( diff --git a/packages/common/src/extensions/slickCellRangeDecorator.ts b/packages/common/src/extensions/slickCellRangeDecorator.ts index 18ad9c481..24f7736dc 100644 --- a/packages/common/src/extensions/slickCellRangeDecorator.ts +++ b/packages/common/src/extensions/slickCellRangeDecorator.ts @@ -1,6 +1,6 @@ import { deepMerge } from '@slickgrid-universal/utils'; -import { CellRange, CellRangeDecoratorOption, type CSSStyleDeclarationWritable, type SlickGrid } from '../interfaces/index'; +import type { CellRange, CellRangeDecoratorOption, CSSStyleDeclarationWritable, SlickGridUniversal } from '../interfaces/index'; import { createDomElement } from '../services/domUtilities'; /** @@ -13,10 +13,10 @@ import { createDomElement } from '../services/domUtilities'; export class SlickCellRangeDecorator { // -- // public API - pluginName: 'CellRangeDecorator' = 'CellRangeDecorator' as const; + pluginName = 'CellRangeDecorator' as const; - protected _addonOptions!: CellRangeDecoratorOption; - protected _elem?: HTMLElement | null; + protected _options: CellRangeDecoratorOption; + protected _elem?: HTMLDivElement | null; protected _defaults = { selectionCssClass: 'slick-range-decorator', selectionCss: { @@ -26,12 +26,12 @@ export class SlickCellRangeDecorator { offset: { top: -1, left: -1, height: -2, width: -2 } } as CellRangeDecoratorOption; - constructor(protected readonly grid: SlickGrid, options?: Partial) { - this._addonOptions = deepMerge(this._defaults, options); + constructor(protected readonly grid: SlickGridUniversal, options?: Partial) { + this._options = deepMerge(this._defaults, options); } get addonOptions() { - return this._addonOptions; + return this._options; } get addonElement(): HTMLElement | null | undefined { @@ -39,10 +39,12 @@ export class SlickCellRangeDecorator { } /** Dispose the plugin. */ - dispose() { + destroy() { this.hide(); } + init() { } + hide() { this._elem?.remove(); this._elem = null; @@ -50,9 +52,9 @@ export class SlickCellRangeDecorator { show(range: CellRange) { if (!this._elem) { - this._elem = createDomElement('div', { className: this._addonOptions.selectionCssClass }); - Object.keys(this._addonOptions.selectionCss as CSSStyleDeclaration).forEach((cssStyleKey) => { - this._elem!.style[cssStyleKey as CSSStyleDeclarationWritable] = this._addonOptions.selectionCss[cssStyleKey as CSSStyleDeclarationWritable]; + this._elem = createDomElement('div', { className: this._options.selectionCssClass }); + Object.keys(this._options.selectionCss as CSSStyleDeclaration).forEach((cssStyleKey) => { + this._elem!.style[cssStyleKey as CSSStyleDeclarationWritable] = this._options.selectionCss[cssStyleKey as CSSStyleDeclarationWritable]; }); this._elem.style.position = 'absolute'; this.grid.getActiveCanvasNode()?.appendChild(this._elem); @@ -61,11 +63,11 @@ export class SlickCellRangeDecorator { const from = this.grid.getCellNodeBox(range.fromRow, range.fromCell); const to = this.grid.getCellNodeBox(range.toRow, range.toCell); - if (from && to && this._addonOptions?.offset) { - this._elem.style.top = `${from.top + this._addonOptions.offset.top}px`; - this._elem.style.left = `${from.left + this._addonOptions.offset.left}px`; - this._elem.style.height = `${to.bottom - from.top + this._addonOptions.offset.height}px`; - this._elem.style.width = `${to.right - from.left + this._addonOptions.offset.width}px`; + if (from && to && this._options?.offset) { + this._elem.style.top = `${from.top + this._options.offset.top}px`; + this._elem.style.left = `${from.left + this._options.offset.left}px`; + this._elem.style.height = `${to.bottom - from.top + this._options.offset.height}px`; + this._elem.style.width = `${to.right - from.left + this._options.offset.width}px`; } return this._elem; } diff --git a/packages/common/src/extensions/slickCellRangeSelector.ts b/packages/common/src/extensions/slickCellRangeSelector.ts index b4e75c079..4b537efa8 100644 --- a/packages/common/src/extensions/slickCellRangeSelector.ts +++ b/packages/common/src/extensions/slickCellRangeSelector.ts @@ -1,33 +1,32 @@ import { deepMerge } from '@slickgrid-universal/utils'; +import { type OnScrollEventArgs, SlickEvent, type SlickEventData, SlickEventHandler, SlickRange } from 'slickgrid'; import type { - CellRange, CellRangeSelectorOption, DOMMouseOrTouchEvent, DragPosition, DragRange, GridOption, MouseOffsetViewport, - OnScrollEventArgs, - SlickEventData, - SlickEventHandler, - SlickGrid, - SlickNamespace + SlickGridUniversal, } from '../interfaces/index'; import { emptyElement, getHtmlElementOffset, } from '../services/domUtilities'; import { SlickCellRangeDecorator } from './index'; -// using external SlickGrid JS libraries -declare const Slick: SlickNamespace; export class SlickCellRangeSelector { - protected _activeCanvas?: HTMLElement; - protected _addonOptions!: CellRangeSelectorOption; + pluginName: 'CellRangeSelector' = 'CellRangeSelector' as const; + onBeforeCellRangeSelected = new SlickEvent<{ row: number; cell: number; }>(); + onCellRangeSelecting = new SlickEvent<{ range: SlickRange; }>(); + onCellRangeSelected = new SlickEvent<{ range: SlickRange; }>(); + + protected _activeCanvas!: HTMLElement; + protected _options!: CellRangeSelectorOption; protected _currentlySelectedRange: DragRange | null = null; - protected _canvas!: HTMLElement; + protected _canvas: HTMLElement | null = null; protected _decorator!: SlickCellRangeDecorator; protected _dragging = false; protected _eventHandler: SlickEventHandler; - protected _grid!: SlickGrid; + protected _grid!: SlickGridUniversal; protected _gridOptions!: GridOption; protected _gridUid = ''; @@ -60,18 +59,14 @@ export class SlickCellRangeSelector { border: '2px dashed blue' } } as CellRangeSelectorOption; - pluginName: 'CellRangeSelector' = 'CellRangeSelector' as const; - onBeforeCellRangeSelected = new Slick.Event<{ row: number; cell: number; }>(); - onCellRangeSelecting = new Slick.Event<{ range: CellRange; }>(); - onCellRangeSelected = new Slick.Event<{ range: CellRange; }>(); constructor(options?: Partial) { - this._eventHandler = new Slick.EventHandler(); - this._addonOptions = deepMerge(this._defaults, options); + this._eventHandler = new SlickEventHandler(); + this._options = deepMerge(this._defaults, options); } get addonOptions() { - return this._addonOptions; + return this._options; } get eventHandler(): SlickEventHandler { @@ -86,19 +81,19 @@ export class SlickCellRangeSelector { return this.gridUid ? `.${this.gridUid}` : ''; } - init(grid: SlickGrid) { + init(grid: SlickGridUniversal) { this._grid = grid; - this._decorator = this._addonOptions.cellDecorator || new SlickCellRangeDecorator(grid, this._addonOptions); + this._decorator = this._options.cellDecorator || new SlickCellRangeDecorator(grid, this._options); this._canvas = grid.getCanvasNode(); this._gridOptions = grid.getOptions(); this._gridUid = grid.getUID(); this._eventHandler - .subscribe(this._grid.onDrag, this.handleDrag.bind(this) as EventListener) - .subscribe(this._grid.onDragInit, this.handleDragInit.bind(this) as EventListener) - .subscribe(this._grid.onDragStart, this.handleDragStart.bind(this) as EventListener) - .subscribe(this._grid.onDragEnd, this.handleDragEnd.bind(this) as EventListener) - .subscribe(this._grid.onScroll, this.handleScroll.bind(this) as EventListener); + .subscribe(this._grid.onDrag, this.handleDrag.bind(this)) + .subscribe(this._grid.onDragInit, this.handleDragInit.bind(this)) + .subscribe(this._grid.onDragStart, this.handleDragStart.bind(this)) + .subscribe(this._grid.onDragEnd, this.handleDragEnd.bind(this)) + .subscribe(this._grid.onScroll, this.handleScroll.bind(this)); } destroy() { @@ -110,7 +105,7 @@ export class SlickCellRangeSelector { this._eventHandler?.unsubscribeAll(); emptyElement(this._activeCanvas); emptyElement(this._canvas); - this._decorator?.dispose(); + this._decorator?.destroy(); this.stopIntervalTimer(); } @@ -122,7 +117,7 @@ export class SlickCellRangeSelector { return this._currentlySelectedRange; } - getMouseOffsetViewport(e: SlickEventData, dd: DragPosition): MouseOffsetViewport { + getMouseOffsetViewport(e: MouseEvent | TouchEvent, dd: DragPosition): MouseOffsetViewport { const targetEvent: MouseEvent | Touch = (e as TouchEvent)?.touches?.[0] ?? e; const viewportLeft = this._activeViewport.scrollLeft; const viewportTop = this._activeViewport.scrollTop; @@ -175,14 +170,15 @@ export class SlickCellRangeSelector { // protected functions // --------------------- - protected handleDrag(e: SlickEventData, dd: DragPosition) { + protected handleDrag(evt: SlickEventData, dd: DragPosition) { if (!this._dragging && !this._gridOptions.enableRowMoveManager) { return; } if (!this._gridOptions.enableRowMoveManager) { - e.stopImmediatePropagation(); + evt.stopImmediatePropagation(); } + const e = evt.getNativeEvent(); if (this.addonOptions.autoScroll) { this._draggingMouseOffset = this.getMouseOffsetViewport(e, dd); if (this._draggingMouseOffset.isOutsideViewport) { @@ -293,7 +289,7 @@ export class SlickCellRangeSelector { if (dd?.range) { dd.range.end = end; - const range = new Slick.Range(dd.range.start.row, dd.range.start.cell, end.row, end.cell); + const range = new SlickRange(dd.range.start.row ?? 0, dd.range.start.cell ?? 0, end.row, end.cell); this._decorator.show(range); this.onCellRangeSelecting.notify({ range }); } @@ -308,7 +304,7 @@ export class SlickCellRangeSelector { this.stopIntervalTimer(); this._decorator.hide(); this.onCellRangeSelected.notify({ - range: new Slick.Range(dd.range.start.row, dd.range.start.cell, dd.range.end.row, dd.range.end.cell) + range: new SlickRange(dd.range.start.row ?? 0, dd.range.start.cell ?? 0, dd.range.end.row, dd.range.end.cell) }); } } @@ -364,12 +360,13 @@ export class SlickCellRangeSelector { this._grid.focus(); - let startX = dd.startX - (getHtmlElementOffset(this._canvas)?.left ?? 0); + const canvasOffset = getHtmlElementOffset(this._canvas); + let startX = dd.startX - (canvasOffset?.left ?? 0); if (this._gridOptions.frozenColumn! >= 0 && this._isRightCanvas) { startX += this._scrollLeft; } - let startY = dd.startY - (getHtmlElementOffset(this._canvas)?.top ?? 0); + let startY = dd.startY - (canvasOffset?.top ?? 0); if (this._gridOptions.frozenRow! >= 0 && this._isBottomCanvas) { startY += this._scrollTop; } @@ -377,7 +374,7 @@ export class SlickCellRangeSelector { const start = this._grid.getCellFromPoint(startX, startY); dd.range = { start, end: {} }; this._currentlySelectedRange = dd.range; - return this._decorator.show(new Slick.Range(start.row, start.cell)); + return this._decorator.show(new SlickRange(start.row, start.cell)); } protected handleScroll(_e: DOMMouseOrTouchEvent, args: OnScrollEventArgs) { diff --git a/packages/common/src/extensions/slickCellSelectionModel.ts b/packages/common/src/extensions/slickCellSelectionModel.ts index 96ef8e41d..ebea0b627 100644 --- a/packages/common/src/extensions/slickCellSelectionModel.ts +++ b/packages/common/src/extensions/slickCellSelectionModel.ts @@ -1,32 +1,30 @@ -import type { CellRange, OnActiveCellChangedEventArgs, SlickDataView, SlickEventHandler, SlickGrid, SlickNamespace, SlickRange } from '../interfaces/index'; -import { SlickCellRangeSelector } from './index'; +import { type OnActiveCellChangedEventArgs, type SelectionModel, SlickEvent, SlickEventData, SlickEventHandler, SlickRange } from 'slickgrid'; -// using external SlickGrid JS libraries -declare const Slick: SlickNamespace; +import { KeyCode } from '../enums/index'; +import type { CellRange, SlickGridUniversal, } from '../interfaces/index'; +import { SlickCellRangeSelector } from './index'; export interface CellSelectionModelOption { selectActiveCell?: boolean; cellRangeSelector: SlickCellRangeSelector; } -export class SlickCellSelectionModel { +export class SlickCellSelectionModel implements SelectionModel { + onSelectedRangesChanged = new SlickEvent(); + pluginName: 'CellSelectionModel' = 'CellSelectionModel' as const; + protected _addonOptions?: CellSelectionModelOption; protected _cachedPageRowCount = 0; protected _eventHandler: SlickEventHandler; - protected _dataView?: SlickDataView; - protected _grid!: SlickGrid; - protected _prevSelectedRow?: number; - protected _prevKeyDown = ''; - protected _ranges: CellRange[] = []; + protected _grid!: SlickGridUniversal; + protected _ranges: SlickRange[] = []; protected _selector: SlickCellRangeSelector; protected _defaults = { selectActiveCell: true, }; - onSelectedRangesChanged = new Slick.Event(); - pluginName: 'CellSelectionModel' = 'CellSelectionModel' as const; constructor(options?: { selectActiveCell: boolean; cellRangeSelector: SlickCellRangeSelector; }) { - this._eventHandler = new Slick.EventHandler(); + this._eventHandler = new SlickEventHandler(); if (options === undefined || options.cellRangeSelector === undefined) { this._selector = new SlickCellRangeSelector({ selectionCss: { border: '2px solid black' } as CSSStyleDeclaration }); } else { @@ -47,18 +45,17 @@ export class SlickCellSelectionModel { return this._eventHandler; } - - init(grid: SlickGrid) { + init(grid: SlickGridUniversal) { this._grid = grid; if (this.hasDataView()) { this._dataView = grid?.getData() ?? {} as SlickDataView; } this._addonOptions = { ...this._defaults, ...this._addonOptions } as CellSelectionModelOption; this._eventHandler - .subscribe(this._grid.onActiveCellChanged, this.handleActiveCellChange.bind(this) as EventListener) - .subscribe(this._grid.onKeyDown, this.handleKeyDown.bind(this) as EventListener) - .subscribe(this._selector.onBeforeCellRangeSelected, this.handleBeforeCellRangeSelected.bind(this) as EventListener) - .subscribe(this._selector.onCellRangeSelected, this.handleCellRangeSelected.bind(this) as EventListener); + .subscribe(this._grid.onActiveCellChanged, this.handleActiveCellChange.bind(this)) + .subscribe(this._grid.onKeyDown, this.handleKeyDown.bind(this)) + .subscribe(this._selector.onBeforeCellRangeSelected, this.handleBeforeCellRangeSelected.bind(this)) + .subscribe(this._selector.onCellRangeSelected, this.handleCellRangeSelected.bind(this)); // register the cell range selector plugin grid.registerPlugin(this._selector); @@ -70,15 +67,15 @@ export class SlickCellSelectionModel { dispose() { if (this._selector) { - this._selector.onBeforeCellRangeSelected.unsubscribe(this.handleBeforeCellRangeSelected.bind(this) as EventListener); - this._selector.onCellRangeSelected.unsubscribe(this.handleCellRangeSelected.bind(this) as EventListener); + this._selector.onBeforeCellRangeSelected.unsubscribe(this.handleBeforeCellRangeSelected.bind(this)); + this._selector.onCellRangeSelected.unsubscribe(this.handleCellRangeSelected.bind(this)); } this._eventHandler.unsubscribeAll(); this._grid?.unregisterPlugin(this._selector); this._selector?.dispose(); } - getSelectedRanges(): CellRange[] { + getSelectedRanges(): SlickRange[] { return this._ranges; } @@ -120,7 +117,7 @@ export class SlickCellSelectionModel { this.setSelectedRanges(this.getSelectedRanges()); } - removeInvalidRanges(ranges: CellRange[]) { + removeInvalidRanges(ranges: SlickRange[]) { const result = []; for (let i = 0; i < ranges.length; i++) { const r = ranges[i]; @@ -131,12 +128,7 @@ export class SlickCellSelectionModel { return result; } - /** Provide a way to force a recalculation of page row count (for example on grid resize) */ - resetPageRowCount() { - this._cachedPageRowCount = 0; - } - - setSelectedRanges(ranges: CellRange[], caller = 'SlickCellSelectionModel.setSelectedRanges') { + setSelectedRanges(ranges: SlickRange[], caller = 'SlickCellSelectionModel.setSelectedRanges') { // simple check for: empty selection didn't change, prevent firing onSelectedRangesChanged if ((!this._ranges || this._ranges.length === 0) && (!ranges || ranges.length === 0)) { return; @@ -147,7 +139,7 @@ export class SlickCellSelectionModel { this._ranges = this.removeInvalidRanges(ranges); if (rangeHasChanged) { - const eventData = new Slick.EventData(); + const eventData = new SlickEventData(); Object.defineProperty(eventData, 'detail', { writable: true, configurable: true, value: { caller } }); this.onSelectedRangesChanged.notify(this._ranges, eventData); } @@ -160,7 +152,7 @@ export class SlickCellSelectionModel { protected handleActiveCellChange(_e: Event, args: OnActiveCellChangedEventArgs) { this._prevSelectedRow = undefined; if (this._addonOptions?.selectActiveCell && args.row !== null && args.cell !== null) { - this.setSelectedRanges([new Slick.Range(args.row, args.cell)]); + this.setSelectedRanges([new SlickRange(args.row, args.cell)]); } else if (!this._addonOptions?.selectActiveCell) { // clear the previous selection once the cell changes this.setSelectedRanges([]); @@ -174,9 +166,9 @@ export class SlickCellSelectionModel { } } - protected handleCellRangeSelected(_e: any, args: { range: CellRange; }) { + protected handleCellRangeSelected(_e: any, args: { range: SlickRange; }) { this._grid.setActiveCell(args.range.fromRow, args.range.fromCell, false, false, true); - this.setSelectedRanges([args.range as SlickRange]); + this.setSelectedRanges([args.range]); } protected isKeyAllowed(key: string) { @@ -184,7 +176,7 @@ export class SlickCellSelectionModel { } protected handleKeyDown(e: KeyboardEvent) { - let ranges: CellRange[]; + let ranges: SlickRange[]; let last: SlickRange; const active = this._grid.getActiveCell(); const metaKey = e.ctrlKey || e.metaKey; @@ -199,7 +191,7 @@ export class SlickCellSelectionModel { if (active && e.shiftKey && !metaKey && !e.altKey && this.isKeyAllowed(e.key)) { ranges = this.getSelectedRanges().slice(); if (!ranges.length) { - ranges.push(new Slick.Range(active.row, active.cell)); + ranges.push(new SlickRange(active.row, active.cell)); } // keyboard can work with last range only last = ranges.pop() as SlickRange; @@ -207,7 +199,7 @@ export class SlickCellSelectionModel { if (typeof last?.contains === 'function') { // can't handle selection out of active cell if (!last.contains(active.row, active.cell)) { - last = new Slick.Range(active.row, active.cell); + last = new SlickRange(active.row, active.cell); } let dRow = last.toRow - last.fromRow; let dCell = last.toCell - last.fromCell; @@ -262,7 +254,7 @@ export class SlickCellSelectionModel { } // define new selection range - const newLast = new Slick.Range(active.row, active.cell, toRow, active.cell + dirCell * dCell); + const newLast = new SlickRange(active.row, active.cell, active.row + dirRow * dRow, active.cell + dirCell * dCell); if (this.removeInvalidRanges([newLast]).length) { ranges.push(newLast); const viewRow = dirRow > 0 ? newLast.toRow : newLast.fromRow; diff --git a/packages/common/src/extensions/slickCheckboxSelectColumn.ts b/packages/common/src/extensions/slickCheckboxSelectColumn.ts index cbd0c7c72..0f23bda56 100644 --- a/packages/common/src/extensions/slickCheckboxSelectColumn.ts +++ b/packages/common/src/extensions/slickCheckboxSelectColumn.ts @@ -1,14 +1,12 @@ import type { BasePubSubService } from '@slickgrid-universal/event-pub-sub'; +import { type SelectionModel, type SlickDataView, SlickEventHandler, } from 'slickgrid'; import { KeyCode } from '../enums/keyCode.enum'; -import type { CheckboxSelectorOption, Column, DOMMouseOrTouchEvent, GridOption, SelectableOverrideCallback, SlickDataView, SlickEventData, SlickEventHandler, SlickGrid, SlickNamespace } from '../interfaces/index'; +import type { CheckboxSelectorOption, Column, DOMMouseOrTouchEvent, GridOption, SelectableOverrideCallback, SlickGridUniversal } from '../interfaces/index'; import { SlickRowSelectionModel } from './slickRowSelectionModel'; import { createDomElement, emptyElement } from '../services/domUtilities'; import { BindingEventService } from '../services/bindingEvent.service'; -// using external SlickGrid JS libraries -declare const Slick: SlickNamespace; - export class SlickCheckboxSelectColumn { pluginName: 'CheckboxSelectColumn' = 'CheckboxSelectColumn' as const; protected _defaults = { @@ -28,10 +26,10 @@ export class SlickCheckboxSelectColumn { protected _dataView!: SlickDataView; protected _eventHandler: SlickEventHandler; protected _headerRowNode?: HTMLElement; - protected _grid!: SlickGrid; + protected _grid!: SlickGridUniversal; protected _isSelectAllChecked = false; protected _isUsingDataView = false; - protected _rowSelectionModel?: SlickRowSelectionModel; + protected _rowSelectionModel?: SelectionModel; protected _selectableOverride?: SelectableOverrideCallback | number; protected _selectAll_UID: number; protected _selectedRowsLookup: any = {}; @@ -39,7 +37,7 @@ export class SlickCheckboxSelectColumn { constructor(protected readonly pubSubService: BasePubSubService, options?: CheckboxSelectorOption) { this._selectAll_UID = this.createUID(); this._bindEventService = new BindingEventService(); - this._eventHandler = new Slick.EventHandler(); + this._eventHandler = new SlickEventHandler(); this._addonOptions = { ...this._defaults, ...options } as CheckboxSelectorOption; } @@ -53,7 +51,7 @@ export class SlickCheckboxSelectColumn { /** Getter for the Grid Options pulled through the Grid Object */ get gridOptions(): GridOption { - return this._grid?.getOptions?.() ?? {}; + return this._grid?.getOptions() ?? {}; } get selectAllUid() { @@ -64,11 +62,11 @@ export class SlickCheckboxSelectColumn { this._selectedRowsLookup = selectedRows; } - init(grid: SlickGrid) { + init(grid: SlickGridUniversal) { this._grid = grid; this._isUsingDataView = !Array.isArray(grid.getData()); if (this._isUsingDataView) { - this._dataView = grid.getData(); + this._dataView = grid.getData(); } // we cannot apply "Select All" to all pages when using a Backend Service API (OData, GraphQL, ...) @@ -77,21 +75,21 @@ export class SlickCheckboxSelectColumn { } this._eventHandler - .subscribe(grid.onSelectedRowsChanged, this.handleSelectedRowsChanged.bind(this) as EventListener) - .subscribe(grid.onClick, this.handleClick.bind(this) as EventListener) - .subscribe(grid.onKeyDown, this.handleKeyDown.bind(this) as EventListener); + .subscribe(grid.onSelectedRowsChanged, this.handleSelectedRowsChanged.bind(this)) + .subscribe(grid.onClick, this.handleClick.bind(this)) + .subscribe(grid.onKeyDown, this.handleKeyDown.bind(this)); if (this._isUsingDataView && this._dataView && this._addonOptions.applySelectOnAllPages) { this._eventHandler - .subscribe(this._dataView.onSelectedRowIdsChanged, this.handleDataViewSelectedIdsChanged.bind(this) as EventListener) - .subscribe(this._dataView.onPagingInfoChanged, this.handleDataViewSelectedIdsChanged.bind(this) as EventListener); + .subscribe(this._dataView.onSelectedRowIdsChanged, this.handleDataViewSelectedIdsChanged.bind(this)) + .subscribe(this._dataView.onPagingInfoChanged, this.handleDataViewSelectedIdsChanged.bind(this)); } if (!this._addonOptions.hideInFilterHeaderRow) { this.addCheckboxToFilterHeaderRow(grid); } if (!this._addonOptions.hideInColumnTitleRow) { - this._eventHandler.subscribe(this._grid.onHeaderClick, this.handleHeaderClick.bind(this) as EventListener); + this._eventHandler.subscribe(this._grid.onHeaderClick, this.handleHeaderClick.bind(this)); } // this also requires the Row Selection Model to be registered as well @@ -283,7 +281,7 @@ export class SlickCheckboxSelectColumn { // protected functions // --------------------- - protected addCheckboxToFilterHeaderRow(grid: SlickGrid) { + protected addCheckboxToFilterHeaderRow(grid: SlickGridUniversal) { this._eventHandler.subscribe(grid.onHeaderRowCellRendered, (_e: any, args: any) => { if (args.column.field === (this._addonOptions.field || '_checkbox_selector')) { emptyElement(args.node); @@ -304,7 +302,7 @@ export class SlickCheckboxSelectColumn { }); } - protected checkboxSelectionFormatter(row: number, cell: number, value: any, columnDef: Column, dataContext: any, grid: SlickGrid) { + protected checkboxSelectionFormatter(row: number, cell: number, value: any, columnDef: Column, dataContext: any, grid: SlickGridUniversal) { if (dataContext && this.checkSelectableOverride(row, dataContext, grid)) { const UID = this.createUID() + row; return ``; @@ -312,7 +310,7 @@ export class SlickCheckboxSelectColumn { return null; } - protected checkSelectableOverride(row: number, dataContext: any, grid: SlickGrid) { + protected checkSelectableOverride(row: number, dataContext: any, grid: SlickGridUniversal) { if (typeof this._selectableOverride === 'function') { return this._selectableOverride(row, dataContext, grid); } @@ -367,7 +365,7 @@ export class SlickCheckboxSelectColumn { } } - protected handleClick(e: DOMMouseOrTouchEvent, args: { row: number; cell: number; grid: SlickGrid; }) { + protected handleClick(e: DOMMouseOrTouchEvent, args: { row: number; cell: number; grid: SlickGridUniversal; }) { // clicking on a row select checkbox if (this._grid.getColumns()[args.cell].id === this._addonOptions.columnId && e.target.type === 'checkbox') { e.target.ariaChecked = String(e.target.checked); @@ -385,7 +383,7 @@ export class SlickCheckboxSelectColumn { } } - protected handleHeaderClick(e: DOMMouseOrTouchEvent, args: { column: Column; node: HTMLDivElement; grid: SlickGrid; }) { + protected handleHeaderClick(e: DOMMouseOrTouchEvent, args: { column: Column; node: HTMLDivElement; grid: SlickGridUniversal; }) { if (args.column.id === this._addonOptions.columnId && e.target.type === 'checkbox') { e.target.ariaChecked = String(e.target.checked); @@ -448,7 +446,7 @@ export class SlickCheckboxSelectColumn { } } - protected handleKeyDown(e: SlickEventData, args: any) { + protected handleKeyDown(e: KeyboardEvent, args: any) { if (e.which === KeyCode.SPACE || e.key === ' ') { if (this._grid.getColumns()[args.cell].id === this._addonOptions.columnId) { // if editing, try to commit diff --git a/packages/common/src/extensions/slickColumnPicker.ts b/packages/common/src/extensions/slickColumnPicker.ts index ab4ecf923..8b837d509 100644 --- a/packages/common/src/extensions/slickColumnPicker.ts +++ b/packages/common/src/extensions/slickColumnPicker.ts @@ -1,13 +1,12 @@ import type { BasePubSubService } from '@slickgrid-universal/event-pub-sub'; +import { type OnColumnsChangedArgs, SlickEvent, SlickEventHandler, } from 'slickgrid'; import type { Column, ColumnPickerOption, DOMMouseOrTouchEvent, GridOption, - SlickEventHandler, - SlickGrid, - SlickNamespace, + SlickGridUniversal, } from '../interfaces/index'; import type { ExtensionUtility } from '../extensions/extensionUtility'; import { BindingEventService } from '../services/bindingEvent.service'; @@ -15,9 +14,6 @@ import type { SharedService } from '../services/shared.service'; import { createDomElement, emptyElement, findWidthOrDefault } from '../services/domUtilities'; import { addColumnTitleElementWhenDefined, addCloseButtomElement, handleColumnPickerItemClick, populateColumnPicker, updateColumnPickerOrder } from '../extensions/extensionCommonUtils'; -// using external SlickGrid JS libraries -declare const Slick: SlickNamespace; - /** * A control to add a Column Picker (right+click on any column header to reveal the column picker) * To specify a custom button in a column header, extend the column definition like so: @@ -31,6 +27,8 @@ declare const Slick: SlickNamespace; * @constructor */ export class SlickColumnPicker { + onColumnsChanged = new SlickEvent(); + protected _areVisibleColumnDifferent = false; protected _bindEventService: BindingEventService; protected _columns: Column[] = []; @@ -40,7 +38,6 @@ export class SlickColumnPicker { protected _listElm!: HTMLSpanElement; protected _menuElm: HTMLDivElement | null = null; protected _columnCheckboxes: HTMLInputElement[] = []; - onColumnsChanged = new Slick.Event(); protected _defaults = { // the last 2 checkboxes titles @@ -55,7 +52,7 @@ export class SlickColumnPicker { /** Constructor of the SlickGrid 3rd party plugin, it can optionally receive options */ constructor(protected readonly extensionUtility: ExtensionUtility, protected readonly pubSubService: BasePubSubService, protected readonly sharedService: SharedService) { this._bindEventService = new BindingEventService(); - this._eventHandler = new Slick.EventHandler(); + this._eventHandler = new SlickEventHandler(); this._columns = this.sharedService.allColumns ?? []; this._gridUid = this.grid?.getUID?.() ?? ''; @@ -81,7 +78,7 @@ export class SlickColumnPicker { return this.sharedService.gridOptions ?? {}; } - get grid(): SlickGrid { + get grid(): SlickGridUniversal { return this.sharedService.slickGrid; } @@ -99,8 +96,8 @@ export class SlickColumnPicker { this.addonOptions.forceFitTitle = this.extensionUtility.getPickerTitleOutputString('forceFitTitle', 'columnPicker'); this.addonOptions.syncResizeTitle = this.extensionUtility.getPickerTitleOutputString('syncResizeTitle', 'columnPicker'); - this._eventHandler.subscribe(this.grid.onHeaderContextMenu, this.handleHeaderContextMenu.bind(this) as EventListener); - this._eventHandler.subscribe(this.grid.onColumnsReordered, updateColumnPickerOrder.bind(this) as EventListener); + this._eventHandler.subscribe(this.grid.onHeaderContextMenu, this.handleHeaderContextMenu.bind(this)); + this._eventHandler.subscribe(this.grid.onColumnsReordered, updateColumnPickerOrder.bind(this)); // Hide the menu on outside click. this._bindEventService.bind(document.body, 'mousedown', this.handleBodyMouseDown.bind(this) as EventListener, undefined, 'body'); diff --git a/packages/common/src/extensions/slickDraggableGrouping.ts b/packages/common/src/extensions/slickDraggableGrouping.ts index d15b8ec82..12bac3a5c 100644 --- a/packages/common/src/extensions/slickDraggableGrouping.ts +++ b/packages/common/src/extensions/slickDraggableGrouping.ts @@ -1,6 +1,7 @@ import type { BasePubSubService, EventSubscription } from '@slickgrid-universal/event-pub-sub'; import { isEmptyObject } from '@slickgrid-universal/utils'; import SortableInstance, { type Options as SortableOptions, type SortableEvent } from 'sortablejs'; +import { type SlickDataView, SlickEvent, SlickEventData, SlickEventHandler } from 'slickgrid'; import * as Sortable_ from 'sortablejs'; const Sortable = ((Sortable_ as any)?.['default'] ?? Sortable_); // patch for rollup @@ -14,20 +15,13 @@ import type { GridOption, Grouping, GroupingGetterFunction, - SlickDataView, - SlickEvent, - SlickEventHandler, - SlickGrid, - SlickNamespace, + SlickGridUniversal, } from '../interfaces/index'; import { BindingEventService } from '../services/bindingEvent.service'; import type { SharedService } from '../services/shared.service'; import { createDomElement, emptyElement } from '../services/domUtilities'; import { sortByFieldType } from '../sortComparers'; -// using external SlickGrid JS libraries -declare const Slick: SlickNamespace; - /** * * Draggable Grouping contributed by: Muthukumar Selconstasu @@ -51,13 +45,17 @@ declare const Slick: SlickNamespace; * }]; */ export class SlickDraggableGrouping { + columnsGroupBy: Column[] = []; + onGroupChanged: SlickEvent; + pluginName: 'DraggableGrouping' = 'DraggableGrouping' as const; + protected _addonOptions!: DraggableGrouping; protected _bindingEventService: BindingEventService; protected _droppableInstance?: SortableInstance; protected _dropzoneElm!: HTMLDivElement; protected _dropzonePlaceholderElm!: HTMLDivElement; protected _eventHandler!: SlickEventHandler; - protected _grid?: SlickGrid; + protected _grid?: SlickGridUniversal; protected _gridColumns: Column[] = []; protected _gridUid = ''; protected _groupToggler?: HTMLDivElement; @@ -72,9 +70,6 @@ export class SlickDraggableGrouping { toggleAllButtonText: '', toggleAllPlaceholderText: 'Toggle all Groups', } as DraggableGroupingOption; - columnsGroupBy: Column[] = []; - onGroupChanged: SlickEvent; - pluginName: 'DraggableGrouping' = 'DraggableGrouping' as const; /** Constructor of the SlickGrid 3rd party plugin, it can optionally receive options */ constructor( @@ -83,8 +78,8 @@ export class SlickDraggableGrouping { protected readonly sharedService: SharedService, ) { this._bindingEventService = new BindingEventService(); - this._eventHandler = new Slick.EventHandler(); - this.onGroupChanged = new Slick.Event(); + this._eventHandler = new SlickEventHandler(); + this.onGroupChanged = new SlickEvent<{ caller?: string; groupColumns: Grouping[]; }>(); } get addonOptions(): DraggableGroupingOption { @@ -93,7 +88,7 @@ export class SlickDraggableGrouping { /** Getter of SlickGrid DataView object */ get dataView(): SlickDataView { - return this.grid?.getData?.() ?? {} as SlickDataView; + return this.grid?.getData() ?? {}; } get dropboxElement() { @@ -116,8 +111,8 @@ export class SlickDraggableGrouping { return this._eventHandler; } - get grid(): SlickGrid { - return this._grid ?? this.sharedService.slickGrid ?? {} as SlickGrid; + get grid(): SlickGridUniversal { + return this._grid ?? this.sharedService.slickGrid ?? {}; } get gridOptions(): GridOption { @@ -134,7 +129,7 @@ export class SlickDraggableGrouping { } /** Initialize plugin. */ - init(grid: SlickGrid, groupingOptions?: DraggableGrouping) { + init(grid: SlickGridUniversal, groupingOptions?: DraggableGrouping) { this._addonOptions = { ...this._defaults, ...groupingOptions }; this._grid = grid; if (grid) { @@ -278,7 +273,7 @@ export class SlickDraggableGrouping { * @param uid - grid UID * @param trigger - callback to execute when triggering a column grouping */ - setupColumnReorder(grid: SlickGrid, headers: any, _headerColumnWidthDiff: any, setColumns: (columns: Column[]) => void, setupColumnResize: () => void, _columns: Column[], getColumnIndex: (columnId: string) => number, _uid: string, trigger: (slickEvent: SlickEvent, data?: any) => void) { + setupColumnReorder(grid: SlickGridUniversal, headers: any, _headerColumnWidthDiff: any, setColumns: (columns: Column[]) => void, setupColumnResize: () => void, _columns: Column[], getColumnIndex: (columnId: string) => number, _uid: string, trigger: (slickEvent: SlickEvent, data?: any) => void) { this.destroySortableInstances(); const dropzoneElm = grid.getPreHeaderPanel(); const draggablePlaceholderElm = dropzoneElm.querySelector('.slick-draggable-dropzone-placeholder'); @@ -349,12 +344,12 @@ export class SlickDraggableGrouping { const finalReorderedColumns: Column[] = []; const reorderedColumns = grid.getColumns(); for (const reorderedId of reorderedIds) { - finalReorderedColumns.push(reorderedColumns[getColumnIndex(reorderedId)]); + finalReorderedColumns.push(reorderedColumns[getColumnIndex.call(grid, reorderedId)]); } - setColumns(finalReorderedColumns); - trigger(grid.onColumnsReordered, { grid }); + setColumns.call(grid, finalReorderedColumns); + trigger.call(grid, grid.onColumnsReordered, { grid }); e.stopPropagation(); - setupColumnResize(); + setupColumnResize.call(grid); } } as SortableOptions; @@ -619,7 +614,7 @@ export class SlickDraggableGrouping { /** call notify on slickgrid event and execute onGroupChanged callback when defined as a function by the user */ protected triggerOnGroupChangedEvent(args: { caller?: string; groupColumns: Grouping[]; }) { if (this._addonOptions && typeof this._addonOptions.onGroupChanged === 'function') { - this._addonOptions.onGroupChanged(new Slick.EventData(), args); + this._addonOptions.onGroupChanged(new SlickEventData(), args); } this.onGroupChanged.notify(args); } diff --git a/packages/common/src/extensions/slickGridMenu.ts b/packages/common/src/extensions/slickGridMenu.ts index a0af9bc17..09acc201b 100644 --- a/packages/common/src/extensions/slickGridMenu.ts +++ b/packages/common/src/extensions/slickGridMenu.ts @@ -1,4 +1,5 @@ import type { BasePubSubService } from '@slickgrid-universal/event-pub-sub'; +import { SlickEvent, } from 'slickgrid'; import type { Column, @@ -10,7 +11,8 @@ import type { GridMenuItem, GridMenuOption, GridOption, - SlickNamespace, + MenuCommandItem, + onGridMenuColumnsChangedCallbackArgs, } from '../interfaces/index'; import { DelimiterType, FileType } from '../enums/index'; import type { ExtensionUtility } from '../extensions/extensionUtility'; @@ -23,9 +25,6 @@ import type { TextExportService } from '../services/textExport.service'; import { addColumnTitleElementWhenDefined, addCloseButtomElement, handleColumnPickerItemClick, populateColumnPicker, updateColumnPickerOrder } from '../extensions/extensionCommonUtils'; import { type ExtendableItemTypes, type ExtractMenuType, MenuBaseClass, type MenuType } from '../extensions/menuBaseClass'; -// using external SlickGrid JS libraries -declare const Slick: SlickNamespace; - /** * A control to add a Grid Menu with Extra Commands & Column Picker (hambuger menu on top-right of the grid) * To specify a custom button in a column header, extend the column definition like so: @@ -40,6 +39,12 @@ declare const Slick: SlickNamespace; * @constructor */ export class SlickGridMenu extends MenuBaseClass { + onAfterMenuShow = new SlickEvent(); + onBeforeMenuShow = new SlickEvent(); + onMenuClose = new SlickEvent(); + onCommand = new SlickEvent(); + onColumnsChanged = new SlickEvent(); + protected _areVisibleColumnDifferent = false; protected _columns: Column[] = []; protected _columnCheckboxes: HTMLInputElement[] = []; @@ -87,7 +92,7 @@ export class SlickGridMenu extends MenuBaseClass { this._menuPluginCssPrefix = 'slick-grid-menu'; this._camelPluginName = 'gridMenu'; this._columns = this.sharedService.allColumns ?? []; - this._gridUid = this.grid?.getUID?.() ?? ''; + this._gridUid = this.grid?.getUID() ?? ''; this.initEventHandlers(); this.init(); @@ -105,7 +110,7 @@ export class SlickGridMenu extends MenuBaseClass { } get gridOptions(): GridOption { - return this.grid.getOptions() || {}; + return this.grid?.getOptions() || {}; } get gridUidSelector(): string { diff --git a/packages/common/src/extensions/slickGroupItemMetadataProvider.ts b/packages/common/src/extensions/slickGroupItemMetadataProvider.ts index 569e83ae2..7985613d2 100644 --- a/packages/common/src/extensions/slickGroupItemMetadataProvider.ts +++ b/packages/common/src/extensions/slickGroupItemMetadataProvider.ts @@ -1,21 +1,17 @@ +import { type OnClickEventArgs, type SlickDataView, SlickEventHandler, SlickGroup, Utils as SlickUtils } from 'slickgrid'; + import { KeyCode } from '../enums/keyCode.enum'; import type { Column, DOMEvent, GroupingFormatterItem, GroupItemMetadataProviderOption, - OnClickEventArgs, - SlickDataView, - SlickEventHandler, - SlickGrid, - SlickNamespace, + ItemMetadata, + SlickGridUniversal, } from '../interfaces/index'; -// using external non-typed js libraries -declare const Slick: SlickNamespace; - /** - * Provides item metadata for group (Slick.Group) and totals (Slick.Totals) rows produced by the DataView. + * Provides item metadata for group (SlickGroup) and totals (SlickTotals) rows produced by the DataView. * This metadata overrides the default behavior and formatting of those rows so that they appear and function * correctly when processed by the grid. * @@ -24,9 +20,9 @@ declare const Slick: SlickNamespace; */ export class SlickGroupItemMetadataProvider { protected _eventHandler: SlickEventHandler; - protected _grid!: SlickGrid; + protected _grid!: SlickGridUniversal; protected _options: GroupItemMetadataProviderOption; - protected _defaults = { + protected _defaults: GroupItemMetadataProviderOption = { groupCssClass: 'slick-group', groupTitleCssClass: 'slick-group-title', totalsCssClass: 'slick-group-totals', @@ -40,11 +36,11 @@ export class SlickGroupItemMetadataProvider { groupFormatter: this.defaultGroupCellFormatter.bind(this), totalsFormatter: this.defaultTotalsCellFormatter.bind(this), includeHeaderTotals: false - } as GroupItemMetadataProviderOption; + }; - constructor() { - this._eventHandler = new Slick.EventHandler(); - this._options = this._defaults; + constructor(inputOptions?: GroupItemMetadataProviderOption) { + this._eventHandler = new SlickEventHandler(); + this._options = SlickUtils.extend(true, {}, this._defaults, inputOptions); } /** Getter of the SlickGrid Event Handler */ @@ -54,19 +50,19 @@ export class SlickGroupItemMetadataProvider { /** Getter of SlickGrid DataView object */ protected get dataView(): SlickDataView { - return this._grid?.getData?.() ?? {} as SlickDataView; - } - - get grid(): SlickGrid { - return this._grid; + return this._grid?.getData() ?? {}; } - init(grid: SlickGrid, inputOptions?: GroupItemMetadataProviderOption) { + init(grid: SlickGridUniversal, inputOptions?: GroupItemMetadataProviderOption) { this._grid = grid; this._options = { ...this._defaults, ...inputOptions }; - this._eventHandler.subscribe(grid.onClick, this.handleGridClick.bind(this) as EventListener); - this._eventHandler.subscribe(grid.onKeyDown, this.handleGridKeyDown.bind(this) as EventListener); + this._eventHandler.subscribe(grid.onClick, this.handleGridClick.bind(this)); + this._eventHandler.subscribe(grid.onKeyDown, this.handleGridKeyDown.bind(this)); + } + + destroy() { + this.dispose(); } dispose() { @@ -82,12 +78,12 @@ export class SlickGroupItemMetadataProvider { this._options = { ...this._options, ...inputOptions }; } - getGroupRowMetadata(item: GroupingFormatterItem) { + getGroupRowMetadata(item: GroupingFormatterItem): ItemMetadata { return { selectable: false, focusable: this._options.groupFocusable, cssClasses: `${this._options.groupCssClass} slick-group-level-${item?.level || 0}`, - formatter: this._options.includeHeaderTotals && this._options.totalsFormatter, + formatter: (this._options.includeHeaderTotals && this._options.totalsFormatter) || undefined, columns: { 0: { colspan: this._options.includeHeaderTotals ? '1' : '*', @@ -112,7 +108,7 @@ export class SlickGroupItemMetadataProvider { // protected functions // ------------------- - protected defaultGroupCellFormatter(_row: number, _cell: number, _value: any, _columnDef: Column, item: any) { + protected defaultGroupCellFormatter(_row: number, _cell: number, _value: any, _columnDef: Column, item: any): string { if (!this._options.enableExpandCollapse) { return item.title; } @@ -126,15 +122,15 @@ export class SlickGroupItemMetadataProvider { `${item.title || ''}`; } - protected defaultTotalsCellFormatter(_row: number, _cell: number, _value: any, columnDef: Column, item: any, grid: SlickGrid) { + protected defaultTotalsCellFormatter(_row: number, _cell: number, _value: any, columnDef: Column, item: any, grid: SlickGridUniversal) { return columnDef?.groupTotalsFormatter?.(item, columnDef, grid) ?? ''; } /** Handle a grid cell clicked, it could be a Group that is being collapsed/expanded or do nothing when it's not */ protected handleGridClick(e: DOMEvent, args: OnClickEventArgs) { const target = e.target; - const item = this.grid.getDataItem(args.row); - if (item instanceof Slick.Group && target.classList.contains(this._options.toggleCssClass || '')) { + const item = this._grid.getDataItem(args.row); + if (item instanceof SlickGroup && target.classList.contains(this._options.toggleCssClass || '')) { this.handleDataViewExpandOrCollapse(item); e.stopImmediatePropagation(); e.preventDefault(); @@ -145,12 +141,12 @@ export class SlickGroupItemMetadataProvider { * Handle a keyboard down event on a grouping cell. * TODO: add -/+ handling */ - protected handleGridKeyDown(e: DOMEvent & { keyCode: number; which: number; }) { + protected handleGridKeyDown(e: KeyboardEvent) { if (this._options.enableExpandCollapse && (e.keyCode === KeyCode.SPACE)) { - const activeCell = this.grid.getActiveCell(); + const activeCell = this._grid.getActiveCell(); if (activeCell) { - const item = this.grid.getDataItem(activeCell.row); - if (item instanceof Slick.Group) { + const item = this._grid.getDataItem(activeCell.row); + if (item instanceof SlickGroup) { this.handleDataViewExpandOrCollapse(item); e.stopImmediatePropagation(); e.preventDefault(); @@ -160,7 +156,7 @@ export class SlickGroupItemMetadataProvider { } protected handleDataViewExpandOrCollapse(item: any) { - const range = this.grid.getRenderedRange(); + const range = this._grid.getRenderedRange(); this.dataView.setRefreshHints({ ignoreDiffsBefore: range.top, ignoreDiffsAfter: range.bottom + 1 diff --git a/packages/common/src/extensions/slickHeaderButtons.ts b/packages/common/src/extensions/slickHeaderButtons.ts index 75c83acde..04e9d814b 100644 --- a/packages/common/src/extensions/slickHeaderButtons.ts +++ b/packages/common/src/extensions/slickHeaderButtons.ts @@ -1,4 +1,5 @@ import type { BasePubSubService } from '@slickgrid-universal/event-pub-sub'; +import { type OnHeaderCellRenderedEventArgs, SlickEventHandler } from 'slickgrid'; import type { Column, @@ -8,19 +9,13 @@ import type { HeaderButtonItem, HeaderButtonOnCommandArgs, HeaderButtonOption, - OnHeaderCellRenderedEventArgs, - SlickEventHandler, - SlickGrid, - SlickNamespace, + SlickGridUniversal, } from '../interfaces/index'; import { BindingEventService } from '../services/bindingEvent.service'; import type { ExtensionUtility } from '../extensions/extensionUtility'; import type { SharedService } from '../services/shared.service'; import { type ExtendableItemTypes, type ExtractMenuType, MenuBaseClass, type MenuType } from './menuBaseClass'; -// using external SlickGrid JS libraries -declare const Slick: SlickNamespace; - /** * A plugin to add custom buttons to column headers. * To specify a custom button in a column header, extend the column definition like so: @@ -44,7 +39,7 @@ export class SlickHeaderButtons extends MenuBaseClass { this._menuCssPrefix = 'slick-header-button'; this._camelPluginName = 'headerButtons'; this._bindEventService = new BindingEventService(); - this._eventHandler = new Slick.EventHandler(); + this._eventHandler = new SlickEventHandler(); this.init(sharedService.gridOptions.headerButton); } @@ -59,7 +54,7 @@ export class SlickHeaderButtons extends MenuBaseClass { return this._eventHandler; } - get grid(): SlickGrid { + get grid(): SlickGridUniversal { return this.sharedService.slickGrid; } diff --git a/packages/common/src/extensions/slickHeaderMenu.ts b/packages/common/src/extensions/slickHeaderMenu.ts index 6fff1338e..5df86a47d 100644 --- a/packages/common/src/extensions/slickHeaderMenu.ts +++ b/packages/common/src/extensions/slickHeaderMenu.ts @@ -1,5 +1,6 @@ import type { BasePubSubService } from '@slickgrid-universal/event-pub-sub'; import { arrayRemoveItemByIndex } from '@slickgrid-universal/utils'; +import type { OnHeaderCellRenderedEventArgs, } from 'slickgrid'; import { EmitterType } from '../enums/index'; import type { @@ -15,7 +16,6 @@ import type { MenuCommandItem, MenuCommandItemCallbackArgs, MultiColumnSort, - OnHeaderCellRenderedEventArgs, } from '../interfaces/index'; import { calculateAvailableSpace, createDomElement, getElementOffsetRelativeToParent, getHtmlElementOffset, getTranslationPrefix } from '../services/index'; import type { ExtensionUtility } from '../extensions/extensionUtility'; diff --git a/packages/common/src/extensions/slickRowMoveManager.ts b/packages/common/src/extensions/slickRowMoveManager.ts index b263a8989..29b4e2261 100644 --- a/packages/common/src/extensions/slickRowMoveManager.ts +++ b/packages/common/src/extensions/slickRowMoveManager.ts @@ -1,4 +1,5 @@ import type { BasePubSubService } from '@slickgrid-universal/event-pub-sub'; +import { SlickEvent, type SlickEventData, SlickEventHandler } from 'slickgrid'; import type { UsabilityOverrideFn } from '../enums/usabilityOverrideFn.type'; import type { @@ -8,16 +9,10 @@ import type { GridOption, RowMoveManager, RowMoveManagerOption, - SlickEventData, - SlickEventHandler, - SlickGrid, - SlickNamespace, + SlickGridUniversal, } from '../interfaces/index'; import { createDomElement, findWidthOrDefault, getHtmlElementOffset } from '../services/domUtilities'; -// using external SlickGrid JS libraries -declare const Slick: SlickNamespace; - /** * Row Move Manager options: * cssClass: A CSS class to be added to the menu item container. @@ -30,12 +25,15 @@ declare const Slick: SlickNamespace; * */ export class SlickRowMoveManager { + onBeforeMoveRows = new SlickEvent<{ grid: SlickGridUniversal; rows: number[]; insertBefore: number; }>(); + onMoveRows = new SlickEvent<{ grid: SlickGridUniversal; rows: number[]; insertBefore: number; }>(); + pluginName: 'RowMoveManager' = 'RowMoveManager' as const; + protected _addonOptions!: RowMoveManager; protected _canvas!: HTMLElement; protected _dragging = false; protected _eventHandler: SlickEventHandler; - protected _grid!: SlickGrid; - protected _handler = new Slick.EventHandler(); + protected _grid!: SlickGridUniversal; protected _usabilityOverride?: UsabilityOverrideFn; protected _defaults = { autoScroll: true, @@ -51,17 +49,14 @@ export class SlickRowMoveManager { singleRowMove: false, width: 40, } as RowMoveManagerOption; - onBeforeMoveRows = new Slick.Event<{ grid: SlickGrid; rows: number[]; insertBefore: number; }>(); - onMoveRows = new Slick.Event<{ grid: SlickGrid; rows: number[]; insertBefore: number; }>(); - pluginName: 'RowMoveManager' = 'RowMoveManager' as const; /** Constructor of the SlickGrid 3rd party plugin, it can optionally receive options */ constructor(protected readonly pubSubService: BasePubSubService) { - this._eventHandler = new Slick.EventHandler(); + this._eventHandler = new SlickEventHandler(); } get addonOptions(): RowMoveManagerOption { - return this._addonOptions as RowMoveManagerOption; + return this._addonOptions; } get eventHandler(): SlickEventHandler { @@ -70,11 +65,11 @@ export class SlickRowMoveManager { /** Getter for the Grid Options pulled through the Grid Object */ get gridOptions(): GridOption { - return this._grid?.getOptions?.() ?? {}; + return this._grid?.getOptions() ?? {}; } /** Initialize plugin. */ - init(grid: SlickGrid, options?: RowMoveManager) { + init(grid: SlickGridUniversal, options?: RowMoveManager) { this._addonOptions = { ...this._defaults, ...options }; this._grid = grid; this._canvas = this._grid.getCanvasNode(); @@ -193,9 +188,10 @@ export class SlickRowMoveManager { } } - protected handleDrag(e: SlickEventData, dd: DragRowMove): boolean | void { + protected handleDrag(evt: SlickEventData, dd: DragRowMove): boolean | void { if (this._dragging) { - e.stopImmediatePropagation(); + evt.stopImmediatePropagation(); + const e = evt.getNativeEvent(); const targetEvent: MouseEvent | Touch = (e as TouchEvent)?.touches?.[0] ?? e; const top = targetEvent.pageY - (getHtmlElementOffset(this._canvas)?.top ?? 0); @@ -309,14 +305,14 @@ export class SlickRowMoveManager { } } - protected checkUsabilityOverride(row: number, dataContext: any, grid: SlickGrid) { + protected checkUsabilityOverride(row: number, dataContext: any, grid: SlickGridUniversal) { if (typeof this._usabilityOverride === 'function') { return this._usabilityOverride(row, dataContext, grid); } return true; } - protected moveIconFormatter(row: number, cell: number, value: any, column: Column, dataContext: any, grid: SlickGrid): FormatterResultObject | string { + protected moveIconFormatter(row: number, cell: number, value: any, column: Column, dataContext: any, grid: SlickGridUniversal): FormatterResultObject | string { if (!this.checkUsabilityOverride(row, dataContext, grid)) { return ''; } else { diff --git a/packages/common/src/extensions/slickRowSelectionModel.ts b/packages/common/src/extensions/slickRowSelectionModel.ts index 1e52301c2..99db633b6 100644 --- a/packages/common/src/extensions/slickRowSelectionModel.ts +++ b/packages/common/src/extensions/slickRowSelectionModel.ts @@ -1,24 +1,20 @@ +import { type OnActiveCellChangedEventArgs, type SelectionModel, SlickEvent, SlickEventData, SlickEventHandler, SlickRange, } from 'slickgrid'; + import { KeyCode } from '../enums/index'; -import type { - CellRange, - GridOption, - OnActiveCellChangedEventArgs, - RowSelectionModelOption, - SlickEventData, - SlickEventHandler, - SlickGrid, - SlickNamespace, -} from '../interfaces/index'; +import type { CellRange, GridOption, RowSelectionModelOption, SlickGridUniversal, } from '../interfaces/index'; import { SlickCellRangeSelector } from '../extensions/slickCellRangeSelector'; -// using external SlickGrid JS libraries -declare const Slick: SlickNamespace; +export class SlickRowSelectionModel implements SelectionModel { + pluginName: 'RowSelectionModel' = 'RowSelectionModel' as const; + + /** triggered when selected ranges changes */ + onSelectedRangesChanged = new SlickEvent(); -export class SlickRowSelectionModel { - protected _addonOptions: RowSelectionModelOption; + protected _options: RowSelectionModelOption; protected _eventHandler: SlickEventHandler; - protected _grid!: SlickGrid; - protected _ranges: CellRange[] = []; + protected _inHandler = false; + protected _grid!: SlickGridUniversal; + protected _ranges: SlickRange[] = []; protected _selector?: SlickCellRangeSelector; protected _defaults = { autoScrollWhenDrag: true, @@ -26,18 +22,14 @@ export class SlickRowSelectionModel { dragToSelect: false, selectActiveRow: true } as RowSelectionModelOption; - pluginName: 'RowSelectionModel' = 'RowSelectionModel' as const; - - /** triggered when selected ranges changes */ - onSelectedRangesChanged = new Slick.Event(); constructor(options?: RowSelectionModelOption) { - this._eventHandler = new Slick.EventHandler(); - this._addonOptions = { ...this._defaults, ...options }; + this._eventHandler = new SlickEventHandler(); + this._options = { ...this._defaults, ...options }; } get addonOptions() { - return this._addonOptions; + return this._options; } get eventHandler(): SlickEventHandler { @@ -45,18 +37,18 @@ export class SlickRowSelectionModel { } get gridOptions(): GridOption { - return this._grid.getOptions(); + return this._grid?.getOptions(); } - init(grid: SlickGrid) { + init(grid: SlickGridUniversal) { this._grid = grid; - this._addonOptions = { ...this._defaults, ...this._addonOptions }; + this._options = { ...this._defaults, ...this._options }; this._selector = this.addonOptions.cellRangeSelector; - if (!this._selector && this._addonOptions.dragToSelect) { + if (!this._selector && this._options.dragToSelect) { this._selector = new SlickCellRangeSelector({ selectionCss: { border: 'none' } as CSSStyleDeclaration, - autoScroll: this._addonOptions.autoScrollWhenDrag + autoScroll: this._options.autoScrollWhenDrag }); this.addonOptions.cellRangeSelector = this._selector; } @@ -68,9 +60,9 @@ export class SlickRowSelectionModel { if (this._selector) { this._grid.registerPlugin(this._selector); - this._selector.onCellRangeSelecting.subscribe(this.handleCellRangeSelected.bind(this) as EventListener); - this._selector.onCellRangeSelected.subscribe(this.handleCellRangeSelected.bind(this) as EventListener); - this._selector.onBeforeCellRangeSelected.subscribe(this.handleBeforeCellRangeSelected.bind(this) as EventListener); + this._selector.onCellRangeSelecting.subscribe(this.handleCellRangeSelected.bind(this)); + this._selector.onCellRangeSelected.subscribe(this.handleCellRangeSelected.bind(this)); + this._selector.onBeforeCellRangeSelected.subscribe(this.handleBeforeCellRangeSelected.bind(this)); } } @@ -85,9 +77,9 @@ export class SlickRowSelectionModel { disposeSelector() { if (this._selector) { - this._selector.onCellRangeSelecting.unsubscribe(this.handleCellRangeSelected.bind(this) as EventListener); - this._selector.onCellRangeSelected.unsubscribe(this.handleCellRangeSelected.bind(this) as EventListener); - this._selector.onBeforeCellRangeSelected.unsubscribe(this.handleBeforeCellRangeSelected.bind(this) as EventListener); + this._selector.onCellRangeSelecting.unsubscribe(this.handleCellRangeSelected.bind(this)); + this._selector.onCellRangeSelected.unsubscribe(this.handleCellRangeSelected.bind(this)); + this._selector.onBeforeCellRangeSelected.unsubscribe(this.handleBeforeCellRangeSelected.bind(this)); this._grid.unregisterPlugin(this._selector); this._selector?.destroy(); this._selector?.dispose(); @@ -114,13 +106,13 @@ export class SlickRowSelectionModel { this.setSelectedRanges(this.rowsToRanges(rows), 'SlickRowSelectionModel.setSelectedRows'); } - setSelectedRanges(ranges: CellRange[], caller = 'SlickRowSelectionModel.setSelectedRanges') { + setSelectedRanges(ranges: SlickRange[], caller = 'SlickRowSelectionModel.setSelectedRanges') { // simple check for: empty selection didn't change, prevent firing onSelectedRangesChanged if ((!this._ranges || this._ranges.length === 0) && (!ranges || ranges.length === 0)) { return; } this._ranges = ranges; - const eventData = new Slick.EventData(); + const eventData = new SlickEventData(); Object.defineProperty(eventData, 'detail', { writable: true, configurable: true, value: { caller } }); this.onSelectedRangesChanged.notify(this._ranges, eventData); } @@ -157,12 +149,12 @@ export class SlickRowSelectionModel { if (!this.gridOptions.multiSelect || !this.addonOptions.selectActiveRow) { return false; } - this.setSelectedRanges([new Slick.Range(args.range.fromRow, 0, args.range.toRow, this._grid.getColumns().length - 1)]); + this.setSelectedRanges([new SlickRange(args.range.fromRow, 0, args.range.toRow, this._grid.getColumns().length - 1)]); } protected handleActiveCellChange(_e: SlickEventData, args: OnActiveCellChangedEventArgs) { - if (this._addonOptions.selectActiveRow && args.row !== null) { - this.setSelectedRanges([new Slick.Range(args.row, 0, args.row, this._grid.getColumns().length - 1)]); + if (this._options.selectActiveRow && args.row !== null) { + this.setSelectedRanges([new SlickRange(args.row, 0, args.row, this._grid.getColumns().length - 1)]); } } @@ -207,7 +199,7 @@ export class SlickRowSelectionModel { return true; } - protected handleKeyDown(e: SlickEventData) { + protected handleKeyDown(e: KeyboardEvent) { const activeRow = this._grid.getActiveCell(); if (this.gridOptions.multiSelect && activeRow && @@ -262,7 +254,7 @@ export class SlickRowSelectionModel { const ranges = []; const lastCell = this._grid.getColumns().length - 1; for (const row of rows) { - ranges.push(new Slick.Range(row, 0, row, lastCell)); + ranges.push(new SlickRange(row, 0, row, lastCell)); } return ranges; } diff --git a/packages/common/src/filters/__tests__/autocompleterFilter.spec.ts b/packages/common/src/filters/__tests__/autocompleterFilter.spec.ts index 206cba6b5..e813b82d5 100644 --- a/packages/common/src/filters/__tests__/autocompleterFilter.spec.ts +++ b/packages/common/src/filters/__tests__/autocompleterFilter.spec.ts @@ -3,7 +3,7 @@ import { of, Subject } from 'rxjs'; import { Filters } from '../index'; import { AutocompleterFilter } from '../autocompleterFilter'; import { FieldType, OperatorType, KeyCode } from '../../enums/index'; -import { AutocompleterOption, Column, ColumnFilter, FilterArguments, GridOption, SlickGrid } from '../../interfaces/index'; +import { AutocompleterOption, Column, ColumnFilter, FilterArguments, GridOption, type SlickGridUniversal } from '../../interfaces/index'; import { CollectionService } from '../../services/collection.service'; import { HttpStub } from '../../../../../test/httpClientStub'; import { RxJsResourceStub } from '../../../../../test/rxjsResourceStub'; @@ -26,7 +26,7 @@ const gridStub = { getColumns: jest.fn(), getHeaderRowColumn: jest.fn(), render: jest.fn(), -} as unknown as SlickGrid; +} as unknown as SlickGridUniversal; describe('AutocompleterFilter', () => { let translaterService: TranslateServiceStub; diff --git a/packages/common/src/filters/__tests__/compoundDateFilter.spec.ts b/packages/common/src/filters/__tests__/compoundDateFilter.spec.ts index fd8a13e7b..ac58a41c7 100644 --- a/packages/common/src/filters/__tests__/compoundDateFilter.spec.ts +++ b/packages/common/src/filters/__tests__/compoundDateFilter.spec.ts @@ -24,7 +24,7 @@ const gridStub = { getColumns: jest.fn(), getHeaderRowColumn: jest.fn(), render: jest.fn(), -} as unknown as SlickGrid; +} as unknown as SlickGridUniversal; describe('CompoundDateFilter', () => { let divContainer: HTMLDivElement; diff --git a/packages/common/src/filters/__tests__/compoundInputFilter.spec.ts b/packages/common/src/filters/__tests__/compoundInputFilter.spec.ts index 80d8b7f2b..b4dde5a04 100644 --- a/packages/common/src/filters/__tests__/compoundInputFilter.spec.ts +++ b/packages/common/src/filters/__tests__/compoundInputFilter.spec.ts @@ -22,7 +22,7 @@ const gridStub = { getColumns: jest.fn(), getHeaderRowColumn: jest.fn(), render: jest.fn(), -} as unknown as SlickGrid; +} as unknown as SlickGridUniversal; describe('CompoundInputFilter', () => { let translateService: TranslateServiceStub; diff --git a/packages/common/src/filters/__tests__/compoundInputNumberFilter.spec.ts b/packages/common/src/filters/__tests__/compoundInputNumberFilter.spec.ts index 0d7f80693..f3ff2cf90 100644 --- a/packages/common/src/filters/__tests__/compoundInputNumberFilter.spec.ts +++ b/packages/common/src/filters/__tests__/compoundInputNumberFilter.spec.ts @@ -18,7 +18,7 @@ const gridStub = { getColumns: jest.fn(), getHeaderRowColumn: jest.fn(), render: jest.fn(), -} as unknown as SlickGrid; +} as unknown as SlickGridUniversal; describe('CompoundInputNumberFilter', () => { let translateService: TranslateServiceStub; diff --git a/packages/common/src/filters/__tests__/compoundInputPasswordFilter.spec.ts b/packages/common/src/filters/__tests__/compoundInputPasswordFilter.spec.ts index 021c1fcbd..0bf6ae2f4 100644 --- a/packages/common/src/filters/__tests__/compoundInputPasswordFilter.spec.ts +++ b/packages/common/src/filters/__tests__/compoundInputPasswordFilter.spec.ts @@ -18,7 +18,7 @@ const gridStub = { getColumns: jest.fn(), getHeaderRowColumn: jest.fn(), render: jest.fn(), -} as unknown as SlickGrid; +} as unknown as SlickGridUniversal; describe('CompoundInputPasswordFilter', () => { let translateService: TranslateServiceStub; diff --git a/packages/common/src/filters/__tests__/compoundSliderFilter.spec.ts b/packages/common/src/filters/__tests__/compoundSliderFilter.spec.ts index d396614eb..f0a48e855 100644 --- a/packages/common/src/filters/__tests__/compoundSliderFilter.spec.ts +++ b/packages/common/src/filters/__tests__/compoundSliderFilter.spec.ts @@ -1,11 +1,12 @@ +import { SlickEvent } from 'slickgrid'; + import { FieldType, OperatorType } from '../../enums/index'; -import { Column, FilterArguments, GridOption, SlickGrid, SlickNamespace } from '../../interfaces/index'; +import { Column, FilterArguments, GridOption, type SlickGridUniversal } from '../../interfaces/index'; import { Filters } from '../index'; import { CompoundSliderFilter } from '../compoundSliderFilter'; import { TranslateServiceStub } from '../../../../../test/translateServiceStub'; const containerId = 'demo-container'; -declare const Slick: SlickNamespace; jest.useFakeTimers(); // define a
    container to simulate the grid container @@ -25,9 +26,9 @@ const gridStub = { getColumns: jest.fn(), getHeaderRowColumn: jest.fn(), render: jest.fn(), - onHeaderMouseLeave: new Slick.Event(), - onHeaderRowMouseEnter: new Slick.Event(), -} as unknown as SlickGrid; + onHeaderMouseLeave: new SlickEvent(), + onHeaderRowMouseEnter: new SlickEvent(), +} as unknown as SlickGridUniversal; describe('CompoundSliderFilter', () => { let translateService: TranslateServiceStub; diff --git a/packages/common/src/filters/__tests__/dateRangeFilter.spec.ts b/packages/common/src/filters/__tests__/dateRangeFilter.spec.ts index a496b442f..f229c288b 100644 --- a/packages/common/src/filters/__tests__/dateRangeFilter.spec.ts +++ b/packages/common/src/filters/__tests__/dateRangeFilter.spec.ts @@ -20,7 +20,7 @@ const gridStub = { getColumns: jest.fn(), getHeaderRowColumn: jest.fn(), render: jest.fn(), -} as unknown as SlickGrid; +} as unknown as SlickGridUniversal; describe('DateRangeFilter', () => { let divContainer: HTMLDivElement; diff --git a/packages/common/src/filters/__tests__/inputFilter.spec.ts b/packages/common/src/filters/__tests__/inputFilter.spec.ts index 246751e40..b0b169a3f 100644 --- a/packages/common/src/filters/__tests__/inputFilter.spec.ts +++ b/packages/common/src/filters/__tests__/inputFilter.spec.ts @@ -17,7 +17,7 @@ const gridStub = { getColumns: jest.fn(), getHeaderRowColumn: jest.fn(), render: jest.fn(), -} as unknown as SlickGrid; +} as unknown as SlickGridUniversal; describe('InputFilter', () => { let divContainer: HTMLDivElement; diff --git a/packages/common/src/filters/__tests__/inputMaskFilter.spec.ts b/packages/common/src/filters/__tests__/inputMaskFilter.spec.ts index e618d45aa..2080e72c5 100644 --- a/packages/common/src/filters/__tests__/inputMaskFilter.spec.ts +++ b/packages/common/src/filters/__tests__/inputMaskFilter.spec.ts @@ -16,7 +16,7 @@ const gridStub = { getColumns: jest.fn(), getHeaderRowColumn: jest.fn(), render: jest.fn(), -} as unknown as SlickGrid; +} as unknown as SlickGridUniversal; describe('InputMaskFilter', () => { let divContainer: HTMLDivElement; diff --git a/packages/common/src/filters/__tests__/inputNumberFilter.spec.ts b/packages/common/src/filters/__tests__/inputNumberFilter.spec.ts index c9b01443b..c9a1f295f 100644 --- a/packages/common/src/filters/__tests__/inputNumberFilter.spec.ts +++ b/packages/common/src/filters/__tests__/inputNumberFilter.spec.ts @@ -17,7 +17,7 @@ const gridStub = { getColumns: jest.fn(), getHeaderRowColumn: jest.fn(), render: jest.fn(), -} as unknown as SlickGrid; +} as unknown as SlickGridUniversal; describe('InputNumberFilter', () => { let divContainer: HTMLDivElement; diff --git a/packages/common/src/filters/__tests__/inputPasswordFilter.spec.ts b/packages/common/src/filters/__tests__/inputPasswordFilter.spec.ts index ac3e7d0be..1214240cd 100644 --- a/packages/common/src/filters/__tests__/inputPasswordFilter.spec.ts +++ b/packages/common/src/filters/__tests__/inputPasswordFilter.spec.ts @@ -17,7 +17,7 @@ const gridStub = { getColumns: jest.fn(), getHeaderRowColumn: jest.fn(), render: jest.fn(), -} as unknown as SlickGrid; +} as unknown as SlickGridUniversal; describe('InputPasswordFilter', () => { let divContainer: HTMLDivElement; diff --git a/packages/common/src/filters/__tests__/multipleSelectFilter.spec.ts b/packages/common/src/filters/__tests__/multipleSelectFilter.spec.ts index 2d92bae5d..e3fff8d44 100644 --- a/packages/common/src/filters/__tests__/multipleSelectFilter.spec.ts +++ b/packages/common/src/filters/__tests__/multipleSelectFilter.spec.ts @@ -22,7 +22,7 @@ const gridStub = { getColumns: jest.fn(), getHeaderRowColumn: jest.fn(), render: jest.fn(), -} as unknown as SlickGrid; +} as unknown as SlickGridUniversal; describe('SelectFilter', () => { let translateService: TranslateServiceStub; diff --git a/packages/common/src/filters/__tests__/nativeSelectFilter.spec.ts b/packages/common/src/filters/__tests__/nativeSelectFilter.spec.ts index 145058bce..e92da5c6a 100644 --- a/packages/common/src/filters/__tests__/nativeSelectFilter.spec.ts +++ b/packages/common/src/filters/__tests__/nativeSelectFilter.spec.ts @@ -20,7 +20,7 @@ const gridStub = { getColumns: jest.fn(), getHeaderRowColumn: jest.fn(), render: jest.fn(), -} as unknown as SlickGrid; +} as unknown as SlickGridUniversal; describe('NativeSelectFilter', () => { let translateService: TranslateServiceStub; diff --git a/packages/common/src/filters/__tests__/selectFilter.spec.ts b/packages/common/src/filters/__tests__/selectFilter.spec.ts index addc987b9..e67244e1f 100644 --- a/packages/common/src/filters/__tests__/selectFilter.spec.ts +++ b/packages/common/src/filters/__tests__/selectFilter.spec.ts @@ -28,7 +28,7 @@ const gridStub = { getColumns: jest.fn(), getHeaderRowColumn: jest.fn(), render: jest.fn(), -} as unknown as SlickGrid; +} as unknown as SlickGridUniversal; describe('SelectFilter', () => { let translateService: TranslateServiceStub; diff --git a/packages/common/src/filters/__tests__/singleSelectFilter.spec.ts b/packages/common/src/filters/__tests__/singleSelectFilter.spec.ts index e0771e58e..bd53a44b7 100644 --- a/packages/common/src/filters/__tests__/singleSelectFilter.spec.ts +++ b/packages/common/src/filters/__tests__/singleSelectFilter.spec.ts @@ -24,7 +24,7 @@ const gridStub = { getColumns: jest.fn(), getHeaderRowColumn: jest.fn(), render: jest.fn(), -} as unknown as SlickGrid; +} as unknown as SlickGridUniversal; describe('SelectFilter', () => { let translateService: TranslateServiceStub; diff --git a/packages/common/src/filters/__tests__/singleSliderFilter.spec.ts b/packages/common/src/filters/__tests__/singleSliderFilter.spec.ts index e3e977958..b03c57d37 100644 --- a/packages/common/src/filters/__tests__/singleSliderFilter.spec.ts +++ b/packages/common/src/filters/__tests__/singleSliderFilter.spec.ts @@ -1,10 +1,11 @@ +import { SlickEvent } from 'slickgrid'; + import { Filters } from '../filters.index'; -import { Column, FilterArguments, GridOption, SlickGrid, SlickNamespace } from '../../interfaces/index'; +import { Column, FilterArguments, GridOption, type SlickGridUniversal } from '../../interfaces/index'; import { SingleSliderFilter } from '../singleSliderFilter'; import { TranslateServiceStub } from '../../../../../test/translateServiceStub'; const containerId = 'demo-container'; -declare const Slick: SlickNamespace; jest.useFakeTimers(); // define a
    container to simulate the grid container @@ -20,9 +21,9 @@ const gridStub = { getColumns: jest.fn(), getHeaderRowColumn: jest.fn(), render: jest.fn(), - onHeaderMouseLeave: new Slick.Event(), - onHeaderRowMouseEnter: new Slick.Event(), -} as unknown as SlickGrid; + onHeaderMouseLeave: new SlickEvent(), + onHeaderRowMouseEnter: new SlickEvent(), +} as unknown as SlickGridUniversal; describe('SingleSliderFilter', () => { let translateService: TranslateServiceStub; diff --git a/packages/common/src/filters/__tests__/sliderRangeFilter.spec.ts b/packages/common/src/filters/__tests__/sliderRangeFilter.spec.ts index a163657b1..16370884e 100644 --- a/packages/common/src/filters/__tests__/sliderRangeFilter.spec.ts +++ b/packages/common/src/filters/__tests__/sliderRangeFilter.spec.ts @@ -1,10 +1,11 @@ +import { SlickEvent } from 'slickgrid'; + import { Filters } from '../filters.index'; -import { Column, FilterArguments, GridOption, SlickGrid, SlickNamespace } from '../../interfaces/index'; +import { Column, FilterArguments, GridOption , type SlickGridUniversal } from '../../interfaces/index'; import { SliderRangeFilter } from '../sliderRangeFilter'; import { TranslateServiceStub } from '../../../../../test/translateServiceStub'; const containerId = 'demo-container'; -declare const Slick: SlickNamespace; jest.useFakeTimers(); // define a
    container to simulate the grid container @@ -20,9 +21,9 @@ const gridStub = { getColumns: jest.fn(), getHeaderRowColumn: jest.fn(), render: jest.fn(), - onHeaderMouseLeave: new Slick.Event(), - onHeaderRowMouseEnter: new Slick.Event(), -} as unknown as SlickGrid; + onHeaderMouseLeave: new SlickEvent(), + onHeaderRowMouseEnter: new SlickEvent(), +} as unknown as SlickGridUniversal; describe('SliderRangeFilter', () => { let translateService: TranslateServiceStub; diff --git a/packages/common/src/filters/autocompleterFilter.ts b/packages/common/src/filters/autocompleterFilter.ts index a95ac980a..54f822c3c 100644 --- a/packages/common/src/filters/autocompleterFilter.ts +++ b/packages/common/src/filters/autocompleterFilter.ts @@ -24,7 +24,7 @@ import type { FilterCallbackArg, GridOption, Locale, - SlickGrid, + SlickGridUniversal, } from '../interfaces/index'; import { addAutocompleteLoadingByOverridingFetch } from '../commonEditorFilter'; import { createDomElement, emptyElement, } from '../services'; @@ -51,7 +51,7 @@ export class AutocompleterFilter implements Fi /** DOM Element Name, useful for auto-detecting positioning (dropup / dropdown) */ elementName!: string; - grid!: SlickGrid; + grid!: SlickGridUniversal; searchTerms: SearchTerm[] = []; columnDef!: Column; callback!: FilterCallback; @@ -137,7 +137,7 @@ export class AutocompleterFilter implements Fi /** Getter for the Grid Options pulled through the Grid Object */ get gridOptions(): GridOption { - return (this.grid && this.grid.getOptions) ? this.grid.getOptions() : {}; + return this.grid?.getOptions() ?? {}; } /** Kraaden AutoComplete instance */ diff --git a/packages/common/src/filters/dateFilter.ts b/packages/common/src/filters/dateFilter.ts index 333f94c3f..3c49b0b54 100644 --- a/packages/common/src/filters/dateFilter.ts +++ b/packages/common/src/filters/dateFilter.ts @@ -20,7 +20,7 @@ import type { FlatpickrOption, GridOption, OperatorDetail, - SlickGrid, + SlickGridUniversal, } from '../interfaces/index'; import { buildSelectOperator, compoundOperatorNumeric } from './filterUtilities'; import { createDomElement, destroyObjectDomElementProps, emptyElement, } from '../services/domUtilities'; @@ -42,7 +42,7 @@ export class DateFilter implements Filter { protected _shouldTriggerQuery = true; inputFilterType: 'compound' | 'range' = 'range'; flatInstance!: FlatpickrInstance; - grid!: SlickGrid; + grid!: SlickGridUniversal; searchTerms: SearchTerm[] = []; columnDef!: Column; callback!: FilterCallback; @@ -54,12 +54,12 @@ export class DateFilter implements Filter { /** Getter for the Grid Options pulled through the Grid Object */ protected get gridOptions(): GridOption { - return (this.grid && this.grid.getOptions) ? this.grid.getOptions() : {}; + return this.grid?.getOptions() ?? {}; } /** Getter for the Column Filter */ get columnFilter(): ColumnFilter { - return this.columnDef && this.columnDef.filter || {}; + return this.columnDef?.filter || {} as ColumnFilter; } /** Getter for the Current Date(s) selected */ diff --git a/packages/common/src/filters/inputFilter.ts b/packages/common/src/filters/inputFilter.ts index d13a4eaaa..6d870cd4d 100644 --- a/packages/common/src/filters/inputFilter.ts +++ b/packages/common/src/filters/inputFilter.ts @@ -8,7 +8,7 @@ import type { FilterCallback, GridOption, OperatorDetail, - SlickGrid, + SlickGridUniversal, } from '../interfaces/index'; import { FieldType, OperatorType, type OperatorString, type SearchTerm } from '../enums/index'; import { BindingEventService } from '../services/bindingEvent.service'; @@ -27,7 +27,7 @@ export class InputFilter implements Filter { protected _filterInputElm!: HTMLInputElement; protected _selectOperatorElm?: HTMLSelectElement; inputFilterType: 'single' | 'compound' = 'single'; - grid!: SlickGrid; + grid!: SlickGridUniversal; searchTerms: SearchTerm[] = []; columnDef!: Column; callback!: FilterCallback; diff --git a/packages/common/src/filters/nativeSelectFilter.ts b/packages/common/src/filters/nativeSelectFilter.ts index 137fd6cf7..c2e5995e9 100644 --- a/packages/common/src/filters/nativeSelectFilter.ts +++ b/packages/common/src/filters/nativeSelectFilter.ts @@ -7,7 +7,7 @@ import type { FilterArguments, FilterCallback, GridOption, - SlickGrid, + SlickGridUniversal, } from '../interfaces/index'; import { OperatorType, type OperatorString, type SearchTerm } from '../enums/index'; import { createDomElement, emptyElement, } from '../services/domUtilities'; @@ -20,7 +20,7 @@ export class NativeSelectFilter implements Filter { protected _shouldTriggerQuery = true; protected _currentValues: any | any[] = []; filterElm!: HTMLSelectElement; - grid!: SlickGrid; + grid!: SlickGridUniversal; searchTerms: SearchTerm[] = []; columnDef!: Column; callback!: FilterCallback; @@ -42,7 +42,7 @@ export class NativeSelectFilter implements Filter { /** Getter for the Grid Options pulled through the Grid Object */ protected get gridOptions(): GridOption { - return (this.grid && this.grid.getOptions) ? this.grid.getOptions() : {}; + return this.grid?.getOptions() ?? {}; } /** Getter for the current Operator */ diff --git a/packages/common/src/filters/selectFilter.ts b/packages/common/src/filters/selectFilter.ts index 8398b2026..b625da598 100644 --- a/packages/common/src/filters/selectFilter.ts +++ b/packages/common/src/filters/selectFilter.ts @@ -13,7 +13,7 @@ import type { FilterCallback, GridOption, Locale, - SlickGrid, + SlickGridUniversal, } from './../interfaces/index'; import type { CollectionService } from '../services/collection.service'; import { collectionObserver, propertyObserver } from '../services/observers'; @@ -37,7 +37,7 @@ export class SelectFilter implements Filter { /** The DOM element */ filterElm?: HTMLElement; - grid!: SlickGrid; + grid!: SlickGridUniversal; searchTerms: SearchTerm[] | undefined; columnDef!: Column; callback!: FilterCallback; diff --git a/packages/common/src/filters/sliderFilter.ts b/packages/common/src/filters/sliderFilter.ts index 40c52debd..5bc3a6597 100644 --- a/packages/common/src/filters/sliderFilter.ts +++ b/packages/common/src/filters/sliderFilter.ts @@ -1,4 +1,5 @@ import { hasData, toSentenceCase } from '@slickgrid-universal/utils'; +import { SlickEventData, } from 'slickgrid'; import { Constants } from '../constants'; import { type OperatorString, OperatorType, type SearchTerm, } from '../enums/index'; @@ -11,8 +12,7 @@ import type { FilterCallback, GridOption, OperatorDetail, - SlickGrid, - SlickNamespace, + SlickGridUniversal, SliderOption, SliderRangeOption, SliderType, @@ -23,7 +23,6 @@ import type { TranslaterService } from '../services/translater.service'; import { mapOperatorToShorthandDesignation } from '../services/utilities'; import { buildSelectOperator, compoundOperatorNumeric, getFilterOptionByName } from './filterUtilities'; -declare const Slick: SlickNamespace; const DEFAULT_SLIDER_TRACK_FILLED_COLOR = '#86bff8'; const GAP_BETWEEN_SLIDER_HANDLES = 0; const Z_INDEX_MIN_GAP = 20; // gap in Px before we change z-index so that lowest/highest handle doesn't block each other @@ -50,7 +49,7 @@ export class SliderFilter implements Filter { protected _sliderRightInputElm?: HTMLInputElement; protected _sliderTrackFilledColor = DEFAULT_SLIDER_TRACK_FILLED_COLOR; sliderType: SliderType = 'double'; - grid!: SlickGrid; + grid!: SlickGridUniversal; searchTerms: SearchTerm[] = []; columnDef!: Column; callback!: FilterCallback; @@ -421,7 +420,7 @@ export class SliderFilter implements Filter { // the minimum requirements for tooltip to work are the columnDef and targetElement this.grid.onHeaderRowMouseEnter.notify( { column: this.columnDef, grid: this.grid }, - { ...new Slick.EventData(), target: this._argFilterContainerElm } + { ...new SlickEventData(), ...{ target: this._argFilterContainerElm } as unknown as Event } ); } @@ -484,7 +483,7 @@ export class SliderFilter implements Filter { // also trigger mouse enter event on the filter in case a SlickCustomTooltip is attached this.grid.onHeaderRowMouseEnter.notify( { column: this.columnDef, grid: this.grid }, - { ...new Slick.EventData(), target: this._argFilterContainerElm } + { ...new SlickEventData(), ...{ target: this._argFilterContainerElm } as unknown as Event } ); } diff --git a/packages/common/src/formatters/__tests__/currencyFormatter.spec.ts b/packages/common/src/formatters/__tests__/currencyFormatter.spec.ts index 60b9a061d..55e72daf6 100644 --- a/packages/common/src/formatters/__tests__/currencyFormatter.spec.ts +++ b/packages/common/src/formatters/__tests__/currencyFormatter.spec.ts @@ -4,7 +4,7 @@ import { currencyFormatter } from '../currencyFormatter'; describe('the Currency Formatter', () => { const gridStub = { getOptions: jest.fn() - } as unknown as SlickGrid; + } as unknown as SlickGridUniversal; beforeEach(() => { jest.spyOn(global.console, 'warn').mockReturnValue(); diff --git a/packages/common/src/formatters/__tests__/decimalFormatter.spec.ts b/packages/common/src/formatters/__tests__/decimalFormatter.spec.ts index 90aa74558..ebc26b513 100644 --- a/packages/common/src/formatters/__tests__/decimalFormatter.spec.ts +++ b/packages/common/src/formatters/__tests__/decimalFormatter.spec.ts @@ -4,7 +4,7 @@ import { decimalFormatter } from '../decimalFormatter'; describe('the Decimal Formatter', () => { const gridStub = { getOptions: jest.fn() - } as unknown as SlickGrid; + } as unknown as SlickGridUniversal; beforeEach(() => { jest.spyOn(global.console, 'warn').mockReturnValue(); diff --git a/packages/common/src/formatters/__tests__/dollarColoredBoldFormatter.spec.ts b/packages/common/src/formatters/__tests__/dollarColoredBoldFormatter.spec.ts index 3b433d261..24fcac358 100644 --- a/packages/common/src/formatters/__tests__/dollarColoredBoldFormatter.spec.ts +++ b/packages/common/src/formatters/__tests__/dollarColoredBoldFormatter.spec.ts @@ -4,7 +4,7 @@ import { dollarColoredBoldFormatter } from '../dollarColoredBoldFormatter'; describe('the DollarColoredBold Formatter', () => { const gridStub = { getOptions: jest.fn() - } as unknown as SlickGrid; + } as unknown as SlickGridUniversal; it('should return an empty string when no value is provided', () => { const output = dollarColoredBoldFormatter(1, 1, '', {} as Column, {}, {} as any); diff --git a/packages/common/src/formatters/__tests__/dollarColoredFormatter.spec.ts b/packages/common/src/formatters/__tests__/dollarColoredFormatter.spec.ts index de7879d38..bd361aa1b 100644 --- a/packages/common/src/formatters/__tests__/dollarColoredFormatter.spec.ts +++ b/packages/common/src/formatters/__tests__/dollarColoredFormatter.spec.ts @@ -4,7 +4,7 @@ import { dollarColoredFormatter } from '../dollarColoredFormatter'; describe('the DollarColored Formatter', () => { const gridStub = { getOptions: jest.fn() - } as unknown as SlickGrid; + } as unknown as SlickGridUniversal; it('should return an empty string when no value is provided', () => { const output = dollarColoredFormatter(1, 1, '', {} as Column, {}, {} as any); diff --git a/packages/common/src/formatters/__tests__/dollarFormatter.spec.ts b/packages/common/src/formatters/__tests__/dollarFormatter.spec.ts index d4c8b38da..58f5d6374 100644 --- a/packages/common/src/formatters/__tests__/dollarFormatter.spec.ts +++ b/packages/common/src/formatters/__tests__/dollarFormatter.spec.ts @@ -4,7 +4,7 @@ import { dollarFormatter } from '../dollarFormatter'; describe('the Dollar Formatter', () => { const gridStub = { getOptions: jest.fn() - } as unknown as SlickGrid; + } as unknown as SlickGridUniversal; it('should display an empty string when no value is provided', () => { const output = dollarFormatter(1, 1, '', {} as Column, {}, {} as any); diff --git a/packages/common/src/formatters/__tests__/formatterUtilities.spec.ts b/packages/common/src/formatters/__tests__/formatterUtilities.spec.ts index e3d39ec08..ef237ce39 100644 --- a/packages/common/src/formatters/__tests__/formatterUtilities.spec.ts +++ b/packages/common/src/formatters/__tests__/formatterUtilities.spec.ts @@ -10,7 +10,7 @@ import { multipleFormatter } from '../multipleFormatter'; describe('formatterUtilities', () => { const gridStub = { getOptions: jest.fn() - } as unknown as SlickGrid; + } as unknown as SlickGridUniversal; describe('autoAddEditorFormatterToColumnsWithEditor', () => { let columnDefinitions: Column[]; diff --git a/packages/common/src/formatters/__tests__/hyperlinkFormatter.spec.ts b/packages/common/src/formatters/__tests__/hyperlinkFormatter.spec.ts index b500a2ed6..c3070cc15 100644 --- a/packages/common/src/formatters/__tests__/hyperlinkFormatter.spec.ts +++ b/packages/common/src/formatters/__tests__/hyperlinkFormatter.spec.ts @@ -1,28 +1,37 @@ -import { Column } from '../../interfaces/index'; +import { Column, SlickGridUniversal } from '../../interfaces/index'; import { hyperlinkFormatter } from '../hyperlinkFormatter'; +const gridStub = { + getData: jest.fn(), + getOptions: jest.fn(), +} as unknown as SlickGridUniversal; + describe('the Hyperlink Formatter', () => { + beforeEach(() => { + jest.spyOn(gridStub, 'getOptions').mockReturnValue(undefined as any); + }); + it('should return empty string when value is not an hyperlink and is empty', () => { - const result = hyperlinkFormatter(0, 0, '', {} as Column, {}, {} as any); + const result = hyperlinkFormatter(0, 0, '', {} as Column, {}, gridStub); expect(result).toBe(''); }); it('should return original value when value is not an hyperlink', () => { - const result = hyperlinkFormatter(0, 0, 'anything', {} as Column, {}, {} as any); + const result = hyperlinkFormatter(0, 0, 'anything', {} as Column, {}, gridStub); expect(result).toBe('anything'); }); it('should return original value when URL passed through the generic params "hyperlinkUrl" is not a valid hyperlink', () => { const hyperlinkUrl1 = ''; const inputValue = 'Company Name'; - const result1 = hyperlinkFormatter(0, 0, inputValue, { params: { hyperlinkUrl: hyperlinkUrl1 } } as Column, {}, {} as any); + const result1 = hyperlinkFormatter(0, 0, inputValue, { params: { hyperlinkUrl: hyperlinkUrl1 } } as Column, {}, gridStub); expect(result1).toBe(inputValue); }); it('should not permit sanitize/remove any bad script code', () => { const inputValue = 'http://company.com'; const sanitizedValue = 'http://company.com'; - const result = hyperlinkFormatter(0, 0, inputValue, {} as Column, {}, {} as any); + const result = hyperlinkFormatter(0, 0, inputValue, {} as Column, {}, gridStub); expect(result).toBe(`${sanitizedValue}`); }); @@ -31,9 +40,9 @@ describe('the Hyperlink Formatter', () => { const inputValue2 = 'https//something.com'; const inputValue3 = 'ftpp://something.com'; - const result1 = hyperlinkFormatter(0, 0, inputValue1, {} as Column, {}, {} as any); - const result2 = hyperlinkFormatter(0, 0, inputValue2, {} as Column, {}, {} as any); - const result3 = hyperlinkFormatter(0, 0, inputValue3, {} as Column, {}, {} as any); + const result1 = hyperlinkFormatter(0, 0, inputValue1, {} as Column, {}, gridStub); + const result2 = hyperlinkFormatter(0, 0, inputValue2, {} as Column, {}, gridStub); + const result3 = hyperlinkFormatter(0, 0, inputValue3, {} as Column, {}, gridStub); expect(result1).toBe(inputValue1); expect(result2).toBe(inputValue2); @@ -45,9 +54,9 @@ describe('the Hyperlink Formatter', () => { const inputValue2 = 'https://something.com'; const inputValue3 = 'ftp://something.com'; - const result1 = hyperlinkFormatter(0, 0, inputValue1, {} as Column, {}, {} as any); - const result2 = hyperlinkFormatter(0, 0, inputValue2, {} as Column, {}, {} as any); - const result3 = hyperlinkFormatter(0, 0, inputValue3, {} as Column, {}, {} as any); + const result1 = hyperlinkFormatter(0, 0, inputValue1, {} as Column, {}, gridStub); + const result2 = hyperlinkFormatter(0, 0, inputValue2, {} as Column, {}, gridStub); + const result3 = hyperlinkFormatter(0, 0, inputValue3, {} as Column, {}, gridStub); expect(result1).toBe(`${inputValue1}`); @@ -61,9 +70,9 @@ describe('the Hyperlink Formatter', () => { const inputValue3 = 'ftp://something.com'; const linkText = 'Company Website'; - const result1 = hyperlinkFormatter(0, 0, inputValue1, { params: { hyperlinkText: linkText } } as Column, {}, {} as any); - const result2 = hyperlinkFormatter(0, 0, inputValue2, { params: { hyperlinkText: linkText } } as Column, {}, {} as any); - const result3 = hyperlinkFormatter(0, 0, inputValue3, { params: { hyperlinkText: linkText } } as Column, {}, {} as any); + const result1 = hyperlinkFormatter(0, 0, inputValue1, { params: { hyperlinkText: linkText } } as Column, {}, gridStub); + const result2 = hyperlinkFormatter(0, 0, inputValue2, { params: { hyperlinkText: linkText } } as Column, {}, gridStub); + const result3 = hyperlinkFormatter(0, 0, inputValue3, { params: { hyperlinkText: linkText } } as Column, {}, gridStub); expect(result1).toBe(`${linkText}`); @@ -77,9 +86,9 @@ describe('the Hyperlink Formatter', () => { const hyperlinkUrl3 = 'ftp://something.com'; const inputValue = 'Company Name'; - const result1 = hyperlinkFormatter(0, 0, inputValue, { params: { hyperlinkUrl: hyperlinkUrl1 } } as Column, {}, {} as any); - const result2 = hyperlinkFormatter(0, 0, inputValue, { params: { hyperlinkUrl: hyperlinkUrl2 } } as Column, {}, {} as any); - const result3 = hyperlinkFormatter(0, 0, inputValue, { params: { hyperlinkUrl: hyperlinkUrl3 } } as Column, {}, {} as any); + const result1 = hyperlinkFormatter(0, 0, inputValue, { params: { hyperlinkUrl: hyperlinkUrl1 } } as Column, {}, gridStub); + const result2 = hyperlinkFormatter(0, 0, inputValue, { params: { hyperlinkUrl: hyperlinkUrl2 } } as Column, {}, gridStub); + const result3 = hyperlinkFormatter(0, 0, inputValue, { params: { hyperlinkUrl: hyperlinkUrl3 } } as Column, {}, gridStub); expect(result1).toBe(`${inputValue}`); @@ -96,9 +105,9 @@ describe('the Hyperlink Formatter', () => { const linkText3 = 'Company XYZ'; const inputValue = 'anything'; - const result1 = hyperlinkFormatter(0, 0, inputValue, { params: { hyperlinkUrl: hyperlinkUrl1, hyperlinkText: linkText1 } } as Column, {}, {} as any); - const result2 = hyperlinkFormatter(0, 0, inputValue, { params: { hyperlinkUrl: hyperlinkUrl2, hyperlinkText: linkText2 } } as Column, {}, {} as any); - const result3 = hyperlinkFormatter(0, 0, inputValue, { params: { hyperlinkUrl: hyperlinkUrl3, hyperlinkText: linkText3 } } as Column, {}, {} as any); + const result1 = hyperlinkFormatter(0, 0, inputValue, { params: { hyperlinkUrl: hyperlinkUrl1, hyperlinkText: linkText1 } } as Column, {}, gridStub); + const result2 = hyperlinkFormatter(0, 0, inputValue, { params: { hyperlinkUrl: hyperlinkUrl2, hyperlinkText: linkText2 } } as Column, {}, gridStub); + const result3 = hyperlinkFormatter(0, 0, inputValue, { params: { hyperlinkUrl: hyperlinkUrl3, hyperlinkText: linkText3 } } as Column, {}, gridStub); expect(result1).toBe(`${linkText1}`); expect(result2).toBe(`${linkText2}`); diff --git a/packages/common/src/formatters/__tests__/percentCompleteFormatter.spec.ts b/packages/common/src/formatters/__tests__/percentCompleteFormatter.spec.ts index 51516ffbb..dca29fae9 100644 --- a/packages/common/src/formatters/__tests__/percentCompleteFormatter.spec.ts +++ b/packages/common/src/formatters/__tests__/percentCompleteFormatter.spec.ts @@ -4,7 +4,7 @@ import { percentCompleteFormatter } from '../percentCompleteFormatter'; describe('the Percent Complete Formatter', () => { const gridStub = { getOptions: jest.fn() - } as unknown as SlickGrid; + } as unknown as SlickGridUniversal; it('should return an empty string when no value is provided', () => { const output = percentCompleteFormatter(1, 1, '', {} as Column, {}, {} as any); diff --git a/packages/common/src/formatters/__tests__/percentFormatter.spec.ts b/packages/common/src/formatters/__tests__/percentFormatter.spec.ts index 83e624c88..5f51cc135 100644 --- a/packages/common/src/formatters/__tests__/percentFormatter.spec.ts +++ b/packages/common/src/formatters/__tests__/percentFormatter.spec.ts @@ -4,7 +4,7 @@ import { percentFormatter } from '../percentFormatter'; describe('the Percent Symbol Formatter', () => { const gridStub = { getOptions: jest.fn() - } as unknown as SlickGrid; + } as unknown as SlickGridUniversal; it('should display an empty string when no value is provided', () => { const output = percentFormatter(1, 1, '', {} as Column, {}, {} as any); diff --git a/packages/common/src/formatters/__tests__/percentSymbolFormatter.spec.ts b/packages/common/src/formatters/__tests__/percentSymbolFormatter.spec.ts index e41d958bd..89c2f6df8 100644 --- a/packages/common/src/formatters/__tests__/percentSymbolFormatter.spec.ts +++ b/packages/common/src/formatters/__tests__/percentSymbolFormatter.spec.ts @@ -4,7 +4,7 @@ import { percentSymbolFormatter } from '../percentSymbolFormatter'; describe('the Percent Symbol Formatter', () => { const gridStub = { getOptions: jest.fn() - } as unknown as SlickGrid; + } as unknown as SlickGridUniversal; it('should display an empty string when no value is provided', () => { const output = percentSymbolFormatter(1, 1, '', {} as Column, {}, {} as any); diff --git a/packages/common/src/formatters/__tests__/translateBooleanFormatter.spec.ts b/packages/common/src/formatters/__tests__/translateBooleanFormatter.spec.ts index f4e3e8a60..6417171da 100644 --- a/packages/common/src/formatters/__tests__/translateBooleanFormatter.spec.ts +++ b/packages/common/src/formatters/__tests__/translateBooleanFormatter.spec.ts @@ -1,4 +1,4 @@ -import { Column, SlickGrid } from '../../interfaces/index'; +import { Column, type SlickGridUniversal } from '../../interfaces/index'; import { translateBooleanFormatter } from '../translateBooleanFormatter'; import { TranslateServiceStub } from '../../../../../test/translateServiceStub'; @@ -8,7 +8,7 @@ describe('the Translate Boolean Formatter', () => { // stub some methods of the SlickGrid Grid instance const gridStub = { getOptions: jest.fn() - } as unknown as SlickGrid; + } as unknown as SlickGridUniversal; beforeEach(() => { translateService = new TranslateServiceStub(); @@ -51,7 +51,7 @@ describe('the Translate Boolean Formatter', () => { it('should return the translated value when value passed is a string and translater service is passed as a ColumnDef Params without any Grid object', async () => { await translateService.use('fr'); - const output = translateBooleanFormatter(1, 1, 'TRUE', { params: { translater: translateService } } as Column, {}, {} as any); + const output = translateBooleanFormatter(1, 1, 'TRUE', { params: { translater: translateService } } as Column, {}, gridStub); expect(output).toBe('Vrai'); }); diff --git a/packages/common/src/formatters/__tests__/translateFormatter.spec.ts b/packages/common/src/formatters/__tests__/translateFormatter.spec.ts index 09ad8c94c..7085f2a88 100644 --- a/packages/common/src/formatters/__tests__/translateFormatter.spec.ts +++ b/packages/common/src/formatters/__tests__/translateFormatter.spec.ts @@ -1,5 +1,5 @@ -import { Column, SlickGrid } from '../../interfaces/index'; +import { Column, type SlickGridUniversal } from '../../interfaces/index'; import { translateFormatter } from '../translateFormatter'; import { TranslateServiceStub } from '../../../../../test/translateServiceStub'; @@ -9,7 +9,7 @@ describe('the Translate Formatter', () => { // stub some methods of the SlickGrid Grid instance const gridStub = { getOptions: jest.fn() - } as unknown as SlickGrid; + } as unknown as SlickGridUniversal; beforeEach(() => { translateService = new TranslateServiceStub(); @@ -47,7 +47,7 @@ describe('the Translate Formatter', () => { it('should return the translated value when value passed is a string and translater service is passed as a ColumnDef Params without any Grid object', async () => { await translateService.use('fr'); - const output = translateFormatter(1, 1, 'HELLO', { params: { translater: translateService } } as Column, {}, {} as any); + const output = translateFormatter(1, 1, 'HELLO', { params: { translater: translateService } } as Column, {}, gridStub); expect(output).toBe('Bonjour'); }); diff --git a/packages/common/src/formatters/__tests__/treeExportFormatter.spec.ts b/packages/common/src/formatters/__tests__/treeExportFormatter.spec.ts index 4d8790f92..4b30ed020 100644 --- a/packages/common/src/formatters/__tests__/treeExportFormatter.spec.ts +++ b/packages/common/src/formatters/__tests__/treeExportFormatter.spec.ts @@ -4,7 +4,7 @@ import { treeExportFormatter } from '../treeExportFormatter'; const gridStub = { getData: jest.fn(), getOptions: jest.fn(), -} as unknown as SlickGrid; +} as unknown as SlickGridUniversal; describe('Tree Export Formatter', () => { let dataset: any[]; diff --git a/packages/common/src/formatters/__tests__/treeFormatter.spec.ts b/packages/common/src/formatters/__tests__/treeFormatter.spec.ts index cdfb2526c..c85108f98 100644 --- a/packages/common/src/formatters/__tests__/treeFormatter.spec.ts +++ b/packages/common/src/formatters/__tests__/treeFormatter.spec.ts @@ -1,10 +1,10 @@ -import { Column, GridOption, SlickGrid } from '../../interfaces/index'; +import { Column, GridOption, SlickGridUniversal } from '../../interfaces/index'; import { treeFormatter } from '../treeFormatter'; const gridStub = { getData: jest.fn(), getOptions: jest.fn(), -} as unknown as SlickGrid; +} as unknown as SlickGridUniversal; describe('Tree Formatter', () => { let dataset; @@ -87,8 +87,8 @@ describe('Tree Formatter', () => { }); it('should return a span with expanded icon and 15px indentation of a tree level 1 with a value prefix when provided', () => { - mockGridOptions.treeDataOptions.levelPropName = 'indent'; - mockGridOptions.treeDataOptions.titleFormatter = (_row, _cell, value, _def, dataContext) => { + mockGridOptions.treeDataOptions!.levelPropName = 'indent'; + mockGridOptions.treeDataOptions!.titleFormatter = (_row, _cell, value, _def, dataContext) => { if (dataContext.indent > 0) { return `${value}`; } diff --git a/packages/common/src/formatters/formatterUtilities.ts b/packages/common/src/formatters/formatterUtilities.ts index 8c9922cf2..dd29612f5 100644 --- a/packages/common/src/formatters/formatterUtilities.ts +++ b/packages/common/src/formatters/formatterUtilities.ts @@ -1,5 +1,5 @@ import { FieldType } from '../enums/fieldType.enum'; -import type { Column, ExcelExportOption, Formatter, GridOption, SlickGrid, TextExportOption } from '../interfaces/index'; +import type { Column, ExcelExportOption, Formatter, GridOption, SlickGridUniversal, TextExportOption } from '../interfaces/index'; import { sanitizeHtmlToText } from '../services/domUtilities'; import { mapMomentDateFormatWithFieldType } from '../services/utilities'; import { multipleFormatter } from './multipleFormatter'; @@ -37,7 +37,7 @@ export function autoAddEditorFormatterToColumnsWithEditor(columnDefinitions: Col } } -export function retrieveFormatterOptions(columnDef: Column, grid: SlickGrid, numberType: NumberType, formatterType: FormatterType) { +export function retrieveFormatterOptions(columnDef: Column, grid: SlickGridUniversal, numberType: NumberType, formatterType: FormatterType) { let defaultMinDecimal; let defaultMaxDecimal; let numberPrefix = ''; @@ -97,7 +97,7 @@ export function getValueFromParamsOrFormatterOptions(optionName: string, columnD export function getAssociatedDateFormatter(fieldType: typeof FieldType[keyof typeof FieldType], defaultSeparator: string): Formatter { const defaultDateFormat = mapMomentDateFormatWithFieldType(fieldType); - return (_row: number, _cell: number, value: any, columnDef: Column, _dataContext: any, grid: SlickGrid) => { + return (_row: number, _cell: number, value: any, columnDef: Column, _dataContext: any, grid: SlickGridUniversal) => { const gridOptions = ((grid && typeof grid.getOptions === 'function') ? grid.getOptions() : {}) as GridOption; const customSeparator = gridOptions?.formatterOptions?.dateSeparator ?? defaultSeparator; const inputType = columnDef?.type ?? FieldType.date; @@ -134,7 +134,7 @@ export function getAssociatedDateFormatter(fieldType: typeof FieldType[keyof typ * @param {Object} exportOptions - Excel or Text Export Options * @returns formatted string output or empty string */ -export function exportWithFormatterWhenDefined(row: number, col: number, columnDef: Column, dataContext: T, grid: SlickGrid, exportOptions?: TextExportOption | ExcelExportOption) { +export function exportWithFormatterWhenDefined(row: number, col: number, columnDef: Column, dataContext: T, grid: SlickGridUniversal, exportOptions?: TextExportOption | ExcelExportOption) { let isEvaluatingFormatter = false; // check if "exportWithFormatter" is provided in the column definition, if so it will have precendence over the Grid Options exportOptions @@ -168,7 +168,7 @@ export function exportWithFormatterWhenDefined(row: number, col: number * @param {Object} grid - Slick Grid object * @returns formatted string output or empty string */ -export function parseFormatterWhenExist(formatter: Formatter | undefined, row: number, col: number, columnDef: Column, dataContext: T, grid: SlickGrid): string { +export function parseFormatterWhenExist(formatter: Formatter | undefined, row: number, col: number, columnDef: Column, dataContext: T, grid: SlickGridUniversal): string { let output = ''; // does the field have the dot (.) notation and is a complex object? if so pull the first property name diff --git a/packages/common/src/formatters/hyperlinkFormatter.ts b/packages/common/src/formatters/hyperlinkFormatter.ts index 1a281fb98..9e72569f2 100644 --- a/packages/common/src/formatters/hyperlinkFormatter.ts +++ b/packages/common/src/formatters/hyperlinkFormatter.ts @@ -13,7 +13,7 @@ import { sanitizeTextByAvailableSanitizer, } from '../services/domUtilities'; */ export const hyperlinkFormatter: Formatter = (_row, _cell, value, columnDef, _dataContext, grid) => { const columnParams = columnDef && columnDef.params || {}; - const gridOptions = (grid && typeof grid.getOptions === 'function') ? grid.getOptions() : {}; + const gridOptions = grid?.getOptions() ?? {}; let displayedText = columnParams.hyperlinkText ? columnParams.hyperlinkText : value; displayedText = sanitizeTextByAvailableSanitizer(gridOptions, displayedText); diff --git a/packages/common/src/formatters/translateBooleanFormatter.ts b/packages/common/src/formatters/translateBooleanFormatter.ts index d6c702e72..e0798c6e7 100644 --- a/packages/common/src/formatters/translateBooleanFormatter.ts +++ b/packages/common/src/formatters/translateBooleanFormatter.ts @@ -2,7 +2,7 @@ import { type Formatter } from './../interfaces/index'; /** Takes a boolean value, cast it to upperCase string and finally translates it (i18n). */ export const translateBooleanFormatter: Formatter = (_row, _cell, value, columnDef, _dataContext, grid) => { - const gridOptions = (grid && typeof grid.getOptions === 'function') ? grid.getOptions() : {}; + const gridOptions = grid?.getOptions() ?? {}; const translater = gridOptions.translater || (columnDef && columnDef.params && columnDef.params.translater); if (!translater || typeof translater.translate !== 'function') { diff --git a/packages/common/src/formatters/translateFormatter.ts b/packages/common/src/formatters/translateFormatter.ts index 81afc4597..1f773316d 100644 --- a/packages/common/src/formatters/translateFormatter.ts +++ b/packages/common/src/formatters/translateFormatter.ts @@ -2,7 +2,7 @@ import { type Formatter } from './../interfaces/index'; /** Takes a cell value and translates it (translater). Requires an instance of the Translate Service:: `translater: this.translate */ export const translateFormatter: Formatter = (_row, _cell, value, columnDef, _dataContext, grid) => { - const gridOptions = (grid && typeof grid.getOptions === 'function') ? grid.getOptions() : {}; + const gridOptions = grid?.getOptions() ?? {}; const translater = gridOptions.translater || (columnDef && columnDef.params && columnDef.params.translater); if (!translater || typeof translater.translate !== 'function') { diff --git a/packages/common/src/global-grid-options.ts b/packages/common/src/global-grid-options.ts index bb8706f87..51d314574 100644 --- a/packages/common/src/global-grid-options.ts +++ b/packages/common/src/global-grid-options.ts @@ -5,7 +5,7 @@ import type { Column, EmptyWarning, GridOption, TreeDataOption } from './interfa import { Filters } from './filters'; /** Global Grid Options Defaults */ -export const GlobalGridOptions: GridOption = { +export const GlobalGridOptions: Partial = { alwaysShowVerticalScroll: true, autoEdit: false, asyncEditorLoading: false, diff --git a/packages/common/src/grouping-formatters/__tests__/avgTotalsCurrencyFormatters.spec.ts b/packages/common/src/grouping-formatters/__tests__/avgTotalsCurrencyFormatters.spec.ts index 7b97253e8..4e284c577 100644 --- a/packages/common/src/grouping-formatters/__tests__/avgTotalsCurrencyFormatters.spec.ts +++ b/packages/common/src/grouping-formatters/__tests__/avgTotalsCurrencyFormatters.spec.ts @@ -5,7 +5,7 @@ describe('avgTotalsCurrencyFormatter', () => { // stub some methods of the SlickGrid Grid instance const gridStub = { getOptions: jest.fn() - } as unknown as SlickGrid; + } as unknown as SlickGridUniversal; it('should display an empty string when no value is provided', () => { const output = avgTotalsCurrencyFormatter({}, {} as Column, gridStub); diff --git a/packages/common/src/grouping-formatters/__tests__/avgTotalsDollarFormatters.spec.ts b/packages/common/src/grouping-formatters/__tests__/avgTotalsDollarFormatters.spec.ts index 484465a51..4836547f6 100644 --- a/packages/common/src/grouping-formatters/__tests__/avgTotalsDollarFormatters.spec.ts +++ b/packages/common/src/grouping-formatters/__tests__/avgTotalsDollarFormatters.spec.ts @@ -5,7 +5,7 @@ describe('avgTotalsDollarFormatter', () => { // stub some methods of the SlickGrid Grid instance const gridStub = { getOptions: jest.fn() - } as unknown as SlickGrid; + } as unknown as SlickGridUniversal; it('should display an empty string when no value is provided', () => { const output = avgTotalsDollarFormatter({}, {} as Column, {} as SlickGrid); diff --git a/packages/common/src/grouping-formatters/__tests__/avgTotalsFormatter.spec.ts b/packages/common/src/grouping-formatters/__tests__/avgTotalsFormatter.spec.ts index f68e6f7f7..af1155d76 100644 --- a/packages/common/src/grouping-formatters/__tests__/avgTotalsFormatter.spec.ts +++ b/packages/common/src/grouping-formatters/__tests__/avgTotalsFormatter.spec.ts @@ -5,7 +5,7 @@ describe('avgTotalsFormatter', () => { // stub some methods of the SlickGrid Grid instance const gridStub = { getOptions: jest.fn() - } as unknown as SlickGrid; + } as unknown as SlickGridUniversal; it('should display an empty string when no value is provided', () => { const output = avgTotalsFormatter({}, {} as Column); diff --git a/packages/common/src/grouping-formatters/__tests__/avgTotalsPercentageFormatter.spec.ts b/packages/common/src/grouping-formatters/__tests__/avgTotalsPercentageFormatter.spec.ts index 71e8ad3ac..e10a2c97d 100644 --- a/packages/common/src/grouping-formatters/__tests__/avgTotalsPercentageFormatter.spec.ts +++ b/packages/common/src/grouping-formatters/__tests__/avgTotalsPercentageFormatter.spec.ts @@ -5,7 +5,7 @@ describe('avgTotalsPercentageFormatter', () => { // stub some methods of the SlickGrid Grid instance const gridStub = { getOptions: jest.fn() - } as unknown as SlickGrid; + } as unknown as SlickGridUniversal; it('should display an empty string when no value is provided', () => { const output = avgTotalsPercentageFormatter({}, {} as Column); diff --git a/packages/common/src/grouping-formatters/__tests__/maxTotalsFormatter.spec.ts b/packages/common/src/grouping-formatters/__tests__/maxTotalsFormatter.spec.ts index 4894a4f8a..873cdbd2c 100644 --- a/packages/common/src/grouping-formatters/__tests__/maxTotalsFormatter.spec.ts +++ b/packages/common/src/grouping-formatters/__tests__/maxTotalsFormatter.spec.ts @@ -5,7 +5,7 @@ describe('maxTotalsFormatter', () => { // stub some methods of the SlickGrid Grid instance const gridStub = { getOptions: jest.fn() - } as unknown as SlickGrid; + } as unknown as SlickGridUniversal; it('should display an empty string when no value is provided', () => { const output = maxTotalsFormatter({}, {} as Column); diff --git a/packages/common/src/grouping-formatters/__tests__/minTotalsFormatter.spec.ts b/packages/common/src/grouping-formatters/__tests__/minTotalsFormatter.spec.ts index 0d6a09d6b..9172501b5 100644 --- a/packages/common/src/grouping-formatters/__tests__/minTotalsFormatter.spec.ts +++ b/packages/common/src/grouping-formatters/__tests__/minTotalsFormatter.spec.ts @@ -5,7 +5,7 @@ describe('minTotalsFormatter', () => { // stub some methods of the SlickGrid Grid instance const gridStub = { getOptions: jest.fn() - } as unknown as SlickGrid; + } as unknown as SlickGridUniversal; it('should display an empty string when no value is provided', () => { const output = minTotalsFormatter({}, {} as Column, {} as SlickGrid); diff --git a/packages/common/src/grouping-formatters/__tests__/sumTotalsBoldFormatter.spec.ts b/packages/common/src/grouping-formatters/__tests__/sumTotalsBoldFormatter.spec.ts index 56d5931b7..627c8ed22 100644 --- a/packages/common/src/grouping-formatters/__tests__/sumTotalsBoldFormatter.spec.ts +++ b/packages/common/src/grouping-formatters/__tests__/sumTotalsBoldFormatter.spec.ts @@ -5,7 +5,7 @@ describe('sumTotalsBoldFormatter', () => { // stub some methods of the SlickGrid Grid instance const gridStub = { getOptions: jest.fn() - } as unknown as SlickGrid; + } as unknown as SlickGridUniversal; it('should display an empty string when no value is provided', () => { const output = sumTotalsBoldFormatter({}, {} as Column); diff --git a/packages/common/src/grouping-formatters/__tests__/sumTotalsColoredFormatter.spec.ts b/packages/common/src/grouping-formatters/__tests__/sumTotalsColoredFormatter.spec.ts index ffc69fa0c..2dc2b6124 100644 --- a/packages/common/src/grouping-formatters/__tests__/sumTotalsColoredFormatter.spec.ts +++ b/packages/common/src/grouping-formatters/__tests__/sumTotalsColoredFormatter.spec.ts @@ -5,7 +5,7 @@ describe('sumTotalsColoredFormatter', () => { // stub some methods of the SlickGrid Grid instance const gridStub = { getOptions: jest.fn() - } as unknown as SlickGrid; + } as unknown as SlickGridUniversal; it('should display an empty string when no value is provided', () => { const output = sumTotalsColoredFormatter({}, {} as Column); diff --git a/packages/common/src/grouping-formatters/__tests__/sumTotalsCurrencyColoredFormatter.spec.ts b/packages/common/src/grouping-formatters/__tests__/sumTotalsCurrencyColoredFormatter.spec.ts index 31e58e32c..b6080b648 100644 --- a/packages/common/src/grouping-formatters/__tests__/sumTotalsCurrencyColoredFormatter.spec.ts +++ b/packages/common/src/grouping-formatters/__tests__/sumTotalsCurrencyColoredFormatter.spec.ts @@ -5,7 +5,7 @@ describe('sumTotalsCurrencyColoredFormatter', () => { // stub some methods of the SlickGrid Grid instance const gridStub = { getOptions: jest.fn() - } as unknown as SlickGrid; + } as unknown as SlickGridUniversal; it('should display an empty string when no value is provided', () => { const output = sumTotalsCurrencyColoredFormatter({}, {} as Column, {} as SlickGrid); diff --git a/packages/common/src/grouping-formatters/__tests__/sumTotalsCurrencyFormatter.spec.ts b/packages/common/src/grouping-formatters/__tests__/sumTotalsCurrencyFormatter.spec.ts index 2a2eca1c6..5a3878b4d 100644 --- a/packages/common/src/grouping-formatters/__tests__/sumTotalsCurrencyFormatter.spec.ts +++ b/packages/common/src/grouping-formatters/__tests__/sumTotalsCurrencyFormatter.spec.ts @@ -5,7 +5,7 @@ describe('sumTotalsCurrencyFormatter', () => { // stub some methods of the SlickGrid Grid instance const gridStub = { getOptions: jest.fn() - } as unknown as SlickGrid; + } as unknown as SlickGridUniversal; it('should display an empty string when no value is provided', () => { const output = sumTotalsCurrencyFormatter({}, {} as Column, {} as SlickGrid); diff --git a/packages/common/src/grouping-formatters/__tests__/sumTotalsDollarBoldFormatter.spec.ts b/packages/common/src/grouping-formatters/__tests__/sumTotalsDollarBoldFormatter.spec.ts index d54cfece6..759ff9c77 100644 --- a/packages/common/src/grouping-formatters/__tests__/sumTotalsDollarBoldFormatter.spec.ts +++ b/packages/common/src/grouping-formatters/__tests__/sumTotalsDollarBoldFormatter.spec.ts @@ -5,7 +5,7 @@ describe('sumTotalsDollarBoldFormatter', () => { // stub some methods of the SlickGrid Grid instance const gridStub = { getOptions: jest.fn() - } as unknown as SlickGrid; + } as unknown as SlickGridUniversal; it('should display an empty string when no value is provided', () => { const output = sumTotalsDollarBoldFormatter({}, {} as Column); diff --git a/packages/common/src/grouping-formatters/__tests__/sumTotalsDollarColoredBoldFormatter.spec.ts b/packages/common/src/grouping-formatters/__tests__/sumTotalsDollarColoredBoldFormatter.spec.ts index 06a185954..99ed53613 100644 --- a/packages/common/src/grouping-formatters/__tests__/sumTotalsDollarColoredBoldFormatter.spec.ts +++ b/packages/common/src/grouping-formatters/__tests__/sumTotalsDollarColoredBoldFormatter.spec.ts @@ -5,7 +5,7 @@ describe('sumTotalsDollarColoredBoldFormatter', () => { // stub some methods of the SlickGrid Grid instance const gridStub = { getOptions: jest.fn() - } as unknown as SlickGrid; + } as unknown as SlickGridUniversal; it('should display an empty string when no value is provided', () => { const output = sumTotalsDollarColoredBoldFormatter({}, {} as Column); diff --git a/packages/common/src/grouping-formatters/__tests__/sumTotalsDollarColoredFormatter.spec.ts b/packages/common/src/grouping-formatters/__tests__/sumTotalsDollarColoredFormatter.spec.ts index 78056dfe4..6cd252dfa 100644 --- a/packages/common/src/grouping-formatters/__tests__/sumTotalsDollarColoredFormatter.spec.ts +++ b/packages/common/src/grouping-formatters/__tests__/sumTotalsDollarColoredFormatter.spec.ts @@ -5,7 +5,7 @@ describe('sumTotalsDollarColoredFormatter', () => { // stub some methods of the SlickGrid Grid instance const gridStub = { getOptions: jest.fn() - } as unknown as SlickGrid; + } as unknown as SlickGridUniversal; it('should display an empty string when no value is provided', () => { const output = sumTotalsDollarColoredFormatter({}, {} as Column, {} as SlickGrid); diff --git a/packages/common/src/grouping-formatters/__tests__/sumTotalsDollarFormatter.spec.ts b/packages/common/src/grouping-formatters/__tests__/sumTotalsDollarFormatter.spec.ts index 2e1a153a5..8a4112370 100644 --- a/packages/common/src/grouping-formatters/__tests__/sumTotalsDollarFormatter.spec.ts +++ b/packages/common/src/grouping-formatters/__tests__/sumTotalsDollarFormatter.spec.ts @@ -5,7 +5,7 @@ describe('sumTotalsDollarFormatter', () => { // stub some methods of the SlickGrid Grid instance const gridStub = { getOptions: jest.fn() - } as unknown as SlickGrid; + } as unknown as SlickGridUniversal; it('should display an empty string when no value is provided', () => { const output = sumTotalsDollarFormatter({}, {} as Column, {} as SlickGrid); diff --git a/packages/common/src/grouping-formatters/__tests__/sumTotalsFormatter.spec.ts b/packages/common/src/grouping-formatters/__tests__/sumTotalsFormatter.spec.ts index 9ae7a12e2..146eb53ae 100644 --- a/packages/common/src/grouping-formatters/__tests__/sumTotalsFormatter.spec.ts +++ b/packages/common/src/grouping-formatters/__tests__/sumTotalsFormatter.spec.ts @@ -5,7 +5,7 @@ describe('sumTotalsFormatter', () => { // stub some methods of the SlickGrid Grid instance const gridStub = { getOptions: jest.fn() - } as unknown as SlickGrid; + } as unknown as SlickGridUniversal; it('should display an empty string when no value is provided', () => { const output = sumTotalsFormatter({}, {} as Column, {} as SlickGrid); diff --git a/packages/common/src/grouping-formatters/avgTotalsCurrencyFormatter.ts b/packages/common/src/grouping-formatters/avgTotalsCurrencyFormatter.ts index a76ea55eb..9d3ab1768 100644 --- a/packages/common/src/grouping-formatters/avgTotalsCurrencyFormatter.ts +++ b/packages/common/src/grouping-formatters/avgTotalsCurrencyFormatter.ts @@ -1,8 +1,8 @@ -import type { Column, GroupTotalsFormatter, SlickGrid } from '../interfaces/index'; +import type { Column, GroupTotalsFormatter, SlickGridUniversal } from '../interfaces/index'; import { retrieveFormatterOptions } from '../formatters/formatterUtilities'; import { formatNumber } from '../services/utilities'; -export const avgTotalsCurrencyFormatter: GroupTotalsFormatter = (totals: any, columnDef: Column, grid: SlickGrid) => { +export const avgTotalsCurrencyFormatter: GroupTotalsFormatter = (totals: any, columnDef: Column, grid: SlickGridUniversal) => { const field = columnDef.field ?? ''; const val = totals.avg?.[field]; const params = columnDef?.params; diff --git a/packages/common/src/grouping-formatters/avgTotalsDollarFormatter.ts b/packages/common/src/grouping-formatters/avgTotalsDollarFormatter.ts index 398c70696..121e10536 100644 --- a/packages/common/src/grouping-formatters/avgTotalsDollarFormatter.ts +++ b/packages/common/src/grouping-formatters/avgTotalsDollarFormatter.ts @@ -1,8 +1,8 @@ -import type { Column, GroupTotalsFormatter, SlickGrid } from './../interfaces/index'; +import type { Column, GroupTotalsFormatter, SlickGridUniversal } from './../interfaces/index'; import { retrieveFormatterOptions } from '../formatters/formatterUtilities'; import { formatNumber } from './../services/utilities'; -export const avgTotalsDollarFormatter: GroupTotalsFormatter = (totals: any, columnDef: Column, grid: SlickGrid) => { +export const avgTotalsDollarFormatter: GroupTotalsFormatter = (totals: any, columnDef: Column, grid: SlickGridUniversal) => { const field = columnDef.field ?? ''; const val = totals.avg?.[field]; const params = columnDef?.params; diff --git a/packages/common/src/grouping-formatters/avgTotalsFormatter.ts b/packages/common/src/grouping-formatters/avgTotalsFormatter.ts index 6966c50d1..016579e55 100644 --- a/packages/common/src/grouping-formatters/avgTotalsFormatter.ts +++ b/packages/common/src/grouping-formatters/avgTotalsFormatter.ts @@ -1,8 +1,8 @@ -import type { Column, GroupTotalsFormatter, SlickGrid } from './../interfaces/index'; +import type { Column, GroupTotalsFormatter, SlickGridUniversal } from './../interfaces/index'; import { decimalFormatted, thousandSeparatorFormatted } from '../services/utilities'; import { retrieveFormatterOptions } from '../formatters/formatterUtilities'; -export const avgTotalsFormatter: GroupTotalsFormatter = (totals: any, columnDef: Column, grid: SlickGrid) => { +export const avgTotalsFormatter: GroupTotalsFormatter = (totals: any, columnDef: Column, grid: SlickGridUniversal) => { const field = columnDef.field ?? ''; let val = totals.avg?.[field]; const params = columnDef?.params; diff --git a/packages/common/src/grouping-formatters/avgTotalsPercentageFormatter.ts b/packages/common/src/grouping-formatters/avgTotalsPercentageFormatter.ts index ce9b0b3ed..48f632987 100644 --- a/packages/common/src/grouping-formatters/avgTotalsPercentageFormatter.ts +++ b/packages/common/src/grouping-formatters/avgTotalsPercentageFormatter.ts @@ -1,8 +1,8 @@ -import type { Column, GroupTotalsFormatter, SlickGrid } from './../interfaces/index'; +import type { Column, GroupTotalsFormatter, SlickGridUniversal } from './../interfaces/index'; import { decimalFormatted, thousandSeparatorFormatted } from '../services/utilities'; import { retrieveFormatterOptions } from '../formatters/formatterUtilities'; -export const avgTotalsPercentageFormatter: GroupTotalsFormatter = (totals: any, columnDef: Column, grid: SlickGrid) => { +export const avgTotalsPercentageFormatter: GroupTotalsFormatter = (totals: any, columnDef: Column, grid: SlickGridUniversal) => { const field = columnDef.field ?? ''; let val = totals.avg?.[field]; const params = columnDef?.params; diff --git a/packages/common/src/grouping-formatters/maxTotalsFormatter.ts b/packages/common/src/grouping-formatters/maxTotalsFormatter.ts index 79a9558b4..236a3ba64 100644 --- a/packages/common/src/grouping-formatters/maxTotalsFormatter.ts +++ b/packages/common/src/grouping-formatters/maxTotalsFormatter.ts @@ -1,8 +1,8 @@ -import type { Column, GroupTotalsFormatter, SlickGrid } from './../interfaces/index'; +import type { Column, GroupTotalsFormatter, SlickGridUniversal } from './../interfaces/index'; import { formatNumber } from '../services/utilities'; import { retrieveFormatterOptions } from '../formatters/formatterUtilities'; -export const maxTotalsFormatter: GroupTotalsFormatter = (totals: any, columnDef: Column, grid: SlickGrid) => { +export const maxTotalsFormatter: GroupTotalsFormatter = (totals: any, columnDef: Column, grid: SlickGridUniversal) => { const field = columnDef.field ?? ''; const val = totals.max?.[field]; const params = columnDef?.params; diff --git a/packages/common/src/grouping-formatters/minTotalsFormatter.ts b/packages/common/src/grouping-formatters/minTotalsFormatter.ts index 1d2598cf6..0414b49d8 100644 --- a/packages/common/src/grouping-formatters/minTotalsFormatter.ts +++ b/packages/common/src/grouping-formatters/minTotalsFormatter.ts @@ -1,8 +1,8 @@ -import type { Column, GroupTotalsFormatter, SlickGrid } from './../interfaces/index'; +import type { Column, GroupTotalsFormatter, SlickGridUniversal } from './../interfaces/index'; import { formatNumber } from '../services/utilities'; import { retrieveFormatterOptions } from '../formatters/formatterUtilities'; -export const minTotalsFormatter: GroupTotalsFormatter = (totals: any, columnDef: Column, grid: SlickGrid) => { +export const minTotalsFormatter: GroupTotalsFormatter = (totals: any, columnDef: Column, grid: SlickGridUniversal) => { const field = columnDef.field ?? ''; const val = totals.min?.[field]; const params = columnDef?.params; diff --git a/packages/common/src/grouping-formatters/sumTotalsBoldFormatter.ts b/packages/common/src/grouping-formatters/sumTotalsBoldFormatter.ts index bd46728d6..04f55732e 100644 --- a/packages/common/src/grouping-formatters/sumTotalsBoldFormatter.ts +++ b/packages/common/src/grouping-formatters/sumTotalsBoldFormatter.ts @@ -1,8 +1,8 @@ -import type { Column, GroupTotalsFormatter, SlickGrid } from './../interfaces/index'; +import type { Column, GroupTotalsFormatter, SlickGridUniversal } from './../interfaces/index'; import { formatNumber } from '../services/utilities'; import { retrieveFormatterOptions } from '../formatters/formatterUtilities'; -export const sumTotalsBoldFormatter: GroupTotalsFormatter = (totals: any, columnDef: Column, grid: SlickGrid) => { +export const sumTotalsBoldFormatter: GroupTotalsFormatter = (totals: any, columnDef: Column, grid: SlickGridUniversal) => { const field = columnDef.field ?? ''; const val = totals.sum?.[field]; const params = columnDef?.params; diff --git a/packages/common/src/grouping-formatters/sumTotalsColoredFormatter.ts b/packages/common/src/grouping-formatters/sumTotalsColoredFormatter.ts index 8f3749d46..cedf0001b 100644 --- a/packages/common/src/grouping-formatters/sumTotalsColoredFormatter.ts +++ b/packages/common/src/grouping-formatters/sumTotalsColoredFormatter.ts @@ -1,8 +1,8 @@ -import type { Column, GroupTotalsFormatter, SlickGrid } from './../interfaces/index'; +import type { Column, GroupTotalsFormatter, SlickGridUniversal } from './../interfaces/index'; import { formatNumber } from '../services/utilities'; import { retrieveFormatterOptions } from '../formatters/formatterUtilities'; -export const sumTotalsColoredFormatter: GroupTotalsFormatter = (totals: any, columnDef: Column, grid: SlickGrid) => { +export const sumTotalsColoredFormatter: GroupTotalsFormatter = (totals: any, columnDef: Column, grid: SlickGridUniversal) => { const field = columnDef.field ?? ''; const val = totals.sum?.[field]; const params = columnDef?.params; diff --git a/packages/common/src/grouping-formatters/sumTotalsCurrencyColoredFormatter.ts b/packages/common/src/grouping-formatters/sumTotalsCurrencyColoredFormatter.ts index a4d2d4570..8f92e87ab 100644 --- a/packages/common/src/grouping-formatters/sumTotalsCurrencyColoredFormatter.ts +++ b/packages/common/src/grouping-formatters/sumTotalsCurrencyColoredFormatter.ts @@ -1,8 +1,8 @@ -import type { Column, GroupTotalsFormatter, SlickGrid } from '../interfaces/index'; +import type { Column, GroupTotalsFormatter, SlickGridUniversal } from '../interfaces/index'; import { formatNumber } from '../services/utilities'; import { retrieveFormatterOptions } from '../formatters/formatterUtilities'; -export const sumTotalsCurrencyColoredFormatter: GroupTotalsFormatter = (totals: any, columnDef: Column, grid: SlickGrid) => { +export const sumTotalsCurrencyColoredFormatter: GroupTotalsFormatter = (totals: any, columnDef: Column, grid: SlickGridUniversal) => { const field = columnDef.field ?? ''; const val = totals.sum?.[field]; const params = columnDef?.params; diff --git a/packages/common/src/grouping-formatters/sumTotalsCurrencyFormatter.ts b/packages/common/src/grouping-formatters/sumTotalsCurrencyFormatter.ts index 3911577d3..7834c2860 100644 --- a/packages/common/src/grouping-formatters/sumTotalsCurrencyFormatter.ts +++ b/packages/common/src/grouping-formatters/sumTotalsCurrencyFormatter.ts @@ -1,8 +1,8 @@ -import type { Column, GroupTotalsFormatter, SlickGrid } from '../interfaces/index'; +import type { Column, GroupTotalsFormatter, SlickGridUniversal } from '../interfaces/index'; import { formatNumber } from '../services/utilities'; import { retrieveFormatterOptions } from '../formatters/formatterUtilities'; -export const sumTotalsCurrencyFormatter: GroupTotalsFormatter = (totals: any, columnDef: Column, grid: SlickGrid) => { +export const sumTotalsCurrencyFormatter: GroupTotalsFormatter = (totals: any, columnDef: Column, grid: SlickGridUniversal) => { const field = columnDef.field ?? ''; const val = totals.sum?.[field]; const params = columnDef?.params; diff --git a/packages/common/src/grouping-formatters/sumTotalsDollarBoldFormatter.ts b/packages/common/src/grouping-formatters/sumTotalsDollarBoldFormatter.ts index be8d33417..508a68e6b 100644 --- a/packages/common/src/grouping-formatters/sumTotalsDollarBoldFormatter.ts +++ b/packages/common/src/grouping-formatters/sumTotalsDollarBoldFormatter.ts @@ -1,8 +1,8 @@ -import type { Column, GroupTotalsFormatter, SlickGrid } from './../interfaces/index'; +import type { Column, GroupTotalsFormatter, SlickGridUniversal } from './../interfaces/index'; import { formatNumber } from './../services/utilities'; import { retrieveFormatterOptions } from '../formatters/formatterUtilities'; -export const sumTotalsDollarBoldFormatter: GroupTotalsFormatter = (totals: any, columnDef: Column, grid: SlickGrid) => { +export const sumTotalsDollarBoldFormatter: GroupTotalsFormatter = (totals: any, columnDef: Column, grid: SlickGridUniversal) => { const field = columnDef.field ?? ''; const val = totals.sum?.[field]; const params = columnDef?.params; diff --git a/packages/common/src/grouping-formatters/sumTotalsDollarColoredBoldFormatter.ts b/packages/common/src/grouping-formatters/sumTotalsDollarColoredBoldFormatter.ts index a69825ad0..f2af7dc16 100644 --- a/packages/common/src/grouping-formatters/sumTotalsDollarColoredBoldFormatter.ts +++ b/packages/common/src/grouping-formatters/sumTotalsDollarColoredBoldFormatter.ts @@ -1,8 +1,8 @@ -import type { Column, GroupTotalsFormatter, SlickGrid } from './../interfaces/index'; +import type { Column, GroupTotalsFormatter, SlickGridUniversal } from './../interfaces/index'; import { formatNumber } from './../services/utilities'; import { retrieveFormatterOptions } from '../formatters/formatterUtilities'; -export const sumTotalsDollarColoredBoldFormatter: GroupTotalsFormatter = (totals: any, columnDef: Column, grid: SlickGrid) => { +export const sumTotalsDollarColoredBoldFormatter: GroupTotalsFormatter = (totals: any, columnDef: Column, grid: SlickGridUniversal) => { const field = columnDef.field ?? ''; const val = totals.sum?.[field]; const params = columnDef?.params; diff --git a/packages/common/src/grouping-formatters/sumTotalsDollarColoredFormatter.ts b/packages/common/src/grouping-formatters/sumTotalsDollarColoredFormatter.ts index 5e81ac7cc..56278400a 100644 --- a/packages/common/src/grouping-formatters/sumTotalsDollarColoredFormatter.ts +++ b/packages/common/src/grouping-formatters/sumTotalsDollarColoredFormatter.ts @@ -1,8 +1,8 @@ -import type { Column, GroupTotalsFormatter, SlickGrid } from './../interfaces/index'; +import type { Column, GroupTotalsFormatter, SlickGridUniversal } from './../interfaces/index'; import { formatNumber } from './../services/utilities'; import { retrieveFormatterOptions } from '../formatters/formatterUtilities'; -export const sumTotalsDollarColoredFormatter: GroupTotalsFormatter = (totals: any, columnDef: Column, grid: SlickGrid) => { +export const sumTotalsDollarColoredFormatter: GroupTotalsFormatter = (totals: any, columnDef: Column, grid: SlickGridUniversal) => { const field = columnDef.field ?? ''; const val = totals.sum?.[field]; const params = columnDef?.params; diff --git a/packages/common/src/grouping-formatters/sumTotalsDollarFormatter.ts b/packages/common/src/grouping-formatters/sumTotalsDollarFormatter.ts index 5cc0dd902..c9be426f1 100644 --- a/packages/common/src/grouping-formatters/sumTotalsDollarFormatter.ts +++ b/packages/common/src/grouping-formatters/sumTotalsDollarFormatter.ts @@ -1,8 +1,8 @@ -import type { Column, GroupTotalsFormatter, SlickGrid } from './../interfaces/index'; +import type { Column, GroupTotalsFormatter, SlickGridUniversal } from './../interfaces/index'; import { formatNumber } from './../services/utilities'; import { retrieveFormatterOptions } from '../formatters/formatterUtilities'; -export const sumTotalsDollarFormatter: GroupTotalsFormatter = (totals: any, columnDef: Column, grid: SlickGrid) => { +export const sumTotalsDollarFormatter: GroupTotalsFormatter = (totals: any, columnDef: Column, grid: SlickGridUniversal) => { const field = columnDef.field ?? ''; const val = totals.sum?.[field]; const params = columnDef?.params; diff --git a/packages/common/src/grouping-formatters/sumTotalsFormatter.ts b/packages/common/src/grouping-formatters/sumTotalsFormatter.ts index 7f52e2ec4..aebc668aa 100644 --- a/packages/common/src/grouping-formatters/sumTotalsFormatter.ts +++ b/packages/common/src/grouping-formatters/sumTotalsFormatter.ts @@ -1,8 +1,8 @@ -import type { Column, GroupTotalsFormatter, SlickGrid } from './../interfaces/index'; +import type { Column, GroupTotalsFormatter, SlickGridUniversal } from './../interfaces/index'; import { formatNumber } from '../services/utilities'; import { retrieveFormatterOptions } from '../formatters/formatterUtilities'; -export const sumTotalsFormatter: GroupTotalsFormatter = (totals: any, columnDef: Column, grid: SlickGrid) => { +export const sumTotalsFormatter: GroupTotalsFormatter = (totals: any, columnDef: Column, grid: SlickGridUniversal) => { const field = columnDef.field ?? ''; const val = totals.sum?.[field]; const params = columnDef?.params; diff --git a/packages/common/src/index.ts b/packages/common/src/index.ts index 38949703a..a7b8c09e8 100644 --- a/packages/common/src/index.ts +++ b/packages/common/src/index.ts @@ -46,3 +46,5 @@ export { SlickgridConfig } from './slickgrid-config'; // re-export MultipleSelectOption to avoid breaking previous code implementation export { MultipleSelectOption } from 'multiple-select-vanilla'; +// re-export SlickGrid +export { SlickGrid, SlickDataView, OnSelectedRowsChangedEventArgs, SlickEventData } from 'slickgrid'; diff --git a/packages/common/src/interfaces/autocompleterOption.interface.ts b/packages/common/src/interfaces/autocompleterOption.interface.ts index b62e3f6ba..78c9447f0 100644 --- a/packages/common/src/interfaces/autocompleterOption.interface.ts +++ b/packages/common/src/interfaces/autocompleterOption.interface.ts @@ -43,5 +43,5 @@ export interface AutocompleterOption extends P * This is the same as the "select" callback and was created so that user don't overwrite exclusive usage of the "select" callback. * Also compare to the "select", it has some extra arguments which are: row, cell, column, dataContext */ - onSelectItem?: (item: any, row: number, cell: number, columnDef: Column, dataContext: any) => void; + onSelectItem?: (item: any, row: number | undefined, cell: number | undefined, columnDef: Column, dataContext: any) => void; } \ No newline at end of file diff --git a/packages/common/src/interfaces/backendService.interface.ts b/packages/common/src/interfaces/backendService.interface.ts index d85c2c49d..379610c79 100644 --- a/packages/common/src/interfaces/backendService.interface.ts +++ b/packages/common/src/interfaces/backendService.interface.ts @@ -10,8 +10,8 @@ import type { PaginationChangedArgs, PaginationCursorChangedArgs, SingleColumnSort, + SlickGridUniversal, } from './index'; -import { SlickGrid } from './slickGrid.interface'; import { SharedService } from '../services'; export interface BackendService { @@ -31,7 +31,7 @@ export interface BackendService { clearSorters?: () => void; /** initialize the backend service with certain options */ - init?: (serviceOptions?: BackendServiceOption | any, pagination?: Pagination, grid?: SlickGrid, sharedService?: SharedService) => void; + init?: (serviceOptions?: BackendServiceOption | any, pagination?: Pagination, grid?: SlickGridUniversal, sharedService?: SharedService) => void; /** Get the dataset name */ getDatasetName?: () => string; diff --git a/packages/common/src/interfaces/cellArgs.interface.ts b/packages/common/src/interfaces/cellArgs.interface.ts index 76cca08f5..0b138d349 100644 --- a/packages/common/src/interfaces/cellArgs.interface.ts +++ b/packages/common/src/interfaces/cellArgs.interface.ts @@ -1,8 +1,8 @@ -import type { SlickGrid } from './slickGrid.interface'; +import type { SlickGridUniversal } from './index'; export interface CellArgs { row: number; cell: number; - grid: SlickGrid; + grid: SlickGridUniversal; item?: any; } diff --git a/packages/common/src/interfaces/cellMenuOption.interface.ts b/packages/common/src/interfaces/cellMenuOption.interface.ts index 4533d06b6..38d8df1b2 100644 --- a/packages/common/src/interfaces/cellMenuOption.interface.ts +++ b/packages/common/src/interfaces/cellMenuOption.interface.ts @@ -1,21 +1,17 @@ -import type { - MenuCallbackArgs, - MenuCommandItem, - MenuOptionItem, -} from './index'; +import type { MenuCallbackArgs, MenuCommandItem, MenuOptionItem } from './index'; export interface CellMenuOption { /** Defaults to true, Auto-align dropup or dropdown menu to the left or right depending on grid viewport available space */ autoAdjustDrop?: boolean; /** Defaults to 0, Optionally add an offset to the auto-align of the drop menu */ - autoAdjustDropOffset?: string; + autoAdjustDropOffset?: number; /** Defaults to true, Auto-align drop menu to the left or right depending on grid viewport available space */ autoAlignSide?: boolean; /** Defaults to 0, Optionally add an offset to the left/right side auto-align */ - autoAlignSideOffset?: string; + autoAlignSideOffset?: number; /** Array of Command Items (title, command, disabled, ...) */ commandItems?: Array; diff --git a/packages/common/src/interfaces/collectionOverrideArgs.interface.ts b/packages/common/src/interfaces/collectionOverrideArgs.interface.ts index ba7e134e0..3c1c29df3 100644 --- a/packages/common/src/interfaces/collectionOverrideArgs.interface.ts +++ b/packages/common/src/interfaces/collectionOverrideArgs.interface.ts @@ -1,5 +1,5 @@ -import type { CompositeEditorOption } from './compositeEditorOption.interface'; -import type { Column, SlickGrid } from './index'; +import type { CompositeEditorOption, SlickGridUniversal } from './index'; +import type { Column } from './index'; export interface CollectionOverrideArgs { /** Column Definition */ @@ -9,7 +9,7 @@ export interface CollectionOverrideArgs { dataContext: any; /** Slick Grid object */ - grid: SlickGrid; + grid: SlickGridUniversal; /** Potential Composite Editor option when triggered by the Composite Editor modal window */ compositeEditorOptions?: Pick; diff --git a/packages/common/src/interfaces/column.interface.ts b/packages/common/src/interfaces/column.interface.ts index 79b651c17..0749d9654 100644 --- a/packages/common/src/interfaces/column.interface.ts +++ b/packages/common/src/interfaces/column.interface.ts @@ -1,4 +1,5 @@ -/* eslint-disable @typescript-eslint/indent */ +import type { Column as ColumnCore, FormatterResultObject } from 'slickgrid'; + import type { CellMenu, ColumnEditor, @@ -12,31 +13,32 @@ import type { GroupTotalsFormatter, HeaderButtonsOrMenu, OnEventArgs, - SlickEventData, - SlickGrid, + SlickGridUniversal, SortComparer, } from './index'; import type { FieldType } from '../enums/fieldType.enum'; -type PathsToStringProps = T extends string | number | boolean | Date ? [] : { - [K in Extract]: [K, ...PathsToStringProps] -}[Extract]; +type FormatterOverrideCallback = (row: number, cell: number, val: any, columnDef: Column, item: any, grid: SlickGridUniversal) => string | FormatterResultObject; + +// type PathsToStringProps = T extends string | number | boolean | Date ? [] : { +// [K in Extract]: [K, ...PathsToStringProps] +// }[Extract]; -/* eslint-disable @typescript-eslint/indent */ -// disable eslint indent rule until this issue is fixed: https://github.com/typescript-eslint/typescript-eslint/issues/1824 -type Join = - T extends [] ? never : - T extends [infer F] ? F : - T extends [infer F, ...infer R] ? - F extends string ? string extends F ? string : `${F}${D}${Join}` : never : string; -/* eslint-enable @typescript-eslint/indent */ +// /* eslint-disable @typescript-eslint/indent */ +// // disable eslint indent rule until this issue is fixed: https://github.com/typescript-eslint/typescript-eslint/issues/1824 +// type Join = +// T extends [] ? never : +// T extends [infer F] ? F : +// T extends [infer F, ...infer R] ? +// F extends string ? string extends F ? string : `${F}${D}${Join}` : never : string; +// /* eslint-enable @typescript-eslint/indent */ -export interface Column { +export interface Column extends ColumnCore { /** Defaults to false, should we always render the column? */ alwaysRenderColumn?: boolean; /** async background post-rendering formatter */ - asyncPostRender?: (domCellNode: any, row: number, dataContext: T, columnDef: Column) => void; + asyncPostRender?: (domCellNode: HTMLElement, row: number, dataContext: T, columnDef: Column, process?: boolean) => void; /** async background post-render cleanup callback function */ asyncPostRenderCleanup?: (node: HTMLElement, rowIdx: number, column: Column) => void; @@ -87,6 +89,7 @@ export interface Column { /** Defaults to false, do we want to deny executing a Paste (from a Copy of CellExternalCopyManager)? */ denyPaste?: boolean; + /** * defaults to False, optionally enable/disable tooltip. * This is typically used on a specific column that you would like to completely disable the custom/regular tooltip. @@ -149,7 +152,7 @@ export interface Column { * NOTE: a field with dot notation (.) will be considered a complex object. * For example: { id: 'Users', field: 'user.firstName' } */ - field: Join, '.'>; + // field: Join, '.'>; /** * Only used by Backend Services since the query is built using the column definitions, this is a way to pass extra properties to the backend query. @@ -174,7 +177,7 @@ export interface Column { formatter?: Formatter; /** Default Formatter override function */ - formatterOverride?: { ReturnsTextOnly?: boolean; } | ((row: number, cell: number, val: any, columnDef: Column, item: any, grid: SlickGrid) => Formatter); + formatterOverride?: { ReturnsTextOnly: boolean; } | FormatterOverrideCallback; /** Grouping option used by a Draggable Grouping Column */ grouping?: Grouping; @@ -192,7 +195,7 @@ export interface Column { headerCellAttrs?: any; /** CSS class that can be added to the column header */ - headerCssClass?: string; + headerCssClass?: string | null; /** ID of the column, each row have to be unique or SlickGrid will throw an error. */ id: number | string; @@ -233,13 +236,13 @@ export interface Column { nameCompositeEditorKey?: string; /** an event that can be used for executing an action before the cell becomes editable (that event happens before the "onCellChange" event) */ - onBeforeEditCell?: (e: SlickEventData, args: OnEventArgs) => void; + onBeforeEditCell?: (e: Event, args: OnEventArgs) => void; /** an event that can be used for executing an action after a cell change */ - onCellChange?: (e: SlickEventData, args: OnEventArgs) => void; + onCellChange?: (e: Event, args: OnEventArgs) => void; /** an event that can be used for executing an action after a cell click */ - onCellClick?: (e: SlickEventData, args: OnEventArgs) => void; + onCellClick?: (e: Event, args: OnEventArgs) => void; /** * Column output type (e.g. Date Picker, the output format that we will see in the picker) diff --git a/packages/common/src/interfaces/columnEditor.interface.ts b/packages/common/src/interfaces/columnEditor.interface.ts index eeaa6eef4..5278d035d 100644 --- a/packages/common/src/interfaces/columnEditor.interface.ts +++ b/packages/common/src/interfaces/columnEditor.interface.ts @@ -6,6 +6,7 @@ import type { CollectionOption, CollectionOverrideArgs, CollectionSortBy, + // Editor, EditorValidator, } from './index'; diff --git a/packages/common/src/interfaces/columnPicker.interface.ts b/packages/common/src/interfaces/columnPicker.interface.ts index e539576aa..50b906ab5 100644 --- a/packages/common/src/interfaces/columnPicker.interface.ts +++ b/packages/common/src/interfaces/columnPicker.interface.ts @@ -1,4 +1,4 @@ -import type { Column, GridOption, SlickGrid } from './index'; +import type { Column, GridOption, SlickGridUniversal } from './index'; import type { SlickColumnPicker } from '../extensions/slickColumnPicker'; export interface ColumnPicker extends ColumnPickerOption { @@ -8,6 +8,27 @@ export interface ColumnPicker extends ColumnPickerOption { /** Fired after extension (control) is registered by SlickGrid */ onExtensionRegistered?: (plugin: SlickColumnPicker) => void; + + /** SlickGrid Event fired when any of the columns checkbox selection changes. */ + onColumnsChanged?: (e: Event, args: { + /** column definition id */ + columnId: number | string; + + /** last command, are we showing or not the column? */ + showing: boolean; + + /** slick grid object */ + grid: SlickGridUniversal; + + /** list of all column definitions (visible & hidden) */ + allColumns: Column[]; + + /** list of all column definitions (visible & hidden) */ + columns: Column[]; + + /** list of visible column definitions */ + visibleColumns: Column[]; + }) => void; } export interface ColumnPickerOption { @@ -43,25 +64,4 @@ export interface ColumnPickerOption { /** Callback method to override the column name output used by the ColumnPicker/GridMenu. */ headerColumnValueExtractor?: (column: Column, gridOptions?: GridOption) => string; - - // -- - // Events - - /** SlickGrid Event fired when any of the columns checkbox selection changes. */ - onColumnsChanged?: (e: Event, args: { - /** column definition id */ - columnId: string; - - /** last command, are we showing or not the column? */ - showing: boolean; - - /** slick grid object */ - grid: SlickGrid; - - /** list of all column definitions (visible & hidden) */ - allColumns: Column[]; - - /** list of visible column definitions */ - visibleColumns: Column[]; - }) => void; } diff --git a/packages/common/src/interfaces/columnSort.interface.ts b/packages/common/src/interfaces/columnSort.interface.ts index ab9ae72f0..b9e909b1f 100644 --- a/packages/common/src/interfaces/columnSort.interface.ts +++ b/packages/common/src/interfaces/columnSort.interface.ts @@ -8,5 +8,5 @@ export interface ColumnSort { sortAsc: boolean; /** Column to be sorted */ - sortCol: Column; + sortCol?: Column; } diff --git a/packages/common/src/interfaces/contextMenuOption.interface.ts b/packages/common/src/interfaces/contextMenuOption.interface.ts index 6ac9625d0..33b3ea23e 100644 --- a/packages/common/src/interfaces/contextMenuOption.interface.ts +++ b/packages/common/src/interfaces/contextMenuOption.interface.ts @@ -9,13 +9,13 @@ export interface ContextMenuOption { autoAdjustDrop?: boolean; /** Defaults to 0, Optionally add an offset to the auto-align of the drop menu */ - autoAdjustDropOffset?: string; + autoAdjustDropOffset?: number; /** Defaults to true, Auto-align drop menu to the left or right depending on grid viewport available space */ autoAlignSide?: boolean; /** Defaults to 0, Optionally add an offset to the left/right side auto-align */ - autoAlignSideOffset?: string; + autoAlignSideOffset?: number; /** Array of Command Items (title, command, disabled, ...) */ commandItems?: Array; diff --git a/packages/common/src/interfaces/customTooltipOption.interface.ts b/packages/common/src/interfaces/customTooltipOption.interface.ts index 9b1661d9e..fe8fe8aeb 100644 --- a/packages/common/src/interfaces/customTooltipOption.interface.ts +++ b/packages/common/src/interfaces/customTooltipOption.interface.ts @@ -1,8 +1,8 @@ import type { Observable, Subject } from '../services/rxjsFacade'; -import type { Column, Formatter, SlickGrid } from './index'; +import type { Column, Formatter, SlickGridUniversal } from './index'; type PostProcessOutput

    = P & { [asyncParamsPropName: string]: any; }; -export type asyncProcess = (row: number, cell: number, value: any, columnDef: Column, dataContext: T, grid?: SlickGrid) => Promise> | Observable> | Subject>; +export type AsyncProcess = (row: number, cell: number, value: any, columnDef: Column, dataContext: T, grid?: SlickGridUniversal) => Promise> | Observable> | Subject>; export interface CustomTooltipOption { /** defaults to "__params", optionally change the property name that will be used to merge the data returned by the async method into the `dataContext` object */ @@ -12,7 +12,7 @@ export interface CustomTooltipOption { * Async Post method returning a Promise, it must return an object with 1 or more properties * Note: internally the data that will automatically be merged into the `dataContext` object under the `__params` property so that you can use it in your `asyncPostFormatter` formatter. */ - asyncProcess?: asyncProcess; + asyncProcess?: AsyncProcess; /** Formatter to execute once the async process is completed, to displayed the actual text result (used when dealing with an Async API to get data to display later in the tooltip) */ asyncPostFormatter?: Formatter; @@ -92,5 +92,5 @@ export interface CustomTooltipOption { // Methods /** Callback method that user can override the default behavior of showing the tooltip. If it returns False, then the tooltip won't show */ - usabilityOverride?: (args: { cell: number; row: number; column: Column; dataContext: any; type: 'cell' | 'header' | 'header-row'; grid: SlickGrid; }) => boolean; + usabilityOverride?: (args: { cell: number; row: number; column: Column; dataContext: any; type: 'cell' | 'header' | 'header-row'; grid: SlickGridUniversal; }) => boolean; } \ No newline at end of file diff --git a/packages/common/src/interfaces/dataViewOption.interface.ts b/packages/common/src/interfaces/dataViewOption.interface.ts index 1fcbe5c10..a1504d880 100644 --- a/packages/common/src/interfaces/dataViewOption.interface.ts +++ b/packages/common/src/interfaces/dataViewOption.interface.ts @@ -5,5 +5,5 @@ export interface DataViewOption { inlineFilters?: boolean; /** Optionally provide a Group Item Metatadata Provider when using Grouping/DraggableGrouping feature */ - groupItemMetadataProvider?: SlickGroupItemMetadataProvider; + groupItemMetadataProvider?: SlickGroupItemMetadataProvider | null; } diff --git a/packages/common/src/interfaces/drag.interface.ts b/packages/common/src/interfaces/drag.interface.ts index ee58ae779..b880a27d4 100644 --- a/packages/common/src/interfaces/drag.interface.ts +++ b/packages/common/src/interfaces/drag.interface.ts @@ -1,4 +1,4 @@ -import type { SlickGrid } from './index'; +import type { SlickGridUniversal } from './index'; export interface DragPosition { startX: number; @@ -25,7 +25,7 @@ export interface DragRowMove { deltaY: number; drag: HTMLElement; drop: any[]; - grid: SlickGrid; + grid: SlickGridUniversal; guide: HTMLElement; insertBefore: number; offsetX: number; diff --git a/packages/common/src/interfaces/draggableGrouping.interface.ts b/packages/common/src/interfaces/draggableGrouping.interface.ts index a939a3e5e..d19157302 100644 --- a/packages/common/src/interfaces/draggableGrouping.interface.ts +++ b/packages/common/src/interfaces/draggableGrouping.interface.ts @@ -1,4 +1,6 @@ -import type { Grouping, SlickEventData } from './index'; +import type { SlickEventData } from 'slickgrid'; + +import type { Grouping } from './index'; import type { DraggableGroupingOption } from './draggableGroupingOption.interface'; import type { SlickDraggableGrouping } from '../extensions/slickDraggableGrouping'; diff --git a/packages/common/src/interfaces/editor.interface.ts b/packages/common/src/interfaces/editor.interface.ts index 9fdfc89ab..43754a5be 100644 --- a/packages/common/src/interfaces/editor.interface.ts +++ b/packages/common/src/interfaces/editor.interface.ts @@ -1,5 +1,4 @@ -import type { EditorArguments } from './editorArguments.interface'; -import type { EditorValidationResult } from './editorValidationResult.interface'; +import type { EditorArguments, EditorValidationResult } from './index'; /** * SlickGrid Editor interface, more info can be found on the SlickGrid repo diff --git a/packages/common/src/interfaces/editorArguments.interface.ts b/packages/common/src/interfaces/editorArguments.interface.ts index f0007385b..2df4c20f1 100644 --- a/packages/common/src/interfaces/editorArguments.interface.ts +++ b/packages/common/src/interfaces/editorArguments.interface.ts @@ -1,4 +1,6 @@ -import type { Column, CompositeEditorOption, ElementPosition, SlickDataView, SlickGrid } from './index'; +import type { SlickDataView } from 'slickgrid'; + +import type { Column, CompositeEditorOption, ElementPosition, SlickGridUniversal } from './index'; import type { PositionMethod } from '../enums/positionMethod.type'; export interface EditorArguments { @@ -18,7 +20,7 @@ export interface EditorArguments { event: Event; /** Slick Grid object */ - grid: SlickGrid; + grid: SlickGridUniversal; /** Grid Position */ gridPosition: ElementPosition; diff --git a/packages/common/src/interfaces/excelCopyBufferOption.interface.ts b/packages/common/src/interfaces/excelCopyBufferOption.interface.ts index a5160d161..89360260d 100644 --- a/packages/common/src/interfaces/excelCopyBufferOption.interface.ts +++ b/packages/common/src/interfaces/excelCopyBufferOption.interface.ts @@ -1,9 +1,6 @@ -import type { - Column, - CellRange, - FormatterResultObject, - SlickEventData, -} from './index'; +import { SlickEventData } from 'slickgrid'; + +import type { Column, CellRange, FormatterResultObject, } from './index'; import type { SlickCellExcelCopyManager, } from '../extensions/slickCellExcelCopyManager'; export interface ExcelCopyBufferOption { diff --git a/packages/common/src/interfaces/externalResource.interface.ts b/packages/common/src/interfaces/externalResource.interface.ts index b268b89cb..cfa228c29 100644 --- a/packages/common/src/interfaces/externalResource.interface.ts +++ b/packages/common/src/interfaces/externalResource.interface.ts @@ -1,4 +1,4 @@ -import type { SlickGrid } from './slickGrid.interface'; +import type { SlickGridUniversal } from './index'; import type { ContainerService } from '../services/index'; export interface ExternalResource { @@ -6,7 +6,7 @@ export interface ExternalResource { className?: string; /** Initialize the External Resource (Component or Service) */ - init?: (grid: SlickGrid, container: ContainerService) => void; + init?: (grid: SlickGridUniversal, container: ContainerService) => void; /** Dispose method */ dispose?: () => void; diff --git a/packages/common/src/interfaces/filter.interface.ts b/packages/common/src/interfaces/filter.interface.ts index f4732bddc..3ee637782 100644 --- a/packages/common/src/interfaces/filter.interface.ts +++ b/packages/common/src/interfaces/filter.interface.ts @@ -1,4 +1,4 @@ -import type { Column, FilterArguments, FilterCallback, SlickGrid } from './index'; +import type { Column, FilterArguments, FilterCallback, SlickGridUniversal } from './index'; import type { OperatorType, OperatorString, SearchTerm, } from '../enums/index'; // export type Filter = (searchTerms: string | number | string[] | number[], columnDef: Column, params?: any) => string; @@ -12,7 +12,7 @@ export interface Filter { callback: FilterCallback; /** SlickGrid grid object */ - grid: SlickGrid; + grid: SlickGridUniversal; /** The default search operator for the filter when not provided */ defaultOperator?: OperatorString | OperatorType; diff --git a/packages/common/src/interfaces/filterArguments.interface.ts b/packages/common/src/interfaces/filterArguments.interface.ts index 056353068..991884b00 100644 --- a/packages/common/src/interfaces/filterArguments.interface.ts +++ b/packages/common/src/interfaces/filterArguments.interface.ts @@ -1,8 +1,8 @@ -import type { Column, FilterCallback, SlickGrid } from './index'; +import type { Column, FilterCallback, SlickGridUniversal } from './index'; import type { OperatorString, OperatorType, SearchTerm } from '../enums/index'; export interface FilterArguments { - grid: SlickGrid; + grid: SlickGridUniversal; columnDef: Column; callback: FilterCallback; operator?: OperatorType | OperatorString; diff --git a/packages/common/src/interfaces/filterCallback.interface.ts b/packages/common/src/interfaces/filterCallback.interface.ts index e5d75d0d2..88f5892ef 100644 --- a/packages/common/src/interfaces/filterCallback.interface.ts +++ b/packages/common/src/interfaces/filterCallback.interface.ts @@ -1,4 +1,4 @@ -import type { Column, SlickEventData } from './index'; +import type { Column } from './index'; import type { OperatorString, OperatorType, SearchTerm } from '../enums/index'; export interface FilterCallbackArg { @@ -27,4 +27,4 @@ export interface FilterCallbackArg { shouldTriggerQuery?: boolean; } -export type FilterCallback = (e: Event | SlickEventData | undefined, args: FilterCallbackArg) => void; +export type FilterCallback = (e: Event | undefined, args: FilterCallbackArg) => void; diff --git a/packages/common/src/interfaces/filterChangedArgs.interface.ts b/packages/common/src/interfaces/filterChangedArgs.interface.ts index 7b4ceba25..b09da7466 100644 --- a/packages/common/src/interfaces/filterChangedArgs.interface.ts +++ b/packages/common/src/interfaces/filterChangedArgs.interface.ts @@ -1,15 +1,14 @@ -import type { Column } from './column.interface'; import type { ColumnFilters } from './columnFilters.interface'; import type { OperatorType } from '../enums/operatorType.enum'; import type { OperatorString } from '../enums/operatorString.type'; import type { SearchTerm } from '../enums/searchTerm.type'; -import type { SlickGrid } from './slickGrid.interface'; +import type { Column, SlickGridUniversal } from './index'; export interface FilterChangedArgs { clearFilterTriggered?: boolean; columnDef: Column; columnFilters: ColumnFilters; - grid: SlickGrid; + grid: SlickGridUniversal; operator: OperatorType | OperatorString; searchTerms: SearchTerm[]; shouldTriggerQuery?: boolean; diff --git a/packages/common/src/interfaces/formatter.interface.ts b/packages/common/src/interfaces/formatter.interface.ts index 6ac071bbf..17cbf9efd 100644 --- a/packages/common/src/interfaces/formatter.interface.ts +++ b/packages/common/src/interfaces/formatter.interface.ts @@ -1,5 +1,3 @@ -import type { Column } from './column.interface'; -import type { FormatterResultObject } from './formatterResultObject.interface'; -import type { SlickGrid } from './slickGrid.interface'; +import type { Column, FormatterResultObject, SlickGridUniversal } from './index'; -export declare type Formatter = (row: number, cell: number, value: any, columnDef: Column, dataContext: T, grid: SlickGrid) => string | FormatterResultObject; +export declare type Formatter = (row: number, cell: number, value: any, columnDef: Column, dataContext: T, grid: SlickGridUniversal) => string | FormatterResultObject; diff --git a/packages/common/src/interfaces/gridMenu.interface.ts b/packages/common/src/interfaces/gridMenu.interface.ts index 53304be6c..8f2ae0b4a 100644 --- a/packages/common/src/interfaces/gridMenu.interface.ts +++ b/packages/common/src/interfaces/gridMenu.interface.ts @@ -2,7 +2,7 @@ import type { Column, GridMenuOption, GridMenuCommandItemCallbackArgs, - SlickGrid, + SlickGridUniversal, } from './index'; import type { SlickGridMenu } from '../extensions/slickGridMenu'; @@ -40,7 +40,7 @@ export interface GridMenuEventBaseCallbackArgs { visibleColumns: Column[]; /** slick grid object */ - grid: SlickGrid; + grid: SlickGridUniversal; } export interface GridMenuEventWithElementCallbackArgs extends GridMenuEventBaseCallbackArgs { diff --git a/packages/common/src/interfaces/gridMenuCommandItemCallbackArgs.interface.ts b/packages/common/src/interfaces/gridMenuCommandItemCallbackArgs.interface.ts index 40b9f6922..7ebbf1ea9 100644 --- a/packages/common/src/interfaces/gridMenuCommandItemCallbackArgs.interface.ts +++ b/packages/common/src/interfaces/gridMenuCommandItemCallbackArgs.interface.ts @@ -1,8 +1,8 @@ -import type { Column, SlickGrid } from '.'; +import type { Column, SlickGridUniversal } from './index'; import type { MenuCommandItem } from './menuCommandItem.interface'; export interface GridMenuCallbackArgs { - grid: SlickGrid; + grid: SlickGridUniversal; menu: any; columns: Column[]; visibleColumns: Column[] @@ -16,7 +16,7 @@ export interface GridMenuCommandItemCallbackArgs { item: MenuCommandItem; /** Slick Grid object */ - grid: SlickGrid; + grid: SlickGridUniversal; /** all columns (including hidden ones) */ allColumns: Column[], diff --git a/packages/common/src/interfaces/gridMenuOption.interface.ts b/packages/common/src/interfaces/gridMenuOption.interface.ts index 20aa6171a..fb0ab564c 100644 --- a/packages/common/src/interfaces/gridMenuOption.interface.ts +++ b/packages/common/src/interfaces/gridMenuOption.interface.ts @@ -160,6 +160,6 @@ export interface GridMenuOption { /** Callback method to override the column name output used by the ColumnPicker/GridMenu. */ headerColumnValueExtractor?: (column: Column, gridOptions?: GridOption) => string; - /** Callback method that user can override to make the menu usable or not (the menu will not be showm when not considered usable). */ - menuUsabilityOverride?: (args: MenuCallbackArgs) => boolean; + /** Callback method that user can override the default behavior of enabling/disabling an item from the list. */ + menuUsabilityOverride?: (args: MenuCallbackArgs) => boolean; } diff --git a/packages/common/src/interfaces/gridOption.interface.ts b/packages/common/src/interfaces/gridOption.interface.ts index 56cd75a93..675b33042 100644 --- a/packages/common/src/interfaces/gridOption.interface.ts +++ b/packages/common/src/interfaces/gridOption.interface.ts @@ -1,4 +1,5 @@ import type { EventNamingStyle } from '@slickgrid-universal/event-pub-sub'; +import type { GridOption as GridOptionCore, SlickEditorLock } from 'slickgrid'; import type { AutoResizeOption, @@ -37,10 +38,11 @@ import type { TextExportOption, TreeDataOption, } from './index'; -import type { ColumnReorderFunction, GridAutosizeColsMode, OperatorType, OperatorString, } from '../enums/index'; +import type { GridAutosizeColsMode, OperatorType, OperatorString, } from '../enums/index'; import type { TranslaterService } from '../services/translater.service'; -export interface GridOption { +export interface GridOption extends GridOptionCore { + // alwaysAllowHorizontalScroll?: boolean; /** CSS class name used on newly added row */ addNewRowCssClass?: string; @@ -181,12 +183,12 @@ export interface GridOption { customTooltip?: CustomTooltipOption; /** Data item column value extractor (getter) that can be used by the Excel like copy buffer plugin */ - dataItemColumnValueExtractor?: (item: any, columnDef: Column) => any; + dataItemColumnValueExtractor?: null | ((item: any, columnDef: C) => any); /** Data item column value setter that can be used by the Excel like copy buffer plugin */ - dataItemColumnValueSetter?: (item: any, columnDef: Column, value: any) => void; + dataItemColumnValueSetter?: (item: any, columnDef: C, value: any) => void; - /** Unique property name on the dataset used by Slick.Data.DataView */ + /** Unique property name on the dataset used by SlickDataView */ datasetIdPropertyName?: string; /** Some of the SlickGrid DataView options */ @@ -240,13 +242,13 @@ export interface GridOption { editable?: boolean; /** option to intercept edit commands and implement undo support. */ - editCommandHandler?: (item: any, column: Column, command: EditCommand) => void; + editCommandHandler?: (item: any, column: C, command: EditCommand) => void; /** Editor classes factory */ editorFactory?: any; /** a global singleton editor lock. */ - editorLock?: any; + editorLock?: SlickEditorLock; /** Default to 450ms and only applies to Composite Editor, how long to wait until we start validating the editor changes on Editor that support it (integer, float, text, longText). */ editorTypingDebounce?: number; @@ -298,7 +300,7 @@ export interface GridOption { * When provided as a boolean, it will permits the user to move an entire column from a position to another. * We could also provide a Column Reorder function, there's mostly only 1 use for this which is the SlickDraggableGrouping plugin. */ - enableColumnReorder?: boolean | ColumnReorderFunction; + // enableColumnReorder?: boolean | ColumnReorderFunction; /** * Defaults to true, when doing a double-click in the column resize section (top right of a column when the mouse resize icon shows up), @@ -422,6 +424,9 @@ export interface GridOption { */ filterTypingDebounce?: number; + /** Firefox max supported CSS height */ + ffMaxSupportedCssHeight?: number; + /** Defaults to 25, which is the grid footer row panel height */ footerRowHeight?: number; @@ -432,7 +437,7 @@ export interface GridOption { forceSyncScrolling?: boolean; /** Formatter classes factory */ - formatterFactory?: any; + // formatterFactory?: { getFormatter: (col: C) => Formatter; } | null; /** Formatter commonly used options defined for the entire grid */ formatterOptions?: FormatterOption; @@ -521,6 +526,9 @@ export interface GridOption { /** Do we leave space for new rows in the DOM visible buffer */ leaveSpaceForNewRows?: boolean; + /** Max supported CSS height */ + maxSupportedCssHeight?: number; + /** What is the minimum row buffer to use? */ minRowBuffer?: number; @@ -598,6 +606,9 @@ export interface GridOption { */ sanitizer?: (dirtyHtml: string) => string; + /** Defaults to 50, render throttling when scrolling large dataset */ + scrollRenderThrottling?: number; + /** CSS class name used when cell is selected */ selectedCellCssClass?: string; diff --git a/packages/common/src/interfaces/groupTotalsFormatter.interface.ts b/packages/common/src/interfaces/groupTotalsFormatter.interface.ts index d1dda36c9..cbdc48a67 100644 --- a/packages/common/src/interfaces/groupTotalsFormatter.interface.ts +++ b/packages/common/src/interfaces/groupTotalsFormatter.interface.ts @@ -1,4 +1,3 @@ -import type { Column } from './column.interface'; -import type { SlickGrid } from './slickGrid.interface'; +import type { Column, SlickGridUniversal } from './index'; -export type GroupTotalsFormatter = (totals: any, columnDef: Column, grid: SlickGrid) => string; +export type GroupTotalsFormatter = (totals: any, columnDef: Column, grid: SlickGridUniversal) => string; diff --git a/packages/common/src/interfaces/headerButtonItem.interface.ts b/packages/common/src/interfaces/headerButtonItem.interface.ts index 58254762c..342710583 100644 --- a/packages/common/src/interfaces/headerButtonItem.interface.ts +++ b/packages/common/src/interfaces/headerButtonItem.interface.ts @@ -1,5 +1,4 @@ -import type { Column } from './column.interface'; -import type { SlickGrid } from './slickGrid.interface'; +import type { Column, SlickGridUniversal } from './index'; export interface HeaderButtonItem { /** A command identifier to be passed to the onCommand event handlers. */ @@ -24,11 +23,11 @@ export interface HeaderButtonItem { // action/override callbacks /** Optionally define a callback function that gets executed when item is chosen (and/or use the onCommand event) */ - action?: (event: Event, callbackArgs: { command: string; button: any; column: Column; grid: SlickGrid; }) => void; + action?: (event: Event, callbackArgs: { command: string; button: any; column: Column; grid: SlickGridUniversal; }) => void; /** Callback method that user can override the default behavior of showing/hiding an item from the list. */ - itemVisibilityOverride?: (args: { node: any; column: Column; grid: SlickGrid; }) => boolean; + itemVisibilityOverride?: (args: { node: any; column: Column; grid: SlickGridUniversal; }) => boolean; /** Callback method that user can override the default behavior of enabling/disabling an item from the list. */ - itemUsabilityOverride?: (args: { node: any; column: Column; grid: SlickGrid; }) => boolean; + itemUsabilityOverride?: (args: { node: any; column: Column; grid: SlickGridUniversal; }) => boolean; } diff --git a/packages/common/src/interfaces/headerButtonOnCommandArgs.interface.ts b/packages/common/src/interfaces/headerButtonOnCommandArgs.interface.ts index c2db296e8..81deac08f 100644 --- a/packages/common/src/interfaces/headerButtonOnCommandArgs.interface.ts +++ b/packages/common/src/interfaces/headerButtonOnCommandArgs.interface.ts @@ -1,9 +1,7 @@ -import type { Column } from './column.interface'; -import type { HeaderButtonItem } from './headerButtonItem.interface'; -import type { SlickGrid } from './slickGrid.interface'; +import type { Column, HeaderButtonItem, SlickGridUniversal } from './index'; export interface HeaderButtonOnCommandArgs { - grid: SlickGrid; + grid: SlickGridUniversal; column: Column; command: string; button: HeaderButtonItem; diff --git a/packages/common/src/interfaces/headerMenu.interface.ts b/packages/common/src/interfaces/headerMenu.interface.ts index 02e5c1923..319266da9 100644 --- a/packages/common/src/interfaces/headerMenu.interface.ts +++ b/packages/common/src/interfaces/headerMenu.interface.ts @@ -1,10 +1,9 @@ -import type { MenuCommandItem } from '../index'; +import type { MenuCommandItem, SlickGridUniversal } from '../index'; import type { SlickHeaderMenu } from '../extensions/slickHeaderMenu'; import type { Column, HeaderMenuOption, MenuCommandItemCallbackArgs, - SlickGrid, } from './index'; export interface HeaderMenuCommandItemCallbackArgs { @@ -12,7 +11,7 @@ export interface HeaderMenuCommandItemCallbackArgs { column: Column; /** Slick Grid object */ - grid: SlickGrid; + grid: SlickGridUniversal; /** html DOM element of the menu */ menu: Array; diff --git a/packages/common/src/interfaces/headerMenuOption.interface.ts b/packages/common/src/interfaces/headerMenuOption.interface.ts index 35c7925df..c709259db 100644 --- a/packages/common/src/interfaces/headerMenuOption.interface.ts +++ b/packages/common/src/interfaces/headerMenuOption.interface.ts @@ -1,4 +1,4 @@ -import type { Column, SlickGrid } from './index'; +import type { Column, SlickGridUniversal } from './index'; export interface HeaderMenuOption { /** Auto-align drop menu to the left when not enough viewport space to show on the right */ @@ -83,5 +83,5 @@ export interface HeaderMenuOption { // Methods /** Callback method that user can override the default behavior of enabling/disabling an item from the list. */ - menuUsabilityOverride?: (args: { grid: SlickGrid, column: Column, menu: HTMLElement }) => boolean; + menuUsabilityOverride?: (args: { grid: SlickGridUniversal, column: Column, menu: HTMLElement }) => boolean; } diff --git a/packages/common/src/interfaces/index.ts b/packages/common/src/interfaces/index.ts index 2fc862f1f..e404c0655 100644 --- a/packages/common/src/interfaces/index.ts +++ b/packages/common/src/interfaces/index.ts @@ -137,14 +137,10 @@ export * from './selectOption.interface'; export * from './servicePagination.interface'; export * from './singleColumnSort.interface'; export * from './slickCompositeEditor.interface'; -export * from './slickDataView.interface'; export * from './slickEditorLock.interface'; -export * from './slickEvent.interface'; -export * from './slickEventData.interface'; -export * from './slickGrid.interface'; -export * from './slickEventHandler.interface'; +export * from './slickGridUniversal.interface'; export * from './slickGroup.interface'; -export * from './slickNamespace.interface'; +export * from './slickPlugin.interface'; export * from './slickRange.interface'; export * from './slickRemoteModel.interface'; export * from './slickResizer.interface'; diff --git a/packages/common/src/interfaces/itemMetadata.interface.ts b/packages/common/src/interfaces/itemMetadata.interface.ts index b6d55a1eb..8f708b24b 100644 --- a/packages/common/src/interfaces/itemMetadata.interface.ts +++ b/packages/common/src/interfaces/itemMetadata.interface.ts @@ -15,7 +15,7 @@ export interface ItemMetadata { focusable?: boolean; /** A custom group formatter. */ - formatter?: GroupTotalsFormatter; + formatter?: GroupTotalsFormatter | Formatter; /** Whether or not a row or any cells in it can be selected. */ selectable?: boolean; diff --git a/packages/common/src/interfaces/menuCallbackArgs.interface.ts b/packages/common/src/interfaces/menuCallbackArgs.interface.ts index 9758fa6b4..01aed76ba 100644 --- a/packages/common/src/interfaces/menuCallbackArgs.interface.ts +++ b/packages/common/src/interfaces/menuCallbackArgs.interface.ts @@ -1,5 +1,4 @@ -import type { Column } from './column.interface'; -import type { SlickGrid } from './slickGrid.interface'; +import type { Column, SlickGridUniversal } from './index'; export interface MenuCallbackArgs { /** Cell or column index */ @@ -9,7 +8,7 @@ export interface MenuCallbackArgs { row?: number; /** Reference to the grid. */ - grid: SlickGrid; + grid: SlickGridUniversal; /** Cell Column definition */ column: Column; diff --git a/packages/common/src/interfaces/menuCommandItem.interface.ts b/packages/common/src/interfaces/menuCommandItem.interface.ts index 4028d78d8..0d1f42e44 100644 --- a/packages/common/src/interfaces/menuCommandItem.interface.ts +++ b/packages/common/src/interfaces/menuCommandItem.interface.ts @@ -1,7 +1,4 @@ -import type { MenuItem } from './menuItem.interface'; -import type { MenuCommandItemCallbackArgs } from './menuCommandItemCallbackArgs.interface'; -import type { SlickEventData } from './slickEventData.interface'; -import type { MenuCallbackArgs } from './menuCallbackArgs.interface'; +import type { MenuCallbackArgs, MenuCommandItemCallbackArgs, MenuItem } from './index'; export interface MenuCommandItem extends MenuItem { /** A command identifier to be passed to the onCommand event callback handler (when using "commandItems"). */ @@ -14,5 +11,5 @@ export interface MenuCommandItem void; + action?: (event: any, callbackArgs: A) => void; } diff --git a/packages/common/src/interfaces/menuFromCellCallbackArgs.interface.ts b/packages/common/src/interfaces/menuFromCellCallbackArgs.interface.ts index e76a148a0..d9bbb11fe 100644 --- a/packages/common/src/interfaces/menuFromCellCallbackArgs.interface.ts +++ b/packages/common/src/interfaces/menuFromCellCallbackArgs.interface.ts @@ -1,5 +1,4 @@ -import type { Column } from './column.interface'; -import type { SlickGrid } from './slickGrid.interface'; +import type { Column, SlickGridUniversal } from './index'; export interface MenuFromCellCallbackArgs { /** Grid cell/column index */ @@ -9,7 +8,7 @@ export interface MenuFromCellCallbackArgs { row: number; /** Reference to the grid. */ - grid: SlickGrid; + grid: SlickGridUniversal; } export interface MenuFromCellWithColumnCallbackArgs extends MenuFromCellCallbackArgs { diff --git a/packages/common/src/interfaces/multiColumnSort.interface.ts b/packages/common/src/interfaces/multiColumnSort.interface.ts index 8e03590e7..3b59c87cc 100644 --- a/packages/common/src/interfaces/multiColumnSort.interface.ts +++ b/packages/common/src/interfaces/multiColumnSort.interface.ts @@ -1,9 +1,8 @@ -import type { ColumnSort } from './columnSort.interface'; -import type { SlickGrid } from './slickGrid.interface'; +import type { ColumnSort, SlickGridUniversal } from './index'; export interface MultiColumnSort { /** SlickGrid grid object */ - grid: SlickGrid; + grid: SlickGridUniversal; /** is it a multi-column sort? */ multiColumnSort: true; diff --git a/packages/common/src/interfaces/onEventArgs.interface.ts b/packages/common/src/interfaces/onEventArgs.interface.ts index e92bba98f..718d6dfef 100644 --- a/packages/common/src/interfaces/onEventArgs.interface.ts +++ b/packages/common/src/interfaces/onEventArgs.interface.ts @@ -1,6 +1,5 @@ -import type { Column } from './column.interface'; -import type { SlickDataView } from './slickDataView.interface'; -import type { SlickGrid } from './slickGrid.interface'; +import type { SlickDataView } from 'slickgrid'; +import type { Column, SlickGridUniversal } from './index'; export interface OnEventArgs { row: number; @@ -8,5 +7,5 @@ export interface OnEventArgs { columnDef: Column; dataContext: any; dataView: SlickDataView; - grid: SlickGrid; + grid: SlickGridUniversal; } diff --git a/packages/common/src/interfaces/pagingInfo.interface.ts b/packages/common/src/interfaces/pagingInfo.interface.ts index 0ebc6e3b5..ce63b383b 100644 --- a/packages/common/src/interfaces/pagingInfo.interface.ts +++ b/packages/common/src/interfaces/pagingInfo.interface.ts @@ -1,4 +1,4 @@ -import type { SlickDataView } from './slickDataView.interface'; +import type { SlickDataView } from 'slickgrid'; export interface PagingInfo { /** Page size number */ diff --git a/packages/common/src/interfaces/resizer.interface.ts b/packages/common/src/interfaces/resizer.interface.ts index 365d99e11..31cbbc486 100644 --- a/packages/common/src/interfaces/resizer.interface.ts +++ b/packages/common/src/interfaces/resizer.interface.ts @@ -1,8 +1,9 @@ +import type { SlickEventData } from 'slickgrid'; + import type { GridSize, ResizerOption, - SlickEventData, - SlickGrid, + SlickGridUniversal, SlickResizer, } from './index'; @@ -14,8 +15,8 @@ export interface Resizer extends ResizerOption { onExtensionRegistered?: (plugin: SlickResizer) => void; /** triggered before rows are being moved */ - onGridAfterResize?: (e: SlickEventData, args: { grid: SlickGrid; dimensions: GridSize; }) => void; + onGridAfterResize?: (e: SlickEventData, args: { grid: SlickGridUniversal; dimensions: GridSize; }) => void; /** triggered when rows are being moved */ - onGridBeforeResize?: (e: SlickEventData, args: { grid: SlickGrid; }) => void; + onGridBeforeResize?: (e: SlickEventData, args: { grid: SlickGridUniversal; }) => void; } diff --git a/packages/common/src/interfaces/rowDetailView.interface.ts b/packages/common/src/interfaces/rowDetailView.interface.ts index d529bc7ee..2a2aa6c88 100644 --- a/packages/common/src/interfaces/rowDetailView.interface.ts +++ b/packages/common/src/interfaces/rowDetailView.interface.ts @@ -1,4 +1,6 @@ -import type { RowDetailViewOption, SlickEventData, SlickGrid, SlickRowDetailView } from './index'; +import type { SlickEventData } from 'slickgrid'; + +import type { RowDetailViewOption, SlickGridUniversal, SlickRowDetailView } from './index'; export interface RowDetailView extends RowDetailViewOption { // -- @@ -8,83 +10,107 @@ export interface RowDetailView extends RowDetailViewOption { onExtensionRegistered?: (plugin: SlickRowDetailView) => void; /** This event must be used with the "notify" by the end user once the Asynchronous Server call returns the item detail */ - onAsyncResponse?: (e: SlickEventData, args: { - /** Item data context object */ - item: any; - - /** An explicit view to use instead of template (Optional) */ - detailView?: any; - }) => void; + onAsyncResponse?: (e: SlickEventData, args: OnRowDetailAsyncResponseArgs) => void; /** Fired when the async response finished */ - onAsyncEndUpdate?: (e: SlickEventData, args: { - /** Item data context object */ - item: any; + onAsyncEndUpdate?: (e: SlickEventData, args: OnRowDetailAsyncEndUpdateArgs) => void; + + /** Fired after the row detail gets toggled */ + onAfterRowDetailToggle?: (e: SlickEventData, args: OnAfterRowDetailToggleArgs) => void; - /** Reference to the Slick grid object */ - grid: SlickGrid; - }) => void; + /** Fired before the row detail gets toggled */ + onBeforeRowDetailToggle?: (e: SlickEventData, args: OnBeforeRowDetailToggleArgs) => void; /** Fired after the row detail gets toggled */ - onAfterRowDetailToggle?: (e: SlickEventData, args: { - /** Item data context object */ - item: any; + onRowBackToViewportRange?: (e: SlickEventData, args: OnRowBackToViewportRangeArgs) => void; - /** Array of the Expanded Row Ids */ - expandedRows: Array; + /** Fired after a row becomes out of viewport range (user can't see the row anymore) */ + onRowOutOfViewportRange?: (e: SlickEventData, args: OnRowOutOfViewportRangeArgs) => void; +} - /** Reference to the Slick grid object */ - grid: SlickGrid; - }) => void; +/** This event must be used with the "notify" by the end user once the Asynchronous Server call returns the item detail */ +export interface OnRowDetailAsyncResponseArgs { + /** Item data context object */ + item: any; - /** Fired before the row detail gets toggled */ - onBeforeRowDetailToggle?: (e: SlickEventData, args: { - /** Item data context object */ - item: any; + /** @alias `item` */ + itemDetail: any; - /** Reference to the Slick grid object */ - grid: SlickGrid; - }) => void; + /** An explicit view to use instead of template (Optional) */ + detailView?: any; +} - /** Fired after the row detail gets toggled */ - onRowBackToViewportRange?: (e: SlickEventData, args: { - /** Item data context object */ - item: any; +/** Fired when the async response finished */ +export interface OnRowDetailAsyncEndUpdateArgs { + /** Item data context object */ + item: any; + + /** @alias `item` */ + itemDetail: any; - /** Id of the Row object (datacontext) in the Grid */ - rowId: string | number; + /** Reference to the Slick grid object */ + grid: SlickGridUniversal; +} - /** Index of the Row in the Grid */ - rowIndex: number; +/** Fired after the row detail gets toggled */ +export interface OnAfterRowDetailToggleArgs { + /** Item data context object */ + item: any; - /** Array of the Expanded Row Ids */ - expandedRows: Array; + /** Array of the Expanded Row Ids */ + expandedRows: Array; - /** Array of the Out of viewport Range Rows */ - rowIdsOutOfViewport: Array; + /** Reference to the Slick grid object */ + grid: SlickGridUniversal; +} - /** Reference to the Slick grid object */ - grid: SlickGrid; - }) => void; +/** Fired before the row detail gets toggled */ +export interface OnBeforeRowDetailToggleArgs { + /** Item data context object */ + item: any; - /** Fired after a row becomes out of viewport range (user can't see the row anymore) */ - onRowOutOfViewportRange?: (e: SlickEventData, args: { - /** Item data context object */ - item: any; + /** Reference to the Slick grid object */ + grid: SlickGridUniversal; +} + +/** Fired after the row detail gets toggled */ +export interface OnRowBackToViewportRangeArgs { + /** Item data context object */ + item: any; - /** Id of the Row object (datacontext) in the Grid */ - rowId: string | number; + /** Id of the Row object (datacontext) in the Grid */ + rowId: string | number; - /** Index of the Row in the Grid */ - rowIndex: number; + /** Index of the Row in the Grid */ + rowIndex: number; - /** Array of the Expanded Row Ids */ - expandedRows: Array; + /** Array of the Expanded Row Ids */ + expandedRows: Array; - /** Array of the Out of viewport Range Rows */ - rowIdsOutOfViewport: Array; + /** Array of the Out of viewport Range Rows */ + rowIdsOutOfViewport: Array; - /** Reference to the Slick grid object */ - grid: SlickGrid; - }) => void; + /** Reference to the Slick grid object */ + grid: SlickGridUniversal; } + +/** Fired after a row becomes out of viewport range (user can't see the row anymore) */ +export interface OnRowOutOfViewportRangeArgs { + /** Item data context object */ + item: any; + + /** Id of the Row object (datacontext) in the Grid */ + rowId: string | number; + + /** Index of the Row in the Grid */ + rowIndex: number; + + /** Array of the Expanded Row Ids */ + expandedRows: Array; + + /** Array of the Out of viewport Range Rows */ + rowIdsOutOfViewport: Array; + + /** Reference to the Slick grid object */ + grid: SlickGridUniversal; +} \ No newline at end of file diff --git a/packages/common/src/interfaces/rowMoveManager.interface.ts b/packages/common/src/interfaces/rowMoveManager.interface.ts index dc3930d37..2eeeaf860 100644 --- a/packages/common/src/interfaces/rowMoveManager.interface.ts +++ b/packages/common/src/interfaces/rowMoveManager.interface.ts @@ -1,8 +1,6 @@ -import type { - RowMoveManagerOption, - SlickEventData, - SlickGrid, -} from './index'; +import type { SlickEventData } from 'slickgrid'; + +import type { RowMoveManagerOption, SlickGridUniversal } from './index'; import type { SlickRowMoveManager } from '../extensions/slickRowMoveManager'; export interface RowMoveManager extends RowMoveManagerOption { @@ -13,8 +11,8 @@ export interface RowMoveManager extends RowMoveManagerOption { onExtensionRegistered?: (plugin: SlickRowMoveManager) => void; /** SlickGrid Event fired before the row is moved. */ - onBeforeMoveRows?: (e: SlickEventData, args: { grid: SlickGrid; rows: number[]; insertBefore: number; }) => boolean | void; + onBeforeMoveRows?: (e: MouseEvent | TouchEvent | SlickEventData, args: { grid: SlickGridUniversal; rows: number[]; insertBefore: number; }) => boolean | void; /** SlickGrid Event fired while the row is moved. */ - onMoveRows?: (e: SlickEventData, args: { grid: SlickGrid; rows: number[]; insertBefore: number; }) => void; + onMoveRows?: (e: SlickEventData, args: { grid: SlickGridUniversal; rows: number[]; insertBefore: number; }) => void; } diff --git a/packages/common/src/interfaces/selectableOverrideCallback.interface.ts b/packages/common/src/interfaces/selectableOverrideCallback.interface.ts index 785091971..fee9b3f49 100644 --- a/packages/common/src/interfaces/selectableOverrideCallback.interface.ts +++ b/packages/common/src/interfaces/selectableOverrideCallback.interface.ts @@ -1,4 +1,4 @@ -import type { SlickGrid } from './slickGrid.interface'; +import type { SlickGridUniversal } from './index'; /** Method that user can pass to override the default behavior or making every row a selectable row. */ export type SelectableOverrideCallback = ( @@ -9,5 +9,5 @@ export type SelectableOverrideCallback = ( dataContext: T, /** SlickGrid object */ - grid: SlickGrid + grid: SlickGridUniversal ) => boolean; diff --git a/packages/common/src/interfaces/singleColumnSort.interface.ts b/packages/common/src/interfaces/singleColumnSort.interface.ts index 95ac16c54..1a4068dbf 100644 --- a/packages/common/src/interfaces/singleColumnSort.interface.ts +++ b/packages/common/src/interfaces/singleColumnSort.interface.ts @@ -1,9 +1,8 @@ -import type { ColumnSort } from './columnSort.interface'; -import type { SlickGrid } from './slickGrid.interface'; +import type { ColumnSort, SlickGridUniversal } from './index'; export interface SingleColumnSort extends ColumnSort { /** SlickGrid grid object */ - grid?: SlickGrid; + grid?: SlickGridUniversal; /** is it a multi-column sort? */ multiColumnSort?: false; diff --git a/packages/common/src/interfaces/slickDataView.interface.ts b/packages/common/src/interfaces/slickDataView.interface.ts deleted file mode 100644 index 8310fbb79..000000000 --- a/packages/common/src/interfaces/slickDataView.interface.ts +++ /dev/null @@ -1,286 +0,0 @@ -import type { - Grouping, - ItemMetadata, - PagingInfo, - SlickEvent, - SlickGrid -} from './index'; - -export type FilterFn = (item: T, args: any) => boolean; - -export interface SlickDataView { - // -- - // Slick DataView Available Methods - - /** Add an item to the DataView */ - addItem(item: any): void; - - /** Add multiple items to the DataView */ - addItems(items: any[]): void; - - /** - * Begin Data Update Transaction - * @param {Boolean} isBulkUpdate - are we doing a bulk update transactions? Defaults to false - */ - beginUpdate(isBulkUpdate?: boolean): void; - - /** Destroy (dispose) of Slick DataView */ - destroy(): void; - - /** Collapse all Groups, optionally pass a level number to only collapse that level */ - collapseAllGroups(level?: number): void; - - /** - * Collapse a Group by passing either a Slick.Group's "groupingKey" property, or a - * variable argument list of grouping values denoting a unique path to the row. - * For example, calling collapseGroup('high', '10%') will collapse the '10%' subgroup of the 'high' group. - */ - collapseGroup(...args: any): void; - - /** Delete an item from the DataView identified by its id */ - deleteItem(id: string | number): void; - - /** Delete multiple items from the DataView identified by their given ids */ - deleteItems(ids: Array): void; - - /** End Data Update Transaction */ - endUpdate(): void; - - /** Expand all Groups, optionally pass a level number to only expand that level */ - expandAllGroups(level?: number): void; - - /** Expand or Collapse all Groups */ - expandCollapseAllGroups(level: number, collapse: boolean): void; - - /** Expand or Collapse a specific Group by its grouping key */ - expandCollapseGroup(level: number, groupingKey: string | number, collapse: boolean): void; - - /** - * Expand a Group by passing either a Slick.Group's "groupingKey" property, or a - * variable argument list of grouping values denoting a unique path to the row. - * For example, calling collapseGroup('high', '10%') will collapse the '10%' subgroup of the 'high' group. - */ - expandGroup(...args: any): void; - - /** - * Provides a workaround for the extremely slow sorting in IE. - * Does a [lexicographic] sort on a give column by temporarily overriding Object.prototype.toString - * to return the value of that field and then doing a native Array.sort(). - */ - // eslint-disable-next-line @typescript-eslint/ban-types - fastSort(field: string | Function, ascending: boolean): void; - - /** Get current Filter used by the DataView */ - getFilter(): FilterFn; - - /** Get only the DataView filtered items */ - getFilteredItems: () => T[]; - - /** Get the array length (count) of only the DataView filtered items */ - getFilteredItemCount(): number; - - /** Get current Grouping info */ - getGrouping(): Grouping[]; - - /** Get current Grouping groups */ - getGroups(): T[]; - - /** Get the DataView Id property name to use (defaults to "Id" but could be customized to something else when instantiating the DataView) */ - getIdPropertyName(): string; - - /** Get all DataView Items */ - getItems: () => T[]; - - /** Get DataView item at specific index */ - getItem: (index: number) => T; - - /** Get an item in the DataView by its Id */ - getItemById: (id: string | number) => T | null; - - /** Get an item in the DataView by its row index */ - getItemByIdx: (idx: number) => T; - - /** Get row index in the DataView by its Id */ - getIdxById(id: string | number): number | undefined; - - /** Get item count, full dataset length that is defined in the DataView */ - getItemCount(): number; - - /** Get item metadata at specific index */ - getItemMetadata(index: number): ItemMetadata | null; - - /** Get row count (rows in displayed current page) */ - getLength(): number; - - /** Get Paging Options */ - getPagingInfo(): PagingInfo; - - /** Get row number in the grid by its item object */ - getRowByItem(item: any): number | undefined; - - /** Get row number in the grid by its Id */ - getRowById(id: string | number): number | undefined; - - /** - * Returns an array of all item IDs corresponding to the currently selected rows (including non-visible rows). - * This will also work with Pagination and will return selected IDs from all pages. - * Note: when using Pagination it will also include hidden selections assuming `preserveHiddenOnSelectionChange` is set to true. - */ - getAllSelectedIds(): Array; - - /** - * Get all selected filtered IDs (similar to "getAllSelectedIds" but only return filtered data) - * Note: when using Pagination it will also include hidden selections assuming `preserveHiddenOnSelectionChange` is set to true. - */ - getAllSelectedFilteredIds(): Array; - - /** - * Get all selected filtered dataContext items (similar to "getAllSelectedItems" but only return filtered data) - * Note: when using Pagination it will also include hidden selections assuming `preserveHiddenOnSelectionChange` is set to true. - */ - getAllSelectedFilteredItems(): T[]; - - /** - * Returns an array of all row dataContext corresponding to the currently selected rows (including non-visible rows). - * This will also work with Pagination and will return dataContext of selected rows from all pages. - */ - getAllSelectedItems(): T[]; - - /** Insert an item to the DataView before a specific index */ - insertItem(insertBefore: number, item: any): void; - - /** Insert multiple items to the DataView before a specific index */ - insertItems(insertBefore: number, items: any[]): void; - - /** From the items array provided, return the mapped rows */ - mapItemsToRows(items: any[]): number[]; - - /** From the Ids array provided, return the mapped rows */ - mapIdsToRows(ids: Array): number[]; - - /** From the rows array provided, return the mapped Ids */ - mapRowsToIds(rows: Array): Array; - - /** Refresh the DataView */ - refresh(): void; - - /** Re-Sort the dataset */ - reSort(): void; - - /** Set some Grouping */ - setGrouping(groupingInfo: Grouping | Grouping[]): void; - - /** Set a Filter that will be used by the DataView */ - setFilter(filterFn: FilterFn): void; - - /** Set extra Filter arguments which will be used by the Filter method */ - setFilterArgs(args: any): void; - - /** Set the Items with a new Dataset and optionally pass a different Id property name */ - setItems(data: any[], objectIdProperty?: string): void; - - /** Set Paging Options */ - setPagingOptions(args: Partial): void; - - /** Set Refresh Hints */ - setRefreshHints(hints: any): void; - - /** - * Set current row selected IDs array (regardless of Pagination) - * NOTE: This will NOT change the selection in the grid, if you need to do that then you still need to call - * "grid.setSelectedRows(rows)" - * @param {Array} selectedIds - list of IDs which have been selected for this action - * @param {Object} options - * - `isRowBeingAdded`: defaults to true, are the new selected IDs being added (or removed) as new row selections - * - `shouldTriggerEvent`: defaults to true, should we trigger `onSelectedRowIdsChanged` event - * - `applyRowSelectionToGrid`: defaults to true, should we apply the row selections to the grid in the UI - */ - setSelectedIds(selectedIds: Array, options?: { isRowBeingAdded?: boolean; shouldTriggerEvent?: boolean; applyRowSelectionToGrid?: boolean; }): void; - - /** Sort Method to use by the DataView */ - // eslint-disable-next-line @typescript-eslint/ban-types - sort(comparer: Function, ascending?: boolean): void; - - /** Add an item in a sorted dataset (a Sort function must be defined) */ - sortedAddItem(item: any): void; - - /** Update an item in a sorted dataset (a Sort function must be defined) */ - sortedUpdateItem(id: string | number, item: number): void; - - /** Get the sorted index of the item to search */ - sortedIndex(searchItem: any): number | undefined; - - /** - * Wires the grid and the DataView together to keep row selection tied to item ids. - * This is useful since, without it, the grid only knows about rows, so if the items - * move around, the same rows stay selected instead of the selection moving along - * with the items. - * - * NOTE: This doesn't work with cell selection model. - * - * @param grid {Slick.Grid} The grid to sync selection with. - * @param preserveHidden {Boolean} Whether to keep selected items that go out of the - * view due to them getting filtered out. - * @param preserveHiddenOnSelectionChange {Boolean} Whether to keep selected items - * that are currently out of the view (see preserveHidden) as selected when selection - * changes. - * @return {Slick.Event} An event that notifies when an internal list of selected row ids - * changes. This is useful since, in combination with the above two options, it allows - * access to the full list selected row ids, and not just the ones visible to the grid. - */ - syncGridSelection(grid: SlickGrid, preserveHidden: boolean, preserveHiddenOnSelectionChange?: boolean): SlickEvent; - - syncGridCellCssStyles(grid: SlickGrid, key: string): void; - - /** Update a specific Index */ - updateIdxById(startingIndex: number): void; - - /** Update an item in the DataView identified by its Id */ - updateItem(id: string | number, item: T): void; - - /** Update multiple items in the DataView identified by their Ids */ - updateItems(id: Array, items: T[]): void; - - // --------------------------- - // Available DataView Events - // --------------------------- - - /** Event triggered when before Paging Info got changed */ - onBeforePagingInfoChanged: SlickEvent; - - /** Event triggered while Grouping is Expanding */ - onGroupExpanded: SlickEvent; - - /** Event triggered while Grouping is Collapsing */ - onGroupCollapsed: SlickEvent; - - /** Event triggered while Paging Info is getting changed */ - onPagingInfoChanged: SlickEvent; - - /** Event triggered when the DataView row count changes */ - onRowCountChanged: SlickEvent; - - /** Event triggered when any of the row got changed */ - onRowsChanged: SlickEvent; - - /** Event triggered when the DataView row count changes OR any of the row got changed */ - onRowsOrCountChanged: SlickEvent; - - /** - * Event triggered when we changed row selections, - * NOTE: it will trigger an event when changing page because its `rows` might have changed. - * Also note that this event will only work when "syncGridSelection" is enabled - */ - onSelectedRowIdsChanged: SlickEvent; - - /** Event triggered when "setItems" function is called */ - onSetItemsCalled: SlickEvent; -} - -export interface OnGroupExpandedEventArgs { level: number; groupingKey: string | number; } -export interface OnGroupCollapsedEventArgs { level: number; groupingKey: string | number; } -export interface OnRowCountChangedEventArgs { previous: number; current: number; itemCount: number; dataView: SlickDataView; callingOnRowsChanged: boolean; } -export interface OnRowsChangedEventArgs { rows: number[]; itemCount: number; dataView: SlickDataView; calledOnRowCountChanged: boolean; } -export interface OnRowsOrCountChangedEventArgs { rowsDiff: number[]; previousRowCount: number; currentRowCount: number; itemCount: number; rowCountChanged: boolean; rowsChanged: boolean; dataView: SlickDataView; } -export interface OnSelectedRowIdsChangedEventArgs { grid: SlickGrid; added?: boolean; filteredIds: Array; selectedRowIds: Array; ids: Array; rows: number[]; dataView: SlickDataView; } -export interface OnSetItemsCalledEventArgs { idProperty: string; itemCount: number; } diff --git a/packages/common/src/interfaces/slickEventHandler.interface.ts b/packages/common/src/interfaces/slickEventHandler.interface.ts index 153a85fa3..48426e13d 100644 --- a/packages/common/src/interfaces/slickEventHandler.interface.ts +++ b/packages/common/src/interfaces/slickEventHandler.interface.ts @@ -1,4 +1,4 @@ -import type { SlickEvent, SlickEventData } from './index'; +import type { SlickEvent, SlickEventData } from 'slickgrid'; export type Handler = (e: SlickEventData, data: H) => void; diff --git a/packages/common/src/interfaces/slickGrid.interface.ts b/packages/common/src/interfaces/slickGrid.interface.ts deleted file mode 100644 index 93a36a29e..000000000 --- a/packages/common/src/interfaces/slickGrid.interface.ts +++ /dev/null @@ -1,586 +0,0 @@ -import type { SlickPluginList } from '../enums/index'; -import type { CompositeEditorOption } from './compositeEditorOption.interface'; -import type { - Column, - ColumnSort, - DragRowMove, - Editor, - EditorValidationResult, - ElementPosition, - FormatterResultObject, - GridOption, - MultiColumnSort, - PagingInfo, - SingleColumnSort, - SlickCompositeEditor, - SlickDataView, - SlickEditorLock, - SlickEvent, -} from './index'; -import type { - SlickCellSelectionModel, - SlickRowSelectionModel, -} from '../extensions/index'; - -export interface SlickGrid { - /** - * Adds an "overlay" of CSS classes to cell DOM elements. SlickGrid can have many such overlays associated with different keys and they are frequently used by plugins. For example, SlickGrid uses this method internally to decorate selected cells with selectedCellCssClass (see options). - * @param key A unique key you can use in calls to setCellCssStyles and removeCellCssStyles. If a hash with that key has already been set, an exception will be thrown. - * @param hash A hash of additional cell CSS classes keyed by row number and then by column id. Multiple CSS classes can be specified and separated by space. - * @example - * { - * 0: { - * number_column: SlickEvent; - * title_column: SlickEvent; - * }, - * 4: { - * percent_column: SlickEvent; - * } - * } - */ - addCellCssStyles(key: string, hash: any): void; - - /** Apply a Formatter Result to a Cell DOM Node */ - applyFormatResultToCellNode(formatterResult?: FormatterResultObject, cellNode?: HTMLDivElement, suppressRemove?: boolean): void; - - /** Proportionally resize a specific column by its name, index or Id */ - autosizeColumn(columnOrIndexOrId: string | number, isInit?: boolean): void; - - /** Proportionately resizes all columns to fill available horizontal space. This does not take the cell contents into consideration. */ - autosizeColumns(autosizeMode?: string, isInit?: boolean): void; - - /** - * Returns true if you can click on a given cell and make it the active focus. - * @param {number} row A row index. - * @param {number} col A column index. - */ - canCellBeActive(row: number, col: number): boolean; - - /** - * Returns true if selecting the row causes this particular cell to have the selectedCellCssClass applied to it. A cell can be selected if it exists and if it isn't on an empty / "Add New" row and if it is not marked as "unselectable" in the column definition. - * @param {number} row A row index. - * @param {number} col A column index. - */ - canCellBeSelected(row: number, col: number): boolean; - - /** - * Destroy (dispose) of SlickGrid - * @param {boolean} [shouldDestroyAllElements] - do we want to destroy (nullify) all DOM elements as well? This help in avoiding mem leaks - */ - destroy(shouldDestroyAllElements?: boolean): void; - - /** - * Attempts to switch the active cell into edit mode. Will throw an error if the cell is set to be not editable. Uses the specified editor, otherwise defaults to any default editor for that given cell. - * @param {object} editor - A SlickGrid editor (see examples in slick.editors.js). - * @param {boolean} [preClickModeOn] - Pre-Click Mode is Enabled? - * @param {object} [event] - */ - editActiveCell(editor: Editor | SlickCompositeEditor, preClickModeOn?: boolean, event?: Event): void; - - /** - * Flashes the cell twice by toggling the CSS class 4 times. - * @param {number} row A row index. - * @param {number} cell A column index. - * @param {number} [speed] (optional) - The milliseconds delay between the toggling calls. Defaults to 100 ms. - */ - flashCell(row: number, cell: number, speed?: number): void; - - /** Set focus */ - focus(): void; - - /** Get the absolute column minimum width */ - getAbsoluteColumnMinWidth(): number; - - /** Get the canvas DOM element */ - getActiveCanvasNode(event?: Event | SlickGridEventData): HTMLElement; - - /** - * Returns an object representing the coordinates of the currently active cell: - * @example `{ row: activeRow, cell: activeCell }` - */ - getActiveCell(): { row: number; cell: number; }; - - /** Returns the DOM element containing the currently active cell. If no cell is active, null is returned. */ - getActiveCellNode(): HTMLDivElement; - - /** Returns an object representing information about the active cell's position. All coordinates are absolute and take into consideration the visibility and scrolling position of all ancestors. */ - getActiveCellPosition(): ElementPosition; - - /** Get the active Viewport DOM node element */ - getActiveViewportNode(event?: Event | SlickGridEventData): HTMLDivElement; - - /** Get the displayed scrollbar dimensions */ - getDisplayedScrollbarDimensions(): { height: number; width: number; } - - /** Get the canvas DOM element */ - getCanvases(): HTMLDivElement; - - /** Get Grid Canvas Node DOM Element */ - getCanvasNode(): HTMLElement; - - /** Get the grid canvas width */ - getCanvasWidth(): number; - - /** - * Accepts a key name, returns the group of CSS styles defined under that name. See setCellCssStyles for more info. - * @param key A string. - */ - getCellCssStyles(key: string): any; - - /** Returns the active cell editor. If there is no actively edited cell, null is returned. */ - getCellEditor(): Editor | null; - - /** - * Returns a hash containing row and cell indexes from a standard W3C event. - * @param e A standard W3C event. - */ - getCellFromEvent(e: Event): { cell: number; row: number; } | null; - - /** - * Returns a hash containing row and cell indexes. Coordinates are relative to the top left corner of the grid beginning with the first row (not including the column headers). - * @param x An x coordinate. - * @param y A y coordinate. - */ - getCellFromPoint(x: number, y: number): { cell: number; row: number; }; - - /** - * Returns a DOM element containing a cell at a given row and cell. - * @param row A row index. - * @param cell A column index. - */ - getCellNode(row: number, cell: number): HTMLDivElement; - - /** - * Returns an object representing information about a cell's position. All coordinates are absolute and take into consideration the visibility and scrolling position of all ancestors. - * @param row A row index. - * @param cell A column index. - */ - getCellNodeBox(row: number, cell: number): ElementPosition; - - /** - * Returns the index of a column with a given id. Since columns can be reordered by the user, this can be used to get the column definition independent of the order: - * @param id A column id. - */ - getColumnIndex(id: string | number): number; - - /** Returns an array of column definitions, containing the option settings for each individual column. */ - getColumns(): Column[]; - - /** Get Grid Canvas Node DOM Element */ - getContainerNode(): HTMLDivElement; - - /** Returns an array of every data object, unless you're using DataView in which case it returns a DataView object. */ - getData(): T; - - /** - * Returns the databinding item at a given position. - * @param index Item row index. - */ - getDataItem(rowIndex: number): T; - - /** Returns the size of the databinding source. */ - getDataLength(): number; - - /** Get Editor lock */ - getEditorLock(): SlickEditorLock; - - /** Get Editor Controller */ - getEditController(): { - /** Commit Current Editor command */ - commitCurrentEdit(): boolean; - - /** Cancel Current Editor command */ - cancelCurrentEdit(): boolean; - }; - - /** Get the Footer DOM element */ - getFooterRow(): HTMLDivElement; - - /** Get the Footer Row Column DOM element */ - getFooterRowColumn(columnIdOrIdx: string | number): HTMLDivElement; - - /** Get frozen (pinned) row offset */ - getFrozenRowOffset(row: number): number; - - /** Get the Grid Position */ - getGridPosition(): ElementPosition; - - /** Get the Header DOM element */ - getHeader(columnDef: Column): HTMLDivElement; - - /** Get a specific Header Column DOM element */ - getHeaderColumn(columnIdOrIdx: string | number): HTMLDivElement; - - /** Get Header Column Width Difference in pixel */ - getHeaderColumnWidthDiff(): number; - - /** Get the Header Row DOM element */ - getHeaderRow(): HTMLDivElement; - - /** Get Header Row Column DOM element by its column Id */ - getHeaderRowColumn(columnId: string | number): HTMLDivElement; - - /** Get the headers width in pixel */ - getHeadersWidth(): number; - - /** Returns an object containing all of the Grid options set on the grid. See a list of Grid Options here. */ - getOptions(): GridOption; - - /** Get a Plugin (addon) by its name */ - getPluginByName(name: string): T; - - /** Get the Pre-Header Panel DOM node element */ - getPreHeaderPanel(): HTMLDivElement; - - /** Get the Pre-Header Panel Left DOM node element */ - getPreHeaderPanelLeft(): HTMLDivElement; - - /** Get the Pre-Header Panel Right DOM node element */ - getPreHeaderPanelRight(): HTMLDivElement; - - /** Get rendered range */ - getRenderedRange(viewportTop?: number, viewportLeft?: number): { top: number; bottom: number; leftPx: number; rightPx: number; }; - - /** Get scrollbar dimensions */ - getScrollbarDimensions(): { height: number; width: number; }; - - /** Returns an array of row indices corresponding to the currently selected rows. */ - getSelectedRows(): number[]; - - /** Returns the current SelectionModel. See here for more information about SelectionModels. */ - getSelectionModel(): T | undefined; - - /** Get sorted columns **/ - getSortColumns(): ColumnSort[]; - - /** Get Top Panel DOM element */ - getTopPanel(): HTMLDivElement; - - /** Get Top Panels (left/right) DOM element */ - getTopPanels(): [HTMLDivElement, HTMLDivElement]; - - /** Get grid unique identifier */ - getUID(): string; - - /** Get Viewport position */ - getViewport(viewportTop?: number, viewportLeft?: number): { top: number; bottom: number; leftPx: number; rightPx: number; }; - - /** Get the Viewport DOM node element */ - getViewportNode(): HTMLDivElement; - - /** Get all the Viewport node elements */ - getViewports(): HTMLDivElement[]; - - /** - * Accepts a row integer and a cell integer, scrolling the view to the row where row is its row index, and cell is its cell index. Optionally accepts a forceEdit boolean which, if true, will attempt to initiate the edit dialogue for the field in the specified cell. - * Unlike setActiveCell, this scrolls the row into the viewport and sets the keyboard focus. - * @param row A row index. - * @param cell A column index. - * @param forceEdit If true, will attempt to initiate the edit dialogue for the field in the specified cell. - */ - gotoCell(row: number, cell: number, forceEdit?: boolean): void; - - /** Initializes the grid. Called after plugins are registered. Normally, this is called by the constructor, so you don't need to call it. However, in certain cases you may need to delay the initialization until some other process has finished. In that case, set the explicitInitialization option to true and call the grid.init() manually. */ - init(): void; - - /** Invalidate all rows and re-render the grid rows */ - invalidate(): void; - - /** Invalidate all rows */ - invalidateAllRows(): void; - - /** Invalidate a specific row number */ - invalidateRow(row: number): void; - - /** Invalidate a specific set of row numbers */ - invalidateRows(rows: number[]): void; - - /** Navigate to the bottom of the grid */ - navigateBottom(): void; - - /** Switches the active cell one row down skipping unselectable cells. Returns a boolean saying whether it was able to complete or not. */ - navigateDown(): boolean; - - /** Switches the active cell one cell left skipping unselectable cells. Unline navigatePrev, navigateLeft stops at the first cell of the row. Returns a boolean saying whether it was able to complete or not. */ - navigateLeft(): boolean; - - /** Tabs over active cell to the next selectable cell. Returns a boolean saying whether it was able to complete or not. */ - navigateNext(): boolean; - - /** Navigate (scroll) by a page up */ - navigatePageUp(): void; - - /** Navigate (scroll) by a page down */ - navigatePageDown(): void; - - /** Tabs over active cell to the previous selectable cell. Returns a boolean saying whether it was able to complete or not. */ - navigatePrev(): boolean; - - /** Switches the active cell one cell right skipping unselectable cells. Unline navigateNext, navigateRight stops at the last cell of the row. Returns a boolean saying whether it was able to complete or not. */ - navigateRight(): boolean; - - /** Navigate to the start row in the grid */ - navigateRowStart(): boolean; - - /** Navigate to the end row in the grid */ - navigateRowEnd(): boolean; - - /** Navigate to the top of the grid */ - navigateTop(): void; - - /** Switches the active cell one row up skipping unselectable cells. Returns a boolean saying whether it was able to complete or not. */ - navigateUp(): boolean; - - /** (re)Render the grid */ - render(): void; - - /** Register an external Plugin (addon) */ - registerPlugin(plugin: T): void; - - /** - * Removes an "overlay" of CSS classes from cell DOM elements. See setCellCssStyles for more. - * @param key A string key. - */ - removeCellCssStyles(key: string): void; - - /** - * Apply Columns Widths in the UI and optionally invalidate & re-render the columns when specified - * @param {Boolean} shouldReRender - should we invalidate and re-render the grid? - */ - reRenderColumns(shouldReRender?: boolean): void; - - /** Resets active cell. */ - resetActiveCell(): void; - - /** Execute a Resize of the Canvas */ - resizeCanvas(): void; - - /** Scroll to a specific cell and make it into the view */ - scrollCellIntoView(row: number, cell: number, doPaging?: boolean): void; - - /** Scroll to a specific column and show it into the viewport */ - scrollColumnIntoView(cell: number): void; - - /** Scroll to a specific row and make it into the view */ - scrollRowIntoView(row: number, doPaging?: boolean): void; - - /** Scroll to the top row and make it into the view */ - scrollRowToTop(row: number): void; - - /** Scroll to an Y position in the grid */ - scrollTo(yPos: number): void; - - /** - * Sets an active cell. - * @param {number} row - A row index. - * @param {number} cell - A column index. - * @param {boolean} optionEditMode Option Edit Mode is Auto-Edit? - * @param {boolean} preClickModeOn Pre-Click Mode is Enabled? - * @param {boolean} suppressActiveCellChangedEvent Are we suppressing Active Cell Changed Event (defaults to false) - */ - setActiveCell(row: number, cell: number, optionEditMode?: boolean, preClickModeOn?: boolean, suppressActiveCellChangedEvent?: boolean): void; - - /** - * Sets an active cell. - * @param {number} row - A row index. - * @param {number} cell - A column index. - * @param {boolean} suppressScrollIntoView - optionally suppress the ScrollIntoView that happens by default (defaults to false) - */ - setActiveRow(row: number, cell?: number, suppressScrollIntoView?: boolean): void; - - /** Sets an active viewport node */ - setActiveViewportNode(element: HTMLDivElement): void; - - /** - * Sets CSS classes to specific grid cells by calling removeCellCssStyles(key) followed by addCellCssStyles(key, hash). key is name for this set of styles so you can reference it later - to modify it or remove it, for example. hash is a per-row-index, per-column-name nested hash of CSS classes to apply. - * Suppose you have a grid with columns: - * ["login", "name", "birthday", "age", "likes_icecream", "favorite_cake"] - * ...and you'd like to highlight the "birthday" and "age" columns for people whose birthday is today, in this case, rows at index 0 and 9. (The first and tenth row in the grid). - * @param key A string key. Will overwrite any data already associated with this key. - * @param hash A hash of additional cell CSS classes keyed by row number and then by column id. Multiple CSS classes can be specified and separated by space. - */ - setCellCssStyles(key: string, hash: any): void; - - /** Set the Column Header Visibility and optionally enable/disable animation (enabled by default) */ - setColumnHeaderVisibility(visible: boolean, animate?: boolean): void; - - /** - * Sets grid columns. Column headers will be recreated and all rendered rows will be removed. To rerender the grid (if necessary), call render(). - * @param columnDefinitions An array of column definitions. - */ - setColumns(columnDefinitions: Column[]): void; - - /** - * Sets a new source for databinding and removes all rendered rows. Note that this doesn't render the new rows - you can follow it with a call to render() to do that. - * @param newData New databinding source using a regular JavaScript array.. or a custom object exposing getItem(index) and getLength() functions. - * @param scrollToTop If true, the grid will reset the vertical scroll position to the top of the grid. - */ - setData(newData: T | T[], scrollToTop?: boolean): void; - - /** Set the Footer Visibility and optionally enable/disable animation (enabled by default) */ - setFooterRowVisibility(visible: boolean, animate?: boolean): void; - - /** Set the Header Row Visibility and optionally enable/disable animation (enabled by default) */ - setHeaderRowVisibility(visible: boolean, animate?: boolean): void; - - /** - * Extends grid options with a given hash. If an there is an active edit, the grid will attempt to commit the changes and only continue if the attempt succeeds. - * @param {Object} options - an object with configuration options. - * @param {Boolean} suppressRender - do we want to supress the grid re-rendering? (defaults to false) - * @param {Boolean} suppressColumnSet - do we want to supress the columns set, via "setColumns()" method? (defaults to false) - * @param {Boolean} suppressSetOverflow - do we want to suppress the call to `setOverflow` - */ - setOptions(options: GridOption, suppressRender?: boolean, suppressColumnSet?: boolean, suppressSetOverflow?: boolean): void; - - /** Set the Pre-Header Visibility and optionally enable/disable animation (enabled by default) */ - setPreHeaderPanelVisibility(visible: boolean, animate?: boolean): void; - - /** - * Accepts an array of row indices and applies the current selectedCellCssClass to the cells in the row, respecting whether cells have been flagged as selectable. - * @param {Array} rowsArray - an array of row numbers. - * @param {String} caller - an optional string to identify who called the method - */ - setSelectedRows(rowsArray: number[], caller?: string): void; - - /** - * Unregisters a current selection model and registers a new one. See the definition of SelectionModel for more information. - * @selectionModel A SelectionModel. - */ - setSelectionModel(selectionModel: SlickCellSelectionModel | SlickRowSelectionModel): void; - - /** - * Accepts a columnId string and an ascending boolean. Applies a sort glyph in either ascending or descending form to the header of the column. Note that this does not actually sort the column. It only adds the sort glyph to the header. - * @param columnId - * @param ascending - */ - setSortColumn(columnId: string | number, ascending: boolean): void; - - /** - * Accepts an array of objects in the form [ { columnId: [string], sortAsc: [boolean] }, ... ]. When called, this will apply a sort glyph in either ascending or descending form to the header of each column specified in the array. Note that this does not actually sort the column. It only adds the sort glyph to the header - * @param cols - */ - setSortColumns(cols: Array<{ columnId: string | number; sortAsc: boolean; }>): void; - - /** Set the Top Panel Visibility and optionally enable/disable animation (enabled by default) */ - setTopPanelVisibility(visible: boolean, animate?: boolean): void; - - /** Unregister an external Plugin (addon) */ - unregisterPlugin(plugin: SlickPluginList): void; - - /** Update a specific cell by its row and column index */ - updateCell(row: number, cell: number): void; - - /** - * Updates an existing column definition and a corresponding header DOM element with the new title and tooltip. - * @param columnId Column id. - * @param title New column name. - * @param toolTip New column tooltip. - */ - updateColumnHeader(columnId: string | number, title?: string, toolTip?: string): void; - - /** Update paging information status from the View */ - updatePagingStatusFromView(pagingInfo: PagingInfo): void; - - /** Update a specific row by its row index */ - updateRow(row: number): void; - - /** Update the dataset row count */ - updateRowCount(): void; - - // ----------------------------- - // Available Slick Grid Events - // ----------------------------- - - onActiveCellChanged: SlickEvent; - onActiveCellPositionChanged: SlickEvent; - onAddNewRow: SlickEvent; - onAutosizeColumns: SlickEvent; - onBeforeAppendCell: SlickEvent; - onBeforeCellEditorDestroy: SlickEvent; - onBeforeColumnsResize: SlickEvent; - onBeforeDestroy: SlickEvent; - onBeforeEditCell: SlickEvent; - onBeforeHeaderCellDestroy: SlickEvent; - onBeforeHeaderRowCellDestroy: SlickEvent; - onBeforeFooterRowCellDestroy: SlickEvent; - onBeforeSetColumns: SlickEvent; - onBeforeSort: SlickEvent; - onCellChange: SlickEvent; - onCellCssStylesChanged: SlickEvent; - onClick: SlickEvent; - onColumnsDrag: SlickEvent; - onColumnsReordered: SlickEvent; - onColumnsResized: SlickEvent; - onColumnsResizeDblClick: SlickEvent; - onCompositeEditorChange: SlickEvent; - onContextMenu: SlickEvent; - onDrag: SlickEvent; - onDragEnd: SlickEvent; - onDragInit: SlickEvent; - onDragStart: SlickEvent; - onDblClick: SlickEvent; - onFooterContextMenu: SlickEvent; - onFooterRowCellRendered: SlickEvent; - onHeaderCellRendered: SlickEvent; - onFooterClick: SlickEvent; - onHeaderClick: SlickEvent; - onHeaderContextMenu: SlickEvent; - onHeaderMouseEnter: SlickEvent; - onHeaderMouseLeave: SlickEvent; - onHeaderRowCellRendered: SlickEvent; - onHeaderRowMouseEnter: SlickEvent; - onHeaderRowMouseLeave: SlickEvent; - onKeyDown: SlickEvent; - onMouseEnter: SlickEvent; - onMouseLeave: SlickEvent; - onValidationError: SlickEvent; - onViewportChanged: SlickEvent; - onRendered: SlickEvent; - onSelectedRowsChanged: SlickEvent; - onSetOptions: SlickEvent; - onScroll: SlickEvent; - onSort: SlickEvent; -} - -export interface SlickGridEventData { grid: SlickGrid; } -export interface OnActiveCellChangedEventArgs extends SlickGridEventData { cell: number; row: number; } -export interface OnAddNewRowEventArgs extends SlickGridEventData { item: any; column: Column; } -export interface OnAutosizeColumnsEventArgs extends SlickGridEventData { columns: Column[]; } -export interface OnBeforeAppendCellEventArgs extends SlickGridEventData { row: number; cell: number; value: any; dataContext: any; } -export interface OnBeforeCellEditorDestroyEventArgs extends SlickGridEventData { editor: Editor; } -export interface OnBeforeColumnsResizeEventArgs extends SlickGridEventData { triggeredByColumn: string; } -export interface OnBeforeEditCellEventArgs extends SlickGridEventData { row: number; cell: number; item: any; column: Column; target?: 'grid' | 'composite'; compositeEditorOptions?: CompositeEditorOption; } -export interface OnBeforeHeaderCellDestroyEventArgs extends SlickGridEventData { node: HTMLElement; column: Column; } -export interface OnBeforeHeaderRowCellDestroyEventArgs extends SlickGridEventData { node: HTMLElement; column: Column; } -export interface OnBeforeFooterRowCellDestroyEventArgs extends SlickGridEventData { node: HTMLElement; column: Column; } -export interface OnBeforeSetColumnsEventArgs extends SlickGridEventData { previousColumns: Column[]; newColumns: Column[]; } -export interface OnCellChangeEventArgs extends SlickGridEventData { row: number; cell: number; item: any; column: Column; } -export interface OnCellCssStylesChangedEventArgs extends SlickGridEventData { key: string; hash: string; } -export interface OnColumnsDragEventArgs extends SlickGridEventData { triggeredByColumn: string; resizeHandle: HTMLDivElement; } -export interface OnColumnsReorderedEventArgs extends SlickGridEventData { impactedColumns: Column[]; } -export interface OnColumnsResizedEventArgs extends SlickGridEventData { triggeredByColumn: string; } -export interface OnColumnsResizeDblClickEventArgs extends SlickGridEventData { triggeredByColumn: string; } -export interface OnCompositeEditorChangeEventArgs extends SlickGridEventData { row: number; cell: number; item: any; column: Column; formValues: any; editors: { [columnId: string]: Editor; }; triggeredBy?: 'user' | 'system'; } -export interface OnClickEventArgs extends SlickGridEventData { row: number; cell: number; } -export interface OnDblClickEventArgs extends SlickGridEventData { row: number; cell: number; } -export interface OnFooterContextMenuEventArgs extends SlickGridEventData { column: Column; } -export interface OnFooterRowCellRenderedEventArgs extends SlickGridEventData { node: HTMLDivElement; column: Column; } -export interface OnHeaderCellRenderedEventArgs extends SlickGridEventData { node: HTMLDivElement; column: Column; } -export interface OnFooterClickEventArgs extends SlickGridEventData { column: Column; } -export interface OnHeaderClickEventArgs extends SlickGridEventData { column: Column; } -export interface OnHeaderContextMenuEventArgs extends SlickGridEventData { column: Column; } -export interface OnHeaderMouseEventArgs extends SlickGridEventData { column: Column; } -export interface OnHeaderRowCellRenderedEventArgs extends SlickGridEventData { node: HTMLDivElement; column: Column; } -export interface OnKeyDownEventArgs extends SlickGridEventData { row: number; cell: number; } -export interface OnValidationErrorEventArgs extends SlickGridEventData { row: number; cell: number; validationResults: EditorValidationResult; column: Column; editor: Editor; cellNode: HTMLDivElement; } -export interface OnRenderedEventArgs extends SlickGridEventData { startRow: number; endRow: number; } -export interface OnSelectedRowsChangedEventArgs extends SlickGridEventData { rows: number[]; previousSelectedRows: number[]; changedSelectedRows: number[]; changedUnselectedRows: number[]; caller: string; } -export interface OnSetOptionsEventArgs extends SlickGridEventData { optionsBefore: GridOption; optionsAfter: GridOption; } - -export interface OnScrollEventArgs extends SlickGridEventData { scrollLeft: number; scrollTop: number; } -export interface OnDragEventArgs extends SlickGridEventData { - count: number; deltaX: number; deltaY: number; offsetX: number; offsetY: number; originalX: number; originalY: number; - available: HTMLDivElement | HTMLDivElement[]; drag: HTMLDivElement; drop: HTMLDivElement | HTMLDivElement[]; helper: HTMLDivElement; - proxy: HTMLDivElement; target: HTMLDivElement; mode: string; - row: number; rows: number[]; startX: number; startY: number; -} diff --git a/packages/common/src/interfaces/slickGridUniversal.interface.ts b/packages/common/src/interfaces/slickGridUniversal.interface.ts new file mode 100644 index 000000000..fdd4f53e9 --- /dev/null +++ b/packages/common/src/interfaces/slickGridUniversal.interface.ts @@ -0,0 +1,5 @@ +import type { SlickGrid } from 'slickgrid'; + +import type { Column, GridOption } from './index'; + +export type SlickGridUniversal = Column, O extends GridOption = GridOption> = SlickGrid; diff --git a/packages/common/src/interfaces/slickNamespace.interface.ts b/packages/common/src/interfaces/slickNamespace.interface.ts deleted file mode 100644 index add74f77f..000000000 --- a/packages/common/src/interfaces/slickNamespace.interface.ts +++ /dev/null @@ -1,207 +0,0 @@ -import type { - AutoTooltipOption, - CellMenuOption, - CheckboxSelectorOption, - Column, - CompositeEditorOption, - ContextMenuOption, - DataViewOption, - DraggableGroupingOption, - ExcelCopyBufferOption, - GridOption, - GridSize, - HeaderButtonOption, - HeaderMenuOption, - ResizerOption, - RowDetailViewOption, - RowMoveManagerOption, - RowSelectionModelOption, - SlickCompositeEditor, - SlickDataView, - SlickEditorLock, - SlickEvent, - SlickEventData, - SlickEventHandler, - SlickGrid, - SlickGroup, - SlickNonDataItem, - SlickRange, - SlickRemoteModel, - SlickResizer, - SlickRowDetailView, -} from './index'; -import type { - SlickAutoTooltip, - SlickCellExternalCopyManager, - SlickCellMenu, - SlickCellRangeDecorator, - SlickCellRangeSelector, - SlickCellSelectionModel, - SlickCheckboxSelectColumn, - SlickContextMenu, - SlickDraggableGrouping, - SlickGridMenu, - SlickGroupItemMetadataProvider, - SlickHeaderButtons, - SlickHeaderMenu, - SlickRowMoveManager, - SlickRowSelectionModel, -} from '../extensions/index'; - -/** - * Slick Grid class interface of the entire library and it's multiple controls/plugins. - * However note that We'll only include what we really use in this lib, - * for example, we defined our own Aggregators, Formatters, ... so we won't use the ones defined in the regular Slick class. - */ -export interface SlickNamespace { - // -- - // Slick Grid & DataView - // -------------------------- - - Data: { - /** Slick DataView which has built-in data manipulation methods. Relies on the data item having an "id" property uniquely identifying it. */ - DataView: new (options?: DataViewOption) => SlickDataView; - - /** Slick AJAX Remote Data store implementation. */ - RemoteModel?: new () => SlickRemoteModel; - - /** - * Provides item metadata for group (Slick.Group) and totals (Slick.Totals) rows produced by the DataView. - * This metadata overrides the default behavior and formatting of those rows so that they appear and function - * correctly when processed by the grid. - * - * This class also acts as a grid plugin providing event handlers to expand & collapse groups. - * If "grid.registerPlugin(...)" is not called, expand & collapse will not work. - * - */ - GroupItemMetadataProvider: new () => SlickGroupItemMetadataProvider; - }; - - /** Slick Grid is a data grid library and this class is the core of the library */ - Grid: new (gridContainer: HTMLElement | string, data: SlickDataView | Array, columnDefinitions: Column[], gridOptions: GridOption) => SlickGrid; - - /** Information about a group of rows. */ - Group: new () => SlickGroup; - - /** A base class that all specia / non-data rows (like Group and GroupTotals) derive from. */ - NonDataItem: new () => SlickNonDataItem; - - // -- - // Slick Core - // -------------------------- - - /** A composite SlickGrid editor factory. Generates an editor that is composed of multiple editors for given columns. */ - CompositeEditor: new (modalColumns: Column[], containers: Array, options?: CompositeEditorOption) => SlickCompositeEditor; - - /** Event is a Pub/Sub SlickGrid Event */ - Event: new () => SlickEvent; - - /** - * An event object for passing data to event handlers and letting them control propagation. - * This is pretty much identical to how W3C implement events. - */ - EventData: new () => SlickEventData; - - /** EventHandler is a Pub/Sub SlickGrid Event Handler */ - EventHandler: new () => SlickEventHandler; - - /** Global Editor Lock */ - GlobalEditorLock: SlickEditorLock; - - /** A structure containing a range of cells. */ - Range: new (fromRow?: number, fromCell?: number, toRow?: number, toCell?: number) => SlickRange; - - /** - * HTML Sanitizer using simple Regular Expression. - * Please note that it is much better to use other tools like DOMPurify when possible. - */ - RegexSanitizer: (dirtyHtml: string) => string, - - // -- - // Slick Controls/Plugins (addons) - // ------------------------------- - - /** AutoTooltips is a 3rd party plugin (addon) to show/hide tooltips when columns are too narrow to fit content. */ - AutoTooltips: new (options?: AutoTooltipOption) => SlickAutoTooltip; - - /** Cell External Copy Manager is a 3rd party plugin (addon) which is an Excel like copy cell range addon */ - CellExternalCopyManager: new (options?: ExcelCopyBufferOption) => SlickCellExternalCopyManager; - - /** Displays an overlay on top of a given cell range. */ - CellRangeDecorator: new () => SlickCellRangeDecorator; - - /** CellRangeSelector is a utility to select a range of cells, this is useful with for example when we use the cell external copy manager (excel like) */ - CellRangeSelector: new () => SlickCellRangeSelector; - - /** CellSelectionModel is a utility to select a range of cells, this is useful with for example when we use the cell external copy manager (excel like) */ - CellSelectionModel: new () => SlickCellSelectionModel; - - /** A plugin to select row(s) via checkboxes typically shown as the 1st column in the grid. */ - CheckboxSelectColumn: new (options?: CheckboxSelectorOption) => SlickCheckboxSelectColumn; - - /** This plugin provides the Draggable Grouping feature */ - DraggableGrouping: new (options?: DraggableGroupingOption) => SlickDraggableGrouping; - - /** RowSelectionModel is a utility to select a range of rows, this is used by at least the CheckboxSelectColumn plugin */ - RowSelectionModel: new (options?: RowSelectionModelOption) => SlickRowSelectionModel; - - /** A plugin that allows to move/reorganize some rows with drag & drop */ - RowMoveManager: new (options?: RowMoveManagerOption) => SlickRowMoveManager; - - // all of the controls are under the Controls namespace - Controls: { - /** A control to add a Grid Menu (hambuger menu on top-right of the grid) */ - GridMenu: new (columns: Column[], grid: SlickGrid, options?: GridOption) => SlickGridMenu; - }, - - // some of the plugins are under the Plugins namespace - Plugins: { - /** A plugin to add Menu on a Cell click (click on the cell that has the cellMenu object defined) */ - CellMenu: new (options?: CellMenuOption) => SlickCellMenu; - - /** A plugin to add Context Menu (mouse right+click), it subscribes to the slickgrid cell "onContextMenu" event. */ - ContextMenu: new (options?: ContextMenuOption) => SlickContextMenu; - - /** A plugin to add custom buttons to column headers. */ - HeaderButtons: new (options?: HeaderButtonOption) => SlickHeaderButtons; - - /** A plugin to add drop-down menus to column headers. */ - HeaderMenu: new (options?: HeaderMenuOption) => SlickHeaderMenu; - - /** A plugin to add row detail panel */ - RowDetailView: new (options?: RowDetailViewOption) => SlickRowDetailView; - - /** Resizer is a 3rd party plugin (addon) that can be used to auto-resize a grid and/or resize it with fixed dimensions. */ - Resizer: new (options?: ResizerOption, fixedGridDimensions?: GridSize) => SlickResizer; - }, - - BindingEventService: { - destroy: () => void; - bind: (elm: HTMLElement, eventName: string, listener: EventListenerOrEventListenerObject) => void; - unbind: (elm: HTMLElement, eventName: string, listener: EventListenerOrEventListenerObject) => void; - unbindByEventName: (elm: HTMLElement, eventName: string) => void; - unbindAll: () => void; - }, - - // SlickGrid Utilities - Utils: { - calculateAvailableSpace: (elm: HTMLElement) => { top: number; left: number; bottom: number; right: number; }; - createDomElement: (tagName: T, elementOptions?: { [P in K]: HTMLElementTagNameMap[T][P] }, appendToParent?: Element) => HTMLElementTagNameMap[T]; - contains: (parent: HTMLElement, child: HTMLElement) => boolean; - debounce: (callback: (args?: any[]) => void, wait?: number) => void; - emptyElement: (elm: HTMLElement) => void; - extend: (deep?: boolean | any, ...args: T[]) => T; - getElementProp: (elm: HTMLElement, prop: string) => any; - innerSize: (elm: HTMLElement, type: 'height' | 'width') => number; - height: (elm: HTMLElement, val?: number | string) => number | void; - width: (elm: HTMLElement, val?: number | string) => number | void; - offset: (elm: HTMLElement) => undefined | { top: number, left: number }; - isEmptyObject: (obj: any) => boolean; - parents: (elm: HTMLElement, selector: string) => HTMLElement[]; - setStyleSize: (elm: HTMLElement, style: string, val: string | (() => string)) => void; - hide: (elm: HTMLElement, type?: string) => void; - show: (elm: HTMLElement, type?: string) => void; - toFloat: (val: number) => number; - windowScrollPosition: () => { top: number; left: number; }; - } -} diff --git a/packages/common/src/interfaces/slickPlugin.interface.ts b/packages/common/src/interfaces/slickPlugin.interface.ts new file mode 100644 index 000000000..08db39aad --- /dev/null +++ b/packages/common/src/interfaces/slickPlugin.interface.ts @@ -0,0 +1,7 @@ +import { SlickGridUniversal } from './slickGridUniversal.interface'; + +export interface SlickPlugin { + pluginName: string; + init: (grid: SlickGridUniversal) => void; + destroy: () => void; +} \ No newline at end of file diff --git a/packages/common/src/interfaces/slickRemoteModel.interface.ts b/packages/common/src/interfaces/slickRemoteModel.interface.ts index 1d89df979..5779d65b3 100644 --- a/packages/common/src/interfaces/slickRemoteModel.interface.ts +++ b/packages/common/src/interfaces/slickRemoteModel.interface.ts @@ -1,5 +1,5 @@ +import type { SlickEvent } from 'slickgrid'; import type { Column } from './column.interface'; -import type { SlickEvent } from './index'; /** * A sample AJAX remote data store implementation. diff --git a/packages/common/src/interfaces/slickResizer.interface.ts b/packages/common/src/interfaces/slickResizer.interface.ts index 32558b381..daa2adbc0 100644 --- a/packages/common/src/interfaces/slickResizer.interface.ts +++ b/packages/common/src/interfaces/slickResizer.interface.ts @@ -1,10 +1,6 @@ -import type { - GridSize, - ResizerOption, - SlickEvent, - SlickEventData, - SlickGrid, -} from './index'; +import type { SlickEvent, SlickEventData } from 'slickgrid'; + +import type { GridSize, ResizerOption, SlickGridUniversal } from './index'; /** * A Resizer plugin that can be used to auto-resize a grid and/or resize with fixed dimensions. @@ -22,7 +18,7 @@ export interface SlickResizer { constructor: (options?: ResizerOption, fixedGridDimensions?: GridSize) => void; /** initialize the 3rd party plugin */ - init(grid: SlickGrid): void; + init(grid: SlickGridUniversal): void; /** destroy the 3rd party plugin */ destroy(): void; @@ -58,8 +54,8 @@ export interface SlickResizer { // Events /** triggered before rows are being moved */ - onGridAfterResize: SlickEvent<{ grid: SlickGrid; dimensions: GridSize; }>; + onGridAfterResize: SlickEvent<{ grid: SlickGridUniversal; dimensions: GridSize; }>; /** triggered when rows are being moved */ - onGridBeforeResize: SlickEvent<{ grid: SlickGrid; }>; + onGridBeforeResize: SlickEvent<{ grid: SlickGridUniversal; }>; } diff --git a/packages/common/src/interfaces/slickRowDetailView.interface.ts b/packages/common/src/interfaces/slickRowDetailView.interface.ts index ee2747e21..0741ca46a 100644 --- a/packages/common/src/interfaces/slickRowDetailView.interface.ts +++ b/packages/common/src/interfaces/slickRowDetailView.interface.ts @@ -1,4 +1,17 @@ -import type { Column, GridOption, RowDetailViewOption, SlickEvent, SlickGrid, } from './index'; +import type { SlickEvent } from 'slickgrid'; + +import type { + Column, + GridOption, + OnAfterRowDetailToggleArgs, + OnBeforeRowDetailToggleArgs, + OnRowBackToViewportRangeArgs, + OnRowDetailAsyncEndUpdateArgs, + OnRowDetailAsyncResponseArgs, + OnRowOutOfViewportRangeArgs, + RowDetailViewOption, + SlickGridUniversal +} from './index'; import type { ContainerService } from '../services/container.service'; import type { UsabilityOverrideFn } from '../enums'; @@ -7,13 +20,13 @@ export interface SlickRowDetailView { pluginName: 'RowDetailView'; /** Initialize the SlickGrid 3rd party plugin */ - init(grid: SlickGrid, containerService?: ContainerService): void; + init(grid: SlickGridUniversal, containerService?: ContainerService): void; /** Destroy (dispose) the SlickGrid 3rd party plugin */ dispose(): void; /** Create the plugin */ - create(columnDefinitions: Column[], gridOptions: GridOption): SlickRowDetailView | null; + create(columnDefinitions: Column[], gridOptions?: GridOption): SlickRowDetailView | null; /** Collapse all of the open items */ collapseAll(): void; @@ -58,20 +71,20 @@ export interface SlickRowDetailView { // Events /** Fired when the async response finished */ - onAsyncEndUpdate?: SlickEvent<{ item: any; grid: SlickGrid; }>; + onAsyncEndUpdate?: SlickEvent; /** This event must be used with the "notify" by the end user once the Asynchronous Server call returns the item detail */ - onAsyncResponse?: SlickEvent<{ item: any; detailView?: any }>; + onAsyncResponse?: SlickEvent; /** Fired after the row detail gets toggled */ - onAfterRowDetailToggle?: SlickEvent<{ item: any; expandedRows: Array; grid: SlickGrid; }>; + onAfterRowDetailToggle?: SlickEvent; /** Fired before the row detail gets toggled */ - onBeforeRowDetailToggle?: SlickEvent<{ item: any; grid: SlickGrid; }>; + onBeforeRowDetailToggle?: SlickEvent; /** Fired after the row detail gets toggled */ - onRowBackToViewportRange?: SlickEvent<{ item: any; rowId: number | string; rowIndex: number; expandedRows: Array; rowIdsOutOfViewport: Array; grid: SlickGrid; }>; + onRowBackToViewportRange?: SlickEvent; /** Fired after a row becomes out of viewport range (user can't see the row anymore) */ - onRowOutOfViewportRange?: SlickEvent<{ item: any; rowId: number | string; rowIndex: number; expandedRows: Array; rowIdsOutOfViewport: Array; grid: SlickGrid; }>; + onRowOutOfViewportRange?: SlickEvent; } \ No newline at end of file diff --git a/packages/common/src/services/__tests__/extension.service.spec.ts b/packages/common/src/services/__tests__/extension.service.spec.ts index 3091887fd..97b66f68d 100644 --- a/packages/common/src/services/__tests__/extension.service.spec.ts +++ b/packages/common/src/services/__tests__/extension.service.spec.ts @@ -2,9 +2,10 @@ jest.mock('../../extensions/slickDraggableGrouping'); import 'jest-extended'; import { BasePubSubService } from '@slickgrid-universal/event-pub-sub'; +import { SlickEvent } from 'slickgrid'; import { ExtensionName } from '../../enums/index'; -import { Column, ExtensionModel, GridOption, SlickGrid, SlickNamespace } from '../../interfaces/index'; +import { Column, ExtensionModel, GridOption, SlickGridUniversal } from '../../interfaces/index'; import { ExtensionUtility } from '../../extensions'; import { ExtensionService, FilterService, SharedService, SortService, TreeDataService } from '../index'; import { TranslateServiceStub } from '../../../../../test/translateServiceStub'; @@ -26,7 +27,6 @@ import { } from '../../extensions/index'; jest.mock('flatpickr', () => { }); -declare const Slick: SlickNamespace; const GRID_UID = 'slickgrid_12345'; const extensionUtilityStub = { @@ -47,7 +47,7 @@ const mockCellSelectionModel = { setSelectedRanges: jest.fn(), getSelectedRows: jest.fn(), setSelectedRows: jest.fn(), - onSelectedRangesChanged: new Slick.Event(), + onSelectedRangesChanged: new SlickEvent(), } as unknown as SlickCellSelectionModel; jest.mock('../../extensions/slickCellSelectionModel'); @@ -56,7 +56,7 @@ const mockRowSelectionModel = { init: jest.fn(), destroy: jest.fn(), dispose: jest.fn(), - onSelectedRangesChanged: new Slick.Event(), + onSelectedRangesChanged: new SlickEvent(), } as unknown as SlickRowSelectionModel; jest.mock('../../extensions/slickRowSelectionModel', () => ({ SlickRowSelectionModel: jest.fn().mockImplementation(() => mockRowSelectionModel), @@ -99,21 +99,21 @@ const gridStub = { registerPlugin: jest.fn(), setSelectionModel: jest.fn(), updateColumnHeader: jest.fn(), - onActiveCellChanged: new Slick.Event(), - onBeforeDestroy: new Slick.Event(), - onBeforeHeaderCellDestroy: new Slick.Event(), - onBeforeSetColumns: new Slick.Event(), - onClick: new Slick.Event(), - onColumnsReordered: new Slick.Event(), - onContextMenu: new Slick.Event(), - onHeaderCellRendered: new Slick.Event(), - onHeaderClick: new Slick.Event(), - onHeaderContextMenu: new Slick.Event(), - onKeyDown: new Slick.Event(), - onSelectedRowsChanged: new Slick.Event(), - onScroll: new Slick.Event(), - onSetOptions: new Slick.Event(), -} as unknown as SlickGrid; + onActiveCellChanged: new SlickEvent(), + onBeforeDestroy: new SlickEvent(), + onBeforeHeaderCellDestroy: new SlickEvent(), + onBeforeSetColumns: new SlickEvent(), + onClick: new SlickEvent(), + onColumnsReordered: new SlickEvent(), + onContextMenu: new SlickEvent(), + onHeaderCellRendered: new SlickEvent(), + onHeaderClick: new SlickEvent(), + onHeaderContextMenu: new SlickEvent(), + onKeyDown: new SlickEvent(), + onSelectedRowsChanged: new SlickEvent(), + onScroll: new SlickEvent(), + onSetOptions: new SlickEvent(), +} as unknown as SlickGridUniversal; const filterServiceStub = { addRxJsResource: jest.fn(), @@ -302,7 +302,7 @@ describe('ExtensionService', () => { jest.spyOn(SharedService.prototype, 'gridOptions', 'get').mockReturnValue(gridOptionsMock); service.bindDifferentExtensions(); - const output = service.getExtensionByName(ExtensionName.autoTooltip); + const output = service.getExtensionByName(ExtensionName.autoTooltip); const pluginInstance = service.getExtensionInstanceByName(ExtensionName.autoTooltip); expect(extSpy).toHaveBeenCalled(); diff --git a/packages/common/src/services/__tests__/filter.service.spec.ts b/packages/common/src/services/__tests__/filter.service.spec.ts index 6f89fb5ae..21c5c3940 100644 --- a/packages/common/src/services/__tests__/filter.service.spec.ts +++ b/packages/common/src/services/__tests__/filter.service.spec.ts @@ -1,4 +1,5 @@ import { of, throwError } from 'rxjs'; +import { type SlickDataView, SlickEvent, SlickEventData, SlickEventHandler } from 'slickgrid'; import { BasePubSubService } from '@slickgrid-universal/event-pub-sub'; import { FieldType } from '../../enums/index'; @@ -12,10 +13,7 @@ import { GridOption, MenuCommandItem, RowDetailView, - SlickDataView, - SlickEventHandler, - SlickGrid, - SlickNamespace, + SlickGridUniversal, } from '../../interfaces/index'; import { Filters, InputFilter, NativeSelectFilter } from '../../filters'; import { FilterService } from '../filter.service'; @@ -28,7 +26,6 @@ import { CollectionService } from '../collection.service'; import { TranslateServiceStub } from '../../../../../test/translateServiceStub'; import { RxJsResourceStub } from '../../../../../test/rxjsResourceStub'; -declare const Slick: SlickNamespace; const DOM_ELEMENT_ID = 'row-detail123'; function initSetWithValues(values: any[]) { @@ -94,15 +91,15 @@ const gridStub = { getSortColumns: jest.fn(), invalidate: jest.fn(), onLocalSortChanged: jest.fn(), - onSort: new Slick.Event(), - onBeforeHeaderRowCellDestroy: new Slick.Event(), - onHeaderRowCellRendered: new Slick.Event(), + onSort: new SlickEvent(), + onBeforeHeaderRowCellDestroy: new SlickEvent(), + onHeaderRowCellRendered: new SlickEvent(), render: jest.fn(), setColumns: jest.fn(), setHeaderRowVisibility: jest.fn(), setSortColumns: jest.fn(), setOptions: jest.fn(), -} as unknown as SlickGrid; +} as unknown as SlickGridUniversal; const pubSubServiceStub = { publish: jest.fn(), @@ -173,7 +170,7 @@ describe('FilterService', () => { service.init(gridStub); service.bindBackendOnFilter(gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs as any, new Slick.EventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs as any, new SlickEventData(), gridStub); const columnFilters = service.getColumnFilters(); const filterMetadataArray = service.getFiltersMetadata(); const destroySpy = jest.spyOn(filterMetadataArray[0], 'destroy'); @@ -183,7 +180,7 @@ describe('FilterService', () => { expect(filterMetadataArray[0] instanceof InputFilter).toBeTruthy(); expect(filterMetadataArray[0]).toContainEntry(['searchTerms', []]); - gridStub.onBeforeHeaderRowCellDestroy.notify(mockArgs as any, new Slick.EventData(), gridStub); + gridStub.onBeforeHeaderRowCellDestroy.notify(mockArgs as any, new SlickEventData(), gridStub); expect(destroySpy).toHaveBeenCalled(); }); @@ -198,8 +195,8 @@ describe('FilterService', () => { service.init(gridStub); service.bindBackendOnFilter(gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs as any, new Slick.EventData(), gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs as any, new Slick.EventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs as any, new SlickEventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs as any, new SlickEventData(), gridStub); const columnFilters = service.getColumnFilters(); const filterMetadataArray = service.getFiltersMetadata(); const destroySpy = jest.spyOn(filterMetadataArray[0], 'destroy'); @@ -212,7 +209,7 @@ describe('FilterService', () => { expect(filterMetadataArray[0] instanceof NativeSelectFilter).toBeTruthy(); expect(filterMetadataArray[0]).toContainEntry(['searchTerms', [true]]); - gridStub.onBeforeHeaderRowCellDestroy.notify(mockArgs as any, new Slick.EventData(), gridStub); + gridStub.onBeforeHeaderRowCellDestroy.notify(mockArgs as any, new SlickEventData(), gridStub); expect(destroySpy).toHaveBeenCalled(); }); @@ -240,8 +237,8 @@ describe('FilterService', () => { service.init(gridStub); service.bindBackendOnFilter(gridStub); - gridStub.onHeaderRowCellRendered.notify(mockHeaderArgs as any, new Slick.EventData(), gridStub); - service.onSearchChange!.notify(mockSearchArgs, new Slick.EventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockHeaderArgs as any, new SlickEventData(), gridStub); + service.onSearchChange!.notify(mockSearchArgs, new SlickEventData(), gridStub); expect(spyBackendChange).toHaveBeenCalledWith(expect.anything(), mockSearchArgs); setTimeout(() => { @@ -267,7 +264,7 @@ describe('FilterService', () => { service.init(gridStub); service.bindLocalOnFilter(gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs as any, new Slick.EventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs as any, new SlickEventData(), gridStub); const columnFilters = service.getColumnFilters(); const filterMetadataArray = service.getFiltersMetadata(); const destroySpy = jest.spyOn(filterMetadataArray[0], 'destroy'); @@ -277,7 +274,7 @@ describe('FilterService', () => { expect(filterMetadataArray[0] instanceof InputFilter).toBeTruthy(); expect(filterMetadataArray[0]).toContainEntry(['searchTerms', []]); - gridStub.onBeforeHeaderRowCellDestroy.notify(mockArgs as any, new Slick.EventData(), gridStub); + gridStub.onBeforeHeaderRowCellDestroy.notify(mockArgs as any, new SlickEventData(), gridStub); expect(destroySpy).toHaveBeenCalled(); }); @@ -295,7 +292,7 @@ describe('FilterService', () => { service.init(gridStub); service.bindLocalOnFilter(gridStub); - service.onSearchChange!.notify(mockArgs as any, new Slick.EventData(), gridStub); + service.onSearchChange!.notify(mockArgs as any, new SlickEventData(), gridStub); setTimeout(() => { expect(pubSubSpy).toHaveBeenCalledWith(`onBeforeFilterChange`, []); @@ -329,8 +326,8 @@ describe('FilterService', () => { service.init(gridStub); service.bindLocalOnFilter(gridStub); - gridStub.onHeaderRowCellRendered.notify(mockHeaderArgs as any, new Slick.EventData(), gridStub); - service.onSearchChange!.notify(mockSearchArgs, new Slick.EventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockHeaderArgs as any, new SlickEventData(), gridStub); + service.onSearchChange!.notify(mockSearchArgs, new SlickEventData(), gridStub); setTimeout(() => { expect(pubSubSpy).toHaveBeenCalledWith(`onBeforeFilterChange`, [{ columnId: 'firstName', operator: 'EQ', searchTerms: [true] }]); @@ -359,7 +356,7 @@ describe('FilterService', () => { service.init(gridStub); service.bindLocalOnFilter(gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs as any, new Slick.EventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs as any, new SlickEventData(), gridStub); service.getFiltersMetadata()[0].callback(new Event('input'), { columnDef: mockColumn, operator: 'EQ', searchTerms: ['John'], shouldTriggerQuery: true }); setTimeout(() => { @@ -388,7 +385,7 @@ describe('FilterService', () => { service.init(gridStub); service.bindLocalOnFilter(gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs as any, new Slick.EventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs as any, new SlickEventData(), gridStub); const mockEvent = new Event('input'); Object.defineProperty(mockEvent, 'target', { writable: true, configurable: true, value: { value: 'John' } }); @@ -412,7 +409,7 @@ describe('FilterService', () => { it('should delete the column filters entry (from column filter object) when searchTerms is empty', () => { service.init(gridStub); service.bindLocalOnFilter(gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs as any, new Slick.EventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs as any, new SlickEventData(), gridStub); service.getFiltersMetadata()[0].callback(new Event('input'), { columnDef: mockColumn, operator: 'EQ', searchTerms: [''], shouldTriggerQuery: true }); expect(service.getColumnFilters()).toEqual({}); @@ -426,7 +423,7 @@ describe('FilterService', () => { service.init(gridStub); service.bindLocalOnFilter(gridStub); mockArgs.column.filter = { emptySearchTermReturnAllValues: false }; - gridStub.onHeaderRowCellRendered.notify(mockArgs as any, new Slick.EventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs as any, new SlickEventData(), gridStub); const tmpDivElm = document.createElement('div'); tmpDivElm.className = 'some-classes'; const inputEvent = new Event('input'); @@ -452,7 +449,7 @@ describe('FilterService', () => { it('should delete the column filters entry (from column filter object) when searchTerms is empty array and even when triggered event is undefined', () => { service.init(gridStub); service.bindLocalOnFilter(gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs as any, new Slick.EventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs as any, new SlickEventData(), gridStub); service.getFiltersMetadata()[0].callback(undefined, { columnDef: mockColumn, operator: 'EQ', searchTerms: [], shouldTriggerQuery: true }); expect(service.getColumnFilters()).toEqual({}); @@ -461,7 +458,7 @@ describe('FilterService', () => { it('should delete the column filters entry (from column filter object) when searchTerms & operator are undefined or not provided', () => { service.init(gridStub); service.bindLocalOnFilter(gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs as any, new Slick.EventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs as any, new SlickEventData(), gridStub); service.getFiltersMetadata()[0].callback(undefined, { columnDef: mockColumn, shouldTriggerQuery: true }); expect(service.getColumnFilters()).toEqual({}); @@ -490,9 +487,9 @@ describe('FilterService', () => { service.init(gridStub); service.bindBackendOnFilter(gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new Slick.EventData(), gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new Slick.EventData(), gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs3 as any, new Slick.EventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new SlickEventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new SlickEventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs3 as any, new SlickEventData(), gridStub); service.getFiltersMetadata()[1].callback(new Event('input'), { columnDef: mockColumn3 }); service.getFiltersMetadata()[0].callback(new Event('input'), { columnDef: mockColumn1, operator: 'EQ', searchTerms: ['John'], shouldTriggerQuery: true }); service.getFiltersMetadata()[1].callback(new Event('input'), { columnDef: mockColumn2, operator: 'NE', searchTerms: ['Doe'], shouldTriggerQuery: true }); @@ -633,8 +630,8 @@ describe('FilterService', () => { service.init(gridStub); service.bindLocalOnFilter(gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new Slick.EventData(), gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new Slick.EventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new SlickEventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new SlickEventData(), gridStub); service.getFiltersMetadata()[0].callback(new Event('input'), { columnDef: mockColumn1, operator: 'EQ', searchTerms: ['John'], shouldTriggerQuery: true }); service.getFiltersMetadata()[1].callback(new Event('input'), { columnDef: mockColumn2, operator: 'NE', searchTerms: ['Doe'], shouldTriggerQuery: true }); }); @@ -1073,7 +1070,7 @@ describe('FilterService', () => { }); it('should return an empty array when column definitions returns nothing as well', () => { - gridStub.getColumns = jest.fn().mockReturnValue(undefined); + jest.spyOn(gridStub, 'getColumns').mockReturnValue([]); service.init(gridStub); const output = service.populateColumnFilterSearchTermPresets(undefined as any); @@ -1241,8 +1238,8 @@ describe('FilterService', () => { service.init(gridStub); service.bindLocalOnFilter(gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new Slick.EventData(), gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new Slick.EventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new SlickEventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new SlickEventData(), gridStub); await service.updateFilters(mockNewFilters); expect(emitSpy).toHaveBeenCalledWith('local'); @@ -1260,8 +1257,8 @@ describe('FilterService', () => { gridOptionMock.resetFilterSearchValueAfterOnBeforeCancellation = true; service.init(gridStub); service.bindLocalOnFilter(gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new Slick.EventData(), gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new Slick.EventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new SlickEventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new SlickEventData(), gridStub); await service.updateFilters(mockNewFilters, false, false, true); expect(pubSubSpy).toHaveBeenCalledWith('onBeforeSearchChange', expect.toBeObject()); @@ -1275,8 +1272,8 @@ describe('FilterService', () => { service.init(gridStub); service.bindLocalOnFilter(gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new Slick.EventData(), gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new Slick.EventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new SlickEventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new SlickEventData(), gridStub); await service.updateFilters(mockNewFilters, false); expect(emitSpy).not.toHaveBeenCalled(); @@ -1301,8 +1298,8 @@ describe('FilterService', () => { service.init(gridStub); service.bindBackendOnFilter(gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new Slick.EventData(), gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new Slick.EventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new SlickEventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new SlickEventData(), gridStub); await service.updateFilters(mockNewFilters); expect(emitSpy).toHaveBeenCalledWith('remote'); @@ -1331,8 +1328,8 @@ describe('FilterService', () => { service.init(gridStub); service.bindBackendOnFilter(gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new Slick.EventData(), gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new Slick.EventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new SlickEventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new SlickEventData(), gridStub); await service.updateFilters(mockNewFilters, false, false); expect(backendProcessSpy).not.toHaveBeenCalled(); @@ -1354,8 +1351,8 @@ describe('FilterService', () => { gridOptionMock.enableTreeData = true; service.init(gridStub); service.bindLocalOnFilter(gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new Slick.EventData(), gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new Slick.EventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new SlickEventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new SlickEventData(), gridStub); await service.updateFilters(mockNewFilters.slice(0, 1), true, false, true); expect(emitSpy).toHaveBeenCalledWith('local'); @@ -1384,8 +1381,8 @@ describe('FilterService', () => { gridOptionMock.enableTreeData = true; service.init(gridStub); service.bindLocalOnFilter(gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new Slick.EventData(), gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new Slick.EventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new SlickEventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new SlickEventData(), gridStub); await service.updateFilters(mockNewFilters.slice(0, 1)); expect(emitSpy).toHaveBeenCalledWith('local'); @@ -1433,8 +1430,8 @@ describe('FilterService', () => { const refreshSpy = jest.spyOn(dataViewStub, 'refresh'); service.init(gridStub); service.bindLocalOnFilter(gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new Slick.EventData(), gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new Slick.EventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new SlickEventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new SlickEventData(), gridStub); await service.updateSingleFilter({ columnId: 'firstName', searchTerms: ['Jane'], operator: 'StartsWith' }); expect(setFilterArgsSpy).toHaveBeenCalledWith({ columnFilters: expectation, grid: gridStub }); @@ -1456,8 +1453,8 @@ describe('FilterService', () => { service.bindLocalOnFilter(gridStub); mockArgs1.column.filter = { emptySearchTermReturnAllValues: false }; mockArgs2.column.filter = { emptySearchTermReturnAllValues: false }; - gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new Slick.EventData(), gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new Slick.EventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new SlickEventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new SlickEventData(), gridStub); await service.updateSingleFilter({ columnId: 'firstName', searchTerms: [''], operator: 'StartsWith' }); expect(setFilterArgsSpy).toHaveBeenCalledWith({ columnFilters: expectation, grid: gridStub }); @@ -1485,8 +1482,8 @@ describe('FilterService', () => { service.init(gridStub); service.bindBackendOnFilter(gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new Slick.EventData(), gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new Slick.EventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new SlickEventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new SlickEventData(), gridStub); await service.updateSingleFilter({ columnId: 'firstName', searchTerms: ['Jane'], operator: 'StartsWith' }); expect(emitSpy).toHaveBeenCalledWith('remote'); @@ -1512,8 +1509,8 @@ describe('FilterService', () => { service.init(gridStub); service.bindBackendOnFilter(gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new Slick.EventData(), gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new Slick.EventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new SlickEventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new SlickEventData(), gridStub); await service.updateSingleFilter({ columnId: 'firstName', searchTerms: ['Jane'], operator: 'StartsWith' }, false, false); expect(backendProcessSpy).not.toHaveBeenCalled(); @@ -1692,8 +1689,8 @@ describe('FilterService', () => { it('should Draw DOM Element Filter on custom HTML element by string id', async () => { service.init(gridStub); service.bindLocalOnFilter(gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new Slick.EventData(), gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new Slick.EventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new SlickEventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new SlickEventData(), gridStub); await service.updateFilters(mockNewFilters); const columnFilterMetadada = service.drawFilterTemplate('name', `#${DOM_ELEMENT_ID}`); @@ -1706,8 +1703,8 @@ describe('FilterService', () => { it('should Draw DOM Element Filter on custom HTML element by string id with searchTerms', async () => { service.init(gridStub); service.bindLocalOnFilter(gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new Slick.EventData(), gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new Slick.EventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new SlickEventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new SlickEventData(), gridStub); await service.updateFilters(mockNewFilters); const columnFilterMetadada = service.drawFilterTemplate('firstName', `#${DOM_ELEMENT_ID}`); @@ -1720,8 +1717,8 @@ describe('FilterService', () => { it('should Draw DOM Element Filter on custom HTML element by HTMLDivElement', async () => { service.init(gridStub); service.bindLocalOnFilter(gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new Slick.EventData(), gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new Slick.EventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new SlickEventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new SlickEventData(), gridStub); await service.updateFilters(mockNewFilters); const filterContainerElm = document.querySelector(`#${DOM_ELEMENT_ID}`) as HTMLDivElement; @@ -1735,8 +1732,8 @@ describe('FilterService', () => { it('should Draw DOM Element Filter on custom HTML element return null', async () => { service.init(gridStub); service.bindLocalOnFilter(gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new Slick.EventData(), gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new Slick.EventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new SlickEventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new SlickEventData(), gridStub); await service.updateFilters(mockNewFilters); const filterContainerElm = document.querySelector(`#${DOM_ELEMENT_ID}`) as HTMLDivElement; @@ -1774,7 +1771,7 @@ describe('FilterService', () => { service.init(gridStub); service.bindLocalOnFilter(gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs as any, new Slick.EventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs as any, new SlickEventData(), gridStub); const columnFilters = service.getColumnFilters(); const filterMetadataArray = service.getFiltersMetadata(); @@ -1865,8 +1862,8 @@ describe('FilterService', () => { service.init(gridStub); service.bindLocalOnFilter(gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new Slick.EventData(), gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new Slick.EventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new SlickEventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new SlickEventData(), gridStub); const columnFilters = { file: { columnDef: mockColumn1, columnId: 'file', operator: 'Contains', searchTerms: ['map'], parsedSearchTerms: ['map'], targetSelector: '', type: FieldType.string } } as ColumnFilters; await service.updateFilters([{ columnId: 'file', operator: '', searchTerms: ['map'] }], true, true, true); @@ -1891,8 +1888,8 @@ describe('FilterService', () => { service.init(gridStub); service.bindLocalOnFilter(gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new Slick.EventData(), gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new Slick.EventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new SlickEventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new SlickEventData(), gridStub); const columnFilters = { file: { columnDef: mockColumn1, columnId: 'file', operator: 'Contains', searchTerms: ['map'], parsedSearchTerms: ['map'], targetSelector: '', type: FieldType.string } } as ColumnFilters; await service.updateFilters([{ columnId: 'file', operator: '', searchTerms: ['map'] }], true, true, true); @@ -1920,8 +1917,8 @@ describe('FilterService', () => { service.init(gridStub); service.bindLocalOnFilter(gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new Slick.EventData(), gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new Slick.EventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new SlickEventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new SlickEventData(), gridStub); const columnFilters = { file: { columnDef: mockColumn1, columnId: 'file', operator: 'Contains', searchTerms: ['map'], parsedSearchTerms: ['map'], targetSelector: '', type: FieldType.string } } as ColumnFilters; await service.updateFilters([{ columnId: 'file', operator: '', searchTerms: ['map'] }], true, true, true); @@ -1946,8 +1943,8 @@ describe('FilterService', () => { service.init(gridStub); service.bindLocalOnFilter(gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new Slick.EventData(), gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new Slick.EventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new SlickEventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new SlickEventData(), gridStub); const columnFilters = { file: { columnDef: mockColumn1, columnId: 'file', operator: 'Contains', searchTerms: ['map'], parsedSearchTerms: ['map'], targetSelector: '', type: FieldType.string } } as ColumnFilters; await service.updateFilters([{ columnId: 'file', operator: '', searchTerms: ['map'] }], true, true, true); @@ -1971,8 +1968,8 @@ describe('FilterService', () => { service.init(gridStub); service.bindLocalOnFilter(gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new Slick.EventData(), gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new Slick.EventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new SlickEventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new SlickEventData(), gridStub); const columnFilters = { file: { columnDef: mockColumn1, columnId: 'file', searchTerms: ['unknown'], targetSelector: '', type: FieldType.string } } as ColumnFilters; await service.updateFilters([{ columnId: 'file', operator: '', searchTerms: ['unknown'] }], true, true, true); @@ -1996,8 +1993,8 @@ describe('FilterService', () => { service.init(gridStub); service.bindLocalOnFilter(gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new Slick.EventData(), gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new Slick.EventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new SlickEventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new SlickEventData(), gridStub); const columnFilters = { file: { columnDef: mockColumn1, columnId: 'file', searchTerms: ['unknown'], type: FieldType.string } } as ColumnFilters; await service.updateSingleFilter({ columnId: 'file', operator: 'Contains', searchTerms: ['unknown'] }, true, true); @@ -2024,8 +2021,8 @@ describe('FilterService', () => { service.init(gridStub); service.bindLocalOnFilter(gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new Slick.EventData(), gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new Slick.EventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new SlickEventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new SlickEventData(), gridStub); const columnFilters = { file: { columnDef: mockColumn1, columnId: 'file', operator: 'Contains', searchTerms: ['misc'], parsedSearchTerms: ['misc'], targetSelector: '', type: FieldType.string } } as ColumnFilters; await service.updateFilters([{ columnId: 'file', operator: '', searchTerms: ['misc'] }], true, true, true); @@ -2050,8 +2047,8 @@ describe('FilterService', () => { service.init(gridStub); service.bindLocalOnFilter(gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new Slick.EventData(), gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new Slick.EventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new SlickEventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new SlickEventData(), gridStub); const columnFilters = { file: { columnDef: mockColumn1, columnId: 'file', operator: 'Contains', searchTerms: ['misc'], parsedSearchTerms: ['misc'], targetSelector: '', type: FieldType.string } } as ColumnFilters; await service.updateFilters([{ columnId: 'file', operator: '', searchTerms: ['misc'] }], true, true, true); @@ -2077,8 +2074,8 @@ describe('FilterService', () => { service.init(gridStub); service.bindLocalOnFilter(gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new Slick.EventData(), gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new Slick.EventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new SlickEventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new SlickEventData(), gridStub); const columnFilters = { file: { columnDef: mockColumn1, columnId: 'file', operator: 'Contains', searchTerms: ['misc'], parsedSearchTerms: ['misc'], targetSelector: '', type: FieldType.string }, @@ -2106,9 +2103,9 @@ describe('FilterService', () => { service.init(gridStub); service.bindLocalOnFilter(gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new Slick.EventData(), gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new Slick.EventData(), gridStub); - gridStub.onHeaderRowCellRendered.notify(mockArgs3 as any, new Slick.EventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new SlickEventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new SlickEventData(), gridStub); + gridStub.onHeaderRowCellRendered.notify(mockArgs3 as any, new SlickEventData(), gridStub); const columnFilters = { size: { columnDef: mockColumn3, columnId: 'size', operator: '<', searchTerms: ['0.1'], parsedSearchTerms: ['0.1'], targetSelector: '', type: FieldType.string }, diff --git a/packages/common/src/services/__tests__/grid.service.spec.ts b/packages/common/src/services/__tests__/grid.service.spec.ts index c911d44da..3c943b9a1 100644 --- a/packages/common/src/services/__tests__/grid.service.spec.ts +++ b/packages/common/src/services/__tests__/grid.service.spec.ts @@ -1,11 +1,11 @@ import 'jest-extended'; import { BasePubSubService } from '@slickgrid-universal/event-pub-sub'; +import { type SlickDataView, SlickEvent } from 'slickgrid'; import { FilterService, GridService, GridStateService, PaginationService, SharedService, SortService, TreeDataService } from '../index'; -import { GridOption, CellArgs, Column, OnEventArgs, SlickGrid, SlickDataView, SlickNamespace } from '../../interfaces/index'; +import { GridOption, CellArgs, Column, OnEventArgs, SlickGridUniversal } from '../../interfaces/index'; import { SlickRowSelectionModel } from '../../extensions/slickRowSelectionModel'; -declare const Slick: SlickNamespace; jest.useFakeTimers(); jest.mock('flatpickr', () => { }); @@ -18,7 +18,7 @@ const mockRowSelectionModel = { setSelectedRows: jest.fn(), getSelectedRanges: jest.fn(), setSelectedRanges: jest.fn(), - onSelectedRangesChanged: new Slick.Event(), + onSelectedRangesChanged: new SlickEvent(), } as unknown as SlickRowSelectionModel; jest.mock('../../extensions/slickRowSelectionModel', () => ({ @@ -87,7 +87,7 @@ const gridStub = { setSelectedRows: jest.fn(), scrollRowIntoView: jest.fn(), updateRow: jest.fn(), -} as unknown as SlickGrid; +} as unknown as SlickGridUniversal; const paginationServiceStub = { goToFirstPage: jest.fn(), @@ -605,7 +605,7 @@ describe('Grid Service', () => { }); it('should throw an error when 1st argument for the item object is missing', () => { - jest.spyOn(gridStub, 'getOptions').mockReturnValue(undefined as any); + jest.spyOn(gridStub, 'getData').mockReturnValueOnce(undefined as any); expect(() => service.addItem(null as any)).toThrowError('[Slickgrid-Universal] We could not find SlickGrid Grid, DataView objects'); }); diff --git a/packages/common/src/services/__tests__/gridEvent.service.spec.ts b/packages/common/src/services/__tests__/gridEvent.service.spec.ts index 6202e156d..ee2042ad7 100644 --- a/packages/common/src/services/__tests__/gridEvent.service.spec.ts +++ b/packages/common/src/services/__tests__/gridEvent.service.spec.ts @@ -1,7 +1,7 @@ -import { GridEventService } from '../gridEvent.service'; -import { Column, SlickDataView, SlickGrid, SlickNamespace } from '../../interfaces/index'; +import { type SlickDataView, SlickEvent, SlickEventData } from 'slickgrid'; -declare const Slick: SlickNamespace; +import { GridEventService } from '../gridEvent.service'; +import { Column, SlickGridUniversal } from '../../interfaces/index'; const dataViewStub = { refresh: jest.fn(), @@ -18,10 +18,10 @@ const gridStub = { setActiveCell: jest.fn(), setColumns: jest.fn(), setSortColumns: jest.fn(), - onBeforeEditCell: new Slick.Event(), - onCellChange: new Slick.Event(), - onClick: new Slick.Event(), -} as unknown as SlickGrid; + onBeforeEditCell: new SlickEvent(), + onCellChange: new SlickEvent(), + onClick: new SlickEvent(), +} as unknown as SlickGridUniversal; describe('GridEventService', () => { let service: GridEventService; @@ -48,7 +48,7 @@ describe('GridEventService', () => { const spyGetCols = jest.spyOn(gridStub, 'getColumns').mockReturnValue([mockColumn]); service.bindOnBeforeEditCell(gridStub); - gridStub.onBeforeEditCell.notify(undefined as any, new Slick.EventData(), gridStub); + gridStub.onBeforeEditCell.notify(undefined as any, new SlickEventData(), gridStub); expect(spyGetCols).not.toHaveBeenCalled(); }); @@ -57,7 +57,7 @@ describe('GridEventService', () => { const spyGetCols = jest.spyOn(gridStub, 'getColumns').mockReturnValue([mockColumn]); service.bindOnBeforeEditCell(gridStub); - gridStub.onBeforeEditCell.notify({ cell: undefined as any, row: undefined as any, grid: gridStub, column: {} as Column, item: {} }, new Slick.EventData(), gridStub); + gridStub.onBeforeEditCell.notify({ cell: undefined as any, row: undefined as any, grid: gridStub, column: {} as Column, item: {} }, new SlickEventData(), gridStub); expect(spyGetCols).not.toHaveBeenCalled(); }); @@ -68,7 +68,7 @@ describe('GridEventService', () => { const spyOnChange = jest.spyOn(mockColumn, 'onBeforeEditCell'); service.bindOnBeforeEditCell(gridStub); - gridStub.onBeforeEditCell.notify({ cell: 0, row: 0, grid: gridStub, column: {} as Column, item: {}, target: 'grid' }, new Slick.EventData(), gridStub); + gridStub.onBeforeEditCell.notify({ cell: 0, row: 0, grid: gridStub, column: {} as Column, item: {}, target: 'grid' }, new SlickEventData(), gridStub); expect(spyGetCols).toHaveBeenCalled(); expect(spyGetData).toHaveBeenCalled(); @@ -96,7 +96,7 @@ describe('GridEventService', () => { const spyGetCols = jest.spyOn(gridStub, 'getColumns').mockReturnValue([mockColumn]); service.bindOnCellChange(gridStub); - gridStub.onCellChange.notify(undefined as any, new Slick.EventData(), gridStub); + gridStub.onCellChange.notify(undefined as any, new SlickEventData(), gridStub); expect(spyGetCols).not.toHaveBeenCalled(); }); @@ -105,7 +105,7 @@ describe('GridEventService', () => { const spyGetCols = jest.spyOn(gridStub, 'getColumns').mockReturnValue([mockColumn]); service.bindOnCellChange(gridStub); - gridStub.onCellChange.notify({ cell: undefined as any, row: undefined as any, grid: gridStub, item: {}, column: {} as Column }, new Slick.EventData(), gridStub); + gridStub.onCellChange.notify({ cell: undefined as any, row: undefined as any, grid: gridStub, item: {}, column: {} as Column }, new SlickEventData(), gridStub); expect(spyGetCols).not.toHaveBeenCalled(); }); @@ -116,7 +116,7 @@ describe('GridEventService', () => { const spyOnChange = jest.spyOn(mockColumn, 'onCellChange'); service.bindOnCellChange(gridStub); - gridStub.onCellChange.notify({ cell: 0, row: 0, grid: gridStub, item: {}, column: {} as Column }, new Slick.EventData(), gridStub); + gridStub.onCellChange.notify({ cell: 0, row: 0, grid: gridStub, item: {}, column: {} as Column }, new SlickEventData(), gridStub); expect(spyGetCols).toHaveBeenCalled(); expect(spyGetData).toHaveBeenCalled(); @@ -144,7 +144,7 @@ describe('GridEventService', () => { const spyGetCols = jest.spyOn(gridStub, 'getColumns').mockReturnValue([mockColumn]); service.bindOnClick(gridStub); - gridStub.onClick.notify(undefined as any, new Slick.EventData(), gridStub); + gridStub.onClick.notify(undefined as any, new SlickEventData(), gridStub); expect(spyGetCols).not.toHaveBeenCalled(); }); @@ -153,7 +153,7 @@ describe('GridEventService', () => { const spyGetCols = jest.spyOn(gridStub, 'getColumns').mockReturnValue([mockColumn]); service.bindOnClick(gridStub); - gridStub.onClick.notify({ cell: undefined as any, row: undefined as any, grid: gridStub, }, new Slick.EventData(), gridStub); + gridStub.onClick.notify({ cell: undefined as any, row: undefined as any, grid: gridStub, }, new SlickEventData(), gridStub); expect(spyGetCols).not.toHaveBeenCalled(); }); @@ -165,7 +165,7 @@ describe('GridEventService', () => { const spyOnChange = jest.spyOn(mockColumn, 'onCellClick'); service.bindOnClick(gridStub); - gridStub.onClick.notify({ cell: 0, row: 0, grid: gridStub }, new Slick.EventData(), gridStub); + gridStub.onClick.notify({ cell: 0, row: 0, grid: gridStub }, new SlickEventData(), gridStub); expect(spyGetCols).toHaveBeenCalled(); expect(spyGetData).toHaveBeenCalled(); diff --git a/packages/common/src/services/__tests__/gridState.service.spec.ts b/packages/common/src/services/__tests__/gridState.service.spec.ts index 7bb3d99dd..2e80e6854 100644 --- a/packages/common/src/services/__tests__/gridState.service.spec.ts +++ b/packages/common/src/services/__tests__/gridState.service.spec.ts @@ -1,4 +1,5 @@ import { BasePubSubService } from '@slickgrid-universal/event-pub-sub'; +import { type SlickDataView, SlickEvent, SlickEventData } from 'slickgrid'; import { ExtensionService } from '../extension.service'; import { FilterService } from '../filter.service'; @@ -19,20 +20,17 @@ import { CurrentFilter, CurrentColumn, GridOption, - SlickDataView, GridStateChange, GridState, RowDetailView, RowMoveManager, - SlickGrid, - SlickNamespace, - SlickRowSelectionModel, + SlickGridUniversal, TreeToggleStateChange, } from '../../interfaces/index'; import { SharedService } from '../shared.service'; import { TreeDataService } from '../treeData.service'; - -declare const Slick: SlickNamespace; +import { SlickRowSelectionModel } from '../../extensions/slickRowSelectionModel'; +import { SlickColumnPicker } from '../../extensions/slickColumnPicker'; const fnCallbacks = {}; const mockPubSub = { @@ -64,9 +62,9 @@ const dataViewStub = { getFilteredItems: jest.fn(), mapIdsToRows: jest.fn(), mapRowsToIds: jest.fn(), - onBeforePagingInfoChanged: new Slick.Event(), - onPagingInfoChanged: new Slick.Event(), - onSelectedRowIdsChanged: new Slick.Event(), + onBeforePagingInfoChanged: new SlickEvent(), + onPagingInfoChanged: new SlickEvent(), + onSelectedRowIdsChanged: new SlickEvent(), } as unknown as SlickDataView; const gridStub = { @@ -79,11 +77,11 @@ const gridStub = { getSelectedRows: jest.fn(), setColumns: jest.fn(), setSelectedRows: jest.fn(), - onColumnsReordered: new Slick.Event(), - onColumnsResized: new Slick.Event(), - onSetOptions: new Slick.Event(), - onSelectedRowsChanged: new Slick.Event(), -} as unknown as SlickGrid; + onColumnsReordered: new SlickEvent(), + onColumnsResized: new SlickEvent(), + onSetOptions: new SlickEvent(), + onSelectedRowsChanged: new SlickEvent(), +} as unknown as SlickGridUniversal; const extensionServiceStub = { getExtensionByName: (_name: string) => { } @@ -108,8 +106,8 @@ const rowSelectionModelStub = { setSelectedRanges: jest.fn(), getSelectedRows: jest.fn(), setSelectedRows: jest.fn(), - onSelectedRangesChanged: new Slick.Event(), -} as SlickRowSelectionModel; + onSelectedRangesChanged: new SlickEvent(), +} as unknown as SlickRowSelectionModel; describe('GridStateService', () => { let service: GridStateService; @@ -134,7 +132,7 @@ describe('GridStateService', () => { let slickgridEvent; beforeEach(() => { - slickgridEvent = new Slick.Event(); + slickgridEvent = new SlickEvent(); }); afterEach(() => { @@ -308,7 +306,7 @@ describe('GridStateService', () => { service.init(gridStub); jest.spyOn(gridStub, 'getSelectionModel').mockReturnValue(rowSelectionModelStub); - slickgridEvent.notify({ columns: columnsMock }, new Slick.EventData(), gridStub); + slickgridEvent.notify({ columns: columnsMock }, new SlickEventData(), gridStub); expect(gridStateSpy).toHaveBeenCalled(); expect(pubSubSpy).toHaveBeenNthCalledWith(1, `onGridStateChanged`, stateChangeMock); @@ -332,7 +330,7 @@ describe('GridStateService', () => { service.init(gridStub); jest.spyOn(gridStub, 'getSelectionModel').mockReturnValue(rowSelectionModelStub); - gridStub.onColumnsReordered.notify({ impactedColumns: columnsMock, grid: gridStub }, new Slick.EventData(), gridStub); + gridStub.onColumnsReordered.notify({ impactedColumns: columnsMock, grid: gridStub }, new SlickEventData(), gridStub); service.resetColumns(); expect(gridColumnSpy).toHaveBeenCalled(); @@ -353,7 +351,7 @@ describe('GridStateService', () => { const gridStateSpy = jest.spyOn(service, 'getCurrentGridState').mockReturnValue(gridStateMock); service.init(gridStub); - gridStub.onSetOptions.notify({ optionsBefore: mockGridOptionsBefore, optionsAfter: mockGridOptionsAfter, grid: gridStub }, new Slick.EventData()); + gridStub.onSetOptions.notify({ optionsBefore: mockGridOptionsBefore, optionsAfter: mockGridOptionsAfter, grid: gridStub }, new SlickEventData()); expect(gridStateSpy).toHaveBeenCalled(); expect(pubSubSpy).toHaveBeenCalledWith(`onGridStateChanged`, stateChangeMock); @@ -674,7 +672,7 @@ describe('GridStateService', () => { }); it('should return null when no BackendService is used and FilterService is missing the "getCurrentLocalFilters" method', () => { - gridStub.getOptions = undefined as any; + gridStub.getOptions = () => undefined as any; const output = service.getCurrentFilters(); expect(output).toBeNull(); }); diff --git a/packages/common/src/services/__tests__/groupingAndColspan.service.spec.ts b/packages/common/src/services/__tests__/groupingAndColspan.service.spec.ts index 694e6e25a..fa8d63291 100644 --- a/packages/common/src/services/__tests__/groupingAndColspan.service.spec.ts +++ b/packages/common/src/services/__tests__/groupingAndColspan.service.spec.ts @@ -1,9 +1,9 @@ -// @ts-nocheck +import { type SlickDataView, SlickEvent, SlickEventData, SlickEventHandler, } from 'slickgrid'; + import { GroupingAndColspanService } from '../groupingAndColspan.service'; -import { Column, SlickDataView, GridOption, SlickEventHandler, SlickGrid, SlickNamespace } from '../../interfaces/index'; +import { Column, GridOption, SlickGridUniversal } from '../../interfaces/index'; import { ExtensionUtility } from '../../extensions/extensionUtility'; -declare const Slick: SlickNamespace; const gridId = 'grid1'; const gridUid = 'slickgrid_124343'; const containerId = 'demo-container'; @@ -28,14 +28,15 @@ const gridOptionMock = { const dataViewStub = { refresh: jest.fn(), sort: jest.fn(), - onRowCountChanged: new Slick.Event(), + onRowCountChanged: new SlickEvent(), reSort: jest.fn(), } as unknown as SlickDataView; const resizerPluginStub = { + pluginName: 'resizer', init: jest.fn(), destroy: jest.fn(), - onGridAfterResize: new Slick.Event(), + onGridAfterResize: new SlickEvent(), }; const gridStub = { @@ -52,17 +53,17 @@ const gridStub = { getPreHeaderPanelRight: jest.fn(), getSortColumns: jest.fn(), invalidate: jest.fn(), - onAutosizeColumns: new Slick.Event(), - onColumnsReordered: new Slick.Event(), - onColumnsResized: new Slick.Event(), - onRendered: new Slick.Event(), - onSetOptions: new Slick.Event(), - onSort: new Slick.Event(), + onAutosizeColumns: new SlickEvent(), + onColumnsReordered: new SlickEvent(), + onColumnsResized: new SlickEvent(), + onRendered: new SlickEvent(), + onSetOptions: new SlickEvent(), + onSort: new SlickEvent(), render: jest.fn(), setColumns: jest.fn(), setOptions: jest.fn(), setSortColumns: jest.fn(), -} as unknown as SlickGrid; +} as unknown as SlickGridUniversal; const mockExtensionUtility = { translateItems: jest.fn(), @@ -114,7 +115,7 @@ describe('GroupingAndColspanService', () => { }); it('should not call the "renderPreHeaderRowGroupingTitles" when there are no grid options', () => { - gridStub.getOptions = undefined; + gridStub.getOptions = () => undefined as any; const spy = jest.spyOn(service, 'renderPreHeaderRowGroupingTitles'); service.init(gridStub); expect(spy).not.toHaveBeenCalled(); @@ -122,7 +123,7 @@ describe('GroupingAndColspanService', () => { describe('init method', () => { let mockColumns: Column[]; - let setTimeoutSpy: jest.Mock; + let setTimeoutSpy: any; beforeEach(() => { const mockParentPreHeaderElm = document.createElement('div'); @@ -152,7 +153,7 @@ describe('GroupingAndColspanService', () => { it('should call the "renderPreHeaderRowGroupingTitles" on initial load even when there are no column definitions', () => { const renderSpy = jest.spyOn(service, 'renderPreHeaderRowGroupingTitles'); - gridStub.getColumns = undefined; + gridStub.getColumns = () => undefined as any; service.init(gridStub); jest.runAllTimers(); // fast-forward timer @@ -166,7 +167,7 @@ describe('GroupingAndColspanService', () => { const renderSpy = jest.spyOn(service, 'renderPreHeaderRowGroupingTitles'); service.init(gridStub); - gridStub.onSort.notify({ columnId: 'lastName', sortAsc: true, sortCol: mockColumns[0] }, new Slick.EventData(), gridStub); + gridStub.onSort.notify({ columnId: 'lastName', sortAsc: true, sortCol: mockColumns[0] }, new SlickEventData(), gridStub); jest.runAllTimers(); // fast-forward timer expect(renderSpy).toHaveBeenCalledTimes(2); @@ -178,7 +179,7 @@ describe('GroupingAndColspanService', () => { const renderSpy = jest.spyOn(service, 'renderPreHeaderRowGroupingTitles'); service.init(gridStub); - gridStub.onAutosizeColumns.notify({ columns: [], grid: gridStub }, new Slick.EventData(), gridStub); + gridStub.onAutosizeColumns.notify({ columns: [], grid: gridStub }, new SlickEventData(), gridStub); jest.runAllTimers(); // fast-forward timer expect(renderSpy).toHaveBeenCalledTimes(2); @@ -190,7 +191,7 @@ describe('GroupingAndColspanService', () => { const renderSpy = jest.spyOn(service, 'renderPreHeaderRowGroupingTitles'); service.init(gridStub); - gridStub.onRendered.notify({ startRow: 0, endRow: 10, grid: gridStub }, new Slick.EventData(), gridStub); + gridStub.onRendered.notify({ startRow: 0, endRow: 10, grid: gridStub }, new SlickEventData(), gridStub); jest.runAllTimers(); // fast-forward timer expect(renderSpy).toHaveBeenCalledTimes(2); @@ -202,7 +203,7 @@ describe('GroupingAndColspanService', () => { const renderSpy = jest.spyOn(service, 'renderPreHeaderRowGroupingTitles'); service.init(gridStub); - gridStub.onColumnsResized.notify({ triggeredByColumn: 'lastName', grid: gridStub }, new Slick.EventData(), gridStub); + gridStub.onColumnsResized.notify({ triggeredByColumn: 'lastName', grid: gridStub }, new SlickEventData(), gridStub); jest.runAllTimers(); // fast-forward timer expect(renderSpy).toHaveBeenCalledTimes(2); @@ -214,7 +215,7 @@ describe('GroupingAndColspanService', () => { const renderSpy = jest.spyOn(service, 'renderPreHeaderRowGroupingTitles'); service.init(gridStub); - gridStub.onColumnsReordered.notify({ impactedColumns: [], grid: gridStub }, new Slick.EventData(), gridStub); + gridStub.onColumnsReordered.notify({ impactedColumns: [], grid: gridStub }, new SlickEventData(), gridStub); jest.runAllTimers(); // fast-forward timer expect(renderSpy).toHaveBeenCalledTimes(2); @@ -226,7 +227,7 @@ describe('GroupingAndColspanService', () => { const renderSpy = jest.spyOn(service, 'renderPreHeaderRowGroupingTitles'); service.init(gridStub); - dataViewStub.onRowCountChanged.notify({ previous: 1, current: 2, dataView: dataViewStub, callingOnRowsChanged: false }, new Slick.EventData(), gridStub); + dataViewStub.onRowCountChanged.notify({ previous: 1, current: 2, dataView: dataViewStub, callingOnRowsChanged: false, itemCount: 1 }, new SlickEventData(), gridStub); jest.runAllTimers(); // fast-forward timer expect(renderSpy).toHaveBeenCalledTimes(2); @@ -239,7 +240,7 @@ describe('GroupingAndColspanService', () => { const renderSpy = jest.spyOn(service, 'renderPreHeaderRowGroupingTitles'); service.init(gridStub); - resizerPluginStub.onGridAfterResize.notify({}, new Slick.EventData(), gridStub); + resizerPluginStub.onGridAfterResize.notify({}, new SlickEventData(), gridStub); jest.runAllTimers(); // fast-forward timer expect(renderSpy).toHaveBeenCalledTimes(2); @@ -352,7 +353,7 @@ describe('GroupingAndColspanService', () => { const renderSpy = jest.spyOn(service, 'renderPreHeaderRowGroupingTitles'); service.init(gridStub); - gridStub.onSetOptions.notify({ grid: gridStub, optionsBefore: { frozenColumn: -1 }, optionsAfter: { frozenColumn: 1 } }, new Slick.EventData(), gridStub); + gridStub.onSetOptions.notify({ grid: gridStub, optionsBefore: { frozenColumn: -1 }, optionsAfter: { frozenColumn: 1 } }, new SlickEventData(), gridStub); jest.runAllTimers(); // fast-forward timer expect(renderSpy).toHaveBeenCalledTimes(2); diff --git a/packages/common/src/services/__tests__/pagination.service.spec.ts b/packages/common/src/services/__tests__/pagination.service.spec.ts index ebcf06cf7..7a43666a1 100644 --- a/packages/common/src/services/__tests__/pagination.service.spec.ts +++ b/packages/common/src/services/__tests__/pagination.service.spec.ts @@ -1,13 +1,12 @@ import { of, throwError } from 'rxjs'; +import { type SlickDataView, SlickEvent, SlickEventData } from 'slickgrid'; import { PaginationService } from './../pagination.service'; import { SharedService } from '../shared.service'; -import { Column, CursorPageInfo, SlickDataView, GridOption, SlickGrid, SlickNamespace, BackendServiceApi, Pagination } from '../../interfaces/index'; +import { BackendServiceApi, Column, GridOption, Pagination, SlickGridUniversal } from '../../interfaces/index'; import { BackendUtilityService } from '../backendUtility.service'; import { RxJsResourceStub } from '../../../../../test/rxjsResourceStub'; -declare const Slick: SlickNamespace; - const fnCallbacks = {}; const mockPubSub = { publish: jest.fn(), @@ -27,9 +26,9 @@ const backendUtilityServiceStub = { } as unknown as BackendUtilityService; const dataviewStub = { - onPagingInfoChanged: new Slick.Event(), - onRowCountChanged: new Slick.Event(), - onRowsChanged: new Slick.Event(), + onPagingInfoChanged: new SlickEvent(), + onRowCountChanged: new SlickEvent(), + onRowsChanged: new SlickEvent(), setPagingOptions: jest.fn(), setRefreshHints: jest.fn(), } as unknown as SlickDataView; @@ -89,7 +88,7 @@ const gridStub = { onColumnsReordered: jest.fn(), onColumnsResized: jest.fn(), registerPlugin: jest.fn(), -} as unknown as SlickGrid; +} as unknown as SlickGridUniversal; describe('PaginationService', () => { let service: PaginationService; @@ -949,7 +948,7 @@ describe('PaginationService', () => { const mockSlickPagingInfo = { pageSize: 5, pageNum: 2, totalRows: expectedNewTotal, totalPages: 3, dataView: dataviewStub }; service.init(gridStub, mockGridOption.pagination as Pagination); - dataviewStub.onPagingInfoChanged.notify(mockSlickPagingInfo, new Slick.EventData(), dataviewStub); + dataviewStub.onPagingInfoChanged.notify(mockSlickPagingInfo, new SlickEventData(), dataviewStub); expect(service.totalItems).toBe(expectedNewTotal); }); diff --git a/packages/common/src/services/__tests__/resizer.service.spec.ts b/packages/common/src/services/__tests__/resizer.service.spec.ts index b6e605b40..1ae06765a 100644 --- a/packages/common/src/services/__tests__/resizer.service.spec.ts +++ b/packages/common/src/services/__tests__/resizer.service.spec.ts @@ -1,11 +1,11 @@ import { EventPubSubService } from '@slickgrid-universal/event-pub-sub'; +import { SlickEvent } from 'slickgrid'; import { Editors } from '../../editors/index'; import { FieldType, } from '../../enums/index'; -import { Column, GridOption, SlickGrid, SlickNamespace, } from '../../interfaces/index'; +import { Column, GridOption, SlickGridUniversal, } from '../../interfaces/index'; import { ResizerService } from '../resizer.service'; -declare const Slick: SlickNamespace; const DATAGRID_MIN_HEIGHT = 180; const DATAGRID_MIN_WIDTH = 300; const DATAGRID_BOTTOM_PADDING = 20; @@ -54,9 +54,9 @@ const gridStub = { setPreHeaderPanelVisibility: jest.fn(), setOptions: jest.fn(), setSortColumns: jest.fn(), - onColumnsResizeDblClick: new Slick.Event(), - onSort: new Slick.Event(), -} as unknown as SlickGrid; + onColumnsResizeDblClick: new SlickEvent(), + onSort: new SlickEvent(), +} as unknown as SlickGridUniversal; describe('Resizer Service', () => { let eventPubSubService: EventPubSubService; diff --git a/packages/common/src/services/__tests__/shared.service.spec.ts b/packages/common/src/services/__tests__/shared.service.spec.ts index 410b98b31..4bdb1a868 100644 --- a/packages/common/src/services/__tests__/shared.service.spec.ts +++ b/packages/common/src/services/__tests__/shared.service.spec.ts @@ -20,7 +20,7 @@ const gridStub = { onColumnsReordered: jest.fn(), onColumnsResized: jest.fn(), registerPlugin: jest.fn(), -} as unknown as SlickGrid; +} as unknown as SlickGridUniversal; const pubSubServiceStub = { publish: jest.fn(), diff --git a/packages/common/src/services/__tests__/sort.service.spec.ts b/packages/common/src/services/__tests__/sort.service.spec.ts index 452fefe14..600f63471 100644 --- a/packages/common/src/services/__tests__/sort.service.spec.ts +++ b/packages/common/src/services/__tests__/sort.service.spec.ts @@ -1,5 +1,6 @@ import { BasePubSubService } from '@slickgrid-universal/event-pub-sub'; import { of, throwError } from 'rxjs'; +import { type SlickDataView, SlickEvent, SlickEventData, SlickEventHandler } from 'slickgrid'; import { EmitterType, FieldType, } from '../../enums/index'; import { @@ -10,10 +11,7 @@ import { GridMenuItem, GridOption, MenuCommandItem, - SlickDataView, - SlickEventHandler, - SlickGrid, - SlickNamespace, + SlickGridUniversal, SingleColumnSort, BackendServiceApi, } from '../../interfaces/index'; @@ -23,9 +21,6 @@ import { BackendUtilityService } from '../backendUtility.service'; import { SharedService } from '../shared.service'; import { RxJsResourceStub } from '../../../../../test/rxjsResourceStub'; -declare const Slick: SlickNamespace; - - const gridOptionMock = { enablePagination: true, backendServiceApi: { @@ -55,7 +50,7 @@ const dataViewStub = { reSort: jest.fn(), sort: jest.fn(), setItems: jest.fn(), - onRowCountChanged: new Slick.Event(), + onRowCountChanged: new SlickEvent(), } as unknown as SlickDataView; const backendServiceStub = { @@ -77,19 +72,19 @@ const gridStub = { getSortColumns: jest.fn(), invalidate: jest.fn(), onLocalSortChanged: jest.fn(), - onSort: new Slick.Event(), + onSort: new SlickEvent(), render: jest.fn(), setColumns: jest.fn(), setOptions: jest.fn(), setSortColumns: jest.fn(), -} as unknown as SlickGrid; +} as unknown as SlickGridUniversal; const pubSubServiceStub = { publish: jest.fn(), subscribe: jest.fn(), unsubscribe: jest.fn(), unsubscribeAll: jest.fn(), -} as PubSubService; +} as BasePubSubService; describe('SortService', () => { let backendUtilityService: BackendUtilityService; @@ -279,7 +274,7 @@ describe('SortService', () => { const spySortChanged = jest.spyOn(service, 'onBackendSortChanged'); service.bindBackendOnSort(gridStub); - gridStub.onSort.notify(mockSortedCol, new Slick.EventData(), gridStub); + gridStub.onSort.notify(mockSortedCol, new SlickEventData(), gridStub); service.clearSorting(); expect(spySetColumns).toHaveBeenCalledWith([]); @@ -293,7 +288,7 @@ describe('SortService', () => { const spySortChanged = jest.spyOn(service, 'onLocalSortChanged'); service.bindLocalOnSort(gridStub); - gridStub.onSort.notify(mockSortedCol, new Slick.EventData(), gridStub); + gridStub.onSort.notify(mockSortedCol, new SlickEventData(), gridStub); service.clearSorting(); expect(pubSubSpy).toHaveBeenCalledWith(`onSortCleared`, true); @@ -308,7 +303,7 @@ describe('SortService', () => { const spyClearSorters = jest.spyOn(backendServiceStub, 'clearSorters'); service.bindBackendOnSort(gridStub); - gridStub.onSort.notify(mockSortedCol, new Slick.EventData(), gridStub); + gridStub.onSort.notify(mockSortedCol, new SlickEventData(), gridStub); service.clearSorting(false); expect(pubSubSpy).toHaveBeenCalledWith(`onSortCleared`, true); @@ -321,7 +316,7 @@ describe('SortService', () => { const spySetColumns = jest.spyOn(gridStub, 'setSortColumns'); service.bindLocalOnSort(gridStub); - gridStub.onSort.notify(mockSortedCol, new Slick.EventData(), gridStub); + gridStub.onSort.notify(mockSortedCol, new SlickEventData(), gridStub); service.clearSorting(false); expect(pubSubSpy).toHaveBeenCalledWith(`onSortCleared`, true); @@ -342,7 +337,7 @@ describe('SortService', () => { const spy = jest.spyOn(service, 'onBackendSortChanged'); service.bindBackendOnSort(gridStub); - gridStub.onSort.notify({ multiColumnSort: true, sortCols: [], grid: gridStub }, new Slick.EventData(), gridStub); + gridStub.onSort.notify({ multiColumnSort: true, sortCols: [], grid: gridStub }, new SlickEventData(), gridStub); expect(spy).toHaveBeenCalledWith(expect.anything(), { grid: gridStub, multiColumnSort: true, sortCols: [] }); }); @@ -356,7 +351,7 @@ describe('SortService', () => { const mockSortedCol = { columnId: 'lastName', sortCol: { id: 'lastName', field: 'lastName', width: 100 }, sortAsc: true } as ColumnSort; service.bindLocalOnSort(gridStub); - gridStub.onSort.notify(mockSortedCol, new Slick.EventData(), gridStub); + gridStub.onSort.notify(mockSortedCol, new SlickEventData(), gridStub); setTimeout(() => { expect(spyCurrentSort).toHaveBeenCalled(); @@ -376,7 +371,7 @@ describe('SortService', () => { ]; service.bindLocalOnSort(gridStub); - gridStub.onSort.notify({ multiColumnSort: true, sortCols: mockSortedCols, grid: gridStub }, new Slick.EventData(), gridStub); + gridStub.onSort.notify({ multiColumnSort: true, sortCols: mockSortedCols, grid: gridStub }, new SlickEventData(), gridStub); setTimeout(() => { expect(spyCurrentSort).toHaveBeenCalled(); @@ -410,7 +405,7 @@ describe('SortService', () => { const mockSortedCol = { columnId: mockColumn.id, sortCol: mockColumn, sortAsc: true, grid: gridStub } as ColumnSort; service.bindBackendOnSort(gridStub); - gridStub.onSort.notify(mockSortedCol, new Slick.EventData(), gridStub); + gridStub.onSort.notify(mockSortedCol, new SlickEventData(), gridStub); setTimeout(() => { expect(spyBackendCurrentSort).toHaveBeenCalled(); @@ -432,7 +427,7 @@ describe('SortService', () => { ]; service.bindBackendOnSort(gridStub); - gridStub.onSort.notify({ multiColumnSort: true, sortCols: mockSortedCols, grid: gridStub }, new Slick.EventData(), gridStub); + gridStub.onSort.notify({ multiColumnSort: true, sortCols: mockSortedCols, grid: gridStub }, new SlickEventData(), gridStub); setTimeout(() => { expect(spyBackendCurrentSort).toHaveBeenCalled(); @@ -491,7 +486,7 @@ describe('SortService', () => { }); it('should use an empty grid option object when grid "getOptions" method is not available', () => { - gridStub.getOptions = undefined as any; + gridStub.getOptions = () => undefined as any; service.bindBackendOnSort(gridStub); expect(() => service.onBackendSortChanged(undefined, { multiColumnSort: true, grid: gridStub, sortCols: [] })).toThrowError('BackendServiceApi requires at least a "process" function and a "service" defined'); @@ -529,10 +524,10 @@ describe('SortService', () => { it('should execute the "onError" method when the Observable throws an error', (done) => { const spyProcess = jest.fn(); const errorExpected = 'observable error'; - gridOptionMock.backendServiceApi.process = () => of(spyProcess); - gridOptionMock.backendServiceApi.onError = (e) => jest.fn(); - const spyOnError = jest.spyOn(gridOptionMock.backendServiceApi, 'onError'); - jest.spyOn(gridOptionMock.backendServiceApi, 'process').mockReturnValue(throwError(errorExpected)); + gridOptionMock.backendServiceApi!.process = () => of(spyProcess); + gridOptionMock.backendServiceApi!.onError = (e) => jest.fn(); + const spyOnError = jest.spyOn(gridOptionMock.backendServiceApi!, 'onError'); + jest.spyOn(gridOptionMock.backendServiceApi!, 'process').mockReturnValue(throwError(errorExpected)); backendUtilityService.addRxJsResource(rxjsResourceStub); service.addRxJsResource(rxjsResourceStub); @@ -651,7 +646,7 @@ describe('SortService', () => { service.bindLocalOnSort(gridStub); service.disableSortFunctionality(false); - gridStub.onSort.notify({ multiColumnSort: true, sortCols: [], grid: gridStub }, new Slick.EventData(), gridStub); + gridStub.onSort.notify({ multiColumnSort: true, sortCols: [], grid: gridStub }, new SlickEventData(), gridStub); mockColumns.forEach(col => { expect(col.sortable).toBeTruthy(); @@ -722,7 +717,7 @@ describe('SortService', () => { ]; service.bindLocalOnSort(gridStub); - service.loadGridSorters(gridOptionMock.presets.sorters); + service.loadGridSorters(gridOptionMock.presets!.sorters!); expect(spySetCols).toHaveBeenCalledWith([ { columnId: 'firstName', sortAsc: true, }, @@ -741,7 +736,7 @@ describe('SortService', () => { gridOptionMock.multiColumnSort = false; service.bindLocalOnSort(gridStub); - service.loadGridSorters(gridOptionMock.presets.sorters); + service.loadGridSorters(gridOptionMock.presets!.sorters!); expect(spySetCols).toHaveBeenCalledWith([{ columnId: 'firstName', sortAsc: true }]); expect(spySortChanged).toHaveBeenCalledWith(gridStub, [expectation[0]]); @@ -754,20 +749,20 @@ describe('SortService', () => { sorters: [{ columnId: 'firstName', direction: 'ASC' }, { columnId: 'lastName', direction: 'DESC' }], }; const spySetCols = jest.spyOn(gridStub, 'setSortColumns'); - gridStub.getColumns = undefined; + gridStub.getColumns = () => undefined as any; service.bindLocalOnSort(gridStub); - service.loadGridSorters(gridOptionMock.presets.sorters); + service.loadGridSorters(gridOptionMock.presets!.sorters!); expect(spySetCols).toHaveBeenCalledWith([]); }); it('should use an empty grid option object when grid "getOptions" method is not available', () => { const spySetCols = jest.spyOn(gridStub, 'setSortColumns'); - gridStub.getOptions = undefined; + gridStub.getOptions = () => undefined as any; service.bindLocalOnSort(gridStub); - service.loadGridSorters(gridOptionMock.presets.sorters); + service.loadGridSorters(gridOptionMock.presets!.sorters!); expect(spySetCols).toHaveBeenCalledWith([]); }); @@ -1058,7 +1053,7 @@ describe('SortService', () => { sharedService.hierarchicalDataset = []; service.bindLocalOnSort(gridStub); - gridStub.onSort.notify({ multiColumnSort: true, sortCols: mockSortedCols, grid: gridStub }, new Slick.EventData(), gridStub); + gridStub.onSort.notify({ multiColumnSort: true, sortCols: mockSortedCols, grid: gridStub }, new SlickEventData(), gridStub); setTimeout(() => { expect(spyCurrentSort).toHaveBeenCalled(); @@ -1088,7 +1083,7 @@ describe('SortService', () => { sharedService.hierarchicalDataset = []; service.bindLocalOnSort(gridStub); - gridStub.onSort.notify({ multiColumnSort: true, sortCols: mockSortedCols, grid: gridStub }, new Slick.EventData(), gridStub); + gridStub.onSort.notify({ multiColumnSort: true, sortCols: mockSortedCols, grid: gridStub }, new SlickEventData(), gridStub); setTimeout(() => { expect(spyCurrentSort).toHaveBeenCalled(); @@ -1205,7 +1200,7 @@ describe('SortService', () => { const mockSortedCols: ColumnSort[] = [{ columnId: 'file', sortAsc: false, sortCol: { id: 'file', field: 'file' } }]; service.bindLocalOnSort(gridStub); - gridStub.onSort.notify({ multiColumnSort: true, sortCols: mockSortedCols, grid: gridStub }, new Slick.EventData(), gridStub); + gridStub.onSort.notify({ multiColumnSort: true, sortCols: mockSortedCols, grid: gridStub }, new SlickEventData(), gridStub); setTimeout(() => { expect(spyCurrentSort).toHaveBeenCalled(); diff --git a/packages/common/src/services/__tests__/treeData.service.spec.ts b/packages/common/src/services/__tests__/treeData.service.spec.ts index ec2f6b04d..01449875c 100644 --- a/packages/common/src/services/__tests__/treeData.service.spec.ts +++ b/packages/common/src/services/__tests__/treeData.service.spec.ts @@ -1,6 +1,8 @@ +import { type SlickDataView, SlickEvent, SlickEventData, SlickEventHandler } from 'slickgrid'; +import { BasePubSubService } from '@slickgrid-universal/event-pub-sub'; + import { Constants } from '../../constants'; -import { Column, SlickDataView, GridOption, SlickEventHandler, SlickGrid, SlickNamespace, BackendService } from '../../interfaces/index'; -import { EventPubSubService } from '@slickgrid-universal/event-pub-sub'; +import { Column, GridOption, SlickGridUniversal, BackendService } from '../../interfaces/index'; import { SumAggregator } from '../../aggregators'; import { SharedService } from '../shared.service'; import { SortService } from '../sort.service'; @@ -12,8 +14,6 @@ const mockUnflattenParentChildArrayToTree = jest.fn(); jest.useFakeTimers(); -declare const Slick: SlickNamespace; - const gridOptionsMock = { multiColumnSort: false, enableFiltering: true, @@ -44,7 +44,7 @@ const dataViewStub = { reSort: jest.fn(), setItems: jest.fn(), updateItem: jest.fn(), - onRowCountChanged: new Slick.Event(), + onRowCountChanged: new SlickEvent(), } as unknown as SlickDataView; const gridStub = { @@ -56,10 +56,10 @@ const gridStub = { getSortColumns: jest.fn(), invalidate: jest.fn(), onLocalSortChanged: jest.fn(), - onClick: new Slick.Event(), + onClick: new SlickEvent(), render: jest.fn(), setSortColumns: jest.fn(), -} as unknown as SlickGrid; +} as unknown as SlickGridUniversal; const fnCallbacks = {}; const mockPubSub = { @@ -67,7 +67,7 @@ const mockPubSub = { subscribe: (eventName, fn) => fnCallbacks[eventName as string] = fn, unsubscribe: jest.fn(), unsubscribeAll: jest.fn(), -} as unknown as EventPubSubService; +} as BasePubSubService; jest.mock('@slickgrid-universal/event-pub-sub', () => ({ PubSubService: () => mockPubSub })); @@ -235,7 +235,7 @@ describe('TreeData Service', () => { const spyGetCols = jest.spyOn(gridStub, 'getColumns').mockReturnValue([mockColumn]); service.init(gridStub); - const eventData = new Slick.EventData(); + const eventData = new SlickEventData(); Object.defineProperty(eventData, 'target', { writable: true, value: div }); gridStub.onClick.notify({ cell: undefined as any, row: undefined as any, grid: gridStub }, eventData, gridStub); @@ -260,7 +260,7 @@ describe('TreeData Service', () => { const spyInvalidate = jest.spyOn(gridStub, 'invalidate'); service.init(gridStub); - const eventData = new Slick.EventData(); + const eventData = new SlickEventData(); div.className = 'toggle'; Object.defineProperty(eventData, 'target', { writable: true, value: div }); gridStub.onClick.notify({ cell: 0, row: 0, grid: gridStub }, eventData, gridStub); @@ -278,7 +278,7 @@ describe('TreeData Service', () => { const spyInvalidate = jest.spyOn(gridStub, 'invalidate'); service.init(gridStub); - const eventData = new Slick.EventData(); + const eventData = new SlickEventData(); div.className = 'toggle'; Object.defineProperty(eventData, 'target', { writable: true, value: div }); gridStub.onClick.notify({ cell: 0, row: 0, grid: gridStub }, eventData, gridStub); @@ -299,7 +299,7 @@ describe('TreeData Service', () => { const spyInvalidate = jest.spyOn(gridStub, 'invalidate'); service.init(gridStub); - const eventData = new Slick.EventData(); + const eventData = new SlickEventData(); div.className = 'toggle'; Object.defineProperty(eventData, 'target', { writable: true, value: div }); service.currentToggledItems = [{ itemId: 123, isCollapsed: true }]; @@ -324,7 +324,7 @@ describe('TreeData Service', () => { const spyInvalidate = jest.spyOn(gridStub, 'invalidate'); service.init(gridStub); - const eventData = new Slick.EventData(); + const eventData = new SlickEventData(); div.className = 'toggle'; Object.defineProperty(eventData, 'target', { writable: true, value: div }); gridStub.onClick.notify({ cell: 0, row: 0, grid: gridStub }, eventData, gridStub); diff --git a/packages/common/src/services/domUtilities.ts b/packages/common/src/services/domUtilities.ts index 61b19b98b..099b6ed70 100644 --- a/packages/common/src/services/domUtilities.ts +++ b/packages/common/src/services/domUtilities.ts @@ -3,7 +3,7 @@ import * as DOMPurify_ from 'dompurify'; const DOMPurify = ((DOMPurify_ as any)?.['default'] ?? DOMPurify_); // patch for rollup import type { InferDOMType, SearchTerm } from '../enums/index'; -import type { Column, GridOption, HtmlElementPosition, SelectOption, SlickGrid, } from '../interfaces/index'; +import type { Column, GridOption, HtmlElementPosition, SelectOption, SlickGridUniversal, } from '../interfaces/index'; import type { TranslaterService } from './translater.service'; /** @@ -17,7 +17,7 @@ import type { TranslaterService } from './translater.service'; * @param {Array<*>} searchTerms - optional array of search term (used by the "filter" type only) * @returns object with 2 properties for the select element & a boolean value telling us if any of the search terms were found and selected in the dropdown */ -export function buildMultipleSelectDataCollection(type: 'editor' | 'filter', collection: any[], columnDef: Column, grid: SlickGrid, isMultiSelect = false, translaterService?: TranslaterService, searchTerms?: SearchTerm[]): { selectElement: HTMLSelectElement; dataCollection: OptionRowData[]; hasFoundSearchTerm: boolean; } { +export function buildMultipleSelectDataCollection(type: 'editor' | 'filter', collection: any[], columnDef: Column, grid: SlickGridUniversal, isMultiSelect = false, translaterService?: TranslaterService, searchTerms?: SearchTerm[]): { selectElement: HTMLSelectElement; dataCollection: OptionRowData[]; hasFoundSearchTerm: boolean; } { const columnId = columnDef?.id ?? ''; const gridOptions = grid.getOptions(); const columnFilterOrEditor = (type === 'editor' ? columnDef?.internalColumnEditor : columnDef?.filter) ?? {}; @@ -228,7 +228,7 @@ export function getElementOffsetRelativeToParent(parentElm: HTMLElement | null, } /** Get HTML element offset with pure JS */ -export function getHtmlElementOffset(element?: HTMLElement): HtmlElementPosition | undefined { +export function getHtmlElementOffset(element?: HTMLElement | null): HtmlElementPosition | undefined { if (!element) { return undefined; } diff --git a/packages/common/src/services/excelExport.service.ts b/packages/common/src/services/excelExport.service.ts index c44175919..117c7e5ef 100644 --- a/packages/common/src/services/excelExport.service.ts +++ b/packages/common/src/services/excelExport.service.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ -import type { ExcelExportOption, ExternalResource, SlickGrid } from '../interfaces/index'; +import type { ExcelExportOption, ExternalResource, SlickGridUniversal } from '../interfaces/index'; import type { ContainerService } from '../services/container.service'; export abstract class ExcelExportService implements ExternalResource { @@ -11,7 +11,7 @@ export abstract class ExcelExportService implements ExternalResource { * @param _grid * @param _containerService */ - init(_grid: SlickGrid, _containerService: ContainerService): void { + init(_grid: SlickGridUniversal, _containerService: ContainerService): void { throw new Error('ExcelExportService the "init" method must be implemented'); } diff --git a/packages/common/src/services/extension.service.ts b/packages/common/src/services/extension.service.ts index 383319d68..8dc8aec7c 100644 --- a/packages/common/src/services/extension.service.ts +++ b/packages/common/src/services/extension.service.ts @@ -316,6 +316,7 @@ export class ExtensionService { if (!this.getCreatedExtensionByName(ExtensionName.draggableGrouping)) { this._draggleGroupingPlugin = new SlickDraggableGrouping(this.extensionUtility, this.pubSubService, this.sharedService); if (this._draggleGroupingPlugin) { + // @ts-ignore gridOptions.enableColumnReorder = this._draggleGroupingPlugin.setupColumnReorder.bind(this._draggleGroupingPlugin) as ColumnReorderFunction; this._extensionCreatedList[ExtensionName.draggableGrouping] = { name: ExtensionName.draggableGrouping, instance: this._draggleGroupingPlugin }; } diff --git a/packages/common/src/services/filter.service.ts b/packages/common/src/services/filter.service.ts index bd2f2e5b0..7cec741d1 100644 --- a/packages/common/src/services/filter.service.ts +++ b/packages/common/src/services/filter.service.ts @@ -1,7 +1,9 @@ import { BasePubSubService } from '@slickgrid-universal/event-pub-sub'; import { deepCopy } from '@slickgrid-universal/utils'; import { dequal } from 'dequal/lite'; +import { type SlickDataView, SlickEvent, SlickEventData, SlickEventHandler, Utils as SlickUtils } from 'slickgrid'; +import { Constants } from '../constants'; import { FilterConditions, getParsedSearchTermsByFieldType } from './../filter-conditions/index'; import { type FilterFactory } from './../filters/filterFactory'; import { @@ -16,7 +18,6 @@ import type { Column, ColumnFilters, CurrentFilter, - SlickDataView, Filter, FilterArguments, FilterCallbackArg, @@ -24,21 +25,13 @@ import type { FilterConditionOption, GridOption, SearchColumnFilter, - SlickEvent, - SlickEventData, - SlickEventHandler, - SlickGrid, - SlickNamespace, + SlickGridUniversal, } from './../interfaces/index'; import type { BackendUtilityService } from './backendUtility.service'; import { getSelectorStringFromElement, sanitizeHtmlToText, } from '../services/domUtilities'; import { findItemInTreeStructure, getDescendantProperty, mapOperatorByFieldType, } from './utilities'; import type { SharedService } from './shared.service'; import type { RxJsFacade, Subject } from './rxjsFacade'; -import { Constants } from '../constants'; - -// using external non-typed js libraries -declare const Slick: SlickNamespace; interface OnSearchChangeEventArgs { clearFilterTriggered?: boolean; @@ -49,7 +42,7 @@ interface OnSearchChangeEventArgs { operator: OperatorType | OperatorString | undefined; parsedSearchTerms?: SearchTerm | SearchTerm[] | undefined; searchTerms: SearchTerm[] | undefined; - grid: SlickGrid; + grid: SlickGridUniversal; target?: HTMLElement; } @@ -59,7 +52,7 @@ export class FilterService { protected _firstColumnIdRendered: string | number = ''; protected _filtersMetadata: Array = []; protected _columnFilters: ColumnFilters = {}; - protected _grid!: SlickGrid; + protected _grid!: SlickGridUniversal; protected _isTreePresetExecuted = false; protected _previousFilters: CurrentFilter[] = []; protected _onSearchChange: SlickEvent | null; @@ -67,8 +60,8 @@ export class FilterService { protected httpCancelRequests$?: Subject; // this will be used to cancel any pending http request constructor(protected filterFactory: FilterFactory, protected pubSubService: BasePubSubService, protected sharedService: SharedService, protected backendUtilities?: BackendUtilityService, protected rxjs?: RxJsFacade) { - this._onSearchChange = new Slick.Event(); - this._eventHandler = new Slick.EventHandler(); + this._onSearchChange = new SlickEvent(); + this._eventHandler = new SlickEventHandler(); if (this.rxjs) { this.httpCancelRequests$ = this.rxjs.createSubject(); } @@ -101,7 +94,7 @@ export class FilterService { /** Getter of SlickGrid DataView object */ protected get _dataView(): SlickDataView { - return this._grid?.getData?.() ?? {} as SlickDataView; + return this._grid?.getData() ?? {}; } addRxJsResource(rxjs: RxJsFacade) { @@ -112,7 +105,7 @@ export class FilterService { * Initialize the Service * @param grid */ - init(grid: SlickGrid): void { + init(grid: SlickGridUniversal): void { this._grid = grid; if (this._gridOptions && this._gridOptions.enableTreeData && this._gridOptions.treeDataOptions) { @@ -154,7 +147,7 @@ export class FilterService { * Bind a backend filter hook to the grid * @param grid SlickGrid Grid object */ - bindBackendOnFilter(grid: SlickGrid) { + bindBackendOnFilter(grid: SlickGridUniversal) { this._filtersMetadata = []; // subscribe to SlickGrid onHeaderRowCellRendered event to create filter template @@ -185,7 +178,7 @@ export class FilterService { * @param gridOptions Grid Options object * @param dataView */ - bindLocalOnFilter(grid: SlickGrid) { + bindLocalOnFilter(grid: SlickGridUniversal) { this._filtersMetadata = []; this._dataView.setFilterArgs({ columnFilters: this._columnFilters, grid: this._grid, dataView: this._dataView }); this._dataView.setFilter(this.customLocalFilter.bind(this)); @@ -318,7 +311,7 @@ export class FilterService { } /** Local Grid Filter search */ - customLocalFilter(item: any, args: { columnFilters: ColumnFilters; dataView: SlickDataView; grid: SlickGrid; }): boolean { + customLocalFilter(item: any, args: { columnFilters: ColumnFilters; dataView: SlickDataView; grid: SlickGridUniversal; }): boolean { const grid = args?.grid; const columnFilters = args?.columnFilters ?? {}; const isGridWithTreeData = this._gridOptions.enableTreeData ?? false; @@ -466,7 +459,7 @@ export class FilterService { * @param grid - SlickGrid object * @returns FilterConditionOption or boolean */ - preProcessFilterConditionOnDataContext(item: any, columnFilter: SearchColumnFilter, grid: SlickGrid): FilterConditionOption | boolean { + preProcessFilterConditionOnDataContext(item: any, columnFilter: SearchColumnFilter, grid: SlickGridUniversal): FilterConditionOption | boolean { const columnDef = columnFilter.columnDef; const columnId = columnFilter.columnId; let columnIndex = grid.getColumnIndex(columnId) as number; @@ -521,9 +514,9 @@ export class FilterService { // when using localization (i18n), we should use the formatter output to search as the new cell value if (columnDef?.params?.useFormatterOuputToFilter === true) { - const dataView = grid.getData() as SlickDataView; - const primaryDataId = this._gridOptions.datasetIdPropertyName || 'id'; - const rowIndex = (dataView && typeof dataView.getIdxById === 'function') ? dataView.getIdxById(item[primaryDataId]) : 0; + const dataView = grid.getData(); + const idPropName = this._gridOptions.datasetIdPropertyName || 'id'; + const rowIndex = (dataView && typeof dataView.getIdxById === 'function') ? dataView.getIdxById(item[idPropName]) : 0; const formattedCellValue = (columnDef && typeof columnDef.formatter === 'function') ? columnDef.formatter(rowIndex || 0, columnIndex, cellValue, columnDef, item, this._grid) : ''; cellValue = sanitizeHtmlToText(formattedCellValue as string); } @@ -806,7 +799,7 @@ export class FilterService { * @param {Array} [items] - optional flat array of parent/child items to use while redoing the full sort & refresh */ refreshTreeDataFilters(items?: any[]) { - const inputItems = items ?? this._dataView?.getItems?.() ?? []; + const inputItems = items ?? this._dataView?.getItems() ?? []; if (this._dataView && this._gridOptions.enableTreeData && inputItems.length > 0) { this._tmpPreFilteredData = this.preFilterTreeData(inputItems, this._columnFilters); @@ -1079,7 +1072,7 @@ export class FilterService { // ------------------- /** Add all created filters (from their template) to the header row section area */ - protected addFilterTemplateToHeaderRow(args: { column: Column; grid: SlickGrid; node: HTMLElement; }, isFilterFirstRender = true) { + protected addFilterTemplateToHeaderRow(args: { column: Column; grid: SlickGridUniversal; node: HTMLElement }, isFilterFirstRender = true) { const columnDef = args.column; const columnId = columnDef?.id ?? ''; @@ -1104,7 +1097,7 @@ export class FilterService { operator, searchTerms, columnDef, - filterContainerElm: this._grid.getHeaderRowColumn(columnId), + filterContainerElm: this._grid.getHeaderRowColumn(columnId) as HTMLDivElement, callback: this.callbackSearchEvent.bind(this) }; @@ -1175,9 +1168,9 @@ export class FilterService { } } - // event might have been created as a CustomEvent (e.g. CompoundDateFilter), without being a valid Slick.EventData, - // if so we will create a new Slick.EventData and merge it with that CustomEvent to avoid having SlickGrid errors - const eventData = ((event && typeof (event as SlickEventData).isPropagationStopped !== 'function') ? Slick.Utils.extend({}, new Slick.EventData(), event) : event) as SlickEventData; + // event might have been created as a CustomEvent (e.g. CompoundDateFilter), without being a valid SlickEventData, + // if so we will create a new SlickEventData and merge it with that CustomEvent to avoid having SlickGrid errors + const eventData = ((event && typeof (event as any).isPropagationStopped !== 'function') ? SlickUtils.extend({}, new SlickEventData(), event) : event); // trigger an event only if Filters changed or if ENTER key was pressed const eventKey = (event as KeyboardEvent)?.key; @@ -1283,7 +1276,7 @@ export class FilterService { * Subscribe to `onBeforeHeaderRowCellDestroy` to destroy Filter(s) to avoid leak and not keep orphan filters * @param {Object} grid - Slick Grid object */ - protected subscribeToOnHeaderRowCellRendered(grid: SlickGrid) { + protected subscribeToOnHeaderRowCellRendered(grid: SlickGridUniversal) { this._eventHandler.subscribe(grid.onBeforeHeaderRowCellDestroy, (_e, args) => { const colFilter: Filter | undefined = this._filtersMetadata.find((filter: Filter) => filter.columnDef.id === args.column.id); colFilter?.destroy?.(); diff --git a/packages/common/src/services/grid.service.ts b/packages/common/src/services/grid.service.ts index 3a3173dac..9e8673e96 100644 --- a/packages/common/src/services/grid.service.ts +++ b/packages/common/src/services/grid.service.ts @@ -1,18 +1,18 @@ import type { BasePubSubService } from '@slickgrid-universal/event-pub-sub'; import { arrayRemoveItemByIndex, isObjectEmpty } from '@slickgrid-universal/utils'; +import type { SlickDataView } from 'slickgrid'; import type { CellArgs, Column, CurrentPinning, - SlickDataView, GridOption, GridServiceDeleteOption, GridServiceInsertOption, GridServiceUpdateOption, HideColumnOption, OnEventArgs, - SlickGrid, + SlickGridUniversal, } from '../interfaces/index'; import type { FilterService } from './filter.service'; import type { GridStateService } from './gridState.service'; @@ -28,7 +28,7 @@ const GridServiceUpdateOptionDefaults: GridServiceUpdateOption = { highlightRow: const HideColumnOptionDefaults: HideColumnOption = { autoResizeColumns: true, triggerEvent: true, hideFromColumnPicker: false, hideFromGridMenu: false }; export class GridService { - protected _grid!: SlickGrid; + protected _grid!: SlickGridUniversal; protected _rowSelectionPlugin?: SlickRowSelectionModel; protected _highlightTimer?: NodeJS.Timeout; protected _highlightTimerEnd?: NodeJS.Timeout; @@ -45,12 +45,12 @@ export class GridService { /** Getter of SlickGrid DataView object */ get _dataView(): SlickDataView { - return (this._grid?.getData && this._grid.getData()) as SlickDataView; + return this._grid?.getData(); } /** Getter for the Grid Options pulled through the Grid Object */ get _gridOptions(): GridOption { - return (this._grid?.getOptions) ? this._grid.getOptions() : {}; + return this._grid?.getOptions() ?? {}; } dispose() { @@ -58,7 +58,7 @@ export class GridService { this._rowSelectionPlugin?.dispose(); } - init(grid: SlickGrid): void { + init(grid: SlickGridUniversal): void { this._grid = grid; } @@ -148,11 +148,11 @@ export class GridService { } /** Get data item by it's row index number */ - getDataItemByRowNumber(rowNumber: number): T { + getDataItemByRowNumber(rowNumber: number) { if (!this._grid || typeof this._grid.getDataItem !== 'function') { throw new Error(`[Slickgrid-Universal] We could not find SlickGrid Grid object or it's "getDataItem" method`); } - return this._grid.getDataItem(rowNumber); + return this._grid.getDataItem(rowNumber); } /** Chain the item Metadata with our implementation of Metadata at given row index */ @@ -161,7 +161,7 @@ export class GridService { const item = this._dataView.getItem(rowNumber); let meta = { cssClasses: '' }; if (typeof previousItemMetadata === 'function') { - meta = previousItemMetadata(rowNumber); + meta = previousItemMetadata.call(this._dataView, rowNumber); } if (!meta) { @@ -719,7 +719,7 @@ export class GridService { }); // Update the items in the dataView, note that the itemIds must be in the same order as the items - this._dataView.updateItems(itemIds, items); + this._dataView.updateItems(itemIds, items); // end the bulk transaction since we're all done this._dataView.endUpdate(); @@ -769,7 +769,7 @@ export class GridService { if (this._dataView.getIdxById(itemId) !== undefined) { // Update the item itself inside the dataView - this._dataView.updateItem(itemId, item); + this._dataView.updateItem(itemId, item); if (rowNumber !== undefined) { this._grid.updateRow(rowNumber); } diff --git a/packages/common/src/services/gridEvent.service.ts b/packages/common/src/services/gridEvent.service.ts index 218676176..77035a8ac 100644 --- a/packages/common/src/services/gridEvent.service.ts +++ b/packages/common/src/services/gridEvent.service.ts @@ -1,24 +1,15 @@ -import type { - Column, - OnEventArgs, - SlickDataView, - SlickEventHandler, - SlickGrid, - SlickNamespace, -} from './../interfaces/index'; - -// using external non-typed js libraries -declare const Slick: SlickNamespace; +import { type SlickDataView, SlickEventHandler, } from 'slickgrid'; +import type { Column, OnEventArgs, SlickGridUniversal, } from './../interfaces/index'; export class GridEventService { protected _eventHandler: SlickEventHandler; - get eventHandler(): SlickEventHandler { + get eventHandler() { return this._eventHandler; } constructor() { - this._eventHandler = new Slick.EventHandler(); + this._eventHandler = new SlickEventHandler(); } dispose() { @@ -26,8 +17,8 @@ export class GridEventService { } /* OnCellChange Event */ - bindOnBeforeEditCell(grid: SlickGrid) { - const dataView = grid?.getData?.() as SlickDataView; + bindOnBeforeEditCell(grid: SlickGridUniversal) { + const dataView = grid?.getData(); // subscribe to this Slickgrid event of onBeforeEditCell this._eventHandler.subscribe(grid.onBeforeEditCell, (e, args) => { @@ -48,15 +39,15 @@ export class GridEventService { dataContext: grid.getDataItem(args.row) }; - // finally call up the Slick.column.onBeforeEditCells.... function + // finally call up the Slick column.onBeforeEditCells.... function column.onBeforeEditCell(e, returnedArgs); } }); } /* OnCellChange Event */ - bindOnCellChange(grid: SlickGrid) { - const dataView = grid?.getData?.() as SlickDataView; + bindOnCellChange(grid: SlickGridUniversal) { + const dataView = grid?.getData(); // subscribe to this Slickgrid event of onCellChange this._eventHandler.subscribe(grid.onCellChange, (e, args) => { @@ -77,21 +68,21 @@ export class GridEventService { dataContext: grid.getDataItem(args.row) }; - // finally call up the Slick.column.onCellChanges.... function + // finally call up the Slick column.onCellChanges.... function column.onCellChange(e, returnedArgs); } }); } /* OnClick Event */ - bindOnClick(grid: SlickGrid) { - const dataView = grid?.getData?.() as SlickDataView; + bindOnClick(grid: SlickGridUniversal) { + const dataView = grid?.getData(); this._eventHandler.subscribe(grid.onClick, (e, args) => { if (!e || !args || !grid || args.cell === undefined || !grid.getColumns || !grid.getDataItem) { return; } - const column: Column = grid.getColumns?.()[args.cell]; + const column: Column = grid.getColumns()[args.cell]; // if the column definition has a onCellClick property (a callback function), then run it if (typeof column.onCellClick === 'function') { @@ -105,7 +96,7 @@ export class GridEventService { dataContext: grid.getDataItem(args.row) }; - // finally call up the Slick.column.onCellClick.... function + // finally call up the Slick column.onCellClick.... function column.onCellClick(e, returnedArgs); } }); diff --git a/packages/common/src/services/gridState.service.ts b/packages/common/src/services/gridState.service.ts index a58d45ee3..1a4d32349 100644 --- a/packages/common/src/services/gridState.service.ts +++ b/packages/common/src/services/gridState.service.ts @@ -1,5 +1,6 @@ import type { BasePubSubService, EventSubscription } from '@slickgrid-universal/event-pub-sub'; import { dequal } from 'dequal/lite'; +import { type SlickDataView, SlickEventHandler, } from 'slickgrid'; import { ExtensionName, GridStateType, } from '../enums/index'; import type { @@ -11,9 +12,7 @@ import type { CurrentSorter, GridOption, GridState, - SlickDataView, - SlickGrid, - SlickNamespace, + SlickGridUniversal, TreeToggleStateChange, } from '../interfaces/index'; import type { ExtensionService } from './extension.service'; @@ -22,13 +21,10 @@ import type { SharedService } from './shared.service'; import type { SortService } from './sort.service'; import type { TreeDataService } from './treeData.service'; -// using external non-typed js libraries -declare const Slick: SlickNamespace; - export class GridStateService { - protected _eventHandler = new Slick.EventHandler(); + protected _eventHandler = new SlickEventHandler(); protected _columns: Column[] = []; - protected _grid!: SlickGrid; + protected _grid!: SlickGridUniversal; protected _subscriptions: EventSubscription[] = []; protected _selectedRowIndexes: number[] | undefined = []; protected _selectedRowDataContextIds: Array | undefined = []; // used with row selection @@ -45,12 +41,12 @@ export class GridStateService { /** Getter of SlickGrid DataView object */ get _dataView(): SlickDataView { - return this._grid?.getData?.() ?? {} as SlickDataView; + return this._grid?.getData() ?? {}; } /** Getter for the Grid Options pulled through the Grid Object */ protected get _gridOptions(): GridOption { - return this._grid?.getOptions?.() ?? {}; + return this._grid?.getOptions() ?? {}; } /** Getter of the selected data context object IDs */ @@ -67,7 +63,7 @@ export class GridStateService { * Initialize the Service * @param grid */ - init(grid: SlickGrid): void { + init(grid: SlickGridUniversal): void { this._grid = grid; this.subscribeToAllGridChanges(grid); } @@ -210,7 +206,7 @@ export class GridStateService { * @param grid * @param currentColumns */ - getAssociatedGridColumns(grid: SlickGrid, currentColumns: CurrentColumn[]): Column[] { + getAssociatedGridColumns(grid: SlickGridUniversal, currentColumns: CurrentColumn[]): Column[] { const columns: Column[] = []; const gridColumns: Column[] = this.sharedService.allColumns || grid.getColumns(); @@ -375,7 +371,7 @@ export class GridStateService { * Subscribe to all necessary SlickGrid or Service Events that deals with a Grid change, * when triggered, we will publish a Grid State Event with current Grid State */ - subscribeToAllGridChanges(grid: SlickGrid) { + subscribeToAllGridChanges(grid: SlickGridUniversal) { // Subscribe to Event Emitter of Filter changed this._subscriptions.push( this.pubSubService.subscribe('onFilterChanged', currentFilters => { @@ -506,7 +502,7 @@ export class GridStateService { * @param event - event name * @param grid - SlickGrid object */ - protected bindSlickGridColumnChangeEventToGridStateChange(eventName: string, grid: SlickGrid) { + protected bindSlickGridColumnChangeEventToGridStateChange(eventName: string, grid: SlickGridUniversal) { const slickGridEvent = (grid as any)?.[eventName]; if (slickGridEvent && typeof slickGridEvent.subscribe === 'function') { @@ -522,7 +518,7 @@ export class GridStateService { * Bind a Grid Event (of grid option changes) to a Grid State change event, if we detect that any of the pinning (frozen) options changes then we'll trigger a Grid State change * @param grid - SlickGrid object */ - protected bindSlickGridOnSetOptionsEventToGridStateChange(grid: SlickGrid) { + protected bindSlickGridOnSetOptionsEventToGridStateChange(grid: SlickGridUniversal) { const onSetOptionsHandler = grid.onSetOptions; this._eventHandler.subscribe(onSetOptionsHandler, (_e, args) => { const { frozenBottom: frozenBottomBefore, frozenColumn: frozenColumnBefore, frozenRow: frozenRowBefore } = args.optionsBefore; diff --git a/packages/common/src/services/groupingAndColspan.service.ts b/packages/common/src/services/groupingAndColspan.service.ts index 9cbae8cd3..ab5e79e4b 100644 --- a/packages/common/src/services/groupingAndColspan.service.ts +++ b/packages/common/src/services/groupingAndColspan.service.ts @@ -1,32 +1,22 @@ import type { BasePubSubService, EventSubscription } from '@slickgrid-universal/event-pub-sub'; +import { type SlickDataView, SlickEventHandler } from 'slickgrid'; -import type { - Column, - GridOption, - SlickDataView, - SlickEventHandler, - SlickGrid, - SlickNamespace, - SlickResizer, -} from './../interfaces/index'; +import type { Column, GridOption, SlickGridUniversal, SlickResizer, } from './../interfaces/index'; import type { ExtensionUtility } from '../extensions/extensionUtility'; import { createDomElement, emptyElement } from './domUtilities'; -// using external non-typed js libraries -declare const Slick: SlickNamespace; - export class GroupingAndColspanService { protected _eventHandler: SlickEventHandler; - protected _grid!: SlickGrid; + protected _grid!: SlickGridUniversal; protected _subscriptions: EventSubscription[] = []; constructor(protected readonly extensionUtility: ExtensionUtility, protected readonly pubSubService: BasePubSubService) { - this._eventHandler = new Slick.EventHandler(); + this._eventHandler = new SlickEventHandler(); } /** Getter of SlickGrid DataView object */ get _dataView(): SlickDataView { - return (this._grid?.getData && this._grid.getData()) as SlickDataView; + return this._grid?.getData() ?? {}; } /** Getter of the SlickGrid Event Handler */ @@ -36,12 +26,12 @@ export class GroupingAndColspanService { /** Getter for the Grid Options pulled through the Grid Object */ protected get _gridOptions(): GridOption { - return (this._grid?.getOptions) ? this._grid.getOptions() : {}; + return this._grid?.getOptions() ?? {} as GridOption; } /** Getter for the Column Definitions pulled through the Grid Object */ protected get _columnDefinitions(): Column[] { - return (this._grid && this._grid.getColumns) ? this._grid.getColumns() : []; + return this._grid?.getColumns() ?? []; } /** @@ -49,7 +39,7 @@ export class GroupingAndColspanService { * @param {object} grid * @param {object} resizerPlugin */ - init(grid: SlickGrid) { + init(grid: SlickGridUniversal) { this._grid = grid; if (grid && this._gridOptions) { diff --git a/packages/common/src/services/pagination.service.ts b/packages/common/src/services/pagination.service.ts index 4c63815b3..c42fc7a59 100644 --- a/packages/common/src/services/pagination.service.ts +++ b/packages/common/src/services/pagination.service.ts @@ -1,5 +1,6 @@ import type { BasePubSubService, EventSubscription } from '@slickgrid-universal/event-pub-sub'; import { dequal } from 'dequal/lite'; +import { type SlickDataView, SlickEventHandler, } from 'slickgrid'; import type { BackendServiceApi, @@ -8,19 +9,14 @@ import type { Pagination, PaginationCursorChangedArgs, ServicePagination, - SlickDataView, - SlickGrid, - SlickNamespace, + SlickGridUniversal, } from '../interfaces/index'; import type { BackendUtilityService } from './backendUtility.service'; import type { SharedService } from './shared.service'; import type { Observable, RxJsFacade } from './rxjsFacade'; -// using external non-typed js libraries -declare const Slick: SlickNamespace; - export class PaginationService { - protected _eventHandler = new Slick.EventHandler(); + protected _eventHandler = new SlickEventHandler(); protected _initialized = false; protected _isLocalGrid = true; protected _backendServiceApi: BackendServiceApi | undefined; @@ -38,14 +34,14 @@ export class PaginationService { protected _isCursorBased = false; /** SlickGrid Grid object */ - grid!: SlickGrid; + grid!: SlickGridUniversal; /** Constructor */ constructor(protected readonly pubSubService: BasePubSubService, protected readonly sharedService: SharedService, protected readonly backendUtilities?: BackendUtilityService, protected rxjs?: RxJsFacade) { } /** Getter of SlickGrid DataView object */ get dataView(): SlickDataView | undefined { - return this.grid?.getData?.() ?? {} as SlickDataView; + return this.grid?.getData() ?? {}; } set paginationOptions(paginationOptions: Pagination) { @@ -115,7 +111,7 @@ export class PaginationService { this.rxjs = rxjs; } - init(grid: SlickGrid, paginationOptions: Pagination, backendServiceApi?: BackendServiceApi) { + init(grid: SlickGridUniversal, paginationOptions: Pagination, backendServiceApi?: BackendServiceApi) { this._availablePageSizes = paginationOptions.pageSizes; this.grid = grid; this._backendServiceApi = backendServiceApi; diff --git a/packages/common/src/services/resizer.service.ts b/packages/common/src/services/resizer.service.ts index 28b95127d..db3f6f6f6 100644 --- a/packages/common/src/services/resizer.service.ts +++ b/packages/common/src/services/resizer.service.ts @@ -1,4 +1,5 @@ import type { BasePubSubService, EventSubscription } from '@slickgrid-universal/event-pub-sub'; +import { type SlickDataView, SlickEventHandler, } from 'slickgrid'; import { FieldType, } from '../enums/index'; import type { @@ -7,16 +8,12 @@ import type { GridOption, GridSize, ResizeByContentOption, - SlickDataView, - SlickEventHandler, - SlickGrid, - SlickNamespace, + SlickGridUniversal, } from '../interfaces/index'; import { BindingEventService, getInnerSize, getHtmlElementOffset, sanitizeHtmlToText, } from '../services/index'; import { parseFormatterWhenExist } from '../formatters/formatterUtilities'; // using external non-typed js libraries -declare const Slick: SlickNamespace; const DATAGRID_BOTTOM_PADDING = 20; const DATAGRID_FOOTER_HEIGHT = 25; const DATAGRID_PAGINATION_HEIGHT = 35; @@ -27,7 +24,7 @@ const DEFAULT_INTERVAL_RETRY_DELAY = 200; export class ResizerService { protected _autoResizeOptions!: AutoResizeOption; protected _bindingEventService: BindingEventService; - protected _grid!: SlickGrid; + protected _grid!: SlickGridUniversal; protected _eventHandler: SlickEventHandler; protected _fixedHeight?: number | string; protected _fixedWidth?: number | string; @@ -51,12 +48,12 @@ export class ResizerService { /** Getter for the Grid Options pulled through the Grid Object */ get gridOptions(): GridOption { - return this._grid?.getOptions?.() ?? {}; + return this._grid?.getOptions() ?? {}; } /** Getter for the SlickGrid DataView */ get dataView(): SlickDataView { - return this._grid?.getData() as SlickDataView; + return this._grid?.getData(); } /** Getter for the grid uid */ @@ -79,7 +76,7 @@ export class ResizerService { } constructor(protected readonly pubSubService: BasePubSubService) { - this._eventHandler = new Slick.EventHandler(); + this._eventHandler = new SlickEventHandler(); this._bindingEventService = new BindingEventService(); } @@ -99,7 +96,7 @@ export class ResizerService { this._bindingEventService.unbindAll(); } - init(grid: SlickGrid, gridParentContainerElm: HTMLElement) { + init(grid: SlickGridUniversal, gridParentContainerElm: HTMLElement) { if (!grid || !this.gridOptions || !gridParentContainerElm) { throw new Error(` [Slickgrid-Universal] Resizer Service requires a valid Grid object and DOM Element Container to be provided. @@ -115,7 +112,7 @@ export class ResizerService { gridParentContainerElm.style.width = typeof fixedGridSizes.width === 'string' ? fixedGridSizes.width : `${fixedGridSizes.width}px`; } - this._gridDomElm = grid?.getContainerNode?.() as HTMLDivElement; + this._gridDomElm = grid?.getContainerNode() as HTMLDivElement; if (typeof this._autoResizeOptions.container === 'string') { this._pageContainerElm = typeof this._autoResizeOptions.container === 'string' ? document.querySelector(this._autoResizeOptions.container) as HTMLElement : this._autoResizeOptions.container; @@ -317,7 +314,7 @@ export class ResizerService { this.pubSubService.publish('onGridAfterResize', dimensions); // we can call our resize by content here (when enabled) - // since the core Slick.Resizer plugin only supports the "autosizeColumns" + // since the core SlickResizer plugin only supports the "autosizeColumns" if (this.gridOptions.enableAutoResizeColumnsByCellContent && (!this._lastDimensions?.width || dimensions?.width !== this._lastDimensions?.width)) { this.resizeColumnsByCellContent(false); } @@ -359,7 +356,7 @@ export class ResizerService { } } else if (this.gridOptions.enableAutoResizeColumnsByCellContent && (!this._lastDimensions?.width || newWidth !== this._lastDimensions?.width)) { // we can call our resize by content here (when enabled) - // since the core Slick.Resizer plugin only supports the "autosizeColumns" + // since the core SlickResizer plugin only supports the "autosizeColumns" this.resizeColumnsByCellContent(false); } @@ -671,7 +668,7 @@ export class ResizerService { // another condition for a required resize is when the grid is hidden (not in current tab) then its "rightPx" rendered range will be 0px // if that's the case then we know the grid is still hidden and we need to resize it whenever it becomes visible (when its "rightPx" becomes greater than 0 then it's visible) - const renderedRangeRightPx = this._grid.getRenderedRange?.()?.rightPx ?? 0; + const renderedRangeRightPx = this._grid.getRenderedRange()?.rightPx ?? 0; if (!isResizeRequired && dataLn > 0 && renderedRangeRightPx === 0 && columns.length > 1) { isResizeRequired = true; } diff --git a/packages/common/src/services/shared.service.ts b/packages/common/src/services/shared.service.ts index c308398bd..ddaedfee3 100644 --- a/packages/common/src/services/shared.service.ts +++ b/packages/common/src/services/shared.service.ts @@ -1,11 +1,12 @@ -import type { Column, CurrentPagination, GridOption, SlickDataView, SlickGrid, } from '../interfaces/index'; +import type { SlickDataView } from 'slickgrid'; +import type { Column, CurrentPagination, GridOption, SlickGridUniversal } from '../interfaces/index'; import type { SlickGroupItemMetadataProvider } from '../extensions/slickGroupItemMetadataProvider'; export class SharedService { protected _allColumns!: Column[]; protected _dataView!: SlickDataView; protected _groupItemMetadataProvider!: SlickGroupItemMetadataProvider; - protected _grid!: SlickGrid; + protected _grid!: SlickGridUniversal; protected _gridContainerElm!: HTMLElement; protected _gridOptions!: GridOption; protected _hasColumnsReordered = false; @@ -30,7 +31,7 @@ export class SharedService { /** Getter for the Column Definitions pulled through the Grid Object */ get columnDefinitions(): Column[] { - return (this._grid && this._grid.getColumns) ? this._grid.getColumns() : []; + return this._grid?.getColumns() ?? []; } /** Getter for the Current Pagination (when Pagination is enabled) */ @@ -71,11 +72,11 @@ export class SharedService { } /** Getter for SlickGrid Grid object */ - get slickGrid(): SlickGrid { + get slickGrid(): SlickGridUniversal { return this._grid; } /** Setter for SlickGrid Grid object */ - set slickGrid(grid: SlickGrid) { + set slickGrid(grid: SlickGridUniversal) { this._grid = grid; } diff --git a/packages/common/src/services/sort.service.ts b/packages/common/src/services/sort.service.ts index a5a57c22b..7d702b6b6 100644 --- a/packages/common/src/services/sort.service.ts +++ b/packages/common/src/services/sort.service.ts @@ -1,45 +1,32 @@ import type { BasePubSubService } from '@slickgrid-universal/event-pub-sub'; - +import { type SlickDataView, type SlickEventData, SlickEventHandler, } from 'slickgrid'; import type { Column, ColumnSort, - SlickDataView, GridOption, CurrentSorter, MultiColumnSort, SingleColumnSort, - SlickEventHandler, - SlickGrid, + SlickGridUniversal, TreeDataOption, - SlickNamespace, - SlickEventData, } from '../interfaces/index'; -import { - EmitterType, - FieldType, - SortDirection, - SortDirectionNumber, - type SortDirectionString, -} from '../enums/index'; +import { EmitterType, FieldType, SortDirection, SortDirectionNumber, type SortDirectionString, } from '../enums/index'; import type { BackendUtilityService } from './backendUtility.service'; import { getDescendantProperty, flattenToParentChildArray } from './utilities'; import { sortByFieldType } from '../sortComparers/sortUtilities'; import type { SharedService } from './shared.service'; import type { RxJsFacade, Subject } from './rxjsFacade'; -// using external non-typed js libraries -declare const Slick: SlickNamespace; - export class SortService { protected _currentLocalSorters: CurrentSorter[] = []; protected _eventHandler: SlickEventHandler; protected _dataView!: SlickDataView; - protected _grid!: SlickGrid; + protected _grid!: SlickGridUniversal; protected _isBackendGrid = false; protected httpCancelRequests$?: Subject; // this will be used to cancel any pending http request constructor(protected readonly sharedService: SharedService, protected readonly pubSubService: BasePubSubService, protected readonly backendUtilities?: BackendUtilityService, protected rxjs?: RxJsFacade) { - this._eventHandler = new Slick.EventHandler(); + this._eventHandler = new SlickEventHandler(); if (this.rxjs) { this.httpCancelRequests$ = this.rxjs.createSubject(); } @@ -52,12 +39,12 @@ export class SortService { /** Getter for the Grid Options pulled through the Grid Object */ protected get _gridOptions(): GridOption { - return (this._grid && this._grid.getOptions) ? this._grid.getOptions() : {}; + return this._grid?.getOptions() ?? {}; } /** Getter for the Column Definitions pulled through the Grid Object */ protected get _columnDefinitions(): Column[] { - return (this._grid && this._grid.getColumns) ? this._grid.getColumns() : []; + return this._grid?.getColumns() ?? []; } dispose() { @@ -80,10 +67,10 @@ export class SortService { * @param grid SlickGrid Grid object * @param dataView SlickGrid DataView object */ - bindBackendOnSort(grid: SlickGrid) { + bindBackendOnSort(grid: SlickGridUniversal) { this._isBackendGrid = true; this._grid = grid; - this._dataView = grid?.getData?.() ?? {} as SlickDataView; + this._dataView = grid?.getData(); // subscribe to the SlickGrid event and call the backend execution this._eventHandler.subscribe(grid.onSort, this.onBackendSortChanged.bind(this) as EventListener); @@ -95,19 +82,25 @@ export class SortService { * @param gridOptions Grid Options object * @param dataView */ - bindLocalOnSort(grid: SlickGrid) { + bindLocalOnSort(grid: SlickGridUniversal) { this._isBackendGrid = false; this._grid = grid; - this._dataView = grid.getData() as SlickDataView; + this._dataView = grid?.getData(); this.processTreeDataInitialSort(); - this._eventHandler.subscribe(grid.onSort, this.handleLocalOnSort.bind(this) as EventListener); + this._eventHandler.subscribe(grid.onSort, this.handleLocalOnSort.bind(this)); } handleLocalOnSort(_e: SlickEventData, args: SingleColumnSort | MultiColumnSort) { // multiSort and singleSort are not exactly the same, but we want to structure it the same for the (for loop) after // also to avoid having to rewrite the for loop in the sort, we will make the singleSort an array of 1 object - const sortColumns: Array = (args.multiColumnSort) ? (args as MultiColumnSort).sortCols : new Array({ columnId: (args as SingleColumnSort).sortCol?.id ?? '', sortAsc: (args as SingleColumnSort).sortAsc, sortCol: (args as SingleColumnSort).sortCol }); + const sortColumns: Array = (args.multiColumnSort) + ? (args as MultiColumnSort).sortCols + : new Array({ + columnId: (args as SingleColumnSort).sortCol?.id ?? '', + sortAsc: (args as SingleColumnSort).sortAsc, + sortCol: (args as SingleColumnSort).sortCol + }); // keep current sorters this._currentLocalSorters = []; // reset current local sorters @@ -146,9 +139,9 @@ export class SortService { // update the grid sortColumns array which will at the same add the visual sort icon(s) on the UI const updatedSortColumns: ColumnSort[] = sortedColsWithoutCurrent.map((col) => { return { - columnId: col && col.sortCol && col.sortCol.id, - sortAsc: col && col.sortAsc, - sortCol: col && col.sortCol, + columnId: col?.sortCol?.id ?? '', + sortAsc: col?.sortAsc, + sortCol: col?.sortCol, }; }); this._grid.setSortColumns(updatedSortColumns); // add sort icon in UI @@ -355,7 +348,7 @@ export class SortService { if (!args || !args.grid) { throw new Error('Something went wrong when trying to bind the "onBackendSortChanged(event, args)" function, it seems that "args" is not populated correctly'); } - const gridOptions: GridOption = (args.grid && args.grid.getOptions) ? args.grid.getOptions() : {}; + const gridOptions: GridOption = args.grid?.getOptions() ?? {}; const backendApi = gridOptions.backendServiceApi; if (!backendApi || !backendApi.process || !backendApi.service) { @@ -391,10 +384,10 @@ export class SortService { } /** When a Sort Changes on a Local grid (JSON dataset) */ - async onLocalSortChanged(grid: SlickGrid, sortColumns: Array, forceReSort = false, emitSortChanged = false) { + async onLocalSortChanged(grid: SlickGridUniversal, sortColumns: Array, forceReSort = false, emitSortChanged = false) { const datasetIdPropertyName = this._gridOptions?.datasetIdPropertyName ?? 'id'; const isTreeDataEnabled = this._gridOptions?.enableTreeData ?? false; - const dataView = grid.getData?.() as SlickDataView; + const dataView = grid.getData(); await this.pubSubService.publish('onBeforeSortChange', { sortColumns }, 0); if (grid && dataView) { @@ -488,10 +481,10 @@ export class SortService { let value2 = dataRow2[queryFieldName2]; // when item is a complex object (dot "." notation), we need to filter the value contained in the object tree - if (queryFieldName1 && queryFieldName1.indexOf('.') >= 0) { + if (queryFieldName1?.indexOf('.') >= 0) { value1 = getDescendantProperty(dataRow1, queryFieldName1); } - if (queryFieldName2 && queryFieldName2.indexOf('.') >= 0) { + if (queryFieldName2?.indexOf('.') >= 0) { value2 = getDescendantProperty(dataRow2, queryFieldName2); } diff --git a/packages/common/src/services/textExport.service.ts b/packages/common/src/services/textExport.service.ts index d6941549f..9258f63ed 100644 --- a/packages/common/src/services/textExport.service.ts +++ b/packages/common/src/services/textExport.service.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ -import type { ExternalResource, SlickGrid, TextExportOption } from '../interfaces/index'; +import type { ExternalResource, SlickGridUniversal, TextExportOption } from '../interfaces/index'; import type { ContainerService } from '../services/container.service'; export abstract class TextExportService implements ExternalResource { @@ -11,7 +11,7 @@ export abstract class TextExportService implements ExternalResource { * @param _grid * @param _containerService */ - init(_grid: SlickGrid, _containerService: ContainerService): void { + init(_grid: SlickGridUniversal, _containerService: ContainerService): void { throw new Error('ExportService the "init" method must be implemented'); } diff --git a/packages/common/src/services/treeData.service.ts b/packages/common/src/services/treeData.service.ts index 4d697b1b2..a35247ee0 100644 --- a/packages/common/src/services/treeData.service.ts +++ b/packages/common/src/services/treeData.service.ts @@ -1,4 +1,5 @@ import type { BasePubSubService, EventSubscription } from '@slickgrid-universal/event-pub-sub'; +import { type OnClickEventArgs, type SlickDataView, SlickEventHandler, } from 'slickgrid'; import { Constants } from '../constants'; import { ToggleStateChangeType, type ToggleStateChangeTypeString } from '../enums/index'; @@ -6,12 +7,7 @@ import type { Column, ColumnSort, GridOption, - OnClickEventArgs, - SlickDataView, - SlickEventData, - SlickEventHandler, - SlickGrid, - SlickNamespace, + SlickGridUniversal, TreeDataOption, TreeToggledItem, TreeToggleStateChange, @@ -24,13 +20,10 @@ import { import type { SharedService } from './shared.service'; import type { SortService } from './sort.service'; -// using external non-typed js libraries -declare const Slick: SlickNamespace; - export class TreeDataService { protected _lastToggleStateChange!: Omit; protected _currentToggledItems: TreeToggledItem[] = []; - protected _grid!: SlickGrid; + protected _grid!: SlickGridUniversal; protected _eventHandler: SlickEventHandler; protected _isLastFullToggleCollapsed = false; protected _isOneCpuCyclePassed = false; @@ -40,7 +33,7 @@ export class TreeDataService { protected _treeDataRecalcHandler: (() => void) | null = null; constructor(protected readonly pubSubService: BasePubSubService, protected readonly sharedService: SharedService, protected readonly sortService: SortService) { - this._eventHandler = new Slick.EventHandler(); + this._eventHandler = new SlickEventHandler(); setTimeout(() => this._isOneCpuCyclePassed = true); } @@ -57,7 +50,7 @@ export class TreeDataService { /** Getter of SlickGrid DataView object */ get dataView(): SlickDataView { - return this._grid?.getData?.() ?? {} as SlickDataView; + return this._grid?.getData(); } /** Getter of the SlickGrid Event Handler */ @@ -66,7 +59,7 @@ export class TreeDataService { } get gridOptions(): GridOption { - return this._grid?.getOptions?.() ?? {}; + return this._grid?.getOptions() ?? {}; } get treeDataOptions() { @@ -79,7 +72,7 @@ export class TreeDataService { this.pubSubService.unsubscribeAll(this._subscriptions); } - init(grid: SlickGrid) { + init(grid: SlickGridUniversal) { this._grid = grid; this._isTreeDataEnabled = this.gridOptions?.enableTreeData ?? false; this._isLastFullToggleCollapsed = this.treeDataOptions?.initiallyCollapsed ?? false; @@ -415,7 +408,7 @@ export class TreeDataService { // protected functions // ------------------ - protected handleOnCellClick(event: SlickEventData, args: OnClickEventArgs) { + protected handleOnCellClick(event: MouseEvent, args: OnClickEventArgs) { if (event && args) { const targetElm: any = event.target || {}; const idPropName = this.gridOptions.datasetIdPropertyName ?? 'id'; diff --git a/packages/composite-editor-component/src/compositeEditor.factory.spec.ts b/packages/composite-editor-component/src/compositeEditor.factory.spec.ts index 0f6e27ab1..1bbcd32cf 100644 --- a/packages/composite-editor-component/src/compositeEditor.factory.spec.ts +++ b/packages/composite-editor-component/src/compositeEditor.factory.spec.ts @@ -1,7 +1,7 @@ -import { Column, CompositeEditorOption, Editors, ElementPosition, GridOption, SlickDataView, SlickGrid, SlickNamespace } from '@slickgrid-universal/common'; -import { CompositeEditor } from './compositeEditor.factory'; +import { Column, CompositeEditorOption, Editors, ElementPosition, GridOption, type SlickGridUniversal } from '@slickgrid-universal/common'; +import { type SlickDataView, SlickEvent } from 'slickgrid'; -declare const Slick: SlickNamespace; +import { CompositeEditor } from './compositeEditor.factory'; const dataViewStub = { getItem: jest.fn(), @@ -45,16 +45,16 @@ const gridStub = { getSortColumns: jest.fn(), invalidate: jest.fn(), onLocalSortChanged: jest.fn(), - onAddNewRow: new Slick.Event(), - onBeforeEditCell: new Slick.Event(), - onClick: new Slick.Event(), - onCompositeEditorChange: new Slick.Event(), + onAddNewRow: new SlickEvent(), + onBeforeEditCell: new SlickEvent(), + onClick: new SlickEvent(), + onCompositeEditorChange: new SlickEvent(), render: jest.fn(), setActiveCell: jest.fn(), setSelectedRows: jest.fn(), setActiveRow: jest.fn(), setSortColumns: jest.fn(), -} as unknown as SlickGrid; +} as unknown as SlickGridUniversal; const columnsMock: Column[] = [ { id: 'productName', field: 'productName', width: 100, name: 'Product', nameKey: 'PRODUCT', editor: Editors.text as any }, diff --git a/packages/composite-editor-component/src/compositeEditor.factory.ts b/packages/composite-editor-component/src/compositeEditor.factory.ts index 49272f436..db7881e2a 100644 --- a/packages/composite-editor-component/src/compositeEditor.factory.ts +++ b/packages/composite-editor-component/src/compositeEditor.factory.ts @@ -6,15 +6,12 @@ import type { EditorValidationResult, ElementPosition, HtmlElementPosition, - SlickNamespace } from '@slickgrid-universal/common'; import { emptyElement, getHtmlElementOffset, } from '@slickgrid-universal/common'; - -// using external non-typed js libraries -declare const Slick: SlickNamespace; +// import { SlickCompositeEditor } from 'slickgrid'; export interface CompositeEditorArguments extends EditorArguments { formValues: any; @@ -268,8 +265,8 @@ export function CompositeEditor(this: any, columns: Column[], containers: Array< init(); } - // so we can do editor instanceof Slick.CompositeEditor OR instanceof CompositeEditor + // so we can do editor instanceof SlickCompositeEditor OR instanceof CompositeEditor editor.prototype = this; - Slick.CompositeEditor = editor as any; + return editor; } \ No newline at end of file diff --git a/packages/composite-editor-component/src/slick-composite-editor.component.spec.ts b/packages/composite-editor-component/src/slick-composite-editor.component.spec.ts index e2c6f06c0..13b2d184d 100644 --- a/packages/composite-editor-component/src/slick-composite-editor.component.spec.ts +++ b/packages/composite-editor-component/src/slick-composite-editor.component.spec.ts @@ -6,18 +6,15 @@ import { Editors, GridOption, GridService, - SlickDataView, - SlickGrid, - SlickNamespace, SlickRowSelectionModel, + type SlickGridUniversal, } from '@slickgrid-universal/common'; +import { type SlickDataView, SlickEvent } from 'slickgrid'; import { SlickCompositeEditorComponent } from './slick-composite-editor.component'; import { TranslateServiceStub } from '../../../test/translateServiceStub'; import { ContainerServiceStub } from '../../../test/containerServiceStub'; -declare const Slick: SlickNamespace; - const gridOptionsMock = { editable: true, enableCellNavigation: true, @@ -96,16 +93,16 @@ const gridStub = { getSortColumns: jest.fn(), invalidate: jest.fn(), onLocalSortChanged: jest.fn(), - onAddNewRow: new Slick.Event(), - onBeforeEditCell: new Slick.Event(), - onClick: new Slick.Event(), - onCompositeEditorChange: new Slick.Event(), + onAddNewRow: new SlickEvent(), + onBeforeEditCell: new SlickEvent(), + onClick: new SlickEvent(), + onCompositeEditorChange: new SlickEvent(), render: jest.fn(), setActiveCell: jest.fn(), setSelectedRows: jest.fn(), setActiveRow: jest.fn(), setSortColumns: jest.fn(), -} as unknown as SlickGrid; +} as unknown as SlickGridUniversal; const rowSelectionModelStub = { pluginName: 'RowSelectionModel', @@ -116,10 +113,10 @@ const rowSelectionModelStub = { setSelectedRanges: jest.fn(), getSelectedRows: jest.fn(), setSelectedRows: jest.fn(), - onSelectedRangesChanged: new Slick.Event(), + onSelectedRangesChanged: new SlickEvent(), } as unknown as SlickRowSelectionModel; -function createNewColumDefinitions(count) { +function createNewColumDefinitions(count: number) { const columnsMock: Column[] = []; for (let i = 0; i < count; i++) { columnsMock.push({ id: `field${i}`, field: `field${i}`, name: `Field ${i}`, editor: { model: Editors.text, massUpdate: true }, width: 75 }); @@ -553,7 +550,7 @@ describe('CompositeEditorService', () => { const mockProduct = { id: 222, address: { zip: 123456 }, productName: 'Product ABC', price: 12.55, field2: 'Test' }; jest.spyOn(gridStub, 'getDataItem').mockReturnValue(mockProduct); const getEditSpy = jest.spyOn(gridStub, 'getEditController'); - const cancelSpy = jest.spyOn(gridStub.getEditController(), 'cancelCurrentEdit'); + const cancelSpy = jest.spyOn(gridStub.getEditController() as any, 'cancelCurrentEdit'); const mockOnClose = jest.fn(); const mockModalOptions = { headerTitle: 'Details', modalType: 'edit', onClose: mockOnClose } as CompositeEditorOpenDetailOption; @@ -595,7 +592,7 @@ describe('CompositeEditorService', () => { it('should NOT execute "onClose" callback when user confirms the closing of the modal when "onClose" callback is defined', (done) => { const mockProduct = { id: 222, address: { zip: 123456 }, productName: 'Product ABC', price: 12.55 }; jest.spyOn(gridStub, 'getDataItem').mockReturnValue(mockProduct); - const cancelSpy = jest.spyOn(gridStub.getEditController(), 'cancelCurrentEdit'); + const cancelSpy = jest.spyOn(gridStub.getEditController() as any, 'cancelCurrentEdit'); const mockOnClose = jest.fn(); const mockModalOptions = { headerTitle: 'Details', modalType: 'edit', onClose: mockOnClose } as CompositeEditorOpenDetailOption; @@ -657,7 +654,7 @@ describe('CompositeEditorService', () => { it('should execute "cancelCurrentEdit" when the "Esc" key is typed', () => { const getEditSpy = jest.spyOn(gridStub, 'getEditController'); - const cancelSpy = jest.spyOn(gridStub.getEditController(), 'cancelCurrentEdit'); + const cancelSpy = jest.spyOn(gridStub.getEditController() as any, 'cancelCurrentEdit'); component = new SlickCompositeEditorComponent(); component.init(gridStub, container); @@ -700,7 +697,7 @@ describe('CompositeEditorService', () => { it('should execute "cancelCurrentEdit" when the "Cancel" button is clicked', () => { const getEditSpy = jest.spyOn(gridStub, 'getEditController'); - const cancelSpy = jest.spyOn(gridStub.getEditController(), 'cancelCurrentEdit'); + const cancelSpy = jest.spyOn(gridStub.getEditController() as any, 'cancelCurrentEdit'); component = new SlickCompositeEditorComponent(); component.init(gridStub, container); @@ -723,7 +720,7 @@ describe('CompositeEditorService', () => { it('should execute "cancelCurrentEdit" when the "Close" button is clicked even with option "showCloseButtonOutside" is enabled', () => { const getEditSpy = jest.spyOn(gridStub, 'getEditController'); - const closeSpy = jest.spyOn(gridStub.getEditController(), 'cancelCurrentEdit'); + const closeSpy = jest.spyOn(gridStub.getEditController() as any, 'cancelCurrentEdit'); component = new SlickCompositeEditorComponent(); component.init(gridStub, container); @@ -743,7 +740,7 @@ describe('CompositeEditorService', () => { it('should execute "commitCurrentEdit" when the "Save" button is clicked', () => { const getEditSpy = jest.spyOn(gridStub, 'getEditController'); - const saveSpy = jest.spyOn(gridStub.getEditController(), 'commitCurrentEdit'); + const saveSpy = jest.spyOn(gridStub.getEditController() as any, 'commitCurrentEdit'); component = new SlickCompositeEditorComponent(); component.init(gridStub, container); @@ -883,7 +880,7 @@ describe('CompositeEditorService', () => { jest.spyOn(gridStub, 'getCellEditor').mockReturnValue(currentEditorMock as any); jest.spyOn(currentEditorMock, 'validate').mockReturnValue({ valid: true, msg: null }); jest.spyOn(gridStub, 'getOptions').mockReturnValue(newGridOptions); - const cancelCommitSpy = jest.spyOn(gridStub.getEditController(), 'cancelCurrentEdit'); + const cancelCommitSpy = jest.spyOn(gridStub.getEditController() as any, 'cancelCurrentEdit'); const gridSrvAddItemSpy = jest.spyOn(gridServiceStub, 'addItem'); const mockOnSave = jest.fn(); @@ -943,7 +940,7 @@ describe('CompositeEditorService', () => { jest.spyOn(gridStub, 'getCellEditor').mockReturnValue(currentEditorMock as any); jest.spyOn(currentEditorMock, 'validate').mockReturnValue({ valid: true, msg: null }); jest.spyOn(gridStub, 'getOptions').mockReturnValue(newGridOptions); - const cancelCommitSpy = jest.spyOn(gridStub.getEditController(), 'cancelCurrentEdit'); + const cancelCommitSpy = jest.spyOn(gridStub.getEditController() as any, 'cancelCurrentEdit'); const gridSrvAddItemSpy = jest.spyOn(gridServiceStub, 'addItem'); const mockOnSave = jest.fn(); @@ -1005,7 +1002,7 @@ describe('CompositeEditorService', () => { jest.spyOn(dataViewStub, 'getItemCount').mockReturnValue(1); jest.spyOn(dataViewStub, 'getItems').mockReturnValue([mockProduct1]); const gridSrvAddItemSpy = jest.spyOn(gridServiceStub, 'addItem'); - const saveSpy = jest.spyOn(gridStub.getEditController(), 'commitCurrentEdit'); + const saveSpy = jest.spyOn(gridStub.getEditController() as any, 'commitCurrentEdit'); const mockModalOptions = { headerTitle: 'Details', modalType: 'create' } as CompositeEditorOpenDetailOption; component = new SlickCompositeEditorComponent(); @@ -1149,7 +1146,7 @@ describe('CompositeEditorService', () => { jest.spyOn(gridStub, 'getDataItem').mockReturnValue(mockNewProduct2); jest.spyOn(dataViewStub, 'getItems').mockReturnValue([mockProduct1]); const gridSrvAddItemSpy = jest.spyOn(gridServiceStub, 'addItem'); - const saveSpy = jest.spyOn(gridStub.getEditController(), 'commitCurrentEdit'); + const saveSpy = jest.spyOn(gridStub.getEditController() as any, 'commitCurrentEdit'); const mockCreateOnSave = jest.fn(); mockCreateOnSave.mockResolvedValue(Promise.resolve(true)); @@ -1579,7 +1576,7 @@ describe('CompositeEditorService', () => { jest.spyOn(dataViewStub, 'getAllSelectedIds').mockReturnValue([222]); jest.spyOn(dataViewStub, 'mapIdsToRows').mockReturnValue([0]); jest.spyOn(dataViewStub, 'getItemById').mockReturnValue(mockProduct); - const cancelCommitSpy = jest.spyOn(gridStub.getEditController(), 'cancelCurrentEdit'); + const cancelCommitSpy = jest.spyOn(gridStub.getEditController() as any, 'cancelCurrentEdit'); const setActiveRowSpy = jest.spyOn(gridStub, 'setActiveRow'); const clearSelectionSpy = jest.spyOn(gridStub, 'setSelectedRows'); const updateItemsSpy = jest.spyOn(gridServiceStub, 'updateItems'); @@ -1634,7 +1631,7 @@ describe('CompositeEditorService', () => { jest.spyOn(dataViewStub, 'mapIdsToRows').mockReturnValue([0]); jest.spyOn(dataViewStub, 'getItemById').mockReturnValue(mockProduct); const getEditSpy = jest.spyOn(gridStub, 'getEditController'); - const cancelCommitSpy = jest.spyOn(gridStub.getEditController(), 'cancelCurrentEdit'); + const cancelCommitSpy = jest.spyOn(gridStub.getEditController() as any, 'cancelCurrentEdit'); const setActiveRowSpy = jest.spyOn(gridStub, 'setActiveRow'); const clearSelectionSpy = jest.spyOn(gridStub, 'setSelectedRows'); const updateItemsSpy = jest.spyOn(gridServiceStub, 'updateItems'); @@ -1702,7 +1699,7 @@ describe('CompositeEditorService', () => { jest.spyOn(dataViewStub, 'getAllSelectedIds').mockReturnValue([222]); jest.spyOn(dataViewStub, 'mapIdsToRows').mockReturnValue([0]); const getEditSpy = jest.spyOn(gridStub, 'getEditController'); - const cancelCommitSpy = jest.spyOn(gridStub.getEditController(), 'cancelCurrentEdit'); + const cancelCommitSpy = jest.spyOn(gridStub.getEditController() as any, 'cancelCurrentEdit'); const setActiveCellSpy = jest.spyOn(gridStub, 'setActiveCell'); const clearSelectionSpy = jest.spyOn(gridStub, 'setSelectedRows'); const setItemsSpy = jest.spyOn(dataViewStub, 'setItems'); @@ -1755,7 +1752,7 @@ describe('CompositeEditorService', () => { jest.spyOn(dataViewStub, 'getAllSelectedIds').mockReturnValue([222]); jest.spyOn(dataViewStub, 'mapIdsToRows').mockReturnValue([0]); const getEditSpy = jest.spyOn(gridStub, 'getEditController'); - const cancelCommitSpy = jest.spyOn(gridStub.getEditController(), 'cancelCurrentEdit'); + const cancelCommitSpy = jest.spyOn(gridStub.getEditController() as any, 'cancelCurrentEdit'); const setActiveCellSpy = jest.spyOn(gridStub, 'setActiveCell'); const clearSelectionSpy = jest.spyOn(gridStub, 'setSelectedRows'); const setItemsSpy = jest.spyOn(dataViewStub, 'setItems'); @@ -1810,7 +1807,7 @@ describe('CompositeEditorService', () => { jest.spyOn(dataViewStub, 'getAllSelectedIds').mockReturnValue([222]); jest.spyOn(dataViewStub, 'mapIdsToRows').mockReturnValue([0]); const getEditSpy = jest.spyOn(gridStub, 'getEditController'); - const cancelCommitSpy = jest.spyOn(gridStub.getEditController(), 'cancelCurrentEdit'); + const cancelCommitSpy = jest.spyOn(gridStub.getEditController() as any, 'cancelCurrentEdit'); const setActiveCellSpy = jest.spyOn(gridStub, 'setActiveCell'); const clearSelectionSpy = jest.spyOn(gridStub, 'setSelectedRows'); const setItemsSpy = jest.spyOn(dataViewStub, 'setItems'); @@ -1868,7 +1865,7 @@ describe('CompositeEditorService', () => { jest.spyOn(currentEditorMock, 'validate').mockReturnValue({ valid: true, msg: null }); jest.spyOn(dataViewStub, 'getAllSelectedIds').mockReturnValue([222]); jest.spyOn(dataViewStub, 'mapIdsToRows').mockReturnValue([0]); - const cancelCommitSpy = jest.spyOn(gridStub.getEditController(), 'cancelCurrentEdit'); + const cancelCommitSpy = jest.spyOn(gridStub.getEditController() as any, 'cancelCurrentEdit'); const mockOnSave = jest.fn(); mockOnSave.mockResolvedValue(Promise.reject(new Error('some error'))); @@ -2005,7 +2002,7 @@ describe('CompositeEditorService', () => { jest.spyOn(dataViewStub, 'mapIdsToRows').mockReturnValue([0]); jest.spyOn(dataViewStub, 'getItemById').mockReturnValue(mockProduct); const getEditSpy = jest.spyOn(gridStub, 'getEditController'); - const cancelCommitSpy = jest.spyOn(gridStub.getEditController(), 'cancelCurrentEdit'); + const cancelCommitSpy = jest.spyOn(gridStub.getEditController() as any, 'cancelCurrentEdit'); const setActiveRowSpy = jest.spyOn(gridStub, 'setActiveRow'); const updateItemsSpy = jest.spyOn(gridServiceStub, 'updateItems'); diff --git a/packages/composite-editor-component/src/slick-composite-editor.component.ts b/packages/composite-editor-component/src/slick-composite-editor.component.ts index 638d1f82c..2532785b8 100644 --- a/packages/composite-editor-component/src/slick-composite-editor.component.ts +++ b/packages/composite-editor-component/src/slick-composite-editor.component.ts @@ -14,13 +14,9 @@ import type { GridService, Locale, OnErrorOption, - OnCompositeEditorChangeEventArgs, PlainFunc, SlickCompositeEditor, - SlickDataView, - SlickEventHandler, - SlickGrid, - SlickNamespace, + SlickGridUniversal, TranslaterService, } from '@slickgrid-universal/common'; import { @@ -32,10 +28,9 @@ import { sanitizeTextByAvailableSanitizer, SortDirectionNumber, } from '@slickgrid-universal/common'; -import { CompositeEditor } from './compositeEditor.factory'; +import { type OnCompositeEditorChangeEventArgs, type SlickDataView, SlickEventHandler } from 'slickgrid'; -// using external non-typed js libraries -declare const Slick: SlickNamespace; +import { CompositeEditor } from './compositeEditor.factory'; const DEFAULT_ON_ERROR = (error: OnErrorOption) => console.log(error.message); @@ -66,7 +61,7 @@ export class SlickCompositeEditorComponent implements ExternalResource { protected _editorContainers!: Array; protected _modalBodyTopValidationElm!: HTMLDivElement; protected _modalSaveButtonElm!: HTMLButtonElement; - protected grid!: SlickGrid; + protected grid!: SlickGridUniversal; protected gridService: GridService | null = null; protected translaterService?: TranslaterService | null; @@ -75,7 +70,7 @@ export class SlickCompositeEditorComponent implements ExternalResource { } get dataView(): SlickDataView { - return this.grid.getData() as SlickDataView; + return this.grid?.getData(); } get dataViewLength(): number { @@ -98,7 +93,7 @@ export class SlickCompositeEditorComponent implements ExternalResource { } constructor() { - this._eventHandler = new Slick.EventHandler(); + this._eventHandler = new SlickEventHandler(); this._bindEventService = new BindingEventService(); } @@ -108,7 +103,7 @@ export class SlickCompositeEditorComponent implements ExternalResource { * Note: we aren't using DI in the constructor simply to be as framework agnostic as possible, * we are simply using this init() function with a very basic container service to do the job */ - init(grid: SlickGrid, containerService: ContainerService) { + init(grid: SlickGridUniversal, containerService: ContainerService) { this.grid = grid; this.gridService = containerService.get('GridService'); this.translaterService = containerService.get('TranslaterService'); @@ -487,7 +482,7 @@ export class SlickCompositeEditorComponent implements ExternalResource { this._editorContainers = modalColumns.map(col => modalBodyElm.querySelector(`[data-editorid=${col.id}]`)) || []; this._compositeOptions = { destroy: this.disposeComponent.bind(this), modalType, validationMsgPrefix: '* ', formValues: {}, editors: this._editors }; const compositeEditor = new (CompositeEditor as any)(modalColumns, this._editorContainers, this._compositeOptions) as SlickCompositeEditor; - this.grid.editActiveCell(compositeEditor); + this.grid.editActiveCell(compositeEditor as any); // -- // Add a few Event Handlers @@ -529,7 +524,7 @@ export class SlickCompositeEditorComponent implements ExternalResource { } if (confirmed) { - this.grid.getEditController().cancelCurrentEdit(); + this.grid.getEditController()?.cancelCurrentEdit(); // cancel current edit is not enough when editing/cloning, // we also need to reset with the original item data context to undo/reset the entire row @@ -903,10 +898,10 @@ export class SlickCompositeEditorComponent implements ExternalResource { } /** Check wether the grid has the Row Selection enabled */ - protected hasRowSelectionEnabled() { + protected hasRowSelectionEnabled(): boolean { const selectionModel = this.grid.getSelectionModel(); const isRowSelectionEnabled = this.gridOptions.enableRowSelection || this.gridOptions.enableCheckboxSelector; - return (isRowSelectionEnabled && selectionModel); + return !!(isRowSelectionEnabled && selectionModel); } /** Reset Form button handler */ @@ -927,7 +922,7 @@ export class SlickCompositeEditorComponent implements ExternalResource { switch (modalType) { case 'mass-update': this.handleMassSaving(modalType, () => { - this.grid.getEditController().cancelCurrentEdit(); + this.grid.getEditController()?.cancelCurrentEdit(); this.grid.setActiveCell(0, 0, false); if (this._options.shouldClearRowSelectionAfterMassAction) { this.grid.setSelectedRows([]); @@ -936,7 +931,7 @@ export class SlickCompositeEditorComponent implements ExternalResource { break; case 'mass-selection': this.handleMassSaving(modalType, () => { - this.grid.getEditController().cancelCurrentEdit(); + this.grid.getEditController()?.cancelCurrentEdit(); this.grid.setActiveRow(this._lastActiveRowNumber); if (this._options.shouldClearRowSelectionAfterMassAction) { this.grid.setSelectedRows([]); @@ -949,7 +944,7 @@ export class SlickCompositeEditorComponent implements ExternalResource { // post save callback (before closing modal) const postSaveCloneCallback = () => { - this.grid.getEditController().cancelCurrentEdit(); + this.grid.getEditController()?.cancelCurrentEdit(); this.grid.setActiveCell(0, 0, false); }; @@ -967,7 +962,7 @@ export class SlickCompositeEditorComponent implements ExternalResource { // commit the changes into the grid // if it's a "create" then it will triggered the "onAddNewRow" event which will in term push it to the grid // while an "edit" will simply applies the changes directly on the same row - this.grid.getEditController().commitCurrentEdit(); + this.grid.getEditController()?.commitCurrentEdit(); // if the user provided the "onSave" callback, let's execute it with the item data context if (typeof this._options?.onSave === 'function') { @@ -1001,7 +996,7 @@ export class SlickCompositeEditorComponent implements ExternalResource { /** Put back the current row to its original item data context using the DataView without triggering a change */ protected resetCurrentRowDataContext() { const idPropName = this.gridOptions.datasetIdPropertyName || 'id'; - const dataView = this.grid.getData(); + const dataView = this.grid.getData(); dataView.updateItem(this._originalDataContext[idPropName], this._originalDataContext); } diff --git a/packages/custom-footer-component/src/slick-footer.component.ts b/packages/custom-footer-component/src/slick-footer.component.ts index 90e7027ae..279756b46 100644 --- a/packages/custom-footer-component/src/slick-footer.component.ts +++ b/packages/custom-footer-component/src/slick-footer.component.ts @@ -1,3 +1,4 @@ +import { SlickEventHandler } from 'slickgrid'; import * as moment_ from 'moment-mini'; const moment = (moment_ as any)['default'] || moment_; // patch to fix rollup "moment has no default export" issue, document here https://github.com/rollup/rollup/issues/670 @@ -7,17 +8,14 @@ import type { Locale, Metrics, MetricTexts, - SlickEventHandler, - SlickGrid, - SlickNamespace, Subscription, + SlickGridUniversal, TranslaterService, } from '@slickgrid-universal/common'; import { Constants, createDomElement, sanitizeTextByAvailableSanitizer, } from '@slickgrid-universal/common'; import { BasePubSubService } from '@slickgrid-universal/event-pub-sub'; import { BindingHelper } from '@slickgrid-universal/binding'; -declare const Slick: SlickNamespace; export class SlickFooterComponent { protected _bindingHelper: BindingHelper; protected _enableTranslate = false; @@ -43,7 +41,7 @@ export class SlickFooterComponent { /** Getter for the Grid Options pulled through the Grid Object */ get gridOptions(): GridOption { - return (this.grid && this.grid.getOptions) ? this.grid.getOptions() : {}; + return this.grid?.getOptions() ?? {}; } get locales(): Locale { @@ -69,10 +67,10 @@ export class SlickFooterComponent { this.renderRightFooterText(text); } - constructor(protected readonly grid: SlickGrid, protected readonly customFooterOptions: CustomFooterOption, protected readonly pubSubService: BasePubSubService, protected readonly translaterService?: TranslaterService) { + constructor(protected readonly grid: SlickGridUniversal, protected readonly customFooterOptions: CustomFooterOption, protected readonly pubSubService: BasePubSubService, protected readonly translaterService?: TranslaterService) { this._bindingHelper = new BindingHelper(); this._bindingHelper.querySelectorPrefix = `.${this.gridUid} `; - this._eventHandler = new Slick.EventHandler(); + this._eventHandler = new SlickEventHandler(); this._enableTranslate = this.gridOptions?.enableTranslate ?? false; this._isLeftFooterOriginallyEmpty = !(this.gridOptions.customFooterOptions?.leftFooterText); this._isRightFooterOriginallyEmpty = !(this.gridOptions.customFooterOptions?.rightFooterText); diff --git a/packages/custom-footer-component/src/slick-footer.spec.ts b/packages/custom-footer-component/src/slick-footer.spec.ts index 9816b2961..3bc06faf9 100644 --- a/packages/custom-footer-component/src/slick-footer.spec.ts +++ b/packages/custom-footer-component/src/slick-footer.spec.ts @@ -1,4 +1,6 @@ -import { CustomFooterOption, GridOption, SlickGrid } from '@slickgrid-universal/common'; +import { CustomFooterOption, GridOption, type SlickGridUniversal } from '@slickgrid-universal/common'; +import { SlickEvent } from 'slickgrid'; + import { SlickFooterComponent } from './slick-footer.component'; import { EventPubSubService } from '@slickgrid-universal/event-pub-sub'; import { TranslateServiceStub } from '../../../test/translateServiceStub'; @@ -7,8 +9,6 @@ function removeExtraSpaces(text: string) { return `${text}`.replace(/\s{2,}/g, ''); } -declare const Slick: any; - const mockGridOptions = { enableTranslate: false, showCustomFooter: true, @@ -17,9 +17,9 @@ const mockGridOptions = { const gridStub = { getOptions: () => mockGridOptions, getUID: () => 'slickgrid_123456', - onSelectedRowsChanged: new Slick.Event(), + onSelectedRowsChanged: new SlickEvent(), registerPlugin: jest.fn(), -} as unknown as SlickGrid; +} as unknown as SlickGridUniversal; describe('Slick-Footer Component', () => { let component: SlickFooterComponent; @@ -188,7 +188,7 @@ describe('Slick-Footer Component', () => { it('should throw an error when enabling translate without a Translate Service', () => { mockGridOptions.enableTranslate = true; - expect(() => new SlickFooterComponent(gridStub, mockGridOptions.customFooterOptions as CustomFooterOption, eventPubSubService, null)) + expect(() => new SlickFooterComponent(gridStub, mockGridOptions.customFooterOptions as CustomFooterOption, eventPubSubService, null as any)) .toThrow('[Slickgrid-Universal] requires a Translate Service to be installed and configured when the grid option "enableTranslate" is enabled.'); }); @@ -263,7 +263,7 @@ describe('Slick-Footer Component', () => { component = new SlickFooterComponent(gridStub, mockGridOptions.customFooterOptions as CustomFooterOption, eventPubSubService, translateService); component.renderFooter(div); component.metrics = { startTime: mockTimestamp, endTime: mockTimestamp, itemCount: 7, totalItemCount: 99 }; - gridStub.onSelectedRowsChanged.notify({ rows: [1], grid: gridStub, previousSelectedRows: [] }); + gridStub.onSelectedRowsChanged.notify({ rows: [1], grid: gridStub, previousSelectedRows: [] } as any); const footerContainerElm = document.querySelector('div.slick-custom-footer.slickgrid_123456') as HTMLDivElement; const leftFooterElm = document.querySelector('div.slick-custom-footer.slickgrid_123456 > div.left-footer') as HTMLSpanElement; @@ -280,17 +280,17 @@ describe('Slick-Footer Component', () => { 7some of99 some items`)); - gridStub.onSelectedRowsChanged.notify({ rows: [1, 2, 3, 4, 5], grid: gridStub, previousSelectedRows: [] }); + gridStub.onSelectedRowsChanged.notify({ rows: [1, 2, 3, 4, 5], grid: gridStub, previousSelectedRows: [] } as any); expect(leftFooterElm.innerHTML).toBe('5 items selected'); }); it('should not not display row selection count after triggering "onSelectedRowsChanged" event when "hideRowSelectionCount" is set to True', () => { mockGridOptions.enableCheckboxSelector = true; - mockGridOptions.customFooterOptions.hideRowSelectionCount = true; + mockGridOptions.customFooterOptions!.hideRowSelectionCount = true; component = new SlickFooterComponent(gridStub, mockGridOptions.customFooterOptions as CustomFooterOption, eventPubSubService, translateService); component.renderFooter(div); component.metrics = { startTime: mockTimestamp, endTime: mockTimestamp, itemCount: 7, totalItemCount: 99 }; - gridStub.onSelectedRowsChanged.notify({ rows: [1], grid: gridStub, previousSelectedRows: [] }); + gridStub.onSelectedRowsChanged.notify({ rows: [1], grid: gridStub, previousSelectedRows: [] } as any); const footerContainerElm = document.querySelector('div.slick-custom-footer.slickgrid_123456') as HTMLDivElement; const leftFooterElm = document.querySelector('div.slick-custom-footer.slickgrid_123456 > div.left-footer') as HTMLSpanElement; @@ -312,12 +312,12 @@ describe('Slick-Footer Component', () => { mockGridOptions.enableCheckboxSelector = true; component = new SlickFooterComponent(gridStub, mockGridOptions.customFooterOptions as CustomFooterOption, eventPubSubService, translateService); component.renderFooter(div); - gridStub.onSelectedRowsChanged.notify({ rows: [1], previousSelectedRows: [], grid: gridStub, }); + gridStub.onSelectedRowsChanged.notify({ rows: [1], previousSelectedRows: [], grid: gridStub, } as any); expect(component).toBeTruthy(); expect(component.leftFooterText).toEqual('1 items selected'); - gridStub.onSelectedRowsChanged.notify({ rows: [1, 2, 3, 4, 5], previousSelectedRows: [], grid: gridStub, }); + gridStub.onSelectedRowsChanged.notify({ rows: [1, 2, 3, 4, 5], previousSelectedRows: [], grid: gridStub, } as any); expect(component.leftFooterText).toEqual('5 items selected'); }); @@ -329,18 +329,18 @@ describe('Slick-Footer Component', () => { component = new SlickFooterComponent(gridStub, mockGridOptions.customFooterOptions as CustomFooterOption, eventPubSubService, translateService); component.renderFooter(div); - gridStub.onSelectedRowsChanged.notify({ rows: [1], previousSelectedRows: [], grid: gridStub, }); + gridStub.onSelectedRowsChanged.notify({ rows: [1], previousSelectedRows: [], grid: gridStub, } as any); expect(component.leftFooterText).toEqual('1 éléments sélectionnés'); - gridStub.onSelectedRowsChanged.notify({ rows: [1, 2, 3, 4, 5], previousSelectedRows: [], grid: gridStub, }); + gridStub.onSelectedRowsChanged.notify({ rows: [1, 2, 3, 4, 5], previousSelectedRows: [], grid: gridStub, } as any); expect(component.leftFooterText).toEqual('5 éléments sélectionnés'); }); it('should not display row selection count after triggering "onSelectedRowsChanged" event if "hideRowSelectionCount" is set to True', () => { mockGridOptions.enableCheckboxSelector = true; - mockGridOptions.customFooterOptions.hideRowSelectionCount = true; + mockGridOptions.customFooterOptions!.hideRowSelectionCount = true; component.renderFooter(div); - gridStub.onSelectedRowsChanged.notify({ rows: [1], previousSelectedRows: [], grid: gridStub, }); + gridStub.onSelectedRowsChanged.notify({ rows: [1], previousSelectedRows: [], grid: gridStub, } as any); expect(component.leftFooterText).toBe('0 items selected'); }); diff --git a/packages/custom-tooltip-plugin/src/__tests__/slickCustomTooltip.spec.ts b/packages/custom-tooltip-plugin/src/__tests__/slickCustomTooltip.spec.ts index e48655315..0cdb87181 100644 --- a/packages/custom-tooltip-plugin/src/__tests__/slickCustomTooltip.spec.ts +++ b/packages/custom-tooltip-plugin/src/__tests__/slickCustomTooltip.spec.ts @@ -1,5 +1,8 @@ import { delay, of, throwError } from 'rxjs'; -import { Column, getHtmlElementOffset, GridOption, SlickDataView, SlickGrid, SlickNamespace, SharedService, } from '@slickgrid-universal/common'; +import { type SlickDataView, SlickEvent, SlickEventData } from 'slickgrid'; + +import { Column, GridOption, SlickGridUniversal, SharedService, } from '@slickgrid-universal/common'; +import * as utilities from '@slickgrid-universal/common/dist/commonjs/services/utilities'; import { SlickCustomTooltip } from '../slickCustomTooltip'; import { ContainerServiceStub } from '../../../../test/containerServiceStub'; @@ -11,7 +14,6 @@ jest.mock('@slickgrid-universal/common', () => ({ getHtmlElementOffset: jest.fn(), })); -declare const Slick: SlickNamespace; const GRID_UID = 'slickgrid12345'; const gridOptionsMock = { enableAutoTooltip: true } as GridOption; @@ -33,13 +35,13 @@ const gridStub = { getOptions: () => gridOptionsMock, getUID: () => GRID_UID, registerPlugin: jest.fn(), - onMouseEnter: new Slick.Event(), - onHeaderMouseEnter: new Slick.Event(), - onHeaderRowMouseEnter: new Slick.Event(), - onMouseLeave: new Slick.Event(), - onHeaderMouseLeave: new Slick.Event(), - onHeaderRowMouseLeave: new Slick.Event(), -} as unknown as SlickGrid; + onMouseEnter: new SlickEvent(), + onHeaderMouseEnter: new SlickEvent(), + onHeaderRowMouseEnter: new SlickEvent(), + onMouseLeave: new SlickEvent(), + onHeaderMouseLeave: new SlickEvent(), + onHeaderRowMouseLeave: new SlickEvent(), +} as unknown as SlickGridUniversal; describe('SlickCustomTooltip plugin', () => { let divContainer = document.createElement('div'); @@ -93,7 +95,7 @@ describe('SlickCustomTooltip plugin', () => { jest.spyOn(dataviewStub, 'getItem').mockReturnValue({ firstName: 'John', lastName: 'Doe' }); plugin.init(gridStub, container); - gridStub.onMouseEnter.notify({ grid: gridStub }, { ...new Slick.EventData(), target: cellNode }); + gridStub.onMouseEnter.notify({ grid: gridStub } as any, { ...new SlickEventData(), target: cellNode } as any); expect(document.body.querySelector('.slick-custom-tooltip')).toBeFalsy(); }); @@ -132,7 +134,7 @@ describe('SlickCustomTooltip plugin', () => { plugin.init(gridStub, container); plugin.setOptions({ usabilityOverride: () => false }); - gridStub.onMouseEnter.notify({ grid: gridStub }, { ...new Slick.EventData(), target: cellNode }); + gridStub.onMouseEnter.notify({ grid: gridStub } as any, { ...new SlickEventData(), target: cellNode } as any); expect(document.body.querySelector('.slick-custom-tooltip')).toBeFalsy(); }); @@ -149,7 +151,7 @@ describe('SlickCustomTooltip plugin', () => { plugin.init(gridStub, container); plugin.setOptions({ useRegularTooltip: true }); - gridStub.onMouseEnter.notify({ grid: gridStub }, { ...new Slick.EventData(), target: cellNode }); + gridStub.onMouseEnter.notify({ grid: gridStub } as any, { ...new SlickEventData(), target: cellNode } as any); expect(document.body.querySelector('.slick-custom-tooltip')).toBeFalsy(); }); @@ -169,7 +171,7 @@ describe('SlickCustomTooltip plugin', () => { plugin.init(gridStub, container); plugin.setOptions({ useRegularTooltip: true }); - gridStub.onMouseEnter.notify({ grid: gridStub }, { ...new Slick.EventData(), target: cellNode }); + gridStub.onMouseEnter.notify({ grid: gridStub } as any, { ...new SlickEventData(), target: cellNode } as any); const tooltipElm = document.body.querySelector('.slick-custom-tooltip') as HTMLDivElement; expect(tooltipElm).toBeTruthy(); @@ -193,7 +195,7 @@ describe('SlickCustomTooltip plugin', () => { plugin.init(gridStub, container); plugin.setOptions({ useRegularTooltip: false, formatter: () => 'EDITING FORMATTER' }); - gridStub.onMouseEnter.notify({ grid: gridStub }, { ...new Slick.EventData(), target: cellNode }); + gridStub.onMouseEnter.notify({ grid: gridStub } as any, { ...new SlickEventData(), target: cellNode } as any); const tooltipElm = document.body.querySelector('.slick-custom-tooltip') as HTMLDivElement; expect(tooltipElm).toBeTruthy(); @@ -214,7 +216,7 @@ describe('SlickCustomTooltip plugin', () => { plugin.init(gridStub, container); plugin.setOptions({ useRegularTooltip: true }); - gridStub.onMouseEnter.notify({ grid: gridStub }, { ...new Slick.EventData(), target: cellNode }); + gridStub.onMouseEnter.notify({ grid: gridStub } as any, { ...new SlickEventData(), target: cellNode } as any); const tooltipElm = document.body.querySelector('.slick-custom-tooltip') as HTMLDivElement; expect(tooltipElm).toBeTruthy(); @@ -235,7 +237,7 @@ describe('SlickCustomTooltip plugin', () => { plugin.init(gridStub, container); plugin.setOptions({ useRegularTooltip: true, position: 'right-align' }); - gridStub.onMouseEnter.notify({ grid: gridStub }, { ...new Slick.EventData(), target: cellNode }); + gridStub.onMouseEnter.notify({ grid: gridStub } as any, { ...new SlickEventData(), target: cellNode } as any); const tooltipElm = document.body.querySelector('.slick-custom-tooltip') as HTMLDivElement; expect(tooltipElm).toBeTruthy(); @@ -258,7 +260,7 @@ describe('SlickCustomTooltip plugin', () => { plugin.init(gridStub, container); plugin.setOptions({ useRegularTooltip: true, position: 'center' }); - gridStub.onMouseEnter.notify({ grid: gridStub }, { ...new Slick.EventData(), target: cellNode }); + gridStub.onMouseEnter.notify({ grid: gridStub } as any, { ...new SlickEventData(), target: cellNode } as any); const tooltipElm = document.body.querySelector('.slick-custom-tooltip') as HTMLDivElement; expect(tooltipElm).toBeTruthy(); @@ -281,7 +283,7 @@ describe('SlickCustomTooltip plugin', () => { plugin.init(gridStub, container); plugin.setOptions({ useRegularTooltip: true, tooltipTextMaxLength: 23 }); - gridStub.onMouseEnter.notify({ grid: gridStub }, { ...new Slick.EventData(), target: cellNode }); + gridStub.onMouseEnter.notify({ grid: gridStub } as any, { ...new SlickEventData(), target: cellNode } as any); const tooltipElm = document.body.querySelector('.slick-custom-tooltip') as HTMLDivElement; expect(tooltipElm).toBeTruthy(); @@ -305,7 +307,7 @@ describe('SlickCustomTooltip plugin', () => { plugin.init(gridStub, container); plugin.setOptions({ useRegularTooltip: true, maxWidth: 85 }); - gridStub.onMouseEnter.notify({ grid: gridStub }, { ...new Slick.EventData(), target: cellNode }); + gridStub.onMouseEnter.notify({ grid: gridStub } as any, { ...new SlickEventData(), target: cellNode } as any); const tooltipElm = document.body.querySelector('.slick-custom-tooltip') as HTMLDivElement; expect(tooltipElm).toBeTruthy(); @@ -316,7 +318,7 @@ describe('SlickCustomTooltip plugin', () => { expect(tooltipElm.classList.contains('arrow-down')).toBeTruthy(); expect(tooltipElm.classList.contains('arrow-left-align')).toBeTruthy(); - gridStub.onMouseLeave.notify({ grid: gridStub }); + gridStub.onMouseLeave.notify({ grid: gridStub } as any); expect(hideColumnSpy).toHaveBeenCalled(); }); @@ -334,7 +336,7 @@ describe('SlickCustomTooltip plugin', () => { plugin.init(gridStub, container); plugin.setOptions({ useRegularTooltip: true, tooltipTextMaxLength: 23 }); - gridStub.onMouseEnter.notify({ grid: gridStub }, { ...new Slick.EventData(), target: cellNode }); + gridStub.onMouseEnter.notify({ grid: gridStub } as any, { ...new SlickEventData(), target: cellNode } as any); const tooltipElm = document.body.querySelector('.slick-custom-tooltip') as HTMLDivElement; expect(tooltipElm).toBeTruthy(); @@ -357,7 +359,7 @@ describe('SlickCustomTooltip plugin', () => { plugin.init(gridStub, container); plugin.setOptions({ useRegularTooltip: true, tooltipTextMaxLength: 23 }); - gridStub.onHeaderMouseEnter.notify({ column: mockColumns[0], grid: gridStub }, { ...new Slick.EventData(), target: cellNode }); + gridStub.onHeaderMouseEnter.notify({ column: mockColumns[0], grid: gridStub }, { ...new SlickEventData(), target: cellNode } as any); const tooltipElm = document.body.querySelector('.slick-custom-tooltip') as HTMLDivElement; expect(tooltipElm).toBeFalsy(); @@ -375,7 +377,7 @@ describe('SlickCustomTooltip plugin', () => { plugin.init(gridStub, container); plugin.setOptions({ useRegularTooltip: true, useRegularTooltipFromFormatterOnly: true, maxHeight: 100 }); - gridStub.onMouseEnter.notify({ grid: gridStub }, { ...new Slick.EventData(), target: cellNode }); + gridStub.onMouseEnter.notify({ grid: gridStub } as any, { ...new SlickEventData(), target: cellNode } as any); const tooltipElm = document.body.querySelector('.slick-custom-tooltip') as HTMLDivElement; expect(tooltipElm).toBeTruthy(); @@ -403,7 +405,7 @@ describe('SlickCustomTooltip plugin', () => { formatter: () => 'loading...', asyncPostFormatter: undefined }); - gridStub.onMouseEnter.notify({ grid: gridStub }, { ...new Slick.EventData(), target: cellNode }); + gridStub.onMouseEnter.notify({ grid: gridStub } as any, { ...new SlickEventData(), target: cellNode } as any); expect(consoleSpy).toHaveBeenCalledWith(`[Slickgrid-Universal] when using "asyncProcess" with Custom Tooltip, you must also provide an "asyncPostFormatter" formatter.`); }); @@ -424,7 +426,7 @@ describe('SlickCustomTooltip plugin', () => { formatter: () => 'loading...', asyncPostFormatter: (row, cell, val, column, dataContext) => `async post text with ratio: ${dataContext.__params.ratio || ''}`, }); - gridStub.onMouseEnter.notify({ grid: gridStub }, { ...new Slick.EventData(), target: cellNode }); + gridStub.onMouseEnter.notify({ grid: gridStub } as any, { ...new SlickEventData(), target: cellNode } as any); let tooltipElm = document.body.querySelector('.slick-custom-tooltip') as HTMLDivElement; expect(tooltipElm).toBeTruthy(); @@ -455,7 +457,7 @@ describe('SlickCustomTooltip plugin', () => { formatter: () => 'loading...', asyncPostFormatter: (row, cell, val, column, dataContext) => `async post text with ratio: ${dataContext.__params.ratio || ''}`, }); - gridStub.onMouseEnter.notify({ grid: gridStub }, { ...new Slick.EventData(), target: cellNode }); + gridStub.onMouseEnter.notify({ grid: gridStub } as any, { ...new SlickEventData(), target: cellNode } as any); let tooltipElm = document.body.querySelector('.slick-custom-tooltip') as HTMLDivElement; expect(tooltipElm).toBeTruthy(); @@ -485,7 +487,7 @@ describe('SlickCustomTooltip plugin', () => { asyncProcess: () => Promise.resolve({ ratio: 1.2 }), asyncPostFormatter: (row, cell, val, column, dataContext) => `async post text with ratio: ${dataContext.__params.ratio || ''}`, }); - gridStub.onMouseEnter.notify({ grid: gridStub }, { ...new Slick.EventData(), target: cellNode }); + gridStub.onMouseEnter.notify({ grid: gridStub } as any, { ...new SlickEventData(), target: cellNode } as any); let tooltipElm = document.body.querySelector('.slick-custom-tooltip') as HTMLDivElement; jest.spyOn(tooltipElm, 'getBoundingClientRect').mockReturnValue({ top: 22, left: 11, height: 100, width: 250 } as any); @@ -523,7 +525,7 @@ describe('SlickCustomTooltip plugin', () => { asyncProcess: () => Promise.resolve({ ratio: 1.2 }), asyncPostFormatter: (row, cell, val, column, dataContext) => `cell value`, }); - gridStub.onMouseEnter.notify({ grid: gridStub }, { ...new Slick.EventData(), target: cellNode }); + gridStub.onMouseEnter.notify({ grid: gridStub } as any, { ...new SlickEventData(), target: cellNode } as any); let tooltipElm = document.body.querySelector('.slick-custom-tooltip') as HTMLDivElement; @@ -553,7 +555,7 @@ describe('SlickCustomTooltip plugin', () => { formatter: () => 'loading...', asyncPostFormatter: (row, cell, val, column, dataContext) => `async post text with ratio: ${dataContext.__params.ratio || ''}`, }); - gridStub.onMouseEnter.notify({ grid: gridStub }, { ...new Slick.EventData(), target: cellNode }); + gridStub.onMouseEnter.notify({ grid: gridStub } as any, { ...new SlickEventData(), target: cellNode } as any); const cancellablePromise = plugin.cancellablePromise; let tooltipElm = document.body.querySelector('.slick-custom-tooltip') as HTMLDivElement; expect(tooltipElm).toBeTruthy(); @@ -580,7 +582,7 @@ describe('SlickCustomTooltip plugin', () => { plugin.init(gridStub, container); plugin.setOptions({ useRegularTooltip: true, headerFormatter: mockFormatter }); - const eventData = new Slick.EventData(); + const eventData = new SlickEventData(); const div = document.createElement('div'); div.className = 'toggle'; Object.defineProperty(eventData, 'target', { writable: true, value: div }); @@ -605,7 +607,7 @@ describe('SlickCustomTooltip plugin', () => { plugin.init(gridStub, container); plugin.setOptions({ headerFormatter: () => 'header tooltip text' }); - const eventData = new Slick.EventData(); + const eventData = new SlickEventData(); const divHeaders = document.createElement('div'); divHeaders.className = 'slick-header-columns'; const divHeaderColumn = document.createElement('div'); @@ -634,7 +636,7 @@ describe('SlickCustomTooltip plugin', () => { plugin.init(gridStub, container); plugin.setOptions({ headerRowFormatter: () => 'header row tooltip text' }); - const eventData = new Slick.EventData(); + const eventData = new SlickEventData(); const divHeaders = document.createElement('div'); divHeaders.className = 'slick-header-columns'; const divHeaderColumn = document.createElement('div'); diff --git a/packages/custom-tooltip-plugin/src/slickCustomTooltip.ts b/packages/custom-tooltip-plugin/src/slickCustomTooltip.ts index 25ee99322..74f3d7e19 100644 --- a/packages/custom-tooltip-plugin/src/slickCustomTooltip.ts +++ b/packages/custom-tooltip-plugin/src/slickCustomTooltip.ts @@ -1,18 +1,17 @@ +import { type SlickDataView, SlickEventHandler } from 'slickgrid'; + import type { CancellablePromiseWrapper, Column, ContainerService, CustomTooltipOption, + DOMEvent, Formatter, GridOption, Observable, RxJsFacade, SharedService, - SlickDataView, - SlickEventData, - SlickEventHandler, - SlickGrid, - SlickNamespace, + SlickGridUniversal, Subscription, } from '@slickgrid-universal/common'; import { @@ -25,9 +24,6 @@ import { sanitizeTextByAvailableSanitizer, } from '@slickgrid-universal/common'; -// using external SlickGrid JS libraries -declare const Slick: SlickNamespace; - type CellType = 'slick-cell' | 'slick-header-column' | 'slick-headerrow-column'; /** @@ -55,6 +51,8 @@ type CellType = 'slick-cell' | 'slick-header-column' | 'slick-headerrow-column'; * }; */ export class SlickCustomTooltip { + name: 'CustomTooltip' = 'CustomTooltip' as const; + protected _addonOptions?: CustomTooltipOption; protected _cellAddonOptions?: CustomTooltipOption; protected _cellNodeElm?: HTMLDivElement; @@ -73,12 +71,11 @@ export class SlickCustomTooltip { regularTooltipWhiteSpace: 'pre-line', whiteSpace: 'normal', } as CustomTooltipOption; - protected _grid!: SlickGrid; + protected _grid!: SlickGridUniversal; protected _eventHandler: SlickEventHandler; - name: 'CustomTooltip' = 'CustomTooltip' as const; constructor() { - this._eventHandler = new Slick.EventHandler(); + this._eventHandler = new SlickEventHandler(); } get addonOptions(): CustomTooltipOption | undefined { @@ -102,7 +99,7 @@ export class SlickCustomTooltip { /** Getter for the Grid Options pulled through the Grid Object */ get gridOptions(): GridOption { - return this._grid.getOptions() || {}; + return this._grid?.getOptions() || {} as GridOption; } /** Getter for the grid uid */ @@ -121,7 +118,7 @@ export class SlickCustomTooltip { this._rxjs = rxjs; } - init(grid: SlickGrid, containerService: ContainerService) { + init(grid: SlickGridUniversal, containerService: ContainerService) { this._grid = grid; this._rxjs = containerService.get('RxJsFacade'); this._sharedService = containerService.get('SharedService'); @@ -180,7 +177,7 @@ export class SlickCustomTooltip { } /** depending on the selector type, execute the necessary handler code */ - protected handleOnHeaderMouseEnterByType(event: SlickEventData, args: any, selector: CellType) { + protected handleOnHeaderMouseEnterByType(event: DOMEvent, args: any, selector: CellType) { this._cellType = selector; // before doing anything, let's remove any previous tooltip before @@ -221,7 +218,7 @@ export class SlickCustomTooltip { } } - protected async handleOnMouseEnter(event: SlickEventData) { + protected async handleOnMouseEnter(event: DOMEvent) { this._cellType = 'slick-cell'; // before doing anything, let's remove any previous tooltip before @@ -230,7 +227,7 @@ export class SlickCustomTooltip { if (event && this._grid) { // get cell only when it's possible (ie, Composite Editor will not be able to get cell and so it will never show any tooltip) - const targetClassName = (event?.target as HTMLDivElement)?.closest('.slick-cell')?.className; + const targetClassName = event?.target?.closest('.slick-cell')?.className; const cell = (targetClassName && /l\d+/.exec(targetClassName || '')) ? this._grid.getCellFromEvent(event) : null; if (cell) { diff --git a/packages/empty-warning-component/src/slick-empty-warning.component.ts b/packages/empty-warning-component/src/slick-empty-warning.component.ts index 6d0a0c897..3ffb19273 100644 --- a/packages/empty-warning-component/src/slick-empty-warning.component.ts +++ b/packages/empty-warning-component/src/slick-empty-warning.component.ts @@ -3,7 +3,7 @@ import type { EmptyWarning, ExternalResource, GridOption, - SlickGrid, + SlickGridUniversal, TranslaterService } from '@slickgrid-universal/common'; import { sanitizeTextByAvailableSanitizer } from '@slickgrid-universal/common'; @@ -11,19 +11,19 @@ import { sanitizeTextByAvailableSanitizer } from '@slickgrid-universal/common'; export class SlickEmptyWarningComponent implements ExternalResource { protected _warningLeftElement: HTMLDivElement | null = null; protected _warningRightElement: HTMLDivElement | null = null; - protected grid!: SlickGrid; + protected grid!: SlickGridUniversal; protected isPreviouslyShown = false; protected translaterService?: TranslaterService | null; /** Getter for the Grid Options pulled through the Grid Object */ get gridOptions(): GridOption { - return (this.grid && this.grid.getOptions) ? this.grid.getOptions() : {}; + return this.grid?.getOptions() ?? {}; } constructor() { } - init(grid: SlickGrid, containerService: ContainerService) { + init(grid: SlickGridUniversal, containerService: ContainerService) { this.grid = grid; this.translaterService = containerService.get('TranslaterService'); } diff --git a/packages/empty-warning-component/src/slick-empty-warning.spec.ts b/packages/empty-warning-component/src/slick-empty-warning.spec.ts index 91f56c7f2..58a753e8a 100644 --- a/packages/empty-warning-component/src/slick-empty-warning.spec.ts +++ b/packages/empty-warning-component/src/slick-empty-warning.spec.ts @@ -15,7 +15,7 @@ const gridStub = { getOptions: () => mockGridOptions, getUID: () => GRID_UID, registerPlugin: jest.fn(), -} as unknown as SlickGrid; +} as unknown as SlickGridUniversal; describe('Slick-Empty-Warning Component', () => { let container: ContainerServiceStub; diff --git a/packages/excel-export/src/excelExport.service.spec.ts b/packages/excel-export/src/excelExport.service.spec.ts index 6f64add34..ef3ff12e2 100644 --- a/packages/excel-export/src/excelExport.service.spec.ts +++ b/packages/excel-export/src/excelExport.service.spec.ts @@ -73,7 +73,7 @@ const gridStub = { getOptions: () => mockGridOptions, getColumns: jest.fn(), getGrouping: jest.fn(), -} as unknown as SlickGrid; +} as unknown as SlickGridUniversal; describe('ExcelExportService', () => { let container: ContainerServiceStub; diff --git a/packages/excel-export/src/excelExport.service.ts b/packages/excel-export/src/excelExport.service.ts index 38c14ca42..4b31f7ab1 100644 --- a/packages/excel-export/src/excelExport.service.ts +++ b/packages/excel-export/src/excelExport.service.ts @@ -16,8 +16,7 @@ import type { KeyTitlePair, Locale, PubSubService, - SlickDataView, - SlickGrid, + SlickGridUniversal, TranslaterService, } from '@slickgrid-universal/common'; import { @@ -32,6 +31,7 @@ import { sanitizeHtmlToText, } from '@slickgrid-universal/common'; import { addWhiteSpaces, deepCopy, titleCase } from '@slickgrid-universal/utils'; +import { type SlickDataView } from 'slickgrid'; import { ExcelCellFormat, ExcelMetadata, ExcelStylesheet, } from './interfaces/index'; import { @@ -48,7 +48,7 @@ const DEFAULT_EXPORT_OPTIONS: ExcelExportOption = { export class ExcelExportService implements ExternalResource, BaseExcelExportService { protected _fileFormat = FileType.xlsx; - protected _grid!: SlickGrid; + protected _grid!: SlickGridUniversal; protected _locales!: Locale; protected _groupedColumnHeaders?: Array; protected _columnHeaders: Array = []; @@ -75,12 +75,12 @@ export class ExcelExportService implements ExternalResource, BaseExcelExportServ /** Getter of SlickGrid DataView object */ get _dataView(): SlickDataView { - return (this._grid?.getData()) as SlickDataView; + return this._grid?.getData(); } /** Getter for the Grid Options pulled through the Grid Object */ protected get _gridOptions(): GridOption { - return this._grid?.getOptions() || {}; + return this._grid?.getOptions() || {} as GridOption; } get stylesheet() { @@ -108,7 +108,7 @@ export class ExcelExportService implements ExternalResource, BaseExcelExportServ * @param grid * @param containerService */ - init(grid: SlickGrid, containerService: ContainerService): void { + init(grid: SlickGridUniversal, containerService: ContainerService): void { this._grid = grid; this._pubSubService = containerService.get('PubSubService'); diff --git a/packages/excel-export/src/excelUtils.spec.ts b/packages/excel-export/src/excelUtils.spec.ts index 3eed76921..6c8901b7a 100644 --- a/packages/excel-export/src/excelUtils.spec.ts +++ b/packages/excel-export/src/excelUtils.spec.ts @@ -1,4 +1,4 @@ -import { Column, ExcelStylesheet, FieldType, Formatters, GridOption, GroupTotalFormatters, SlickGrid } from '@slickgrid-universal/common'; +import { Column, ExcelStylesheet, FieldType, Formatters, GridOption, GroupTotalFormatters, SlickGridUniversal } from '@slickgrid-universal/common'; import { getExcelFormatFromGridFormatter, getExcelNumberCallback, getNumericFormatterOptions, useCellFormatByFieldType } from './excelUtils'; @@ -13,7 +13,7 @@ const gridStub = { getOptions: () => mockGridOptions, getColumns: jest.fn(), getGrouping: jest.fn(), -} as unknown as SlickGrid; +} as unknown as SlickGridUniversal; const stylesheetStub = { createFormat: jest.fn(), @@ -683,7 +683,7 @@ describe('excelUtils', () => { const columnDef = { type: FieldType.number, formatter: Formatters.decimal, // eslint-disable-next-line @typescript-eslint/no-unused-vars - groupTotalsFormatter: (totals: any, _columnDef: Column, _grid: SlickGrid) => `Some Total: ${totals.sum}`, + groupTotalsFormatter: (totals: any, _columnDef: Column, _grid: SlickGridUniversal) => `Some Total: ${totals.sum}`, } as Column; const output = getExcelFormatFromGridFormatter(stylesheetStub, { numberFormatter: { id: 3 } }, columnDef, gridStub, 'group'); diff --git a/packages/excel-export/src/excelUtils.ts b/packages/excel-export/src/excelUtils.ts index d349a6b70..4679a93c1 100644 --- a/packages/excel-export/src/excelUtils.ts +++ b/packages/excel-export/src/excelUtils.ts @@ -5,7 +5,7 @@ import type { FormatterType, GetDataValueCallback, GridOption, - SlickGrid, + SlickGridUniversal, } from '@slickgrid-universal/common'; import { Constants, @@ -41,7 +41,7 @@ export function parseNumberWithFormatterOptions(value: any, column: Column, grid } /** use different Excel Stylesheet Format as per the Field Type */ -export function useCellFormatByFieldType(stylesheet: ExcelStylesheet, stylesheetFormatters: any, columnDef: Column, grid: SlickGrid, autoDetect = true) { +export function useCellFormatByFieldType(stylesheet: ExcelStylesheet, stylesheetFormatters: any, columnDef: Column, grid: SlickGridUniversal, autoDetect = true) { const fieldType = getColumnFieldType(columnDef); let stylesheetFormatterId: number | undefined; let callback: GetDataValueCallback = getExcelSameInputDataCallback; @@ -58,7 +58,7 @@ export function getGroupTotalValue(totals: any, columnDef: Column, groupType: st } /** Get numeric formatter options when defined or use default values (minDecimal, maxDecimal, thousandSeparator, decimalSeparator, wrapNegativeNumber) */ -export function getNumericFormatterOptions(columnDef: Column, grid: SlickGrid, formatterType: FormatterType) { +export function getNumericFormatterOptions(columnDef: Column, grid: SlickGridUniversal, formatterType: FormatterType) { let dataType: 'currency' | 'decimal' | 'percent' | 'regular'; if (formatterType === 'group') { @@ -131,7 +131,7 @@ export function getFormatterNumericDataType(formatter?: Formatter) { return dataType; } -export function getExcelFormatFromGridFormatter(stylesheet: ExcelStylesheet, stylesheetFormatters: any, columnDef: Column, grid: SlickGrid, formatterType: FormatterType) { +export function getExcelFormatFromGridFormatter(stylesheet: ExcelStylesheet, stylesheetFormatters: any, columnDef: Column, grid: SlickGridUniversal, formatterType: FormatterType) { let format = ''; let groupType = ''; let stylesheetFormatter: undefined | ExcelFormatter; @@ -250,7 +250,7 @@ function createFormatFromNumber(formattedVal: string) { return format.replace(',', '\,'); } -function createExcelFormatFromGridFormatter(columnDef: Column, grid: SlickGrid, formatterType: FormatterType, groupType = '') { +function createExcelFormatFromGridFormatter(columnDef: Column, grid: SlickGridUniversal, formatterType: FormatterType, groupType = '') { let outputFormat = ''; let positiveFormat = ''; let negativeFormat = ''; diff --git a/packages/graphql/src/services/__tests__/graphql.service.spec.ts b/packages/graphql/src/services/__tests__/graphql.service.spec.ts index 0627813a8..8bc040c7b 100644 --- a/packages/graphql/src/services/__tests__/graphql.service.spec.ts +++ b/packages/graphql/src/services/__tests__/graphql.service.spec.ts @@ -39,7 +39,7 @@ const gridStub = { registerPlugin: jest.fn(), setSelectedRows: jest.fn(), setSortColumns: jest.fn(), -} as unknown as SlickGrid; +} as unknown as SlickGridUniversal; describe('GraphqlService', () => { let mockColumns: Column[]; diff --git a/packages/graphql/src/services/graphql.service.ts b/packages/graphql/src/services/graphql.service.ts index 6c3fb4efa..f78170071 100644 --- a/packages/graphql/src/services/graphql.service.ts +++ b/packages/graphql/src/services/graphql.service.ts @@ -16,7 +16,7 @@ import type { PaginationCursorChangedArgs, SharedService, SingleColumnSort, - SlickGrid, + SlickGridUniversal, SortDirectionString, } from '@slickgrid-universal/common'; import { @@ -46,7 +46,7 @@ export class GraphqlService implements BackendService { protected _currentPagination: CurrentPagination | null = null; protected _currentSorters: CurrentSorter[] = []; protected _columnDefinitions?: Column[]; - protected _grid: SlickGrid | undefined; + protected _grid: SlickGridUniversal | undefined; protected _datasetIdPropName = 'id'; options: GraphqlServiceOption | undefined; pagination: Pagination | undefined; @@ -62,11 +62,11 @@ export class GraphqlService implements BackendService { /** Getter for the Grid Options pulled through the Grid Object */ protected get _gridOptions(): GridOption { - return (this._grid?.getOptions) ? this._grid.getOptions() : {}; + return this._grid?.getOptions() ?? {} as GridOption; } /** Initialization of the service, which acts as a constructor */ - init(serviceOptions?: GraphqlServiceOption, pagination?: Pagination, grid?: SlickGrid, sharedService?: SharedService): void { + init(serviceOptions?: GraphqlServiceOption, pagination?: Pagination, grid?: SlickGridUniversal, sharedService?: SharedService): void { this._grid = grid; this.options = serviceOptions || { datasetName: '' }; this.pagination = pagination; @@ -362,7 +362,7 @@ export class GraphqlService implements BackendService { * } */ processOnSortChanged(_event: Event | undefined, args: SingleColumnSort | MultiColumnSort): string { - const sortColumns = (args.multiColumnSort) ? (args as MultiColumnSort).sortCols : new Array({ columnId: (args as ColumnSort).sortCol.id, sortCol: (args as ColumnSort).sortCol, sortAsc: (args as ColumnSort).sortAsc }); + const sortColumns = (args.multiColumnSort) ? (args as MultiColumnSort).sortCols : new Array({ columnId: (args as ColumnSort).sortCol?.id ?? '', sortCol: (args as ColumnSort).sortCol, sortAsc: (args as ColumnSort).sortAsc }); // loop through all columns to inspect sorters & set the query this.updateSorters(sortColumns); diff --git a/packages/odata/src/services/__tests__/grid-odata.service.spec.ts b/packages/odata/src/services/__tests__/grid-odata.service.spec.ts index 7b35c3d00..c3a39dcb9 100644 --- a/packages/odata/src/services/__tests__/grid-odata.service.spec.ts +++ b/packages/odata/src/services/__tests__/grid-odata.service.spec.ts @@ -34,7 +34,7 @@ const gridStub = { registerPlugin: jest.fn(), setSelectedRows: jest.fn(), setSortColumns: jest.fn(), -} as unknown as SlickGrid; +} as unknown as SlickGridUniversal; describe('GridOdataService', () => { let service: GridOdataService; diff --git a/packages/odata/src/services/grid-odata.service.ts b/packages/odata/src/services/grid-odata.service.ts index 7daf03416..f961bd9d4 100644 --- a/packages/odata/src/services/grid-odata.service.ts +++ b/packages/odata/src/services/grid-odata.service.ts @@ -18,7 +18,7 @@ import type { SearchTerm, SharedService, SingleColumnSort, - SlickGrid, + SlickGridUniversal, } from '@slickgrid-universal/common'; import { CaseType, @@ -40,7 +40,7 @@ export class GridOdataService implements BackendService { protected _currentPagination: CurrentPagination | null = null; protected _currentSorters: CurrentSorter[] = []; protected _columnDefinitions: Column[] = []; - protected _grid: SlickGrid | undefined; + protected _grid: SlickGridUniversal | undefined; protected _odataService: OdataQueryBuilderService; options?: Partial; pagination: Pagination | undefined; @@ -62,14 +62,14 @@ export class GridOdataService implements BackendService { /** Getter for the Grid Options pulled through the Grid Object */ protected get _gridOptions(): GridOption { - return (this._grid?.getOptions) ? this._grid.getOptions() : {}; + return this._grid?.getOptions() ?? {} as GridOption; } constructor() { this._odataService = new OdataQueryBuilderService(); } - init(serviceOptions?: Partial, pagination?: Pagination, grid?: SlickGrid, sharedService?: SharedService): void { + init(serviceOptions?: Partial, pagination?: Pagination, grid?: SlickGridUniversal, sharedService?: SharedService): void { this._grid = grid; const mergedOptions = { ...this.defaultOptions, ...serviceOptions }; @@ -279,7 +279,7 @@ export class GridOdataService implements BackendService { * SORTING */ processOnSortChanged(_event: Event | undefined, args: SingleColumnSort | MultiColumnSort) { - const sortColumns = (args.multiColumnSort) ? (args as MultiColumnSort).sortCols : new Array({ columnId: (args as ColumnSort).sortCol.id, sortCol: (args as ColumnSort).sortCol, sortAsc: (args as ColumnSort).sortAsc }); + const sortColumns = (args.multiColumnSort) ? (args as MultiColumnSort).sortCols : new Array({ columnId: (args as ColumnSort).sortCol?.id ?? '', sortCol: (args as ColumnSort).sortCol, sortAsc: (args as ColumnSort).sortAsc }); // loop through all columns to inspect sorters & set the query this.updateSorters(sortColumns); diff --git a/packages/pagination-component/src/__tests__/slick-pagination-without-i18n.spec.ts b/packages/pagination-component/src/__tests__/slick-pagination-without-i18n.spec.ts index ca0797914..02cbdd6a8 100644 --- a/packages/pagination-component/src/__tests__/slick-pagination-without-i18n.spec.ts +++ b/packages/pagination-component/src/__tests__/slick-pagination-without-i18n.spec.ts @@ -13,7 +13,7 @@ const gridStub = { getOptions: jest.fn(), getUID: () => 'slickgrid_123456', registerPlugin: jest.fn(), -} as unknown as SlickGrid; +} as unknown as SlickGridUniversal; const mockLocales = { TEXT_ITEMS_PER_PAGE: 'items per page', diff --git a/packages/pagination-component/src/__tests__/slick-pagination.spec.ts b/packages/pagination-component/src/__tests__/slick-pagination.spec.ts index 3ac215186..9e6f48265 100644 --- a/packages/pagination-component/src/__tests__/slick-pagination.spec.ts +++ b/packages/pagination-component/src/__tests__/slick-pagination.spec.ts @@ -13,7 +13,7 @@ const gridStub = { getOptions: jest.fn(), getUID: () => 'slickgrid_123456', registerPlugin: jest.fn(), -} as unknown as SlickGrid; +} as unknown as SlickGridUniversal; const mockGridOptions = { enableTranslate: false } as GridOption; diff --git a/packages/pagination-component/src/slick-pagination.component.ts b/packages/pagination-component/src/slick-pagination.component.ts index 01b06473e..3e6f8dc00 100644 --- a/packages/pagination-component/src/slick-pagination.component.ts +++ b/packages/pagination-component/src/slick-pagination.component.ts @@ -5,6 +5,7 @@ import type { PubSubService, ServicePagination, SharedService, + SlickGridUniversal, Subscription, TranslaterService, } from '@slickgrid-universal/common'; @@ -12,7 +13,6 @@ import { Constants, createDomElement, getTranslationPrefix, - SlickGrid, } from '@slickgrid-universal/common'; import { BindingHelper } from '@slickgrid-universal/binding'; @@ -99,7 +99,7 @@ export class SlickPaginationComponent { return this.paginationService.pageNumber; } - get grid(): SlickGrid { + get grid(): SlickGridUniversal { return this.sharedService.slickGrid; } diff --git a/packages/row-detail-view-plugin/src/slickRowDetailView.spec.ts b/packages/row-detail-view-plugin/src/slickRowDetailView.spec.ts index 2fa412a27..b13b20e5c 100644 --- a/packages/row-detail-view-plugin/src/slickRowDetailView.spec.ts +++ b/packages/row-detail-view-plugin/src/slickRowDetailView.spec.ts @@ -1,11 +1,9 @@ -import { Column, GridOption, PubSubService, SlickDataView, SlickGrid, SlickNamespace, } from '@slickgrid-universal/common'; +import { type SlickDataView, SlickEvent, SlickEventData } from 'slickgrid'; +import { Column, GridOption, PubSubService, SlickGridUniversal } from '@slickgrid-universal/common'; import { SlickRowDetailView } from './slickRowDetailView'; - -declare const Slick: SlickNamespace; const GRID_UID = 'slickgrid12345'; - const gridOptionsMock = { enableAutoTooltip: true, rowHeight: 25 } as GridOption; const dataviewStub = { @@ -18,9 +16,9 @@ const dataviewStub = { getRowById: jest.fn(), insertItem: jest.fn(), updateItem: jest.fn(), - onRowsChanged: new Slick.Event(), - onRowCountChanged: new Slick.Event(), - onSetItemsCalled: new Slick.Event(), + onRowsChanged: new SlickEvent(), + onRowCountChanged: new SlickEvent(), + onSetItemsCalled: new SlickEvent(), } as unknown as SlickDataView; const getEditorLockMock = { @@ -42,12 +40,12 @@ const gridStub = { registerPlugin: jest.fn(), render: jest.fn(), updateRowCount: jest.fn(), - onBeforeEditCell: new Slick.Event(), - onClick: new Slick.Event(), - onRendered: new Slick.Event(), - onScroll: new Slick.Event(), - onSort: new Slick.Event(), -} as unknown as SlickGrid; + onBeforeEditCell: new SlickEvent(), + onClick: new SlickEvent(), + onRendered: new SlickEvent(), + onScroll: new SlickEvent(), + onSort: new SlickEvent(), +} as unknown as SlickGridUniversal; const pubSubServiceStub = { publish: jest.fn(), @@ -134,8 +132,8 @@ describe('SlickRowDetailView plugin', () => { jest.spyOn(gridStub, 'getOptions').mockReturnValue({ ...gridOptionsMock, rowDetailView: { collapseAllOnSort: true } as any }); plugin.init(gridStub); - const eventData = { ...new Slick.EventData(), preventDefault: jest.fn() }; - gridStub.onSort.notify({ sortCols: [{ columnId: mockColumns[0].id, sortCol: mockColumns[0], sortAsc: true }], multiColumnSort: true, previousSortColumns: [], grid: gridStub }, eventData, gridStub); + const eventData = { ...new SlickEventData(), preventDefault: jest.fn() }; + gridStub.onSort.notify({ sortCols: [{ columnId: mockColumns[0].id, sortCol: mockColumns[0], sortAsc: true }], multiColumnSort: true, previousSortColumns: [], grid: gridStub }, eventData as any, gridStub); expect(plugin.getExpandedRows()).toEqual([]); expect(plugin.getOutOfViewportRows()).toEqual([]); @@ -147,7 +145,7 @@ describe('SlickRowDetailView plugin', () => { jest.spyOn(gridStub, 'getOptions').mockReturnValue({ ...gridOptionsMock, rowDetailView: { collapseAllOnSort: true } as any }); plugin.init(gridStub); - gridStub.onBeforeEditCell.notify({ cell: undefined as any, row: undefined as any, grid: gridStub, column: {} as Column, item: {} }, new Slick.EventData(), gridStub); + gridStub.onBeforeEditCell.notify({ cell: undefined as any, row: undefined as any, grid: gridStub, column: {} as Column, item: {} }, new SlickEventData(), gridStub); expect(plugin.getExpandedRows()).toEqual([]); expect(plugin.getOutOfViewportRows()).toEqual([]); @@ -159,7 +157,7 @@ describe('SlickRowDetailView plugin', () => { const renderSpy = jest.spyOn(gridStub, 'render'); plugin.init(gridStub); - dataviewStub.onRowCountChanged.notify({ previous: 0, current: 1, itemCount: 2, dataView: dataviewStub, callingOnRowsChanged: true }, new Slick.EventData(), gridStub); + dataviewStub.onRowCountChanged.notify({ previous: 0, current: 1, itemCount: 2, dataView: dataviewStub, callingOnRowsChanged: true }, new SlickEventData(), gridStub); expect(plugin.eventHandler).toBeTruthy(); expect(updateRowCountSpy).toHaveBeenCalled(); @@ -171,7 +169,7 @@ describe('SlickRowDetailView plugin', () => { const renderSpy = jest.spyOn(gridStub, 'render'); plugin.init(gridStub); - dataviewStub.onRowsChanged.notify({ rows: [1, 3], itemCount: 2, calledOnRowCountChanged: true, dataView: dataviewStub }, new Slick.EventData(), gridStub); + dataviewStub.onRowsChanged.notify({ rows: [1, 3], itemCount: 2, calledOnRowCountChanged: true, dataView: dataviewStub }, new SlickEventData(), gridStub); expect(plugin.eventHandler).toBeTruthy(); expect(invalidateRowsSpy).toHaveBeenCalledWith([1, 3]); @@ -182,7 +180,7 @@ describe('SlickRowDetailView plugin', () => { jest.spyOn(dataviewStub, 'getIdPropertyName').mockReturnValue('rowId'); plugin.init(gridStub); - dataviewStub.onSetItemsCalled.notify({ idProperty: 'rowId' } as any, new Slick.EventData(), gridStub); + dataviewStub.onSetItemsCalled.notify({ idProperty: 'rowId' } as any, new SlickEventData(), gridStub); expect(plugin.dataViewIdProperty).toBe('rowId'); }); @@ -191,7 +189,7 @@ describe('SlickRowDetailView plugin', () => { jest.spyOn(gridStub, 'getOptions').mockReturnValue({ ...gridOptionsMock, rowDetailView: { useSimpleViewportCalc: true } as any }); plugin.init(gridStub); - gridStub.onRendered.notify({ endRow: 2, startRow: 0, grid: gridStub }, new Slick.EventData(), gridStub); + gridStub.onRendered.notify({ endRow: 2, startRow: 0, grid: gridStub }, new SlickEventData(), gridStub); expect(plugin.visibleRenderedCellCount).toEqual(2); // end-start => 2-0=2 }); @@ -249,7 +247,7 @@ describe('SlickRowDetailView plugin', () => { jest.spyOn(gridStub, 'getOptions').mockReturnValue({ ...gridOptionsMock, rowDetailView: { postTemplate: postViewMock } as any }); plugin.init(gridStub); - plugin.onAsyncResponse.notify({}, new Slick.EventData()); + plugin.onAsyncResponse.notify({} as any, new SlickEventData()); expect(consoleSpy).toHaveBeenCalledWith('SlickRowDetailView plugin requires the onAsyncResponse() to supply "args.item" property.'); expect(updateItemSpy).not.toHaveBeenCalled(); @@ -263,7 +261,7 @@ describe('SlickRowDetailView plugin', () => { jest.spyOn(gridStub, 'getOptions').mockReturnValue({ ...gridOptionsMock, rowDetailView: { postTemplate: postViewMock } as any }); plugin.init(gridStub); - plugin.onAsyncResponse.notify({ item: itemMock, itemDetail: itemMock, }, new Slick.EventData()); + plugin.onAsyncResponse.notify({ item: itemMock, itemDetail: itemMock, }, new SlickEventData()); expect(updateItemSpy).toHaveBeenCalledWith(123, { _detailContent: 'Post 123', _detailViewLoaded: true, id: 123, firstName: 'John', lastName: 'Doe' }); expect(asyncEndUpdateSpy).toHaveBeenCalledWith({ grid: gridStub, item: itemMock, itemDetail: { _detailContent: 'Post 123', _detailViewLoaded: true, id: 123, firstName: 'John', lastName: 'Doe' } }); @@ -276,7 +274,7 @@ describe('SlickRowDetailView plugin', () => { const detailView = `loading...`; plugin.init(gridStub); - plugin.onAsyncResponse.notify({ item: itemMock, itemDetail: itemMock, detailView, }, new Slick.EventData()); + plugin.onAsyncResponse.notify({ item: itemMock, itemDetail: itemMock, detailView, }, new SlickEventData()); expect(updateItemSpy).toHaveBeenCalledWith(123, { _detailContent: `loading...`, _detailViewLoaded: true, id: 123, firstName: 'John', lastName: 'Doe' }); expect(asyncEndUpdateSpy).toHaveBeenCalledWith({ grid: gridStub, item: itemMock, itemDetail: { _detailContent: `loading...`, _detailViewLoaded: true, id: 123, firstName: 'John', lastName: 'Doe' } }); @@ -290,7 +288,7 @@ describe('SlickRowDetailView plugin', () => { plugin.init(gridStub); plugin.expandableOverride(() => false); - plugin.onAsyncResponse.notify({ item: itemMock, itemDetail: itemMock, detailView, }, new Slick.EventData()); + plugin.onAsyncResponse.notify({ item: itemMock, itemDetail: itemMock, detailView, }, new SlickEventData()); const clickEvent = new Event('click'); Object.defineProperty(clickEvent, 'target', { writable: true, configurable: true, value: document.createElement('div') }); @@ -319,7 +317,7 @@ describe('SlickRowDetailView plugin', () => { jest.spyOn(gridStub, 'getOptions').mockReturnValue({ ...gridOptionsMock, rowDetailView: { process: mockProcess, columnIndexPosition: 0, useRowClick: true, maxRows: 2, panelRows: 2 } as any }); plugin.init(gridStub); - plugin.onAsyncResponse.notify({ item: itemMock, itemDetail: itemMock, detailView, }, new Slick.EventData()); + plugin.onAsyncResponse.notify({ item: itemMock, itemDetail: itemMock, detailView, }, new SlickEventData()); const clickEvent = new Event('click'); Object.defineProperty(clickEvent, 'target', { writable: true, configurable: true, value: document.createElement('div') }); @@ -347,7 +345,7 @@ describe('SlickRowDetailView plugin', () => { jest.spyOn(gridStub, 'getOptions').mockReturnValue({ ...gridOptionsMock, rowDetailView: { columnIndexPosition: 0, useRowClick: true } as any }); plugin.init(gridStub); - plugin.onAsyncResponse.notify({ item: itemMock, itemDetail: itemMock, detailView, }, new Slick.EventData()); + plugin.onAsyncResponse.notify({ item: itemMock, itemDetail: itemMock, detailView, }, new SlickEventData()); const filteredItem = plugin.getFilterItem(itemMock); expect(updateItemSpy).toHaveBeenCalledWith(123, { _detailContent: `loading...`, _detailViewLoaded: true, id: 123, firstName: 'John', lastName: 'Doe' }); @@ -381,7 +379,7 @@ describe('SlickRowDetailView plugin', () => { jest.spyOn(gridStub, 'getColumns').mockReturnValue(mockColumns); jest.spyOn(gridStub, 'getOptions').mockReturnValue({ ...gridOptionsMock, rowDetailView: { process: mockProcess, preTemplate: loadingTemplate, panelRows: 5, useRowClick: true, singleRowExpand: true, loadOnce: true } as any }); plugin.init(gridStub); - plugin.onAsyncResponse.notify({ item: itemMock, itemDetail: itemMock, detailView, }, new Slick.EventData()); + plugin.onAsyncResponse.notify({ item: itemMock, itemDetail: itemMock, detailView, }, new SlickEventData()); expect(updateItemSpy).toHaveBeenCalledWith(123, { _detailContent: `loading...`, _detailViewLoaded: true, id: 123, firstName: 'John', lastName: 'Doe' }); expect(asyncEndUpdateSpy).toHaveBeenCalledWith({ grid: gridStub, item: itemMock, itemDetail: { _detailContent: `loading...`, _detailViewLoaded: true, id: 123, firstName: 'John', lastName: 'Doe' } }); @@ -519,8 +517,8 @@ describe('SlickRowDetailView plugin', () => { plugin.resizeDetailView(itemMock); plugin.expandDetailView(itemMock); - const eventData = { ...new Slick.EventData(), preventDefault: jest.fn() }; - gridStub.onScroll.notify({ scrollLeft: 20, scrollTop: 33, grid: gridStub }, eventData, gridStub); + const eventData = { ...new SlickEventData(), preventDefault: jest.fn() }; + gridStub.onScroll.notify({ scrollLeft: 20, scrollTop: 33, grid: gridStub }, eventData as any, gridStub); expect(mockProcess).toHaveBeenCalledWith({ firstName: 'John', id: 123, lastName: 'Doe', @@ -545,11 +543,11 @@ describe('SlickRowDetailView plugin', () => { plugin.resizeDetailView(itemMock); plugin.expandDetailView(itemMock); - const eventData = { ...new Slick.EventData(), preventDefault: jest.fn() }; - gridStub.onScroll.notify({ scrollLeft: 20, scrollTop: 33, grid: gridStub }, eventData, gridStub); - gridStub.onScroll.notify({ scrollLeft: 22, scrollTop: 35, grid: gridStub }, eventData, gridStub); + const eventData = { ...new SlickEventData(), preventDefault: jest.fn() }; + gridStub.onScroll.notify({ scrollLeft: 20, scrollTop: 33, grid: gridStub }, eventData as any, gridStub); + gridStub.onScroll.notify({ scrollLeft: 22, scrollTop: 35, grid: gridStub }, eventData as any, gridStub); plugin.lastRange = { bottom: 18, top: 30 }; - gridStub.onScroll.notify({ scrollLeft: 22, scrollTop: 0, grid: gridStub }, eventData, gridStub); + gridStub.onScroll.notify({ scrollLeft: 22, scrollTop: 0, grid: gridStub }, eventData as any, gridStub); expect(mockProcess).toHaveBeenCalledWith({ firstName: 'John', id: 123, lastName: 'Doe', @@ -577,11 +575,11 @@ describe('SlickRowDetailView plugin', () => { plugin.rowIdsOutOfViewport = [123]; const onRowBackToViewportSpy = jest.spyOn(plugin.onRowBackToViewportRange, 'notify'); - const eventData = { ...new Slick.EventData(), preventDefault: jest.fn() }; - gridStub.onScroll.notify({ scrollLeft: 20, scrollTop: 33, grid: gridStub }, eventData, gridStub); - gridStub.onScroll.notify({ scrollLeft: 22, scrollTop: 35, grid: gridStub }, eventData, gridStub); + const eventData = { ...new SlickEventData(), preventDefault: jest.fn() }; + gridStub.onScroll.notify({ scrollLeft: 20, scrollTop: 33, grid: gridStub }, eventData as any, gridStub); + gridStub.onScroll.notify({ scrollLeft: 22, scrollTop: 35, grid: gridStub }, eventData as any, gridStub); plugin.lastRange = { bottom: 18, top: 30 }; - gridStub.onScroll.notify({ scrollLeft: 22, scrollTop: 0, grid: gridStub }, eventData, gridStub); + gridStub.onScroll.notify({ scrollLeft: 22, scrollTop: 0, grid: gridStub }, eventData as any, gridStub); setTimeout(() => { expect(mockProcess).toHaveBeenCalledWith({ @@ -614,11 +612,11 @@ describe('SlickRowDetailView plugin', () => { plugin.rowIdsOutOfViewport = [123]; const onRowBackToViewportSpy = jest.spyOn(plugin.onRowBackToViewportRange, 'notify'); - const eventData = { ...new Slick.EventData(), preventDefault: jest.fn() }; - gridStub.onScroll.notify({ scrollLeft: 20, scrollTop: 33, grid: gridStub }, eventData, gridStub); - gridStub.onScroll.notify({ scrollLeft: 22, scrollTop: 35, grid: gridStub }, eventData, gridStub); + const eventData = { ...new SlickEventData(), preventDefault: jest.fn() }; + gridStub.onScroll.notify({ scrollLeft: 20, scrollTop: 33, grid: gridStub }, eventData as any, gridStub); + gridStub.onScroll.notify({ scrollLeft: 22, scrollTop: 35, grid: gridStub }, eventData as any, gridStub); plugin.lastRange = { bottom: 18, top: 30 }; - gridStub.onScroll.notify({ scrollLeft: 22, scrollTop: 0, grid: gridStub }, eventData, gridStub); + gridStub.onScroll.notify({ scrollLeft: 22, scrollTop: 0, grid: gridStub }, eventData as any, gridStub); setTimeout(() => { expect(mockProcess).toHaveBeenCalledWith({ @@ -647,11 +645,11 @@ describe('SlickRowDetailView plugin', () => { plugin.resizeDetailView(itemMock); plugin.expandDetailView(itemMock); plugin.rowIdsOutOfViewport = [123]; - gridStub.onRendered.notify({ endRow: 15, startRow: 5, grid: gridStub }, new Slick.EventData(), gridStub); + gridStub.onRendered.notify({ endRow: 15, startRow: 5, grid: gridStub }, new SlickEventData(), gridStub); const onRowOutOfViewportRangeSpy = jest.spyOn(plugin.onRowOutOfViewportRange, 'notify'); - const eventData = { ...new Slick.EventData(), preventDefault: jest.fn() }; - gridStub.onScroll.notify({ scrollLeft: 20, scrollTop: 33, grid: gridStub }, eventData, gridStub); + const eventData = { ...new SlickEventData(), preventDefault: jest.fn() }; + gridStub.onScroll.notify({ scrollLeft: 20, scrollTop: 33, grid: gridStub }, eventData as any, gridStub); expect(mockProcess).toHaveBeenCalledWith({ firstName: 'John', id: 123, lastName: 'Doe', @@ -681,11 +679,11 @@ describe('SlickRowDetailView plugin', () => { plugin.resizeDetailView(itemMock); plugin.expandDetailView(itemMock); plugin.rowIdsOutOfViewport = [123]; - gridStub.onRendered.notify({ endRow: 77, startRow: 5, grid: gridStub }, new Slick.EventData(), gridStub); + gridStub.onRendered.notify({ endRow: 77, startRow: 5, grid: gridStub }, new SlickEventData(), gridStub); const onRowBackToViewportSpy = jest.spyOn(plugin.onRowBackToViewportRange, 'notify'); - const eventData = { ...new Slick.EventData(), preventDefault: jest.fn() }; - gridStub.onScroll.notify({ scrollLeft: 20, scrollTop: 33, grid: gridStub }, eventData, gridStub); + const eventData = { ...new SlickEventData(), preventDefault: jest.fn() }; + gridStub.onScroll.notify({ scrollLeft: 20, scrollTop: 33, grid: gridStub }, eventData as any, gridStub); expect(mockProcess).toHaveBeenCalledWith({ firstName: 'John', id: 123, lastName: 'Doe', diff --git a/packages/row-detail-view-plugin/src/slickRowDetailView.ts b/packages/row-detail-view-plugin/src/slickRowDetailView.ts index 1d23c3dd1..c9b3db619 100644 --- a/packages/row-detail-view-plugin/src/slickRowDetailView.ts +++ b/packages/row-detail-view-plugin/src/slickRowDetailView.ts @@ -1,38 +1,63 @@ +import { type SlickDataView, SlickEvent, type SlickEventData, SlickEventHandler } from 'slickgrid'; + import type { Column, DOMMouseOrTouchEvent, ExternalResource, FormatterResultObject, GridOption, + OnAfterRowDetailToggleArgs, + OnBeforeRowDetailToggleArgs, + OnRowBackToViewportRangeArgs, + OnRowDetailAsyncEndUpdateArgs, + OnRowDetailAsyncResponseArgs, + OnRowOutOfViewportRangeArgs, PubSubService, RowDetailView, RowDetailViewOption, - SlickDataView, - SlickEventData, - SlickEventHandler, - SlickGrid, - SlickNamespace, + SlickGridUniversal, SlickRowDetailView as UniversalRowDetailView, UsabilityOverrideFn, } from '@slickgrid-universal/common'; import { objectAssignAndExtend } from '@slickgrid-universal/utils'; -// using external non-typed js libraries -declare const Slick: SlickNamespace; - -/*** +/** * A plugin to add Row Detail Panel View (for example providing order detail info when clicking on the order row in the grid) * Original StackOverflow question & article making this possible (thanks to violet313) * https://stackoverflow.com/questions/10535164/can-slickgrids-row-height-be-dynamically-altered#29399927 * http://violet313.org/slickgrids/#intro */ export class SlickRowDetailView implements ExternalResource, UniversalRowDetailView { + // -- + // public API + pluginName = 'RowDetailView' as const; + + /** Fired when the async response finished */ + onAsyncEndUpdate = new SlickEvent(); + + /** This event must be used with the "notify" by the end user once the Asynchronous Server call returns the item detail */ + onAsyncResponse = new SlickEvent(); + + /** Fired after the row detail gets toggled */ + onAfterRowDetailToggle = new SlickEvent(); + + /** Fired before the row detail gets toggled */ + onBeforeRowDetailToggle = new SlickEvent(); + + /** Fired after the row detail gets toggled */ + onRowBackToViewportRange = new SlickEvent(); + + /** Fired after a row becomes out of viewport range (when user can't see the row anymore) */ + onRowOutOfViewportRange = new SlickEvent(); + + // -- + // protected props protected _addonOptions!: RowDetailView; protected _dataViewIdProperty = 'id'; protected _eventHandler: SlickEventHandler; protected _expandableOverride: UsabilityOverrideFn | null = null; protected _expandedRows: any[] = []; - protected _grid!: SlickGrid; + protected _grid!: SlickGridUniversal; protected _gridRowBuffer = 0; protected _gridUid = ''; protected _keyPrefix = ''; @@ -57,29 +82,10 @@ export class SlickRowDetailView implements ExternalResource, UniversalRowDetailV toolTip: '', width: 30, } as unknown as RowDetailView; - pluginName: 'RowDetailView' = 'RowDetailView' as const; - - /** Fired when the async response finished */ - onAsyncEndUpdate = new Slick.Event(); - - /** This event must be used with the "notify" by the end user once the Asynchronous Server call returns the item detail */ - onAsyncResponse = new Slick.Event(); - - /** Fired after the row detail gets toggled */ - onAfterRowDetailToggle = new Slick.Event(); - - /** Fired before the row detail gets toggled */ - onBeforeRowDetailToggle = new Slick.Event(); - - /** Fired after the row detail gets toggled */ - onRowBackToViewportRange = new Slick.Event(); - - /** Fired after a row becomes out of viewport range (when user can't see the row anymore) */ - onRowOutOfViewportRange = new Slick.Event(); /** Constructor of the SlickGrid 3rd party plugin, it can optionally receive options */ constructor(protected readonly pubSubService: PubSubService) { - this._eventHandler = new Slick.EventHandler(); + this._eventHandler = new SlickEventHandler(); } get addonOptions() { @@ -88,7 +94,7 @@ export class SlickRowDetailView implements ExternalResource, UniversalRowDetailV /** Getter of SlickGrid DataView object */ get dataView(): SlickDataView { - return this._grid?.getData() || {} as SlickDataView; + return this._grid?.getData(); } get dataViewIdProperty(): string { @@ -125,7 +131,7 @@ export class SlickRowDetailView implements ExternalResource, UniversalRowDetailV * @param _grid * @param _containerService */ - init(grid: SlickGrid) { + init(grid: SlickGridUniversal) { this._grid = grid; if (!grid) { throw new Error('[Slickgrid-Universal] RowDetailView Plugin requires the Grid instance to be passed as argument to the "init()" method.'); @@ -566,7 +572,7 @@ export class SlickRowDetailView implements ExternalResource, UniversalRowDetailV } } - protected checkExpandableOverride(row: number, dataContext: any, grid: SlickGrid) { + protected checkExpandableOverride(row: number, dataContext: any, grid: SlickGridUniversal) { if (typeof this._expandableOverride === 'function') { return this._expandableOverride(row, dataContext, grid); } @@ -598,7 +604,7 @@ export class SlickRowDetailView implements ExternalResource, UniversalRowDetailV } /** The Formatter of the toggling icon of the Row Detail */ - protected detailSelectionFormatter(row: number, cell: number, value: any, columnDef: Column, dataContext: any, grid: SlickGrid): FormatterResultObject | string { + protected detailSelectionFormatter(row: number, cell: number, value: any, columnDef: Column, dataContext: any, grid: SlickGridUniversal): FormatterResultObject | string { if (!this.checkExpandableOverride(row, dataContext, grid)) { return ''; } else { diff --git a/packages/text-export/src/textExport.service.spec.ts b/packages/text-export/src/textExport.service.spec.ts index 0a71264e6..67aef1450 100644 --- a/packages/text-export/src/textExport.service.spec.ts +++ b/packages/text-export/src/textExport.service.spec.ts @@ -66,7 +66,7 @@ const gridStub = { getOptions: () => mockGridOptions, getColumns: jest.fn(), getGrouping: jest.fn(), -} as unknown as SlickGrid; +} as unknown as SlickGridUniversal; describe('ExportService', () => { let container: ContainerServiceStub; diff --git a/packages/text-export/src/textExport.service.ts b/packages/text-export/src/textExport.service.ts index 1e1220622..52dec3cfe 100644 --- a/packages/text-export/src/textExport.service.ts +++ b/packages/text-export/src/textExport.service.ts @@ -1,3 +1,4 @@ +import type { SlickDataView } from 'slickgrid'; import { TextEncoder } from 'text-encoding-utf-8'; import type { Column, @@ -7,8 +8,7 @@ import type { KeyTitlePair, Locale, PubSubService, - SlickDataView, - SlickGrid, + SlickGridUniversal, TextExportOption, TextExportService as BaseTextExportService, TranslaterService, @@ -46,7 +46,7 @@ export class TextExportService implements ExternalResource, BaseTextExportServic protected _exportOptions!: TextExportOption; protected _fileFormat = FileType.csv; protected _lineCarriageReturn = '\n'; - protected _grid!: SlickGrid; + protected _grid!: SlickGridUniversal; protected _groupedColumnHeaders?: Array; protected _columnHeaders: Array = []; protected _hasGroupedItems = false; @@ -65,12 +65,12 @@ export class TextExportService implements ExternalResource, BaseTextExportServic /** Getter of SlickGrid DataView object */ get _dataView(): SlickDataView { - return (this._grid?.getData && this._grid.getData()) as SlickDataView; + return this._grid?.getData(); } /** Getter for the Grid Options pulled through the Grid Object */ protected get _gridOptions(): GridOption { - return (this._grid?.getOptions) ? this._grid.getOptions() : {}; + return this._grid?.getOptions() ?? {} as GridOption; } dispose() { @@ -82,7 +82,7 @@ export class TextExportService implements ExternalResource, BaseTextExportServic * @param grid * @param containerService */ - init(grid: SlickGrid, containerService: ContainerService): void { + init(grid: SlickGridUniversal, containerService: ContainerService): void { this._grid = grid; this._pubSubService = containerService.get('PubSubService'); diff --git a/packages/vanilla-bundle/package.json b/packages/vanilla-bundle/package.json index c725b2632..d05ad5deb 100644 --- a/packages/vanilla-bundle/package.json +++ b/packages/vanilla-bundle/package.json @@ -66,7 +66,7 @@ "@slickgrid-universal/utils": "workspace:~", "dequal": "^2.0.3", "flatpickr": "^4.6.13", - "slickgrid": "^4.1.3", + "slickgrid": "^5.0.0-alpha.2", "sortablejs": "^1.15.0", "whatwg-fetch": "^3.6.19" }, diff --git a/packages/vanilla-bundle/src/components/__tests__/slick-vanilla-grid.spec.ts b/packages/vanilla-bundle/src/components/__tests__/slick-vanilla-grid.spec.ts index 3e4b50a08..a7f018b33 100644 --- a/packages/vanilla-bundle/src/components/__tests__/slick-vanilla-grid.spec.ts +++ b/packages/vanilla-bundle/src/components/__tests__/slick-vanilla-grid.spec.ts @@ -1,7 +1,16 @@ +jest.mock('sortablejs'); + import 'jest-extended'; import { of, throwError } from 'rxjs'; import { - autoAddEditorFormatterToColumnsWithEditor, + OnRowCountChangedEventArgs, + OnRowsChangedEventArgs, + OnSetItemsCalledEventArgs, + SlickDataView, + SlickEventHandler, +} from 'slickgrid'; + +import { BackendServiceApi, BackendUtilityService, Column, @@ -26,18 +35,13 @@ import { GridStateService, GridStateType, GroupingAndColspanService, - OnRowCountChangedEventArgs, - OnRowsChangedEventArgs, - OnSetItemsCalledEventArgs, Pagination, PaginationService, ResizerService, ServicePagination, SharedService, - SlickDataView, - SlickEventHandler, SlickEditorLock, - SlickGrid, + SlickGridUniversal, SlickGroupItemMetadataProvider, SortService, TreeDataService, @@ -58,9 +62,6 @@ jest.mock('@slickgrid-universal/common', () => ({ autoAddEditorFormatterToColumnsWithEditor: jest.fn(), })); -declare const Slick: any; -const slickEventHandler = new MockSlickEventHandler() as unknown as SlickEventHandler; - const extensionServiceStub = { addRxJsResource: jest.fn(), bindDifferentExtensions: jest.fn(), @@ -104,7 +105,6 @@ const backendUtilityServiceStub = { refreshBackendDataset: jest.fn(), } as unknown as BackendUtilityService; - const collectionServiceStub = { filterCollection: jest.fn(), singleFilterCollection: jest.fn(), @@ -260,19 +260,19 @@ const mockGrid = { onRendered: jest.fn(), onScroll: jest.fn(), onDataviewCreated: new MockSlickEvent(), -} as unknown as SlickGrid; +} as unknown as SlickGridUniversal; -const mockSlickEventHandlerImplementation = jest.fn().mockImplementation(() => mockSlickEventHandler); -const mockDataViewImplementation = jest.fn().mockImplementation(() => mockDataView); -const mockGridImplementation = jest.fn().mockImplementation(() => mockGrid); const template = `
    `; +const slickEventHandler = new MockSlickEventHandler() as unknown as SlickEventHandler; -describe('Slick-Vanilla-Grid-Bundle Component instantiated via Constructor', () => { - jest.mock('slickgrid/slick.grid', () => mockGridImplementation); - Slick.Grid = mockGridImplementation; - Slick.EventHandler = slickEventHandler; - Slick.Data = { DataView: mockDataViewImplementation, }; +jest.mock('slickgrid', () => ({ + ...(jest.requireActual('slickgrid') as any), + SlickGrid: jest.fn().mockImplementation(() => mockGrid), + SlickEventHandler: jest.fn().mockImplementation(() => mockSlickEventHandler), + SlickDataView: jest.fn().mockImplementation(() => mockDataView), +})); +describe('Slick-Vanilla-Grid-Bundle Component instantiated via Constructor', () => { let component: SlickVanillaGridBundle; let divContainer: HTMLDivElement; let cellDiv: HTMLDivElement; @@ -516,7 +516,7 @@ describe('Slick-Vanilla-Grid-Bundle Component instantiated via Constructor', () describe('dataset changed', () => { beforeEach(() => { jest.clearAllMocks(); - sharedService.slickGrid = mockGrid as unknown as SlickGrid; + sharedService.slickGrid = mockGrid as unknown as SlickGridUniversal; }); it('should expect "autosizeColumns" being called when "autoFitColumnsOnFirstLoad" is set and we are on first page load', () => { @@ -600,7 +600,7 @@ describe('Slick-Vanilla-Grid-Bundle Component instantiated via Constructor', () describe('options changed', () => { beforeEach(() => { jest.clearAllMocks(); - sharedService.slickGrid = mockGrid as unknown as SlickGrid; + sharedService.slickGrid = mockGrid as unknown as SlickGridUniversal; sharedService.gridOptions = gridOptions; }); @@ -610,34 +610,36 @@ describe('Slick-Vanilla-Grid-Bundle Component instantiated via Constructor', () }); it('should merge grid options with global options when slickgrid "getOptions" does not exist yet', () => { - mockGrid.getOptions = null as any; + mockGrid.getOptions = () => null as any; const setOptionSpy = jest.spyOn(mockGrid, 'setOptions'); const sharedOptionSpy = jest.spyOn(SharedService.prototype, 'gridOptions', 'set'); const mockData = [{ firstName: 'John', lastName: 'Doe' }, { firstName: 'Jane', lastName: 'Smith' }]; + const mockGridOptions = { autoCommitEdit: false, autoResize: null as any }; - component.gridOptions = { autoCommitEdit: false, autoResize: null as any }; + component.gridOptions = mockGridOptions; component.initialization(divContainer, slickEventHandler); component.dataset = mockData; expect(component.gridOptions.autoCommitEdit).toEqual(false); // expect(component.gridOptions.autoResize.bottomPadding).toEqual(50 + DATAGRID_FOOTER_HEIGHT); // calculated by the lib - expect(setOptionSpy).toBeCalledWith(component.gridOptions, false, true); - expect(sharedOptionSpy).toBeCalledWith(component.gridOptions); + expect(setOptionSpy).toBeCalledWith(mockGridOptions, false, true); + expect(sharedOptionSpy).toBeCalledWith(mockGridOptions); }); it('should merge grid options with global options and expect bottom padding to be calculated', () => { - mockGrid.getOptions = null as any; + mockGrid.getOptions = () => null as any; const setOptionSpy = jest.spyOn(mockGrid, 'setOptions'); const sharedOptionSpy = jest.spyOn(SharedService.prototype, 'gridOptions', 'set'); const mockData = [{ firstName: 'John', lastName: 'Doe' }, { firstName: 'Jane', lastName: 'Smith' }]; + const mockGridOptions = { autoCommitEdit: false, autoResize: null as any }; - component.gridOptions = { autoCommitEdit: false, autoResize: null as any }; + component.gridOptions = mockGridOptions; component.initialization(divContainer, slickEventHandler); component.dataset = mockData; expect(component.gridOptions.autoCommitEdit).toEqual(false); - expect(setOptionSpy).toBeCalledWith(component.gridOptions, false, true); - expect(sharedOptionSpy).toBeCalledWith(component.gridOptions); + expect(setOptionSpy).toBeCalledWith(mockGridOptions, false, true); + expect(sharedOptionSpy).toBeCalledWith(mockGridOptions); }); it('should merge paginationOptions when some already exist', () => { @@ -791,7 +793,7 @@ describe('Slick-Vanilla-Grid-Bundle Component instantiated via Constructor', () describe('use grouping', () => { it('should load groupItemMetaProvider to the DataView when using "draggableGrouping" feature', () => { - const dataviewSpy = jest.spyOn(mockDataViewImplementation.prototype, 'constructor'); + const dataviewSpy = jest.spyOn(SlickDataView.prototype, 'constructor' as any); const sharedMetaSpy = jest.spyOn(SharedService.prototype, 'groupItemMetadataProvider', 'set'); jest.spyOn(extensionServiceStub, 'extensionList', 'get').mockReturnValue({ draggableGrouping: { pluginName: 'DraggableGrouping' } } as unknown as ExtensionList); @@ -808,7 +810,7 @@ describe('Slick-Vanilla-Grid-Bundle Component instantiated via Constructor', () }); it('should load groupItemMetaProvider to the DataView when using "enableGrouping" feature', () => { - const dataviewSpy = jest.spyOn(mockDataViewImplementation.prototype, 'constructor'); + const dataviewSpy = jest.spyOn(SlickDataView.prototype, 'constructor' as any); const sharedMetaSpy = jest.spyOn(SharedService.prototype, 'groupItemMetadataProvider', 'set'); component.gridOptions = { enableGrouping: true }; @@ -826,7 +828,7 @@ describe('Slick-Vanilla-Grid-Bundle Component instantiated via Constructor', () afterEach(() => { component.dispose(); jest.clearAllMocks(); - sharedService.slickGrid = mockGrid as unknown as SlickGrid; + sharedService.slickGrid = mockGrid as unknown as SlickGridUniversal; }); it('should call the onDataviewCreated emitter', () => { @@ -937,7 +939,7 @@ describe('Slick-Vanilla-Grid-Bundle Component instantiated via Constructor', () afterEach(() => { jest.clearAllMocks(); component.dispose(); - sharedService.slickGrid = mockGrid as unknown as SlickGrid; + sharedService.slickGrid = mockGrid as unknown as SlickGridUniversal; }); it('should initialize groupingAndColspanService when "createPreHeaderPanel" grid option is enabled and "enableDraggableGrouping" is disabled', () => { @@ -1894,7 +1896,7 @@ describe('Slick-Vanilla-Grid-Bundle Component instantiated via Constructor', () describe('loadRowSelectionPresetWhenExists method', () => { beforeEach(() => { jest.clearAllMocks(); - sharedService.slickGrid = mockGrid as unknown as SlickGrid; + sharedService.slickGrid = mockGrid as unknown as SlickGridUniversal; }); it('should call the "mapIdsToRows" from the DataView then "setSelectedRows" from the Grid when there are row selection presets with "dataContextIds" array set', (done) => { @@ -1966,7 +1968,7 @@ describe('Slick-Vanilla-Grid-Bundle Component instantiated via Constructor', () describe('onPaginationVisibilityChanged event', () => { beforeEach(() => { jest.clearAllMocks(); - sharedService.slickGrid = mockGrid as unknown as SlickGrid; + sharedService.slickGrid = mockGrid as unknown as SlickGridUniversal; }); it('should change "showPagination" flag when "onPaginationVisibilityChanged" from the Pagination Service is triggered', () => { @@ -2131,10 +2133,6 @@ describe('Slick-Vanilla-Grid-Bundle Component instantiated via Constructor', () }); describe('Slick-Vanilla-Grid-Bundle Component instantiated via Constructor with a Hierarchical Dataset', () => { - jest.mock('slickgrid/slick.grid', () => mockGridImplementation); - Slick.Grid = mockGridImplementation; - Slick.Data = { DataView: mockDataViewImplementation, }; - let component: SlickVanillaGridBundle; let divContainer: HTMLDivElement; let cellDiv: HTMLDivElement; @@ -2206,18 +2204,13 @@ describe('Slick-Vanilla-Grid-Bundle Component instantiated via Constructor with const mockHierarchical = [{ file: 'documents', files: [{ file: 'vacation.txt' }] }]; component.gridOptions = { enableTreeData: true, treeDataOptions: { columnId: 'file' } } as unknown as GridOption; - component.initialization(divContainer, slickEventHandler); + component.initialization(divContainer, slickEventHandler as any); expect(hierarchicalSpy).toHaveBeenCalledWith(mockHierarchical); }); }); describe('Slick-Vanilla-Grid-Bundle Component instantiated via Constructor with a Slickgrid Container that already exist', () => { - jest.mock('slickgrid/slick.grid', () => mockGridImplementation); - Slick.Grid = mockGridImplementation; - Slick.EventHandler = mockSlickEventHandlerImplementation; - Slick.Data = { DataView: mockDataViewImplementation, }; - let component: SlickVanillaGridBundle; let divContainer: HTMLDivElement; let cellDiv: HTMLDivElement; diff --git a/packages/vanilla-bundle/src/components/slick-vanilla-grid-bundle.ts b/packages/vanilla-bundle/src/components/slick-vanilla-grid-bundle.ts index 8838b9574..68077ecc3 100644 --- a/packages/vanilla-bundle/src/components/slick-vanilla-grid-bundle.ts +++ b/packages/vanilla-bundle/src/components/slick-vanilla-grid-bundle.ts @@ -1,9 +1,6 @@ import { dequal } from 'dequal/lite'; import 'flatpickr/dist/l10n/fr'; -import 'slickgrid/slick.core'; -import 'slickgrid/slick.interactions'; -import 'slickgrid/slick.grid'; -import 'slickgrid/slick.dataview'; +import { type DataViewOption as DataViewOptionCore, SlickDataView, SlickEventHandler, SlickGrid, Utils as SlickUtils } from 'slickgrid'; import SortableInstance, * as Sortable_ from 'sortablejs'; const Sortable = ((Sortable_ as any)?.['default'] ?? Sortable_); // patch for rollup @@ -20,10 +17,7 @@ import type { Pagination, SelectEditor, ServicePagination, - SlickDataView, - SlickEventHandler, - SlickGrid, - SlickNamespace, + SlickGridUniversal, Subscription, RxJsFacade, } from '@slickgrid-universal/common'; @@ -68,16 +62,13 @@ import { SlickPaginationComponent } from '@slickgrid-universal/pagination-compon import { SlickerGridInstance } from '../interfaces/slickerGridInstance.interface'; import { UniversalContainerService } from '../services/universalContainer.service'; -// using external non-typed js libraries -declare const Slick: SlickNamespace; - // add Sortable to the window object so that SlickGrid lib can use globally (window as any).Sortable = Sortable as SortableInstance; -export class SlickVanillaGridBundle { +export class SlickVanillaGridBundle { protected _currentDatasetLength = 0; protected _eventPubSubService!: EventPubSubService; - protected _columnDefinitions?: Column[]; + protected _columnDefinitions?: Column[]; protected _gridOptions?: GridOption; protected _gridContainerElm!: HTMLElement; protected _gridParentContainerElm!: HTMLElement; @@ -94,8 +85,8 @@ export class SlickVanillaGridBundle { protected _slickgridInitialized = false; protected _slickerGridInstances: SlickerGridInstance | undefined; backendServiceApi: BackendServiceApi | undefined; - dataView?: SlickDataView; - slickGrid?: SlickGrid; + dataView?: SlickDataView; + slickGrid?: SlickGridUniversal; metrics?: Metrics; customDataView = false; paginationData?: { @@ -140,10 +131,10 @@ export class SlickVanillaGridBundle { return this._eventHandler; } - get columnDefinitions(): Column[] { + get columnDefinitions(): Column[] { return this._columnDefinitions || []; } - set columnDefinitions(columnDefinitions: Column[]) { + set columnDefinitions(columnDefinitions: Column[]) { this._columnDefinitions = columnDefinitions; if (this._slickgridInitialized) { this.updateColumnDefinitionsList(this._columnDefinitions); @@ -213,7 +204,7 @@ export class SlickVanillaGridBundle { } get gridOptions(): GridOption { - return this._gridOptions || {}; + return this._gridOptions || {} as GridOption; } set gridOptions(options: GridOption) { @@ -222,13 +213,13 @@ export class SlickVanillaGridBundle { // if we already have grid options, when grid was already initialized, we'll merge with those options // else we'll merge with global grid options if (this.slickGrid?.getOptions) { - mergedOptions = Slick.Utils.extend(true, {}, this.slickGrid.getOptions(), options); + mergedOptions = (SlickUtils.extend(true, {} as GridOption, this.slickGrid.getOptions() as GridOption, options)) as GridOption; } else { mergedOptions = this.mergeGridOptions(options); } if (this.sharedService?.gridOptions && this.slickGrid?.setOptions) { this.sharedService.gridOptions = mergedOptions; - this.slickGrid.setOptions(mergedOptions, false, true); // make sure to supressColumnCheck (3rd arg) to avoid problem with changeColumnsArrangement() and custom grid view + this.slickGrid.setOptions(mergedOptions as any, false, true); // make sure to supressColumnCheck (3rd arg) to avoid problem with changeColumnsArrangement() and custom grid view this.slickGrid.reRenderColumns(true); // then call a re-render since we did supressColumnCheck on previous setOptions } this._gridOptions = mergedOptions; @@ -280,8 +271,8 @@ export class SlickVanillaGridBundle { */ constructor( gridParentContainerElm: HTMLElement, - columnDefs?: Column[], - options?: GridOption, + columnDefs?: Column[], + options?: Partial, dataset?: any[], hierarchicalDataset?: any[], services?: { @@ -325,13 +316,13 @@ export class SlickVanillaGridBundle { if (this._columnDefinitions.length > 0) { this.copyColumnWidthsReference(this._columnDefinitions); } - this._gridOptions = this.mergeGridOptions(options || {}); + this._gridOptions = this.mergeGridOptions((options || {}) as GridOption); const isDeepCopyDataOnPageLoadEnabled = !!(this._gridOptions?.enableDeepCopyDatasetOnPageLoad); this.universalContainerService = services?.universalContainerService ?? new UniversalContainerService(); // if user is providing a Translate Service, it has to be passed under the "translater" grid option - this.translaterService = services?.translaterService ?? this._gridOptions.translater; + this.translaterService = services?.translaterService ?? this._gridOptions?.translater; // initialize and assign all Service Dependencies this._eventPubSubService = services?.eventPubSubService ?? new EventPubSubService(gridParentContainerElm); @@ -367,7 +358,7 @@ export class SlickVanillaGridBundle { if (hierarchicalDataset) { this.sharedService.hierarchicalDataset = (isDeepCopyDataOnPageLoadEnabled ? deepCopy(hierarchicalDataset || []) : hierarchicalDataset) || []; } - const eventHandler = new Slick.EventHandler(); + const eventHandler = new SlickEventHandler(); // register all service instances in the container this.universalContainerService.registerInstance('PubSubService', this._eventPubSubService); // external resources require this one registration (ExcelExport, TextExport) @@ -483,7 +474,7 @@ export class SlickVanillaGridBundle { this._eventPubSubService.publish('onBeforeGridCreate', true); this._eventHandler = eventHandler; - this._gridOptions = this.mergeGridOptions(this._gridOptions || {}); + this._gridOptions = this.mergeGridOptions(this._gridOptions || {} as GridOption); this.backendServiceApi = this._gridOptions?.backendServiceApi; this._isLocalGrid = !this.backendServiceApi; // considered a local grid if it doesn't have a backend service set this._eventPubSubService.eventNamingStyle = this._gridOptions?.eventNamingStyle ?? EventNamingStyle.camelCase; @@ -493,14 +484,14 @@ export class SlickVanillaGridBundle { if (!this.customDataView) { const dataviewInlineFilters = this._gridOptions?.dataView?.inlineFilters ?? false; - let dataViewOptions: DataViewOption = { inlineFilters: dataviewInlineFilters }; + let dataViewOptions: Partial = { inlineFilters: dataviewInlineFilters }; if (this.gridOptions.draggableGrouping || this.gridOptions.enableGrouping) { this.groupItemMetadataProvider = new SlickGroupItemMetadataProvider(); this.sharedService.groupItemMetadataProvider = this.groupItemMetadataProvider; dataViewOptions = { ...dataViewOptions, groupItemMetadataProvider: this.groupItemMetadataProvider }; } - this.dataView = new Slick.Data.DataView(dataViewOptions); + this.dataView = new SlickDataView(dataViewOptions as Partial); this._eventPubSubService.publish('onDataviewCreated', this.dataView); } @@ -515,7 +506,7 @@ export class SlickVanillaGridBundle { this._columnDefinitions = this.swapInternalEditorToSlickGridFactoryEditor(this._columnDefinitions || []); // if the user wants to automatically add a Custom Editor Formatter, we need to call the auto add function again - if (this._gridOptions.autoAddCustomEditorFormatter) { + if (this._gridOptions?.autoAddCustomEditorFormatter) { autoAddEditorFormatterToColumnsWithEditor(this._columnDefinitions, this._gridOptions.autoAddCustomEditorFormatter); } @@ -541,9 +532,9 @@ export class SlickVanillaGridBundle { this.gridOptions = { ...this.gridOptions, ...this.gridOptions.presets.pinning }; } - this.slickGrid = new Slick.Grid(gridContainerElm, this.dataView as SlickDataView, this._columnDefinitions, this._gridOptions); + this.slickGrid = new SlickGrid, GridOption>>(gridContainerElm, this.dataView as SlickDataView, this._columnDefinitions, this._gridOptions); this.sharedService.dataView = this.dataView as SlickDataView; - this.sharedService.slickGrid = this.slickGrid; + this.sharedService.slickGrid = this.slickGrid as SlickGridUniversal; this.sharedService.gridContainerElement = this._gridContainerElm; this.extensionService.bindDifferentExtensions(); @@ -580,7 +571,7 @@ export class SlickVanillaGridBundle { // if you don't want the items that are not visible (due to being filtered out or being on a different page) // to stay selected, pass 'false' to the second arg - const selectionModel = this.slickGrid?.getSelectionModel?.(); + const selectionModel = this.slickGrid?.getSelectionModel(); if (selectionModel && this._gridOptions?.dataView && this._gridOptions.dataView.hasOwnProperty('syncGridSelection')) { // if we are using a Backend Service, we will do an extra flag check, the reason is because it might have some unintended behaviors // with the BackendServiceApi because technically the data in the page changes the DataView on every page change. @@ -675,7 +666,7 @@ export class SlickVanillaGridBundle { } mergeGridOptions(gridOptions: GridOption) { - const options = Slick.Utils.extend(true, {}, GlobalGridOptions, gridOptions); + const options = SlickUtils.extend(true, {}, GlobalGridOptions, gridOptions); // also make sure to show the header row if user have enabled filtering if (options.enableFiltering && !options.showHeaderRow) { @@ -706,7 +697,7 @@ export class SlickVanillaGridBundle { * For now, this is GraphQL Service ONLY feature and it will basically * refresh the Dataset & Pagination without having the user to create his own PostProcess every time */ - createBackendApiInternalPostProcessCallback(gridOptions: GridOption) { + createBackendApiInternalPostProcessCallback(gridOptions?: GridOption) { const backendApi = gridOptions?.backendServiceApi; if (backendApi?.service) { const backendApiService = backendApi.service; @@ -725,7 +716,7 @@ export class SlickVanillaGridBundle { } } - bindDifferentHooks(grid: SlickGrid, gridOptions: GridOption, dataView: SlickDataView) { + bindDifferentHooks(grid: SlickGridUniversal, gridOptions: GridOption, dataView: SlickDataView) { // if user is providing a Translate Service, we need to add our PubSub Service (but only after creating all dependencies) // so that we can later subscribe to the "onLanguageChange" event and translate any texts whenever that get triggered if (gridOptions.enableTranslate && this.translaterService?.addPubSubMessaging) { @@ -921,7 +912,7 @@ export class SlickVanillaGridBundle { } } - bindResizeHook(grid: SlickGrid, options: GridOption) { + bindResizeHook(grid: SlickGridUniversal, options: GridOption) { if ((options.autoFitColumnsOnFirstLoad && options.autosizeColumnsByCellContentOnFirstLoad) || (options.enableAutoSizeColumns && options.enableAutoResizeColumnsByCellContent)) { throw new Error(`[Slickgrid-Universal] You cannot enable both autosize/fit viewport & resize by content, you must choose which resize technique to use. You can enable these 2 options ("autoFitColumnsOnFirstLoad" and "enableAutoSizeColumns") OR these other 2 options ("autosizeColumnsByCellContentOnFirstLoad" and "enableAutoResizeColumnsByCellContent").`); } @@ -1052,7 +1043,7 @@ export class SlickVanillaGridBundle { * We will re-render the grid so that the new header and data shows up correctly. * If using translater, we also need to trigger a re-translate of the column headers */ - updateColumnDefinitionsList(newColumnDefinitions: Column[]) { + updateColumnDefinitionsList(newColumnDefinitions: Column[]) { if (this.slickGrid && this._gridOptions && Array.isArray(newColumnDefinitions)) { // map/swap the internal library Editor to the SlickGrid Editor factory newColumnDefinitions = this.swapInternalEditorToSlickGridFactoryEditor(newColumnDefinitions); @@ -1108,7 +1099,7 @@ export class SlickVanillaGridBundle { * Loop through all column definitions and copy the original optional `width` properties optionally provided by the user. * We will use this when doing a resize by cell content, if user provided a `width` it won't override it. */ - protected copyColumnWidthsReference(columnDefinitions: Column[]) { + protected copyColumnWidthsReference(columnDefinitions: Column[]) { columnDefinitions.forEach(col => col.originalWidth = col.width); } @@ -1182,7 +1173,7 @@ export class SlickVanillaGridBundle { } /** Load the Editor Collection asynchronously and replace the "collection" property when Promise resolves */ - protected loadEditorCollectionAsync(column: Column) { + protected loadEditorCollectionAsync(column: Column) { const collectionAsync = (column?.editor as ColumnEditor).collectionAsync; (column?.editor as ColumnEditor).disabled = true; // disable the Editor DOM element, we'll re-enable it after receiving the collection with "updateEditorCollection()" @@ -1214,7 +1205,7 @@ export class SlickVanillaGridBundle { } } - protected insertDynamicPresetColumns(columnId: string, gridPresetColumns: Column[]) { + protected insertDynamicPresetColumns(columnId: string, gridPresetColumns: Column[]) { if (this._columnDefinitions) { const columnPosition = this._columnDefinitions.findIndex(c => c.id === columnId); if (columnPosition >= 0) { @@ -1232,7 +1223,7 @@ export class SlickVanillaGridBundle { protected loadColumnPresetsWhenDatasetInitialized() { // if user entered some Columns "presets", we need to reflect them all in the grid if (this.slickGrid && this.gridOptions.presets && Array.isArray(this.gridOptions.presets.columns) && this.gridOptions.presets.columns.length > 0) { - const gridPresetColumns: Column[] = this.gridStateService.getAssociatedGridColumns(this.slickGrid, this.gridOptions.presets.columns); + const gridPresetColumns: Column[] = this.gridStateService.getAssociatedGridColumns(this.slickGrid, this.gridOptions.presets.columns); if (gridPresetColumns && Array.isArray(gridPresetColumns) && gridPresetColumns.length > 0 && Array.isArray(this._columnDefinitions)) { // make sure that the dynamic columns are included in presets (1.Row Move, 2. Row Selection, 3. Row Detail) if (this.gridOptions.enableRowMoveManager) { @@ -1295,7 +1286,7 @@ export class SlickVanillaGridBundle { protected loadRowSelectionPresetWhenExists() { // if user entered some Row Selections "presets" const presets = this.gridOptions?.presets; - const selectionModel = this.slickGrid?.getSelectionModel?.(); + const selectionModel = this.slickGrid?.getSelectionModel(); const enableRowSelection = this.gridOptions && (this.gridOptions.enableCheckboxSelector || this.gridOptions.enableRowSelection); if (this.slickGrid && this.dataView && enableRowSelection && selectionModel && presets?.rowSelection && (Array.isArray(presets.rowSelection.gridRowIndexes) || Array.isArray(presets.rowSelection.dataContextIds))) { let dataContextIds = presets.rowSelection.dataContextIds; @@ -1390,7 +1381,7 @@ export class SlickVanillaGridBundle { * Takes a flat dataset with parent/child relationship, sort it (via its tree structure) and return the sorted flat array * @returns {Array} sort flat parent/child dataset */ - protected sortTreeDataset(flatDatasetInput: T[], forceGridRefresh = false): T[] { + protected sortTreeDataset(flatDatasetInput: U[], forceGridRefresh = false): U[] { const prevDatasetLn = this._currentDatasetLength; let sortedDatasetResult; let flatDatasetOutput: any[] = []; @@ -1427,16 +1418,16 @@ export class SlickVanillaGridBundle { * so in our lib we will swap "editor" and copy it into a new property called "internalColumnEditor" * then take back "editor.model" and make it the new "editor" so that SlickGrid Editor Factory still works */ - protected swapInternalEditorToSlickGridFactoryEditor(columnDefinitions: Column[]) { + protected swapInternalEditorToSlickGridFactoryEditor(columnDefinitions: Column[]): Column[] { const columns = Array.isArray(columnDefinitions) ? columnDefinitions : []; if (columns.some(col => `${col.id}`.includes('.'))) { console.error('[Slickgrid-Universal] Make sure that none of your Column Definition "id" property includes a dot in its name because that will cause some problems with the Editors. For example if your column definition "field" property is "user.firstName" then use "firstName" as the column "id".'); } - return columns.map((column: Column) => { + return columns.map((column) => { // on every Editor that have a "collectionAsync", resolve the data and assign it to the "collection" property - if (column.editor?.collectionAsync) { + if ((column.editor as ColumnEditor)?.collectionAsync) { this.loadEditorCollectionAsync(column); } @@ -1462,7 +1453,7 @@ export class SlickVanillaGridBundle { * Since this is called after the async call resolves, the pointer will not be the same as the "column" argument passed. * Once we found the new pointer, we will reassign the "editor" and "collection" to the "internalColumnEditor" so it has newest collection */ - protected updateEditorCollection(column: Column, newCollection: T[]) { + protected updateEditorCollection(column: Column, newCollection: U[]) { (column.editor as ColumnEditor).collection = newCollection; (column.editor as ColumnEditor).disabled = false; diff --git a/packages/vanilla-bundle/src/index.ts b/packages/vanilla-bundle/src/index.ts index 083f7c36b..a73b3d9bc 100644 --- a/packages/vanilla-bundle/src/index.ts +++ b/packages/vanilla-bundle/src/index.ts @@ -28,4 +28,4 @@ export { Aggregators, Editors, Enums, EventPubSubService, Filters, Formatters, G export { SlickEmptyWarningComponent, SlickPaginationComponent, SlickVanillaGridBundle }; // export the custom components & interfaces export { Slicker }; export * from './interfaces/index'; -export * from './services/index'; +export * from './services/index'; \ No newline at end of file diff --git a/packages/vanilla-bundle/src/interfaces/slickerGridInstance.interface.ts b/packages/vanilla-bundle/src/interfaces/slickerGridInstance.interface.ts index a0a5d3758..dfca7aac4 100644 --- a/packages/vanilla-bundle/src/interfaces/slickerGridInstance.interface.ts +++ b/packages/vanilla-bundle/src/interfaces/slickerGridInstance.interface.ts @@ -9,19 +9,19 @@ import type { GroupingAndColspanService, PaginationService, ResizerService, - SlickDataView, - SlickGrid, + SlickGridUniversal, SortService, TreeDataService, } from '@slickgrid-universal/common'; import { EventPubSubService } from '@slickgrid-universal/event-pub-sub'; +import type { SlickDataView } from 'slickgrid'; -export interface SlickerGridInstance { +export interface SlickerGridInstance { /** Slick DataView object */ - dataView: SlickDataView; + dataView: SlickDataView; /** Slick Grid object */ - slickGrid: SlickGrid; + slickGrid: SlickGridUniversal; // -- // Methods diff --git a/packages/vanilla-force-bundle/src/__tests__/vanilla-force-bundle.spec.ts b/packages/vanilla-force-bundle/src/__tests__/vanilla-force-bundle.spec.ts index be3624c61..54ead10ee 100644 --- a/packages/vanilla-force-bundle/src/__tests__/vanilla-force-bundle.spec.ts +++ b/packages/vanilla-force-bundle/src/__tests__/vanilla-force-bundle.spec.ts @@ -1,4 +1,12 @@ import 'jest-extended'; +import { + OnRowCountChangedEventArgs, + OnRowsChangedEventArgs, + OnSetItemsCalledEventArgs, + SlickDataView, + SlickEventHandler, +} from 'slickgrid'; + import { BackendUtilityService, Column, @@ -11,16 +19,11 @@ import { GridService, GridStateService, GroupingAndColspanService, - OnRowCountChangedEventArgs, - OnRowsChangedEventArgs, - OnSetItemsCalledEventArgs, PaginationService, ResizerService, SharedService, - SlickDataView, - SlickEventHandler, SlickEditorLock, - SlickGrid, + SlickGridUniversal, SortService, TreeDataService, TranslaterService, @@ -36,8 +39,8 @@ import { TranslateServiceStub } from '../../../../test/translateServiceStub'; import { MockSlickEvent, MockSlickEventHandler } from '../../../../test/mockSlickEvent'; import { RxJsResourceStub } from '../../../../test/rxjsResourceStub'; -declare const Slick: any; -const slickEventHandler = new MockSlickEventHandler() as unknown as SlickEventHandler; +const mockAutoAddCustomEditorFormatter = jest.fn(); +(formatterUtilities.autoAddEditorFormatterToColumnsWithEditor as any) = mockAutoAddCustomEditorFormatter; const extensionServiceStub = { addRxJsResource: jest.fn(), @@ -228,7 +231,7 @@ const mockGrid = { onRendered: jest.fn(), onScroll: jest.fn(), onDataviewCreated: new MockSlickEvent(), -} as unknown as SlickGrid; +} as unknown as SlickGridUniversal; const mockSlickCustomTooltip = { init: jest.fn(), @@ -246,17 +249,17 @@ jest.mock('@slickgrid-universal/text-export', () => ({ TextExportService: jest.fn().mockImplementation(() => mockTextExportService), })); -const mockSlickEventHandlerImplementation = jest.fn().mockImplementation(() => mockSlickEventHandler); -const mockDataViewImplementation = jest.fn().mockImplementation(() => mockDataView); -const mockGridImplementation = jest.fn().mockImplementation(() => mockGrid); const template = `
    `; +const slickEventHandler = new MockSlickEventHandler() as unknown as SlickEventHandler; -describe('Vanilla-Force-Grid-Bundle Component instantiated via Constructor', () => { - jest.mock('slickgrid/slick.grid', () => mockGridImplementation); - Slick.Grid = mockGridImplementation; - Slick.EventHandler = mockSlickEventHandlerImplementation; - Slick.Data = { DataView: mockDataViewImplementation, }; +jest.mock('slickgrid', () => ({ + ...(jest.requireActual('slickgrid') as any), + SlickGrid: jest.fn().mockImplementation(() => mockGrid), + SlickEventHandler: jest.fn().mockImplementation(() => mockSlickEventHandler), + SlickDataView: jest.fn().mockImplementation(() => mockDataView), +})); +describe('Vanilla-Force-Grid-Bundle Component instantiated via Constructor', () => { let component: VanillaForceGridBundle; let divContainer: HTMLDivElement; let cellDiv: HTMLDivElement; @@ -394,7 +397,7 @@ describe('Vanilla-Force-Grid-Bundle Component instantiated via Constructor', () describe('options changed', () => { beforeEach(() => { jest.clearAllMocks(); - sharedService.slickGrid = mockGrid as unknown as SlickGrid; + sharedService.slickGrid = mockGrid as unknown as SlickGridUniversal; sharedService.gridOptions = gridOptions; }); @@ -404,33 +407,35 @@ describe('Vanilla-Force-Grid-Bundle Component instantiated via Constructor', () }); it('should merge grid options with global options when slickgrid "getOptions" does not exist yet', () => { - mockGrid.getOptions = null as any; + mockGrid.getOptions = () => null as any; const setOptionSpy = jest.spyOn(mockGrid, 'setOptions'); const sharedOptionSpy = jest.spyOn(SharedService.prototype, 'gridOptions', 'set'); const mockData = [{ firstName: 'John', lastName: 'Doe' }, { firstName: 'Jane', lastName: 'Smith' }]; + const mockGridOptions = { autoCommitEdit: false, autoResize: null as any }; - component.gridOptions = { autoCommitEdit: false, autoResize: null as any }; + component.gridOptions = mockGridOptions; component.initialization(divContainer, slickEventHandler); component.dataset = mockData; expect(component.gridOptions.autoCommitEdit).toEqual(false); - expect(setOptionSpy).toBeCalledWith(component.gridOptions, false, true); - expect(sharedOptionSpy).toBeCalledWith(component.gridOptions); + expect(setOptionSpy).toBeCalledWith(mockGridOptions, false, true); + expect(sharedOptionSpy).toBeCalledWith(mockGridOptions); }); it('should merge grid options with global options and expect bottom padding to be calculated', () => { - mockGrid.getOptions = null as any; + mockGrid.getOptions = () => null as any; const setOptionSpy = jest.spyOn(mockGrid, 'setOptions'); const sharedOptionSpy = jest.spyOn(SharedService.prototype, 'gridOptions', 'set'); const mockData = [{ firstName: 'John', lastName: 'Doe' }, { firstName: 'Jane', lastName: 'Smith' }]; + const mockGridOptions = { autoCommitEdit: false, autoResize: null as any }; - component.gridOptions = { autoCommitEdit: false, autoResize: null as any }; + component.gridOptions = mockGridOptions; component.initialization(divContainer, slickEventHandler); component.dataset = mockData; expect(component.gridOptions.autoCommitEdit).toEqual(false); - expect(setOptionSpy).toBeCalledWith(component.gridOptions, false, true); - expect(sharedOptionSpy).toBeCalledWith(component.gridOptions); + expect(setOptionSpy).toBeCalledWith(mockGridOptions, false, true); + expect(sharedOptionSpy).toBeCalledWith(mockGridOptions); }); it('should merge paginationOptions when some already exist', () => { @@ -458,8 +463,8 @@ describe('Vanilla-Force-Grid-Bundle Component instantiated via Constructor', () describe('flag checks', () => { afterEach(() => { jest.clearAllMocks(); - component.dispose(); - sharedService.slickGrid = mockGrid as unknown as SlickGrid; + // component.dispose(); + sharedService.slickGrid = mockGrid as unknown as SlickGridUniversal; }); it('should initialize groupingAndColspanService when "createPreHeaderPanel" grid option is enabled and "enableDraggableGrouping" is disabled', () => { diff --git a/packages/vanilla-force-bundle/src/vanilla-force-bundle.ts b/packages/vanilla-force-bundle/src/vanilla-force-bundle.ts index d04f49003..6c897857b 100644 --- a/packages/vanilla-force-bundle/src/vanilla-force-bundle.ts +++ b/packages/vanilla-force-bundle/src/vanilla-force-bundle.ts @@ -15,7 +15,6 @@ import type { ResizerService, RxJsFacade, SharedService, - SlickNamespace, SortService, TranslaterService, TreeDataService, @@ -28,12 +27,10 @@ import { SlickEmptyWarningComponent } from '@slickgrid-universal/empty-warning-c import { SlickCustomTooltip } from '@slickgrid-universal/custom-tooltip-plugin'; import { TextExportService } from '@slickgrid-universal/text-export'; import { SlickVanillaGridBundle, UniversalContainerService } from '@slickgrid-universal/vanilla-bundle'; +import { Utils as SlickUtils } from 'slickgrid'; import { SalesforceGlobalGridOptions } from './salesforce-global-grid-options'; -// using external non-typed js libraries -declare const Slick: SlickNamespace; - export class VanillaForceGridBundle extends SlickVanillaGridBundle { slickCompositeEditor: SlickCompositeEditorComponent | undefined; @@ -78,7 +75,7 @@ export class VanillaForceGridBundle extends SlickVanillaGridBundle { mergeGridOptions(gridOptions: GridOption) { const extraOptions = (gridOptions.useSalesforceDefaultGridOptions || (this._gridOptions?.useSalesforceDefaultGridOptions)) ? SalesforceGlobalGridOptions : {}; - const options = Slick.Utils.extend(true, {}, GlobalGridOptions, extraOptions, gridOptions); + const options = SlickUtils.extend(true, {}, GlobalGridOptions, extraOptions, gridOptions); // also make sure to show the header row if user have enabled filtering if (options.enableFiltering && !options.showHeaderRow) { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f553aa087..434de80e5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -93,8 +93,8 @@ importers: specifier: ^4.0.2 version: 4.0.2 slickgrid: - specifier: ^4.1.3 - version: 4.1.3 + specifier: ^5.0.0-alpha.2 + version: 5.0.0-alpha.2 sortablejs: specifier: ^1.15.0 version: 1.15.0 @@ -232,8 +232,8 @@ importers: specifier: ^0.6.3 version: 0.6.3 slickgrid: - specifier: ^4.1.3 - version: 4.1.3 + specifier: ^5.0.0-alpha.2 + version: 5.0.0-alpha.2 sortablejs: specifier: ^1.15.0 version: 1.15.0 @@ -524,8 +524,8 @@ importers: specifier: ^4.6.13 version: 4.6.13 slickgrid: - specifier: ^4.1.3 - version: 4.1.3 + specifier: ^5.0.0-alpha.2 + version: 5.0.0-alpha.2 sortablejs: specifier: ^1.15.0 version: 1.15.0 @@ -8581,8 +8581,9 @@ packages: is-fullwidth-code-point: 3.0.0 dev: true - /slickgrid@4.1.3: - resolution: {integrity: sha512-mAJFYk4XNfGnNP3TQ/Rq/rEWRPaXOF7nqpQkgcTgOcz9RXXJ0jxgjx4L+iwLXJoZZnI9MxVZzdtp7NBHOu33gQ==} + /slickgrid@5.0.0-alpha.2: + resolution: {integrity: sha512-Xr+Ri5yql7dnFRNm3ZZlXr+S/4X3grHlviIQHzB0JlO/1CFgINzXjnyjr39bekpLbR6mBg7n/ND+ClQuCavIQw==} + engines: {node: '>=16.0.0', npm: '>=8.0.0'} dependencies: sortablejs: 1.15.0 @@ -9439,7 +9440,44 @@ packages: rollup: 4.3.1 sass: 1.69.5 optionalDependencies: - fsevents: 2.3.3 + fsevents: 2.3.2 + dev: true + + /vite@4.4.9(@types/node@20.6.2)(sass@1.67.0): + resolution: {integrity: sha512-2mbUn2LlUmNASWwSCNSJ/EG2HuSRTnVNaydp6vMCm5VIqJsjMfbIWtbH2kDuwUVW5mMUKKZvGPX/rqeqVvv1XA==} + engines: {node: ^14.18.0 || >=16.0.0} + hasBin: true + peerDependencies: + '@types/node': '>= 14' + less: '*' + lightningcss: ^1.21.0 + sass: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + dependencies: + '@types/node': 20.6.2 + esbuild: 0.18.19 + postcss: 8.4.27 + rollup: 3.27.2 + sass: 1.67.0 + optionalDependencies: + fsevents: 2.3.2 dev: true /w3c-xmlserializer@4.0.0: diff --git a/test/cypress.config.ts b/test/cypress.config.ts index 6abc6658b..55ea40f09 100644 --- a/test/cypress.config.ts +++ b/test/cypress.config.ts @@ -28,7 +28,6 @@ export default defineConfig({ experimentalRunAllSpecs: true, supportFile: 'test/cypress/support/index.ts', specPattern: 'test/cypress/e2e/**/*.cy.{js,ts}', - excludeSpecPattern: process.env.CI ? ['**/node_modules/**', '**/000-*.cy.{js,ts}'] : ['**/node_modules/**'], testIsolation: false, }, }); \ No newline at end of file diff --git a/test/cypress/support/commands.ts b/test/cypress/support/commands.ts index 975e2ae79..4c018c4a0 100644 --- a/test/cypress/support/commands.ts +++ b/test/cypress/support/commands.ts @@ -46,4 +46,4 @@ Cypress.Commands.add('getCell', (row: number, col: number, viewport = 'topLeft', const canvasSelectorY = position.y ? `.grid-canvas-${position.y}` : ''; return cy.get(`${parentSelector} ${canvasSelectorX}${canvasSelectorY} [style="top:${row * rowHeight}px"] > .slick-cell:nth(${col})`); -}); +}); \ No newline at end of file diff --git a/test/cypress/support/drag.ts b/test/cypress/support/drag.ts index 329676524..2f68222bc 100644 --- a/test/cypress/support/drag.ts +++ b/test/cypress/support/drag.ts @@ -12,15 +12,17 @@ declare global { } } } - -Cypress.Commands.add('dragStart', { prevSubject: true }, (subject, { cellWidth = 90, cellHeight = 35 } = {}) => { - return cy.wrap(subject).click({ force: true }) +// @ts-ignore +Cypress.Commands.add('dragStart', { prevSubject: true }, (subject: HTMLElement, { cellWidth = 90, cellHeight = 35 } = {}) => { + return cy.wrap(subject) + .click({ force: true }) .trigger('mousedown', { which: 1 } as any, { force: true }) .trigger('mousemove', cellWidth / 3, cellHeight / 3); }); // use a different command name than 'drag' so that it doesn't conflict with the '@4tw/cypress-drag-drop' lib -Cypress.Commands.add('dragCell', { prevSubject: true }, (subject, addRow, addCell, { cellWidth = 90, cellHeight = 35 } = {}) => { +// @ts-ignore +Cypress.Commands.add('dragCell', { prevSubject: true as any }, (subject: HTMLElement, addRow: number, addCell: number, { cellWidth = 90, cellHeight = 35 } = {}) => { return cy.wrap(subject).trigger('mousemove', cellWidth * (addCell + 0.5), cellHeight * (addRow + 0.5), { force: true }); }); diff --git a/test/jest-pretest.ts b/test/jest-pretest.ts index d06dd3707..51ba632d7 100644 --- a/test/jest-pretest.ts +++ b/test/jest-pretest.ts @@ -6,8 +6,3 @@ import 'whatwg-fetch'; (global as any).navigator = { userAgent: 'node.js' }; (global as any).Slick = (window as any).Slick = {}; (global as any).Sortable = (window as any).Sortable = Sortable; - -require('slickgrid/slick.core'); -require('slickgrid/slick.dataview'); -require('slickgrid/slick.interactions'); -require('slickgrid/slick.grid'); \ No newline at end of file diff --git a/test/mockSlickEvent.ts b/test/mockSlickEvent.ts index 83387d065..2e80f71ae 100644 --- a/test/mockSlickEvent.ts +++ b/test/mockSlickEvent.ts @@ -1,44 +1,44 @@ -import { Handler, SlickEvent, SlickEventData, SlickEventHandler } from '@slickgrid-universal/common'; +import { Handler, MergeTypes, SlickEvent, SlickEventData } from 'slickgrid'; -export class MockSlickEvent implements SlickEvent { - private _handlers = []; +export class MockSlickEvent extends SlickEvent { + protected handlers: Handler[] = []; - notify(args: T, event?: SlickEventData, scope?: any) { + notify(args: ArgType, event?: SlickEventData | Event | MergeTypes | null, scope?: any) { scope = scope || this; - let returnValue; - for (let i = 0; i < this._handlers.length; i++) { - returnValue = this._handlers[i].call(scope, event, args); + let returnValue: any; + for (let i = 0; i < this.handlers.length; i++) { + returnValue = this.handlers[i].call(scope, event, args); } return returnValue; } - subscribe(handler: (e: SlickEventData, data: Partial) => void): any { - this._handlers.push(handler); + subscribe(handler: Handler): any { + this.handlers.push(handler); } - unsubscribe(handler: (e: SlickEventData, data?: any) => void) { - this._handlers.forEach((handlerFn, index) => { + unsubscribe(handler: Handler) { + this.handlers.forEach((handlerFn, index) => { if (handlerFn === handler) { - this._handlers.splice(index, 1); + this.handlers.splice(index, 1); } }); } } -export class MockSlickEventHandler implements SlickEventHandler { - private _handlers: any[] = []; +export class MockSlickEventHandler { + protected handlers: any[] = []; notify(eventName: string, data?: any) { - const pubSub = this._handlers.find(subscription => subscription.name === eventName); + const pubSub = this.handlers.find(subscription => subscription.name === eventName); if (typeof pubSub?.handler === 'function') { pubSub.handler(data); } } subscribe(event: MockSlickEvent, handler: Handler): any { - this._handlers.push({ event, handler }); + this.handlers.push({ event, handler }); if (event.subscribe) { event.subscribe(handler); } @@ -47,11 +47,11 @@ export class MockSlickEventHandler implements SlickEventHandler { } unsubscribe(event: MockSlickEvent, handler: Handler) { - let i = this._handlers.length; + let i = this.handlers.length; while (i--) { - if (this._handlers[i].event === event && - this._handlers[i].handler === handler) { - this._handlers.splice(i, 1); + if (this.handlers[i].event === event && + this.handlers[i].handler === handler) { + this.handlers.splice(i, 1); if (event.unsubscribe) { event.unsubscribe(handler); } @@ -63,13 +63,13 @@ export class MockSlickEventHandler implements SlickEventHandler { } unsubscribeAll() { - let i = this._handlers.length; + let i = this.handlers.length; while (i--) { - if (this._handlers[i].event.unsubscribe) { - this._handlers[i].event.unsubscribe(this._handlers[i].handler); + if (this.handlers[i].event.unsubscribe) { + this.handlers[i].event.unsubscribe(this.handlers[i].handler); } } - this._handlers = []; + this.handlers = []; return this; // allow chaining } From cd90176348dd30ec3241777c32ae0b3be121c29a Mon Sep 17 00:00:00 2001 From: Ghislain B Date: Tue, 19 Sep 2023 15:23:48 -0400 Subject: [PATCH 02/21] chore(deps): upgrade to official SlickGrid 5.0 version (#1111) --- package.json | 2 +- packages/common/package.json | 2 +- packages/vanilla-bundle/package.json | 2 +- pnpm-lock.yaml | 16 ++++++++-------- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index 09b4f41d6..9d1274df4 100644 --- a/package.json +++ b/package.json @@ -85,7 +85,7 @@ "rimraf": "^5.0.5", "rxjs": "^7.8.1", "servor": "^4.0.2", - "slickgrid": "^5.0.0-alpha.2", + "slickgrid": "^5.0.0", "sortablejs": "^1.15.0", "ts-jest": "^29.1.1", "ts-node": "^10.9.1", diff --git a/packages/common/package.json b/packages/common/package.json index 7aba0bc6b..8f0eb2d61 100644 --- a/packages/common/package.json +++ b/packages/common/package.json @@ -81,7 +81,7 @@ "flatpickr": "^4.6.13", "moment-mini": "^2.29.4", "multiple-select-vanilla": "^0.4.10", - "slickgrid": "^5.0.0-alpha.2", + "slickgrid": "^5.0.0", "sortablejs": "^1.15.0", "un-flatten-tree": "^2.0.12" }, diff --git a/packages/vanilla-bundle/package.json b/packages/vanilla-bundle/package.json index d05ad5deb..8f22a0b94 100644 --- a/packages/vanilla-bundle/package.json +++ b/packages/vanilla-bundle/package.json @@ -66,7 +66,7 @@ "@slickgrid-universal/utils": "workspace:~", "dequal": "^2.0.3", "flatpickr": "^4.6.13", - "slickgrid": "^5.0.0-alpha.2", + "slickgrid": "^5.0.0", "sortablejs": "^1.15.0", "whatwg-fetch": "^3.6.19" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 434de80e5..84bc79520 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -93,8 +93,8 @@ importers: specifier: ^4.0.2 version: 4.0.2 slickgrid: - specifier: ^5.0.0-alpha.2 - version: 5.0.0-alpha.2 + specifier: ^5.0.0 + version: 5.0.0 sortablejs: specifier: ^1.15.0 version: 1.15.0 @@ -232,8 +232,8 @@ importers: specifier: ^0.6.3 version: 0.6.3 slickgrid: - specifier: ^5.0.0-alpha.2 - version: 5.0.0-alpha.2 + specifier: ^5.0.0 + version: 5.0.0 sortablejs: specifier: ^1.15.0 version: 1.15.0 @@ -524,8 +524,8 @@ importers: specifier: ^4.6.13 version: 4.6.13 slickgrid: - specifier: ^5.0.0-alpha.2 - version: 5.0.0-alpha.2 + specifier: ^5.0.0 + version: 5.0.0 sortablejs: specifier: ^1.15.0 version: 1.15.0 @@ -8581,8 +8581,8 @@ packages: is-fullwidth-code-point: 3.0.0 dev: true - /slickgrid@5.0.0-alpha.2: - resolution: {integrity: sha512-Xr+Ri5yql7dnFRNm3ZZlXr+S/4X3grHlviIQHzB0JlO/1CFgINzXjnyjr39bekpLbR6mBg7n/ND+ClQuCavIQw==} + /slickgrid@5.0.0: + resolution: {integrity: sha512-f7H7VRxZJwfbgamuIxehlCFs1yhXFthUyVKID2H6DyBZmHIbN07XKgk3YvjFGhEqGt1EIcC4IJx34xMIwqm3eQ==} engines: {node: '>=16.0.0', npm: '>=8.0.0'} dependencies: sortablejs: 1.15.0 From cb3e3f2574fae5b4107f22e938337a8c2257047d Mon Sep 17 00:00:00 2001 From: Ghislain B Date: Tue, 26 Sep 2023 23:54:52 -0400 Subject: [PATCH 03/21] chore: test with latest SlickGrid 5.0.1 (#1120) --- package.json | 2 +- packages/common/package.json | 2 +- packages/vanilla-bundle/package.json | 2 +- pnpm-lock.yaml | 16 ++++++++-------- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index 9d1274df4..e38c5ee15 100644 --- a/package.json +++ b/package.json @@ -85,7 +85,7 @@ "rimraf": "^5.0.5", "rxjs": "^7.8.1", "servor": "^4.0.2", - "slickgrid": "^5.0.0", + "slickgrid": "^5.0.1", "sortablejs": "^1.15.0", "ts-jest": "^29.1.1", "ts-node": "^10.9.1", diff --git a/packages/common/package.json b/packages/common/package.json index 8f0eb2d61..535140677 100644 --- a/packages/common/package.json +++ b/packages/common/package.json @@ -81,7 +81,7 @@ "flatpickr": "^4.6.13", "moment-mini": "^2.29.4", "multiple-select-vanilla": "^0.4.10", - "slickgrid": "^5.0.0", + "slickgrid": "^5.0.1", "sortablejs": "^1.15.0", "un-flatten-tree": "^2.0.12" }, diff --git a/packages/vanilla-bundle/package.json b/packages/vanilla-bundle/package.json index 8f22a0b94..176628f5e 100644 --- a/packages/vanilla-bundle/package.json +++ b/packages/vanilla-bundle/package.json @@ -66,7 +66,7 @@ "@slickgrid-universal/utils": "workspace:~", "dequal": "^2.0.3", "flatpickr": "^4.6.13", - "slickgrid": "^5.0.0", + "slickgrid": "^5.0.1", "sortablejs": "^1.15.0", "whatwg-fetch": "^3.6.19" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 84bc79520..d42cffdfd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -93,8 +93,8 @@ importers: specifier: ^4.0.2 version: 4.0.2 slickgrid: - specifier: ^5.0.0 - version: 5.0.0 + specifier: ^5.0.1 + version: 5.0.1 sortablejs: specifier: ^1.15.0 version: 1.15.0 @@ -232,8 +232,8 @@ importers: specifier: ^0.6.3 version: 0.6.3 slickgrid: - specifier: ^5.0.0 - version: 5.0.0 + specifier: ^5.0.1 + version: 5.0.1 sortablejs: specifier: ^1.15.0 version: 1.15.0 @@ -524,8 +524,8 @@ importers: specifier: ^4.6.13 version: 4.6.13 slickgrid: - specifier: ^5.0.0 - version: 5.0.0 + specifier: ^5.0.1 + version: 5.0.1 sortablejs: specifier: ^1.15.0 version: 1.15.0 @@ -8581,8 +8581,8 @@ packages: is-fullwidth-code-point: 3.0.0 dev: true - /slickgrid@5.0.0: - resolution: {integrity: sha512-f7H7VRxZJwfbgamuIxehlCFs1yhXFthUyVKID2H6DyBZmHIbN07XKgk3YvjFGhEqGt1EIcC4IJx34xMIwqm3eQ==} + /slickgrid@5.0.1: + resolution: {integrity: sha512-rUAOp0qDbGnXt8kbeZCOQVnkaxKwYM0Jj4+9O9T7JsvwBKAQkEGns7OjPmqGrF4xgDyEty7Y1y2KIcJczbIWgw==} engines: {node: '>=16.0.0', npm: '>=8.0.0'} dependencies: sortablejs: 1.15.0 From 77b1cc3d15ed999b7717e0b1bfad0340c877e706 Mon Sep 17 00:00:00 2001 From: ghiscoding Date: Sun, 8 Oct 2023 00:57:45 -0400 Subject: [PATCH 04/21] chore: fix SlickRange typo --- packages/common/src/extensions/slickCellSelectionModel.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/common/src/extensions/slickCellSelectionModel.ts b/packages/common/src/extensions/slickCellSelectionModel.ts index ebea0b627..928959b33 100644 --- a/packages/common/src/extensions/slickCellSelectionModel.ts +++ b/packages/common/src/extensions/slickCellSelectionModel.ts @@ -128,6 +128,11 @@ export class SlickCellSelectionModel implements SelectionModel { return result; } + /** Provide a way to force a recalculation of page row count (for example on grid resize) */ + resetPageRowCount() { + this._cachedPageRowCount = 0; + } + setSelectedRanges(ranges: SlickRange[], caller = 'SlickCellSelectionModel.setSelectedRanges') { // simple check for: empty selection didn't change, prevent firing onSelectedRangesChanged if ((!this._ranges || this._ranges.length === 0) && (!ranges || ranges.length === 0)) { From 783e8200ad9d1248be5515421d22ff6503c1e6bc Mon Sep 17 00:00:00 2001 From: Ghislain B Date: Sun, 8 Oct 2023 01:09:13 -0400 Subject: [PATCH 05/21] chore: upgrade to latest SlickGrid 5.1.0 (#1132) * chore: test with latest SlickGrid 5.1.0 --- .../src/examples/example19.ts | 8 ++++---- package.json | 2 +- packages/common/package.json | 2 +- .../src/extensions/slickCellSelectionModel.ts | 1 + packages/vanilla-bundle/package.json | 2 +- pnpm-lock.yaml | 16 ++++++++-------- test/cypress/e2e/example19.cy.ts | 18 +++++++++--------- 7 files changed, 25 insertions(+), 24 deletions(-) diff --git a/examples/vite-demo-vanilla-bundle/src/examples/example19.ts b/examples/vite-demo-vanilla-bundle/src/examples/example19.ts index bdb4d7afa..c2ced2fae 100644 --- a/examples/vite-demo-vanilla-bundle/src/examples/example19.ts +++ b/examples/vite-demo-vanilla-bundle/src/examples/example19.ts @@ -1,12 +1,12 @@ -import { CellRange, Column, GridOption, SlickEventHandler, SlickNamespace, } from '@slickgrid-universal/common'; +import { CellRange, Column, GridOption, } from '@slickgrid-universal/common'; import { Slicker, SlickVanillaGridBundle } from '@slickgrid-universal/vanilla-bundle'; +import { SlickEventHandler } from 'slickgrid'; import { ExampleGridOptions } from './example-grid-options'; import '../salesforce-styles.scss'; import './example19.scss'; const NB_ITEMS = 100; -declare const Slick: SlickNamespace; -export default class Example19 { +export default class Example34 { protected _eventHandler: SlickEventHandler; columnDefinitions: Column[] = []; @@ -17,7 +17,7 @@ export default class Example19 { sgb: SlickVanillaGridBundle; attached() { - this._eventHandler = new Slick.EventHandler(); + this._eventHandler = new SlickEventHandler(); // define the grid options & columns and then create the grid itself this.defineGrid(); diff --git a/package.json b/package.json index e38c5ee15..138f1acb9 100644 --- a/package.json +++ b/package.json @@ -85,7 +85,7 @@ "rimraf": "^5.0.5", "rxjs": "^7.8.1", "servor": "^4.0.2", - "slickgrid": "^5.0.1", + "slickgrid": "^5.1.0", "sortablejs": "^1.15.0", "ts-jest": "^29.1.1", "ts-node": "^10.9.1", diff --git a/packages/common/package.json b/packages/common/package.json index 535140677..4d2fdd6bf 100644 --- a/packages/common/package.json +++ b/packages/common/package.json @@ -81,7 +81,7 @@ "flatpickr": "^4.6.13", "moment-mini": "^2.29.4", "multiple-select-vanilla": "^0.4.10", - "slickgrid": "^5.0.1", + "slickgrid": "^5.1.0", "sortablejs": "^1.15.0", "un-flatten-tree": "^2.0.12" }, diff --git a/packages/common/src/extensions/slickCellSelectionModel.ts b/packages/common/src/extensions/slickCellSelectionModel.ts index 928959b33..87fbfa9fd 100644 --- a/packages/common/src/extensions/slickCellSelectionModel.ts +++ b/packages/common/src/extensions/slickCellSelectionModel.ts @@ -86,6 +86,7 @@ export class SlickCellSelectionModel implements SelectionModel { * @return {Number} rowCount */ getViewportRowCount() { + // @ts-ignore const viewportElm = this._grid.getViewportNode(); const viewportHeight = viewportElm?.clientHeight ?? 0; const scrollbarHeight = this._grid.getScrollbarDimensions()?.height ?? 0; diff --git a/packages/vanilla-bundle/package.json b/packages/vanilla-bundle/package.json index 176628f5e..92f33c3bb 100644 --- a/packages/vanilla-bundle/package.json +++ b/packages/vanilla-bundle/package.json @@ -66,7 +66,7 @@ "@slickgrid-universal/utils": "workspace:~", "dequal": "^2.0.3", "flatpickr": "^4.6.13", - "slickgrid": "^5.0.1", + "slickgrid": "^5.1.0", "sortablejs": "^1.15.0", "whatwg-fetch": "^3.6.19" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d42cffdfd..e6eafe748 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -93,8 +93,8 @@ importers: specifier: ^4.0.2 version: 4.0.2 slickgrid: - specifier: ^5.0.1 - version: 5.0.1 + specifier: ^5.1.0 + version: 5.1.0 sortablejs: specifier: ^1.15.0 version: 1.15.0 @@ -232,8 +232,8 @@ importers: specifier: ^0.6.3 version: 0.6.3 slickgrid: - specifier: ^5.0.1 - version: 5.0.1 + specifier: ^5.1.0 + version: 5.1.0 sortablejs: specifier: ^1.15.0 version: 1.15.0 @@ -524,8 +524,8 @@ importers: specifier: ^4.6.13 version: 4.6.13 slickgrid: - specifier: ^5.0.1 - version: 5.0.1 + specifier: ^5.1.0 + version: 5.1.0 sortablejs: specifier: ^1.15.0 version: 1.15.0 @@ -8581,8 +8581,8 @@ packages: is-fullwidth-code-point: 3.0.0 dev: true - /slickgrid@5.0.1: - resolution: {integrity: sha512-rUAOp0qDbGnXt8kbeZCOQVnkaxKwYM0Jj4+9O9T7JsvwBKAQkEGns7OjPmqGrF4xgDyEty7Y1y2KIcJczbIWgw==} + /slickgrid@5.1.0: + resolution: {integrity: sha512-jwHWFlchv+NWH9OjtdEf0+NtmaeXmxoBdorwLUodPQWJU/522VqU+pUE0e+U55GUDXeUVNpxzyxr6Y34K2Q0UQ==} engines: {node: '>=16.0.0', npm: '>=8.0.0'} dependencies: sortablejs: 1.15.0 diff --git a/test/cypress/e2e/example19.cy.ts b/test/cypress/e2e/example19.cy.ts index a575f86ab..87b1f9f8d 100644 --- a/test/cypress/e2e/example19.cy.ts +++ b/test/cypress/e2e/example19.cy.ts @@ -32,7 +32,7 @@ describe('Example 19 - ExcelCopyBuffer with Cell Selection', () => { .type('{shift}{end}'); cy.get('#selectionRange') - .should('have.text', '{"fromRow":14,"fromCell":2,"toRow":19,"toCell":2}'); + .should('have.text', '{"fromRow":14,"fromCell":2,"toCell":2,"toRow":19}'); }); it('should click on cell C19 then Shift+End w/selection C0-19', () => { @@ -44,7 +44,7 @@ describe('Example 19 - ExcelCopyBuffer with Cell Selection', () => { .type('{shift}{home}'); cy.get('#selectionRange') - .should('have.text', '{"fromRow":0,"fromCell":2,"toRow":19,"toCell":2}'); + .should('have.text', '{"fromRow":0,"fromCell":2,"toCell":2,"toRow":19}'); }); it('should click on cell E3 then Shift+PageDown multiple times with current page selection starting at E3 w/selection E3-19', () => { @@ -56,7 +56,7 @@ describe('Example 19 - ExcelCopyBuffer with Cell Selection', () => { .type('{shift}{pagedown}{pagedown}{pagedown}'); cy.get('#selectionRange') - .should('have.text', '{"fromRow":3,"fromCell":5,"toRow":19,"toCell":5}'); + .should('have.text', '{"fromRow":3,"fromCell":5,"toCell":5,"toRow":19}'); }); it('should change to 2nd page then click on cell D41 then Shift+PageUp multiple times with current page selection w/selection D25-41', () => { @@ -70,7 +70,7 @@ describe('Example 19 - ExcelCopyBuffer with Cell Selection', () => { .type('{shift}{pageup}{pageup}{pageup}'); cy.get('#selectionRange') - .should('have.text', '{"fromRow":0,"fromCell":4,"toRow":15,"toCell":4}'); + .should('have.text', '{"fromRow":0,"fromCell":4,"toCell":4,"toRow":15}'); }); }); @@ -92,7 +92,7 @@ describe('Example 19 - ExcelCopyBuffer with Cell Selection', () => { .should('have.length', 3); cy.get('#selectionRange') - .should('have.text', '{"fromRow":8,"fromCell":2,"toRow":10,"toCell":2}'); + .should('have.text', '{"fromRow":8,"fromCell":2,"toCell":2,"toRow":10}'); }); it('should click on cell D10 then PageDown 2 times w/selection D10-D50 (or D10-D52)', () => { @@ -105,7 +105,7 @@ describe('Example 19 - ExcelCopyBuffer with Cell Selection', () => { .type('{shift}{pagedown}{pagedown}'); cy.get('#selectionRange') - .should('contains', /{"fromRow":10,"fromCell":4,"toRow":5[0-2],"toCell":4}/); + .should('contains', /{"fromRow":10,"fromCell":4,"toCell":4,"toRow":5[0-2]}/); }); it('should click on cell D10 then PageDown 3 times then PageUp 1 time w/selection D10-D50 (or D10-D52)', () => { @@ -117,7 +117,7 @@ describe('Example 19 - ExcelCopyBuffer with Cell Selection', () => { .type('{shift}{pagedown}{pagedown}{pagedown}{pageup}'); cy.get('#selectionRange') - .should('contains', /{"fromRow":10,"fromCell":4,"toRow":5[0-2],"toCell":4}/); + .should('contains', /{"fromRow":10,"fromCell":4,"toCell":4,"toRow":5[0-2]}/); }); it('should click on cell E12 then End key w/selection E52-E99', () => { @@ -129,7 +129,7 @@ describe('Example 19 - ExcelCopyBuffer with Cell Selection', () => { .type('{shift}{end}'); cy.get('#selectionRange') - .should('have.text', '{"fromRow":52,"fromCell":5,"toRow":99,"toCell":5}'); + .should('have.text', '{"fromRow":52,"fromCell":5,"toCell":5,"toRow":99}'); }); it('should click on cell C85 then End key w/selection C0-C85', () => { @@ -141,7 +141,7 @@ describe('Example 19 - ExcelCopyBuffer with Cell Selection', () => { .type('{shift}{home}'); cy.get('#selectionRange') - .should('have.text', '{"fromRow":0,"fromCell":3,"toRow":85,"toCell":3}'); + .should('have.text', '{"fromRow":0,"fromCell":3,"toCell":3,"toRow":85}'); }); }); }); From 352b0d2750aace013f473655c9b5663f71ce2158 Mon Sep 17 00:00:00 2001 From: ghiscoding Date: Sat, 14 Oct 2023 22:12:53 -0400 Subject: [PATCH 06/21] feat(core)!: move SlickGrid core files directly into the project - drop `slickgrid` npm dependency and instead move all files into the project - the end goal is to have less depencies but also to get rid of unused code like the SlickGrid AutoSize since we have our own code in our ResizerService, this will hopefully make the build smaller as well. There are other duplicate code elsewhere, so moving the code in the project should help simplify the code --- examples/vite-demo-vanilla-bundle/src/app.ts | 8 +- .../src/examples/example03.ts | 2 +- .../src/examples/example04.ts | 2 +- .../src/examples/example06.ts | 2 +- .../src/examples/example11.ts | 2 +- .../src/examples/example12.ts | 3 +- .../src/examples/example14.ts | 2 +- .../src/examples/example18.ts | 8 +- .../src/examples/example19.ts | 3 +- .../src/interfaces.ts | 6 + package.json | 1 - packages/common/package.json | 1 - .../common/src/aggregators/avgAggregator.ts | 2 +- .../common/src/aggregators/cloneAggregator.ts | 2 +- .../common/src/aggregators/countAggregator.ts | 2 +- .../src/aggregators/distinctAggregator.ts | 2 +- .../common/src/aggregators/maxAggregator.ts | 2 +- .../common/src/aggregators/minAggregator.ts | 2 +- .../common/src/aggregators/sumAggregator.ts | 2 +- packages/common/src/core/index.ts | 5 + .../src/core/models/autoSize.interface.ts | 19 + packages/common/src/core/slick.core.ts | 972 +++ packages/common/src/core/slick.dataview.ts | 1538 ++++ packages/common/src/core/slick.grid.ts | 6667 +++++++++++++++++ .../common/src/core/slick.interactions.ts | 261 + .../__tests__/autocompleterEditor.spec.ts | 6 +- .../editors/__tests__/checkboxEditor.spec.ts | 6 +- .../src/editors/__tests__/dateEditor.spec.ts | 6 +- .../editors/__tests__/dualInputEditor.spec.ts | 6 +- .../src/editors/__tests__/floatEditor.spec.ts | 6 +- .../src/editors/__tests__/inputEditor.spec.ts | 6 +- .../__tests__/inputPasswordEditor.spec.ts | 6 +- .../editors/__tests__/integerEditor.spec.ts | 6 +- .../editors/__tests__/longTextEditor.spec.ts | 6 +- .../__tests__/multipleSelectEditor.spec.ts | 5 +- .../editors/__tests__/selectEditor.spec.ts | 6 +- .../__tests__/singleSelectEditor.spec.ts | 5 +- .../editors/__tests__/sliderEditor.spec.ts | 6 +- .../common/src/editors/autocompleterEditor.ts | 6 +- packages/common/src/editors/checkboxEditor.ts | 6 +- packages/common/src/editors/dateEditor.ts | 6 +- .../common/src/editors/dualInputEditor.ts | 7 +- packages/common/src/editors/inputEditor.ts | 6 +- packages/common/src/editors/longTextEditor.ts | 6 +- packages/common/src/editors/selectEditor.ts | 6 +- packages/common/src/editors/sliderEditor.ts | 6 +- .../src/enums/columnReorderFunction.type.ts | 6 +- packages/common/src/enums/index.ts | 1 + packages/common/src/enums/infer.type.ts | 6 +- .../common/src/enums/selectionModel.type.ts | 9 + .../src/enums/usabilityOverrideFn.type.ts | 4 +- .../__tests__/extensionUtility.spec.ts | 4 +- .../__tests__/slickAutoTooltip.spec.ts | 6 +- .../slickCellExcelCopyManager.spec.ts | 6 +- .../slickCellExternalCopyManager.spec.ts | 7 +- .../__tests__/slickCellMenu.plugin.spec.ts | 6 +- .../__tests__/slickCellRangeDecorator.spec.ts | 4 +- .../__tests__/slickCellRangeSelector.spec.ts | 6 +- .../__tests__/slickCellSelectionModel.spec.ts | 6 +- .../slickCheckboxSelectColumn.spec.ts | 8 +- .../__tests__/slickColumnPicker.spec.ts | 6 +- .../__tests__/slickContextMenu.spec.ts | 6 +- .../__tests__/slickDraggableGrouping.spec.ts | 8 +- .../__tests__/slickGridMenu.spec.ts | 6 +- .../slickGroupItemMetadataProvider.spec.ts | 6 +- .../__tests__/slickHeaderButtons.spec.ts | 6 +- .../__tests__/slickHeaderMenu.spec.ts | 6 +- .../__tests__/slickRowMoveManager.spec.ts | 6 +- .../__tests__/slickRowSelectionModel.spec.ts | 6 +- .../common/src/extensions/menuBaseClass.ts | 6 +- .../common/src/extensions/slickAutoTooltip.ts | 8 +- .../extensions/slickCellExcelCopyManager.ts | 8 +- .../slickCellExternalCopyManager.ts | 10 +- .../src/extensions/slickCellRangeDecorator.ts | 4 +- .../src/extensions/slickCellRangeSelector.ts | 9 +- .../src/extensions/slickCellSelectionModel.ts | 10 +- .../extensions/slickCheckboxSelectColumn.ts | 19 +- .../src/extensions/slickColumnPicker.ts | 7 +- .../src/extensions/slickDraggableGrouping.ts | 14 +- .../common/src/extensions/slickGridMenu.ts | 2 +- .../slickGroupItemMetadataProvider.ts | 11 +- .../src/extensions/slickHeaderButtons.ts | 7 +- .../common/src/extensions/slickHeaderMenu.ts | 2 +- .../src/extensions/slickRowMoveManager.ts | 16 +- .../src/extensions/slickRowSelectionModel.ts | 10 +- .../__tests__/autocompleterFilter.spec.ts | 4 +- .../__tests__/compoundDateFilter.spec.ts | 4 +- .../__tests__/compoundInputFilter.spec.ts | 4 +- .../compoundInputNumberFilter.spec.ts | 4 +- .../compoundInputPasswordFilter.spec.ts | 4 +- .../__tests__/compoundSliderFilter.spec.ts | 6 +- .../filters/__tests__/dateRangeFilter.spec.ts | 4 +- .../src/filters/__tests__/inputFilter.spec.ts | 6 +- .../filters/__tests__/inputMaskFilter.spec.ts | 6 +- .../__tests__/inputNumberFilter.spec.ts | 6 +- .../__tests__/inputPasswordFilter.spec.ts | 6 +- .../__tests__/multipleSelectFilter.spec.ts | 4 +- .../__tests__/nativeSelectFilter.spec.ts | 4 +- .../filters/__tests__/selectFilter.spec.ts | 4 +- .../__tests__/singleSelectFilter.spec.ts | 4 +- .../__tests__/singleSliderFilter.spec.ts | 6 +- .../__tests__/sliderRangeFilter.spec.ts | 6 +- .../common/src/filters/autocompleterFilter.ts | 4 +- packages/common/src/filters/dateFilter.ts | 4 +- packages/common/src/filters/inputFilter.ts | 4 +- .../common/src/filters/nativeSelectFilter.ts | 4 +- packages/common/src/filters/selectFilter.ts | 4 +- packages/common/src/filters/sliderFilter.ts | 6 +- .../__tests__/currencyFormatter.spec.ts | 4 +- .../__tests__/decimalFormatter.spec.ts | 4 +- .../dollarColoredBoldFormatter.spec.ts | 4 +- .../__tests__/dollarColoredFormatter.spec.ts | 4 +- .../__tests__/dollarFormatter.spec.ts | 4 +- .../__tests__/formatterUtilities.spec.ts | 5 +- .../__tests__/hyperlinkFormatter.spec.ts | 4 +- .../percentCompleteFormatter.spec.ts | 4 +- .../__tests__/percentFormatter.spec.ts | 4 +- .../__tests__/percentSymbolFormatter.spec.ts | 4 +- .../translateBooleanFormatter.spec.ts | 4 +- .../__tests__/translateFormatter.spec.ts | 4 +- .../__tests__/treeExportFormatter.spec.ts | 12 +- .../__tests__/treeFormatter.spec.ts | 4 +- .../src/formatters/formatterUtilities.ts | 10 +- .../avgTotalsCurrencyFormatters.spec.ts | 42 +- .../avgTotalsDollarFormatters.spec.ts | 44 +- .../__tests__/avgTotalsFormatter.spec.ts | 55 +- .../avgTotalsPercentageFormatter.spec.ts | 54 +- .../__tests__/maxTotalsFormatter.spec.ts | 58 +- .../__tests__/minTotalsFormatter.spec.ts | 58 +- .../__tests__/sumTotalsBoldFormatter.spec.ts | 58 +- .../sumTotalsColoredFormatter.spec.ts | 58 +- .../sumTotalsCurrencyColoredFormatter.spec.ts | 58 +- .../sumTotalsCurrencyFormatter.spec.ts | 58 +- .../sumTotalsDollarBoldFormatter.spec.ts | 58 +- ...umTotalsDollarColoredBoldFormatter.spec.ts | 58 +- .../sumTotalsDollarColoredFormatter.spec.ts | 58 +- .../sumTotalsDollarFormatter.spec.ts | 58 +- .../__tests__/sumTotalsFormatter.spec.ts | 56 +- .../avgTotalsCurrencyFormatter.ts | 4 +- .../avgTotalsDollarFormatter.ts | 4 +- .../grouping-formatters/avgTotalsFormatter.ts | 4 +- .../avgTotalsPercentageFormatter.ts | 4 +- .../grouping-formatters/maxTotalsFormatter.ts | 4 +- .../grouping-formatters/minTotalsFormatter.ts | 4 +- .../sumTotalsBoldFormatter.ts | 4 +- .../sumTotalsColoredFormatter.ts | 4 +- .../sumTotalsCurrencyColoredFormatter.ts | 4 +- .../sumTotalsCurrencyFormatter.ts | 4 +- .../sumTotalsDollarBoldFormatter.ts | 4 +- .../sumTotalsDollarColoredBoldFormatter.ts | 4 +- .../sumTotalsDollarColoredFormatter.ts | 4 +- .../sumTotalsDollarFormatter.ts | 4 +- .../grouping-formatters/sumTotalsFormatter.ts | 4 +- packages/common/src/index.ts | 12 +- .../interfaces/backendService.interface.ts | 4 +- .../src/interfaces/cellArgs.interface.ts | 4 +- .../collectionOverrideArgs.interface.ts | 4 +- .../common/src/interfaces/column.interface.ts | 48 +- .../src/interfaces/columnPicker.interface.ts | 43 +- .../customTooltipOption.interface.ts | 6 +- .../interfaces/dataViewEvents.interface.ts | 9 + .../common/src/interfaces/drag.interface.ts | 4 +- .../interfaces/draggableGrouping.interface.ts | 2 +- .../interfaces/editController.interface.ts | 7 + .../common/src/interfaces/editor.interface.ts | 4 + .../interfaces/editorArguments.interface.ts | 7 +- .../excelCopyBufferOption.interface.ts | 2 +- .../interfaces/externalResource.interface.ts | 4 +- .../common/src/interfaces/filter.interface.ts | 4 +- .../interfaces/filterArguments.interface.ts | 4 +- .../interfaces/filterChangedArgs.interface.ts | 4 +- .../src/interfaces/formatter.interface.ts | 4 +- .../src/interfaces/gridEvents.interface.ts | 46 + .../src/interfaces/gridMenu.interface.ts | 4 +- ...idMenuCommandItemCallbackArgs.interface.ts | 6 +- .../src/interfaces/gridOption.interface.ts | 82 +- .../groupTotalsFormatter.interface.ts | 4 +- .../src/interfaces/headerButton.interface.ts | 2 +- .../interfaces/headerButtonItem.interface.ts | 8 +- .../headerButtonOnCommandArgs.interface.ts | 4 +- .../src/interfaces/headerMenu.interface.ts | 4 +- .../interfaces/headerMenuOption.interface.ts | 4 +- packages/common/src/interfaces/index.ts | 7 +- .../src/interfaces/interactions.interface.ts | 51 + .../interfaces/menuCallbackArgs.interface.ts | 4 +- .../menuFromCellCallbackArgs.interface.ts | 4 +- .../interfaces/multiColumnSort.interface.ts | 4 +- .../src/interfaces/onEventArgs.interface.ts | 6 +- .../src/interfaces/pagingInfo.interface.ts | 2 +- .../src/interfaces/resizer.interface.ts | 8 +- .../src/interfaces/rowDetailView.interface.ts | 14 +- .../src/interfaces/rowInfo.interface.ts | 10 + .../interfaces/rowMoveManager.interface.ts | 8 +- .../selectableOverrideCallback.interface.ts | 4 +- .../interfaces/singleColumnSort.interface.ts | 4 +- .../src/interfaces/slickEvent.interface.ts | 29 - .../interfaces/slickEventData.interface.ts | 28 - .../interfaces/slickEventHandler.interface.ts | 14 - .../interfaces/slickGridModel.interface.ts | 5 + .../slickGridUniversal.interface.ts | 5 - .../src/interfaces/slickPlugin.interface.ts | 4 +- .../interfaces/slickRemoteModel.interface.ts | 2 +- .../src/interfaces/slickResizer.interface.ts | 10 +- .../slickRowDetailView.interface.ts | 9 +- .../__tests__/bindingEvent.service.spec.ts | 16 + .../__tests__/extension.service.spec.ts | 6 +- .../services/__tests__/filter.service.spec.ts | 6 +- .../services/__tests__/grid.service.spec.ts | 6 +- .../__tests__/gridEvent.service.spec.ts | 6 +- .../__tests__/gridState.service.spec.ts | 6 +- .../groupingAndColspan.service.spec.ts | 6 +- .../__tests__/pagination.service.spec.ts | 6 +- .../__tests__/resizer.service.spec.ts | 6 +- .../services/__tests__/shared.service.spec.ts | 6 +- .../services/__tests__/sort.service.spec.ts | 6 +- .../__tests__/treeData.service.spec.ts | 6 +- .../src/services/bindingEvent.service.ts | 35 +- packages/common/src/services/domUtilities.ts | 4 +- .../src/services/excelExport.service.ts | 4 +- .../common/src/services/filter.service.ts | 23 +- packages/common/src/services/grid.service.ts | 8 +- .../common/src/services/gridEvent.service.ts | 10 +- .../common/src/services/gridState.service.ts | 16 +- .../services/groupingAndColspan.service.ts | 8 +- .../common/src/services/pagination.service.ts | 8 +- .../common/src/services/resizer.service.ts | 8 +- .../common/src/services/shared.service.ts | 10 +- packages/common/src/services/sort.service.ts | 12 +- .../common/src/services/textExport.service.ts | 4 +- .../common/src/services/treeData.service.ts | 9 +- .../src/compositeEditor.factory.spec.ts | 5 +- .../src/compositeEditor.factory.ts | 1 - .../slick-composite-editor.component.spec.ts | 7 +- .../src/slick-composite-editor.component.ts | 10 +- .../src/slick-footer.component.ts | 7 +- .../src/slick-footer.spec.ts | 5 +- .../src/__tests__/slickCustomTooltip.spec.ts | 11 +- .../src/slickCustomTooltip.ts | 9 +- .../src/slick-empty-warning.component.ts | 6 +- .../src/slick-empty-warning.spec.ts | 4 +- .../src/excelExport.service.spec.ts | 6 +- .../excel-export/src/excelExport.service.ts | 8 +- packages/excel-export/src/excelUtils.spec.ts | 6 +- packages/excel-export/src/excelUtils.ts | 10 +- .../__tests__/graphql.service.spec.ts | 4 +- .../graphql/src/services/graphql.service.ts | 6 +- .../__tests__/grid-odata.service.spec.ts | 4 +- .../odata/src/services/grid-odata.service.ts | 6 +- .../slick-pagination-without-i18n.spec.ts | 4 +- .../src/__tests__/slick-pagination.spec.ts | 4 +- .../src/slick-pagination.component.ts | 4 +- .../src/slickRowDetailView.spec.ts | 6 +- .../src/slickRowDetailView.ts | 14 +- .../src/textExport.service.spec.ts | 14 +- .../text-export/src/textExport.service.ts | 8 +- packages/vanilla-bundle/package.json | 1 - .../__tests__/slick-vanilla-grid.spec.ts | 39 +- .../components/slick-vanilla-grid-bundle.ts | 22 +- .../slickerGridInstance.interface.ts | 6 +- .../__tests__/vanilla-force-bundle.spec.ts | 28 +- .../src/vanilla-force-bundle.ts | 3 +- pnpm-lock.yaml | 19 +- test/jest-pretest.ts | 5 +- test/mockSlickEvent.ts | 9 +- 264 files changed, 10860 insertions(+), 1247 deletions(-) create mode 100644 packages/common/src/core/index.ts create mode 100644 packages/common/src/core/models/autoSize.interface.ts create mode 100644 packages/common/src/core/slick.core.ts create mode 100644 packages/common/src/core/slick.dataview.ts create mode 100644 packages/common/src/core/slick.grid.ts create mode 100644 packages/common/src/core/slick.interactions.ts create mode 100644 packages/common/src/enums/selectionModel.type.ts create mode 100644 packages/common/src/interfaces/dataViewEvents.interface.ts create mode 100644 packages/common/src/interfaces/editController.interface.ts create mode 100644 packages/common/src/interfaces/gridEvents.interface.ts create mode 100644 packages/common/src/interfaces/interactions.interface.ts create mode 100644 packages/common/src/interfaces/rowInfo.interface.ts delete mode 100644 packages/common/src/interfaces/slickEvent.interface.ts delete mode 100644 packages/common/src/interfaces/slickEventData.interface.ts delete mode 100644 packages/common/src/interfaces/slickEventHandler.interface.ts create mode 100644 packages/common/src/interfaces/slickGridModel.interface.ts delete mode 100644 packages/common/src/interfaces/slickGridUniversal.interface.ts diff --git a/examples/vite-demo-vanilla-bundle/src/app.ts b/examples/vite-demo-vanilla-bundle/src/app.ts index 0ad085ac0..fcb5be213 100644 --- a/examples/vite-demo-vanilla-bundle/src/app.ts +++ b/examples/vite-demo-vanilla-bundle/src/app.ts @@ -1,14 +1,8 @@ import { AppRouting } from './app-routing'; import { Renderer } from './renderer'; -import { RouterConfig } from './interfaces'; +import { ElementEventListener, RouterConfig } from './interfaces'; const pageLayoutGlobs = import.meta.glob('./examples/**/*.html', { as: 'raw', eager: true }); -interface ElementEventListener { - element: Element; - eventName: string; - listener: EventListenerOrEventListenerObject; -} - export class App { private _boundedEventWithListeners: ElementEventListener[] = []; documentTitle = 'Slickgrid-Universal'; diff --git a/examples/vite-demo-vanilla-bundle/src/examples/example03.ts b/examples/vite-demo-vanilla-bundle/src/examples/example03.ts index ff6b98145..8d49caa51 100644 --- a/examples/vite-demo-vanilla-bundle/src/examples/example03.ts +++ b/examples/vite-demo-vanilla-bundle/src/examples/example03.ts @@ -13,13 +13,13 @@ import { GroupingGetterFunction, GroupTotalFormatters, SlickDraggableGrouping, + SlickGlobalEditorLock, SortComparers, SortDirectionNumber, } from '@slickgrid-universal/common'; import { ExcelExportService } from '@slickgrid-universal/excel-export'; import { TextExportService } from '@slickgrid-universal/text-export'; import { Slicker, SlickVanillaGridBundle } from '@slickgrid-universal/vanilla-bundle'; -import { SlickGlobalEditorLock } from 'slickgrid'; import { ExampleGridOptions } from './example-grid-options'; import './example03.scss?inline'; diff --git a/examples/vite-demo-vanilla-bundle/src/examples/example04.ts b/examples/vite-demo-vanilla-bundle/src/examples/example04.ts index bb092fb67..f606cb5c3 100644 --- a/examples/vite-demo-vanilla-bundle/src/examples/example04.ts +++ b/examples/vite-demo-vanilla-bundle/src/examples/example04.ts @@ -46,7 +46,7 @@ interface ReportItem { effortDriven: boolean; } -const customEditableInputFormatter: Formatter = (_row: number, _cell: number, _value: any, _columnDef: Column, item: ReportItem) => { +const customEditableInputFormatter: Formatter = (_row, _cell, _value, _columnDef, item) => { return item.title; }; diff --git a/examples/vite-demo-vanilla-bundle/src/examples/example06.ts b/examples/vite-demo-vanilla-bundle/src/examples/example06.ts index 3a9c07280..ac6707043 100644 --- a/examples/vite-demo-vanilla-bundle/src/examples/example06.ts +++ b/examples/vite-demo-vanilla-bundle/src/examples/example06.ts @@ -228,7 +228,7 @@ export default class Example6 { } treeFormatter: Formatter = (_row, _cell, value, _columnDef, dataContext, grid) => { - const gridOptions = grid.getOptions() as GridOption; + const gridOptions = grid.getOptions(); const treeLevelPropName = gridOptions?.treeDataOptions?.levelPropName || '__treeLevel'; if (value === null || value === undefined || dataContext === undefined) { return ''; diff --git a/examples/vite-demo-vanilla-bundle/src/examples/example11.ts b/examples/vite-demo-vanilla-bundle/src/examples/example11.ts index e138f57f9..9791e105d 100644 --- a/examples/vite-demo-vanilla-bundle/src/examples/example11.ts +++ b/examples/vite-demo-vanilla-bundle/src/examples/example11.ts @@ -21,11 +21,11 @@ import { deepCopy, formatNumber, SliderOption, + SlickGlobalEditorLock, } from '@slickgrid-universal/common'; import { ExcelExportService } from '@slickgrid-universal/excel-export'; import { Slicker, SlickVanillaGridBundle } from '@slickgrid-universal/vanilla-bundle'; import moment from 'moment-mini'; -import { SlickGlobalEditorLock } from 'slickgrid'; import exampleModal from './example11-modal.html?raw'; import Example11Modal from './example11-modal'; diff --git a/examples/vite-demo-vanilla-bundle/src/examples/example12.ts b/examples/vite-demo-vanilla-bundle/src/examples/example12.ts index dd155abd9..ff78d3aca 100644 --- a/examples/vite-demo-vanilla-bundle/src/examples/example12.ts +++ b/examples/vite-demo-vanilla-bundle/src/examples/example12.ts @@ -18,12 +18,13 @@ import { // utilities formatNumber, + OnCompositeEditorChangeEventArgs, + SlickGlobalEditorLock, } from '@slickgrid-universal/common'; import { ExcelExportService } from '@slickgrid-universal/excel-export'; import { SlickerGridInstance } from '@slickgrid-universal/vanilla-bundle'; import { VanillaForceGridBundle, Slicker } from '@slickgrid-universal/vanilla-force-bundle'; import { CompositeEditor, SlickCompositeEditorComponent } from '@slickgrid-universal/composite-editor-component'; -import { OnCompositeEditorChangeEventArgs, SlickGlobalEditorLock } from 'slickgrid'; import { ExampleGridOptions } from './example-grid-options'; import countriesJson from './data/countries.json?raw'; import './example12.scss'; diff --git a/examples/vite-demo-vanilla-bundle/src/examples/example14.ts b/examples/vite-demo-vanilla-bundle/src/examples/example14.ts index d46765301..fdfbdcf04 100644 --- a/examples/vite-demo-vanilla-bundle/src/examples/example14.ts +++ b/examples/vite-demo-vanilla-bundle/src/examples/example14.ts @@ -19,10 +19,10 @@ import { formatNumber, Utilities, GridStateChange, + SlickGlobalEditorLock, } from '@slickgrid-universal/common'; import { ExcelExportService } from '@slickgrid-universal/excel-export'; import { Slicker, SlickVanillaGridBundle } from '@slickgrid-universal/vanilla-bundle'; -import { SlickGlobalEditorLock } from 'slickgrid'; import countriesJson from './data/countries.json?raw'; import { ExampleGridOptions } from './example-grid-options'; diff --git a/examples/vite-demo-vanilla-bundle/src/examples/example18.ts b/examples/vite-demo-vanilla-bundle/src/examples/example18.ts index ccc08c407..e0653993c 100644 --- a/examples/vite-demo-vanilla-bundle/src/examples/example18.ts +++ b/examples/vite-demo-vanilla-bundle/src/examples/example18.ts @@ -18,18 +18,18 @@ import '../material-styles.scss'; const NB_ITEMS = 200; -const currencyFormatter: Formatter = (_cell: number, _row: number, value: string) => +const currencyFormatter: Formatter = (_cell, _row, value: string) => ` ${value}`; -const priceFormatter: Formatter = (_cell: number, _row: number, value: number, _col: Column, dataContext: any) => { +const priceFormatter: Formatter = (_cell, _row, value, _col, dataContext) => { const direction = dataContext.priceChange >= 0 ? 'up' : 'down'; return ` ${value}`; }; -const transactionTypeFormatter: Formatter = (_row: number, _cell: number, value: string) => +const transactionTypeFormatter: Formatter = (_row, _cell, value: string) => ` ${value}`; -const historicSparklineFormatter: Formatter = (_row: number, _cell: number, _value: string, _col: Column, dataContext: any) => { +const historicSparklineFormatter: Formatter = (_row, _cell, _value: string, _col, dataContext) => { const svgElem = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); svgElem.setAttributeNS(null, 'width', '135'); svgElem.setAttributeNS(null, 'height', '30'); diff --git a/examples/vite-demo-vanilla-bundle/src/examples/example19.ts b/examples/vite-demo-vanilla-bundle/src/examples/example19.ts index c2ced2fae..1ba6cda18 100644 --- a/examples/vite-demo-vanilla-bundle/src/examples/example19.ts +++ b/examples/vite-demo-vanilla-bundle/src/examples/example19.ts @@ -1,6 +1,5 @@ -import { CellRange, Column, GridOption, } from '@slickgrid-universal/common'; +import { CellRange, Column, GridOption, SlickEventHandler, } from '@slickgrid-universal/common'; import { Slicker, SlickVanillaGridBundle } from '@slickgrid-universal/vanilla-bundle'; -import { SlickEventHandler } from 'slickgrid'; import { ExampleGridOptions } from './example-grid-options'; import '../salesforce-styles.scss'; import './example19.scss'; diff --git a/examples/vite-demo-vanilla-bundle/src/interfaces.ts b/examples/vite-demo-vanilla-bundle/src/interfaces.ts index f8fd90fde..eea17e5ed 100644 --- a/examples/vite-demo-vanilla-bundle/src/interfaces.ts +++ b/examples/vite-demo-vanilla-bundle/src/interfaces.ts @@ -1,3 +1,9 @@ +export interface ElementEventListener { + element: Element; + eventName: string; + listener: EventListenerOrEventListenerObject; +} + export interface Route { route: string; name?: string; diff --git a/package.json b/package.json index 138f1acb9..58819b12e 100644 --- a/package.json +++ b/package.json @@ -85,7 +85,6 @@ "rimraf": "^5.0.5", "rxjs": "^7.8.1", "servor": "^4.0.2", - "slickgrid": "^5.1.0", "sortablejs": "^1.15.0", "ts-jest": "^29.1.1", "ts-node": "^10.9.1", diff --git a/packages/common/package.json b/packages/common/package.json index 4d2fdd6bf..92652f703 100644 --- a/packages/common/package.json +++ b/packages/common/package.json @@ -81,7 +81,6 @@ "flatpickr": "^4.6.13", "moment-mini": "^2.29.4", "multiple-select-vanilla": "^0.4.10", - "slickgrid": "^5.1.0", "sortablejs": "^1.15.0", "un-flatten-tree": "^2.0.12" }, diff --git a/packages/common/src/aggregators/avgAggregator.ts b/packages/common/src/aggregators/avgAggregator.ts index 3836f3104..ff2d09479 100644 --- a/packages/common/src/aggregators/avgAggregator.ts +++ b/packages/common/src/aggregators/avgAggregator.ts @@ -1,6 +1,6 @@ import { isNumber } from '@slickgrid-universal/utils'; -import type { SlickGroupTotals } from 'slickgrid'; +import { SlickGroupTotals } from '../core/slick.core'; import type { Aggregator } from './../interfaces/aggregator.interface'; export class AvgAggregator implements Aggregator { diff --git a/packages/common/src/aggregators/cloneAggregator.ts b/packages/common/src/aggregators/cloneAggregator.ts index 7874f3ceb..ba7023634 100644 --- a/packages/common/src/aggregators/cloneAggregator.ts +++ b/packages/common/src/aggregators/cloneAggregator.ts @@ -1,4 +1,4 @@ -import type { SlickGroupTotals } from 'slickgrid'; +import { SlickGroupTotals } from '../core/slick.core'; import type { Aggregator } from './../interfaces/aggregator.interface'; export class CloneAggregator implements Aggregator { diff --git a/packages/common/src/aggregators/countAggregator.ts b/packages/common/src/aggregators/countAggregator.ts index d7e1d062a..0b8e67a07 100644 --- a/packages/common/src/aggregators/countAggregator.ts +++ b/packages/common/src/aggregators/countAggregator.ts @@ -1,7 +1,7 @@ import { isNumber } from '@slickgrid-universal/utils'; -import type { SlickGroupTotals } from 'slickgrid'; import type { Aggregator } from './../interfaces/aggregator.interface'; +import { SlickGroupTotals } from '../core/slick.core'; export class CountAggregator implements Aggregator { private _isInitialized = false; diff --git a/packages/common/src/aggregators/distinctAggregator.ts b/packages/common/src/aggregators/distinctAggregator.ts index 91dce7855..85ab8af9e 100644 --- a/packages/common/src/aggregators/distinctAggregator.ts +++ b/packages/common/src/aggregators/distinctAggregator.ts @@ -1,4 +1,4 @@ -import type { SlickGroupTotals } from 'slickgrid'; +import { SlickGroupTotals } from '../core/slick.core'; import type { Aggregator } from './../interfaces/aggregator.interface'; export class DistinctAggregator implements Aggregator { diff --git a/packages/common/src/aggregators/maxAggregator.ts b/packages/common/src/aggregators/maxAggregator.ts index 1826bfa02..b8f0a1400 100644 --- a/packages/common/src/aggregators/maxAggregator.ts +++ b/packages/common/src/aggregators/maxAggregator.ts @@ -1,7 +1,7 @@ -import type { SlickGroupTotals } from 'slickgrid'; import { isNumber } from '@slickgrid-universal/utils'; import type { Aggregator } from './../interfaces/aggregator.interface'; +import { SlickGroupTotals } from '../core/slick.core'; export class MaxAggregator implements Aggregator { private _isInitialized = false; diff --git a/packages/common/src/aggregators/minAggregator.ts b/packages/common/src/aggregators/minAggregator.ts index 09391565e..a1e1f370c 100644 --- a/packages/common/src/aggregators/minAggregator.ts +++ b/packages/common/src/aggregators/minAggregator.ts @@ -1,6 +1,6 @@ -import type { SlickGroupTotals } from 'slickgrid'; import { isNumber } from '@slickgrid-universal/utils'; +import { SlickGroupTotals } from '../core/slick.core'; import type { Aggregator } from './../interfaces/aggregator.interface'; export class MinAggregator implements Aggregator { diff --git a/packages/common/src/aggregators/sumAggregator.ts b/packages/common/src/aggregators/sumAggregator.ts index f7340fda4..3e33563b2 100644 --- a/packages/common/src/aggregators/sumAggregator.ts +++ b/packages/common/src/aggregators/sumAggregator.ts @@ -1,6 +1,6 @@ -import type { SlickGroupTotals } from 'slickgrid'; import { isNumber } from '@slickgrid-universal/utils'; +import { SlickGroupTotals } from '../core/slick.core'; import type { Aggregator } from './../interfaces/aggregator.interface'; export class SumAggregator implements Aggregator { diff --git a/packages/common/src/core/index.ts b/packages/common/src/core/index.ts new file mode 100644 index 000000000..f7744c0f5 --- /dev/null +++ b/packages/common/src/core/index.ts @@ -0,0 +1,5 @@ +export * from './models/autoSize.interface'; +export * from './slick.core'; +export * from './slick.dataview'; +export * from './slick.grid'; +export * from './slick.interactions'; diff --git a/packages/common/src/core/models/autoSize.interface.ts b/packages/common/src/core/models/autoSize.interface.ts new file mode 100644 index 000000000..abe01892b --- /dev/null +++ b/packages/common/src/core/models/autoSize.interface.ts @@ -0,0 +1,19 @@ +import { Formatter } from '../../interfaces'; + +export interface AutoSize { + allowAddlPercent?: number; + autosizeMode?: string; + colDataTypeOf?: any; + colValueArray?: any[]; + contentSizePx?: number; + formatterOverride?: Formatter; + headerWidthPx?: number; + ignoreHeaderText?: boolean; + rowSelectionModeOnInit?: boolean | undefined; + rowSelectionMode?: string; + rowSelectionCount?: number; + sizeToRemaining?: boolean | undefined; + valueFilterMode?: string; + widthEvalMode?: string; + widthPx?: number; +} \ No newline at end of file diff --git a/packages/common/src/core/slick.core.ts b/packages/common/src/core/slick.core.ts new file mode 100644 index 000000000..8e0ba2019 --- /dev/null +++ b/packages/common/src/core/slick.core.ts @@ -0,0 +1,972 @@ +/* eslint-disable @typescript-eslint/ban-types */ +/* eslint-disable guard-for-in */ +/* eslint-disable object-shorthand */ + +/** + * Contains core SlickGrid classes. + * @module Core + * @namespace Slick + */ + +import { InferDOMType, MergeTypes } from '../enums/index'; +import { CSSStyleDeclarationWritable, EditController } from '../interfaces'; + +export type Handler = (e: any, args: ArgType) => void; + +/** + * An event object for passing data to event handlers and letting them control propagation. + *

    This is pretty much identical to how W3C and jQuery implement events.

    + * @class EventData + * @constructor + */ +export class SlickEventData { + protected _isPropagationStopped = false; + protected _isImmediatePropagationStopped = false; + protected _isDefaultPrevented = false; + protected returnValues: string[] = []; + protected returnValue: any = undefined; + protected target?: EventTarget | null; + protected nativeEvent?: Event | null; + protected arguments_?: ArgType; + + constructor(protected event?: Event | null, protected args?: ArgType) { + this.nativeEvent = event; + this.arguments_ = args; + + // when we already have an event, we want to keep some of the event properties + // looping through some props is the only way to keep and sync these properties to the returned EventData + if (event) { + const eventProps = [ + 'altKey', 'ctrlKey', 'metaKey', 'shiftKey', 'key', 'keyCode', + 'clientX', 'clientY', 'offsetX', 'offsetY', 'pageX', 'pageY', + 'bubbles', 'type', 'which', 'x', 'y' + ]; + for (const key of eventProps) { + (this as any)[key] = event[key as keyof Event]; + } + } + this.target = this.nativeEvent ? this.nativeEvent.target : undefined; + } + + /** + * Stops event from propagating up the DOM tree. + * @method stopPropagation + */ + stopPropagation() { + this._isPropagationStopped = true; + this.nativeEvent?.stopPropagation(); + } + + /** + * Returns whether stopPropagation was called on this event object. + * @method isPropagationStopped + * @return {Boolean} + */ + isPropagationStopped() { + return this._isPropagationStopped; + } + + /** + * Prevents the rest of the handlers from being executed. + * @method stopImmediatePropagation + */ + stopImmediatePropagation() { + this._isImmediatePropagationStopped = true; + if (this.nativeEvent) { + this.nativeEvent.stopImmediatePropagation(); + } + }; + + /** + * Returns whether stopImmediatePropagation was called on this event object.\ + * @method isImmediatePropagationStopped + * @return {Boolean} + */ + isImmediatePropagationStopped() { + return this._isImmediatePropagationStopped; + }; + + getNativeEvent() { + return this.nativeEvent as E; + } + + preventDefault() { + if (this.nativeEvent) { + this.nativeEvent.preventDefault(); + } + this._isDefaultPrevented = true; + } + + isDefaultPrevented() { + if (this.nativeEvent) { + return this.nativeEvent.defaultPrevented; + } + return this._isDefaultPrevented; + } + + addReturnValue(value: any) { + this.returnValues.push(value); + if (this.returnValue === undefined && value !== undefined) { + this.returnValue = value; + } + } + + getReturnValue() { + return this.returnValue; + } + + getArguments() { + return this.arguments_; + } +} + +/** + * A simple publisher-subscriber implementation. + * @class Event + * @constructor + */ +export class SlickEvent { + protected handlers: Handler[] = []; + + /** + * Adds an event handler to be called when the event is fired. + *

    Event handler will receive two arguments - an EventData and the data + * object the event was fired with.

    + * @method subscribe + * @param fn {Function} Event handler. + */ + subscribe(fn: Handler) { + this.handlers.push(fn); + } + + /** + * Removes an event handler added with subscribe(fn). + * @method unsubscribe + * @param fn {Function} Event handler to be removed. + */ + unsubscribe(fn?: Handler) { + for (let i = this.handlers.length - 1; i >= 0; i--) { + if (this.handlers[i] === fn) { + this.handlers.splice(i, 1); + } + } + } + + /** + * Fires an event notifying all subscribers. + * @method notify + * @param args {Object} Additional data object to be passed to all handlers. + * @param e {EventData} + * Optional. + * An EventData object to be passed to all handlers. + * For DOM events, an existing W3C event object can be passed in. + * @param scope {Object} + * Optional. + * The scope ("this") within which the handler will be executed. + * If not specified, the scope will be set to the Event instance. + */ + notify(args: ArgType, evt?: SlickEventData | Event | MergeTypes | null, scope?: any) { + const sed: SlickEventData = evt instanceof SlickEventData + ? evt + : new SlickEventData(evt, args); + scope = scope || this; + + for (let i = 0; i < this.handlers.length && !(sed.isPropagationStopped() || sed.isImmediatePropagationStopped()); i++) { + const returnValue = this.handlers[i].call(scope, sed as SlickEvent | SlickEventData, args); + sed.addReturnValue(returnValue); + } + + return sed; + } +} + +export class SlickEventHandler { + protected handlers: Array<{ event: SlickEvent; handler: Handler; }> = []; + + subscribe(event: SlickEvent, handler: Handler) { + this.handlers.push({ event, handler }); + event.subscribe(handler); + + return this; // allow chaining + } + + unsubscribe(event: SlickEvent, handler: Handler) { + let i = this.handlers.length; + while (i--) { + if (this.handlers[i].event === event && + this.handlers[i].handler === handler) { + this.handlers.splice(i, 1); + event.unsubscribe(handler); + return; + } + } + + return this; // allow chaining + } + + unsubscribeAll() { + let i = this.handlers.length; + while (i--) { + this.handlers[i].event.unsubscribe(this.handlers[i].handler); + } + this.handlers = []; + + return this; // allow chaining + } +} + +/** + * A structure containing a range of cells. + * @class Range + * @constructor + * @param fromRow {Integer} Starting row. + * @param fromCell {Integer} Starting cell. + * @param toRow {Integer} Optional. Ending row. Defaults to fromRow. + * @param toCell {Integer} Optional. Ending cell. Defaults to fromCell. + */ +export class SlickRange { + fromRow: number; + fromCell: number; + toCell: number; + toRow: number; + + constructor(fromRow: number, fromCell: number, toRow?: number, toCell?: number) { + if (toRow === undefined && toCell === undefined) { + toRow = fromRow; + toCell = fromCell; + } + + /** + * @property fromRow + * @type {Integer} + */ + this.fromRow = Math.min(fromRow, toRow as number); + + /** + * @property fromCell + * @type {Integer} + */ + this.fromCell = Math.min(fromCell, toCell as number); + + /** + * @property toCell + * @type {Integer} + */ + this.toCell = Math.max(fromCell, toCell as number); + + /** + * @property toRow + * @type {Integer} + */ + this.toRow = Math.max(fromRow, toRow as number); + } + + + /** + * Returns whether a range represents a single row. + * @method isSingleRow + * @return {Boolean} + */ + isSingleRow() { + return this.fromRow === this.toRow; + } + + /** + * Returns whether a range represents a single cell. + * @method isSingleCell + * @return {Boolean} + */ + isSingleCell() { + return this.fromRow === this.toRow && this.fromCell === this.toCell; + } + + /** + * Returns whether a range contains a given cell. + * @method contains + * @param row {Integer} + * @param cell {Integer} + * @return {Boolean} + */ + contains(row: number, cell: number) { + return row >= this.fromRow && row <= this.toRow && + cell >= this.fromCell && cell <= this.toCell; + } + + /** + * Returns a readable representation of a range. + * @method toString + * @return {String} + */ + toString() { + if (this.isSingleCell()) { + return `(${this.fromRow}:${this.fromCell})`; + } + else { + return `(${this.fromRow}:${this.fromCell} - ${this.toRow}:${this.toCell})`; + } + }; +} + + +/** + * A base class that all special / non-data rows (like Group and GroupTotals) derive from. + * @class NonDataItem + * @constructor + */ +export class SlickNonDataItem { + __nonDataRow = true; +} + + +/** + * Information about a group of rows. + * @class Group + * @extends Slick.NonDataItem + * @constructor + */ +export class SlickGroup extends SlickNonDataItem { + __group = true; + + /** + * Grouping level, starting with 0. + * @property level + * @type {Number} + */ + level = 0; + + /** + * Number of rows in the group. + * @property count + * @type {Integer} + */ + count = 0; + + /** + * Grouping value. + * @property value + * @type {Object} + */ + value = null; + + /** + * Formatted display value of the group. + * @property title + * @type {String} + */ + title: string | null = null; + + /** + * Whether a group is collapsed. + * @property collapsed + * @type {Boolean} + */ + collapsed: boolean | number = false; + + /** + * Whether a group selection checkbox is checked. + * @property selectChecked + * @type {Boolean} + */ + selectChecked = false; + + /** + * GroupTotals, if any. + * @property totals + * @type {GroupTotals} + */ + totals: SlickGroupTotals = null as any; + + /** + * Rows that are part of the group. + * @property rows + * @type {Array} + */ + rows: number[] = []; + + /** + * Sub-groups that are part of the group. + * @property groups + * @type {Array} + */ + groups: any[] = null as any; + + /** + * A unique key used to identify the group. This key can be used in calls to DataView + * collapseGroup() or expandGroup(). + * @property groupingKey + * @type {Object} + */ + groupingKey: any = null; + + constructor() { + super(); + } + /** + * Compares two Group instances. + * @method equals + * @return {Boolean} + * @param group {Group} Group instance to compare to. + */ + equals(group: SlickGroup): boolean { + return this.value === group.value && + this.count === group.count && + this.collapsed === group.collapsed && + this.title === group.title; + }; +} + +/** + * Information about group totals. + * An instance of GroupTotals will be created for each totals row and passed to the aggregators + * so that they can store arbitrary data in it. That data can later be accessed by group totals + * formatters during the display. + * @class GroupTotals + * @extends Slick.NonDataItem + * @constructor + */ +export class SlickGroupTotals extends SlickNonDataItem { + __groupTotals = true; + + /** + * Parent Group. + * @param group + * @type {Group} + */ + group: SlickGroup = null as any; + + /** + * Whether the totals have been fully initialized / calculated. + * Will be set to false for lazy-calculated group totals. + * @param initialized + * @type {Boolean} + */ + initialized = false; + + constructor() { + super(); + } +} + +/** + * A locking helper to track the active edit controller and ensure that only a single controller + * can be active at a time. This prevents a whole class of state and validation synchronization + * issues. An edit controller (such as SlickGrid) can query if an active edit is in progress + * and attempt a commit or cancel before proceeding. + * @class EditorLock + * @constructor + */ +export class SlickEditorLock { + activeEditController: any = null; + + /** + * Returns true if a specified edit controller is active (has the edit lock). + * If the parameter is not specified, returns true if any edit controller is active. + * @method isActive + * @param editController {EditController} + * @return {Boolean} + */ + isActive(editController?: EditController): boolean { + return (editController ? this.activeEditController === editController : this.activeEditController !== null); + }; + + /** + * Sets the specified edit controller as the active edit controller (acquire edit lock). + * If another edit controller is already active, and exception will be throw new Error(. + * @method activate + * @param editController {EditController} edit controller acquiring the lock + */ + activate(editController: EditController) { + if (editController === this.activeEditController) { // already activated? + return; + } + if (this.activeEditController !== null) { + throw new Error(`Slick.EditorLock.activate: an editController is still active, can't activate another editController`); + } + if (!editController.commitCurrentEdit) { + throw new Error('Slick.EditorLock.activate: editController must implement .commitCurrentEdit()'); + } + if (!editController.cancelCurrentEdit) { + throw new Error('Slick.EditorLock.activate: editController must implement .cancelCurrentEdit()'); + } + this.activeEditController = editController; + }; + + /** + * Unsets the specified edit controller as the active edit controller (release edit lock). + * If the specified edit controller is not the active one, an exception will be throw new Error(. + * @method deactivate + * @param editController {EditController} edit controller releasing the lock + */ + deactivate(editController: EditController) { + if (!this.activeEditController) { + return; + } + if (this.activeEditController !== editController) { + throw new Error('Slick.EditorLock.deactivate: specified editController is not the currently active one'); + } + this.activeEditController = null; + }; + + /** + * Attempts to commit the current edit by calling "commitCurrentEdit" method on the active edit + * controller and returns whether the commit attempt was successful (commit may fail due to validation + * errors, etc.). Edit controller's "commitCurrentEdit" must return true if the commit has succeeded + * and false otherwise. If no edit controller is active, returns true. + * @method commitCurrentEdit + * @return {Boolean} + */ + commitCurrentEdit(): boolean { + return (this.activeEditController ? this.activeEditController.commitCurrentEdit() : true); + }; + + /** + * Attempts to cancel the current edit by calling "cancelCurrentEdit" method on the active edit + * controller and returns whether the edit was successfully cancelled. If no edit controller is + * active, returns true. + * @method cancelCurrentEdit + * @return {Boolean} + */ + cancelCurrentEdit(): boolean { + return (this.activeEditController ? this.activeEditController.cancelCurrentEdit() : true); + }; +} + +function regexSanitizer(dirtyHtml: string) { + return dirtyHtml.replace(/(\b)(on[a-z]+)(\s*)=|javascript:([^>]*)[^>]*|(<\s*)(\/*)script([<>]*).*(<\s*)(\/*)script(>*)|(<)(\/*)(script|script defer)(.*)(>|>">)/gi, ''); +} + +export function isDefined(value: T | undefined | null): value is T { + return value !== undefined && value !== null; +} + +export class Utils { + // jQuery's extend + private static getProto = Object.getPrototypeOf; + private static class2type: any = {}; + private static toString = Utils.class2type.toString; + private static hasOwn = Utils.class2type.hasOwnProperty; + private static fnToString = Utils.hasOwn.toString; + private static ObjectFunctionString = Utils.fnToString.call(Object); + public static storage = { + // https://stackoverflow.com/questions/29222027/vanilla-alternative-to-jquery-data-function-any-native-javascript-alternati + _storage: new WeakMap(), + put: function (element: any, key: string, obj: any) { + if (!this._storage.has(element)) { + this._storage.set(element, new Map()); + } + this._storage.get(element).set(key, obj); + }, + get: function (element: any, key: string) { + const el = this._storage.get(element); + if (el) { + return el.get(key); + } + return null; + }, + remove: function (element: any, key: string) { + const ret = this._storage.get(element).delete(key); + if (!(this._storage.get(element).size === 0)) { + this._storage.delete(element); + } + return ret; + } + }; + + public static isFunction(obj: any) { + return typeof obj === 'function' && typeof obj.nodeType !== 'number' && + typeof obj.item !== 'function'; + } + + public static isPlainObject(obj: any) { + if (!obj || Utils.toString.call(obj) !== '[object Object]') { + return false; + } + + const proto = Utils.getProto(obj); + if (!proto) { + return true; + } + const Ctor = Utils.hasOwn.call(proto, 'constructor') && proto.constructor; + return typeof Ctor === 'function' && Utils.fnToString.call(Ctor) === Utils.ObjectFunctionString; + } + + public static calculateAvailableSpace(element: HTMLElement) { + let bottom = 0; + let top = 0; + let left = 0; + let right = 0; + + const windowHeight = window.innerHeight || 0; + const windowWidth = window.innerWidth || 0; + const scrollPosition = Utils.windowScrollPosition(); + const pageScrollTop = scrollPosition.top; + const pageScrollLeft = scrollPosition.left; + const elmOffset = Utils.offset(element); + + if (elmOffset) { + const elementOffsetTop = elmOffset.top || 0; + const elementOffsetLeft = elmOffset.left || 0; + top = elementOffsetTop - pageScrollTop; + bottom = windowHeight - (elementOffsetTop - pageScrollTop); + left = elementOffsetLeft - pageScrollLeft; + right = windowWidth - (elementOffsetLeft - pageScrollLeft); + } + + return { top, bottom, left, right }; + } + + public static extend(...args: any[]): T { + // eslint-disable-next-line one-var + let options, name, src, copy, copyIsArray, clone, + target = args[0], + i = 1, + deep = false; + const length = args.length; + + if (typeof target === 'boolean') { + deep = target; + target = args[i] || {}; + i++; + } else { + target = target || {}; + } + if (typeof target !== 'object' && !Utils.isFunction(target)) { + target = {}; + } + if (i === length) { + // @ts-ignore + // eslint-disable-next-line @typescript-eslint/no-this-alias + target = this; + i--; + } + for (; i < length; i++) { + if (isDefined(options = args[i])) { + for (name in options) { + copy = options[name]; + if (name === '__proto__' || target === copy) { + continue; + } + if (deep && copy && (Utils.isPlainObject(copy) || + (copyIsArray = Array.isArray(copy)))) { + src = target[name]; + if (copyIsArray && !Array.isArray(src)) { + clone = []; + } else if (!copyIsArray && !Utils.isPlainObject(src)) { + clone = {}; + } else { + clone = src; + } + copyIsArray = false; + target[name] = Utils.extend(deep, clone, copy); + } else if (copy !== undefined) { + target[name] = copy; + } + } + } + } + return target as T; + } + + /** + * Create a DOM Element with any optional attributes or properties. + * It will only accept valid DOM element properties that `createElement` would accept. + * For example: `createDomElement('div', { className: 'my-css-class' })`, + * for style or dataset you need to use nested object `{ style: { display: 'none' }} + * The last argument is to optionally append the created element to a parent container element. + * @param {String} tagName - html tag + * @param {Object} options - element properties + * @param {[HTMLElement]} appendToParent - parent element to append to + */ + public static createDomElement( + tagName: T, + elementOptions?: null | { [P in K]: InferDOMType }, + appendToParent?: Element + ): HTMLElementTagNameMap[T] { + const elm = document.createElement(tagName); + + if (elementOptions) { + Object.keys(elementOptions).forEach((elmOptionKey) => { + const elmValue = elementOptions[elmOptionKey as keyof typeof elementOptions]; + if (typeof elmValue === 'object') { + Object.assign(elm[elmOptionKey as K] as object, elmValue); + } else { + elm[elmOptionKey as K] = (elementOptions as any)[elmOptionKey as keyof typeof elementOptions]; + } + }); + } + if (appendToParent?.appendChild) { + appendToParent.appendChild(elm); + } + return elm; + } + + public static emptyElement(element: HTMLElement | null) { + if (element?.firstChild) { + while (element.firstChild) { + if (element.lastChild) { + element.removeChild(element.lastChild); + } + } + } + return element; + } + + public static innerSize(elm: HTMLElement, type: 'height' | 'width') { + let size = 0; + + if (elm) { + const clientSize = type === 'height' ? 'clientHeight' : 'clientWidth'; + const sides = type === 'height' ? ['top', 'bottom'] : ['left', 'right']; + size = elm[clientSize]; + for (const side of sides) { + const sideSize = (parseFloat(Utils.getElementProp(elm, `padding-${side}`) || '') || 0); + size -= sideSize; + } + } + return size; + } + + public static getElementProp(elm: HTMLElement & { getComputedStyle?: () => CSSStyleDeclaration }, property: string) { + if (elm?.getComputedStyle) { + return window.getComputedStyle(elm, null).getPropertyValue(property); + } + return null; + } + + public static isEmptyObject(obj: any) { + if (obj === null || obj === undefined) { + return true; + } + return Object.entries(obj).length === 0; + } + + public static noop() { } + + public static offset(el: HTMLElement | null) { + if (!el || !el.getBoundingClientRect) { + return undefined; + } + const box = el.getBoundingClientRect(); + const docElem = document.documentElement; + + return { + top: box.top + window.pageYOffset - docElem.clientTop, + left: box.left + window.pageXOffset - docElem.clientLeft + }; + } + + public static windowScrollPosition() { + return { + left: window.pageXOffset || document.documentElement.scrollLeft || 0, + top: window.pageYOffset || document.documentElement.scrollTop || 0, + }; + } + + public static width(el: HTMLElement, value?: number | string): number | void { + if (!el || !el.getBoundingClientRect) { return; } + if (value === undefined) { + return el.getBoundingClientRect().width; + } + Utils.setStyleSize(el, 'width', value); + } + + public static height(el: HTMLElement, value?: number | string): number | void { + if (!el) { + return; + } + if (value === undefined) { + return el.getBoundingClientRect().height; + } + Utils.setStyleSize(el, 'height', value); + } + + public static setStyleSize(el: HTMLElement, style: string, val?: number | string | Function) { + if (typeof val === 'function') { + val = val(); + } else if (typeof val === 'string') { + el.style[style as CSSStyleDeclarationWritable] = val; + } else { + el.style[style as CSSStyleDeclarationWritable] = val + 'px'; + } + } + + public static contains(parent: HTMLElement, child: HTMLElement) { + if (!parent || !child) { + return false; + } + + const parentList = Utils.parents(child); + return !parentList.every((p) => { + if (parent === p) { + return false; + } + return true; + }); + } + + public static isHidden(el: HTMLElement) { + return el.offsetWidth === 0 && el.offsetHeight === 0; + } + + public static parents(el: HTMLElement | ParentNode, selector?: string) { + const parents: Array = []; + const visible = selector === ':visible'; + const hidden = selector === ':hidden'; + + while ((el = el.parentNode as ParentNode) && el !== document) { + if (!el || !el.parentNode) { + break; + } + if (hidden) { + if (Utils.isHidden(el as HTMLElement)) { + parents.push(el); + } + } else if (visible) { + if (!Utils.isHidden(el as HTMLElement)) { + parents.push(el); + } + } else if (!selector || (el as any).matches(selector)) { + parents.push(el); + } + } + return parents; + } + + public static toFloat(value: string | number) { + const x = parseFloat(value as string); + if (isNaN(x)) { + return 0; + } + return x; + } + + public static show(el: HTMLElement | HTMLElement[], type = '') { + if (Array.isArray(el)) { + el.forEach((e) => e.style.display = type); + } else { + el.style.display = type; + } + } + + public static hide(el: HTMLElement | HTMLElement[]) { + if (Array.isArray(el)) { + el.forEach(function (e) { + e.style.display = 'none'; + }); + } else { + el.style.display = 'none'; + } + } + + public static slideUp(el: HTMLElement | HTMLElement[], callback: Function) { + return Utils.slideAnimation(el, 'slideUp', callback); + } + + public static slideDown(el: HTMLElement | HTMLElement[], callback: Function) { + return Utils.slideAnimation(el, 'slideDown', callback); + } + + public static slideAnimation(el: HTMLElement | HTMLElement[], slideDirection: 'slideDown' | 'slideUp', callback: Function) { + if ((window as any).jQuery !== undefined) { + (window as any).jQuery(el)[slideDirection]('fast', callback); + return; + } + (slideDirection === 'slideUp') ? Utils.hide(el) : Utils.show(el); + callback(); + } + + public static applyDefaults(targetObj: any, srcObj: any) { + for (const key in srcObj) { + if (srcObj.hasOwnProperty(key) && !targetObj.hasOwnProperty(key)) { + targetObj[key] = srcObj[key]; + } + } + } +} + +export const SlickGlobalEditorLock = new SlickEditorLock(); + +// export Slick namespace on both global & window objects +const SlickCore = { + Event: SlickEvent, + EventData: SlickEventData, + EventHandler: SlickEventHandler, + Range: SlickRange, + NonDataRow: SlickNonDataItem, + Group: SlickGroup, + GroupTotals: SlickGroupTotals, + EditorLock: SlickEditorLock, + RegexSanitizer: regexSanitizer, + + /** + * A global singleton editor lock. + * @class GlobalEditorLock + * @static + * @constructor + */ + GlobalEditorLock: SlickGlobalEditorLock, + + keyCode: { + SPACE: 8, + BACKSPACE: 8, + DELETE: 46, + DOWN: 40, + END: 35, + ENTER: 13, + ESCAPE: 27, + HOME: 36, + INSERT: 45, + LEFT: 37, + PAGE_DOWN: 34, + PAGE_UP: 33, + RIGHT: 39, + TAB: 9, + UP: 38, + A: 65 + }, + preClickClassName: 'slick-edit-preclick', + + GridAutosizeColsMode: { + None: 'NOA', + LegacyOff: 'LOF', + LegacyForceFit: 'LFF', + IgnoreViewport: 'IGV', + FitColsToViewport: 'FCV', + FitViewportToCols: 'FVC' + }, + + 'ColAutosizeMode': { + Locked: 'LCK', + Guide: 'GUI', + Content: 'CON', + ContentExpandOnly: 'CXO', + ContentIntelligent: 'CTI' + }, + + 'RowSelectionMode': { + FirstRow: 'FS1', + FirstNRows: 'FSN', + AllRows: 'ALL', + LastRow: 'LS1' + }, + + 'ValueFilterMode': { + None: 'NONE', + DeDuplicate: 'DEDP', + GetGreatestAndSub: 'GR8T', + GetLongestTextAndSub: 'LNSB', + GetLongestText: 'LNSC' + }, + + WidthEvalMode: { + Auto: 'AUTO', + TextOnly: 'CANV', + HTML: 'HTML' + } +}; + +export const { + EditorLock, Event, EventData, EventHandler, Group, GroupTotals, NonDataRow, Range, + RegexSanitizer, GlobalEditorLock, keyCode, preClickClassName, GridAutosizeColsMode, ColAutosizeMode, + RowSelectionMode, ValueFilterMode, WidthEvalMode +} = SlickCore; \ No newline at end of file diff --git a/packages/common/src/core/slick.dataview.ts b/packages/common/src/core/slick.dataview.ts new file mode 100644 index 000000000..8bffdd76b --- /dev/null +++ b/packages/common/src/core/slick.dataview.ts @@ -0,0 +1,1538 @@ +/* eslint-disable no-new-func */ +/* eslint-disable no-bitwise */ +import { SlickGroupItemMetadataProvider } from '../extensions/slickGroupItemMetadataProvider'; +import { Aggregator, Grouping, GroupingFormatterItem, ItemMetadata, OnGroupCollapsedEventArgs, OnGroupExpandedEventArgs, OnRowCountChangedEventArgs, OnRowsChangedEventArgs, OnRowsOrCountChangedEventArgs, OnSelectedRowIdsChangedEventArgs, OnSetItemsCalledEventArgs, PagingInfo } from '../interfaces'; +import { CssStyleHash, CustomDataView } from '../interfaces/gridOption.interface'; +import { + isDefined, + SlickEvent, + SlickEventData, + SlickGroup, + SlickGroupTotals, + SlickNonDataItem, + Utils, +} from './slick.core'; +import type { SlickGrid } from './slick.grid'; + +export interface DataViewOption { + groupItemMetadataProvider: SlickGroupItemMetadataProvider | null; + inlineFilters: boolean; +} +export type FilterFn = (item: T, args: any) => boolean; +export type DataIdType = number | string; +export type SlickDataItem = SlickNonDataItem | SlickGroup | SlickGroupTotals | any; +export type GroupGetterFn = (val: any) => string | number; +export type AnyFunction = (...args: any[]) => any; + +/** + * A sample Model implementation. + * Provides a filtered view of the underlying data. + * + * Relies on the data item having an "id" property uniquely identifying it. + */ +export class SlickDataView implements CustomDataView { + protected defaults: DataViewOption = { + groupItemMetadataProvider: null, + inlineFilters: false + }; + + // private + protected idProperty = 'id'; // property holding a unique row id + protected items: TData[] = []; // data by index + protected rows: TData[] = []; // data by row + protected idxById = new Map(); // indexes by id + protected rowsById: { [id: DataIdType]: number } | undefined = undefined; // rows by id; lazy-calculated + protected filter: FilterFn | null = null; // filter function + protected updated: ({ [id: DataIdType]: boolean }) | null = null; // updated item ids + protected suspend = false; // suspends the recalculation + protected isBulkSuspend = false; // delays protectedious operations like the + // index update and delete to efficient + // versions at endUpdate + protected bulkDeleteIds = new Map(); + protected sortAsc: boolean | undefined = true; + protected fastSortField?: string | null | (() => string); + protected sortComparer!: ((a: TData, b: TData) => number); + protected refreshHints: any = {}; + protected prevRefreshHints: any = {}; + protected filterArgs: any; + protected filteredItems: TData[] = []; + protected compiledFilter?: FilterFn | null; + protected compiledFilterWithCaching?: FilterFn | null; + protected filterCache: any[] = []; + protected _grid?: SlickGrid; // grid object will be defined only after using "syncGridSelection()" method" + + // grouping + protected groupingInfoDefaults: Grouping = { + getter: undefined, + formatter: undefined, + comparer: (a: { value: any; }, b: { value: any; }) => (a.value === b.value ? 0 : (a.value > b.value ? 1 : -1)), + predefinedValues: [], + aggregators: [], + aggregateEmpty: false, + aggregateCollapsed: false, + aggregateChildGroups: false, + collapsed: false, + displayTotalsRow: true, + lazyTotalsCalculation: false + }; + protected groupingInfos: Array = []; + protected groups: SlickGroup[] = []; + protected toggledGroupsByLevel: any[] = []; + protected groupingDelimiter = ':|:'; + protected selectedRowIds: DataIdType[] = []; + protected preSelectedRowIdsChangeFn?: (args?: any) => void; + + protected pagesize = 0; + protected pagenum = 0; + protected totalRows = 0; + protected _options: DataViewOption; + + // public events + onBeforePagingInfoChanged = new SlickEvent(); + onGroupExpanded = new SlickEvent(); + onGroupCollapsed = new SlickEvent(); + onPagingInfoChanged = new SlickEvent(); + onRowCountChanged = new SlickEvent(); + onRowsChanged = new SlickEvent(); + onRowsOrCountChanged = new SlickEvent(); + onSelectedRowIdsChanged = new SlickEvent(); + onSetItemsCalled = new SlickEvent(); + + constructor(options: Partial) { + this._options = Utils.extend(true, {}, this.defaults, options); + } + + /** + * Begins a bached update of the items in the data view. + * including deletes and the related events are postponed to the endUpdate call. + * As certain operations are postponed during this update, some methods might not + * deliver fully consistent information. + * @param {Boolean} [bulkUpdate] - if set to true, most data view modifications + */ + beginUpdate(bulkUpdate?: boolean) { + this.suspend = true; + this.isBulkSuspend = bulkUpdate === true; + } + + endUpdate() { + const wasBulkSuspend = this.isBulkSuspend; + this.isBulkSuspend = false; + this.suspend = false; + if (wasBulkSuspend) { + this.processBulkDelete(); + this.ensureIdUniqueness(); + } + this.refresh(); + } + + destroy() { + this.items = []; + this.idxById = null as any; + this.rowsById = null as any; + this.filter = null as any; + this.updated = null as any; + this.sortComparer = null as any; + this.filterCache = []; + this.filteredItems = []; + this.compiledFilter = null; + this.compiledFilterWithCaching = null; + + if (this._grid && this._grid.onSelectedRowsChanged && this._grid.onCellCssStylesChanged) { + this._grid.onSelectedRowsChanged.unsubscribe(); + this._grid.onCellCssStylesChanged.unsubscribe(); + } + if (this.onRowsOrCountChanged) { + this.onRowsOrCountChanged.unsubscribe(); + } + } + + setRefreshHints(hints: any) { + this.refreshHints = hints; + } + + setFilterArgs(args: any) { + this.filterArgs = args; + } + + /** + * Processes all delete requests placed during bulk update + * by recomputing the items and idxById members. + */ + protected processBulkDelete() { + if (!this.idxById) { return; } + + // the bulk update is processed by + // recomputing the whole items array and the index lookup in one go. + // this is done by placing the not-deleted items + // from left to right into the array and shrink the array the the new + // size afterwards. + // see https://github.com/6pac/SlickGrid/issues/571 for further details. + + let id: DataIdType; + let item; + let newIdx = 0; + for (let i = 0, l = this.items.length; i < l; i++) { + item = this.items[i]; + id = item[this.idProperty as keyof TData] as DataIdType; + if (id === undefined) { + throw new Error(`[SlickGrid DataView] Each data element must implement a unique 'id' property`); + } + + // if items have been marked as deleted we skip them for the new final items array + // and we remove them from the lookup table. + if (this.bulkDeleteIds.has(id)) { + this.idxById.delete(id); + } else { + // for items which are not deleted, we add them to the + // next free position in the array and register the index in the lookup. + this.items[newIdx] = item; + this.idxById.set(id, newIdx); + ++newIdx; + } + } + + // here we shrink down the full item array to the ones actually + // inserted in the cleanup loop above. + this.items.length = newIdx; + // and finally cleanup the deleted ids to start cleanly on the next update. + this.bulkDeleteIds = new Map(); + } + + protected updateIdxById(startingIndex?: number) { + if (this.isBulkSuspend || !this.idxById) { // during bulk update we do not reorganize + return; + } + startingIndex = startingIndex || 0; + let id: DataIdType; + for (let i = startingIndex, l = this.items.length; i < l; i++) { + id = this.items[i][this.idProperty as keyof TData] as DataIdType; + if (id === undefined) { + throw new Error(`[SlickGrid DataView] Each data element must implement a unique 'id' property`); + } + this.idxById.set(id, i); + } + } + + protected ensureIdUniqueness() { + if (this.isBulkSuspend || !this.idxById) { // during bulk update we do not reorganize + return; + } + let id: DataIdType; + for (let i = 0, l = this.items.length; i < l; i++) { + id = this.items[i][this.idProperty as keyof TData] as DataIdType; + if (id === undefined || this.idxById.get(id) !== i) { + throw new Error(`[SlickGrid DataView] Each data element must implement a unique 'id' property`); + } + } + } + + /** Get all DataView Items */ + getItems() { + return this.items; + } + + /** Get the DataView Id property name to use (defaults to "Id" but could be customized to something else when instantiating the DataView) */ + getIdPropertyName() { + return this.idProperty; + } + + /** + * Set the Items with a new Dataset and optionally pass a different Id property name + * @param {Array<*>} data - array of data + * @param {String} [objectIdProperty] - optional id property to use as primary id + */ + setItems(data: TData[], objectIdProperty?: string) { + if (objectIdProperty !== undefined) { + this.idProperty = objectIdProperty; + } + this.items = this.filteredItems = data; + this.onSetItemsCalled.notify({ idProperty: this.idProperty, itemCount: this.items.length }, null, this); + this.idxById = new Map(); + this.updateIdxById(); + this.ensureIdUniqueness(); + this.refresh(); + } + + /** Set Paging Options */ + setPagingOptions(args: Partial) { + if (this.onBeforePagingInfoChanged.notify(this.getPagingInfo(), null, this).getReturnValue() !== false) { + if (isDefined(args.pageSize)) { + this.pagesize = args.pageSize; + this.pagenum = this.pagesize ? Math.min(this.pagenum, Math.max(0, Math.ceil(this.totalRows / this.pagesize) - 1)) : 0; + } + + if (isDefined(args.pageNum)) { + this.pagenum = Math.min(args.pageNum, Math.max(0, Math.ceil(this.totalRows / this.pagesize) - 1)); + } + + this.onPagingInfoChanged.notify(this.getPagingInfo(), null, this); + + this.refresh(); + } + } + + /** Get Paging Options */ + getPagingInfo(): PagingInfo { + const totalPages = this.pagesize ? Math.max(1, Math.ceil(this.totalRows / this.pagesize)) : 1; + return { pageSize: this.pagesize, pageNum: this.pagenum, totalRows: this.totalRows, totalPages, dataView: this as SlickDataView }; + } + + /** Sort Method to use by the DataView */ + sort(comparer: (a: TData, b: TData) => number, ascending?: boolean) { + this.sortAsc = ascending; + this.sortComparer = comparer; + this.fastSortField = null; + if (ascending === false) { + this.items.reverse(); + } + this.items.sort(comparer); + if (ascending === false) { + this.items.reverse(); + } + this.idxById = new Map(); + this.updateIdxById(); + this.refresh(); + } + + /** + * Provides a workaround for the extremely slow sorting in IE. + * Does a [lexicographic] sort on a give column by temporarily overriding Object.prototype.toString + * to return the value of that field and then doing a native Array.sort(). + */ + fastSort(field: string | (() => string), ascending?: boolean) { + this.sortAsc = ascending; + this.fastSortField = field; + this.sortComparer = null as any; + const oldToString = Object.prototype.toString; + Object.prototype.toString = (typeof field === 'function') ? field : function () { + // @ts-ignore + return this[field]; + }; + // an extra reversal for descending sort keeps the sort stable + // (assuming a stable native sort implementation, which isn't true in some cases) + if (ascending === false) { + this.items.reverse(); + } + this.items.sort(); + Object.prototype.toString = oldToString; + if (ascending === false) { + this.items.reverse(); + } + this.idxById = new Map(); + this.updateIdxById(); + this.refresh(); + } + + /** Re-Sort the dataset */ + reSort() { + if (this.sortComparer) { + this.sort(this.sortComparer, this.sortAsc); + } else if (this.fastSortField) { + this.fastSort(this.fastSortField, this.sortAsc); + } + } + + /** Get only the DataView filtered items */ + getFilteredItems() { + return this.filteredItems as T[]; + } + + /** Get the array length (count) of only the DataView filtered items */ + getFilteredItemCount() { + return this.filteredItems.length; + } + + /** Get current Filter used by the DataView */ + getFilter() { + return this.filter; + } + + /** + * Set a Filter that will be used by the DataView + * @param {Function} fn - filter callback function + */ + setFilter(filterFn: FilterFn) { + this.filter = filterFn; + if (this._options.inlineFilters) { + this.compiledFilter = this.compileFilter(); + this.compiledFilterWithCaching = this.compileFilterWithCaching(); + } + this.refresh(); + } + + /** Get current Grouping info */ + getGrouping(): Grouping[] { + return this.groupingInfos; + } + + /** Set some Grouping */ + setGrouping(groupingInfo: Grouping | Grouping[]) { + if (!this._options.groupItemMetadataProvider) { + this._options.groupItemMetadataProvider = new SlickGroupItemMetadataProvider(); + } + + this.groups = []; + this.toggledGroupsByLevel = []; + groupingInfo = groupingInfo || []; + this.groupingInfos = ((groupingInfo instanceof Array) ? groupingInfo : [groupingInfo]) as any; + + for (let i = 0; i < this.groupingInfos.length; i++) { + const gi = this.groupingInfos[i] = Utils.extend(true, {}, this.groupingInfoDefaults, this.groupingInfos[i]); + gi.getterIsAFn = typeof gi.getter === 'function'; + + // pre-compile accumulator loops + gi.compiledAccumulators = []; + let idx = gi.aggregators.length; + while (idx--) { + gi.compiledAccumulators[idx] = this.compileAccumulatorLoop(gi.aggregators[idx]); + } + + this.toggledGroupsByLevel[i] = {}; + } + + this.refresh(); + } + + /** Get an item in the DataView by its row index */ + getItemByIdx(i: number) { + return this.items[i] as T; + } + + /** Get row index in the DataView by its Id */ + getIdxById(id: DataIdType) { + return this.idxById?.get(id); + } + + protected ensureRowsByIdCache() { + if (!this.rowsById) { + this.rowsById = {}; + for (let i = 0, l = this.rows.length; i < l; i++) { + this.rowsById[this.rows[i][this.idProperty as keyof TData] as DataIdType] = i; + } + } + } + + /** Get row number in the grid by its item object */ + getRowByItem(item: TData) { + this.ensureRowsByIdCache(); + return this.rowsById?.[item[this.idProperty as keyof TData] as DataIdType]; + } + + /** Get row number in the grid by its Id */ + getRowById(id: DataIdType) { + this.ensureRowsByIdCache(); + return this.rowsById?.[id]; + } + + /** Get an item in the DataView by its Id */ + getItemById(id: DataIdType) { + return this.items[(this.idxById.get(id) as number)] as T; + } + + /** From the items array provided, return the mapped rows */ + mapItemsToRows(itemArray: TData[]) { + const rows: number[] = []; + this.ensureRowsByIdCache(); + for (let i = 0, l = itemArray.length; i < l; i++) { + const row = this.rowsById?.[itemArray[i][this.idProperty as keyof TData] as DataIdType]; + if (isDefined(row)) { + rows[rows.length] = row as number; + } + } + return rows; + } + + /** From the Ids array provided, return the mapped rows */ + mapIdsToRows(idArray: DataIdType[]) { + const rows: number[] = []; + this.ensureRowsByIdCache(); + for (let i = 0, l = idArray.length; i < l; i++) { + const row = this.rowsById?.[idArray[i]]; + if (isDefined(row)) { + rows[rows.length] = row as number; + } + } + return rows; + } + + /** From the rows array provided, return the mapped Ids */ + mapRowsToIds(rowArray: number[]) { + const ids: DataIdType[] = []; + for (let i = 0, l = rowArray.length; i < l; i++) { + if (rowArray[i] < this.rows.length) { + const rowItem = this.rows[rowArray[i]]; + ids[ids.length] = rowItem![this.idProperty as keyof TData] as DataIdType; + } + } + return ids; + } + + /** + * Performs the update operations of a single item by id without + * triggering any events or refresh operations. + * @param id The new id of the item. + * @param item The item which should be the new value for the given id. + */ + updateSingleItem(id: DataIdType, item: TData) { + if (!this.idxById) { return; } + + // see also https://github.com/mleibman/SlickGrid/issues/1082 + if (!this.idxById.has(id)) { + throw new Error('[SlickGrid DataView] Invalid id'); + } + + // What if the specified item also has an updated idProperty? + // Then we'll have to update the index as well, and possibly the `updated` cache too. + if (id !== item[this.idProperty as keyof TData]) { + // make sure the new id is unique: + const newId = item[this.idProperty as keyof TData] as DataIdType; + if (!isDefined(newId)) { + throw new Error('[SlickGrid DataView] Cannot update item to associate with a null id'); + } + if (this.idxById.has(newId)) { + throw new Error('[SlickGrid DataView] Cannot update item to associate with a non-unique id'); + } + this.idxById.set(newId, this.idxById.get(id) as number); + this.idxById.delete(id); + + // Also update the `updated` hashtable/markercache? Yes, `recalc()` inside `refresh()` needs that one! + if (this.updated?.[id]) { + delete this.updated[id]; + } + + // Also update the row indexes? no need since the `refresh()`, further down, blows away the `rowsById[]` cache! + + id = newId; + } + this.items[this.idxById.get(id) as number] = item; + + // Also update the rows? no need since the `refresh()`, further down, blows away the `rows[]` cache and recalculates it via `recalc()`! + + if (!this.updated) { + this.updated = {}; + } + this.updated[id] = true; + } + + /** + * Updates a single item in the data view given the id and new value. + * @param id The new id of the item. + * @param item The item which should be the new value for the given id. + */ + updateItem(id: DataIdType, item: T) { + this.updateSingleItem(id, item); + this.refresh(); + } + + /** + * Updates multiple items in the data view given the new ids and new values. + * @param id {Array} The array of new ids which is in the same order as the items. + * @param newItems {Array} The new items that should be set in the data view for the given ids. + */ + updateItems(ids: DataIdType[], newItems: T[]) { + if (ids.length !== newItems.length) { + throw new Error(`[SlickGrid DataView] Mismatch on the length of ids and items provided to update`); + } + for (let i = 0, l = newItems.length; i < l; i++) { + this.updateSingleItem(ids[i], newItems[i]); + } + this.refresh(); + } + + /** + * Inserts a single item into the data view at the given position. + * @param insertBefore {Number} The 0-based index before which the item should be inserted. + * @param item The item to insert. + */ + insertItem(insertBefore: number, item: TData) { + this.items.splice(insertBefore, 0, item); + this.updateIdxById(insertBefore); + this.refresh(); + } + + /** + * Inserts multiple items into the data view at the given position. + * @param insertBefore {Number} The 0-based index before which the items should be inserted. + * @param newItems {Array} The items to insert. + */ + insertItems(insertBefore: number, newItems: TData[]) { + // @ts-ignore + Array.prototype.splice.apply(this.items, [insertBefore, 0].concat(newItems)); + this.updateIdxById(insertBefore); + this.refresh(); + } + + /** + * Adds a single item at the end of the data view. + * @param item The item to add at the end. + */ + addItem(item: TData) { + this.items.push(item); + this.updateIdxById(this.items.length - 1); + this.refresh(); + } + + /** + * Adds multiple items at the end of the data view. + * @param {Array} newItems The items to add at the end. + */ + addItems(newItems: TData[]) { + this.items = this.items.concat(newItems); + this.updateIdxById(this.items.length - newItems.length); + this.refresh(); + } + + /** + * Deletes a single item identified by the given id from the data view. + * @param {String|Number} id The id identifying the object to delete. + */ + deleteItem(id: DataIdType) { + if (!this.idxById) { return; } + if (this.isBulkSuspend) { + this.bulkDeleteIds.set(id, true); + } else { + const idx = this.idxById.get(id); + if (idx === undefined) { + throw new Error('[SlickGrid DataView] Invalid id'); + } + this.idxById.delete(id); + this.items.splice(idx, 1); + this.updateIdxById(idx); + this.refresh(); + } + } + + /** + * Deletes multiple item identified by the given ids from the data view. + * @param {Array} ids The ids of the items to delete. + */ + deleteItems(ids: DataIdType[]) { + if (ids.length === 0 || !this.idxById) { + return; + } + + if (this.isBulkSuspend) { + for (let i = 0, l = ids.length; i < l; i++) { + const id = ids[i]; + const idx = this.idxById.get(id); + if (idx === undefined) { + throw new Error('[SlickGrid DataView] Invalid id'); + } + this.bulkDeleteIds.set(id, true); + } + } else { + // collect all indexes + const indexesToDelete: number[] = []; + for (let i = 0, l = ids.length; i < l; i++) { + const id = ids[i]; + const idx = this.idxById.get(id); + if (idx === undefined) { + throw new Error('[SlickGrid DataView] Invalid id'); + } + this.idxById.delete(id); + indexesToDelete.push(idx); + } + + // Remove from back to front + indexesToDelete.sort(); + for (let i = indexesToDelete.length - 1; i >= 0; --i) { + this.items.splice(indexesToDelete[i], 1); + } + + // update lookup from front to back + this.updateIdxById(indexesToDelete[0]); + this.refresh(); + } + } + + /** Add an item in a sorted dataset (a Sort function must be defined) */ + sortedAddItem(item: TData) { + if (!this.sortComparer) { + throw new Error('[SlickGrid DataView] sortedAddItem() requires a sort comparer, use sort()'); + } + this.insertItem(this.sortedIndex(item), item); + } + + /** Update an item in a sorted dataset (a Sort function must be defined) */ + sortedUpdateItem(id: string | number, item: TData) { + if (!this.idxById) { return; } + if (!this.idxById.has(id) || id !== item[this.idProperty as keyof TData]) { + throw new Error('[SlickGrid DataView] Invalid or non-matching id ' + this.idxById.get(id)); + } + if (!this.sortComparer) { + throw new Error('[SlickGrid DataView] sortedUpdateItem() requires a sort comparer, use sort()'); + } + const oldItem = this.getItemById(id); + if (this.sortComparer(oldItem, item) !== 0) { + // item affects sorting -> must use sorted add + this.deleteItem(id); + this.sortedAddItem(item); + } else { // update does not affect sorting -> regular update works fine + this.updateItem(id, item); + } + } + + protected sortedIndex(searchItem: TData) { + let low = 0; + let high = this.items.length; + + while (low < high) { + const mid = low + high >>> 1; + if (this.sortComparer(this.items[mid], searchItem) === -1) { + low = mid + 1; + } else { + high = mid; + } + } + return low; + } + + /** Get item count, that is the full dataset lenght of the DataView */ + getItemCount() { + return this.items.length; + } + + /** Get row count (rows displayed in current page) */ + getLength() { + return this.rows.length; + } + + /** Retrieve an item from the DataView at specific index */ + getItem(i: number) { + const item = this.rows[i] as T; + + // if this is a group row, make sure totals are calculated and update the title + if ((item as SlickGroup)?.__group && (item as SlickGroup).totals && !(item as SlickGroup).totals?.initialized) { + const gi = this.groupingInfos[(item as SlickGroup).level]; + if (!gi.displayTotalsRow) { + this.calculateTotals((item as SlickGroup).totals); + (item as SlickGroup).title = gi.formatter ? gi.formatter((item as SlickGroup)) : (item as SlickGroup).value; + } + } + // if this is a totals row, make sure it's calculated + else if ((item as SlickGroupTotals)?.__groupTotals && !(item as SlickGroupTotals).initialized) { + this.calculateTotals(item as SlickGroupTotals); + } + + return item; + } + + getItemMetadata(i: number): ItemMetadata | null { + const item = this.rows[i]; + if (item === undefined) { + return null; + } + + // overrides for grouping rows + if ((item as SlickGroup).__group) { + return this._options.groupItemMetadataProvider!.getGroupRowMetadata(item as GroupingFormatterItem); + } + + // overrides for totals rows + if ((item as SlickGroupTotals).__groupTotals) { + return this._options.groupItemMetadataProvider!.getTotalsRowMetadata(item as { group: GroupingFormatterItem }); + } + + return null; + } + + protected expandCollapseAllGroups(level?: number, collapse?: boolean) { + if (!isDefined(level)) { + for (let i = 0; i < this.groupingInfos.length; i++) { + this.toggledGroupsByLevel[i] = {}; + this.groupingInfos[i].collapsed = collapse; + + if (collapse === true) { + this.onGroupCollapsed.notify({ level: i, groupingKey: null }); + } else { + this.onGroupExpanded.notify({ level: i, groupingKey: null }); + } + } + } else { + this.toggledGroupsByLevel[level] = {}; + this.groupingInfos[level].collapsed = collapse; + + if (collapse === true) { + this.onGroupCollapsed.notify({ level, groupingKey: null }); + } else { + this.onGroupExpanded.notify({ level, groupingKey: null }); + } + } + this.refresh(); + } + + /** + * @param {Number} [level] Optional level to collapse. If not specified, applies to all levels. + */ + collapseAllGroups(level?: number) { + this.expandCollapseAllGroups(level, true); + } + + /** + * @param {Number} [level] Optional level to expand. If not specified, applies to all levels. + */ + expandAllGroups(level?: number) { + this.expandCollapseAllGroups(level, false); + } + + expandCollapseGroup(level: number, groupingKey: string, collapse?: boolean) { + // @ts-ignore + this.toggledGroupsByLevel[level][groupingKey] = this.groupingInfos[level].collapsed ^ collapse; + this.refresh(); + } + + /** + * @param varArgs Either a Slick.Group's "groupingKey" property, or a + * variable argument list of grouping values denoting a unique path to the row. For + * example, calling collapseGroup('high', '10%') will collapse the '10%' subgroup of + * the 'high' group. + */ + collapseGroup(...args: any) { + const calledArgs = Array.prototype.slice.call(args); + const arg0 = calledArgs[0]; + let groupingKey; + let level; + + if (args.length === 1 && arg0.indexOf(this.groupingDelimiter) !== -1) { + groupingKey = arg0; + level = arg0.split(this.groupingDelimiter).length - 1; + } else { + groupingKey = args.join(this.groupingDelimiter); + level = args.length - 1; + } + + this.expandCollapseGroup(level, groupingKey, true); + this.onGroupCollapsed.notify({ level, groupingKey }); + } + + /** + * @param varArgs Either a Slick.Group's "groupingKey" property, or a + * variable argument list of grouping values denoting a unique path to the row. For + * example, calling expandGroup('high', '10%') will expand the '10%' subgroup of + * the 'high' group. + */ + expandGroup(...args: any) { + const calledArgs = Array.prototype.slice.call(args); + const arg0 = calledArgs[0]; + let groupingKey; + let level; + + if (args.length === 1 && arg0.indexOf(this.groupingDelimiter) !== -1) { + level = arg0.split(this.groupingDelimiter).length - 1; + groupingKey = arg0; + } else { + level = args.length - 1; + groupingKey = args.join(this.groupingDelimiter); + } + + this.expandCollapseGroup(level, groupingKey, false); + this.onGroupExpanded.notify({ level, groupingKey }); + } + + getGroups() { + return this.groups; + } + + protected extractGroups(rows: any[], parentGroup?: SlickGroup) { + let group; + let val; + const groups: SlickGroup[] = []; + const groupsByVal: any = {}; + let r; + const level = parentGroup ? parentGroup.level + 1 : 0; + const gi = this.groupingInfos[level]; + + for (let i = 0, l = gi.predefinedValues?.length ?? 0; i < l; i++) { + val = gi.predefinedValues?.[i]; + group = groupsByVal[val]; + if (!group) { + group = new SlickGroup(); + group.value = val; + group.level = level; + group.groupingKey = (parentGroup ? parentGroup.groupingKey + this.groupingDelimiter : '') + val; + groups[groups.length] = group; + groupsByVal[val] = group; + } + } + + for (let i = 0, l = rows.length; i < l; i++) { + r = rows[i]; + val = gi.getterIsAFn ? (gi.getter as GroupGetterFn)(r) : r[gi.getter as keyof TData]; + group = groupsByVal[val]; + if (!group) { + group = new SlickGroup(); + group.value = val; + group.level = level; + group.groupingKey = (parentGroup ? parentGroup.groupingKey + this.groupingDelimiter : '') + val; + groups[groups.length] = group; + groupsByVal[val] = group; + } + + group.rows[group.count++] = r; + } + + if (level < this.groupingInfos.length - 1) { + for (let i = 0; i < groups.length; i++) { + group = groups[i]; + group.groups = this.extractGroups(group.rows, group); + } + } + + if (groups.length) { + this.addTotals(groups, level); + } + + groups.sort(this.groupingInfos[level].comparer); + + return groups; + } + + protected calculateTotals(totals: SlickGroupTotals) { + const group = totals.group; + const gi = this.groupingInfos[group.level ?? 0]; + const isLeafLevel = (group.level === this.groupingInfos.length); + let agg: Aggregator; + let idx = gi.aggregators.length; + + if (!isLeafLevel && gi.aggregateChildGroups) { + // make sure all the subgroups are calculated + let i = group.groups?.length ?? 0; + while (i--) { + if (!group.groups[i].totals.initialized) { + this.calculateTotals(group.groups[i].totals); + } + } + } + + while (idx--) { + agg = gi.aggregators[idx]; + agg.init(); + if (!isLeafLevel && gi.aggregateChildGroups) { + gi.compiledAccumulators[idx].call(agg, group.groups); + } else { + gi.compiledAccumulators[idx].call(agg, group.rows); + } + agg.storeResult(totals); + } + totals.initialized = true; + } + + protected addGroupTotals(group: SlickGroup) { + const gi = this.groupingInfos[group.level]; + const totals = new SlickGroupTotals(); + totals.group = group; + group.totals = totals; + if (!gi.lazyTotalsCalculation) { + this.calculateTotals(totals); + } + } + + protected addTotals(groups: SlickGroup[], level?: number) { + level = level || 0; + const gi = this.groupingInfos[level]; + const groupCollapsed = gi.collapsed; + const toggledGroups = this.toggledGroupsByLevel[level]; + let idx = groups.length; + let g; + while (idx--) { + g = groups[idx]; + + if (g.collapsed && !gi.aggregateCollapsed) { + continue; + } + + // Do a depth-first aggregation so that parent group aggregators can access subgroup totals. + if (g.groups) { + this.addTotals(g.groups, level + 1); + } + + if (gi.aggregators?.length && ( + gi.aggregateEmpty || g.rows.length || g.groups?.length)) { + this.addGroupTotals(g); + } + + g.collapsed = (groupCollapsed as any) ^ toggledGroups[g.groupingKey]; + g.title = gi.formatter ? gi.formatter(g) : g.value; + } + } + + protected flattenGroupedRows(groups: SlickGroup[], level?: number) { + level = level || 0; + const gi = this.groupingInfos[level]; + const groupedRows: any[] = []; + let rows: any[]; + let gl = 0; + let g; + for (let i = 0, l = groups.length; i < l; i++) { + g = groups[i]; + groupedRows[gl++] = g; + + if (!g.collapsed) { + rows = g.groups ? this.flattenGroupedRows(g.groups, level + 1) : g.rows; + for (let j = 0, jj = rows.length; j < jj; j++) { + groupedRows[gl++] = rows[j]; + } + } + + if (g.totals && gi.displayTotalsRow && (!g.collapsed || gi.aggregateCollapsed)) { + groupedRows[gl++] = g.totals; + } + } + return groupedRows; + } + + protected getFunctionInfo(fn: AnyFunction) { + const fnStr = fn.toString(); + const usingEs5 = fnStr.indexOf('function') >= 0; // with ES6, the word function is not present + const fnRegex = usingEs5 ? /^function[^(]*\(([^)]*)\)\s*{([\s\S]*)}$/ : /^[^(]*\(([^)]*)\)\s*{([\s\S]*)}$/; + const matches = fn.toString().match(fnRegex) || []; + return { + params: matches[1].split(','), + body: matches[2] + }; + } + + protected compileAccumulatorLoop(aggregator: Aggregator) { + if (aggregator.accumulate) { + const accumulatorInfo = this.getFunctionInfo(aggregator.accumulate); + const fn: any = new Function( + '_items', + 'for (var ' + accumulatorInfo.params[0] + ', _i=0, _il=_items.length; _i<_il; _i++) {' + + accumulatorInfo.params[0] + ' = _items[_i]; ' + + accumulatorInfo.body + + '}' + ); + const fnName = 'compiledAccumulatorLoop'; + fn.displayName = fnName; + fn.name = this.setFunctionName(fn, fnName); + return fn; + } else { + return function noAccumulator() { }; + } + } + + protected compileFilter(): FilterFn { + const filterInfo = this.getFunctionInfo(this.filter as FilterFn); + + const filterPath1 = '{ continue _coreloop; }$1'; + const filterPath2 = '{ _retval[_idx++] = $item$; continue _coreloop; }$1'; + // make some allowances for minification - there's only so far we can go with RegEx + const filterBody = filterInfo.body + .replace(/return false\s*([;}]|\}|$)/gi, filterPath1) + .replace(/return!1([;}]|\}|$)/gi, filterPath1) + .replace(/return true\s*([;}]|\}|$)/gi, filterPath2) + .replace(/return!0([;}]|\}|$)/gi, filterPath2) + .replace(/return ([^;}]+?)\s*([;}]|$)/gi, + '{ if ($1) { _retval[_idx++] = $item$; }; continue _coreloop; }$2'); + + // This preserves the function template code after JS compression, + // so that replace() commands still work as expected. + let tpl = [ + // 'function(_items, _args) { ', + 'var _retval = [], _idx = 0; ', + 'var $item$, $args$ = _args; ', + '_coreloop: ', + 'for (var _i = 0, _il = _items.length; _i < _il; _i++) { ', + '$item$ = _items[_i]; ', + '$filter$; ', + '} ', + 'return _retval; ' + // '}' + ].join(''); + tpl = tpl.replace(/\$filter\$/gi, filterBody); + tpl = tpl.replace(/\$item\$/gi, filterInfo.params[0]); + tpl = tpl.replace(/\$args\$/gi, filterInfo.params[1]); + + const fn: any = new Function('_items,_args', tpl); + const fnName = 'compiledFilter'; + fn.displayName = fnName; + fn.name = this.setFunctionName(fn, fnName); + return fn; + } + + protected compileFilterWithCaching() { + const filterInfo = this.getFunctionInfo(this.filter as FilterFn); + + const filterPath1 = '{ continue _coreloop; }$1'; + const filterPath2 = '{ _cache[_i] = true;_retval[_idx++] = $item$; continue _coreloop; }$1'; + // make some allowances for minification - there's only so far we can go with RegEx + const filterBody = filterInfo.body + .replace(/return false\s*([;}]|\}|$)/gi, filterPath1) + .replace(/return!1([;}]|\}|$)/gi, filterPath1) + .replace(/return true\s*([;}]|\}|$)/gi, filterPath2) + .replace(/return!0([;}]|\}|$)/gi, filterPath2) + .replace(/return ([^;}]+?)\s*([;}]|$)/gi, + '{ if ((_cache[_i] = $1)) { _retval[_idx++] = $item$; }; continue _coreloop; }$2'); + + // This preserves the function template code after JS compression, + // so that replace() commands still work as expected. + let tpl = [ + // 'function(_items, _args, _cache) { ', + 'var _retval = [], _idx = 0; ', + 'var $item$, $args$ = _args; ', + '_coreloop: ', + 'for (var _i = 0, _il = _items.length; _i < _il; _i++) { ', + '$item$ = _items[_i]; ', + 'if (_cache[_i]) { ', + '_retval[_idx++] = $item$; ', + 'continue _coreloop; ', + '} ', + '$filter$; ', + '} ', + 'return _retval; ' + // '}' + ].join(''); + tpl = tpl.replace(/\$filter\$/gi, filterBody); + tpl = tpl.replace(/\$item\$/gi, filterInfo.params[0]); + tpl = tpl.replace(/\$args\$/gi, filterInfo.params[1]); + + const fn: any = new Function('_items,_args,_cache', tpl); + const fnName = 'compiledFilterWithCaching'; + fn.displayName = fnName; + fn.name = this.setFunctionName(fn, fnName); + return fn; + } + + /** + * In ES5 we could set the function name on the fly but in ES6 this is forbidden and we need to set it through differently + * We can use Object.defineProperty and set it the property to writable, see MDN for reference + * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty + * @param {*} fn + * @param {string} fnName + */ + protected setFunctionName(fn: any, fnName: string) { + try { + Object.defineProperty(fn, 'name', { + writable: true, + value: fnName + }); + } catch (err) { + fn.name = fnName; + } + } + + protected uncompiledFilter(items: TData[], args: any) { + const retval: any[] = []; + let idx = 0; + + for (let i = 0, ii = items.length; i < ii; i++) { + if (this.filter?.(items[i], args)) { + retval[idx++] = items[i]; + } + } + + return retval; + } + + protected uncompiledFilterWithCaching(items: TData[], args: any, cache: any) { + const retval: any[] = []; + let idx = 0; + let item: TData; + + for (let i = 0, ii = items.length; i < ii; i++) { + item = items[i]; + if (cache[i]) { + retval[idx++] = item; + } else if (this.filter?.(item, args)) { + retval[idx++] = item; + cache[i] = true; + } + } + + return retval; + } + + protected getFilteredAndPagedItems(items: TData[]) { + if (this.filter) { + const batchFilter = (this._options.inlineFilters ? this.compiledFilter : this.uncompiledFilter) as AnyFunction; + const batchFilterWithCaching = (this._options.inlineFilters ? this.compiledFilterWithCaching : this.uncompiledFilterWithCaching) as AnyFunction; + + if (this.refreshHints.isFilterNarrowing) { + this.filteredItems = batchFilter.call(this, this.filteredItems, this.filterArgs); + } else if (this.refreshHints.isFilterExpanding) { + this.filteredItems = batchFilterWithCaching.call(this, items, this.filterArgs, this.filterCache); + } else if (!this.refreshHints.isFilterUnchanged) { + this.filteredItems = batchFilter.call(this, items, this.filterArgs); + } + } else { + // special case: if not filtering and not paging, the resulting + // rows collection needs to be a copy so that changes due to sort + // can be caught + this.filteredItems = this.pagesize ? items : items.concat(); + } + + // get the current page + let paged: TData[]; + if (this.pagesize) { + if (this.filteredItems.length <= this.pagenum * this.pagesize) { + if (this.filteredItems.length === 0) { + this.pagenum = 0; + } else { + this.pagenum = Math.floor((this.filteredItems.length - 1) / this.pagesize); + } + } + paged = this.filteredItems.slice(this.pagesize * this.pagenum, this.pagesize * this.pagenum + this.pagesize); + } else { + paged = this.filteredItems; + } + return { totalRows: this.filteredItems.length, rows: paged }; + } + + protected getRowDiffs(rows: TData[], newRows: TData[]) { + let item: any; + let r; + let eitherIsNonData; + const diff: number[] = []; + let from = 0; + let to = Math.max(newRows.length, rows.length); + + if (this.refreshHints?.ignoreDiffsBefore) { + from = Math.max(0, + Math.min(newRows.length, this.refreshHints.ignoreDiffsBefore)); + } + + if (this.refreshHints?.ignoreDiffsAfter) { + to = Math.min(newRows.length, + Math.max(0, this.refreshHints.ignoreDiffsAfter)); + } + + for (let i = from, rl = rows.length; i < to; i++) { + if (i >= rl) { + diff[diff.length] = i; + } else { + item = newRows[i]; + r = rows[i]; + + if (!item || (this.groupingInfos.length && (eitherIsNonData = ((item as SlickNonDataItem).__nonDataRow) || ((r as SlickNonDataItem).__nonDataRow)) && + (item as SlickGroup).__group !== (r as SlickGroup).__group || + (item as SlickGroup).__group && !(item as SlickGroup).equals(r as SlickGroup)) + || (eitherIsNonData && + // no good way to compare totals since they are arbitrary DTOs + // deep object comparison is pretty expensive + // always considering them 'dirty' seems easier for the time being + ((item as SlickGroupTotals).__groupTotals || (r as SlickGroupTotals).__groupTotals)) + || item[this.idProperty as keyof TData] !== r[this.idProperty as keyof TData] + || (this.updated?.[item[this.idProperty as keyof TData]]) + ) { + diff[diff.length] = i; + } + } + } + return diff; + } + + protected recalc(_items: TData[]) { + this.rowsById = undefined; + + if (this.refreshHints.isFilterNarrowing !== this.prevRefreshHints.isFilterNarrowing || + this.refreshHints.isFilterExpanding !== this.prevRefreshHints.isFilterExpanding) { + this.filterCache = []; + } + + const filteredItems = this.getFilteredAndPagedItems(_items); + this.totalRows = filteredItems.totalRows; + let newRows: TData[] = filteredItems.rows; + + this.groups = []; + if (this.groupingInfos.length) { + this.groups = this.extractGroups(newRows); + if (this.groups.length) { + newRows = this.flattenGroupedRows(this.groups); + } + } + + const diff = this.getRowDiffs(this.rows, newRows as TData[]); + + this.rows = newRows as TData[]; + + return diff; + } + + refresh() { + if (this.suspend) { + return; + } + + const previousPagingInfo = Utils.extend(true, {}, this.getPagingInfo()); + + const countBefore = this.rows.length; + const totalRowsBefore = this.totalRows; + + let diff = this.recalc(this.items); // pass as direct refs to avoid closure perf hit + + // if the current page is no longer valid, go to last page and recalc + // we suffer a performance penalty here, but the main loop (recalc) remains highly optimized + if (this.pagesize && this.totalRows < this.pagenum * this.pagesize) { + this.pagenum = Math.max(0, Math.ceil(this.totalRows / this.pagesize) - 1); + diff = this.recalc(this.items); + } + + this.updated = null; + this.prevRefreshHints = this.refreshHints; + this.refreshHints = {}; + + if (totalRowsBefore !== this.totalRows) { + // use the previously saved paging info + if (this.onBeforePagingInfoChanged.notify(previousPagingInfo, null, this).getReturnValue() !== false) { + this.onPagingInfoChanged.notify(this.getPagingInfo(), null, this); + } + } + if (countBefore !== this.rows.length) { + this.onRowCountChanged.notify({ previous: countBefore, current: this.rows.length, itemCount: this.items.length, dataView: this, callingOnRowsChanged: (diff.length > 0) }, null, this); + } + if (diff.length > 0) { + this.onRowsChanged.notify({ rows: diff, itemCount: this.items.length, dataView: this, calledOnRowCountChanged: (countBefore !== this.rows.length) }, null, this); + } + if (countBefore !== this.rows.length || diff.length > 0) { + this.onRowsOrCountChanged.notify({ + rowsDiff: diff, previousRowCount: countBefore, currentRowCount: this.rows.length, itemCount: this.items.length, + rowCountChanged: countBefore !== this.rows.length, rowsChanged: diff.length > 0, dataView: this + }, null, this); + } + } + + /** + * Wires the grid and the DataView together to keep row selection tied to item ids. + * This is useful since, without it, the grid only knows about rows, so if the items + * move around, the same rows stay selected instead of the selection moving along + * with the items. + * + * NOTE: This doesn't work with cell selection model. + * + * @param {SlickGrid} grid - The grid to sync selection with. + * @param {Boolean} preserveHidden - Whether to keep selected items that go out of the + * view due to them getting filtered out. + * @param {Boolean} [preserveHiddenOnSelectionChange] - Whether to keep selected items + * that are currently out of the view (see preserveHidden) as selected when selection + * changes. + * @return {Event} An event that notifies when an internal list of selected row ids + * changes. This is useful since, in combination with the above two options, it allows + * access to the full list selected row ids, and not just the ones visible to the grid. + * @method syncGridSelection + */ + syncGridSelection(grid: SlickGrid, preserveHidden: boolean, preserveHiddenOnSelectionChange?: boolean) { + this._grid = grid; + let inHandler: boolean; + this.selectedRowIds = this.mapRowsToIds(grid.getSelectedRows()); + + /** @param {Array} rowIds */ + const setSelectedRowIds = (rowIds: DataIdType[] | false) => { + if (rowIds === false) { + this.selectedRowIds = []; + } else { + if (this.selectedRowIds!.sort().join(',') !== rowIds.sort().join(',')) { + this.selectedRowIds = rowIds; + } + } + }; + + const update = () => { + if ((this.selectedRowIds || []).length > 0 && !inHandler) { + inHandler = true; + const selectedRows = this.mapIdsToRows(this.selectedRowIds || []); + if (!preserveHidden) { + const selectedRowsChangedArgs = { + grid: this._grid, + ids: this.mapRowsToIds(selectedRows), + rows: selectedRows, + dataView: this + }; + this.preSelectedRowIdsChangeFn!(selectedRowsChangedArgs); + this.onSelectedRowIdsChanged.notify(Object.assign(selectedRowsChangedArgs, { + selectedRowIds: this.selectedRowIds, + filteredIds: this.getAllSelectedFilteredIds() as DataIdType[], + }), new SlickEventData(), this); + } + grid.setSelectedRows(selectedRows); + inHandler = false; + } + }; + + grid.onSelectedRowsChanged.subscribe((_e: Event, args: { rows: number[]; }) => { + if (!inHandler) { + const newSelectedRowIds = this.mapRowsToIds(args.rows); + const selectedRowsChangedArgs = { + grid: this._grid, + ids: newSelectedRowIds, + rows: args.rows, + added: true, + dataView: this + }; + this.preSelectedRowIdsChangeFn!(selectedRowsChangedArgs); + this.onSelectedRowIdsChanged.notify(Object.assign(selectedRowsChangedArgs, { + selectedRowIds: this.selectedRowIds, + filteredIds: this.getAllSelectedFilteredIds() as DataIdType[], + }), new SlickEventData(), this); + } + }); + + this.preSelectedRowIdsChangeFn = (args: { ids: DataIdType[]; added?: boolean; }) => { + if (!inHandler) { + inHandler = true; + const overwrite = (typeof args.added === typeof undefined); + + if (overwrite) { + setSelectedRowIds(args.ids); + } else { + let rowIds: DataIdType[]; + if (args.added) { + if (preserveHiddenOnSelectionChange && grid.getOptions().multiSelect) { + // find the ones that are hidden + const hiddenSelectedRowIds = this.selectedRowIds?.filter((id) => this.getRowById(id) === undefined); + // add the newly selected ones + rowIds = hiddenSelectedRowIds!.concat(args.ids); + } else { + rowIds = args.ids; + } + } else { + if (preserveHiddenOnSelectionChange && grid.getOptions().multiSelect) { + // remove rows whose id is on the list + rowIds = this.selectedRowIds!.filter((id) => args.ids.indexOf(id) === -1); + } else { + rowIds = []; + } + } + setSelectedRowIds(rowIds); + } + inHandler = false; + } + }; + + this.onRowsOrCountChanged.subscribe(update.bind(this)); + + return this.onSelectedRowIdsChanged; + } + + /** + * Get all selected IDs + * Note: when using Pagination it will also include hidden selections assuming `preserveHiddenOnSelectionChange` is set to true. + */ + getAllSelectedIds() { + return this.selectedRowIds; + } + + /** + * Get all selected filtered IDs (similar to "getAllSelectedIds" but only return filtered data) + * Note: when using Pagination it will also include hidden selections assuming `preserveHiddenOnSelectionChange` is set to true. + */ + getAllSelectedFilteredIds() { + return this.getAllSelectedFilteredItems().map((item) => item[this.idProperty as keyof TData]); + } + + /** + * Set current row selected IDs array (regardless of Pagination) + * NOTE: This will NOT change the selection in the grid, if you need to do that then you still need to call + * "grid.setSelectedRows(rows)" + * @param {Array} selectedIds - list of IDs which have been selected for this action + * @param {Object} options + * - `isRowBeingAdded`: defaults to true, are the new selected IDs being added (or removed) as new row selections + * - `shouldTriggerEvent`: defaults to true, should we trigger `onSelectedRowIdsChanged` event + * - `applyRowSelectionToGrid`: defaults to true, should we apply the row selections to the grid in the UI + */ + setSelectedIds(selectedIds: Array, options?: Partial<{ isRowBeingAdded: boolean; shouldTriggerEvent: boolean; applyRowSelectionToGrid: boolean; }>) { + let isRowBeingAdded = options?.isRowBeingAdded; + const shouldTriggerEvent = options?.shouldTriggerEvent; + const applyRowSelectionToGrid = options?.applyRowSelectionToGrid; + + if (isRowBeingAdded !== false) { + isRowBeingAdded = true; + } + const selectedRows = this.mapIdsToRows(selectedIds); + const selectedRowsChangedArgs = { + grid: this._grid, + ids: selectedIds, + rows: selectedRows, + added: isRowBeingAdded, + dataView: this + }; + this.preSelectedRowIdsChangeFn?.(selectedRowsChangedArgs); + + if (shouldTriggerEvent !== false) { + this.onSelectedRowIdsChanged.notify(Object.assign(selectedRowsChangedArgs, { + selectedRowIds: this.selectedRowIds, + filteredIds: this.getAllSelectedFilteredIds() as DataIdType[], + }), new SlickEventData(), this); + } + + // should we also apply the row selection in to the grid (UI) as well? + if (applyRowSelectionToGrid !== false && this._grid) { + this._grid.setSelectedRows(selectedRows); + } + } + + /** + * Get all selected dataContext items + * Note: when using Pagination it will also include hidden selections assuming `preserveHiddenOnSelectionChange` is set to true. + */ + getAllSelectedItems() { + const selectedData: TData[] = []; + const selectedIds = this.getAllSelectedIds(); + selectedIds!.forEach((id) => { + selectedData.push(this.getItemById(id)); + }); + return selectedData as T[]; + } + + /** + * Get all selected filtered dataContext items (similar to "getAllSelectedItems" but only return filtered data) + * Note: when using Pagination it will also include hidden selections assuming `preserveHiddenOnSelectionChange` is set to true. + */ + getAllSelectedFilteredItems() { + if (!Array.isArray(this.selectedRowIds)) { + return []; + } + + const intersection = this.filteredItems.filter((a) => this.selectedRowIds!.some((b) => a[this.idProperty as keyof TData] === b)); + return (intersection || []) as T[]; + } + + syncGridCellCssStyles(grid: SlickGrid, key: string) { + let hashById: any; + let inHandler: boolean; + + const storeCellCssStyles = (hash: CssStyleHash) => { + hashById = {}; + for (const row in hash) { + if (hash) { + const id = this.rows[row as any][this.idProperty as keyof TData]; + hashById[id] = hash[row]; + } + } + }; + + // since this method can be called after the cell styles have been set, + // get the existing ones right away + storeCellCssStyles(grid.getCellCssStyles(key)); + + const update = () => { + if (hashById) { + inHandler = true; + this.ensureRowsByIdCache(); + const newHash: CssStyleHash = {}; + for (const id in hashById) { + if (hashById) { + const row = this.rowsById?.[id]; + if (isDefined(row)) { + newHash[row] = hashById[id]; + } + } + } + grid.setCellCssStyles(key, newHash); + inHandler = false; + } + }; + + grid.onCellCssStylesChanged.subscribe((_e: Event, args: any) => { + if (inHandler) { return; } + if (key !== args.key) { return; } + if (args.hash) { + storeCellCssStyles(args.hash); + } else { + grid.onCellCssStylesChanged.unsubscribe(); + this.onRowsOrCountChanged.unsubscribe(update); + } + }); + + this.onRowsOrCountChanged.subscribe(update.bind(this)); + } +} diff --git a/packages/common/src/core/slick.grid.ts b/packages/common/src/core/slick.grid.ts new file mode 100644 index 000000000..79f356a8f --- /dev/null +++ b/packages/common/src/core/slick.grid.ts @@ -0,0 +1,6667 @@ +/* eslint-disable no-cond-assign */ +// @ts-ignore +import SortableInstance, * as Sortable_ from 'sortablejs'; +const Sortable = ((Sortable_ as any)?.['default'] ?? Sortable_); // patch for rollup +import moment from 'moment-mini'; +import { BindingEventService } from '../services/bindingEvent.service'; + +import { + ColAutosizeMode, + GlobalEditorLock, + GridAutosizeColsMode, + isDefined, + keyCode, + preClickClassName, + RowSelectionMode, + type SlickEditorLock, + SlickEvent, + SlickEventData, + SlickRange, + Utils, + ValueFilterMode, + WidthEvalMode, +} from './slick.core'; +import { Draggable, MouseWheel, Resizable } from './slick.interactions'; +import { SelectionModel } from '../enums/index'; +import { + CellViewportRange, + Column, + ColumnSort, + CSSStyleDeclarationWritable, + CssStyleHash, + CustomDataView, + DOMEvent, + DOMMouseOrTouchEvent, + DragPosition, + DragRowMove, + EditController, + Editor, + Formatter, + FormatterOverrideCallback, + FormatterResultObject, + InteractionBase, + ItemMetadata, + GridOption as BaseGridOption, + MultiColumnSort, + OnActivateChangedOptionsEventArgs, + OnActiveCellChangedEventArgs, + OnAddNewRowEventArgs, + OnAutosizeColumnsEventArgs, + OnBeforeAppendCellEventArgs, + OnBeforeCellEditorDestroyEventArgs, + OnBeforeColumnsResizeEventArgs, + OnBeforeEditCellEventArgs, + OnBeforeFooterRowCellDestroyEventArgs, + OnBeforeHeaderCellDestroyEventArgs, + OnBeforeHeaderRowCellDestroyEventArgs, + OnBeforeSetColumnsEventArgs, + OnBeforeUpdateColumnsEventArgs, + OnCellChangeEventArgs, + OnCellCssStylesChangedEventArgs, + OnClickEventArgs, + OnColumnsDragEventArgs, + OnColumnsReorderedEventArgs, + OnColumnsResizedEventArgs, + OnColumnsResizeDblClickEventArgs, + OnCompositeEditorChangeEventArgs, + OnDblClickEventArgs, + OnFooterRowCellRenderedEventArgs, + OnFooterContextMenuEventArgs, + OnHeaderCellRenderedEventArgs, + OnFooterClickEventArgs, + OnHeaderClickEventArgs, + OnHeaderContextMenuEventArgs, + OnHeaderMouseEventArgs, + OnHeaderRowCellRenderedEventArgs, + OnKeyDownEventArgs, + OnRenderedEventArgs, + OnScrollEventArgs, + OnSelectedRowsChangedEventArgs, + OnSetOptionsEventArgs, + OnValidationErrorEventArgs, + PagingInfo, + RowInfo, + SingleColumnSort, + SlickPlugin, + SlickGridEventData, + SlickGridModel, +} from '../interfaces'; +import { AutoSize } from './models/autoSize.interface'; + +/** + * @license + * (c) 2009-present Michael Leibman + * michael{dot}leibman{at}gmail{dot}com + * http://github.com/mleibman/slickgrid + * + * Distributed under MIT license. + * All rights reserved. + * + * SlickGrid v5.1.0 + * + * NOTES: + * Cell/row DOM manipulations are done directly bypassing JS DOM manipulation methods. + * This increases the speed dramatically, + * but can only be done safely because there are no event handlers + * or data associated with any cell/row DOM nodes. Cell editors must make sure they implement .destroy() + * and do proper cleanup. + */ + +// SlickGrid class implementation (available as SlickGrid) + +interface RowCaching { + rowNode: HTMLElement[] | null, + cellColSpans: Array; + cellNodesByColumnIdx: HTMLElement[]; + cellRenderQueue: any[]; +} + +export class SlickGrid = Column, O extends BaseGridOption = BaseGridOption> { + // Public API + slickGridVersion = '5.1.0'; + + /** optional grid state clientId */ + cid = ''; + + // Events + onActiveCellChanged = new SlickEvent(); + onActiveCellPositionChanged = new SlickEvent(); + onAddNewRow = new SlickEvent(); + onAutosizeColumns = new SlickEvent(); + onBeforeAppendCell = new SlickEvent(); + onBeforeCellEditorDestroy = new SlickEvent(); + onBeforeColumnsResize = new SlickEvent(); + onBeforeDestroy = new SlickEvent(); + onBeforeEditCell = new SlickEvent(); + onBeforeFooterRowCellDestroy = new SlickEvent(); + onBeforeHeaderCellDestroy = new SlickEvent(); + onBeforeHeaderRowCellDestroy = new SlickEvent(); + onBeforeSetColumns = new SlickEvent(); + onBeforeSort = new SlickEvent(); + onBeforeUpdateColumns = new SlickEvent(); + onCellChange = new SlickEvent(); + onCellCssStylesChanged = new SlickEvent(); + onClick = new SlickEvent(); + onColumnsReordered = new SlickEvent(); + onColumnsDrag = new SlickEvent(); + onColumnsResized = new SlickEvent(); + onColumnsResizeDblClick = new SlickEvent(); + onCompositeEditorChange = new SlickEvent(); + onContextMenu = new SlickEvent(); + onDrag = new SlickEvent(); + onDblClick = new SlickEvent(); + onDragInit = new SlickEvent(); + onDragStart = new SlickEvent(); + onDragEnd = new SlickEvent(); + onFooterClick = new SlickEvent(); + onFooterContextMenu = new SlickEvent(); + onFooterRowCellRendered = new SlickEvent(); + onHeaderCellRendered = new SlickEvent(); + onHeaderClick = new SlickEvent(); + onHeaderContextMenu = new SlickEvent(); + onHeaderMouseEnter = new SlickEvent(); + onHeaderMouseLeave = new SlickEvent(); + onHeaderRowCellRendered = new SlickEvent(); + onHeaderRowMouseEnter = new SlickEvent(); + onHeaderRowMouseLeave = new SlickEvent(); + onKeyDown = new SlickEvent(); + onMouseEnter = new SlickEvent(); + onMouseLeave = new SlickEvent(); + onRendered = new SlickEvent(); + onScroll = new SlickEvent(); + onSelectedRowsChanged = new SlickEvent(); + onSetOptions = new SlickEvent(); + onActivateChangedOptions = new SlickEvent(); + onSort = new SlickEvent(); + onValidationError = new SlickEvent(); + onViewportChanged = new SlickEvent(); + + // --- + // protected variables + + // shared across all grids on the page + protected scrollbarDimensions?: { height: number; width: number; }; + protected maxSupportedCssHeight!: number; // browser's breaking point + + protected canvas: HTMLCanvasElement | null = null; + protected canvas_context: CanvasRenderingContext2D | null = null; + + // settings + protected _options!: O; + protected _defaults: BaseGridOption = { + alwaysShowVerticalScroll: false, + alwaysAllowHorizontalScroll: false, + explicitInitialization: false, + rowHeight: 25, + defaultColumnWidth: 80, + enableAddRow: false, + leaveSpaceForNewRows: false, + editable: false, + autoEdit: true, + autoEditNewRow: true, + autoCommitEdit: false, + suppressActiveCellChangeOnEdit: false, + enableCellNavigation: true, + enableColumnReorder: true, + asyncEditorLoading: false, + asyncEditorLoadDelay: 100, + forceFitColumns: false, + enableAsyncPostRender: false, + asyncPostRenderDelay: 50, + enableAsyncPostRenderCleanup: false, + asyncPostRenderCleanupDelay: 40, + auto: false, + editorLock: GlobalEditorLock, + showColumnHeader: true, + showHeaderRow: false, + headerRowHeight: 25, + createFooterRow: false, + showFooterRow: false, + footerRowHeight: 25, + createPreHeaderPanel: false, + showPreHeaderPanel: false, + preHeaderPanelHeight: 25, + showTopPanel: false, + topPanelHeight: 25, + formatterFactory: null, + editorFactory: null, + cellFlashingCssClass: 'flashing', + selectedCellCssClass: 'selected', + multiSelect: true, + enableTextSelectionOnCells: false, + dataItemColumnValueExtractor: null, + frozenBottom: false, + frozenColumn: -1, + frozenRow: -1, + frozenRightViewportMinWidth: 100, + fullWidthRows: false, + multiColumnSort: false, + numberedMultiColumnSort: false, + tristateMultiColumnSort: false, + sortColNumberInSeparateSpan: false, + defaultFormatter: this.defaultFormatter, + forceSyncScrolling: false, + addNewRowCssClass: 'new-row', + preserveCopiedSelectionOnPaste: false, + showCellSelection: true, + viewportClass: undefined, + minRowBuffer: 3, + emulatePagingWhenScrolling: true, // when scrolling off bottom of viewport, place new row at top of viewport + editorCellNavOnLRKeys: false, + enableMouseWheelScrollHandler: true, + doPaging: true, + autosizeColsMode: GridAutosizeColsMode.LegacyOff, + autosizeColPaddingPx: 4, + scrollRenderThrottling: 50, + autosizeTextAvgToMWidthRatio: 0.75, + viewportSwitchToScrollModeWidthPercent: undefined, + viewportMinWidthPx: undefined, + viewportMaxWidthPx: undefined, + suppressCssChangesOnHiddenInit: false, + ffMaxSupportedCssHeight: 6000000, + maxSupportedCssHeight: 1000000000, + sanitizer: undefined, // sanitize function, built in basic sanitizer is: Slick.RegexSanitizer(dirtyHtml) + logSanitizedHtml: false, // log to console when sanitised - recommend true for testing of dev and production + mixinDefaults: true + }; + + protected _columnDefaults = { + name: '', + resizable: true, + sortable: false, + minWidth: 30, + maxWidth: undefined, + rerenderOnResize: false, + headerCssClass: null, + defaultSortAsc: true, + focusable: true, + selectable: true, + hidden: false + } as Partial; + + protected _columnAutosizeDefaults: AutoSize = { + ignoreHeaderText: false, + colValueArray: undefined, + allowAddlPercent: undefined, + formatterOverride: undefined, + autosizeMode: ColAutosizeMode.ContentIntelligent, + rowSelectionModeOnInit: undefined, + rowSelectionMode: RowSelectionMode.FirstNRows, + rowSelectionCount: 100, + valueFilterMode: ValueFilterMode.None, + widthEvalMode: WidthEvalMode.Auto, + sizeToRemaining: undefined, + widthPx: undefined, + contentSizePx: 0, + headerWidthPx: 0, + colDataTypeOf: undefined + }; + + // scroller + protected th!: number; // virtual height + protected h!: number; // real scrollable height + protected ph!: number; // page height + protected n!: number; // number of pages + protected cj!: number; // "jumpiness" coefficient + + protected page = 0; // current page + protected offset = 0; // current page offset + protected vScrollDir = 1; + protected _bindingEventService = new BindingEventService(); + protected initialized = false; + protected _container!: HTMLElement; + protected uid = `slickgrid_${Math.round(1000000 * Math.random())}`; + protected _focusSink!: HTMLDivElement; + protected _focusSink2!: HTMLDivElement; + protected _groupHeaders: HTMLDivElement[] = []; + protected _headerScroller: HTMLDivElement[] = []; + protected _headers: HTMLDivElement[] = []; + protected _headerRows!: HTMLDivElement[]; + protected _headerRowScroller!: HTMLDivElement[]; + protected _headerRowSpacerL!: HTMLDivElement; + protected _headerRowSpacerR!: HTMLDivElement; + protected _footerRow!: HTMLDivElement[]; + protected _footerRowScroller!: HTMLDivElement[]; + protected _footerRowSpacerL!: HTMLDivElement; + protected _footerRowSpacerR!: HTMLDivElement; + protected _preHeaderPanel!: HTMLDivElement; + protected _preHeaderPanelScroller!: HTMLDivElement; + protected _preHeaderPanelSpacer!: HTMLDivElement; + protected _preHeaderPanelR!: HTMLDivElement; + protected _preHeaderPanelScrollerR!: HTMLDivElement; + protected _preHeaderPanelSpacerR!: HTMLDivElement; + protected _topPanelScrollers!: HTMLDivElement[]; + protected _topPanels!: HTMLDivElement[]; + protected _viewport!: HTMLDivElement[]; + protected _canvas!: HTMLDivElement[]; + protected _style: any; + protected _boundAncestors: HTMLElement[] = []; + protected stylesheet?: { cssRules: Array<{ selectorText: string; }>; rules: Array<{ selectorText: string; }>; } | null; + protected columnCssRulesL?: Array<{ selectorText: string; }>; + protected columnCssRulesR?: Array<{ selectorText: string; }>; + protected viewportH = 0; + protected viewportW = 0; + protected canvasWidth = 0; + protected canvasWidthL = 0; + protected canvasWidthR = 0; + protected headersWidth = 0; + protected headersWidthL = 0; + protected headersWidthR = 0; + protected viewportHasHScroll = false; + protected viewportHasVScroll = false; + protected headerColumnWidthDiff = 0; + protected headerColumnHeightDiff = 0; // border+padding + protected cellWidthDiff = 0; + protected cellHeightDiff = 0; + protected absoluteColumnMinWidth!: number; + protected hasFrozenRows = false; + protected frozenRowsHeight = 0; + protected actualFrozenRow = -1; + protected paneTopH = 0; + protected paneBottomH = 0; + protected viewportTopH = 0; + protected viewportBottomH = 0; + protected topPanelH = 0; + protected headerRowH = 0; + protected footerRowH = 0; + + protected tabbingDirection = 1; + protected _activeCanvasNode!: HTMLDivElement; + protected _activeViewportNode!: HTMLDivElement; + protected activePosX!: number; + protected activeRow!: number; + protected activeCell!: number; + protected activeCellNode: HTMLDivElement | null = null; + protected currentEditor: Editor | null = null; + protected serializedEditorValue: any; + protected editController?: EditController; + + protected rowsCache: Array = {} as any; + protected renderedRows = 0; + protected numVisibleRows = 0; + protected prevScrollTop = 0; + protected scrollTop = 0; + protected lastRenderedScrollTop = 0; + protected lastRenderedScrollLeft = 0; + protected prevScrollLeft = 0; + protected scrollLeft = 0; + + protected selectionModel?: SelectionModel; + protected selectedRows: number[] = []; + + protected plugins: SlickPlugin[] = []; + protected cellCssClasses: CssStyleHash = {}; + + protected columnsById: Record = {}; + protected sortColumns: ColumnSort[] = []; + protected columnPosLeft: number[] = []; + protected columnPosRight: number[] = []; + + protected pagingActive = false; + protected pagingIsLastPage = false; + + protected scrollThrottle!: { enqueue: () => void; dequeue: () => void; }; + + // async call handles + protected h_editorLoader: any = null; + protected h_render = null; + protected h_postrender: any = null; + protected h_postrenderCleanup: any = null; + protected postProcessedRows: any = {}; + protected postProcessToRow: number = null as any; + protected postProcessFromRow: number = null as any; + protected postProcessedCleanupQueue: Array<{ + actionType: string; + groupId: number; + node: HTMLElement | HTMLElement[]; + columnIdx?: number; + rowIdx?: number; + }> = []; + protected postProcessgroupId = 0; + + // perf counters + protected counter_rows_rendered = 0; + protected counter_rows_removed = 0; + + protected _paneHeaderL!: HTMLDivElement; + protected _paneHeaderR!: HTMLDivElement; + protected _paneTopL!: HTMLDivElement; + protected _paneTopR!: HTMLDivElement; + protected _paneBottomL!: HTMLDivElement; + protected _paneBottomR!: HTMLDivElement; + protected _headerScrollerL!: HTMLDivElement; + protected _headerScrollerR!: HTMLDivElement; + protected _headerL!: HTMLDivElement; + protected _headerR!: HTMLDivElement; + protected _groupHeadersL!: HTMLDivElement; + protected _groupHeadersR!: HTMLDivElement; + protected _headerRowScrollerL!: HTMLDivElement; + protected _headerRowScrollerR!: HTMLDivElement; + protected _footerRowScrollerL!: HTMLDivElement; + protected _footerRowScrollerR!: HTMLDivElement; + protected _headerRowL!: HTMLDivElement; + protected _headerRowR!: HTMLDivElement; + protected _footerRowL!: HTMLDivElement; + protected _footerRowR!: HTMLDivElement; + protected _topPanelScrollerL!: HTMLDivElement; + protected _topPanelScrollerR!: HTMLDivElement; + protected _topPanelL!: HTMLDivElement; + protected _topPanelR!: HTMLDivElement; + protected _viewportTopL!: HTMLDivElement; + protected _viewportTopR!: HTMLDivElement; + protected _viewportBottomL!: HTMLDivElement; + protected _viewportBottomR!: HTMLDivElement; + protected _canvasTopL!: HTMLDivElement; + protected _canvasTopR!: HTMLDivElement; + protected _canvasBottomL!: HTMLDivElement; + protected _canvasBottomR!: HTMLDivElement; + protected _viewportScrollContainerX!: HTMLDivElement; + protected _viewportScrollContainerY!: HTMLDivElement; + protected _headerScrollContainer!: HTMLDivElement; + protected _headerRowScrollContainer!: HTMLDivElement; + protected _footerRowScrollContainer!: HTMLDivElement; + + // store css attributes if display:none is active in container or parent + protected cssShow = { position: 'absolute', visibility: 'hidden', display: 'block' }; + protected _hiddenParents: HTMLElement[] = []; + protected oldProps: Array> = []; + protected enforceFrozenRowHeightRecalc = false; + protected columnResizeDragging = false; + protected slickDraggableInstance: InteractionBase | null = null; + protected slickMouseWheelInstances: Array = []; + protected slickResizableInstances: Array = []; + protected sortableSideLeftInstance?: SortableInstance; + protected sortableSideRightInstance?: SortableInstance; + protected logMessageCount = 0; + protected logMessageMaxCount = 30; + + /** + * Creates a new instance of the grid. + * @class SlickGrid + * @constructor + * @param {Node} container - Container node to create the grid in. + * @param {Array|Object} data - An array of objects for databinding. + * @param {Array} columns - An array of column definitions. + * @param {Object} [options] - Grid this._options. + **/ + constructor(protected container: HTMLElement | string, protected data: CustomDataView | TData[], protected columns: C[], protected options: Partial) { + this.initialize(); + } + + // Initialization + + /** Initializes the grid. */ + init() { + this.finishInitialization(); + } + + protected initialize() { + if (typeof this.container === 'string') { + this._container = document.querySelector(this.container) as HTMLDivElement; + } else { + this._container = this.container; + } + + if (!this._container) { + throw new Error(`SlickGrid requires a valid container, ${this.container} does not exist in the DOM.`); + } + + // calculate these only once and share between grid instances + if (this.options.mixinDefaults) { + if (!this.options) { this.options = {}; } + Utils.applyDefaults(this.options, this._defaults); + } else { + this._options = Utils.extend(true, {}, this._defaults, this.options); + } + this.scrollThrottle = this.actionThrottle(this.render.bind(this), this._options.scrollRenderThrottling as number); + this.maxSupportedCssHeight = this.maxSupportedCssHeight || this.getMaxSupportedCssHeight(); + this.validateAndEnforceOptions(); + this._columnDefaults.width = this._options.defaultColumnWidth; + + if (!this._options.suppressCssChangesOnHiddenInit) { + this.cacheCssForHiddenInit(); + } + + this.updateColumnProps(); + + // validate loaded JavaScript modules against requested options + if (this._options.enableColumnReorder && (!Sortable || !Sortable.create)) { + throw new Error('SlickGrid requires Sortable.js module to be loaded'); + } + + this.editController = { + commitCurrentEdit: this.commitCurrentEdit.bind(this), + cancelCurrentEdit: this.cancelCurrentEdit.bind(this), + }; + + Utils.emptyElement(this._container); + this._container.style.overflow = 'hidden'; + this._container.style.outline = String(0); + this._container.classList.add(this.uid); + this._container.classList.add('ui-widget'); + + const containerStyles = window.getComputedStyle(this._container); + if (!(/relative|absolute|fixed/).test(containerStyles.position)) { + this._container.style.position = 'relative'; + } + + this._focusSink = Utils.createDomElement('div', { tabIndex: 0, style: { position: 'fixed', width: '0px', height: '0px', top: '0px', left: '0px', outline: '0px' } }, this._container); + + // Containers used for scrolling frozen columns and rows + this._paneHeaderL = Utils.createDomElement('div', { className: 'slick-pane slick-pane-header slick-pane-left', tabIndex: 0 }, this._container); + this._paneHeaderR = Utils.createDomElement('div', { className: 'slick-pane slick-pane-header slick-pane-right', tabIndex: 0 }, this._container); + this._paneTopL = Utils.createDomElement('div', { className: 'slick-pane slick-pane-top slick-pane-left', tabIndex: 0 }, this._container); + this._paneTopR = Utils.createDomElement('div', { className: 'slick-pane slick-pane-top slick-pane-right', tabIndex: 0 }, this._container); + this._paneBottomL = Utils.createDomElement('div', { className: 'slick-pane slick-pane-bottom slick-pane-left', tabIndex: 0 }, this._container); + this._paneBottomR = Utils.createDomElement('div', { className: 'slick-pane slick-pane-bottom slick-pane-right', tabIndex: 0 }, this._container); + + if (this._options.createPreHeaderPanel) { + this._preHeaderPanelScroller = Utils.createDomElement('div', { className: 'slick-preheader-panel ui-state-default slick-state-default', style: { overflow: 'hidden', position: 'relative' } }, this._paneHeaderL); + this._preHeaderPanelScroller.appendChild(document.createElement('div')); + this._preHeaderPanel = Utils.createDomElement('div', null, this._preHeaderPanelScroller); + this._preHeaderPanelSpacer = Utils.createDomElement('div', { style: { display: 'block', height: '1px', position: 'absolute', top: '0px', left: '0px' } }, this._preHeaderPanelScroller); + + this._preHeaderPanelScrollerR = Utils.createDomElement('div', { className: 'slick-preheader-panel ui-state-default slick-state-default', style: { overflow: 'hidden', position: 'relative' } }, this._paneHeaderR); + this._preHeaderPanelR = Utils.createDomElement('div', null, this._preHeaderPanelScrollerR); + this._preHeaderPanelSpacerR = Utils.createDomElement('div', { style: { display: 'block', height: '1px', position: 'absolute', top: '0px', left: '0px' } }, this._preHeaderPanelScrollerR); + + if (!this._options.showPreHeaderPanel) { + Utils.hide(this._preHeaderPanelScroller); + Utils.hide(this._preHeaderPanelScrollerR); + } + } + + // Append the header scroller containers + this._headerScrollerL = Utils.createDomElement('div', { className: 'slick-header ui-state-default slick-state-default slick-header-left' }, this._paneHeaderL); + this._headerScrollerR = Utils.createDomElement('div', { className: 'slick-header ui-state-default slick-state-default slick-header-right' }, this._paneHeaderR); + + // Cache the header scroller containers + this._headerScroller.push(this._headerScrollerL); + this._headerScroller.push(this._headerScrollerR); + + // Append the columnn containers to the headers + this._headerL = Utils.createDomElement('div', { className: 'slick-header-columns slick-header-columns-left', style: { left: '-1000px' } }, this._headerScrollerL); + this._headerR = Utils.createDomElement('div', { className: 'slick-header-columns slick-header-columns-right', style: { left: '-1000px' } }, this._headerScrollerR); + + // Cache the header columns + this._headers = [this._headerL, this._headerR]; + + this._headerRowScrollerL = Utils.createDomElement('div', { className: 'slick-headerrow ui-state-default slick-state-default' }, this._paneTopL); + this._headerRowScrollerR = Utils.createDomElement('div', { className: 'slick-headerrow ui-state-default slick-state-default' }, this._paneTopR); + + this._headerRowScroller = [this._headerRowScrollerL, this._headerRowScrollerR]; + + this._headerRowSpacerL = Utils.createDomElement('div', { style: { display: 'block', height: '1px', position: 'absolute', top: '0px', left: '0px' } }, this._headerRowScrollerL); + this._headerRowSpacerR = Utils.createDomElement('div', { style: { display: 'block', height: '1px', position: 'absolute', top: '0px', left: '0px' } }, this._headerRowScrollerR); + + this._headerRowL = Utils.createDomElement('div', { className: 'slick-headerrow-columns slick-headerrow-columns-left' }, this._headerRowScrollerL); + this._headerRowR = Utils.createDomElement('div', { className: 'slick-headerrow-columns slick-headerrow-columns-right' }, this._headerRowScrollerR); + + this._headerRows = [this._headerRowL, this._headerRowR]; + + // Append the top panel scroller + this._topPanelScrollerL = Utils.createDomElement('div', { className: 'slick-top-panel-scroller ui-state-default slick-state-default' }, this._paneTopL); + this._topPanelScrollerR = Utils.createDomElement('div', { className: 'slick-top-panel-scroller ui-state-default slick-state-default' }, this._paneTopR); + + this._topPanelScrollers = [this._topPanelScrollerL, this._topPanelScrollerR]; + + // Append the top panel + this._topPanelL = Utils.createDomElement('div', { className: 'slick-top-panel', style: { width: '10000px' } }, this._topPanelScrollerL); + this._topPanelR = Utils.createDomElement('div', { className: 'slick-top-panel', style: { width: '10000px' } }, this._topPanelScrollerR); + + this._topPanels = [this._topPanelL, this._topPanelR]; + + if (!this._options.showColumnHeader) { + this._headerScroller.forEach((el) => { + Utils.hide(el); + }); + } + + if (!this._options.showTopPanel) { + this._topPanelScrollers.forEach((scroller) => { + Utils.hide(scroller); + }); + } + + if (!this._options.showHeaderRow) { + this._headerRowScroller.forEach((scroller) => { + Utils.hide(scroller); + }); + } + + // Append the viewport containers + this._viewportTopL = Utils.createDomElement('div', { className: 'slick-viewport slick-viewport-top slick-viewport-left', tabIndex: 0 }, this._paneTopL); + this._viewportTopR = Utils.createDomElement('div', { className: 'slick-viewport slick-viewport-top slick-viewport-right', tabIndex: 0 }, this._paneTopR); + this._viewportBottomL = Utils.createDomElement('div', { className: 'slick-viewport slick-viewport-bottom slick-viewport-left', tabIndex: 0 }, this._paneBottomL); + this._viewportBottomR = Utils.createDomElement('div', { className: 'slick-viewport slick-viewport-bottom slick-viewport-right', tabIndex: 0 }, this._paneBottomR); + + // Cache the viewports + this._viewport = [this._viewportTopL, this._viewportTopR, this._viewportBottomL, this._viewportBottomR]; + if (this._options.viewportClass) { + this._viewport.forEach((view) => { + view.classList.add(...(this._options.viewportClass || '').split(' ')); + }); + } + + // Default the active viewport to the top left + this._activeViewportNode = this._viewportTopL; + + // Append the canvas containers + this._canvasTopL = Utils.createDomElement('div', { className: 'grid-canvas grid-canvas-top grid-canvas-left', tabIndex: 0 }, this._viewportTopL); + this._canvasTopR = Utils.createDomElement('div', { className: 'grid-canvas grid-canvas-top grid-canvas-right', tabIndex: 0 }, this._viewportTopR); + this._canvasBottomL = Utils.createDomElement('div', { className: 'grid-canvas grid-canvas-bottom grid-canvas-left', tabIndex: 0 }, this._viewportBottomL); + this._canvasBottomR = Utils.createDomElement('div', { className: 'grid-canvas grid-canvas-bottom grid-canvas-right', tabIndex: 0 }, this._viewportBottomR); + + // Cache the canvases + this._canvas = [this._canvasTopL, this._canvasTopR, this._canvasBottomL, this._canvasBottomR]; + + this.scrollbarDimensions = this.scrollbarDimensions || this.measureScrollbar(); + + // Default the active canvas to the top left + this._activeCanvasNode = this._canvasTopL; + + // pre-header + if (this._preHeaderPanelSpacer) { + Utils.width(this._preHeaderPanelSpacer, this.getCanvasWidth() + this.scrollbarDimensions.width); + } + + this._headers.forEach((el) => { + Utils.width(el, this.getHeadersWidth()); + }); + + Utils.width(this._headerRowSpacerL, this.getCanvasWidth() + this.scrollbarDimensions.width); + Utils.width(this._headerRowSpacerR, this.getCanvasWidth() + this.scrollbarDimensions.width); + + // footer Row + if (this._options.createFooterRow) { + this._footerRowScrollerR = Utils.createDomElement('div', { className: 'slick-footerrow ui-state-default slick-state-default' }, this._paneTopR); + this._footerRowScrollerL = Utils.createDomElement('div', { className: 'slick-footerrow ui-state-default slick-state-default' }, this._paneTopL); + + this._footerRowScroller = [this._footerRowScrollerL, this._footerRowScrollerR]; + + this._footerRowSpacerL = Utils.createDomElement('div', { style: { display: 'block', height: '1px', position: 'absolute', top: '0px', left: '0px' } }, this._footerRowScrollerL); + Utils.width(this._footerRowSpacerL, this.getCanvasWidth() + this.scrollbarDimensions.width); + this._footerRowSpacerR = Utils.createDomElement('div', { style: { display: 'block', height: '1px', position: 'absolute', top: '0px', left: '0px' } }, this._footerRowScrollerR); + Utils.width(this._footerRowSpacerR, this.getCanvasWidth() + this.scrollbarDimensions.width); + + this._footerRowL = Utils.createDomElement('div', { className: 'slick-footerrow-columns slick-footerrow-columns-left' }, this._footerRowScrollerL); + this._footerRowR = Utils.createDomElement('div', { className: 'slick-footerrow-columns slick-footerrow-columns-right' }, this._footerRowScrollerR); + + this._footerRow = [this._footerRowL, this._footerRowR]; + + if (!this._options.showFooterRow) { + this._footerRowScroller.forEach((scroller) => { + Utils.hide(scroller); + }); + } + } + + this._focusSink2 = this._focusSink.cloneNode(true) as HTMLDivElement; + this._container.appendChild(this._focusSink2); + + if (!this._options.explicitInitialization) { + this.finishInitialization(); + } + } + + protected finishInitialization() { + if (!this.initialized) { + this.initialized = true; + + this.getViewportWidth(); + this.getViewportHeight(); + + // header columns and cells may have different padding/border skewing width calculations (box-sizing, hello?) + // calculate the diff so we can set consistent sizes + this.measureCellPaddingAndBorder(); + + // for usability reasons, all text selection in SlickGrid is disabled + // with the exception of input and textarea elements (selection must + // be enabled there so that editors work as expected); note that + // selection in grid cells (grid body) is already unavailable in + // all browsers except IE + this.disableSelection(this._headers); // disable all text selection in header (including input and textarea) + + if (!this._options.enableTextSelectionOnCells) { + // disable text selection in grid cells except in input and textarea elements + // (this is IE-specific, because selectstart event will only fire in IE) + this._viewport.forEach((view) => { + this._bindingEventService.bind(view, 'selectstart', (event) => { + if (event.target instanceof HTMLInputElement || event.target instanceof HTMLTextAreaElement) { + return; + } + }); + }); + } + + this.setFrozenOptions(); + this.setPaneVisibility(); + this.setScroller(); + this.setOverflow(); + + this.updateColumnCaches(); + this.createColumnHeaders(); + this.createColumnFooter(); + this.setupColumnSort(); + this.createCssRules(); + this.resizeCanvas(); + this.bindAncestorScrollEvents(); + + this._bindingEventService.bind(this._container, 'resize', this.resizeCanvas.bind(this)); + this._viewport.forEach((view) => { + this._bindingEventService.bind(view, 'scroll', this.handleScroll.bind(this)); + }); + + if (this._options.enableMouseWheelScrollHandler) { + this._viewport.forEach((view) => { + this.slickMouseWheelInstances.push(MouseWheel({ + element: view, + onMouseWheel: this.handleMouseWheel.bind(this) + })); + }); + } + + this._headerScroller.forEach((el) => { + this._bindingEventService.bind(el, 'contextmenu', this.handleHeaderContextMenu.bind(this) as EventListener); + this._bindingEventService.bind(el, 'click', this.handleHeaderClick.bind(this) as EventListener); + }); + + this._headerRowScroller.forEach((scroller) => { + this._bindingEventService.bind(scroller, 'scroll', this.handleHeaderRowScroll.bind(this) as EventListener); + }); + + if (this._options.createFooterRow) { + this._footerRow.forEach((footer) => { + this._bindingEventService.bind(footer, 'contextmenu', this.handleFooterContextMenu.bind(this) as EventListener); + this._bindingEventService.bind(footer, 'click', this.handleFooterClick.bind(this) as EventListener); + }); + + this._footerRowScroller.forEach((scroller) => { + this._bindingEventService.bind(scroller, 'scroll', this.handleFooterRowScroll.bind(this) as EventListener); + }); + } + + if (this._options.createPreHeaderPanel) { + this._bindingEventService.bind(this._preHeaderPanelScroller, 'scroll', this.handlePreHeaderPanelScroll.bind(this) as EventListener); + } + + this._bindingEventService.bind(this._focusSink, 'keydown', this.handleKeyDown.bind(this) as EventListener); + this._bindingEventService.bind(this._focusSink2, 'keydown', this.handleKeyDown.bind(this) as EventListener); + + this._canvas.forEach((element) => { + this._bindingEventService.bind(element, 'keydown', this.handleKeyDown.bind(this) as EventListener); + this._bindingEventService.bind(element, 'click', this.handleClick.bind(this) as EventListener); + this._bindingEventService.bind(element, 'dblclick', this.handleDblClick.bind(this) as EventListener); + this._bindingEventService.bind(element, 'contextmenu', this.handleContextMenu.bind(this) as EventListener); + this._bindingEventService.bind(element, 'mouseover', this.handleCellMouseOver.bind(this) as EventListener); + this._bindingEventService.bind(element, 'mouseout', this.handleCellMouseOut.bind(this) as EventListener); + }); + + if (Draggable) { + this.slickDraggableInstance = Draggable({ + containerElement: this._container, + allowDragFrom: 'div.slick-cell', + onDragInit: this.handleDragInit.bind(this), + onDragStart: this.handleDragStart.bind(this), + onDrag: this.handleDrag.bind(this), + onDragEnd: this.handleDragEnd.bind(this) + }); + } + + if (!this._options.suppressCssChangesOnHiddenInit) { + this.restoreCssFromHiddenInit(); + } + } + } + + /** handles "display:none" on container or container parents, related to issue: https://github.com/6pac/SlickGrid/issues/568 */ + cacheCssForHiddenInit() { + this._hiddenParents = Utils.parents(this._container, ':hidden') as HTMLElement[]; + for (const el of this._hiddenParents) { + const old: Partial = {}; + for (const name in this.cssShow) { + if (this.cssShow) { + old[name as any] = el.style[name as 'position' | 'visibility' | 'display']; + el.style[name as any] = this.cssShow[name as 'position' | 'visibility' | 'display']; + } + } + this.oldProps.push(old); + } + } + + restoreCssFromHiddenInit() { + // finish handle display:none on container or container parents + // - put values back the way they were + let i = 0; + for (const el of this._hiddenParents) { + const old = this.oldProps[i++]; + for (const name in this.cssShow) { + if (this.cssShow) { + el.style[name as CSSStyleDeclarationWritable] = (old as any)[name]; + } + } + } + } + + protected hasFrozenColumns() { + return this._options.frozenColumn! > -1; + } + + /** Register an external Plugin */ + registerPlugin(plugin: T) { + this.plugins.unshift(plugin); + plugin.init(this as unknown as SlickGridModel); + } + + /** Unregister (destroy) an external Plugin */ + unregisterPlugin(plugin: SlickPlugin) { + for (let i = this.plugins.length; i >= 0; i--) { + if (this.plugins[i] === plugin) { + this.plugins[i]?.destroy(); + this.plugins.splice(i, 1); + break; + } + } + } + + /** Get a Plugin (addon) by its name */ + getPluginByName

    (name: string) { + for (let i = this.plugins.length - 1; i >= 0; i--) { + if (this.plugins[i]?.pluginName === name) { + return this.plugins[i] as P; + } + } + return undefined; + } + + /** + * Unregisters a current selection model and registers a new one. See the definition of SelectionModel for more information. + * @param {Object} selectionModel A SelectionModel. + */ + setSelectionModel(model: SelectionModel) { + if (this.selectionModel) { + this.selectionModel.onSelectedRangesChanged.unsubscribe(this.handleSelectedRangesChanged.bind(this)); + if (this.selectionModel.destroy) { + this.selectionModel.destroy(); + } + } + + this.selectionModel = model; + if (this.selectionModel) { + this.selectionModel.init(this as unknown as SlickGridModel); + this.selectionModel.onSelectedRangesChanged.subscribe(this.handleSelectedRangesChanged.bind(this)); + } + } + + /** Returns the current SelectionModel. See here for more information about SelectionModels. */ + getSelectionModel() { + return this.selectionModel; + } + + /** Get Grid Canvas Node DOM Element */ + getCanvasNode(columnIdOrIdx?: number | string, rowIndex?: number) { + return this._getContainerElement(this.getCanvases(), columnIdOrIdx, rowIndex) as HTMLDivElement; + } + + /** Get the canvas DOM element */ + getActiveCanvasNode(e?: Event | SlickEventData) { + if (e === undefined) { + return this._activeCanvasNode; + } + + if (e instanceof SlickEventData) { + e = e.getNativeEvent(); + } + + this._activeCanvasNode = (e as any)?.target.closest('.grid-canvas'); + return this._activeCanvasNode; + } + + /** Get the canvas DOM element */ + getCanvases() { + return this._canvas; + } + + /** Get the Viewport DOM node element */ + getViewportNode(columnIdOrIdx?: number | string, rowIndex?: number) { + return this._getContainerElement(this.getViewports(), columnIdOrIdx, rowIndex); + } + + /** Get all the Viewport node elements */ + getViewports() { + return this._viewport; + } + + getActiveViewportNode(e: Event | SlickEventData) { + this.setActiveViewportNode(e); + + return this._activeViewportNode; + } + + /** Sets an active viewport node */ + setActiveViewportNode(e: Event | SlickEventData) { + if (e instanceof SlickEventData) { + e = e.getNativeEvent(); + } + this._activeViewportNode = (e as any)?.target.closest('.slick-viewport'); + return this._activeViewportNode; + } + + protected _getContainerElement(targetContainers: HTMLElement[], columnIdOrIdx?: number | string, rowIndex?: number) { + if (!targetContainers) { return; } + if (!columnIdOrIdx) { columnIdOrIdx = 0; } + if (!rowIndex) { rowIndex = 0; } + + const idx = (typeof columnIdOrIdx === 'number' ? columnIdOrIdx : this.getColumnIndex(columnIdOrIdx)); + + const isBottomSide = this.hasFrozenRows && rowIndex >= this.actualFrozenRow + (this._options.frozenBottom ? 0 : 1); + const isRightSide = this.hasFrozenColumns() && idx > this._options.frozenColumn!; + + return targetContainers[(isBottomSide ? 2 : 0) + (isRightSide ? 1 : 0)]; + } + + protected measureScrollbar() { + let className = ''; + this._viewport.forEach(v => className += v.className); + const outerdiv = Utils.createDomElement('div', { className, style: { position: 'absolute', top: '-10000px', left: '-10000px', overflow: 'auto', width: '100px', height: '100px' } }, document.body); + const innerdiv = Utils.createDomElement('div', { style: { width: '200px', height: '200px', overflow: 'auto' } }, outerdiv); + const dim = { + width: outerdiv.offsetWidth - outerdiv.clientWidth, + height: outerdiv.offsetHeight - outerdiv.clientHeight + }; + innerdiv.remove(); + outerdiv.remove(); + return dim; + } + + /** Get the headers width in pixel */ + getHeadersWidth() { + this.headersWidth = this.headersWidthL = this.headersWidthR = 0; + const includeScrollbar = !this._options.autoHeight; + + let i = 0; + const ii = this.columns.length; + for (i = 0; i < ii; i++) { + if (!this.columns[i] || this.columns[i].hidden) { continue; } + + const width = this.columns[i].width; + + if ((this._options.frozenColumn!) > -1 && (i > this._options.frozenColumn!)) { + this.headersWidthR += width || 0; + } else { + this.headersWidthL += width || 0; + } + } + + if (includeScrollbar) { + if ((this._options.frozenColumn!) > -1 && (i > this._options.frozenColumn!)) { + this.headersWidthR += this.scrollbarDimensions?.width ?? 0; + } else { + this.headersWidthL += this.scrollbarDimensions?.width ?? 0; + } + } + + if (this.hasFrozenColumns()) { + this.headersWidthL = this.headersWidthL + 1000; + + this.headersWidthR = Math.max(this.headersWidthR, this.viewportW) + this.headersWidthL; + this.headersWidthR += this.scrollbarDimensions?.width ?? 0; + } else { + this.headersWidthL += this.scrollbarDimensions?.width ?? 0; + this.headersWidthL = Math.max(this.headersWidthL, this.viewportW) + 1000; + } + + this.headersWidth = this.headersWidthL + this.headersWidthR; + return Math.max(this.headersWidth, this.viewportW) + 1000; + } + + protected getHeadersWidthL() { + this.headersWidthL = 0; + + this.columns.forEach((column, i) => { + if (column.hidden) { return; } + + if (!((this._options.frozenColumn!) > -1 && (i > this._options.frozenColumn!))) { + this.headersWidthL += column.width || 0; + } + }); + + if (this.hasFrozenColumns()) { + this.headersWidthL += 1000; + } else { + this.headersWidthL += this.scrollbarDimensions?.width ?? 0; + this.headersWidthL = Math.max(this.headersWidthL, this.viewportW) + 1000; + } + + return this.headersWidthL; + } + + protected getHeadersWidthR() { + this.headersWidthR = 0; + + this.columns.forEach((column, i) => { + if (column.hidden) { return; } + if ((this._options.frozenColumn!) > -1 && (i > this._options.frozenColumn!)) { + this.headersWidthR += column.width || 0; + } + }); + + if (this.hasFrozenColumns()) { + this.headersWidthR = Math.max(this.headersWidthR, this.viewportW) + this.getHeadersWidthL(); + this.headersWidthR += this.scrollbarDimensions?.width ?? 0; + } + + return this.headersWidthR; + } + + /** Get the grid canvas width */ + getCanvasWidth(): number { + const availableWidth = this.viewportHasVScroll ? this.viewportW - (this.scrollbarDimensions?.width ?? 0) : this.viewportW; + let i = this.columns.length; + + this.canvasWidthL = this.canvasWidthR = 0; + + while (i--) { + if (!this.columns[i] || this.columns[i].hidden) { continue; } + + if (this.hasFrozenColumns() && (i > this._options.frozenColumn!)) { + this.canvasWidthR += this.columns[i].width || 0; + } else { + this.canvasWidthL += this.columns[i].width || 0; + } + } + let totalRowWidth = this.canvasWidthL + this.canvasWidthR; + if (this._options.fullWidthRows) { + const extraWidth = Math.max(totalRowWidth, availableWidth) - totalRowWidth; + if (extraWidth > 0) { + totalRowWidth += extraWidth; + if (this.hasFrozenColumns()) { + this.canvasWidthR += extraWidth; + } else { + this.canvasWidthL += extraWidth; + } + } + } + return totalRowWidth; + } + + protected updateCanvasWidth(forceColumnWidthsUpdate?: boolean) { + const oldCanvasWidth = this.canvasWidth; + const oldCanvasWidthL = this.canvasWidthL; + const oldCanvasWidthR = this.canvasWidthR; + this.canvasWidth = this.getCanvasWidth(); + + const widthChanged = this.canvasWidth !== oldCanvasWidth || this.canvasWidthL !== oldCanvasWidthL || this.canvasWidthR !== oldCanvasWidthR; + + if (widthChanged || this.hasFrozenColumns() || this.hasFrozenRows) { + Utils.width(this._canvasTopL, this.canvasWidthL); + + this.getHeadersWidth(); + + Utils.width(this._headerL, this.headersWidthL); + Utils.width(this._headerR, this.headersWidthR); + + if (this.hasFrozenColumns()) { + const cWidth = Utils.width(this._container) || 0; + if (cWidth > 0 && this.canvasWidthL > cWidth) { + throw new Error('[SlickGrid] Frozen columns cannot be wider than the actual grid container width. ' + + 'Make sure to have less columns freezed or make your grid container wider'); + } + Utils.width(this._canvasTopR, this.canvasWidthR); + + Utils.width(this._paneHeaderL, this.canvasWidthL); + Utils.setStyleSize(this._paneHeaderR, 'left', this.canvasWidthL); + Utils.setStyleSize(this._paneHeaderR, 'width', this.viewportW - this.canvasWidthL); + + Utils.width(this._paneTopL, this.canvasWidthL); + Utils.setStyleSize(this._paneTopR, 'left', this.canvasWidthL); + Utils.width(this._paneTopR, this.viewportW - this.canvasWidthL); + + Utils.width(this._headerRowScrollerL, this.canvasWidthL); + Utils.width(this._headerRowScrollerR, this.viewportW - this.canvasWidthL); + + Utils.width(this._headerRowL, this.canvasWidthL); + Utils.width(this._headerRowR, this.canvasWidthR); + + if (this._options.createFooterRow) { + Utils.width(this._footerRowScrollerL, this.canvasWidthL); + Utils.width(this._footerRowScrollerR, this.viewportW - this.canvasWidthL); + + Utils.width(this._footerRowL, this.canvasWidthL); + Utils.width(this._footerRowR, this.canvasWidthR); + } + if (this._options.createPreHeaderPanel) { + Utils.width(this._preHeaderPanel, this.canvasWidth); + } + Utils.width(this._viewportTopL, this.canvasWidthL); + Utils.width(this._viewportTopR, this.viewportW - this.canvasWidthL); + + if (this.hasFrozenRows) { + Utils.width(this._paneBottomL, this.canvasWidthL); + Utils.setStyleSize(this._paneBottomR, 'left', this.canvasWidthL); + + Utils.width(this._viewportBottomL, this.canvasWidthL); + Utils.width(this._viewportBottomR, this.viewportW - this.canvasWidthL); + + Utils.width(this._canvasBottomL, this.canvasWidthL); + Utils.width(this._canvasBottomR, this.canvasWidthR); + } + } else { + Utils.width(this._paneHeaderL, '100%'); + Utils.width(this._paneTopL, '100%'); + Utils.width(this._headerRowScrollerL, '100%'); + Utils.width(this._headerRowL, this.canvasWidth); + + if (this._options.createFooterRow) { + Utils.width(this._footerRowScrollerL, '100%'); + Utils.width(this._footerRowL, this.canvasWidth); + } + + if (this._options.createPreHeaderPanel) { + Utils.width(this._preHeaderPanel, this.canvasWidth); + } + Utils.width(this._viewportTopL, '100%'); + + if (this.hasFrozenRows) { + Utils.width(this._viewportBottomL, '100%'); + Utils.width(this._canvasBottomL, this.canvasWidthL); + } + } + } + + this.viewportHasHScroll = (this.canvasWidth >= this.viewportW - (this.scrollbarDimensions?.width ?? 0)); + + Utils.width(this._headerRowSpacerL, this.canvasWidth + (this.viewportHasVScroll ? (this.scrollbarDimensions?.width ?? 0) : 0)); + Utils.width(this._headerRowSpacerR, this.canvasWidth + (this.viewportHasVScroll ? (this.scrollbarDimensions?.width ?? 0) : 0)); + + if (this._options.createFooterRow) { + Utils.width(this._footerRowSpacerL, this.canvasWidth + (this.viewportHasVScroll ? (this.scrollbarDimensions?.width ?? 0) : 0)); + Utils.width(this._footerRowSpacerR, this.canvasWidth + (this.viewportHasVScroll ? (this.scrollbarDimensions?.width ?? 0) : 0)); + } + + if (widthChanged || forceColumnWidthsUpdate) { + this.applyColumnWidths(); + } + } + + protected disableSelection(target: HTMLElement[]) { + target.forEach((el) => { + el.setAttribute('unselectable', 'on'); + (el.style as any).mozUserSelect = 'none'; + this._bindingEventService.bind(el, 'selectstart', () => false); + }); + } + + protected getMaxSupportedCssHeight() { + let supportedHeight = 1000000; + // FF reports the height back but still renders blank after ~6M px + // let testUpTo = navigator.userAgent.toLowerCase().match(/firefox/) ? 6000000 : 1000000000; + const testUpTo = navigator.userAgent.toLowerCase().match(/firefox/) ? this._options.ffMaxSupportedCssHeight : this._options.maxSupportedCssHeight; + const div = Utils.createDomElement('div', { style: { display: 'hidden' } }, document.body); + + while (true) { + const test = supportedHeight * 2; + Utils.height(div, test); + const height = Utils.height(div); + + if (test > testUpTo! || height !== test) { + break; + } else { + supportedHeight = test; + } + } + + div.remove(); + return supportedHeight; + } + + /** Get grid unique identifier */ + getUID() { + return this.uid; + } + + /** Get Header Column Width Difference in pixel */ + getHeaderColumnWidthDiff() { + return this.headerColumnWidthDiff; + } + + /** Get scrollbar dimensions */ + getScrollbarDimensions() { + return this.scrollbarDimensions; + } + + /** Get the displayed scrollbar dimensions */ + getDisplayedScrollbarDimensions() { + return { + width: this.viewportHasVScroll ? (this.scrollbarDimensions?.width ?? 0) : 0, + height: this.viewportHasHScroll ? (this.scrollbarDimensions?.height ?? 0) : 0 + }; + } + + /** Get the absolute column minimum width */ + getAbsoluteColumnMinWidth(): number { + return this.absoluteColumnMinWidth; + } + + // TODO: this is static. need to handle page mutation. + protected bindAncestorScrollEvents() { + let elem: HTMLElement | null = (this.hasFrozenRows && !this._options.frozenBottom) ? this._canvasBottomL : this._canvasTopL; + while ((elem = elem!.parentNode as HTMLElement) !== document.body && elem) { + // bind to scroll containers only + if (elem === this._viewportTopL || elem.scrollWidth !== elem.clientWidth || elem.scrollHeight !== elem.clientHeight) { + this._boundAncestors.push(elem); + this._bindingEventService.bind(elem, 'scroll', this.handleActiveCellPositionChange.bind(this)); + } + } + } + + protected unbindAncestorScrollEvents() { + this._boundAncestors.forEach((ancestor) => { + this._bindingEventService.unbindByEventName(ancestor, 'scroll'); + }); + this._boundAncestors = []; + } + + /** + * Updates an existing column definition and a corresponding header DOM element with the new title and tooltip. + * @param {Number|String} columnId Column id. + * @param {String} [title] New column name. + * @param {String} [toolTip] New column tooltip. + */ + updateColumnHeader(columnId: number | string, title?: string, toolTip?: string) { + if (!this.initialized) { return; } + const idx = this.getColumnIndex(columnId); + if (!isDefined(idx)) { + return; + } + + const columnDef = this.columns[idx]; + const header: any = this.getColumnByIndex(idx); + if (header) { + if (title !== undefined) { + this.columns[idx].name = title; + } + if (toolTip !== undefined) { + this.columns[idx].toolTip = toolTip; + } + + this.trigger(this.onBeforeHeaderCellDestroy, { + node: header, + column: columnDef, + grid: this + }); + + header.setAttribute('title', toolTip || ''); + if (title !== undefined) { + header.children[0].innerHTML = this.sanitizeHtmlString(title); + } + + this.trigger(this.onHeaderCellRendered, { + node: header, + column: columnDef, + grid: this + }); + } + } + + /** + * Get the Header DOM element + * @param {C} columnDef - column definition + */ + getHeader(columnDef: C) { + if (!columnDef) { + return this.hasFrozenColumns() ? this._headers : this._headerL; + } + const idx = this.getColumnIndex(columnDef.id); + return this.hasFrozenColumns() ? ((idx <= this._options.frozenColumn!) ? this._headerL : this._headerR) : this._headerL; + } + + /** + * Get a specific Header Column DOM element by its column Id or index + * @param {Number|String} columnIdOrIdx - column Id or index + */ + getHeaderColumn(columnIdOrIdx: number | string) { + const idx = (typeof columnIdOrIdx === 'number' ? columnIdOrIdx : this.getColumnIndex(columnIdOrIdx)); + const targetHeader = this.hasFrozenColumns() ? ((idx <= this._options.frozenColumn!) ? this._headerL : this._headerR) : this._headerL; + const targetIndex = this.hasFrozenColumns() ? ((idx <= this._options.frozenColumn!) ? idx : idx - this._options.frozenColumn! - 1) : idx; + + return targetHeader.children[targetIndex] as HTMLDivElement; + } + + /** Get the Header Row DOM element */ + getHeaderRow() { + return this.hasFrozenColumns() ? this._headerRows : this._headerRows[0]; + } + + /** Get the Footer DOM element */ + getFooterRow() { + return this.hasFrozenColumns() ? this._footerRow : this._footerRow[0]; + } + + /** @alias `getPreHeaderPanelLeft` */ + getPreHeaderPanel() { + return this._preHeaderPanel; + } + + /** Get the Pre-Header Panel Left DOM node element */ + getPreHeaderPanelLeft() { + return this._preHeaderPanel; + } + + /** Get the Pre-Header Panel Right DOM node element */ + getPreHeaderPanelRight() { + return this._preHeaderPanelR; + } + + /** + * Get Header Row Column DOM element by its column Id or index + * @param {Number|String} columnIdOrIdx - column Id or index + */ + getHeaderRowColumn(columnIdOrIdx: number | string) { + let idx = (typeof columnIdOrIdx === 'number' ? columnIdOrIdx : this.getColumnIndex(columnIdOrIdx)); + let headerRowTarget: HTMLDivElement; + + if (this.hasFrozenColumns()) { + if (idx <= this._options.frozenColumn!) { + headerRowTarget = this._headerRowL; + } else { + headerRowTarget = this._headerRowR; + idx -= this._options.frozenColumn! + 1; + } + } else { + headerRowTarget = this._headerRowL; + } + + return headerRowTarget.children[idx] as HTMLDivElement; + } + + /** + * Get the Footer Row Column DOM element by its column Id or index + * @param {Number|String} columnIdOrIdx - column Id or index + */ + getFooterRowColumn(columnIdOrIdx: number | string) { + let idx = (typeof columnIdOrIdx === 'number' ? columnIdOrIdx : this.getColumnIndex(columnIdOrIdx)); + let footerRowTarget: HTMLDivElement; + + if (this.hasFrozenColumns()) { + if (idx <= this._options.frozenColumn!) { + footerRowTarget = this._footerRowL; + } else { + footerRowTarget = this._footerRowR; + + idx -= this._options.frozenColumn! + 1; + } + } else { + footerRowTarget = this._footerRowL; + } + + return footerRowTarget.children[idx] as HTMLDivElement; + } + + protected createColumnFooter() { + if (this._options.createFooterRow) { + this._footerRow.forEach((footer) => { + const columnElements = footer.querySelectorAll('.slick-footerrow-column'); + columnElements.forEach((column) => { + const columnDef = Utils.storage.get(column, 'column'); + this.trigger(this.onBeforeFooterRowCellDestroy, { + node: column, + column: columnDef, + grid: this + }); + }); + }); + + Utils.emptyElement(this._footerRowL); + Utils.emptyElement(this._footerRowR); + + for (let i = 0; i < this.columns.length; i++) { + const m = this.columns[i]; + if (!m || m.hidden) { continue; } + + const footerRowCell = Utils.createDomElement('div', { className: `ui-state-default slick-state-default slick-footerrow-column l${i} r${i}` }, this.hasFrozenColumns() && (i > this._options.frozenColumn!) ? this._footerRowR : this._footerRowL); + const className = this.hasFrozenColumns() && i <= this._options.frozenColumn! ? 'frozen' : null; + if (className) { + footerRowCell.classList.add(className); + } + + Utils.storage.put(footerRowCell, 'column', m); + + this.trigger(this.onFooterRowCellRendered, { + node: footerRowCell, + column: m, + grid: this + }); + } + } + } + + protected handleHeaderMouseHoverOn(e: Event | SlickEventData) { + (e as any)?.target.classList.add('ui-state-hover', 'slick-state-hover'); + } + + protected handleHeaderMouseHoverOff(e: Event | SlickEventData) { + (e as any)?.target.classList.remove('ui-state-hover', 'slick-state-hover'); + } + + protected createColumnHeaders() { + this._headers.forEach((header) => { + const columnElements = header.querySelectorAll('.slick-header-column'); + columnElements.forEach((column) => { + const columnDef = Utils.storage.get(column, 'column'); + if (columnDef) { + this.trigger(this.onBeforeHeaderCellDestroy, { + node: column, + column: columnDef, + grid: this + }); + } + }); + }); + + Utils.emptyElement(this._headerL); + Utils.emptyElement(this._headerR); + + this.getHeadersWidth(); + + Utils.width(this._headerL, this.headersWidthL); + Utils.width(this._headerR, this.headersWidthR); + + this._headerRows.forEach((row) => { + const columnElements = row.querySelectorAll('.slick-headerrow-column'); + columnElements.forEach((column) => { + const columnDef = Utils.storage.get(column, 'column'); + if (columnDef) { + this.trigger(this.onBeforeHeaderRowCellDestroy, { + node: this, + column: columnDef, + grid: this + }); + } + }); + }); + + Utils.emptyElement(this._headerRowL); + Utils.emptyElement(this._headerRowR); + + if (this._options.createFooterRow) { + const footerRowLColumnElements = this._footerRowL.querySelectorAll('.slick-footerrow-column'); + footerRowLColumnElements.forEach((column) => { + const columnDef = Utils.storage.get(column, 'column'); + if (columnDef) { + this.trigger(this.onBeforeFooterRowCellDestroy, { + node: this, + column: columnDef, + grid: this + }); + } + }); + Utils.emptyElement(this._footerRowL); + + if (this.hasFrozenColumns()) { + const footerRowRColumnElements = this._footerRowR.querySelectorAll('.slick-footerrow-column'); + footerRowRColumnElements.forEach((column) => { + const columnDef = Utils.storage.get(column, 'column'); + if (columnDef) { + this.trigger(this.onBeforeFooterRowCellDestroy, { + node: this, + column: columnDef, + grid: this + }); + } + }); + Utils.emptyElement(this._footerRowR); + } + } + + for (let i = 0; i < this.columns.length; i++) { + const m: C = this.columns[i]; + const headerTarget = this.hasFrozenColumns() ? ((i <= this._options.frozenColumn!) ? this._headerL : this._headerR) : this._headerL; + const headerRowTarget = this.hasFrozenColumns() ? ((i <= this._options.frozenColumn!) ? this._headerRowL : this._headerRowR) : this._headerRowL; + + const header = Utils.createDomElement('div', { id: `${this.uid + m.id}`, dataset: { id: String(m.id) }, className: 'ui-state-default slick-state-default slick-header-column', title: m.toolTip || '' }, headerTarget); + Utils.createDomElement('span', { className: 'slick-column-name', innerHTML: this.sanitizeHtmlString(m.name as string) }, header); + Utils.width(header, m.width! - this.headerColumnWidthDiff); + + let classname = m.headerCssClass || null; + if (classname) { + header.classList.add(...classname.split(' ')); + } + classname = this.hasFrozenColumns() && i <= this._options.frozenColumn! ? 'frozen' : null; + if (classname) { + header.classList.add(classname); + } + + this._bindingEventService.bind(header, 'mouseenter', this.handleHeaderMouseEnter.bind(this) as EventListener); + this._bindingEventService.bind(header, 'mouseleave', this.handleHeaderMouseLeave.bind(this) as EventListener); + + Utils.storage.put(header, 'column', m); + + if (this._options.enableColumnReorder || m.sortable) { + this._bindingEventService.bind(header, 'mouseenter', this.handleHeaderMouseHoverOn.bind(this) as EventListener); + this._bindingEventService.bind(header, 'mouseleave', this.handleHeaderMouseHoverOff.bind(this) as EventListener); + } + + if (m.hasOwnProperty('headerCellAttrs') && m.headerCellAttrs instanceof Object) { + for (const key in m.headerCellAttrs) { + if (m.headerCellAttrs.hasOwnProperty(key)) { + header.setAttribute(key, m.headerCellAttrs[key]); + } + } + } + + if (m.sortable) { + header.classList.add('slick-header-sortable'); + Utils.createDomElement('div', { className: `slick-sort-indicator ${this._options.numberedMultiColumnSort && !this._options.sortColNumberInSeparateSpan ? ' slick-sort-indicator-numbered' : ''}` }, header); + if (this._options.numberedMultiColumnSort && this._options.sortColNumberInSeparateSpan) { + Utils.createDomElement('div', { className: 'slick-sort-indicator-numbered' }, header); + } + } + + this.trigger(this.onHeaderCellRendered, { + node: header, + column: m, + grid: this + }); + + if (this._options.showHeaderRow) { + const headerRowCell = Utils.createDomElement('div', { className: `ui-state-default slick-state-default slick-headerrow-column l${i} r${i}` }, headerRowTarget); + const frozenClasses = this.hasFrozenColumns() && i <= this._options.frozenColumn! ? 'frozen' : null; + if (frozenClasses) { + headerRowCell.classList.add(frozenClasses); + } + + this._bindingEventService.bind(headerRowCell, 'mouseenter', this.handleHeaderRowMouseEnter.bind(this) as EventListener); + this._bindingEventService.bind(headerRowCell, 'mouseleave', this.handleHeaderRowMouseLeave.bind(this) as EventListener); + + Utils.storage.put(headerRowCell, 'column', m); + + this.trigger(this.onHeaderRowCellRendered, { + node: headerRowCell, + column: m, + grid: this + }); + } + if (this._options.createFooterRow && this._options.showFooterRow) { + const footerRowTarget = this.hasFrozenColumns() ? ((i <= this._options.frozenColumn!) ? this._footerRow[0] : this._footerRow[1]) : this._footerRow[0]; + const footerRowCell = Utils.createDomElement('div', { className: `ui-state-default slick-state-default slick-footerrow-column l${i} r${i}` }, footerRowTarget); + Utils.storage.put(footerRowCell, 'column', m); + + this.trigger(this.onFooterRowCellRendered, { + node: footerRowCell, + column: m, + grid: this + }); + } + } + + this.setSortColumns(this.sortColumns); + this.setupColumnResize(); + if (this._options.enableColumnReorder) { + if (typeof this._options.enableColumnReorder === 'function') { + this._options.enableColumnReorder(this as unknown as SlickGridModel, this._headers, this.headerColumnWidthDiff, this.setColumns as any, this.setupColumnResize, this.columns, this.getColumnIndex, this.uid, this.trigger); + } else { + this.setupColumnReorder(); + } + } + } + + protected setupColumnSort() { + this._headers.forEach((header) => { + this._bindingEventService.bind(header, 'click', (e: any) => { + if (this.columnResizeDragging) { + return; + } + + if (e.target.classList.contains('slick-resizable-handle')) { + return; + } + + const coll = e.target.closest('.slick-header-column'); + if (!coll) { + return; + } + + const column = Utils.storage.get(coll, 'column'); + if (column.sortable) { + if (!this.getEditorLock()?.commitCurrentEdit()) { + return; + } + + const previousSortColumns = this.sortColumns.slice(); + let sortColumn: ColumnSort | null = null; + let i = 0; + for (; i < this.sortColumns.length; i++) { + if (this.sortColumns[i].columnId === column.id) { + sortColumn = this.sortColumns[i]; + sortColumn.sortAsc = !sortColumn.sortAsc; + break; + } + } + const hadSortCol = !!sortColumn; + + if (this._options.tristateMultiColumnSort) { + if (!sortColumn) { + sortColumn = { columnId: column.id, sortAsc: column.defaultSortAsc, sortCol: column }; + } + if (hadSortCol && sortColumn.sortAsc) { + // three state: remove sort rather than go back to ASC + this.sortColumns.splice(i, 1); + sortColumn = null; + } + if (!this._options.multiColumnSort) { + this.sortColumns = []; + } + if (sortColumn && (!hadSortCol || !this._options.multiColumnSort)) { + this.sortColumns.push(sortColumn); + } + } else { + // legacy behaviour + if (e.metaKey && this._options.multiColumnSort) { + if (sortColumn) { + this.sortColumns.splice(i, 1); + } + } else { + if ((!e.shiftKey && !e.metaKey) || !this._options.multiColumnSort) { + this.sortColumns = []; + } + + if (!sortColumn) { + sortColumn = { columnId: column.id, sortAsc: column.defaultSortAsc, sortCol: column }; + this.sortColumns.push(sortColumn); + } else if (this.sortColumns.length === 0) { + this.sortColumns.push(sortColumn); + } + } + } + + let onSortArgs; + if (!this._options.multiColumnSort) { + onSortArgs = { + multiColumnSort: false, + previousSortColumns, + columnId: (this.sortColumns.length > 0 ? column.id : null), + sortCol: (this.sortColumns.length > 0 ? column : null), + sortAsc: (this.sortColumns.length > 0 ? this.sortColumns[0].sortAsc : true) + }; + } else { + onSortArgs = { + multiColumnSort: true, + previousSortColumns, + sortCols: this.sortColumns.map((col) => { + return { columnId: this.columns[this.getColumnIndex(col.columnId)].id, sortCol: this.columns[this.getColumnIndex(col.columnId)], sortAsc: col.sortAsc }; + }) + }; + } + + if (this.trigger(this.onBeforeSort, onSortArgs, e).getReturnValue() !== false) { + this.setSortColumns(this.sortColumns); + this.trigger(this.onSort, onSortArgs, e); + } + } + }); + }); + } + + protected currentPositionInHeader(id: number | string) { + let currentPosition = 0; + this._headers.forEach((header) => { + const columnElements = header.querySelectorAll('.slick-header-column'); + columnElements.forEach((column, i) => { + if (column.id === id) { + currentPosition = i; + } + }); + }); + + return currentPosition; + } + + protected remove(arr: any[], elem: HTMLElement) { + const index = arr.lastIndexOf(elem); + if (index > -1) { + arr.splice(index, 1); + this.remove(arr, elem); + } + } + + protected setupColumnReorder() { + this.sortableSideLeftInstance?.destroy(); + this.sortableSideRightInstance?.destroy(); + + let columnScrollTimer: any = null; + + const scrollColumnsRight = () => this._viewportScrollContainerX.scrollLeft = this._viewportScrollContainerX.scrollLeft + 10; + const scrollColumnsLeft = () => this._viewportScrollContainerX.scrollLeft = this._viewportScrollContainerX.scrollLeft - 10; + + let canDragScroll; + const sortableOptions = { + animation: 50, + direction: 'horizontal', + chosenClass: 'slick-header-column-active', + ghostClass: 'slick-sortable-placeholder', + draggable: '.slick-header-column', + dragoverBubble: false, + revertClone: true, + scroll: !this.hasFrozenColumns(), // enable auto-scroll + onStart: (e: { item: any; originalEvent: MouseEvent; }) => { + canDragScroll = !this.hasFrozenColumns() || + Utils.offset(e.item)!.left > Utils.offset(this._viewportScrollContainerX)!.left; + + if (canDragScroll && e.originalEvent.pageX > this._container.clientWidth) { + if (!(columnScrollTimer)) { + columnScrollTimer = setInterval(scrollColumnsRight, 100); + } + } else if (canDragScroll && e.originalEvent.pageX < Utils.offset(this._viewportScrollContainerX)!.left) { + if (!(columnScrollTimer)) { + columnScrollTimer = setInterval(scrollColumnsLeft, 100); + } + } else { + clearInterval(columnScrollTimer); + columnScrollTimer = null; + } + }, + onEnd: (e: MouseEvent & { item: any; originalEvent: MouseEvent; }) => { + const cancel = false; + clearInterval(columnScrollTimer); + columnScrollTimer = null; + let limit; + + if (cancel || !this.getEditorLock()?.commitCurrentEdit()) { + return; + } + + let reorderedIds = this.sortableSideLeftInstance?.toArray() ?? []; + reorderedIds = reorderedIds.concat(this.sortableSideRightInstance?.toArray() ?? []); + + const reorderedColumns: C[] = []; + for (let i = 0; i < reorderedIds.length; i++) { + reorderedColumns.push(this.columns[this.getColumnIndex(reorderedIds[i])]); + } + this.setColumns(reorderedColumns); + + this.trigger(this.onColumnsReordered, { impactedColumns: this.getImpactedColumns(limit) }); + e.stopPropagation(); + this.setupColumnResize(); + if (this.activeCellNode) { + this.setFocus(); // refocus on active cell + } + } + }; + + this.sortableSideLeftInstance = Sortable.create(this._headerL, sortableOptions); + this.sortableSideRightInstance = Sortable.create(this._headerR, sortableOptions); + } + + protected getHeaderChildren() { + const a = Array.from(this._headers[0].children); + const b = Array.from(this._headers[1].children); + return a.concat(b) as HTMLElement[]; + } + + protected getImpactedColumns(limit?: { start: number; end: number; }) { + let impactedColumns: C[] = []; + + if (limit) { + for (let i = limit.start; i <= limit.end; i++) { + impactedColumns.push(this.columns[i]); + } + } else { + impactedColumns = this.columns; + } + + return impactedColumns; + } + + protected handleResizeableHandleDoubleClick(evt: MouseEvent & { target: HTMLDivElement; }) { + const triggeredByColumn = evt.target.parentElement!.id.replace(this.uid, ''); + this.trigger(this.onColumnsResizeDblClick, { triggeredByColumn }); + } + + protected setupColumnResize() { + if (typeof Resizable === 'undefined') { + throw new Error(`Slick.Resizable is undefined, make sure to import "slick.interactions.js"`); + } + + let j: number; + let k: number; + let c: C; + let pageX: number; + let minPageX: number; + let maxPageX: number; + let firstResizable: number | undefined; + let lastResizable = -1; + let frozenLeftColMaxWidth = 0; + + const children: HTMLElement[] = this.getHeaderChildren(); + for (let i = 0; i < children.length; i++) { + const child = children[i]; + const handles = child.querySelectorAll('.slick-resizable-handle'); + handles.forEach((handle) => handle.remove()); + + if (i >= this.columns.length || !this.columns[i] || this.columns[i].hidden) { + continue; + } + + if (this.columns[i].resizable) { + if (firstResizable === undefined) { + firstResizable = i; + } + lastResizable = i; + } + } + + if (firstResizable === undefined) { + return; + } + + for (let i = 0; i < children.length; i++) { + const colElm = children[i]; + + if (i >= this.columns.length || !this.columns[i] || this.columns[i].hidden) { + continue; + } + if (i < firstResizable || (this._options.forceFitColumns && i >= lastResizable)) { + continue; + } + + const resizeableHandle = Utils.createDomElement('div', { className: 'slick-resizable-handle', role: 'separator', ariaOrientation: 'horizontal' }, colElm); + this._bindingEventService.bind(resizeableHandle, 'dblclick', this.handleResizeableHandleDoubleClick.bind(this) as EventListener); + + this.slickResizableInstances.push( + Resizable({ + resizeableElement: colElm as HTMLElement, + resizeableHandleElement: resizeableHandle, + onResizeStart: (e: DOMMouseOrTouchEvent, resizeElms: { resizeableElement: HTMLElement; }): boolean | void => { + const targetEvent = e.touches ? e.touches[0] : e; + if (!this.getEditorLock()?.commitCurrentEdit()) { + return false; + } + pageX = targetEvent.pageX; + frozenLeftColMaxWidth = 0; + resizeElms.resizeableElement.classList.add('slick-header-column-active'); + let shrinkLeewayOnRight: number | null = null; + let stretchLeewayOnRight: number | null = null; + // lock each column's width option to current width + for (let pw = 0; pw < children.length; pw++) { + if (pw >= this.columns.length || !this.columns[pw] || this.columns[pw].hidden) { + continue; + } + this.columns[pw].previousWidth = children[pw].offsetWidth; + } + if (this._options.forceFitColumns) { + shrinkLeewayOnRight = 0; + stretchLeewayOnRight = 0; + // colums on right affect maxPageX/minPageX + for (j = i + 1; j < this.columns.length; j++) { + c = this.columns[j]; + if (c && c.resizable && !c.hidden) { + if (stretchLeewayOnRight !== null) { + if (c.maxWidth) { + stretchLeewayOnRight += c.maxWidth - (c.previousWidth || 0); + } else { + stretchLeewayOnRight = null; + } + } + shrinkLeewayOnRight += (c.previousWidth || 0) - Math.max(c.minWidth || 0, this.absoluteColumnMinWidth); + } + } + } + let shrinkLeewayOnLeft = 0; + let stretchLeewayOnLeft: number | null = 0; + for (j = 0; j <= i; j++) { + // columns on left only affect minPageX + c = this.columns[j]; + if (c && c.resizable && !c.hidden) { + if (stretchLeewayOnLeft !== null) { + if (c.maxWidth) { + stretchLeewayOnLeft += c.maxWidth - (c.previousWidth || 0); + } else { + stretchLeewayOnLeft = null; + } + } + shrinkLeewayOnLeft += (c.previousWidth || 0) - Math.max(c.minWidth || 0, this.absoluteColumnMinWidth); + } + } + if (shrinkLeewayOnRight === null) { + shrinkLeewayOnRight = 100000; + } + if (shrinkLeewayOnLeft === null) { + shrinkLeewayOnLeft = 100000; + } + if (stretchLeewayOnRight === null) { + stretchLeewayOnRight = 100000; + } + if (stretchLeewayOnLeft === null) { + stretchLeewayOnLeft = 100000; + } + maxPageX = pageX + Math.min(shrinkLeewayOnRight, stretchLeewayOnLeft); + minPageX = pageX - Math.min(shrinkLeewayOnLeft, stretchLeewayOnRight); + }, + onResize: (e: DOMMouseOrTouchEvent, resizeElms: { resizeableElement: HTMLElement; resizeableHandleElement: HTMLElement; }) => { + const targetEvent = e.touches ? e.touches[0] : e; + this.columnResizeDragging = true; + let actualMinWidth; + const d = Math.min(maxPageX, Math.max(minPageX, targetEvent.pageX)) - pageX; + let x; + let newCanvasWidthL = 0; + let newCanvasWidthR = 0; + const viewportWidth = this.viewportHasVScroll ? this.viewportW - (this.scrollbarDimensions?.width ?? 0) : this.viewportW; + + if (d < 0) { // shrink column + x = d; + + for (j = i; j >= 0; j--) { + c = this.columns[j]; + if (c && c.resizable && !c.hidden) { + actualMinWidth = Math.max(c.minWidth || 0, this.absoluteColumnMinWidth); + if (x && (c.previousWidth || 0) + x < actualMinWidth) { + x += (c.previousWidth || 0) - actualMinWidth; + c.width = actualMinWidth; + } else { + c.width = (c.previousWidth || 0) + x; + x = 0; + } + } + } + + for (k = 0; k <= i; k++) { + c = this.columns[k]; + if (!c || c.hidden) { continue; } + + if (this.hasFrozenColumns() && (k > this._options.frozenColumn!)) { + newCanvasWidthR += c.width || 0; + } else { + newCanvasWidthL += c.width || 0; + } + } + + if (this._options.forceFitColumns) { + x = -d; + for (j = i + 1; j < this.columns.length; j++) { + c = this.columns[j]; + if (!c || c.hidden) { continue; } + if (c.resizable) { + if (x && c.maxWidth && (c.maxWidth - (c.previousWidth || 0) < x)) { + x -= c.maxWidth - (c.previousWidth || 0); + c.width = c.maxWidth; + } else { + c.width = (c.previousWidth || 0) + x; + x = 0; + } + + if (this.hasFrozenColumns() && (j > this._options.frozenColumn!)) { + newCanvasWidthR += c.width || 0; + } else { + newCanvasWidthL += c.width || 0; + } + } + } + } else { + for (j = i + 1; j < this.columns.length; j++) { + c = this.columns[j]; + if (!c || c.hidden) { continue; } + + if (this.hasFrozenColumns() && (j > this._options.frozenColumn!)) { + newCanvasWidthR += c.width || 0; + } else { + newCanvasWidthL += c.width || 0; + } + } + } + + if (this._options.forceFitColumns) { + x = -d; + for (j = i + 1; j < this.columns.length; j++) { + c = this.columns[j]; + if (!c || c.hidden) { continue; } + if (c.resizable) { + if (x && c.maxWidth && (c.maxWidth - (c.previousWidth || 0) < x)) { + x -= c.maxWidth - (c.previousWidth || 0); + c.width = c.maxWidth; + } else { + c.width = (c.previousWidth || 0) + x; + x = 0; + } + } + } + } + } else { // stretch column + x = d; + + newCanvasWidthL = 0; + newCanvasWidthR = 0; + + for (j = i; j >= 0; j--) { + c = this.columns[j]; + if (!c || c.hidden) { continue; } + if (c.resizable) { + if (x && c.maxWidth && (c.maxWidth - (c.previousWidth || 0) < x)) { + x -= c.maxWidth - (c.previousWidth || 0); + c.width = c.maxWidth; + } else { + const newWidth = (c.previousWidth || 0) + x; + const resizedCanvasWidthL = this.canvasWidthL + x; + + if (this.hasFrozenColumns() && (j <= this._options.frozenColumn!)) { + // if we're on the left frozen side, we need to make sure that our left section width never goes over the total viewport width + if (newWidth > frozenLeftColMaxWidth && resizedCanvasWidthL < (viewportWidth - this._options.frozenRightViewportMinWidth!)) { + frozenLeftColMaxWidth = newWidth; // keep max column width ref, if we go over the limit this number will stop increasing + } + c.width = ((resizedCanvasWidthL + this._options.frozenRightViewportMinWidth!) > viewportWidth) ? frozenLeftColMaxWidth : newWidth; + } else { + c.width = newWidth; + } + x = 0; + } + } + } + + for (k = 0; k <= i; k++) { + c = this.columns[k]; + if (!c || c.hidden) { continue; } + + if (this.hasFrozenColumns() && (k > this._options.frozenColumn!)) { + newCanvasWidthR += c.width || 0; + } else { + newCanvasWidthL += c.width || 0; + } + } + + if (this._options.forceFitColumns) { + x = -d; + for (j = i + 1; j < this.columns.length; j++) { + c = this.columns[j]; + if (!c || c.hidden) { continue; } + if (c.resizable) { + actualMinWidth = Math.max(c.minWidth || 0, this.absoluteColumnMinWidth); + if (x && (c.previousWidth || 0) + x < actualMinWidth) { + x += (c.previousWidth || 0) - actualMinWidth; + c.width = actualMinWidth; + } else { + c.width = (c.previousWidth || 0) + x; + x = 0; + } + + if (this.hasFrozenColumns() && (j > this._options.frozenColumn!)) { + newCanvasWidthR += c.width || 0; + } else { + newCanvasWidthL += c.width || 0; + } + } + } + } else { + for (j = i + 1; j < this.columns.length; j++) { + c = this.columns[j]; + if (!c || c.hidden) { continue; } + + if (this.hasFrozenColumns() && (j > this._options.frozenColumn!)) { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + newCanvasWidthR += c.width || 0; + } else { + newCanvasWidthL += c.width || 0; + } + } + } + } + + if (this.hasFrozenColumns() && newCanvasWidthL !== this.canvasWidthL) { + Utils.width(this._headerL, newCanvasWidthL + 1000); + Utils.setStyleSize(this._paneHeaderR, 'left', newCanvasWidthL); + } + + this.applyColumnHeaderWidths(); + if (this._options.syncColumnCellResize) { + this.applyColumnWidths(); + } + this.trigger(this.onColumnsDrag, { + triggeredByColumn: resizeElms.resizeableElement, + resizeHandle: resizeElms.resizeableHandleElement + }); + }, + onResizeEnd: (_e: Event, resizeElms: { resizeableElement: HTMLElement; }) => { + resizeElms.resizeableElement.classList.remove('slick-header-column-active'); + + const triggeredByColumn = resizeElms.resizeableElement.id.replace(this.uid, ''); + if (this.trigger(this.onBeforeColumnsResize, { triggeredByColumn }).getReturnValue() === true) { + this.applyColumnHeaderWidths(); + } + let newWidth; + for (j = 0; j < this.columns.length; j++) { + c = this.columns[j]; + if (!c || c.hidden) { continue; } + newWidth = children[j].offsetWidth; + + if (c.previousWidth !== newWidth && c.rerenderOnResize) { + this.invalidateAllRows(); + } + } + this.updateCanvasWidth(true); + this.render(); + this.trigger(this.onColumnsResized, { triggeredByColumn }); + setTimeout(() => { this.columnResizeDragging = false; }, 300); + } + }) + ); + } + } + + protected getVBoxDelta(el: HTMLElement) { + const p = ['borderTopWidth', 'borderBottomWidth', 'paddingTop', 'paddingBottom']; + const styles = getComputedStyle(el); + let delta = 0; + p.forEach((val) => delta += Utils.toFloat(styles[val as any])); + return delta; + } + + protected setFrozenOptions() { + this._options.frozenColumn = (this._options.frozenColumn! >= 0 && this._options.frozenColumn! < this.columns.length) + ? parseInt(this._options.frozenColumn as unknown as string, 10) + : -1; + + if (this._options.frozenRow! > -1) { + this.hasFrozenRows = true; + this.frozenRowsHeight = (this._options.frozenRow!) * this._options.rowHeight!; + const dataLength = this.getDataLength(); + + this.actualFrozenRow = (this._options.frozenBottom) + ? (dataLength - this._options.frozenRow!) + : this._options.frozenRow!; + } else { + this.hasFrozenRows = false; + } + } + + protected setPaneVisibility() { + if (this.hasFrozenColumns()) { + Utils.show(this._paneHeaderR); + Utils.show(this._paneTopR); + + if (this.hasFrozenRows) { + Utils.show(this._paneBottomL); + Utils.show(this._paneBottomR); + } else { + Utils.hide(this._paneBottomR); + Utils.hide(this._paneBottomL); + } + } else { + Utils.hide(this._paneHeaderR); + Utils.hide(this._paneTopR); + Utils.hide(this._paneBottomR); + + if (this.hasFrozenRows) { + Utils.show(this._paneBottomL); + } else { + Utils.hide(this._paneBottomR); + Utils.hide(this._paneBottomL); + } + } + } + + protected setOverflow() { + this._viewportTopL.style.overflowX = (this.hasFrozenColumns()) ? (this.hasFrozenRows && !this._options.alwaysAllowHorizontalScroll ? 'hidden' : 'scroll') : (this.hasFrozenRows && !this._options.alwaysAllowHorizontalScroll ? 'hidden' : 'auto'); + this._viewportTopL.style.overflowY = (!this.hasFrozenColumns() && this._options.alwaysShowVerticalScroll) ? 'scroll' : ((this.hasFrozenColumns()) ? (this.hasFrozenRows ? 'hidden' : 'hidden') : (this.hasFrozenRows ? 'scroll' : 'auto')); + + this._viewportTopR.style.overflowX = (this.hasFrozenColumns()) ? (this.hasFrozenRows && !this._options.alwaysAllowHorizontalScroll ? 'hidden' : 'scroll') : (this.hasFrozenRows && !this._options.alwaysAllowHorizontalScroll ? 'hidden' : 'auto'); + this._viewportTopR.style.overflowY = this._options.alwaysShowVerticalScroll ? 'scroll' : ((this.hasFrozenColumns()) ? (this.hasFrozenRows ? 'scroll' : 'auto') : (this.hasFrozenRows ? 'scroll' : 'auto')); + + this._viewportBottomL.style.overflowX = (this.hasFrozenColumns()) ? (this.hasFrozenRows && !this._options.alwaysAllowHorizontalScroll ? 'scroll' : 'auto') : (this.hasFrozenRows && !this._options.alwaysAllowHorizontalScroll ? 'auto' : 'auto'); + this._viewportBottomL.style.overflowY = (!this.hasFrozenColumns() && this._options.alwaysShowVerticalScroll) ? 'scroll' : ((this.hasFrozenColumns()) ? (this.hasFrozenRows ? 'hidden' : 'hidden') : (this.hasFrozenRows ? 'scroll' : 'auto')); + + this._viewportBottomR.style.overflowX = (this.hasFrozenColumns()) ? (this.hasFrozenRows && !this._options.alwaysAllowHorizontalScroll ? 'scroll' : 'auto') : (this.hasFrozenRows && !this._options.alwaysAllowHorizontalScroll ? 'auto' : 'auto'); + this._viewportBottomR.style.overflowY = this._options.alwaysShowVerticalScroll ? 'scroll' : ((this.hasFrozenColumns()) ? (this.hasFrozenRows ? 'auto' : 'auto') : (this.hasFrozenRows ? 'auto' : 'auto')); + + if (this._options.viewportClass) { + this._viewportTopL.classList.add(...this._options.viewportClass.split(' ')); + this._viewportTopR.classList.add(...this._options.viewportClass.split(' ')); + this._viewportBottomL.classList.add(...this._options.viewportClass.split(' ')); + this._viewportBottomR.classList.add(...this._options.viewportClass.split(' ')); + } + } + + protected setScroller() { + if (this.hasFrozenColumns()) { + this._headerScrollContainer = this._headerScrollerR; + this._headerRowScrollContainer = this._headerRowScrollerR; + this._footerRowScrollContainer = this._footerRowScrollerR; + + if (this.hasFrozenRows) { + if (this._options.frozenBottom) { + this._viewportScrollContainerX = this._viewportBottomR; + this._viewportScrollContainerY = this._viewportTopR; + } else { + this._viewportScrollContainerX = this._viewportScrollContainerY = this._viewportBottomR; + } + } else { + this._viewportScrollContainerX = this._viewportScrollContainerY = this._viewportTopR; + } + } else { + this._headerScrollContainer = this._headerScrollerL; + this._headerRowScrollContainer = this._headerRowScrollerL; + this._footerRowScrollContainer = this._footerRowScrollerL; + + if (this.hasFrozenRows) { + if (this._options.frozenBottom) { + this._viewportScrollContainerX = this._viewportBottomL; + this._viewportScrollContainerY = this._viewportTopL; + } else { + this._viewportScrollContainerX = this._viewportScrollContainerY = this._viewportBottomL; + } + } else { + this._viewportScrollContainerX = this._viewportScrollContainerY = this._viewportTopL; + } + } + } + + protected measureCellPaddingAndBorder() { + const h = ['borderLeftWidth', 'borderRightWidth', 'paddingLeft', 'paddingRight']; + const v = ['borderTopWidth', 'borderBottomWidth', 'paddingTop', 'paddingBottom']; + const header = this._headers[0]; + + this.headerColumnWidthDiff = this.headerColumnHeightDiff = 0; + this.cellWidthDiff = this.cellHeightDiff = 0; + + let el = Utils.createDomElement('div', { className: 'ui-state-default slick-state-default slick-header-column', style: { visibility: 'hidden' }, textContent: '-' }, header); + let style = getComputedStyle(el); + if (style.boxSizing !== 'border-box') { + h.forEach((val) => this.headerColumnWidthDiff += Utils.toFloat(style[val as any])); + v.forEach((val) => this.headerColumnHeightDiff += Utils.toFloat(style[val as any])); + } + el.remove(); + + const r = Utils.createDomElement('div', { className: 'slick-row' }, this._canvas[0]); + el = Utils.createDomElement('div', { className: 'slick-cell', id: '', style: { visibility: 'hidden' }, textContent: '-' }, r); + style = getComputedStyle(el); + if (style.boxSizing !== 'border-box') { + h.forEach((val) => this.cellWidthDiff += Utils.toFloat(style[val as any])); + v.forEach((val) => this.cellHeightDiff += Utils.toFloat(style[val as any])); + } + r.remove(); + + this.absoluteColumnMinWidth = Math.max(this.headerColumnWidthDiff, this.cellWidthDiff); + } + + protected createCssRules() { + const template = Utils.createDomElement('template', { innerHTML: '