periplo-ui 4.1.1 → 4.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -21,6 +21,7 @@ type PaginationLinkProps = {
21
21
  anchorComponent?: React.ComponentType<AnchorComponentProps>;
22
22
  previousLabel?: string;
23
23
  nextLabel?: string;
24
+ ariaLabel?: string;
24
25
  } & Pick<ButtonProps, 'size'> & React.ComponentProps<'a'>;
25
26
  /** Base props shared between both link and button modes */
26
27
  type BasePaginationComponentProps = {
@@ -110,4 +111,4 @@ declare const PaginationEllipsis: {
110
111
  * ```
111
112
  */
112
113
  declare const Pagination: React.FC<PaginationProps>;
113
- export { PaginationRoot, PaginationContent, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, PaginationEllipsis, Pagination, };
114
+ export { Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, PaginationRoot, };
@@ -1,7 +1,6 @@
1
1
  "use client";
2
2
  import { jsx, jsxs } from 'react/jsx-runtime';
3
- import { CaretLeft } from '@phosphor-icons/react/dist/ssr/CaretLeft';
4
- import { CaretRight } from '@phosphor-icons/react/dist/ssr/CaretRight';
3
+ import { CaretLeft, CaretRight } from '@phosphor-icons/react/dist/ssr';
5
4
  import * as React from 'react';
6
5
  import { buttonVariants, Button } from '../Button/Button.js';
7
6
  import { cn } from '../../lib/utils.js';
@@ -21,7 +20,7 @@ PaginationContent.displayName = "PaginationContent";
21
20
  const PaginationItem = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("li", { ref, className: cn(baseStyles.item, className), ...props }));
22
21
  PaginationItem.displayName = "PaginationItem";
23
22
  const PaginationLink = React.forwardRef(
24
- ({ className, isActive, size = "sm", disabled = false, href, rel, ...props }, ref) => {
23
+ ({ className, isActive, ariaLabel, size = "sm", disabled = false, href, rel, ...props }, ref) => {
25
24
  const buttonClassName = cn(
26
25
  buttonVariants({
27
26
  variant: isActive ? "primary" : "text",
@@ -42,6 +41,7 @@ const PaginationLink = React.forwardRef(
42
41
  href: href ?? "#",
43
42
  rel,
44
43
  "aria-current": isActive ? "page" : void 0,
44
+ "aria-label": ariaLabel,
45
45
  className: cn(baseStyles.link, buttonClassName),
46
46
  children: props.children
47
47
  }
@@ -50,11 +50,11 @@ const PaginationLink = React.forwardRef(
50
50
  );
51
51
  PaginationLink.displayName = "PaginationLink";
52
52
  const PaginationPrevious = React.forwardRef(
53
- ({ className, disabled, href, previousLabel = "", ...props }, ref) => /* @__PURE__ */ jsxs(
53
+ ({ className, disabled, href, previousLabel, ...props }, ref) => /* @__PURE__ */ jsxs(
54
54
  PaginationLink,
55
55
  {
56
56
  ref,
57
- "aria-label": previousLabel || "Go to previous page",
57
+ ariaLabel: previousLabel === "" ? "Go to previous page" : previousLabel,
58
58
  size: "sm",
59
59
  disabled,
60
60
  href,
@@ -70,11 +70,11 @@ const PaginationPrevious = React.forwardRef(
70
70
  );
71
71
  PaginationPrevious.displayName = "PaginationPrevious";
72
72
  const PaginationNext = React.forwardRef(
73
- ({ className, disabled, href, nextLabel = "", ...props }, ref) => /* @__PURE__ */ jsxs(
73
+ ({ className, disabled, href, nextLabel, ...props }, ref) => /* @__PURE__ */ jsxs(
74
74
  PaginationLink,
75
75
  {
76
76
  ref,
77
- "aria-label": nextLabel || "Go to next page",
77
+ ariaLabel: nextLabel === "" ? "Go to next page" : nextLabel,
78
78
  size: "sm",
79
79
  disabled,
80
80
  href,
@@ -116,33 +116,26 @@ const Pagination = ({
116
116
  const commonProps = {
117
117
  isActive: currentPage === pageNum,
118
118
  href: mode === "link" ? generateHref(pageNum) : void 0,
119
- anchorComponent,
120
- pageLabel: labels.page
119
+ ariaLabel: labels.page ? labels.page.replace("{number}", pageNum.toString()) : void 0,
120
+ anchorComponent
121
121
  };
122
122
  const encodedPageNum = btoa(`page-${pageNum}`).replaceAll(/[+/=]/g, "");
123
123
  items.push(
124
- /* @__PURE__ */ jsx(
125
- PaginationItem,
124
+ /* @__PURE__ */ jsx(PaginationItem, { children: mode === "button" ? /* @__PURE__ */ jsx(
125
+ Button,
126
126
  {
127
- "aria-label": labels.page ? labels.page.replace("{number}", pageNum.toString()) : void 0,
128
- children: mode === "button" ? /* @__PURE__ */ jsx(
129
- Button,
130
- {
131
- variant: commonProps.isActive ? "primary" : "text",
132
- size: "sm",
133
- className: baseStyles.button,
134
- onClick: (event) => {
135
- event.preventDefault();
136
- handlePageChange(pageNum);
137
- },
138
- "aria-label": labels.page ? labels.page.replace("{number}", pageNum.toString()) : `Go to page ${pageNum.toString()}`,
139
- "aria-current": commonProps.isActive ? "page" : void 0,
140
- children: pageNum
141
- }
142
- ) : /* @__PURE__ */ jsx(PaginationLink, { ...commonProps, children: pageNum })
143
- },
144
- `${encodedPageNum}`
145
- )
127
+ variant: commonProps.isActive ? "primary" : "text",
128
+ size: "sm",
129
+ className: baseStyles.button,
130
+ onClick: (event) => {
131
+ event.preventDefault();
132
+ handlePageChange(pageNum);
133
+ },
134
+ "aria-label": commonProps.ariaLabel,
135
+ "aria-current": commonProps.isActive ? "page" : void 0,
136
+ children: pageNum
137
+ }
138
+ ) : /* @__PURE__ */ jsx(PaginationLink, { ...commonProps, children: pageNum }) }, `${encodedPageNum}`)
146
139
  );
147
140
  };
148
141
  addPageNumber(1);
@@ -1 +1 @@
1
- {"version":3,"file":"Pagination.js","sources":["../../../src/components/Pagination/Pagination.tsx"],"sourcesContent":["'use client'\n\nimport { CaretLeft } from '@phosphor-icons/react/dist/ssr/CaretLeft'\nimport { CaretRight } from '@phosphor-icons/react/dist/ssr/CaretRight'\nimport * as React from 'react'\n\nimport { Button, ButtonProps, buttonVariants } from '../Button'\n\nimport { cn } from '@/lib/utils'\n\nconst baseStyles = {\n nav: 'flex justify-center',\n content: 'flex flex-row items-center gap-1',\n item: 'list-none',\n link: 'outline-none',\n button: 'min-w-8 px-2 transition-none',\n ellipsis: 'flex h-8 w-8 items-center justify-center',\n}\n\ntype BasePaginationProps = {\n className?: string\n}\n\ntype PaginationRootProps = BasePaginationProps & React.ComponentProps<'nav'>\ntype PaginationContentProps = BasePaginationProps & React.ComponentProps<'ul'>\ntype PaginationItemProps = BasePaginationProps & React.ComponentProps<'li'>\n\ntype AnchorComponentProps = {\n href: string\n className?: string\n 'aria-current'?: 'page'\n children: React.ReactNode\n onClick?: (e: React.MouseEvent<HTMLAnchorElement>) => void\n rel?: string\n}\n\ntype PaginationLinkProps = {\n isActive?: boolean\n disabled?: boolean\n href?: string\n anchorComponent?: React.ComponentType<AnchorComponentProps>\n previousLabel?: string\n nextLabel?: string\n} & Pick<ButtonProps, 'size'> &\n React.ComponentProps<'a'>\n\n/** Base props shared between both link and button modes */\ntype BasePaginationComponentProps = {\n /** The current active page number (1-based indexing) */\n currentPage: number\n /** The total number of available pages */\n totalPages: number\n /** Optional CSS class name for styling the pagination container */\n className?: string\n labels?: {\n /** Text to show in the previous button (default: '') */\n previous?: string\n /** Text to show in the next button (default: '') */\n next?: string\n /** Aria label to show in the page number (default: 'Page {number}') */\n page?: string\n }\n}\n\n/** Props specific to link mode */\ntype LinkModePaginationProps = {\n mode: 'link'\n /**\n * Custom component to use for links (e.g., Next.js Link)\n * Must accept standard anchor props (href, className, etc.)\n */\n anchorComponent: React.ComponentType<AnchorComponentProps>\n /**\n * Function to generate the href for each page link\n */\n generateHref: (page: number) => string\n /** Optional callback when page changes - not required in link mode since links handle navigation */\n onPageChange?: (page: number) => void\n} & BasePaginationComponentProps\n\n/** Props specific to button mode */\ntype ButtonModePaginationProps = {\n mode: 'button'\n /** Callback function called when a page is selected - required in button mode */\n onPageChange: (page: number) => void\n /** These props are not used in button mode */\n anchorComponent?: never\n generateHref?: never\n} & BasePaginationComponentProps\n\n/** Union type for all possible pagination props */\nexport type PaginationProps =\n | LinkModePaginationProps\n | ButtonModePaginationProps\n | (Omit<BasePaginationComponentProps, 'mode'> & {\n mode: undefined\n onPageChange: (page: number) => void\n anchorComponent?: React.ComponentType<AnchorComponentProps>\n generateHref?: (page: number) => string\n })\n\nconst PaginationRoot = React.forwardRef<HTMLElement, PaginationRootProps>(({ className, ...props }, ref) => (\n <nav ref={ref} role=\"navigation\" aria-label=\"pagination\" className={cn(baseStyles.nav, className)} {...props} />\n))\nPaginationRoot.displayName = 'PaginationRoot'\n\nconst PaginationContent = React.forwardRef<HTMLUListElement, PaginationContentProps>(({ className, ...props }, ref) => (\n <ul ref={ref} className={cn(baseStyles.content, className)} {...props} />\n))\nPaginationContent.displayName = 'PaginationContent'\n\nconst PaginationItem = React.forwardRef<HTMLLIElement, PaginationItemProps>(({ className, ...props }, ref) => (\n <li ref={ref} className={cn(baseStyles.item, className)} {...props} />\n))\nPaginationItem.displayName = 'PaginationItem'\n\nconst PaginationLink = React.forwardRef<HTMLAnchorElement, PaginationLinkProps>(\n ({ className, isActive, size = 'sm', disabled = false, href, rel, ...props }, ref) => {\n const buttonClassName = cn(\n buttonVariants({\n variant: isActive ? 'primary' : 'text',\n size,\n }),\n disabled && 'opacity-50',\n baseStyles.button,\n className,\n )\n\n if (disabled) {\n return (\n <Button variant=\"text\" size=\"sm\" disabled className={buttonClassName}>\n {props.children}\n </Button>\n )\n }\n\n const AnchorComponent = props.anchorComponent ?? 'a'\n\n return (\n <AnchorComponent\n ref={ref}\n href={href ?? '#'}\n rel={rel}\n aria-current={isActive ? 'page' : undefined}\n className={cn(baseStyles.link, buttonClassName)}\n >\n {props.children}\n </AnchorComponent>\n )\n },\n)\nPaginationLink.displayName = 'PaginationLink'\n\nconst PaginationPrevious = React.forwardRef<HTMLAnchorElement, PaginationLinkProps>(\n ({ className, disabled, href, previousLabel = '', ...props }, ref) => (\n <PaginationLink\n ref={ref}\n aria-label={previousLabel || 'Go to previous page'}\n size=\"sm\"\n disabled={disabled}\n href={href}\n rel=\"prev\"\n className={cn('flex items-center gap-2', baseStyles.button, className)}\n {...props}\n >\n <CaretLeft className=\"h-4 w-4 shrink-0\" />\n {previousLabel && <span>{previousLabel}</span>}\n </PaginationLink>\n ),\n)\nPaginationPrevious.displayName = 'PaginationPrevious'\n\nconst PaginationNext = React.forwardRef<HTMLAnchorElement, PaginationLinkProps>(\n ({ className, disabled, href, nextLabel = '', ...props }, ref) => (\n <PaginationLink\n ref={ref}\n aria-label={nextLabel || 'Go to next page'}\n size=\"sm\"\n disabled={disabled}\n href={href}\n rel=\"next\"\n className={cn('flex items-center gap-2', baseStyles.button, className)}\n {...props}\n >\n {nextLabel && <span>{nextLabel}</span>}\n <CaretRight className=\"h-4 w-4 shrink-0\" />\n </PaginationLink>\n ),\n)\nPaginationNext.displayName = 'PaginationNext'\n\nconst PaginationEllipsis = ({ className }: BasePaginationProps) => (\n <span className={cn(baseStyles.ellipsis, className)}>...</span>\n)\nPaginationEllipsis.displayName = 'PaginationEllipsis'\n\n/**\n * A pagination component that displays page numbers and navigation controls.\n *\n * @example\n * ```tsx\n * // Basic usage with anchor tags\n * <Pagination\n * currentPage={1}\n * totalPages={10}\n * />\n *\n * // With Next.js Link component\n * <Pagination\n * currentPage={1}\n * totalPages={10}\n * onPageChange={setPage}\n * anchorComponent={Link}\n * generateHref={(page) => `/posts?page=${page}`}\n * />\n *\n * // Client-side table navigation\n * <Pagination\n * currentPage={1}\n * totalPages={10}\n * onPageChange={setPage}\n * mode=\"button\"\n * />\n * ```\n */\nconst Pagination: React.FC<PaginationProps> = ({\n currentPage,\n totalPages,\n onPageChange,\n className,\n mode = 'button',\n anchorComponent,\n generateHref = () => '#',\n labels = {\n previous: '',\n next: '',\n page: 'Page {number}',\n },\n}) => {\n const handlePageChange = (pageNum: number) => {\n if (onPageChange) {\n onPageChange(pageNum)\n }\n }\n\n const renderPageNumbers = () => {\n const items: Array<React.ReactNode> = []\n\n const addPageNumber = (pageNum: number) => {\n const commonProps = {\n isActive: currentPage === pageNum,\n href: mode === 'link' ? generateHref(pageNum) : undefined,\n anchorComponent,\n pageLabel: labels.page,\n }\n\n const encodedPageNum = btoa(`page-${pageNum}`).replaceAll(/[+/=]/g, '')\n\n items.push(\n <PaginationItem\n key={`${encodedPageNum}`}\n aria-label={labels.page ? labels.page.replace('{number}', pageNum.toString()) : undefined}\n >\n {mode === 'button' ? (\n <Button\n variant={commonProps.isActive ? 'primary' : 'text'}\n size=\"sm\"\n className={baseStyles.button}\n onClick={(event: React.MouseEvent) => {\n event.preventDefault()\n handlePageChange(pageNum)\n }}\n aria-label={\n labels.page ? labels.page.replace('{number}', pageNum.toString()) : `Go to page ${pageNum.toString()}`\n }\n aria-current={commonProps.isActive ? 'page' : undefined}\n >\n {pageNum}\n </Button>\n ) : (\n <PaginationLink {...commonProps}>{pageNum}</PaginationLink>\n )}\n </PaginationItem>,\n )\n }\n\n addPageNumber(1)\n\n if (currentPage > 3) {\n items.push(<PaginationEllipsis key=\"ellipsis-1\" />)\n }\n\n for (let index = Math.max(2, currentPage - 1); index <= Math.min(totalPages - 1, currentPage + 1); index++) {\n addPageNumber(index)\n }\n\n if (currentPage < totalPages - 2) {\n items.push(<PaginationEllipsis key=\"ellipsis-2\" />)\n }\n\n if (totalPages > 1) {\n addPageNumber(totalPages)\n }\n\n return items\n }\n\n const commonNavProps = (page: number) => ({\n onClick: (event: React.MouseEvent) => {\n event.preventDefault()\n handlePageChange(page)\n },\n href: generateHref(page),\n anchorComponent,\n })\n\n return (\n <PaginationRoot className={className}>\n <PaginationContent>\n <PaginationItem>\n {mode === 'button' ? (\n <Button\n variant=\"text\"\n size=\"sm\"\n className={cn('flex items-center gap-2', baseStyles.button, currentPage === 1 && 'opacity-50')}\n onClick={currentPage > 1 ? commonNavProps(currentPage - 1).onClick : undefined}\n disabled={currentPage === 1}\n aria-label={labels.previous === '' ? 'Go to previous page' : labels.previous}\n >\n <CaretLeft className=\"h-4 w-4 shrink-0\" />\n {labels.previous && <span>{labels.previous}</span>}\n </Button>\n ) : (\n <PaginationPrevious\n {...commonNavProps(currentPage - 1)}\n disabled={currentPage === 1}\n previousLabel={labels.previous}\n />\n )}\n </PaginationItem>\n {renderPageNumbers()}\n <PaginationItem>\n {mode === 'button' ? (\n <Button\n variant=\"text\"\n size=\"sm\"\n className={cn('flex items-center gap-2', baseStyles.button, currentPage === totalPages && 'opacity-50')}\n onClick={currentPage < totalPages ? commonNavProps(currentPage + 1).onClick : undefined}\n disabled={currentPage === totalPages || totalPages === 0}\n aria-label={labels.next === '' ? 'Go to next page' : labels.next}\n >\n {labels.next && <span>{labels.next}</span>}\n <CaretRight className=\"h-4 w-4 shrink-0\" />\n </Button>\n ) : (\n <PaginationNext\n {...commonNavProps(currentPage + 1)}\n disabled={currentPage === totalPages || totalPages === 0}\n nextLabel={labels.next}\n />\n )}\n </PaginationItem>\n </PaginationContent>\n </PaginationRoot>\n )\n}\n\nexport {\n PaginationRoot,\n PaginationContent,\n PaginationItem,\n PaginationLink,\n PaginationNext,\n PaginationPrevious,\n PaginationEllipsis,\n Pagination,\n}\n"],"names":[],"mappings":";;;;;;;;AAUA;AAAmB;AACZ;AACI;AACH;AACA;AACE;AAEV;AAoFA;AAGA;AAEA;AAGA;AAEA;AAGA;AAEA;AAA6B;AAEzB;AAAwB;AACP;AACmB;AAChC;AACD;AACW;AACD;AACX;AAGF;AACE;AAGE;AAIJ;AAEA;AACE;AAAC;AAAA;AACC;AACc;AACd;AACkC;AACY;AAEvC;AAAA;AACT;AAGN;AACA;AAEA;AAAiC;AAE7B;AAAC;AAAA;AACC;AAC6B;AACxB;AACL;AACA;AACI;AACiE;AACjE;AAEJ;AAAwC;AACD;AAAA;AAAA;AAG7C;AACA;AAEA;AAA6B;AAEzB;AAAC;AAAA;AACC;AACyB;AACpB;AACL;AACA;AACI;AACiE;AACjE;AAEH;AAA8B;AACU;AAAA;AAAA;AAG/C;AACA;AAEA;AAGA;AA+BA;AAA+C;AAC7C;AACA;AACA;AACA;AACO;AACP;AACqB;AACZ;AACG;AACJ;AACA;AAEV;AACE;AACE;AACE;AAAoB;AACtB;AAGF;AACE;AAEA;AACE;AAAoB;AACQ;AACsB;AAChD;AACkB;AAGpB;AAEA;AAAM;AACJ;AAAC;AAAA;AAEiF;AAG9E;AAAC;AAAA;AAC6C;AACvC;AACiB;AAEpB;AACA;AAAwB;AAC1B;AAEsG;AAExD;AAE7C;AAAA;AAGuC;AAAA;AApBtB;AAsBxB;AACF;AAGF;AAEA;AACE;AAAkD;AAGpD;AACE;AAAmB;AAGrB;AACE;AAAkD;AAGpD;AACE;AAAwB;AAG1B;AAAO;AAGT;AAA0C;AAEtC;AACA;AAAqB;AACvB;AACuB;AACvB;AAGF;AAGM;AAEI;AAAC;AAAA;AACS;AACH;AACwF;AACxB;AAC3C;AAC0C;AAEpE;AAAwC;AACG;AAAA;AAAA;AAG7C;AAAC;AAAA;AACmC;AACR;AACJ;AAAA;AAG5B;AACmB;AAGf;AAAC;AAAA;AACS;AACH;AACiG;AACxB;AACvB;AACK;AAE3D;AAAkC;AACM;AAAA;AAAA;AAG3C;AAAC;AAAA;AACmC;AACqB;AACrC;AAAA;AAGxB;AAIR;;"}
1
+ {"version":3,"file":"Pagination.js","sources":["../../../src/components/Pagination/Pagination.tsx"],"sourcesContent":["'use client'\n\nimport { CaretLeft, CaretRight } from '@phosphor-icons/react/dist/ssr'\nimport * as React from 'react'\n\nimport { Button, ButtonProps, buttonVariants } from '../Button'\n\nimport { cn } from '@/lib/utils'\n\nconst baseStyles = {\n nav: 'flex justify-center',\n content: 'flex flex-row items-center gap-1',\n item: 'list-none',\n link: 'outline-none',\n button: 'min-w-8 px-2 transition-none',\n ellipsis: 'flex h-8 w-8 items-center justify-center',\n}\n\ntype BasePaginationProps = {\n className?: string\n}\n\ntype PaginationRootProps = BasePaginationProps & React.ComponentProps<'nav'>\ntype PaginationContentProps = BasePaginationProps & React.ComponentProps<'ul'>\ntype PaginationItemProps = BasePaginationProps & React.ComponentProps<'li'>\n\ntype AnchorComponentProps = {\n href: string\n className?: string\n 'aria-current'?: 'page'\n children: React.ReactNode\n onClick?: (e: React.MouseEvent<HTMLAnchorElement>) => void\n rel?: string\n}\n\ntype PaginationLinkProps = {\n isActive?: boolean\n disabled?: boolean\n href?: string\n anchorComponent?: React.ComponentType<AnchorComponentProps>\n previousLabel?: string\n nextLabel?: string\n ariaLabel?: string\n} & Pick<ButtonProps, 'size'> &\n React.ComponentProps<'a'>\n\n/** Base props shared between both link and button modes */\ntype BasePaginationComponentProps = {\n /** The current active page number (1-based indexing) */\n currentPage: number\n /** The total number of available pages */\n totalPages: number\n /** Optional CSS class name for styling the pagination container */\n className?: string\n labels?: {\n /** Text to show in the previous button (default: '') */\n previous?: string\n /** Text to show in the next button (default: '') */\n next?: string\n /** Aria label to show in the page number (default: 'Page {number}') */\n page?: string\n }\n}\n\n/** Props specific to link mode */\ntype LinkModePaginationProps = {\n mode: 'link'\n /**\n * Custom component to use for links (e.g., Next.js Link)\n * Must accept standard anchor props (href, className, etc.)\n */\n anchorComponent: React.ComponentType<AnchorComponentProps>\n /**\n * Function to generate the href for each page link\n */\n generateHref: (page: number) => string\n /** Optional callback when page changes - not required in link mode since links handle navigation */\n onPageChange?: (page: number) => void\n} & BasePaginationComponentProps\n\n/** Props specific to button mode */\ntype ButtonModePaginationProps = {\n mode: 'button'\n /** Callback function called when a page is selected - required in button mode */\n onPageChange: (page: number) => void\n /** These props are not used in button mode */\n anchorComponent?: never\n generateHref?: never\n} & BasePaginationComponentProps\n\n/** Union type for all possible pagination props */\nexport type PaginationProps =\n | LinkModePaginationProps\n | ButtonModePaginationProps\n | (Omit<BasePaginationComponentProps, 'mode'> & {\n mode: undefined\n onPageChange: (page: number) => void\n anchorComponent?: React.ComponentType<AnchorComponentProps>\n generateHref?: (page: number) => string\n })\n\nconst PaginationRoot = React.forwardRef<HTMLElement, PaginationRootProps>(({ className, ...props }, ref) => (\n <nav ref={ref} role=\"navigation\" aria-label=\"pagination\" className={cn(baseStyles.nav, className)} {...props} />\n))\nPaginationRoot.displayName = 'PaginationRoot'\n\nconst PaginationContent = React.forwardRef<HTMLUListElement, PaginationContentProps>(({ className, ...props }, ref) => (\n <ul ref={ref} className={cn(baseStyles.content, className)} {...props} />\n))\nPaginationContent.displayName = 'PaginationContent'\n\nconst PaginationItem = React.forwardRef<HTMLLIElement, PaginationItemProps>(({ className, ...props }, ref) => (\n <li ref={ref} className={cn(baseStyles.item, className)} {...props} />\n))\nPaginationItem.displayName = 'PaginationItem'\n\nconst PaginationLink = React.forwardRef<HTMLAnchorElement, PaginationLinkProps>(\n ({ className, isActive, ariaLabel, size = 'sm', disabled = false, href, rel, ...props }, ref) => {\n const buttonClassName = cn(\n buttonVariants({\n variant: isActive ? 'primary' : 'text',\n size,\n }),\n disabled && 'opacity-50',\n baseStyles.button,\n className,\n )\n\n if (disabled) {\n return (\n <Button variant=\"text\" size=\"sm\" disabled className={buttonClassName}>\n {props.children}\n </Button>\n )\n }\n\n const AnchorComponent = props.anchorComponent ?? 'a'\n\n return (\n <AnchorComponent\n ref={ref}\n href={href ?? '#'}\n rel={rel}\n aria-current={isActive ? 'page' : undefined}\n aria-label={ariaLabel}\n className={cn(baseStyles.link, buttonClassName)}\n >\n {props.children}\n </AnchorComponent>\n )\n },\n)\nPaginationLink.displayName = 'PaginationLink'\n\nconst PaginationPrevious = React.forwardRef<HTMLAnchorElement, PaginationLinkProps>(\n ({ className, disabled, href, previousLabel, ...props }, ref) => (\n <PaginationLink\n ref={ref}\n ariaLabel={previousLabel === '' ? 'Go to previous page' : previousLabel}\n size=\"sm\"\n disabled={disabled}\n href={href}\n rel=\"prev\"\n className={cn('flex items-center gap-2', baseStyles.button, className)}\n {...props}\n >\n <CaretLeft className=\"h-4 w-4 shrink-0\" />\n {previousLabel && <span>{previousLabel}</span>}\n </PaginationLink>\n ),\n)\nPaginationPrevious.displayName = 'PaginationPrevious'\n\nconst PaginationNext = React.forwardRef<HTMLAnchorElement, PaginationLinkProps>(\n ({ className, disabled, href, nextLabel, ...props }, ref) => (\n <PaginationLink\n ref={ref}\n ariaLabel={nextLabel === '' ? 'Go to next page' : nextLabel}\n size=\"sm\"\n disabled={disabled}\n href={href}\n rel=\"next\"\n className={cn('flex items-center gap-2', baseStyles.button, className)}\n {...props}\n >\n {nextLabel && <span>{nextLabel}</span>}\n <CaretRight className=\"h-4 w-4 shrink-0\" />\n </PaginationLink>\n ),\n)\nPaginationNext.displayName = 'PaginationNext'\n\nconst PaginationEllipsis = ({ className }: BasePaginationProps) => (\n <span className={cn(baseStyles.ellipsis, className)}>...</span>\n)\nPaginationEllipsis.displayName = 'PaginationEllipsis'\n\n/**\n * A pagination component that displays page numbers and navigation controls.\n *\n * @example\n * ```tsx\n * // Basic usage with anchor tags\n * <Pagination\n * currentPage={1}\n * totalPages={10}\n * />\n *\n * // With Next.js Link component\n * <Pagination\n * currentPage={1}\n * totalPages={10}\n * onPageChange={setPage}\n * anchorComponent={Link}\n * generateHref={(page) => `/posts?page=${page}`}\n * />\n *\n * // Client-side table navigation\n * <Pagination\n * currentPage={1}\n * totalPages={10}\n * onPageChange={setPage}\n * mode=\"button\"\n * />\n * ```\n */\nconst Pagination: React.FC<PaginationProps> = ({\n currentPage,\n totalPages,\n onPageChange,\n className,\n mode = 'button',\n anchorComponent,\n generateHref = () => '#',\n labels = {\n previous: '',\n next: '',\n page: 'Page {number}',\n },\n}) => {\n const handlePageChange = (pageNum: number) => {\n if (onPageChange) {\n onPageChange(pageNum)\n }\n }\n\n const renderPageNumbers = () => {\n const items: Array<React.ReactNode> = []\n\n const addPageNumber = (pageNum: number) => {\n const commonProps = {\n isActive: currentPage === pageNum,\n href: mode === 'link' ? generateHref(pageNum) : undefined,\n ariaLabel: labels.page ? labels.page.replace('{number}', pageNum.toString()) : undefined,\n anchorComponent,\n }\n\n const encodedPageNum = btoa(`page-${pageNum}`).replaceAll(/[+/=]/g, '')\n\n items.push(\n <PaginationItem key={`${encodedPageNum}`}>\n {mode === 'button' ? (\n <Button\n variant={commonProps.isActive ? 'primary' : 'text'}\n size=\"sm\"\n className={baseStyles.button}\n onClick={(event: React.MouseEvent) => {\n event.preventDefault()\n handlePageChange(pageNum)\n }}\n aria-label={commonProps.ariaLabel}\n aria-current={commonProps.isActive ? 'page' : undefined}\n >\n {pageNum}\n </Button>\n ) : (\n <PaginationLink {...commonProps}>{pageNum}</PaginationLink>\n )}\n </PaginationItem>,\n )\n }\n\n addPageNumber(1)\n\n if (currentPage > 3) {\n items.push(<PaginationEllipsis key=\"ellipsis-1\" />)\n }\n\n for (let index = Math.max(2, currentPage - 1); index <= Math.min(totalPages - 1, currentPage + 1); index++) {\n addPageNumber(index)\n }\n\n if (currentPage < totalPages - 2) {\n items.push(<PaginationEllipsis key=\"ellipsis-2\" />)\n }\n\n if (totalPages > 1) {\n addPageNumber(totalPages)\n }\n\n return items\n }\n\n const commonNavProps = (page: number) => ({\n onClick: (event: React.MouseEvent) => {\n event.preventDefault()\n handlePageChange(page)\n },\n href: generateHref(page),\n anchorComponent,\n })\n\n return (\n <PaginationRoot className={className}>\n <PaginationContent>\n <PaginationItem>\n {mode === 'button' ? (\n <Button\n variant=\"text\"\n size=\"sm\"\n className={cn('flex items-center gap-2', baseStyles.button, currentPage === 1 && 'opacity-50')}\n onClick={currentPage > 1 ? commonNavProps(currentPage - 1).onClick : undefined}\n disabled={currentPage === 1}\n aria-label={labels.previous === '' ? 'Go to previous page' : labels.previous}\n >\n <CaretLeft className=\"h-4 w-4 shrink-0\" />\n {labels.previous && <span>{labels.previous}</span>}\n </Button>\n ) : (\n <PaginationPrevious\n {...commonNavProps(currentPage - 1)}\n disabled={currentPage === 1}\n previousLabel={labels.previous}\n />\n )}\n </PaginationItem>\n {renderPageNumbers()}\n <PaginationItem>\n {mode === 'button' ? (\n <Button\n variant=\"text\"\n size=\"sm\"\n className={cn('flex items-center gap-2', baseStyles.button, currentPage === totalPages && 'opacity-50')}\n onClick={currentPage < totalPages ? commonNavProps(currentPage + 1).onClick : undefined}\n disabled={currentPage === totalPages || totalPages === 0}\n aria-label={labels.next === '' ? 'Go to next page' : labels.next}\n >\n {labels.next && <span>{labels.next}</span>}\n <CaretRight className=\"h-4 w-4 shrink-0\" />\n </Button>\n ) : (\n <PaginationNext\n {...commonNavProps(currentPage + 1)}\n disabled={currentPage === totalPages || totalPages === 0}\n nextLabel={labels.next}\n />\n )}\n </PaginationItem>\n </PaginationContent>\n </PaginationRoot>\n )\n}\n\nexport {\n Pagination,\n PaginationContent,\n PaginationEllipsis,\n PaginationItem,\n PaginationLink,\n PaginationNext,\n PaginationPrevious,\n PaginationRoot,\n}\n"],"names":[],"mappings":";;;;;;;AASA;AAAmB;AACZ;AACI;AACH;AACA;AACE;AAEV;AAqFA;AAGA;AAEA;AAGA;AAEA;AAGA;AAEA;AAA6B;AAEzB;AAAwB;AACP;AACmB;AAChC;AACD;AACW;AACD;AACX;AAGF;AACE;AAGE;AAIJ;AAEA;AACE;AAAC;AAAA;AACC;AACc;AACd;AACkC;AACtB;AACkC;AAEvC;AAAA;AACT;AAGN;AACA;AAEA;AAAiC;AAE7B;AAAC;AAAA;AACC;AAC0D;AACrD;AACL;AACA;AACI;AACiE;AACjE;AAEJ;AAAwC;AACD;AAAA;AAAA;AAG7C;AACA;AAEA;AAA6B;AAEzB;AAAC;AAAA;AACC;AACkD;AAC7C;AACL;AACA;AACI;AACiE;AACjE;AAEH;AAA8B;AACU;AAAA;AAAA;AAG/C;AACA;AAEA;AAGA;AA+BA;AAA+C;AAC7C;AACA;AACA;AACA;AACO;AACP;AACqB;AACZ;AACG;AACJ;AACA;AAEV;AACE;AACE;AACE;AAAoB;AACtB;AAGF;AACE;AAEA;AACE;AAAoB;AACQ;AACsB;AAC+B;AAC/E;AAGF;AAEA;AAAM;AAGA;AAAC;AAAA;AAC6C;AACvC;AACiB;AAEpB;AACA;AAAwB;AAC1B;AACwB;AACsB;AAE7C;AAAA;AAKP;AACF;AAGF;AAEA;AACE;AAAkD;AAGpD;AACE;AAAmB;AAGrB;AACE;AAAkD;AAGpD;AACE;AAAwB;AAG1B;AAAO;AAGT;AAA0C;AAEtC;AACA;AAAqB;AACvB;AACuB;AACvB;AAGF;AAGM;AAEI;AAAC;AAAA;AACS;AACH;AACwF;AACxB;AAC3C;AAC0C;AAEpE;AAAwC;AACG;AAAA;AAAA;AAG7C;AAAC;AAAA;AACmC;AACR;AACJ;AAAA;AAG5B;AACmB;AAGf;AAAC;AAAA;AACS;AACH;AACiG;AACxB;AACvB;AACK;AAE3D;AAAkC;AACM;AAAA;AAAA;AAG3C;AAAC;AAAA;AACmC;AACqB;AACrC;AAAA;AAGxB;AAIR;;"}
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "periplo-ui",
3
3
  "description": "IATI UI library",
4
4
  "private": false,
5
- "version": "4.1.1",
5
+ "version": "4.2.0",
6
6
  "type": "module",
7
7
  "main": "dist/index.js",
8
8
  "types": "dist/index.d.ts",
@@ -221,33 +221,10 @@
221
221
  "peerDependencies": {
222
222
  "@hookform/resolvers": "^3 || ^5",
223
223
  "@phosphor-icons/react": "^2",
224
- "@radix-ui/react-accordion": "^1",
225
- "@radix-ui/react-avatar": "^1",
226
- "@radix-ui/react-checkbox": "^1",
227
- "@radix-ui/react-collapsible": "^1",
228
- "@radix-ui/react-dialog": "^1",
229
- "@radix-ui/react-dropdown-menu": "^2",
230
- "@radix-ui/react-label": "^2",
231
- "@radix-ui/react-popover": "^1",
232
- "@radix-ui/react-progress": "^1",
233
- "@radix-ui/react-radio-group": "^1",
234
- "@radix-ui/react-select": "^2",
235
- "@radix-ui/react-separator": "^1",
236
- "@radix-ui/react-slot": "^1",
237
- "@radix-ui/react-tabs": "^1",
238
- "@radix-ui/react-toggle": "^1",
239
- "@radix-ui/react-toggle-group": "^1",
240
- "@radix-ui/react-tooltip": "^1",
241
224
  "@tanstack/react-table": "^8",
242
- "@tanstack/react-virtual": "^3",
243
- "cmdk": "^1",
244
- "date-fns": "^3 || ^4",
245
- "embla-carousel-react": "^8",
246
225
  "react": "^18 || ^19",
247
- "react-day-picker": "^9",
248
226
  "react-dom": "^18 || ^19",
249
227
  "react-hook-form": "^7",
250
- "sonner": "^1 || ^2",
251
228
  "zod": "^3 || ^4"
252
229
  },
253
230
  "peerDependenciesMeta": {
@@ -257,81 +234,12 @@
257
234
  "@phosphor-icons/react": {
258
235
  "optional": true
259
236
  },
260
- "@radix-ui/react-accordion": {
261
- "optional": true
262
- },
263
- "@radix-ui/react-avatar": {
264
- "optional": true
265
- },
266
- "@radix-ui/react-checkbox": {
267
- "optional": true
268
- },
269
- "@radix-ui/react-collapsible": {
270
- "optional": true
271
- },
272
- "@radix-ui/react-dialog": {
273
- "optional": true
274
- },
275
- "@radix-ui/react-dropdown-menu": {
276
- "optional": true
277
- },
278
- "@radix-ui/react-label": {
279
- "optional": true
280
- },
281
- "@radix-ui/react-popover": {
282
- "optional": true
283
- },
284
- "@radix-ui/react-progress": {
285
- "optional": true
286
- },
287
- "@radix-ui/react-radio-group": {
288
- "optional": true
289
- },
290
- "@radix-ui/react-select": {
291
- "optional": true
292
- },
293
- "@radix-ui/react-separator": {
294
- "optional": true
295
- },
296
- "@radix-ui/react-slot": {
297
- "optional": true
298
- },
299
- "@radix-ui/react-tabs": {
300
- "optional": true
301
- },
302
- "@radix-ui/react-toggle": {
303
- "optional": true
304
- },
305
- "@radix-ui/react-toggle-group": {
306
- "optional": true
307
- },
308
- "@radix-ui/react-tooltip": {
309
- "optional": true
310
- },
311
237
  "@tanstack/react-table": {
312
238
  "optional": true
313
239
  },
314
- "@tanstack/react-virtual": {
315
- "optional": true
316
- },
317
- "cmdk": {
318
- "optional": true
319
- },
320
- "date-fns": {
321
- "optional": true
322
- },
323
- "embla-carousel-react": {
324
- "optional": true
325
- },
326
- "react-day-picker": {
327
- "optional": true
328
- },
329
240
  "react-hook-form": {
330
241
  "optional": true
331
242
  },
332
- "sonner": {
333
- "optional": true
334
- },
335
243
  "zod": {
336
244
  "optional": true
337
245
  }
@@ -427,8 +335,31 @@
427
335
  "dist"
428
336
  ],
429
337
  "dependencies": {
338
+ "@radix-ui/react-accordion": "^1.2.11",
339
+ "@radix-ui/react-avatar": "^1.1.10",
340
+ "@radix-ui/react-checkbox": "^1.3.2",
341
+ "@radix-ui/react-collapsible": "^1.1.11",
342
+ "@radix-ui/react-dialog": "^1.1.14",
343
+ "@radix-ui/react-dropdown-menu": "^2.1.15",
344
+ "@radix-ui/react-label": "^2.1.7",
345
+ "@radix-ui/react-popover": "^1.1.14",
346
+ "@radix-ui/react-progress": "^1.1.7",
347
+ "@radix-ui/react-radio-group": "^1.3.7",
348
+ "@radix-ui/react-select": "^2.2.5",
349
+ "@radix-ui/react-separator": "^1.1.7",
350
+ "@radix-ui/react-slot": "^1.2.3",
351
+ "@radix-ui/react-tabs": "^1.1.12",
352
+ "@radix-ui/react-toggle": "^1.1.9",
353
+ "@radix-ui/react-toggle-group": "^1.1.10",
354
+ "@radix-ui/react-tooltip": "^1.2.7",
430
355
  "class-variance-authority": "0.7.1",
431
356
  "clsx": "2.1.1",
432
- "tailwind-merge": "3.3.1"
357
+ "cmdk": "^1.1.1",
358
+ "date-fns": "^4.1.0",
359
+ "embla-carousel-react": "^8.6.0",
360
+ "react-day-picker": "^9.7.0",
361
+ "sonner": "^2.0.5",
362
+ "tailwind-merge": "3.3.1",
363
+ "@tanstack/react-virtual": "^3.13.18"
433
364
  }
434
365
  }