diff --git a/angular/demo/daisyui/src/app/samples/pagination/pagination.component.ts b/angular/demo/daisyui/src/app/samples/pagination/pagination.component.ts index ff483d804c..7412a44ee9 100644 --- a/angular/demo/daisyui/src/app/samples/pagination/pagination.component.ts +++ b/angular/demo/daisyui/src/app/samples/pagination/pagination.component.ts @@ -30,7 +30,6 @@ export class PaginationComponent extends BaseWidgetDirective { readonly collectionSize = input(undefined, {transform: auNumberAttribute}); readonly page = model(0); readonly pageSize = input(undefined, {transform: auNumberAttribute}); - readonly size = input(); readonly pagesFactory = input<(page: number, pageCount: number) => number[]>(); readonly className = input(); diff --git a/core-bootstrap/src/components/pagination/pagination.spec.ts b/core-bootstrap/src/components/pagination/pagination.spec.ts index 299271f424..24ce284536 100644 --- a/core-bootstrap/src/components/pagination/pagination.spec.ts +++ b/core-bootstrap/src/components/pagination/pagination.spec.ts @@ -3,6 +3,7 @@ import {beforeEach, describe, expect, test, vi} from 'vitest'; import type {PaginationState, PaginationWidget} from './pagination'; import {createPagination, getPaginationDefaultConfig} from './pagination'; import {ngBootstrapPagination} from './pageFactory'; +import {assign} from '../../../../common/utils'; describe(`Pagination`, () => { let pagination: PaginationWidget; @@ -27,41 +28,49 @@ describe(`Pagination`, () => { }; }); + const expectLogInvalidValue = () => { + expect(consoleErrorSpy).toHaveBeenCalledTimes(1); + expect(consoleErrorSpy.mock.calls[0][0]).toContain('invalid'); + consoleErrorSpy.mockClear(); + }; + + const expectedState: PaginationState = { + pageCount: 1, // total number of page + page: 1, // current page + pages: [1], // list of the visible pages + previousDisabled: true, + ariaLabel: 'Page navigation', + className: '', + nextDisabled: true, + disabled: false, + directionLinks: true, + boundaryLinks: false, + structure: undefined, + ellipsisLabel: '…', + firstPageLabel: '«', + previousPageLabel: '‹', + nextPageLabel: '›', + lastPageLabel: '»', + pagesDisplay: undefined, + numberLabel: getPaginationDefaultConfig().numberLabel, + size: null, + activeLabel: '(current)', + ariaFirstLabel: 'Action link for first page', + ariaLastLabel: 'Action link for last page', + ariaNextLabel: 'Action link for next page', + ariaPreviousLabel: 'Action link for previous page', + ariaEllipsisLabel: 'Ellipsis page element', + ariaLiveLabelText: 'Current page is 1', + directionsHrefs: { + next: '#', + previous: '#', + }, + pagesHrefs: ['#'], + pagesLabel: ['Page 1 of 1'], + }; + test(`should have sensible state`, () => { - expect(state).toStrictEqual({ - pageCount: 1, // total number of page - page: 1, // current page - pages: [1], // list of the visible pages - previousDisabled: true, - ariaLabel: 'Page navigation', - className: '', - nextDisabled: true, - disabled: false, - directionLinks: true, - boundaryLinks: false, - structure: undefined, - ellipsisLabel: '…', - firstPageLabel: '«', - previousPageLabel: '‹', - nextPageLabel: '›', - lastPageLabel: '»', - pagesDisplay: undefined, - numberLabel: state.numberLabel, - size: null, - activeLabel: '(current)', - ariaFirstLabel: 'Action link for first page', - ariaLastLabel: 'Action link for last page', - ariaNextLabel: 'Action link for next page', - ariaPreviousLabel: 'Action link for previous page', - ariaEllipsisLabel: 'Ellipsis page element', - ariaLiveLabelText: 'Current page is 1', - directionsHrefs: { - next: '#', - previous: '#', - }, - pagesHrefs: ['#'], - pagesLabel: ['Page 1 of 1'], - }); + expect(state).toStrictEqual(expectedState); }); test('should include a simple pageFactory implementation in default config', () => { @@ -224,4 +233,13 @@ describe(`Pagination`, () => { pagination.patch({page: 12}); expect(state.pages).toStrictEqual([1, -1, 8, 9, 10, 11, 12]); }); + + test('should warn using invalid size value', () => { + const state = {...expectedState}; + pagination.patch({size: 'invalidSize' as 'sm'}); + expect(state).toStrictEqual(assign(state, {size: null})); + expectLogInvalidValue(); + pagination.patch({size: 'sm'}); + expect(state).toStrictEqual(assign(state, {size: 'sm'})); + }); }); diff --git a/core-bootstrap/src/components/pagination/pagination.ts b/core-bootstrap/src/components/pagination/pagination.ts index 4b3e5ae64d..233dadd094 100644 --- a/core-bootstrap/src/components/pagination/pagination.ts +++ b/core-bootstrap/src/components/pagination/pagination.ts @@ -1,5 +1,5 @@ import {extendWidgetProps} from '@agnos-ui/core/services/extendWidget'; -import type {SlotContent, Widget, WidgetFactory, WidgetSlotContext} from '@agnos-ui/core/types'; +import type {ConfigValidator, SlotContent, Widget, WidgetFactory, WidgetSlotContext} from '@agnos-ui/core/types'; import type { PaginationApi, PaginationDirectives, @@ -7,6 +7,7 @@ import type { PaginationState as CoreState, } from '@agnos-ui/core/components/pagination'; import {createPagination as createCorePagination, getPaginationDefaultConfig as getCoreDefaultConfig} from '@agnos-ui/core/components/pagination'; +import {createTypeEnum} from '@agnos-ui/core/utils/writables'; export * from '@agnos-ui/core/components/pagination'; @@ -99,6 +100,15 @@ interface PaginationExtraProps { * ``` */ numberLabel: SlotContent; + + /** + * The pagination display size. + * + * Bootstrap currently supports small and large sizes. + * + * @defaultValue `null` + */ + size: 'sm' | 'lg' | null; } export interface PaginationState extends CoreState, PaginationExtraProps {} @@ -115,7 +125,21 @@ const defaultConfigExtraProps: PaginationExtraProps = { lastPageLabel: '»', numberLabel: ({displayedPage}: PaginationNumberContext) => `${displayedPage}`, pagesDisplay: undefined, + size: null, }; + +const configValidator: ConfigValidator = { + structure: undefined, + ellipsisLabel: undefined, + firstPageLabel: undefined, + previousPageLabel: undefined, + nextPageLabel: undefined, + lastPageLabel: undefined, + numberLabel: undefined, + pagesDisplay: undefined, + size: createTypeEnum(['lg', 'sm', null]), +}; + /** * Retrieve a shallow copy of the default Pagination config * @returns the default Pagination config @@ -129,4 +153,4 @@ export function getPaginationDefaultConfig(): PaginationProps { * @param config - an optional alert config * @returns a PaginationWidget */ -export const createPagination: WidgetFactory = extendWidgetProps(createCorePagination, defaultConfigExtraProps); +export const createPagination: WidgetFactory = extendWidgetProps(createCorePagination, defaultConfigExtraProps, configValidator); diff --git a/core/src/components/pagination/pagination.spec.ts b/core/src/components/pagination/pagination.spec.ts index ae814a1cb2..bd1acdd11b 100644 --- a/core/src/components/pagination/pagination.spec.ts +++ b/core/src/components/pagination/pagination.spec.ts @@ -44,7 +44,6 @@ describe(`Pagination`, () => { disabled: false, directionLinks: true, boundaryLinks: false, - size: null, activeLabel: '(current)', ariaFirstLabel: 'Action link for first page', ariaLastLabel: 'Action link for last page', @@ -65,14 +64,6 @@ describe(`Pagination`, () => { expect(getPaginationDefaultConfig().pagesFactory(5, 10)).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); }); - test('should warn using invalid size value', () => { - pagination.patch({size: 'invalidSize' as 'sm'}); - expect(state).toStrictEqual(assign(expectedState, {size: null})); - expectLogInvalidValue(); - pagination.patch({size: 'sm'}); - expect(state).toStrictEqual(assign(expectedState, {size: 'sm'})); - }); - test('actions should update the state', () => { pagination.patch({collectionSize: 200}); const pagesLabel = Array.from({length: 20}, (_, index) => `Page ${index + 1} of 20`); diff --git a/core/src/components/pagination/pagination.ts b/core/src/components/pagination/pagination.ts index 17c27a52dd..cf3f46fe0b 100644 --- a/core/src/components/pagination/pagination.ts +++ b/core/src/components/pagination/pagination.ts @@ -2,7 +2,7 @@ import {computed} from '@amadeus-it-group/tansu'; import type {ReadableSignal} from '@amadeus-it-group/tansu'; import {bindableProp, stateStores, writablesForProps} from '../../utils/stores'; import {clamp, isNumber} from '../../utils/internal/checks'; -import {createTypeEnum, typeBoolean, typeFunction, typeNumber, typeString} from '../../utils/writables'; +import {typeBoolean, typeFunction, typeNumber, typeString} from '../../utils/writables'; import type {ConfigValidator, PropsConfig, Widget, Directive} from '../../types'; import {noop} from '../../utils/internal/func'; import type {WidgetsCommonPropsAndState} from '../commonProps'; @@ -18,15 +18,6 @@ interface PaginationCommonPropsAndState extends WidgetsCommonPropsAndState { */ page: number; // value of the current/init page to display - /** - * The pagination display size. - * - * Bootstrap currently supports small and large sizes. - * - * @defaultValue `null` - */ - size: 'sm' | 'lg' | null; - /** * The label for the nav element. * @@ -335,7 +326,6 @@ const defaultConfig: PaginationProps = { disabled: false, directionLinks: true, boundaryLinks: false, - size: null, onPageChange: noop, pagesFactory: (_page: number, pageCount: number) => { const pages: number[] = []; @@ -372,7 +362,6 @@ const configValidator: ConfigValidator = { disabled: typeBoolean, directionLinks: typeBoolean, boundaryLinks: typeBoolean, - size: createTypeEnum(['lg', 'sm', null]), onPageChange: typeFunction, pagesFactory: typeFunction, ariaLabel: typeString,