Skip to content

Commit

Permalink
feat: base pagination (#151)
Browse files Browse the repository at this point in the history
* feat(component & doc page): base pagination component

base pagination component, it's fully working now, but it's not finished yet, I will add more
funcionallity & better design & code refactoring

Add Pagination component #130

* Signed CLA

* docs(daisy/pagination): pagi doc

added base pagination to daisy docs, and not just headless

* fix(pagination): fixed PR issues #15

fixed PR issues #151

* fix(removed unused vars): removeed unused vars

* refactor(pagination): no shared code

instead of implementing the code twice, wrap the headless in the daisy (not finished yet)

* feat(pagination): pagination

added a pagination for headless & daisy, changed approach & better ts

130

* Update apps/website/src/routes/docs/daisy/pagination/index.tsx

* Update packages/headless/src/components/pagination/pagination.tsx

* Update apps/website/src/routes/docs/headless/pagination/index.tsx

---------

Co-authored-by: Giorgio Boa <35845425+gioboa@users.noreply.github.com>
  • Loading branch information
yishayhaz and gioboa authored Feb 24, 2023
1 parent f9b997d commit 76aed0e
Show file tree
Hide file tree
Showing 14 changed files with 369 additions and 2 deletions.
2 changes: 1 addition & 1 deletion CLA.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ You accept and agree to the following terms and conditions for your present and

7. Should You wish to submit work that is not Your original creation, You may submit it to Qwikifiers separately from any Contribution, identifying the complete details of its source and of any license or other restriction (including, but not limited to, related patents, trademarks, and license agreements) of which you are personally aware, and conspicuously marking the work as "Submitted on behalf of a third-party: [named here]".

8. You agree to notify Qwikifiers of any facts or circumstances of which you become aware that would make these representations inaccurate in any respect.
8. You agree to notify Qwikifiers of any facts or circumstances of which you become aware that would make these representations inaccurate in any respect.
4 changes: 4 additions & 0 deletions apps/website/src/components/menu/menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ export const Menu = component$<Props>(({ onClose$ }) => {
{ label: 'Toggle', path: `/docs/${appState.theme.toLowerCase()}/toggle` },
{ label: 'Tooltip', path: `/docs/${appState.theme.toLowerCase()}/tooltip` },
{ label: 'Slider', path: `/docs/${appState.theme.toLowerCase()}/slider` },
{
label: 'Pagination',
path: `/docs/${appState.theme.toLowerCase()}/pagination`,
},
{
label: 'Progress',
path: `/docs/${appState.theme.toLowerCase()}/progress`,
Expand Down
22 changes: 22 additions & 0 deletions apps/website/src/routes/docs/daisy/pagination/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { component$, useStore } from '@builder.io/qwik';
import { Pagination as DaisyPagination } from '@qwik-ui/theme-daisy';

export default component$(() => {
const store = useStore({
pages: 10,
page: 1,
});

return (
<div class={'flex flex-col gap-4'}>
<h2>This is the documentation for the Pagination</h2>
<DaisyPagination
pages={store.pages}
page={store.page}
onPaging$={(index) => {
store.page = index;
}}
/>
</div>
);
});
22 changes: 22 additions & 0 deletions apps/website/src/routes/docs/headless/pagination/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { component$, useStore } from '@builder.io/qwik';
import { Pagination as HeadlessPagination } from '@qwik-ui/headless';

export default component$(() => {
const store = useStore({
pages: 10,
page: 1,
});

return (
<>
<h2>This is the documentation for the Pagination</h2>
<HeadlessPagination
pages={store.pages}
page={store.page}
onPaging$={(index) => {
store.page = index;
}}
/>
</>
);
});
2 changes: 1 addition & 1 deletion cla-signs/v1/cla.json
Original file line number Diff line number Diff line change
Expand Up @@ -177,4 +177,4 @@
"pullRequestNo": 196
}
]
}
}
63 changes: 63 additions & 0 deletions packages/daisy/src/components/pagination/pagination.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { component$, $, PropFunction, Slot } from '@builder.io/qwik';
import {
IRenderPaginationItemProps,
Pagination as HeadlessPagination,
} from '@qwik-ui/headless';
import { Button } from '@qwik-ui/theme-daisy';

