Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(Pagination): fix locale support #1651

Merged
merged 1 commit into from
Oct 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 50 additions & 23 deletions packages/dnb-eufemia/src/components/pagination/PaginationBar.tsx
Original file line number Diff line number Diff line change
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 }
Original file line number Diff line number Diff line change
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