Skip to content

Commit

Permalink
fix(Pagination): fix locale support (#1651)
Browse files Browse the repository at this point in the history
  • Loading branch information
tujoworker committed Oct 21, 2022
1 parent d5437bb commit 01b93ce
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 23 deletions.
73 changes: 50 additions & 23 deletions packages/dnb-eufemia/src/components/pagination/PaginationBar.tsx
Expand Up @@ -19,33 +19,54 @@ import Context from '../../shared/Context'
import Button from '../button/Button'
import IconPrimary from '../icon-primary/IconPrimary'
import styleProperties from '../../style/properties'
import { LocaleProps } from '../../shared/types'
import { SkeletonShow } from '../Skeleton'

interface PaginationBarProps {
export type PaginationBarProps = {
/**
* The title used in every button shown in the bar. Defaults to Side %s.
*/
button_title?: string

/**
* The title used in the previous page button. Defaults to Forrige side.
*/
prev_title?: string

/**
* The title used in the next page button. Defaults to Neste side.
*/
next_title?: string

/**
* The title used in the dots. Relevant for screen-readers. Defaults to %s flere sider.
*/
more_pages?: string

/**
* Reference to the parent component. Used to contain height between updates.
*/
contentRef?: React.RefObject<HTMLElement>

/**
* the given content can be either a function or a React node, depending on your needs. A function contains several helper functions. More details down below and have a look at the examples in the demos section.
*/
children?: React.ReactNode
locale?: string
children?: React.ReactNode | (() => React.ReactNode)

skeleton: SkeletonShow
}

export type PaginationBarAllProps = PaginationBarProps &
LocaleProps &
React.HTMLProps<HTMLElement>

type PaginationBarContext = {
currentPage: number
pageCount: number
disabled: boolean
onPageUpdate: (cb: () => void) => void
setState: (state: { currentPage: number }) => void
updatePageContent: (currentPage: number) => void
}

const defaultProps = {
Expand All @@ -57,14 +78,20 @@ const defaultProps = {
children: null,
}

const PaginationBar = (innerProps: PaginationBarProps) => {
const PaginationBar = (localProps: PaginationBarAllProps) => {
const context = useContext(PaginationContext)
const { currentPage, pageCount, disabled, skeleton } = context.pagination

const props = extendPropsWithContext(
localProps,
defaultProps,
context.pagination
) as PaginationBarProps & PaginationBarContext

const { currentPage, pageCount, disabled, skeleton } = props

// because of accessibility
const focusPage = () => {
const { onPageUpdate } = context.pagination
const { contentRef } = innerProps
const { onPageUpdate, contentRef } = props

onPageUpdate(() => {
try {
Expand All @@ -78,19 +105,19 @@ const PaginationBar = (innerProps: PaginationBarProps) => {

const keepPageHeight = () => {
try {
const elem = innerProps.contentRef.current
const elem = props.contentRef.current
const pageHeight = elem.offsetHeight
elem.style.height = `${pageHeight / 16}rem`
elem.style.minHeight = elem.style.height // because of the "min-height: inherit;" in &__indicator
} catch (e) {
//
}

const { onPageUpdate } = context.pagination
const { onPageUpdate } = props

onPageUpdate(() => {
try {
const elem = innerProps.contentRef.current
const elem = props.contentRef.current
elem.style.height = 'auto'
elem.style.minHeight = elem.style.height
} catch (e) {
Expand All @@ -102,27 +129,26 @@ const PaginationBar = (innerProps: PaginationBarProps) => {
const setPage = (currentPage: number, event = null) => {
keepPageHeight()

const { setState: setContextState, updatePageContent } =
context.pagination
const { setState: setContextState, updatePageContent } = props
setContextState({
currentPage,
})
updatePageContent(currentPage)

dispatchCustomElementEvent(context.pagination, 'on_change', {
dispatchCustomElementEvent(props, 'on_change', {
page: currentPage, // deprecated
pageNo: currentPage, // deprecated
pageNumber: currentPage,
...context.pagination,
...props,
event,
})
}

const setPrevPage = () => {
setPage(context.pagination.currentPage - 1)
setPage(props.currentPage - 1)
}
const setNextPage = () => {
setPage(context.pagination.currentPage + 1)
setPage(props.currentPage + 1)
}

const clickHandler = ({ pageNumber, event }) => {
Expand All @@ -133,10 +159,9 @@ const PaginationBar = (innerProps: PaginationBarProps) => {
const { getTranslation } = useContext(Context)
const { button_title, prev_title, next_title, more_pages } =
extendPropsWithContext(
{ ...defaultProps, ...innerProps },
props,
defaultProps,
getTranslation(innerProps as Pick<PaginationBarProps, 'locale'>)
.Pagination
getTranslation(props as LocaleProps).Pagination
)

const prevIsDisabled = currentPage > -1 ? currentPage === 1 : true
Expand Down Expand Up @@ -193,7 +218,7 @@ const PaginationBar = (innerProps: PaginationBarProps) => {
key={pageNumber}
className="dnb-pagination__button"
text={String(pageNumber)}
aria-label={button_title.replace('%s', pageNumber)}
aria-label={button_title.replace('%s', String(pageNumber))}
variant={
pageNumber === currentPage ? 'primary' : 'secondary'
}
Expand Down Expand Up @@ -231,7 +256,10 @@ const PaginationBar = (innerProps: PaginationBarProps) => {
: null
)}
text={String(pageNumber)}
aria-label={button_title.replace('%s', pageNumber)}
aria-label={button_title.replace(
'%s',
String(pageNumber)
)}
variant={
pageNumber === currentPage ? 'primary' : 'secondary'
}
Expand All @@ -252,7 +280,7 @@ const PaginationBar = (innerProps: PaginationBarProps) => {
</div>

<span className="dnb-sr-only" aria-live="assertive">
{button_title.replace('%s', currentPage)}
{button_title.replace('%s', String(currentPage))}
</span>
</div>
)
Expand Down Expand Up @@ -318,4 +346,3 @@ const getSizeInPx = (size) => {
}

export default PaginationBar
export type { PaginationBarProps }
Expand Up @@ -11,7 +11,11 @@ import {
toJson,
loadScss,
} from '../../../core/jest/jestSetup'
import { render } from '@testing-library/react'
import Component, { createPagination, Bar } from '../Pagination'
import nbNO from '../../../shared/locales/nb-NO'
import enGB from '../../../shared/locales/en-GB'
import Provider from '../../../shared/Provider'

const snapshotProps = {
...fakeProps(require.resolve('../Pagination'), {
Expand All @@ -22,6 +26,9 @@ const snapshotProps = {
snapshotProps.page_count = 4
snapshotProps.current_page = 2

const nb = nbNO['nb-NO'].Pagination
const en = enGB['en-GB'].Pagination

describe('Pagination bar', () => {
const props = {
page_count: 30,
Expand Down Expand Up @@ -541,6 +548,68 @@ describe('Infinity scroller', () => {
expect(Comp.exists('div#page-content')).toBe(true)
})

it('should support locale prop', () => {
const { rerender } = render(<Component {...props} />)

const element = document.querySelector(
'.dnb-pagination__bar__skip button'
)

expect(element.textContent).toContain(nb.prev_title)

rerender(<Component {...props} locale="en-GB" />)

expect(element.textContent).toContain(en.prev_title)
})

it('should support locale from provider', () => {
const { rerender } = render(
<Provider>
<Component {...props} />
</Provider>
)

const element = document.querySelector(
'.dnb-pagination__bar__skip button'
)

expect(element.textContent).toContain(nb.prev_title)

rerender(
<Provider locale="en-GB">
<Component {...props} />
</Provider>
)

expect(element.textContent).toContain(en.prev_title)

rerender(
<Provider locale="nb-NO">
<Component {...props} />
</Provider>
)

expect(element.textContent).toContain(nb.prev_title)
})

it('should support spacing props', () => {
render(<Component top="2rem" {...props} />)

const element = document.querySelector('.dnb-pagination')
const attributes = Array.from(element.attributes).map(
(attr) => attr.name
)

expect(attributes).toEqual(['class'])
expect(Array.from(element.classList)).toEqual(
expect.arrayContaining([
'dnb-pagination',
'dnb-space__top--large',
'dnb-pagination--left',
])
)
})

it('should support InfinityMarker from createPagination', async () => {
let resetInfinityHandler

Expand Down

0 comments on commit 01b93ce

Please sign in to comment.