From c36bae4b21e4a6c899be39800ca90051f79db1e0 Mon Sep 17 00:00:00 2001 From: Benjamin Canac Date: Wed, 17 Apr 2024 15:51:46 +0200 Subject: [PATCH] feat(Pagination): new component Resolves #11 --- playground/app.vue | 1 + playground/pages/pagination.vue | 7 + src/runtime/components/Pagination.vue | 121 + src/runtime/types/index.d.ts | 1 + src/theme/icons.ts | 3 + src/theme/index.ts | 1 + src/theme/pagination.ts | 8 + test/components/Pagination.spec.ts | 47 + .../__snapshots__/Pagination.spec.ts.snap | 2076 +++++++++++++++++ 9 files changed, 2265 insertions(+) create mode 100644 playground/pages/pagination.vue create mode 100644 src/runtime/components/Pagination.vue create mode 100644 src/theme/pagination.ts create mode 100644 test/components/Pagination.spec.ts create mode 100644 test/components/__snapshots__/Pagination.spec.ts.snap diff --git a/playground/app.vue b/playground/app.vue index ae3add34..aedbd599 100644 --- a/playground/app.vue +++ b/playground/app.vue @@ -29,6 +29,7 @@ const components = [ 'link', 'modal', 'navigation-menu', + 'pagination', 'popover', 'radio-group', 'separator', diff --git a/playground/pages/pagination.vue b/playground/pages/pagination.vue new file mode 100644 index 00000000..940d9f2f --- /dev/null +++ b/playground/pages/pagination.vue @@ -0,0 +1,7 @@ + + + diff --git a/src/runtime/components/Pagination.vue b/src/runtime/components/Pagination.vue new file mode 100644 index 00000000..4f332178 --- /dev/null +++ b/src/runtime/components/Pagination.vue @@ -0,0 +1,121 @@ + + + + + diff --git a/src/runtime/types/index.d.ts b/src/runtime/types/index.d.ts index 74487d08..a96aaef7 100644 --- a/src/runtime/types/index.d.ts +++ b/src/runtime/types/index.d.ts @@ -20,6 +20,7 @@ export * from '../components/Kbd.vue' export * from '../components/Link.vue' export * from '../components/Modal.vue' export * from '../components/NavigationMenu.vue' +export * from '../components/Pagination.vue' export * from '../components/Popover.vue' export * from '../components/RadioGroup.vue' export * from '../components/Separator.vue' diff --git a/src/theme/icons.ts b/src/theme/icons.ts index 6e9290f8..444d088a 100644 --- a/src/theme/icons.ts +++ b/src/theme/icons.ts @@ -2,8 +2,11 @@ export default { chevronDown: 'i-heroicons-chevron-down-20-solid', chevronLeft: 'i-heroicons-chevron-left-20-solid', chevronRight: 'i-heroicons-chevron-right-20-solid', + chevronDoubleLeft: 'i-heroicons-chevron-double-left-20-solid', + chevronDoubleRight: 'i-heroicons-chevron-double-right-20-solid', check: 'i-heroicons-check-20-solid', close: 'i-heroicons-x-mark-20-solid', + ellipsis: 'i-heroicons-ellipsis-horizontal-20-solid', empty: 'i-heroicons-circle-stack-20-solid', loading: 'i-heroicons-arrow-path-20-solid', minus: 'i-heroicons-minus-20-solid', diff --git a/src/theme/index.ts b/src/theme/index.ts index 0b6bc07f..fe744570 100644 --- a/src/theme/index.ts +++ b/src/theme/index.ts @@ -18,6 +18,7 @@ export { default as kbd } from './kbd' export { default as link } from './link' export { default as modal } from './modal' export { default as navigationMenu } from './navigation-menu' +export { default as pagination } from './pagination' export { default as popover } from './popover' export { default as radioGroup } from './radio-group' export { default as separator } from './separator' diff --git a/src/theme/pagination.ts b/src/theme/pagination.ts new file mode 100644 index 00000000..28082b03 --- /dev/null +++ b/src/theme/pagination.ts @@ -0,0 +1,8 @@ +export default { + slots: { + root: '', + list: 'flex items-center gap-1', + ellipsis: 'pointer-events-none', + label: 'min-w-5' + } +} diff --git a/test/components/Pagination.spec.ts b/test/components/Pagination.spec.ts new file mode 100644 index 00000000..d115f5c5 --- /dev/null +++ b/test/components/Pagination.spec.ts @@ -0,0 +1,47 @@ +import { describe, it, expect } from 'vitest' +import Pagination, { type PaginationProps } from '../../src/runtime/components/Pagination.vue' +import ComponentRender from '../component-render' +import theme from '#build/ui/button' + +describe('Pagination', () => { + const sizes = Object.keys(theme.variants.size) as any + const colors = Object.keys(theme.variants.color) as any + const variants = Object.keys(theme.variants.variant) as any + + const props = { total: 100 } + + it.each([ + // Props + ['with total', { props }], + ['with as', { props: { ...props, as: 'div' } }], + ['with defaultPage', { props: { ...props, defaultPage: 2 } }], + ['with disabled', { props: { ...props, disabled: true } }], + ['with itemsPerPage', { props: { ...props, itemsPerPage: 5 } }], + ['with page', { props: { ...props, page: 2 } }], + ['with showEdges', { props: { ...props, showEdges: true } }], + ['with siblingCount', { props: { ...props, siblingCount: 1, showEdges: true, page: 5 } }], + ['without showControls', { props: { ...props, showControls: false } }], + ['with firstIcon', { props: { ...props, firstIcon: 'i-heroicons-arrow-left' } }], + ['with prevIcon', { props: { ...props, prevIcon: 'i-heroicons-arrow-small-left' } }], + ['with nextIcon', { props: { ...props, nextIcon: 'i-heroicons-arrow-small-right' } }], + ['with lastIcon', { props: { ...props, lastIcon: 'i-heroicons-arrow-right' } }], + ['with ellipsisIcon', { props: { ...props, ellipsisIcon: 'i-heroicons-ellipsis-vertical', siblingCount: 1, showEdges: true, page: 5 } }], + ...sizes.map((size: string) => [`with size ${size}`, { props: { ...props, size } }]), + ...colors.map((color: string) => [`with color ${color}`, { props: { ...props, color } }]), + ...variants.map((variant: string) => [`with variant ${variant}`, { props: { ...props, color: 'primary', variant } }]), + ...colors.map((activeColor: string) => [`with active color ${activeColor}`, { props: { ...props, activeColor } }]), + ...variants.map((activeVariant: string) => [`with active variant ${activeVariant}`, { props: { ...props, color: 'primary', activeVariant } }]), + ['with class', { props: { ...props, class: 'relative' } }], + ['with ui', { props: { ...props, ui: { list: 'gap-3' } } }], + // Slots + ['with first slot', { props, slots: { first: () => 'First slot' } }], + ['with prev slot', { props, slots: { prev: () => 'Prev slot' } }], + ['with next slot', { props, slots: { next: () => 'Next slot' } }], + ['with last slot', { props, slots: { last: () => 'Last slot' } }], + ['with ellipsis slot', { props: { ...props, siblingCount: 1, showEdges: true, page: 5 }, slots: { ellipsis: () => 'Ellipsis slot' } }], + ['with item slot', { props, slots: { item: () => 'Item slot' } }] + ])('renders %s correctly', async (nameOrHtml: string, options: { props?: PaginationProps, slots?: any }) => { + const html = await ComponentRender(nameOrHtml, options, Pagination) + expect(html).toMatchSnapshot() + }) +}) diff --git a/test/components/__snapshots__/Pagination.spec.ts.snap b/test/components/__snapshots__/Pagination.spec.ts.snap new file mode 100644 index 00000000..a11ebfe7 --- /dev/null +++ b/test/components/__snapshots__/Pagination.spec.ts.snap @@ -0,0 +1,2076 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`Pagination > renders with active color black correctly 1`] = ` +"" +`; + +exports[`Pagination > renders with active color gray correctly 1`] = ` +"" +`; + +exports[`Pagination > renders with active color green correctly 1`] = ` +"" +`; + +exports[`Pagination > renders with active color primary correctly 1`] = ` +"" +`; + +exports[`Pagination > renders with active color red correctly 1`] = ` +"" +`; + +exports[`Pagination > renders with active color white correctly 1`] = ` +"" +`; + +exports[`Pagination > renders with active variant ghost correctly 1`] = ` +"" +`; + +exports[`Pagination > renders with active variant link correctly 1`] = ` +"" +`; + +exports[`Pagination > renders with active variant outline correctly 1`] = ` +"" +`; + +exports[`Pagination > renders with active variant soft correctly 1`] = ` +"" +`; + +exports[`Pagination > renders with active variant solid correctly 1`] = ` +"" +`; + +exports[`Pagination > renders with active variant subtle correctly 1`] = ` +"" +`; + +exports[`Pagination > renders with as correctly 1`] = ` +"
+
+
" +`; + +exports[`Pagination > renders with class correctly 1`] = ` +"" +`; + +exports[`Pagination > renders with color black correctly 1`] = ` +"" +`; + +exports[`Pagination > renders with color gray correctly 1`] = ` +"" +`; + +exports[`Pagination > renders with color green correctly 1`] = ` +"" +`; + +exports[`Pagination > renders with color primary correctly 1`] = ` +"" +`; + +exports[`Pagination > renders with color red correctly 1`] = ` +"" +`; + +exports[`Pagination > renders with color white correctly 1`] = ` +"" +`; + +exports[`Pagination > renders with defaultPage correctly 1`] = ` +"" +`; + +exports[`Pagination > renders with disabled correctly 1`] = ` +"" +`; + +exports[`Pagination > renders with ellipsis slot correctly 1`] = ` +"" +`; + +exports[`Pagination > renders with ellipsisIcon correctly 1`] = ` +"" +`; + +exports[`Pagination > renders with first slot correctly 1`] = ` +"" +`; + +exports[`Pagination > renders with firstIcon correctly 1`] = ` +"" +`; + +exports[`Pagination > renders with item slot correctly 1`] = ` +"" +`; + +exports[`Pagination > renders with itemsPerPage correctly 1`] = ` +"" +`; + +exports[`Pagination > renders with last slot correctly 1`] = ` +"" +`; + +exports[`Pagination > renders with lastIcon correctly 1`] = ` +"" +`; + +exports[`Pagination > renders with next slot correctly 1`] = ` +"" +`; + +exports[`Pagination > renders with nextIcon correctly 1`] = ` +"" +`; + +exports[`Pagination > renders with page correctly 1`] = ` +"" +`; + +exports[`Pagination > renders with prev slot correctly 1`] = ` +"" +`; + +exports[`Pagination > renders with prevIcon correctly 1`] = ` +"" +`; + +exports[`Pagination > renders with showEdges correctly 1`] = ` +"" +`; + +exports[`Pagination > renders with siblingCount correctly 1`] = ` +"" +`; + +exports[`Pagination > renders with size lg correctly 1`] = ` +"" +`; + +exports[`Pagination > renders with size md correctly 1`] = ` +"" +`; + +exports[`Pagination > renders with size sm correctly 1`] = ` +"" +`; + +exports[`Pagination > renders with size xl correctly 1`] = ` +"" +`; + +exports[`Pagination > renders with size xs correctly 1`] = ` +"" +`; + +exports[`Pagination > renders with total correctly 1`] = ` +"" +`; + +exports[`Pagination > renders with ui correctly 1`] = ` +"" +`; + +exports[`Pagination > renders with variant ghost correctly 1`] = ` +"" +`; + +exports[`Pagination > renders with variant link correctly 1`] = ` +"" +`; + +exports[`Pagination > renders with variant outline correctly 1`] = ` +"" +`; + +exports[`Pagination > renders with variant soft correctly 1`] = ` +"" +`; + +exports[`Pagination > renders with variant solid correctly 1`] = ` +"" +`; + +exports[`Pagination > renders with variant subtle correctly 1`] = ` +"" +`; + +exports[`Pagination > renders without showControls correctly 1`] = ` +"" +`;