Skip to content

Commit

Permalink
refactor(pagination): move size property from core to bootstrap-core (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
divdavem authored Oct 28, 2024
1 parent e311275 commit fd3cda6
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 58 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ export class PaginationComponent extends BaseWidgetDirective<PaginationWidget> {
readonly collectionSize = input(undefined, {transform: auNumberAttribute});
readonly page = model(0);
readonly pageSize = input(undefined, {transform: auNumberAttribute});
readonly size = input<string>();
readonly pagesFactory = input<(page: number, pageCount: number) => number[]>();
readonly className = input<string>();

Expand Down
86 changes: 52 additions & 34 deletions core-bootstrap/src/components/pagination/pagination.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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', () => {
Expand Down Expand Up @@ -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'}));
});
});
28 changes: 26 additions & 2 deletions core-bootstrap/src/components/pagination/pagination.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
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,
PaginationProps as CoreProps,
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';

Expand Down Expand Up @@ -99,6 +100,15 @@ interface PaginationExtraProps {
* ```
*/
numberLabel: SlotContent<PaginationNumberContext>;

/**
* The pagination display size.
*
* Bootstrap currently supports small and large sizes.
*
* @defaultValue `null`
*/
size: 'sm' | 'lg' | null;
}

export interface PaginationState extends CoreState, PaginationExtraProps {}
Expand All @@ -115,7 +125,21 @@ const defaultConfigExtraProps: PaginationExtraProps = {
lastPageLabel: '»',
numberLabel: ({displayedPage}: PaginationNumberContext) => `${displayedPage}`,
pagesDisplay: undefined,
size: null,
};

const configValidator: ConfigValidator<PaginationExtraProps> = {
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
Expand All @@ -129,4 +153,4 @@ export function getPaginationDefaultConfig(): PaginationProps {
* @param config - an optional alert config
* @returns a PaginationWidget
*/
export const createPagination: WidgetFactory<PaginationWidget> = extendWidgetProps(createCorePagination, defaultConfigExtraProps);
export const createPagination: WidgetFactory<PaginationWidget> = extendWidgetProps(createCorePagination, defaultConfigExtraProps, configValidator);
9 changes: 0 additions & 9 deletions core/src/components/pagination/pagination.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand All @@ -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`);
Expand Down
13 changes: 1 addition & 12 deletions core/src/components/pagination/pagination.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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.
*
Expand Down Expand Up @@ -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[] = [];
Expand Down Expand Up @@ -372,7 +362,6 @@ const configValidator: ConfigValidator<PaginationProps> = {
disabled: typeBoolean,
directionLinks: typeBoolean,
boundaryLinks: typeBoolean,
size: createTypeEnum(['lg', 'sm', null]),
onPageChange: typeFunction,
pagesFactory: typeFunction,
ariaLabel: typeString,
Expand Down

0 comments on commit fd3cda6

Please sign in to comment.