@aurora-ds/components 0.17.16 → 0.18.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.
package/README.md CHANGED
@@ -62,6 +62,7 @@ function App() {
62
62
  | **Menu** | Dropdown menu component positioned absolutely |
63
63
  | **Page** | Page layout component |
64
64
  | **PageSection** | Section within a page |
65
+ | **Pagination** | Pagination component for navigating between pages |
65
66
  | **Separator** | Visual separator component |
66
67
  | **Select** | Dropdown select component for single item selection |
67
68
  | **DatePicker** | Date picker component with calendar popup |
@@ -22,6 +22,7 @@ export * from '@components/overlay/modal';
22
22
  export * from '@components/navigation/drawer-item';
23
23
  export * from '@components/navigation/breadcrumb';
24
24
  export * from '@components/navigation/tabs';
25
+ export * from '@components/navigation/pagination';
25
26
  export type { ButtonVariants, ButtonVariantStyle } from '@interfaces/button.types';
26
27
  export type { TextVariants, TextVariantStyle } from '@interfaces/text.types';
27
28
  export type { ChipVariant, ChipColor, ChipSize } from '@interfaces/chip.types';
@@ -3,10 +3,10 @@ import { CSSProperties, ReactNode } from 'react';
3
3
  export type GridProps = {
4
4
  /** Grid children elements */
5
5
  children: ReactNode;
6
- /** Number of columns (number or CSS grid-template-columns value). Acts as max columns when minChildWidth is set. */
7
- columns?: number | string;
8
- /** Number of rows (number or CSS grid-template-rows value). */
9
- rows?: number | string;
6
+ /** Number of columns. Acts as max columns when minChildWidth is set for responsive behavior. */
7
+ columns?: number;
8
+ /** Number of rows. */
9
+ rows?: number;
10
10
  /** Gap between columns (theme spacing key) */
11
11
  columnGap?: keyof Theme['spacing'];
12
12
  /** Gap between rows (theme spacing key) */
@@ -41,8 +41,8 @@ export type GridProps = {
41
41
  tabIndex?: number;
42
42
  };
43
43
  export type GridStyleParams = {
44
- columns?: number | string;
45
- rows?: number | string;
44
+ columns?: number;
45
+ rows?: number;
46
46
  columnGap?: keyof Theme['spacing'];
47
47
  rowGap?: keyof Theme['spacing'];
48
48
  width?: CSSProperties['width'];
@@ -0,0 +1,6 @@
1
+ import { FC } from 'react';
2
+ import { PaginationProps } from '@components/navigation/pagination/Pagination.props';
3
+ /**
4
+ * Pagination component for navigating between pages
5
+ */
6
+ export declare const Pagination: FC<PaginationProps>;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Props for the Pagination component
3
+ */
4
+ export type PaginationProps = {
5
+ /** Current page number (1-indexed) */
6
+ currentPage: number;
7
+ /** Total number of pages */
8
+ totalPages: number;
9
+ /** Callback when page changes */
10
+ onPageChange: (page: number) => void;
11
+ /** Callback when clicking the previous button */
12
+ onPrevious?: (page: number) => void;
13
+ /** Callback when clicking the next button */
14
+ onNext?: (page: number) => void;
15
+ /** Maximum number of page buttons to display */
16
+ maxVisiblePages?: number;
17
+ /** Accessibility label for the pagination */
18
+ ariaLabel?: string;
19
+ };
20
+ export type PaginationStyleParams = {
21
+ disabled?: boolean;
22
+ };
@@ -0,0 +1,7 @@
1
+ import { PaginationStyleParams } from '@components/navigation/pagination/Pagination.props';
2
+ export declare const PAGINATION_STYLES: {
3
+ root: string;
4
+ pageButton: (args_0: PaginationStyleParams) => string;
5
+ activePageButton: string;
6
+ navigationButton: (args_0: PaginationStyleParams) => string;
7
+ };
@@ -0,0 +1,2 @@
1
+ export * from '@components/navigation/pagination/Pagination';
2
+ export type { PaginationProps } from '@components/navigation/pagination/Pagination.props';
@@ -1,13 +1,10 @@
1
1
  import { ReactNode } from 'react';
2
+ import { ButtonProps } from '@/components';
2
3
  export type ModalProps = {
3
4
  isOpen: boolean;
4
5
  onClose: () => void;
5
6
  label: string;
6
7
  children: ReactNode;
7
8
  isForm?: boolean;
8
- action?: {
9
- label: string;
10
- onClick: () => void;
11
- disabled?: boolean;
12
- };
9
+ action?: ButtonProps;
13
10
  };
package/dist/cjs/index.js CHANGED
@@ -942,25 +942,29 @@ const CalendarIcon = () => {
942
942
  };
943
943
 
944
944
  const ChevronDownIcon = () => {
945
- return (jsxRuntime.jsx("svg", { xmlns: 'http://www.w3.org/2000/svg', width: '100%', height: '100%', viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', "stroke-width": '2', "stroke-linecap": 'round', "stroke-linejoin": 'round', className: 'lucide lucide-chevron-down-icon lucide-chevron-down', children: jsxRuntime.jsx("path", { d: 'm6 9 6 6 6-6' }) }));
945
+ return (jsxRuntime.jsx("svg", { xmlns: 'http://www.w3.org/2000/svg', width: '100%', height: '100%', viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: '2', strokeLinecap: 'round', strokeLinejoin: 'round', className: 'lucide lucide-chevron-down-icon lucide-chevron-down', children: jsxRuntime.jsx("path", { d: 'm6 9 6 6 6-6' }) }));
946
+ };
947
+
948
+ const ChevronLeftIcon = () => {
949
+ return (jsxRuntime.jsx("svg", { xmlns: 'http://www.w3.org/2000/svg', width: '24', height: '24', viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: '2', strokeLinecap: 'round', strokeLinejoin: 'round', className: 'lucide lucide-chevron-left-icon lucide-chevron-left', children: jsxRuntime.jsx("path", { d: 'm15 18-6-6 6-6' }) }));
946
950
  };
947
951
 
948
952
  const ChevronRightIcon = () => {
949
- return (jsxRuntime.jsx("svg", { xmlns: 'http://www.w3.org/2000/svg', width: '24', height: '24', viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', "stroke-width": '2', "stroke-linecap": 'round', "stroke-linejoin": 'round', className: 'lucide lucide-chevron-right-icon lucide-chevron-right', children: jsxRuntime.jsx("path", { d: 'm9 18 6-6-6-6' }) }));
953
+ return (jsxRuntime.jsx("svg", { xmlns: 'http://www.w3.org/2000/svg', width: '24', height: '24', viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: '2', strokeLinecap: 'round', strokeLinejoin: 'round', className: 'lucide lucide-chevron-right-icon lucide-chevron-right', children: jsxRuntime.jsx("path", { d: 'm9 18 6-6-6-6' }) }));
950
954
  };
951
955
 
952
956
  const CloseIcon = () => (jsxRuntime.jsx("svg", { width: '16', height: '16', viewBox: '0 0 16 16', fill: 'none', xmlns: 'http://www.w3.org/2000/svg', children: jsxRuntime.jsx("path", { d: 'M12 4L4 12M4 4l8 8', stroke: 'currentColor', strokeWidth: '2', strokeLinecap: 'round', strokeLinejoin: 'round' }) }));
953
957
 
954
958
  const EyeIcon = () => {
955
- return (jsxRuntime.jsxs("svg", { xmlns: 'http://www.w3.org/2000/svg', width: '24', height: '24', viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', "stroke-width": '2', "stroke-linecap": 'round', "stroke-linejoin": 'round', className: 'lucide lucide-eye-icon lucide-eye', children: [jsxRuntime.jsx("path", { d: 'M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0' }), jsxRuntime.jsx("circle", { cx: '12', cy: '12', r: '3' })] }));
959
+ return (jsxRuntime.jsxs("svg", { xmlns: 'http://www.w3.org/2000/svg', width: '24', height: '24', viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: '2', strokeLinecap: 'round', strokeLinejoin: 'round', className: 'lucide lucide-eye-icon lucide-eye', children: [jsxRuntime.jsx("path", { d: 'M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0' }), jsxRuntime.jsx("circle", { cx: '12', cy: '12', r: '3' })] }));
956
960
  };
957
961
 
958
962
  const EyeOffIcon = () => {
959
- return (jsxRuntime.jsxs("svg", { xmlns: 'http://www.w3.org/2000/svg', width: '24', height: '24', viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', "stroke-width": '2', "stroke-linecap": 'round', "stroke-linejoin": 'round', className: 'lucide lucide-eye-off-icon lucide-eye-off', children: [jsxRuntime.jsx("path", { d: 'M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49' }), jsxRuntime.jsx("path", { d: 'M14.084 14.158a3 3 0 0 1-4.242-4.242' }), jsxRuntime.jsx("path", { d: 'M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143' }), jsxRuntime.jsx("path", { d: 'm2 2 20 20' })] }));
963
+ return (jsxRuntime.jsxs("svg", { xmlns: 'http://www.w3.org/2000/svg', width: '24', height: '24', viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: '2', strokeLinecap: 'round', strokeLinejoin: 'round', className: 'lucide lucide-eye-off-icon lucide-eye-off', children: [jsxRuntime.jsx("path", { d: 'M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49' }), jsxRuntime.jsx("path", { d: 'M14.084 14.158a3 3 0 0 1-4.242-4.242' }), jsxRuntime.jsx("path", { d: 'M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143' }), jsxRuntime.jsx("path", { d: 'm2 2 20 20' })] }));
960
964
  };
961
965
 
962
966
  const MoreHorizontalIcon = () => {
963
- return (jsxRuntime.jsxs("svg", { xmlns: 'http://www.w3.org/2000/svg', width: '24', height: '24', viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', "stroke-width": '2', "stroke-linecap": 'round', "stroke-linejoin": 'round', className: 'lucide lucide-ellipsis-icon lucide-ellipsis', children: [jsxRuntime.jsx("circle", { cx: '12', cy: '12', r: '1' }), jsxRuntime.jsx("circle", { cx: '19', cy: '12', r: '1' }), jsxRuntime.jsx("circle", { cx: '5', cy: '12', r: '1' })] }));
967
+ return (jsxRuntime.jsxs("svg", { xmlns: 'http://www.w3.org/2000/svg', width: '24', height: '24', viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: '2', strokeLinecap: 'round', strokeLinejoin: 'round', className: 'lucide lucide-ellipsis-icon lucide-ellipsis', children: [jsxRuntime.jsx("circle", { cx: '12', cy: '12', r: '1' }), jsxRuntime.jsx("circle", { cx: '19', cy: '12', r: '1' }), jsxRuntime.jsx("circle", { cx: '5', cy: '12', r: '1' })] }));
964
968
  };
965
969
 
966
970
  /**
@@ -1893,8 +1897,8 @@ Card.displayName = 'Card';
1893
1897
  /**
1894
1898
  * Generates the grid-template-columns value based on columns and minChildWidth props
1895
1899
  * - If only columns is defined: creates a fixed number of columns
1896
- * - If only minChildWidth is defined: creates responsive auto-fill columns (items stretch)
1897
- * - If both are defined: creates responsive columns with a maximum limit (items don't stretch beyond column width)
1900
+ * - If only minChildWidth is defined: creates responsive auto-fill columns
1901
+ * - If both are defined: creates responsive columns with a maximum limit (columns acts as max)
1898
1902
  *
1899
1903
  * Key difference between auto-fill and auto-fit:
1900
1904
  * - auto-fill: keeps empty column tracks, items don't stretch to fill container
@@ -1902,12 +1906,11 @@ Card.displayName = 'Card';
1902
1906
  */
1903
1907
  const getGridTemplateColumns = (columns, minChildWidth, columnGap) => {
1904
1908
  const minWidthValue = typeof minChildWidth === 'number' ? `${minChildWidth}px` : minChildWidth;
1905
- if (minChildWidth && typeof columns === 'number') {
1909
+ if (minChildWidth && columns) {
1906
1910
  // Responsive grid with max columns limit
1907
1911
  // Uses auto-fill to preserve empty column tracks (items don't stretch beyond their column)
1908
1912
  // The min value ensures items are at least minChildWidth
1909
1913
  // The max value is 1fr to distribute space evenly within the max columns constraint
1910
- // The calc ensures we never exceed the specified number of columns
1911
1914
  const gapValue = columnGap || '0px';
1912
1915
  const minColumnWidth = `calc((100% - (${columns} - 1) * ${gapValue}) / ${columns})`;
1913
1916
  return `repeat(auto-fill, minmax(max(${minWidthValue}, ${minColumnWidth}), 1fr))`;
@@ -1916,20 +1919,20 @@ const getGridTemplateColumns = (columns, minChildWidth, columnGap) => {
1916
1919
  // Responsive grid without column limit - items will fill available space
1917
1920
  return `repeat(auto-fill, minmax(${minWidthValue}, 1fr))`;
1918
1921
  }
1919
- if (typeof columns === 'number') {
1922
+ if (columns) {
1920
1923
  // Fixed number of columns - each column takes equal space
1921
1924
  return `repeat(${columns}, 1fr)`;
1922
1925
  }
1923
- return columns;
1926
+ return undefined;
1924
1927
  };
1925
1928
  /**
1926
1929
  * Generates the grid-template-rows value based on rows prop
1927
1930
  */
1928
1931
  const getGridTemplateRows = (rows) => {
1929
- if (typeof rows === 'number') {
1930
- return `repeat(${rows}, 1fr)`;
1932
+ if (rows) {
1933
+ return `repeat(${rows}, auto)`;
1931
1934
  }
1932
- return rows;
1935
+ return undefined;
1933
1936
  };
1934
1937
  /**
1935
1938
  * Grid styles using createStyles from @aurora-ds/theme
@@ -1967,7 +1970,7 @@ const GRID_STYLES = theme.createStyles((theme) => ({
1967
1970
  * - Use `minChildWidth` for responsive auto-fill grids
1968
1971
  * - Combine `columns` + `minChildWidth` for responsive grid with max columns limit
1969
1972
  */
1970
- const Grid = ({ children, columns = 1, rows, columnGap = 'md', rowGap = 'md', width, height, minHeight, alignItems, justifyItems, alignContent, justifyContent, padding, minChildWidth, ariaLabel, ariaLabelledBy, ariaDescribedBy, role, tabIndex, }) => {
1973
+ const Grid = ({ children, columns = 3, rows, columnGap = 'md', rowGap = 'md', width, height, minHeight, alignItems, justifyItems, alignContent, justifyContent, padding, minChildWidth, ariaLabel, ariaLabelledBy, ariaDescribedBy, role, tabIndex, }) => {
1971
1974
  return (jsxRuntime.jsx("div", { className: GRID_STYLES.root({
1972
1975
  columns,
1973
1976
  rows,
@@ -2177,15 +2180,16 @@ const Modal = ({ isOpen, onClose, label, children, isForm, action }) => {
2177
2180
  document.addEventListener('keydown', handleKeyDown);
2178
2181
  return () => document.removeEventListener('keydown', handleKeyDown);
2179
2182
  }, [isOpen, onClose]);
2180
- // components
2181
- const Wrapper = isForm ? Form$1 : React.Fragment;
2182
- const wrapperProps = isForm ? {
2183
- onSubmit: (e) => {
2184
- e.preventDefault();
2185
- action?.onClick();
2183
+ // actions
2184
+ const safeInvokeAction = (e) => {
2185
+ if (action && typeof action.onClick === 'function') {
2186
+ // Cast e to required MouseEvent type (or undefined) and call
2187
+ action.onClick(e);
2186
2188
  }
2187
- } : {};
2188
- return reactDom.createPortal(jsxRuntime.jsx(React.Fragment, { children: isVisible ? (jsxRuntime.jsx("div", { className: MODAL_STYLES.background(isFadingIn), ref: modalRef, children: jsxRuntime.jsx("div", { className: MODAL_STYLES.content(isFadingIn), children: jsxRuntime.jsxs(Wrapper, { ...wrapperProps, children: [jsxRuntime.jsxs(Stack, { justify: 'space-between', height: BUTTON_SIZE, width: '100%', children: [jsxRuntime.jsx(Text, { variant: 'h3', children: label }), !action && (jsxRuntime.jsx(IconButton, { icon: jsxRuntime.jsx(CloseIcon, {}), onClick: onClose, size: 'small', variant: 'text', textColor: 'text' }))] }), children, action && (jsxRuntime.jsxs(Stack, { justify: 'flex-end', width: '100%', children: [jsxRuntime.jsx(Button, { label: 'Cancel', onClick: onClose, variant: 'outlined' }), jsxRuntime.jsx(Button, { label: action.label, onClick: !isForm ? action.onClick : undefined, type: isForm ? 'submit' : 'button', disabled: action.disabled })] }))] }) }) })) : null }), document.body);
2189
+ };
2190
+ // body of the modal
2191
+ const body = (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs(Stack, { justify: 'space-between', height: BUTTON_SIZE, width: '100%', children: [jsxRuntime.jsx(Text, { variant: 'h3', children: label }), !action && (jsxRuntime.jsx(IconButton, { icon: jsxRuntime.jsx(CloseIcon, {}), onClick: onClose, size: 'small', variant: 'text', textColor: 'text' }))] }), children, action && (jsxRuntime.jsxs(Stack, { justify: 'flex-end', width: '100%', children: [jsxRuntime.jsx(Button, { label: 'Cancel', onClick: onClose, variant: 'outlined' }), jsxRuntime.jsx(Button, { label: action.label, onClick: !isForm ? action.onClick : undefined, type: isForm ? 'submit' : 'button', disabled: action.disabled })] }))] }));
2192
+ return reactDom.createPortal(jsxRuntime.jsx(React.Fragment, { children: isVisible ? (jsxRuntime.jsx("div", { className: MODAL_STYLES.background(isFadingIn), ref: modalRef, children: jsxRuntime.jsx("div", { className: MODAL_STYLES.content(isFadingIn), children: isForm ? (jsxRuntime.jsx(Form$1, { onSubmit: (e) => { e.preventDefault(); safeInvokeAction(); }, children: body })) : (jsxRuntime.jsx(React.Fragment, { children: body })) }) })) : null }), document.body);
2189
2193
  };
2190
2194
  Modal.displayName = 'Modal';
2191
2195
 
@@ -2501,6 +2505,135 @@ const TabItem = ({ label, isActive = false, onClick, startIcon, endIcon }) => {
2501
2505
  };
2502
2506
  TabItem.displayName = 'TabItem';
2503
2507
 
2508
+ const PAGINATION_STYLES = theme.createStyles((theme) => ({
2509
+ root: {
2510
+ display: 'flex',
2511
+ alignItems: 'center',
2512
+ gap: theme.spacing.xs,
2513
+ },
2514
+ pageButton: ({ disabled = false }) => ({
2515
+ display: 'inline-flex',
2516
+ alignItems: 'center',
2517
+ justifyContent: 'center',
2518
+ boxSizing: 'border-box',
2519
+ padding: theme.spacing.sm,
2520
+ borderRadius: theme.radius.md,
2521
+ cursor: disabled ? 'not-allowed' : 'pointer',
2522
+ transition: `background-color ${theme.transition.fast}, color ${theme.transition.fast}`,
2523
+ minHeight: '40px',
2524
+ maxHeight: '40px',
2525
+ minWidth: '40px',
2526
+ maxWidth: '40px',
2527
+ fontFamily: 'inherit',
2528
+ fontSize: theme.fontSize.md,
2529
+ fontWeight: theme.fontWeight.medium,
2530
+ backgroundColor: 'transparent',
2531
+ color: theme.colors.text,
2532
+ border: 'none',
2533
+ opacity: disabled ? 0.4 : 1,
2534
+ ':hover': disabled ? {} : {
2535
+ backgroundColor: theme.colors.surfaceHover,
2536
+ },
2537
+ ':active': disabled ? {} : {
2538
+ backgroundColor: theme.colors.surfaceActive,
2539
+ },
2540
+ }),
2541
+ activePageButton: {
2542
+ backgroundColor: theme.colors.primary,
2543
+ color: theme.colors.onPrimary,
2544
+ ':hover': {
2545
+ backgroundColor: theme.colors.primary,
2546
+ },
2547
+ ':active': {
2548
+ backgroundColor: theme.colors.primary,
2549
+ },
2550
+ },
2551
+ navigationButton: ({ disabled = false }) => ({
2552
+ display: 'inline-flex',
2553
+ alignItems: 'center',
2554
+ justifyContent: 'center',
2555
+ boxSizing: 'border-box',
2556
+ padding: theme.spacing.sm,
2557
+ borderRadius: theme.radius.md,
2558
+ cursor: disabled ? 'not-allowed' : 'pointer',
2559
+ transition: `background-color ${theme.transition.fast}, color ${theme.transition.fast}`,
2560
+ minHeight: '40px',
2561
+ maxHeight: '40px',
2562
+ minWidth: '40px',
2563
+ maxWidth: '40px',
2564
+ fontFamily: 'inherit',
2565
+ backgroundColor: 'transparent',
2566
+ color: theme.colors.text,
2567
+ border: 'none',
2568
+ opacity: disabled ? 0.4 : 1,
2569
+ ':hover': disabled ? {} : {
2570
+ backgroundColor: theme.colors.surfaceHover,
2571
+ },
2572
+ ':active': disabled ? {} : {
2573
+ backgroundColor: theme.colors.surfaceActive,
2574
+ },
2575
+ }),
2576
+ }));
2577
+
2578
+ /**
2579
+ * Pagination component for navigating between pages
2580
+ */
2581
+ const Pagination = ({ currentPage, totalPages, onPageChange, onPrevious, onNext, maxVisiblePages = 7, ariaLabel = 'Pagination' }) => {
2582
+ const styles = PAGINATION_STYLES;
2583
+ // Calculate which page numbers to display
2584
+ const visiblePages = React.useMemo(() => {
2585
+ const pages = [];
2586
+ if (totalPages <= maxVisiblePages) {
2587
+ // Show all pages if they fit
2588
+ for (let i = 1; i <= totalPages; i++) {
2589
+ pages.push(i);
2590
+ }
2591
+ }
2592
+ else {
2593
+ // Calculate range around current page
2594
+ const halfVisible = Math.floor(maxVisiblePages / 2);
2595
+ const start = Math.max(1, currentPage - halfVisible);
2596
+ const end = Math.min(totalPages, start + maxVisiblePages - 1);
2597
+ // Adjust start if we're near the end
2598
+ const adjustedStart = end === totalPages ? Math.max(1, end - maxVisiblePages + 1) : start;
2599
+ for (let i = adjustedStart; i <= end; i++) {
2600
+ pages.push(i);
2601
+ }
2602
+ }
2603
+ return pages;
2604
+ }, [currentPage, totalPages, maxVisiblePages]);
2605
+ const handlePrevious = () => {
2606
+ if (currentPage > 1) {
2607
+ const newPage = currentPage - 1;
2608
+ if (onPrevious) {
2609
+ onPrevious(newPage);
2610
+ }
2611
+ onPageChange(newPage);
2612
+ }
2613
+ };
2614
+ const handleNext = () => {
2615
+ if (currentPage < totalPages) {
2616
+ const newPage = currentPage + 1;
2617
+ if (onNext) {
2618
+ onNext(newPage);
2619
+ }
2620
+ onPageChange(newPage);
2621
+ }
2622
+ };
2623
+ const handlePageClick = (page) => {
2624
+ if (page !== currentPage) {
2625
+ onPageChange(page);
2626
+ }
2627
+ };
2628
+ const isPreviousDisabled = currentPage === 1;
2629
+ const isNextDisabled = currentPage === totalPages;
2630
+ return (jsxRuntime.jsxs("nav", { "aria-label": ariaLabel, className: styles.root, children: [jsxRuntime.jsx("button", { type: 'button', onClick: handlePrevious, disabled: isPreviousDisabled, "aria-label": 'Page précédente', className: styles.navigationButton({ disabled: isPreviousDisabled }), children: jsxRuntime.jsx(ChevronLeftIcon, {}) }), visiblePages.map((page) => {
2631
+ const isActive = page === currentPage;
2632
+ return (jsxRuntime.jsx("button", { type: 'button', onClick: () => handlePageClick(page), "aria-label": `Page ${page}`, "aria-current": isActive ? 'page' : undefined, className: `${styles.pageButton({ disabled: false })} ${isActive ? styles.activePageButton : ''}`, children: page }, page));
2633
+ }), jsxRuntime.jsx("button", { type: 'button', onClick: handleNext, disabled: isNextDisabled, "aria-label": 'Page suivante', className: styles.navigationButton({ disabled: isNextDisabled }), children: jsxRuntime.jsx(ChevronRightIcon, {}) })] }));
2634
+ };
2635
+ Pagination.displayName = 'Pagination';
2636
+
2504
2637
  exports.Accordion = Accordion;
2505
2638
  exports.Avatar = Avatar;
2506
2639
  exports.AvatarGroup = AvatarGroup;
@@ -2525,6 +2658,7 @@ exports.MenuItem = MenuItem;
2525
2658
  exports.Modal = Modal;
2526
2659
  exports.Page = Page;
2527
2660
  exports.PageSection = PageSection;
2661
+ exports.Pagination = Pagination;
2528
2662
  exports.Select = Select;
2529
2663
  exports.Separator = Separator;
2530
2664
  exports.Skeleton = Skeleton;