export interface PaginationProps {
pages: number;
page: number;
onPaging$: PropFunction<(index: number) => void>;
}

/**
* Pagination
* ----------
* A pagination component
* first page is 1
*
* @example
* <Pagination pages={15} page={store.page} onPaging$={incrementCount} />
*/

export const RenderPaginationItem = component$(
({
'aria-label': ariaLabel,
disabled,
'aria-current': ariaCurrent,
onClick$,
key,
value,
}: IRenderPaginationItemProps) => {
return (
<Button
onClick$={onClick$}
aria-label={ariaLabel}
disabled={disabled}
variant={'ghost'}
key={key}
active={ariaCurrent}
circle
>
{value === 'prev' ? '‹' : value === 'next' ? '›' : value}
</Button>
);
}
);

export const Pagination = component$((props: PaginationProps) => {
return (
<div class="flex gap-2 items-center">
<HeadlessPagination
page={props.page}
pages={props.pages}
onPaging$={props.onPaging$}
RenderItem={RenderPaginationItem}
RenderDivider={component$(() => {
return <span class="mb-2">...</span>;
})}
/>
</div>
);
});
1 change: 1 addition & 0 deletions packages/daisy/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@ export * from './components/tabs';
export * from './components/toast/toast';
export * from './components/toggle/toggle';
export * from './components/tooltip/tooltip';
export * from './components/pagination/pagination';
export * from './components/ratio/radio';
export * from './components/slider/slider';
169 changes: 169 additions & 0 deletions packages/headless/src/components/pagination/pagination.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
import {
$,
component$,
PropFunction,
JSXNode,
QRL,
FunctionComponent,
JSXChildren,
Component,
QwikIntrinsicElements,
Slot,
Fragment,
} from '@builder.io/qwik';
import { JSX } from '@builder.io/qwik/jsx-runtime';
import { Button as HeadlessButton } from '@qwik-ui/headless';

export interface IPaginationProps {
pages: number;
page: number;
onPaging$: PropFunction<(index: number) => void>;
RenderItem?: Component<IRenderPaginationItemProps>;
RenderDivider?: Component<object>;
}

export interface IRenderPaginationItemProps {
onClick$: PropFunction<() => void>;
disabled?: boolean;
'aria-label': string;
'aria-current'?: boolean;
value: PaginationItemValue;
key?: string | number;
}

export type PaginationItemValue = 'prev' | 'next' | number;

export function getPaginationItems(pages: number, page: number) {
// *show which arrows to light up
const canGo = {
prev: page > 1,
next: page < pages,
};

// one of first 5 pages -> should show 1, 2, 3, 4, 5 ... [last]
// or if length is less than 5, all pages
if (pages < 4 || page < 5) {
return {
items: Array.from({ length: Math.min(pages, 5) }, (_, i) => i + 1),
after: pages > 5 ? pages : -1,
before: -1,
...canGo,
};
}

// one of last 4 pages -> should show [first] ... [6, 7, 8, 9, 10]
if (Math.abs(page - pages) < 4) {
return {
items: Array.from({ length: 5 }, (_, i) => pages - 4 + i),
before: 1,
after: -1,
...canGo,
};
}

// it's somewhere in the middle
// -> [first] ... [4, 5, 6] ... [last]
return {
items: Array.from({ length: 3 }, (_, i) => page - 1 + i),
before: 1,
after: pages,
...canGo,
};
}

export const RenderPaginationItem = component$(
({
'aria-label': ariaLabel,
disabled,
onClick$,
key,
value,
}: IRenderPaginationItemProps) => {
return (
<HeadlessButton
onClick$={onClick$}
aria-label={ariaLabel}
disabled={disabled}
key={key}
>
{value}
</HeadlessButton>
);
}
);

export const PaginationDivider = component$(() => {
return <span>...</span>;
});

