diff --git a/docs/getting-started/quick-start.md b/docs/getting-started/quick-start.md index 28b85a7c1..d07d163ce 100644 --- a/docs/getting-started/quick-start.md +++ b/docs/getting-started/quick-start.md @@ -35,8 +35,8 @@ You could also compile the SASS files with your own customization, for that simp $cell-odd-background-color: lightyellow; $row-mouse-hover-color: lightgreen; -/* make sure to add the @import the SlickGrid Bootstrap Theme AFTER the variables changes */ -@import '../node_modules/@slickgrid-universal/common/dist/styles/sass/slickgrid-theme-bootstrap.scss'; +/* make sure to add the @use the SlickGrid Bootstrap Theme AFTER the variables changes */ +@use '../node_modules/@slickgrid-universal/common/dist/styles/sass/slickgrid-theme-bootstrap.scss'; ``` ### 3. Include it in your App diff --git a/docs/styling/styling.md b/docs/styling/styling.md index 271ca45ff..b02ada6e8 100644 --- a/docs/styling/styling.md +++ b/docs/styling/styling.md @@ -28,11 +28,11 @@ The Material & Salesforce Themes are using SVGs internally for the icons used by ##### with CSS ```scss /* style.css */ -@import '@slickgrid-universal/common/dist/styles/css/slickgrid-theme-bootstrap.css'; +@use '@slickgrid-universal/common/dist/styles/css/slickgrid-theme-bootstrap.css'; // or other Themes -// @import '@slickgrid-universal/common/dist/styles/styles/css/slickgrid-theme-material.css'; -// @import '@slickgrid-universal/common/dist/styles/css/slickgrid-theme-salesforce.css'; +// @use '@slickgrid-universal/common/dist/styles/styles/css/slickgrid-theme-material.css'; +// @use '@slickgrid-universal/common/dist/styles/css/slickgrid-theme-salesforce.css'; ``` ##### with SASS @@ -43,11 +43,11 @@ $slick-cell-odd-background-color: lightyellow; $slick-row-mouse-hover-color: lightgreen; /* style.scss */ -@import '@slickgrid-universal/common/dist/styles/sass/slickgrid-theme-bootstrap.scss'; +@use '@slickgrid-universal/common/dist/styles/sass/slickgrid-theme-bootstrap.scss'; // or other Themes -// @import '@slickgrid-universal/common/dist/styles/sass/slickgrid-theme-material.scss'; -// @import '@slickgrid-universal/common/dist/styles/sass/slickgrid-theme-salesforce.scss'; +// @use '@slickgrid-universal/common/dist/styles/sass/slickgrid-theme-material.scss'; +// @use '@slickgrid-universal/common/dist/styles/sass/slickgrid-theme-salesforce.scss'; ``` ### Using CSS Variables _(instead of SASS)_ @@ -77,8 +77,8 @@ $slick-icon-group-collapsed-svg-path: "M8.59,16.58L13.17,12L8.59,7.41L10,6L16,12 $slick-icon-group-expanded-svg-path: "M7.41,8.58L12,13.17L16.59,8.58L18,10L12,16L6,10L7.41,8.58Z"; $slick-icon-group-font-size: 13px; -// then on the last line, import the Theme that you wish to override -@import '@slickgrid-universal/common/dist/styles/sass/slickgrid-theme-bootstrap.scss'; +// then on the last line, load the Theme that you wish to override +@use '@slickgrid-universal/common/dist/styles/sass/slickgrid-theme-bootstrap.scss'; ``` > **Note** since the SVG are generated by a SASS function, you can easily override an SVG path in SASS but that is not the case with CSS variable. We still have a way to override an SVG via CSS variable but it requires to override the entire SVG content (not just its path) as can be seen below (also notice that the CSS variable is named without the `"-path"` suffix and also note that the URL must be encoded) diff --git a/package.json b/package.json index 2db3c361a..e5b98be03 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "@jest/types": "^29.6.3", "@lerna-lite/cli": "^3.10.0", "@lerna-lite/publish": "^3.10.0", - "@slickgrid-universal/common": "^5.8.0", + "@slickgrid-universal/common": "^5.9.0", "@types/jest": "^29.5.13", "@types/node": "^22.7.7", "conventional-changelog-conventionalcommits": "^7.0.2", diff --git a/packages/aurelia-slickgrid/package.json b/packages/aurelia-slickgrid/package.json index 272e58218..62073298a 100644 --- a/packages/aurelia-slickgrid/package.json +++ b/packages/aurelia-slickgrid/package.json @@ -53,13 +53,13 @@ "@aurelia/runtime": "^2.0.0-beta.22", "@aurelia/runtime-html": "^2.0.0-beta.22", "@formkit/tempo": "^0.1.2", - "@slickgrid-universal/common": "~5.8.0", - "@slickgrid-universal/custom-footer-component": "~5.8.0", - "@slickgrid-universal/empty-warning-component": "~5.8.0", - "@slickgrid-universal/event-pub-sub": "~5.8.0", - "@slickgrid-universal/pagination-component": "~5.8.0", - "@slickgrid-universal/row-detail-view-plugin": "~5.8.0", - "@slickgrid-universal/utils": "~5.8.0", + "@slickgrid-universal/common": "~5.9.0", + "@slickgrid-universal/custom-footer-component": "~5.9.0", + "@slickgrid-universal/empty-warning-component": "~5.9.0", + "@slickgrid-universal/event-pub-sub": "~5.9.0", + "@slickgrid-universal/pagination-component": "~5.9.0", + "@slickgrid-universal/row-detail-view-plugin": "~5.9.0", + "@slickgrid-universal/utils": "~5.9.0", "dequal": "^2.0.3", "sortablejs": "^1.15.3" }, diff --git a/packages/aurelia-slickgrid/src/custom-elements/aurelia-slickgrid.ts b/packages/aurelia-slickgrid/src/custom-elements/aurelia-slickgrid.ts index 2d1772e2f..7c04bc34b 100644 --- a/packages/aurelia-slickgrid/src/custom-elements/aurelia-slickgrid.ts +++ b/packages/aurelia-slickgrid/src/custom-elements/aurelia-slickgrid.ts @@ -1,6 +1,9 @@ -// interfaces/types +import type { ICollectionObserver, ICollectionSubscriber } from '@aurelia/runtime'; +import { bindable, BindingMode, customElement, IContainer, IEventAggregator, type IDisposable, IObserverLocator, resolve } from 'aurelia'; +import { dequal } from 'dequal/lite'; import type { BackendService, + BasePaginationComponent, AutocompleterEditor, BackendServiceApi, BackendServiceOption, @@ -12,10 +15,9 @@ import type { Locale, Metrics, Pagination, + PaginationMetadata, SelectEditor, - ServicePagination, } from '@slickgrid-universal/common'; - import { // services autoAddEditorFormatterToColumnsWithEditor, @@ -53,10 +55,6 @@ import { SlickEmptyWarningComponent } from '@slickgrid-universal/empty-warning-c import { SlickPaginationComponent } from '@slickgrid-universal/pagination-component'; import { extend } from '@slickgrid-universal/utils'; -import { bindable, BindingMode, customElement, IContainer, IEventAggregator, type IDisposable, IObserverLocator, resolve } from 'aurelia'; -import type { ICollectionObserver, ICollectionSubscriber } from '@aurelia/runtime'; -import { dequal } from 'dequal/lite'; - import { Constants } from '../constants'; import { GlobalGridOptions } from '../global-grid-options'; import type { AureliaGridInstance, GridOption } from '../models/index'; @@ -117,7 +115,8 @@ export class AureliaSlickgridCustomElement { // components / plugins slickEmptyWarning: SlickEmptyWarningComponent | undefined; slickFooter: SlickFooterComponent | undefined; - slickPagination: SlickPaginationComponent | undefined; + paginationComponent: BasePaginationComponent | undefined; + slickPagination: BasePaginationComponent | undefined; slickRowDetailView?: SlickRowDetailView; // services @@ -193,7 +192,7 @@ export class AureliaSlickgridCustomElement { this.gridStateService = new GridStateService(this.extensionService, this.filterService, this._eventPubSubService, this.sharedService, this.sortService, this.treeDataService); this.gridService = new GridService(this.gridStateService, this.filterService, this._eventPubSubService, this.paginationService, this.sharedService, this.sortService, this.treeDataService); - this.headerGroupingService = new HeaderGroupingService(this.extensionUtility, this._eventPubSubService); + this.headerGroupingService = new HeaderGroupingService(this.extensionUtility); this.serviceList = [ this.extensionService, @@ -478,6 +477,7 @@ export class AureliaSlickgridCustomElement { groupingService: this.headerGroupingService, headerGroupingService: this.headerGroupingService, extensionService: this.extensionService, + paginationComponent: this.slickPagination, paginationService: this.paginationService, resizerService: this.resizerService, sortService: this.sortService, @@ -943,7 +943,7 @@ export class AureliaSlickgridCustomElement { * On a Pagination changed, we will trigger a Grid State changed with the new pagination info * Also if we use Row Selection or the Checkbox Selector with a Backend Service (Odata, GraphQL), we need to reset any selection */ - paginationChanged(pagination: ServicePagination) { + paginationChanged(pagination: PaginationMetadata) { const isSyncGridSelectionEnabled = this.gridStateService?.needToPreserveRowSelection() ?? false; if (this.grid && !isSyncGridSelectionEnabled && this.gridOptions?.backendServiceApi && (this.gridOptions.enableRowSelection || this.gridOptions.enableCheckboxSelector)) { this.grid.setSelectedRows([]); @@ -1175,7 +1175,7 @@ export class AureliaSlickgridCustomElement { this.paginationService.totalItems = this.totalItems; this.paginationService.init(this.grid, paginationOptions, this.backendServiceApi); this.subscriptions.push( - this._eventPubSubService.subscribe('onPaginationChanged', (paginationChanges: ServicePagination) => this.paginationChanged(paginationChanges)), + this._eventPubSubService.subscribe('onPaginationChanged', (paginationChanges: PaginationMetadata) => this.paginationChanged(paginationChanges)), this._eventPubSubService.subscribe('onPaginationVisibilityChanged', (visibility: { visible: boolean }) => { this.showPagination = visibility?.visible ?? false; if (this.gridOptions?.backendServiceApi) { @@ -1484,11 +1484,26 @@ export class AureliaSlickgridCustomElement { * @param {Boolean} showPagination - show (new render) or not (dispose) the Pagination * @param {Boolean} shouldDisposePaginationService - when disposing the Pagination, do we also want to dispose of the Pagination Service? (defaults to True) */ - protected renderPagination(showPagination = true) { - if (this.gridOptions?.enablePagination && !this._isPaginationInitialized && showPagination) { - this.slickPagination = new SlickPaginationComponent(this.paginationService, this._eventPubSubService, this.sharedService, this.translaterService); - this.slickPagination.renderPagination(this.elm.querySelector('div') as HTMLDivElement); - this._isPaginationInitialized = true; + protected async renderPagination(showPagination = true) { + if (this.grid && this.gridOptions?.enablePagination && !this._isPaginationInitialized && showPagination) { + if (this.gridOptions.customPaginationComponent) { + const paginationContainer = document.createElement('section'); + this.elm.appendChild(paginationContainer); + const vm = await this.aureliaUtilService.createAureliaViewModelAddToSlot(this.gridOptions.customPaginationComponent!, undefined, paginationContainer); + const elmBindingContext = vm?.controller?.children?.[0].scope.bindingContext; + if (elmBindingContext) { + this.instances!.paginationComponent = elmBindingContext as BasePaginationComponent; + this.slickPagination = elmBindingContext as BasePaginationComponent; + } + } else { + this.slickPagination = new SlickPaginationComponent(); + } + + if (this.slickPagination) { + this.slickPagination.init(this.grid, this.paginationService, this._eventPubSubService, this.translaterService); + this.slickPagination.renderPagination(this.elm.querySelector('div') as HTMLDivElement); + this._isPaginationInitialized = true; + } } else if (!showPagination) { this.slickPagination?.dispose(); this._isPaginationInitialized = false; @@ -1546,7 +1561,7 @@ export class AureliaSlickgridCustomElement { } protected suggestDateParsingWhenHelpful() { - if (/* !this.gridOptions.silenceWarnings && */ this.dataview?.getItemCount() > WARN_NO_PREPARSE_DATE_SIZE && !this.gridOptions.preParseDateColumns && this.grid.getColumns().some(c => isColumnDateType(c.type))) { + if (!this.gridOptions.silenceWarnings && this.dataview?.getItemCount() > WARN_NO_PREPARSE_DATE_SIZE && !this.gridOptions.preParseDateColumns && this.grid.getColumns().some(c => isColumnDateType(c.type))) { console.warn( '[Slickgrid-Universal] For getting better perf, we suggest you enable the `preParseDateColumns` grid option, ' + 'for more info visit => https://ghiscoding.gitbook.io/aurelia-slickgrid/column-functionalities/sorting#pre-parse-date-columns-for-better-perf' diff --git a/packages/aurelia-slickgrid/src/models/aureliaGridInstance.interface.ts b/packages/aurelia-slickgrid/src/models/aureliaGridInstance.interface.ts index 67385be98..8969fa30c 100644 --- a/packages/aurelia-slickgrid/src/models/aureliaGridInstance.interface.ts +++ b/packages/aurelia-slickgrid/src/models/aureliaGridInstance.interface.ts @@ -1,5 +1,6 @@ import type { BackendService, + BasePaginationComponent, ExtensionService, FilterService, GridEventService, @@ -57,6 +58,9 @@ export interface AureliaGridInstance { /** Grouping (and colspan) Service */ headerGroupingService: HeaderGroupingService; + /** Pagination Component */ + paginationComponent?: BasePaginationComponent; + /** Pagination Service (allows you to programmatically go to first/last page, etc...) */ paginationService?: PaginationService; diff --git a/packages/demo/package.json b/packages/demo/package.json index 59459a321..826f602b6 100644 --- a/packages/demo/package.json +++ b/packages/demo/package.json @@ -43,19 +43,19 @@ "@fnando/sparkline": "^0.3.10", "@formkit/tempo": "^0.1.2", "@popperjs/core": "^2.11.8", - "@slickgrid-universal/common": "^5.8.0", - "@slickgrid-universal/composite-editor-component": "^5.8.0", - "@slickgrid-universal/custom-tooltip-plugin": "^5.8.0", - "@slickgrid-universal/excel-export": "^5.8.0", - "@slickgrid-universal/graphql": "^5.8.0", - "@slickgrid-universal/odata": "^5.8.0", - "@slickgrid-universal/row-detail-view-plugin": "^5.8.0", - "@slickgrid-universal/rxjs-observable": "^5.8.0", - "@slickgrid-universal/text-export": "^5.8.0", + "@slickgrid-universal/common": "^5.9.0", + "@slickgrid-universal/composite-editor-component": "^5.9.0", + "@slickgrid-universal/custom-tooltip-plugin": "^5.9.0", + "@slickgrid-universal/excel-export": "^5.9.0", + "@slickgrid-universal/graphql": "^5.9.0", + "@slickgrid-universal/odata": "^5.9.0", + "@slickgrid-universal/row-detail-view-plugin": "^5.9.0", + "@slickgrid-universal/rxjs-observable": "^5.9.0", + "@slickgrid-universal/text-export": "^5.9.0", "aurelia": "^2.0.0-beta.22", "aurelia-slickgrid": "workspace:*", "bootstrap": "^5.3.3", - "i18next": "^23.15.1", + "i18next": "^23.16.1", "i18next-fetch-backend": "^6.0.0", "rxjs": "^7.8.1" }, diff --git a/packages/demo/src/examples/slickgrid/example25.scss b/packages/demo/src/examples/slickgrid/example25.scss index 61750101f..5d278d9e2 100644 --- a/packages/demo/src/examples/slickgrid/example25.scss +++ b/packages/demo/src/examples/slickgrid/example25.scss @@ -1,8 +1,7 @@ -$slick-preheader-font-size: 18px; -$slick-preheader-border-right: 1px solid lightgrey; - -/* make sure to add the @import the SlickGrid Bootstrap Theme AFTER the variables changes */ -@import '@slickgrid-universal/common/dist/styles/sass/slickgrid-theme-bootstrap.scss'; +@use '@slickgrid-universal/common/dist/styles/sass/slickgrid-theme-bootstrap.scss' with ( + $slick-preheader-font-size: 18px, + $slick-preheader-border-right: 1px solid lightgrey +); .alert { padding: 8px; diff --git a/packages/demo/src/examples/slickgrid/example27.scss b/packages/demo/src/examples/slickgrid/example27.scss index e8c1de9f8..e4075e670 100644 --- a/packages/demo/src/examples/slickgrid/example27.scss +++ b/packages/demo/src/examples/slickgrid/example27.scss @@ -1,5 +1,5 @@ -/* make sure to add the @import the SlickGrid Theme AFTER the variables changes */ -// @import '@slickgrid-universal/common/dist/styles/sass/slickgrid-theme-material.lite.scss'; +/* make sure to add the @use the SlickGrid Theme AFTER the variables changes */ +// @use '@slickgrid-universal/common/dist/styles/sass/slickgrid-theme-material.lite.scss' with (...); #grid27 { .slick-cell { diff --git a/packages/demo/src/examples/slickgrid/example28.scss b/packages/demo/src/examples/slickgrid/example28.scss index 5cb04f380..d44fc0965 100644 --- a/packages/demo/src/examples/slickgrid/example28.scss +++ b/packages/demo/src/examples/slickgrid/example28.scss @@ -1,4 +1,4 @@ -// @import '@slickgrid-universal/common/dist/styles/sass/slickgrid-theme-salesforce.scss'; +// @use '@slickgrid-universal/common/dist/styles/sass/slickgrid-theme-salesforce.lite.scss' with (...); #grid28 { .slick-cell { diff --git a/packages/demo/src/examples/slickgrid/example31.scss b/packages/demo/src/examples/slickgrid/example31.scss index 4f68c9768..3e5293333 100644 --- a/packages/demo/src/examples/slickgrid/example31.scss +++ b/packages/demo/src/examples/slickgrid/example31.scss @@ -1,2 +1 @@ -/* make sure to add the @import the SlickGrid Theme AFTER the variables changes */ -// @import '@slickgrid-universal/common/dist/styles/sass/slickgrid-theme-salesforce.lite.scss'; +// @use '@slickgrid-universal/common/dist/styles/sass/slickgrid-theme-material.lite.scss' with (...); diff --git a/packages/demo/src/examples/slickgrid/example33.scss b/packages/demo/src/examples/slickgrid/example33.scss index 7e03faead..dc45c472d 100644 --- a/packages/demo/src/examples/slickgrid/example33.scss +++ b/packages/demo/src/examples/slickgrid/example33.scss @@ -1,7 +1,9 @@ @use 'sass:color'; +$button-border-color: #ababab; -$slick-button-border-color: #ababab !default; -@import '@slickgrid-universal/common/dist/styles/sass/slickgrid-theme-bootstrap.scss'; +@use '@slickgrid-universal/common/dist/styles/sass/slickgrid-theme-bootstrap.scss' with ( + $slick-button-border-color: $button-border-color +); // -- // Custom Tooltips CSS Variables (or SASS equivalent) @@ -26,12 +28,12 @@ $slick-button-border-color: #ababab !default; .button-style { cursor: pointer; background-color: white; - border: 1px solid #{$slick-button-border-color}; + border: 1px solid #{$button-border-color}; border-radius: 2px; justify-content: center; text-align: center; &:hover { - border-color: color.adjust($slick-button-border-color, $lightness: -10%); + border-color: color.adjust($button-border-color, $lightness: -10%); } } diff --git a/packages/demo/src/examples/slickgrid/example34.scss b/packages/demo/src/examples/slickgrid/example34.scss index 5a7a4846c..c5b886ec7 100644 --- a/packages/demo/src/examples/slickgrid/example34.scss +++ b/packages/demo/src/examples/slickgrid/example34.scss @@ -1,4 +1,4 @@ -// @import '@slickgrid-universal/common/dist/styles/sass/slickgrid-theme-salesforce.lite.scss'; +// @use '@slickgrid-universal/common/dist/styles/sass/slickgrid-theme-material.lite.scss' with (...); $sparkline-color: #00b78d; // $sparkline-color: #573585; diff --git a/packages/demo/src/examples/slickgrid/example42-pager.scss b/packages/demo/src/examples/slickgrid/example42-pager.scss new file mode 100644 index 000000000..3e8ddebec --- /dev/null +++ b/packages/demo/src/examples/slickgrid/example42-pager.scss @@ -0,0 +1,56 @@ +@use 'sass:color'; + +.custom-pagination { + display: flex; + justify-content: flex-end; + margin: 10px; + font-size: 13px; + + .custom-pagination-settings { + display: inline-flex; + align-items: center; + margin-right: 30px; + } + + .custom-pagination-nav { + display: flex; + align-items: center; + list-style-type: none; + + .page-item { + display: flex; + width: 26px; + justify-content: center; + margin: 0; + &.disabled .pagination-link { + color: rgb(180, 179, 179); + background-color: rgb(180, 179, 179); + } + } + + .page-number { + .page-number { + padding: 0 5px; + display: inline-flex; + justify-content: center; + width: 20px; + } + } + + nav { + ul.custom-pagination-ul { + display: flex; + margin: 0; + padding: 0 5px; + color: #0d6efd; + + .pagination-link { + color: #0d6efd; + &:hover { + color: color.adjust(#0d6efd, $lightness: 10%); + } + } + } + } + } +} diff --git a/packages/demo/src/examples/slickgrid/example42-pager.ts b/packages/demo/src/examples/slickgrid/example42-pager.ts new file mode 100644 index 000000000..f0c546fab --- /dev/null +++ b/packages/demo/src/examples/slickgrid/example42-pager.ts @@ -0,0 +1,144 @@ +import { bindable, customElement, resolve } from 'aurelia'; +import type { BasePaginationComponent, PaginationMetadata, PaginationService, PubSubService, SlickGrid, Subscription } from '@slickgrid-universal/common'; +import './example42-pager.scss'; + +/** Custom Pagination Componnet, please note that you MUST `implements BasePaginationComponent` with required functions */ +@customElement({ + name: 'custom-pager', + template: `
+ + + + + $\{currentPagination?.dataFrom} + - + + $\{currentPagination?.dataTo} + + of + + + $\{currentPagination?.totalItems} + items + + + +
+ +
+ Page + $\{currentPagination?.pageNumber} + of + $\{currentPagination?.pageCount} +
+ +
+
` +}) +export class CustomPagerComponent implements BasePaginationComponent { + protected _paginationElement!: HTMLDivElement; + protected _subscriptions: Subscription[] = []; + protected _grid!: SlickGrid; + protected _paginationService!: PaginationService; + protected _pubSubService!: PubSubService; + @bindable() currentPagination = {} as PaginationMetadata; + + constructor(protected readonly elm: HTMLElement = resolve(HTMLElement)) { } + + get isLeftPaginationDisabled(): boolean { + return this.currentPagination.pageNumber === 1 || this.currentPagination.totalItems === 0; + } + + get isRightPaginationDisabled(): boolean { + return this.currentPagination.pageNumber === this.currentPagination.pageCount || this.currentPagination.totalItems === 0; + } + + init(grid: SlickGrid, paginationService: PaginationService, pubSubService: PubSubService) { + this._grid = grid; + this._paginationService = paginationService; + this._pubSubService = pubSubService; + this.currentPagination = this._paginationService.getFullPagination(); + + // Anytime the pagination is initialized or has changes, + // we'll copy the data into a local object so that we can add binding to this local object + this._subscriptions.push( + this._pubSubService.subscribe('onPaginationRefreshed', paginationChanges => { + this.currentPagination.dataFrom = paginationChanges.dataFrom; + this.currentPagination.dataTo = paginationChanges.dataTo; + this.currentPagination.pageCount = paginationChanges.pageCount; + this.currentPagination.pageNumber = paginationChanges.pageNumber; + this.currentPagination.pageSize = paginationChanges.pageSize; + this.currentPagination.pageSizes = paginationChanges.pageSizes; + this.currentPagination.totalItems = paginationChanges.totalItems; + }) + ); + } + + dispose() { + this._pubSubService.unsubscribeAll(this._subscriptions); + this.disposeElement(); + } + + disposeElement() { + this._paginationElement?.remove(); + } + + renderPagination(containerElm: HTMLElement, position: 'top' | 'bottom' = 'top') { + this._paginationElement = this.elm as HTMLDivElement; + this._paginationElement.id = 'pager'; + this._paginationElement.className = `pagination-container pager ${this._grid.getUID()}`; + this._paginationElement.style.width = '100%'; + + if (position === 'top') { + // we can prepend the grid if we wish + this._paginationElement.classList.add('top'); + containerElm.prepend(this._paginationElement); + } else { + // or append it at the bottom + this._paginationElement.classList.add('bottom'); + containerElm.appendChild(this._paginationElement); + } + } + + onFirstPageClicked(event: MouseEvent): void { + if (!this.isLeftPaginationDisabled) { + this._paginationService.goToFirstPage(event); + } + } + + onLastPageClicked(event: MouseEvent): void { + if (!this.isRightPaginationDisabled) { + this._paginationService.goToLastPage(event); + } + } + + onNextPageClicked(event: MouseEvent): void { + if (!this.isRightPaginationDisabled) { + this._paginationService.goToNextPage(event); + } + } + + onPreviousPageClicked(event: MouseEvent): void { + if (!this.isLeftPaginationDisabled) { + this._paginationService.goToPreviousPage(event); + } + } +} diff --git a/packages/demo/src/examples/slickgrid/example42.html b/packages/demo/src/examples/slickgrid/example42.html new file mode 100644 index 000000000..e64bcb1f9 --- /dev/null +++ b/packages/demo/src/examples/slickgrid/example42.html @@ -0,0 +1,37 @@ +
+

+ Example 42: Custom Pagination + + + code + + +

+ +
+ You can create a Custom Pagination by passing an Aurelia Custom Element and it must implements BasePaginationComponent. + Any of the pagination controls could be moved anywhere on the page (for example we purposely moved the page size away from the rest of the pagination elements). +
+ +
+ + + + Page Size + + +
+ + + +
diff --git a/packages/demo/src/examples/slickgrid/example42.ts b/packages/demo/src/examples/slickgrid/example42.ts new file mode 100644 index 000000000..458931e93 --- /dev/null +++ b/packages/demo/src/examples/slickgrid/example42.ts @@ -0,0 +1,162 @@ +import { bindable } from 'aurelia'; +import { + type AureliaGridInstance, + type Column, + FieldType, + Formatters, + type GridOption, + type MultipleSelectOption, + Filters, + OperatorType, + type Pagination, + type SliderRangeOption, +} from 'aurelia-slickgrid'; + +import { CustomPagerComponent } from './example42-pager'; + +const NB_ITEMS = 5000; + +function randomBetween(min: number, max: number): number { + return Math.floor(Math.random() * (max - min + 1) + min); +} + +export class Example42 { + @bindable() pageSize = 50; + columnDefinitions: Column[] = []; + gridContainerElm!: HTMLDivElement; + gridOptions!: GridOption; + dataset: any[] = []; + paginationPosition: 'bottom' | 'top' = 'top'; + aureliaGrid: AureliaGridInstance; + paginationOptions!: Pagination; + + constructor() { + this.defineGrid(); + } + + attached() { + this.dataset = this.loadData(NB_ITEMS); + } + + aureliaGridReady(aureliaGrid: AureliaGridInstance) { + this.aureliaGrid = aureliaGrid; + } + + defineGrid() { + this.columnDefinitions = [ + { + id: 'title', name: 'Title', field: 'id', minWidth: 100, + sortable: true, + filterable: true, + formatter: (_row, _cell, val) => `Task ${val}`, + params: { useFormatterOuputToFilter: true } + }, + { + id: 'description', name: 'Description', field: 'description', filterable: true, sortable: true, minWidth: 80, + type: FieldType.string, + }, + { + id: 'percentComplete', name: '% Complete', field: 'percentComplete', minWidth: 120, + sortable: true, + customTooltip: { position: 'center' }, + formatter: Formatters.progressBar, + type: FieldType.number, + filterable: true, + filter: { + model: Filters.sliderRange, + maxValue: 100, // or you can use the filterOptions as well + operator: OperatorType.rangeInclusive, // defaults to inclusive + filterOptions: { + hideSliderNumbers: false, // you can hide/show the slider numbers on both side + min: 0, step: 5 + } as SliderRangeOption + } + }, + { + id: 'start', name: 'Start', field: 'start', formatter: Formatters.dateIso, sortable: true, minWidth: 75, width: 100, exportWithFormatter: true, + type: FieldType.date, filterable: true, filter: { model: Filters.compoundDate } + }, + { + id: 'finish', name: 'Finish', field: 'finish', formatter: Formatters.dateIso, sortable: true, minWidth: 75, width: 120, exportWithFormatter: true, + type: FieldType.date, + filterable: true, + filter: { + model: Filters.dateRange, + } + }, + { + id: 'duration', field: 'duration', name: 'Duration', maxWidth: 90, + type: FieldType.number, + sortable: true, + filterable: true, + filter: { + model: Filters.input, + operator: OperatorType.rangeExclusive // defaults to exclusive + } + }, + { + id: 'completed', name: 'Completed', field: 'completed', minWidth: 85, maxWidth: 90, + formatter: Formatters.checkmarkMaterial, + exportWithFormatter: true, // you can set this property in the column definition OR in the grid options, column def has priority over grid options + filterable: true, + filter: { + collection: [{ value: '', label: '' }, { value: true, label: 'True' }, { value: false, label: 'False' }], + model: Filters.singleSelect, + filterOptions: { autoAdjustDropHeight: true } as MultipleSelectOption + } + } + ]; + + this.gridOptions = { + autoResize: { + container: '#demo-container', + bottomPadding: this.paginationPosition === 'top' ? -1 : 38 // use a negative bottom padding since we've prepended custom pagination + }, + enableExcelCopyBuffer: true, + enableFiltering: true, + customPaginationComponent: CustomPagerComponent, // load our Custom Pagination Component + enablePagination: true, + pagination: { + pageSize: this.pageSize + }, + rowHeight: 40, + }; + } + + loadData(itemCount: number): any[] { + // mock a dataset + const tempDataset: any[] = []; + for (let i = 0, ln = itemCount; i < ln; i++) { + const randomDuration = randomBetween(0, 365); + const randomYear = randomBetween(new Date().getFullYear(), new Date().getFullYear() + 1); + const randomMonth = randomBetween(0, 12); + const randomDay = randomBetween(10, 28); + const randomPercent = randomBetween(0, 100); + + tempDataset.push({ + id: i, + title: 'Task ' + i, + description: (i % 5) ? 'desc ' + i : null, // also add some random to test NULL field + duration: randomDuration, + percentComplete: randomPercent, + percentCompleteNumber: randomPercent, + start: (i % 4) ? null : new Date(randomYear, randomMonth, randomDay), // provide a Date format + finish: new Date(randomYear, randomMonth, randomDay), + completed: (randomPercent === 100) ? true : false, + }); + } + + return tempDataset; + } + + pageSizeChanged(pageSize: number) { + this.aureliaGrid.paginationService?.changeItemPerPage(pageSize); + } + + togglePaginationPosition() { + const gridContainerElm = document.querySelector(`#${this.aureliaGrid.slickGrid.getOptions().gridContainerId || ''}`) as HTMLElement; + this.paginationPosition = this.paginationPosition === 'top' ? 'bottom' : 'top'; + (this.aureliaGrid.paginationComponent as CustomPagerComponent)?.disposeElement(); + (this.aureliaGrid.paginationComponent as CustomPagerComponent)?.renderPagination(gridContainerElm, this.paginationPosition); + } +} diff --git a/packages/demo/src/examples/slickgrid/example8.scss b/packages/demo/src/examples/slickgrid/example8.scss index 95c9c56d1..ab45accb7 100644 --- a/packages/demo/src/examples/slickgrid/example8.scss +++ b/packages/demo/src/examples/slickgrid/example8.scss @@ -1,11 +1,10 @@ -$slick-header-menu-button-border-width: 0px 1px; -$slick-header-menu-button-icon-svg-path: "M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M7,10L12,15L17,10H7Z"; -$slick-header-menu-button-icon-size: 16px; -$slick-header-menu-button-padding: 10px 0 0 3px; -$slick-sort-indicator-hint-opacity: 0; - -/* make sure to add the @import the SlickGrid Bootstrap Theme AFTER the variables changes */ -@import '@slickgrid-universal/common/dist/styles/sass/slickgrid-theme-bootstrap.scss'; +@use '@slickgrid-universal/common/dist/styles/sass/slickgrid-theme-bootstrap.scss' with ( + $slick-header-menu-button-border-width: 0px 1px, + $slick-header-menu-button-icon-svg-path: "M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M7,10L12,15L17,10H7Z", + $slick-header-menu-button-icon-size: 16px, + $slick-header-menu-button-padding: 10px 0 0 3px, + $slick-sort-indicator-hint-opacity: 0, +); .blue { color: rgb(73, 73, 255); diff --git a/packages/demo/src/examples/slickgrid/example9.scss b/packages/demo/src/examples/slickgrid/example9.scss index 27edccf97..e5567a0e0 100644 --- a/packages/demo/src/examples/slickgrid/example9.scss +++ b/packages/demo/src/examples/slickgrid/example9.scss @@ -1,11 +1,11 @@ -$slick-column-picker-icon-checked-svg-path: "M19,3H5A2,2 0 0,0 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V5A2,2 0 0,0 19,3M19,5V19H5V5H19M10,17L6,13L7.41,11.58L10,14.17L16.59,7.58L18,9"; -$slick-column-picker-icon-unchecked-svg-path: "M19,3H5C3.89,3 3,3.89 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V5C21,3.89 20.1,3 19,3M19,5V19H5V5H19Z"; $slickcolumn-picker-checkbox-opacity: 0.2; $slickcolumn-picker-checkbox-opacity-hover: 0.35; -$slick-column-picker-icon-font-size: 16px; -/* make sure to add the @import the SlickGrid Bootstrap Theme AFTER the variables changes */ -@import '@slickgrid-universal/common/dist/styles/sass/slickgrid-theme-bootstrap.scss'; +@use '@slickgrid-universal/common/dist/styles/sass/slickgrid-theme-bootstrap.scss' with ( + $slick-column-picker-icon-checked-svg-path: "M19,3H5A2,2 0 0,0 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V5A2,2 0 0,0 19,3M19,5V19H5V5H19M10,17L6,13L7.41,11.58L10,14.17L16.59,7.58L18,9", + $slick-column-picker-icon-unchecked-svg-path: "M19,3H5C3.89,3 3,3.89 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V5C21,3.89 20.1,3 19,3M19,5V19H5V5H19Z", + $slick-column-picker-icon-font-size: 16px +); .blue { color: rgb(73, 73, 255); diff --git a/packages/demo/src/main.ts b/packages/demo/src/main.ts index 3a11ba7eb..6b07eb53a 100644 --- a/packages/demo/src/main.ts +++ b/packages/demo/src/main.ts @@ -13,6 +13,7 @@ import { DateFormatValueConverter, DecimalValueConverter, StringifyValueConverte import 'bootstrap'; // dynamic components that can be enhanced in Example 19, 26 +import { CustomPagerComponent } from './examples/slickgrid/example42-pager'; import { CustomTitleFormatter } from './examples/slickgrid/custom-title-formatter'; import { EditorSelect } from './examples/slickgrid/editor-select'; import { FilterSelect } from './examples/slickgrid/filter-select'; @@ -32,6 +33,7 @@ Aurelia // dynamic components to enhance CustomTitleFormatter, + CustomPagerComponent, Example19DetailView, Example19Preload, EditorSelect, diff --git a/packages/demo/src/my-app.ts b/packages/demo/src/my-app.ts index 6e8868ef1..62189a05d 100644 --- a/packages/demo/src/my-app.ts +++ b/packages/demo/src/my-app.ts @@ -46,6 +46,7 @@ export class MyApp { { path: 'example39', component: () => import('./examples/slickgrid/example39'), title: '39- Infinite Scroll with GraphQL' }, { path: 'example40', component: () => import('./examples/slickgrid/example40'), title: '40- Infinite Scroll from JSON data' }, { path: 'example41', component: () => import('./examples/slickgrid/example41'), title: '41- Drag & Drop' }, + { path: 'example42', component: () => import('./examples/slickgrid/example42'), title: '42- Custom Pagination' }, { path: 'home', component: () => import('./home-page'), title: 'Home' }, ]; diff --git a/packages/demo/src/styles.scss b/packages/demo/src/styles.scss index 37798c388..bfd88f24c 100644 --- a/packages/demo/src/styles.scss +++ b/packages/demo/src/styles.scss @@ -1,12 +1,14 @@ @use 'sass:color'; -$slick-input-focus-box-shadow: 0 0 0 0.25rem #0d6efd40; -$slick-button-border-color: #ababab !default; $navbar-height: 56px; $side-menu-width: 250px; +$button-border-color: #ababab; -/* make sure to add the @import the SlickGrid Bootstrap Theme AFTER the variables changes */ -@import '@slickgrid-universal/common/dist/styles/sass/slickgrid-theme-bootstrap.scss'; +/* make sure to add the @use the SlickGrid Bootstrap Theme AFTER the variables changes */ +@use '@slickgrid-universal/common/dist/styles/sass/slickgrid-theme-bootstrap.scss' with ( + $slick-input-focus-box-shadow: 0 0 0 0.25rem #0d6efd40, + $slick-button-border-color: $button-border-color +); .btn-group-xs > .btn, .btn-xs { padding : 1px 5px; @@ -143,12 +145,12 @@ outline: 0 none; .button-style { cursor: pointer; background-color: white; - border: 1px solid #{$slick-button-border-color}; + border: 1px solid #{$button-border-color}; border-radius: 2px; justify-content: center; text-align: center; &:hover { - border-color: color.adjust($slick-button-border-color, $lightness: -10%); + border-color: color.adjust($button-border-color, $lightness: -10%); } } @@ -163,14 +165,14 @@ outline: 0 none; .button-style { cursor: pointer; - background-color: var(--slick-button-style-bg-color, $slick-button-style-bg-color); - border: 1px solid #{var(--slick-button-border-color, $slick-button-border-color)}; + background-color: var(--slick-button-style-bg-color, #fff); + border: 1px solid #{var(--slick-button-border-color, $button-border-color)}; border-radius: 2px; justify-content: center; text-align: center; &:hover { - border-color: color.adjust($slick-button-border-color, $lightness: -10%); + border-color: color.adjust($button-border-color, $lightness: -10%); } } diff --git a/packages/demo/webpack.config.js b/packages/demo/webpack.config.js index 803e51091..b180db430 100644 --- a/packages/demo/webpack.config.js +++ b/packages/demo/webpack.config.js @@ -55,6 +55,14 @@ module.exports = ({ production, node } = {}, { server } = {}, { analyze } = {}) } }, devServer: { + client: { + overlay: { + errors: true, + runtimeErrors: true, + warnings: false + }, + progress: true, + }, historyApiFallback: true, open: !process.env.CI, port: 9000 diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 367f593e7..316ca142e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -40,8 +40,8 @@ importers: specifier: ^3.10.0 version: 3.10.0(@types/node@22.7.7)(typescript@5.6.3) '@slickgrid-universal/common': - specifier: ^5.8.0 - version: 5.8.0 + specifier: ^5.9.0 + version: 5.9.0 '@types/jest': specifier: ^29.5.13 version: 29.5.13 @@ -130,26 +130,26 @@ importers: specifier: ^0.1.2 version: 0.1.2 '@slickgrid-universal/common': - specifier: ~5.8.0 - version: 5.8.0 + specifier: ~5.9.0 + version: 5.9.0 '@slickgrid-universal/custom-footer-component': - specifier: ~5.8.0 - version: 5.8.0 + specifier: ~5.9.0 + version: 5.9.0 '@slickgrid-universal/empty-warning-component': - specifier: ~5.8.0 - version: 5.8.0 + specifier: ~5.9.0 + version: 5.9.0 '@slickgrid-universal/event-pub-sub': - specifier: ~5.8.0 - version: 5.8.0 + specifier: ~5.9.0 + version: 5.9.0 '@slickgrid-universal/pagination-component': - specifier: ~5.8.0 - version: 5.8.0 + specifier: ~5.9.0 + version: 5.9.0 '@slickgrid-universal/row-detail-view-plugin': - specifier: ~5.8.0 - version: 5.8.0 + specifier: ~5.9.0 + version: 5.9.0 '@slickgrid-universal/utils': - specifier: ~5.8.0 - version: 5.8.0 + specifier: ~5.9.0 + version: 5.9.0 aurelia: specifier: ^2.0.0-beta.22 version: 2.0.0-beta.22 @@ -215,32 +215,32 @@ importers: specifier: ^2.11.8 version: 2.11.8 '@slickgrid-universal/common': - specifier: ^5.8.0 - version: 5.8.0 + specifier: ^5.9.0 + version: 5.9.0 '@slickgrid-universal/composite-editor-component': - specifier: ^5.8.0 - version: 5.8.0 + specifier: ^5.9.0 + version: 5.9.0 '@slickgrid-universal/custom-tooltip-plugin': - specifier: ^5.8.0 - version: 5.8.0 + specifier: ^5.9.0 + version: 5.9.0 '@slickgrid-universal/excel-export': - specifier: ^5.8.0 - version: 5.8.0 + specifier: ^5.9.0 + version: 5.9.0 '@slickgrid-universal/graphql': - specifier: ^5.8.0 - version: 5.8.0 + specifier: ^5.9.0 + version: 5.9.0 '@slickgrid-universal/odata': - specifier: ^5.8.0 - version: 5.8.0 + specifier: ^5.9.0 + version: 5.9.0 '@slickgrid-universal/row-detail-view-plugin': - specifier: ^5.8.0 - version: 5.8.0 + specifier: ^5.9.0 + version: 5.9.0 '@slickgrid-universal/rxjs-observable': - specifier: ^5.8.0 - version: 5.8.0 + specifier: ^5.9.0 + version: 5.9.0 '@slickgrid-universal/text-export': - specifier: ^5.8.0 - version: 5.8.0 + specifier: ^5.9.0 + version: 5.9.0 aurelia: specifier: ^2.0.0-beta.22 version: 2.0.0-beta.22 @@ -251,8 +251,8 @@ importers: specifier: ^5.3.3 version: 5.3.3(@popperjs/core@2.11.8) i18next: - specifier: ^23.15.1 - version: 23.15.1 + specifier: ^23.16.1 + version: 23.16.1 i18next-fetch-backend: specifier: ^6.0.0 version: 6.0.0 @@ -999,8 +999,8 @@ packages: levn: 0.4.1 dev: true - /@excel-builder-vanilla/types@3.0.7: - resolution: {integrity: sha512-WDvLaT5eHAQUHnOXFoMSfse3ePWZMros9TEbmG468iXm0Qmrft9bTIHUWo+VtLhJWVEx6XHN6LJHbpZ43EmPjw==} + /@excel-builder-vanilla/types@3.0.14: + resolution: {integrity: sha512-9gq9hPPdVGzz/3fESgVW6WlxienIxpr83QnGS364cRPmzxg3cZQewZvKns2DFYfLLMxBLH3L6PperVqInR+0ag==} dependencies: fflate: 0.8.2 @@ -2127,114 +2127,114 @@ packages: '@sinonjs/commons': 3.0.1 dev: true - /@slickgrid-universal/binding@5.8.0: - resolution: {integrity: sha512-+XJEtey7Y0SHX4KYHFJyxxxG9BDME4MlNnyKRAq6zI8csGozNT5/b9pheS3gHD4ZrCWNuabczMxya+849+07lg==} + /@slickgrid-universal/binding@5.9.0: + resolution: {integrity: sha512-u3tP6UMbDdG+bBuOrxajN18l/KI0qMN6QoMkY/JjFNgV9E/Iq/EYa0QafZyV6DJnwdQD2ZlBb2nBqFj1MEIP4w==} - /@slickgrid-universal/common@5.8.0: - resolution: {integrity: sha512-9NU6PhxaoL4ZvsAS8piBwl4ROrPDkvANyGpCFxUpxSmo1I27sfnGdQXwKuTdISoLdewTBXTajEO/pr7HAOHA8A==} + /@slickgrid-universal/common@5.9.0: + resolution: {integrity: sha512-l3HlQB8zKhllhwg8kQuKi8+4Lozfe3mVoXJr6MUbiWX8gauYPy0ZTRO9gS+Y7LgxYJzNKuyzanGIbWYC6Dqogw==} engines: {node: ^18.0.0 || >=20.0.0} dependencies: - '@excel-builder-vanilla/types': 3.0.7 + '@excel-builder-vanilla/types': 3.0.14 '@formkit/tempo': 0.1.2 - '@slickgrid-universal/binding': 5.8.0 - '@slickgrid-universal/event-pub-sub': 5.8.0 - '@slickgrid-universal/utils': 5.8.0 + '@slickgrid-universal/binding': 5.9.0 + '@slickgrid-universal/event-pub-sub': 5.9.0 + '@slickgrid-universal/utils': 5.9.0 '@types/sortablejs': 1.15.8 '@types/trusted-types': 2.0.7 autocompleter: 9.3.2 dequal: 2.0.3 - multiple-select-vanilla: 3.3.4 + multiple-select-vanilla: 3.3.7 sortablejs: 1.15.3 un-flatten-tree: 2.0.12 vanilla-calendar-pro: 2.9.10 - /@slickgrid-universal/composite-editor-component@5.8.0: - resolution: {integrity: sha512-teJ6Z/qVnYVIUN/0Q/h/7OFdySAatrZVACOXc7EBLFgyrnD80FIYxLMui2P1xkZYLsHHOmJiTueQe/8l/agYxw==} + /@slickgrid-universal/composite-editor-component@5.9.0: + resolution: {integrity: sha512-ufmWDG7GWVvuOjTzbQVEr+gSrpkYmC8c8FMyWIvzUSkofwiljHK1SVqJ/maRqkNFhMwFmTdtlLw+ChLxtRlDOw==} dependencies: - '@slickgrid-universal/binding': 5.8.0 - '@slickgrid-universal/common': 5.8.0 - '@slickgrid-universal/utils': 5.8.0 + '@slickgrid-universal/binding': 5.9.0 + '@slickgrid-universal/common': 5.9.0 + '@slickgrid-universal/utils': 5.9.0 dev: false - /@slickgrid-universal/custom-footer-component@5.8.0: - resolution: {integrity: sha512-jyKIx/9wemcT1CCIHBv7HbemBPqfOK8izEQv+yd2CiwtdlhXVpnzD1qWO25Q1RpEWCN67sEdzXUVnQGmzHX5VQ==} + /@slickgrid-universal/custom-footer-component@5.9.0: + resolution: {integrity: sha512-yjQZXk7TTvlis7uoBFRrLOitd+FiV9z89czWjBOo+QyJ4hfwGFXrbsiQDJcx5DrjcjdltKpp0ia5ZDLgz1o+Lg==} dependencies: '@formkit/tempo': 0.1.2 - '@slickgrid-universal/binding': 5.8.0 - '@slickgrid-universal/common': 5.8.0 + '@slickgrid-universal/binding': 5.9.0 + '@slickgrid-universal/common': 5.9.0 dev: false - /@slickgrid-universal/custom-tooltip-plugin@5.8.0: - resolution: {integrity: sha512-A5ff/R+S/zK6PHBWiyoyj3gvBEnhhiE1/nsyPkXwmR9lDJresnPkS3e/LVvvlcEe2kOkiNDC//XEyNIgsiOQEQ==} + /@slickgrid-universal/custom-tooltip-plugin@5.9.0: + resolution: {integrity: sha512-6bTr1Zg2xsLIMZRKkmoWGlGa/EXKhJimNTHAfjb/hK2I0Kl9ODl72QMd6Dpm2WeH7Bg5mxFLzkSKr7sml1xYTw==} dependencies: - '@slickgrid-universal/common': 5.8.0 - '@slickgrid-universal/utils': 5.8.0 + '@slickgrid-universal/common': 5.9.0 + '@slickgrid-universal/utils': 5.9.0 dev: false - /@slickgrid-universal/empty-warning-component@5.8.0: - resolution: {integrity: sha512-fNhT1gJH45PcNISrE73220s7OqdPBHN9c6117Cc3mpu2uXj84iLUTgd66MkotglEnINketLCskolsdUCQ/zepA==} + /@slickgrid-universal/empty-warning-component@5.9.0: + resolution: {integrity: sha512-gjYgvDDhOMh0R4qV8/ZDaAw0eqISfc9a+5JKBzC284n0acgDuQRmWevtSjhV66pIrHTZ5MAQNlZoVsIabKOeTg==} dependencies: - '@slickgrid-universal/common': 5.8.0 + '@slickgrid-universal/common': 5.9.0 dev: false - /@slickgrid-universal/event-pub-sub@5.8.0: - resolution: {integrity: sha512-77yuw4yDjRJ7zJJ8GMaTL4R1+9iMvIogT4rd7Hjc5sEH5aVLHNRK95Cgj/OaWa7SB+mlU0v0bTs22omgKbMAFg==} + /@slickgrid-universal/event-pub-sub@5.9.0: + resolution: {integrity: sha512-KnpY/WCTIwm6jWrX2RDKmDb1ifT2u4xs+1CPGWOWY6qQ/J0Fl9Ah25sZj/mM20BZvmg5/oCu7c9F62TdSiU3Zg==} dependencies: - '@slickgrid-universal/utils': 5.8.0 + '@slickgrid-universal/utils': 5.9.0 - /@slickgrid-universal/excel-export@5.8.0: - resolution: {integrity: sha512-sMWOOcdjmW9HnNVqY7/YIXceX6sGVJN1XDP2qHBOvZe7aOAd3d5/AUZyl6y3GVfy9dBgxQovsxsjQEDzCf3ZqA==} + /@slickgrid-universal/excel-export@5.9.0: + resolution: {integrity: sha512-pakTTesp2YH6hni5sq0ZQkHSBJvbkUBIjWCaSDUwHZXcrTwHmVWPd55kzL9yabyZ3urbEmkvh0H1lAnegPei4Q==} dependencies: - '@slickgrid-universal/common': 5.8.0 - '@slickgrid-universal/utils': 5.8.0 - excel-builder-vanilla: 3.0.6 + '@slickgrid-universal/common': 5.9.0 + '@slickgrid-universal/utils': 5.9.0 + excel-builder-vanilla: 3.0.14 dev: false - /@slickgrid-universal/graphql@5.8.0: - resolution: {integrity: sha512-OAu4KHdL9JZtwJ0l/47UTTh9VRcNdUF7/U5j4l1oWqxBXtuUonM3qDfVL1sL+3zO85EO8SgY8RWR3NMNV/0CQA==} + /@slickgrid-universal/graphql@5.9.0: + resolution: {integrity: sha512-m/E08Q37Lg6JBscDqvcZO65ZZuTy2zBt+1iggq6RxufQdYwmZjoj7WpRUAeEOigAk0CtnxvYPdPP6FAfkGWSIQ==} dependencies: - '@slickgrid-universal/common': 5.8.0 - '@slickgrid-universal/utils': 5.8.0 + '@slickgrid-universal/common': 5.9.0 + '@slickgrid-universal/utils': 5.9.0 dev: false - /@slickgrid-universal/odata@5.8.0: - resolution: {integrity: sha512-KMyoc4EJB5x+rFelVrTcCrIx6BzmKCm57NQQ3B4uXkE6fQTpCOrT5jNQ79afle6/x5WLoWcKMMlaWFpcULYgkg==} + /@slickgrid-universal/odata@5.9.0: + resolution: {integrity: sha512-llgrrNZhd66jwr4d8HtGPzK15m+W4nzNQ1tkNksTd5EHjD3FDJGB3bqFAdwv5aX0YRYgSC2l7dvTxfY50AVx/A==} dependencies: - '@slickgrid-universal/common': 5.8.0 - '@slickgrid-universal/utils': 5.8.0 + '@slickgrid-universal/common': 5.9.0 + '@slickgrid-universal/utils': 5.9.0 dev: false - /@slickgrid-universal/pagination-component@5.8.0: - resolution: {integrity: sha512-2qwdEk+AHzq1yn9ZwPQwG6u8ljzaTSVjiYJxCXlfN6/+43IdlK6fhDkANcvAGEbFDHYDFoquT3/B971nUVerXw==} + /@slickgrid-universal/pagination-component@5.9.0: + resolution: {integrity: sha512-8R2X9/CUujT4LGGGnq3tZt8qzbhxsGUKEKdWxgn+2WYm87gkH1Rcw4YXABRzM2B93P1US0tUmoRds1DrQ5TG4w==} dependencies: - '@slickgrid-universal/binding': 5.8.0 - '@slickgrid-universal/common': 5.8.0 + '@slickgrid-universal/binding': 5.9.0 + '@slickgrid-universal/common': 5.9.0 dev: false - /@slickgrid-universal/row-detail-view-plugin@5.8.0: - resolution: {integrity: sha512-tyEb/uJh5eg6AhUMEftp8qnzkpRPOLt8R5E7bOMAaR5Zr3Gd0Je0yioHGYEHYxeFizSqvgEzjvbp60jK1fsKUA==} + /@slickgrid-universal/row-detail-view-plugin@5.9.0: + resolution: {integrity: sha512-QkOoGODCABsvRPoeHG4lAd6fOFAIh2fRsrbnvgeVPXQ8dXGoPUKAW2jMbuVPm0cX+YDiydh2O/1lSpGptXphCA==} dependencies: - '@slickgrid-universal/common': 5.8.0 - '@slickgrid-universal/utils': 5.8.0 + '@slickgrid-universal/common': 5.9.0 + '@slickgrid-universal/utils': 5.9.0 dev: false - /@slickgrid-universal/rxjs-observable@5.8.0: - resolution: {integrity: sha512-o7EK9wxoZ3WlI9cdAH3NGWQ4kl6YLR2g1fty1lX+iNq2/pBn0zapQURQoQu5rn0LCdpVmt6AgYVLjUbFjST5CQ==} + /@slickgrid-universal/rxjs-observable@5.9.0: + resolution: {integrity: sha512-tNyLV5NX26ZKFrMs0nmH+qHkI9tiTI3qHv1GcZmVbPKYDMoqo3DjZdkIQoNwNaI1MopArUv1QIcs/Rw9XnQRYg==} dependencies: - '@slickgrid-universal/common': 5.8.0 + '@slickgrid-universal/common': 5.9.0 rxjs: 7.8.1 dev: false - /@slickgrid-universal/text-export@5.8.0: - resolution: {integrity: sha512-Z6JUIMmkEdZRLxXsSr5Bv7IFq3HNckwbVEtk9fQbWZ1Eey2ClcpHe1IL/UJEXF+csRHGfaEmX8f2gfSEdwmqhQ==} + /@slickgrid-universal/text-export@5.9.0: + resolution: {integrity: sha512-4g/mjESz3YtN+ysAz4B/cl1m6nvyiShRvqzowHIaHwwZdKkOTb6wvX03ftBiPwppVhFxY94m9cX1u1c6lKsoOg==} dependencies: - '@slickgrid-universal/common': 5.8.0 - '@slickgrid-universal/utils': 5.8.0 + '@slickgrid-universal/common': 5.9.0 + '@slickgrid-universal/utils': 5.9.0 text-encoding-utf-8: 1.0.2 dev: false - /@slickgrid-universal/utils@5.8.0: - resolution: {integrity: sha512-fUDKcI9hsqWKeXQlQbinSYgCIFtDVwK2d3BP9mGvP7NmaWDIKkmCQzrBkPV3fHWV875pXvYHDHOyvsj13FnaXg==} + /@slickgrid-universal/utils@5.9.0: + resolution: {integrity: sha512-2A/OoTvautUZ4FR86E9npoIA6f0iFSEqqiXivmKdQK3Ed0UAQEGak639p1dkFAHfbJxd7U7l6Gx0n0vtgjNu/Q==} /@tootallnate/once@2.0.0: resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==} @@ -4739,8 +4739,8 @@ packages: engines: {node: '>=0.8.x'} dev: true - /excel-builder-vanilla@3.0.6: - resolution: {integrity: sha512-WV+I1DgJ30TfqhjqEJZsp9G2wpSm+N/4Wk+EmP552NzW4wjGYq4bjw59jddetbrFyaCNBxXVcyOK2ae8z6zfaQ==} + /excel-builder-vanilla@3.0.14: + resolution: {integrity: sha512-lXjyxAVVSwkHIikzCpQq+ydtrXWIGec/x6f5IzZV30BvW30i1adzNISSuq+OZqMuxbffKgmH0wgRkvSrl9WHgg==} dependencies: fflate: 0.8.2 dev: false @@ -5649,6 +5649,12 @@ packages: dependencies: '@babel/runtime': 7.24.1 + /i18next@23.16.1: + resolution: {integrity: sha512-H73h/H7BN7PI38Sq9XsOXzWFBH6mtyCYFiUMVtd9BxiYNDWPPIzKcBmDrqhjKbw3IXP5j6JoSW4ugJlaZuOvKw==} + dependencies: + '@babel/runtime': 7.24.1 + dev: false + /iconv-lite@0.4.24: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} engines: {node: '>=0.10.0'} @@ -7178,8 +7184,8 @@ packages: minimatch: 9.0.5 dev: true - /multiple-select-vanilla@3.3.4: - resolution: {integrity: sha512-NQuuoJqj+LY9JAhg94qvGIXPELKQpVlocuegxi1vhADvUnZSFbbgflcryO3CgcHII77zkWl82U0sFs8tLpBmlg==} + /multiple-select-vanilla@3.3.7: + resolution: {integrity: sha512-SpaHK0r2Kd343nRUSQsJxCdsy7Gt6l1K71NDDEohgmUAOPrM2j6+FSPRjr3W2E7fAyltT9ihyW0RY5FrmHZPgg==} dependencies: '@types/trusted-types': 2.0.7 diff --git a/test/cypress/e2e/example42.cy.ts b/test/cypress/e2e/example42.cy.ts new file mode 100644 index 000000000..15e9b0eff --- /dev/null +++ b/test/cypress/e2e/example42.cy.ts @@ -0,0 +1,82 @@ +describe('Example 42 - Custom Pagination', () => { + const GRID_ROW_HEIGHT = 40; + const titles = ['Title', 'Description', '% Complete', 'Start', 'Finish', 'Duration', 'Completed']; + + it('should display Example title', () => { + cy.visit(`${Cypress.config('baseUrl')}/example42`); + cy.get('h2').should('contain', 'Example 42: Custom Pagination'); + }); + + it('should have exact Column Titles in the grid', () => { + cy.get('.slick-header-columns') + .children() + .each(($child, index) => expect($child.text()).to.eq(titles[index])); + }); + + it('should expect first row to be Task 0', () => { + cy.get('.seek-first').should('have.class', 'disabled'); + cy.get('.seek-prev').should('have.class', 'disabled'); + cy.get('.item-from').should('contain', 1); + cy.get('.item-to').should('contain', 50); + cy.get(`[style="top: ${GRID_ROW_HEIGHT * 0}px;"] > .slick-cell:nth(0)`).should('contain', 'Task 0'); + cy.get(`[style="top: ${GRID_ROW_HEIGHT * 1}px;"] > .slick-cell:nth(0)`).should('contain', 'Task 1'); + cy.get(`[style="top: ${GRID_ROW_HEIGHT * 2}px;"] > .slick-cell:nth(0)`).should('contain', 'Task 2'); + cy.get(`[style="top: ${GRID_ROW_HEIGHT * 3}px;"] > .slick-cell:nth(0)`).should('contain', 'Task 3'); + cy.get(`[style="top: ${GRID_ROW_HEIGHT * 4}px;"] > .slick-cell:nth(0)`).should('contain', 'Task 4'); + }); + + it('should click on next page and expect top row to be Task 50', () => { + cy.get('.page-item.seek-next').click(); + + cy.get('.seek-first').should('not.have.class', 'disabled'); + cy.get('.seek-prev').should('not.have.class', 'disabled'); + cy.get('.item-from').should('contain', 51); + cy.get('.item-to').should('contain', 100); + cy.get(`[style="top: ${GRID_ROW_HEIGHT * 0}px;"] > .slick-cell:nth(0)`).should('contain', 'Task 50'); + cy.get(`[style="top: ${GRID_ROW_HEIGHT * 1}px;"] > .slick-cell:nth(0)`).should('contain', 'Task 51'); + cy.get(`[style="top: ${GRID_ROW_HEIGHT * 2}px;"] > .slick-cell:nth(0)`).should('contain', 'Task 52'); + cy.get(`[style="top: ${GRID_ROW_HEIGHT * 3}px;"] > .slick-cell:nth(0)`).should('contain', 'Task 53'); + cy.get(`[style="top: ${GRID_ROW_HEIGHT * 4}px;"] > .slick-cell:nth(0)`).should('contain', 'Task 54'); + }); + + it('should click on goto last page and expect top row to be Task 50', () => { + cy.get('.page-item.seek-end').click(); + + cy.get('.seek-next').should('have.class', 'disabled'); + cy.get('.seek-end').should('have.class', 'disabled'); + cy.get('.item-from').should('contain', 4951); + cy.get('.item-to').should('contain', 5000); + cy.get(`[style="top: ${GRID_ROW_HEIGHT * 0}px;"] > .slick-cell:nth(0)`).should('contain', 'Task 4950'); + cy.get(`[style="top: ${GRID_ROW_HEIGHT * 1}px;"] > .slick-cell:nth(0)`).should('contain', 'Task 4951'); + cy.get(`[style="top: ${GRID_ROW_HEIGHT * 2}px;"] > .slick-cell:nth(0)`).should('contain', 'Task 4952'); + cy.get(`[style="top: ${GRID_ROW_HEIGHT * 3}px;"] > .slick-cell:nth(0)`).should('contain', 'Task 4953'); + cy.get(`[style="top: ${GRID_ROW_HEIGHT * 4}px;"] > .slick-cell:nth(0)`).should('contain', 'Task 4954'); + }); + + it('should change page size and expect pagination to be updated', () => { + cy.get('[data-test="page-size-input"]').type('{backspace}{backspace}75'); + cy.get('.seek-first').should('have.class', 'disabled'); + cy.get('.seek-prev').should('have.class', 'disabled'); + cy.get('.item-from').should('contain', 1); + cy.get('.item-to').should('contain', 75); + cy.get(`[style="top: ${GRID_ROW_HEIGHT * 0}px;"] > .slick-cell:nth(0)`).should('contain', 'Task 0'); + cy.get(`[style="top: ${GRID_ROW_HEIGHT * 1}px;"] > .slick-cell:nth(0)`).should('contain', 'Task 1'); + cy.get(`[style="top: ${GRID_ROW_HEIGHT * 2}px;"] > .slick-cell:nth(0)`).should('contain', 'Task 2'); + cy.get(`[style="top: ${GRID_ROW_HEIGHT * 3}px;"] > .slick-cell:nth(0)`).should('contain', 'Task 3'); + cy.get(`[style="top: ${GRID_ROW_HEIGHT * 4}px;"] > .slick-cell:nth(0)`).should('contain', 'Task 4'); + }); + + it('should toggle pagination position to bottom', () => { + cy.get('[data-text="toggle-pagination-btn"]').click(); + cy.get('#pager.bottom').should('exist'); + cy.get('.page-item.seek-next').click(); + + cy.get('.item-from').should('contain', 76); + cy.get('.item-to').should('contain', 150); + cy.get(`[style="top: ${GRID_ROW_HEIGHT * 0}px;"] > .slick-cell:nth(0)`).should('contain', 'Task 75'); + cy.get(`[style="top: ${GRID_ROW_HEIGHT * 1}px;"] > .slick-cell:nth(0)`).should('contain', 'Task 76'); + cy.get(`[style="top: ${GRID_ROW_HEIGHT * 2}px;"] > .slick-cell:nth(0)`).should('contain', 'Task 77'); + cy.get(`[style="top: ${GRID_ROW_HEIGHT * 3}px;"] > .slick-cell:nth(0)`).should('contain', 'Task 78'); + cy.get(`[style="top: ${GRID_ROW_HEIGHT * 4}px;"] > .slick-cell:nth(0)`).should('contain', 'Task 79'); + }); +});