/**
* Pagination
* ----------
* A pagination component
* first page is 1
*
* @example
* <Pagination pages={15} page={store.page} onPaging$={incrementCount} />
*/
export const Pagination = component$(
({
RenderItem = RenderPaginationItem,
RenderDivider = PaginationDivider,
onPaging$,
page,
pages,
}: IPaginationProps) => {
const pagi = getPaginationItems(pages, page);

const _onPaging$ = $((page: number) => {
if (page < 1 || page > pages) return;
onPaging$(page);
});

return (
<>
<RenderItem
onClick$={() => _onPaging$(page - 1)}
disabled={!pagi.prev}
aria-label="Previous page"
value={'prev'}
/>
{pagi.before !== -1 && (
<>
<RenderItem
onClick$={() => _onPaging$(pagi.before)}
aria-label="Page 1"
value={pagi.before}
/>
<RenderDivider />
</>
)}
{pagi.items.map((item) => (
<RenderItem
key={item}
onClick$={() => _onPaging$(item)}
aria-label={`Page ${item}`}
aria-current={item === page}
value={item}
/>
))}
{pagi.after !== -1 && (
<>
<RenderDivider />
<RenderItem
aria-label={`Page ${pagi.after}`}
onClick$={() => _onPaging$(pagi.after)}
value={pagi.after}
/>
</>
)}
<RenderItem
aria-label={`Next page`}
onClick$={() => _onPaging$(page + 1)}
disabled={!pagi.next}
value={'next'}
/>
</>
);
}
);
1 change: 1 addition & 0 deletions packages/headless/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export * from './components/button/button';
export * from './components/progress/progress';
export * from './components/button-group/button-group';
export * from './components/card';
export * from './components/pagination/pagination';
export * from './components/collapse/collapse';
export * from './components/drawer';
export * from './components/menu/menu';
Expand Down
15 changes: 15 additions & 0 deletions packages/website/server/@qwik-city-not-found-paths.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const notFounds = [
[
'/',
'<!DOCTYPE html>\n<html>\n<head>\n <meta charset="utf-8">\n <meta http-equiv="Status" content="404">\n <title>404 Resource Not Found</title>\n <meta name="viewport" content="width=device-width,initial-scale=1">\n <style>\n body { color: #006ce9; background-color: #fafafa; padding: 30px; font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, Roboto, sans-serif; }\n p { max-width: 600px; margin: 60px auto 30px auto; background: white; border-radius: 4px; box-shadow: 0px 0px 50px -20px #006ce9; overflow: hidden; }\n strong { display: inline-block; padding: 15px; background: #006ce9; color: white; }\n span { display: inline-block; padding: 15px; }\n </style>\n</head>\n<body><p><strong>404</strong> <span>Resource Not Found</span></p></body>\n</html>',
],
];
function getNotFound(p) {
for (const r of notFounds) {
if (p.startsWith(r[0])) {
return r[1];
}
}
return 'Resource Not Found';
}
export { getNotFound };
27 changes: 27 additions & 0 deletions packages/website/server/@qwik-city-static-paths.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const staticPaths = new Set([]);
function isStaticPath(method, url) {
if (method.toUpperCase() !== 'GET') {
return false;
}
const p = url.pathname;
if (p.startsWith('/build/')) {
return true;
}
if (p.startsWith('/assets/')) {
return true;
}
if (staticPaths.has(p)) {
return true;
}
if (p.endsWith('/q-data.json')) {
const pWithoutQdata = p.replace(/\/q-data.json$/, '');
if (staticPaths.has(pWithoutQdata + '/')) {
return true;
}
if (staticPaths.has(pWithoutQdata)) {
return true;
}
}
return false;
}
export { isStaticPath };
3 changes: 3 additions & 0 deletions packages/website/server/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"type": "module"
}
20 changes: 20 additions & 0 deletions packages/website/src/routes/docs/daisy/pagination/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { $, component$, useStore } from '@builder.io/qwik';
import { Pagination } from '@qwik-ui/theme-daisy';

export default component$(() => {
const store = useStore({ page: 665 });

const incrementCount = $((newValue: number) => {
store.page = newValue;
});

return (
<div class="flex flex-col mt-4">
<h2>This is the documentation for the Pagination</h2>
<div class="flex flex-col gap-8">
<h2>Basic Example:</h2>
<Pagination pages={1500} page={store.page} onPaging$={incrementCount} />
</div>
</div>
);
});
Loading

0 comments on commit 76aed0e

Please # to comment.