@aurora-ds/components 0.17.17 → 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.
@@ -1,9 +1,10 @@
1
1
  import { CalendarIcon } from '@resources/icons/CalendarIcon.tsx';
2
2
  import { ChevronDownIcon } from '@resources/icons/ChevronDownIcon.tsx';
3
+ import { ChevronLeftIcon } from '@resources/icons/ChevronLeftIcon.tsx';
3
4
  import { ChevronRightIcon } from '@resources/icons/ChevronRightIcon.tsx';
4
5
  import { CloseIcon } from '@resources/icons/CloseIcon.tsx';
5
6
  import { EyeIcon } from '@resources/icons/EyeIcon.tsx';
6
7
  import { EyeOffIcon } from '@resources/icons/EyeOffIcon.tsx';
7
8
  import { InfoIcon } from '@resources/icons/InfoIcon.tsx';
8
9
  import { MoreHorizontalIcon } from '@resources/icons/MoreHorizontalIcon.tsx';
9
- export { CalendarIcon, ChevronDownIcon, ChevronRightIcon, InfoIcon, MoreHorizontalIcon, EyeIcon, EyeOffIcon, CloseIcon };
10
+ export { CalendarIcon, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, InfoIcon, MoreHorizontalIcon, EyeIcon, EyeOffIcon, CloseIcon };
@@ -0,0 +1 @@
1
+ export declare const ChevronLeftIcon: () => import("react/jsx-runtime").JSX.Element;
@@ -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';
@@ -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/esm/index.js CHANGED
@@ -940,25 +940,29 @@ const CalendarIcon = () => {
940
940
  };
941
941
 
942
942
  const ChevronDownIcon = () => {
943
- return (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: jsx("path", { d: 'm6 9 6 6 6-6' }) }));
943
+ return (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: jsx("path", { d: 'm6 9 6 6 6-6' }) }));
944
+ };
945
+
946
+ const ChevronLeftIcon = () => {
947
+ return (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: jsx("path", { d: 'm15 18-6-6 6-6' }) }));
944
948
  };
945
949
 
946
950
  const ChevronRightIcon = () => {
947
- return (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: jsx("path", { d: 'm9 18 6-6-6-6' }) }));
951
+ return (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: jsx("path", { d: 'm9 18 6-6-6-6' }) }));
948
952
  };
949
953
 
950
954
  const CloseIcon = () => (jsx("svg", { width: '16', height: '16', viewBox: '0 0 16 16', fill: 'none', xmlns: 'http://www.w3.org/2000/svg', children: jsx("path", { d: 'M12 4L4 12M4 4l8 8', stroke: 'currentColor', strokeWidth: '2', strokeLinecap: 'round', strokeLinejoin: 'round' }) }));
951
955
 
952
956
  const EyeIcon = () => {
953
- return (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: [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' }), jsx("circle", { cx: '12', cy: '12', r: '3' })] }));
957
+ return (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: [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' }), jsx("circle", { cx: '12', cy: '12', r: '3' })] }));
954
958
  };
955
959
 
956
960
  const EyeOffIcon = () => {
957
- return (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: [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' }), jsx("path", { d: 'M14.084 14.158a3 3 0 0 1-4.242-4.242' }), 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' }), jsx("path", { d: 'm2 2 20 20' })] }));
961
+ return (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: [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' }), jsx("path", { d: 'M14.084 14.158a3 3 0 0 1-4.242-4.242' }), 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' }), jsx("path", { d: 'm2 2 20 20' })] }));
958
962
  };
959
963
 
960
964
  const MoreHorizontalIcon = () => {
961
- return (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: [jsx("circle", { cx: '12', cy: '12', r: '1' }), jsx("circle", { cx: '19', cy: '12', r: '1' }), jsx("circle", { cx: '5', cy: '12', r: '1' })] }));
965
+ return (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: [jsx("circle", { cx: '12', cy: '12', r: '1' }), jsx("circle", { cx: '19', cy: '12', r: '1' }), jsx("circle", { cx: '5', cy: '12', r: '1' })] }));
962
966
  };
963
967
 
964
968
  /**
@@ -2174,15 +2178,16 @@ const Modal = ({ isOpen, onClose, label, children, isForm, action }) => {
2174
2178
  document.addEventListener('keydown', handleKeyDown);
2175
2179
  return () => document.removeEventListener('keydown', handleKeyDown);
2176
2180
  }, [isOpen, onClose]);
2177
- // components
2178
- const Wrapper = isForm ? Form : Fragment;
2179
- const wrapperProps = isForm ? {
2180
- onSubmit: (e) => {
2181
- e.preventDefault();
2182
- action?.onClick();
2181
+ // actions
2182
+ const safeInvokeAction = (e) => {
2183
+ if (action && typeof action.onClick === 'function') {
2184
+ // Cast e to required MouseEvent type (or undefined) and call
2185
+ action.onClick(e);
2183
2186
  }
2184
- } : {};
2185
- return createPortal(jsx(Fragment, { children: isVisible ? (jsx("div", { className: MODAL_STYLES.background(isFadingIn), ref: modalRef, children: jsx("div", { className: MODAL_STYLES.content(isFadingIn), children: jsxs(Wrapper, { ...wrapperProps, children: [jsxs(Stack, { justify: 'space-between', height: BUTTON_SIZE, width: '100%', children: [jsx(Text, { variant: 'h3', children: label }), !action && (jsx(IconButton, { icon: jsx(CloseIcon, {}), onClick: onClose, size: 'small', variant: 'text', textColor: 'text' }))] }), children, action && (jsxs(Stack, { justify: 'flex-end', width: '100%', children: [jsx(Button, { label: 'Cancel', onClick: onClose, variant: 'outlined' }), jsx(Button, { label: action.label, onClick: !isForm ? action.onClick : undefined, type: isForm ? 'submit' : 'button', disabled: action.disabled })] }))] }) }) })) : null }), document.body);
2187
+ };
2188
+ // body of the modal
2189
+ const body = (jsxs(Fragment$1, { children: [jsxs(Stack, { justify: 'space-between', height: BUTTON_SIZE, width: '100%', children: [jsx(Text, { variant: 'h3', children: label }), !action && (jsx(IconButton, { icon: jsx(CloseIcon, {}), onClick: onClose, size: 'small', variant: 'text', textColor: 'text' }))] }), children, action && (jsxs(Stack, { justify: 'flex-end', width: '100%', children: [jsx(Button, { label: 'Cancel', onClick: onClose, variant: 'outlined' }), jsx(Button, { label: action.label, onClick: !isForm ? action.onClick : undefined, type: isForm ? 'submit' : 'button', disabled: action.disabled })] }))] }));
2190
+ return createPortal(jsx(Fragment, { children: isVisible ? (jsx("div", { className: MODAL_STYLES.background(isFadingIn), ref: modalRef, children: jsx("div", { className: MODAL_STYLES.content(isFadingIn), children: isForm ? (jsx(Form, { onSubmit: (e) => { e.preventDefault(); safeInvokeAction(); }, children: body })) : (jsx(Fragment, { children: body })) }) })) : null }), document.body);
2186
2191
  };
2187
2192
  Modal.displayName = 'Modal';
2188
2193
 
@@ -2498,5 +2503,134 @@ const TabItem = ({ label, isActive = false, onClick, startIcon, endIcon }) => {
2498
2503
  };
2499
2504
  TabItem.displayName = 'TabItem';
2500
2505
 
2501
- export { Accordion, Avatar, AvatarGroup, Breadcrumb, BreadcrumbEllipsis, BreadcrumbLink, BreadcrumbPage, BreadcrumbSeparator, Button, Card, Chip, DatePicker_default as DatePicker, DrawerItem, Form, Grid, Icon, IconButton, Input_default as Input, Menu, MenuGroup, MenuItem, Modal, Page, PageSection, Select, Separator, Skeleton, Stack, TabItem, Tabs, Text, TextArea_default as TextArea, useAnchorPosition, useClickOutside, useTransitionRender };
2506
+ const PAGINATION_STYLES = createStyles((theme) => ({
2507
+ root: {
2508
+ display: 'flex',
2509
+ alignItems: 'center',
2510
+ gap: theme.spacing.xs,
2511
+ },
2512
+ pageButton: ({ disabled = false }) => ({
2513
+ display: 'inline-flex',
2514
+ alignItems: 'center',
2515
+ justifyContent: 'center',
2516
+ boxSizing: 'border-box',
2517
+ padding: theme.spacing.sm,
2518
+ borderRadius: theme.radius.md,
2519
+ cursor: disabled ? 'not-allowed' : 'pointer',
2520
+ transition: `background-color ${theme.transition.fast}, color ${theme.transition.fast}`,
2521
+ minHeight: '40px',
2522
+ maxHeight: '40px',
2523
+ minWidth: '40px',
2524
+ maxWidth: '40px',
2525
+ fontFamily: 'inherit',
2526
+ fontSize: theme.fontSize.md,
2527
+ fontWeight: theme.fontWeight.medium,
2528
+ backgroundColor: 'transparent',
2529
+ color: theme.colors.text,
2530
+ border: 'none',
2531
+ opacity: disabled ? 0.4 : 1,
2532
+ ':hover': disabled ? {} : {
2533
+ backgroundColor: theme.colors.surfaceHover,
2534
+ },
2535
+ ':active': disabled ? {} : {
2536
+ backgroundColor: theme.colors.surfaceActive,
2537
+ },
2538
+ }),
2539
+ activePageButton: {
2540
+ backgroundColor: theme.colors.primary,
2541
+ color: theme.colors.onPrimary,
2542
+ ':hover': {
2543
+ backgroundColor: theme.colors.primary,
2544
+ },
2545
+ ':active': {
2546
+ backgroundColor: theme.colors.primary,
2547
+ },
2548
+ },
2549
+ navigationButton: ({ disabled = false }) => ({
2550
+ display: 'inline-flex',
2551
+ alignItems: 'center',
2552
+ justifyContent: 'center',
2553
+ boxSizing: 'border-box',
2554
+ padding: theme.spacing.sm,
2555
+ borderRadius: theme.radius.md,
2556
+ cursor: disabled ? 'not-allowed' : 'pointer',
2557
+ transition: `background-color ${theme.transition.fast}, color ${theme.transition.fast}`,
2558
+ minHeight: '40px',
2559
+ maxHeight: '40px',
2560
+ minWidth: '40px',
2561
+ maxWidth: '40px',
2562
+ fontFamily: 'inherit',
2563
+ backgroundColor: 'transparent',
2564
+ color: theme.colors.text,
2565
+ border: 'none',
2566
+ opacity: disabled ? 0.4 : 1,
2567
+ ':hover': disabled ? {} : {
2568
+ backgroundColor: theme.colors.surfaceHover,
2569
+ },
2570
+ ':active': disabled ? {} : {
2571
+ backgroundColor: theme.colors.surfaceActive,
2572
+ },
2573
+ }),
2574
+ }));
2575
+
2576
+ /**
2577
+ * Pagination component for navigating between pages
2578
+ */
2579
+ const Pagination = ({ currentPage, totalPages, onPageChange, onPrevious, onNext, maxVisiblePages = 7, ariaLabel = 'Pagination' }) => {
2580
+ const styles = PAGINATION_STYLES;
2581
+ // Calculate which page numbers to display
2582
+ const visiblePages = useMemo(() => {
2583
+ const pages = [];
2584
+ if (totalPages <= maxVisiblePages) {
2585
+ // Show all pages if they fit
2586
+ for (let i = 1; i <= totalPages; i++) {
2587
+ pages.push(i);
2588
+ }
2589
+ }
2590
+ else {
2591
+ // Calculate range around current page
2592
+ const halfVisible = Math.floor(maxVisiblePages / 2);
2593
+ const start = Math.max(1, currentPage - halfVisible);
2594
+ const end = Math.min(totalPages, start + maxVisiblePages - 1);
2595
+ // Adjust start if we're near the end
2596
+ const adjustedStart = end === totalPages ? Math.max(1, end - maxVisiblePages + 1) : start;
2597
+ for (let i = adjustedStart; i <= end; i++) {
2598
+ pages.push(i);
2599
+ }
2600
+ }
2601
+ return pages;
2602
+ }, [currentPage, totalPages, maxVisiblePages]);
2603
+ const handlePrevious = () => {
2604
+ if (currentPage > 1) {
2605
+ const newPage = currentPage - 1;
2606
+ if (onPrevious) {
2607
+ onPrevious(newPage);
2608
+ }
2609
+ onPageChange(newPage);
2610
+ }
2611
+ };
2612
+ const handleNext = () => {
2613
+ if (currentPage < totalPages) {
2614
+ const newPage = currentPage + 1;
2615
+ if (onNext) {
2616
+ onNext(newPage);
2617
+ }
2618
+ onPageChange(newPage);
2619
+ }
2620
+ };
2621
+ const handlePageClick = (page) => {
2622
+ if (page !== currentPage) {
2623
+ onPageChange(page);
2624
+ }
2625
+ };
2626
+ const isPreviousDisabled = currentPage === 1;
2627
+ const isNextDisabled = currentPage === totalPages;
2628
+ return (jsxs("nav", { "aria-label": ariaLabel, className: styles.root, children: [jsx("button", { type: 'button', onClick: handlePrevious, disabled: isPreviousDisabled, "aria-label": 'Page précédente', className: styles.navigationButton({ disabled: isPreviousDisabled }), children: jsx(ChevronLeftIcon, {}) }), visiblePages.map((page) => {
2629
+ const isActive = page === currentPage;
2630
+ return (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));
2631
+ }), jsx("button", { type: 'button', onClick: handleNext, disabled: isNextDisabled, "aria-label": 'Page suivante', className: styles.navigationButton({ disabled: isNextDisabled }), children: jsx(ChevronRightIcon, {}) })] }));
2632
+ };
2633
+ Pagination.displayName = 'Pagination';
2634
+
2635
+ export { Accordion, Avatar, AvatarGroup, Breadcrumb, BreadcrumbEllipsis, BreadcrumbLink, BreadcrumbPage, BreadcrumbSeparator, Button, Card, Chip, DatePicker_default as DatePicker, DrawerItem, Form, Grid, Icon, IconButton, Input_default as Input, Menu, MenuGroup, MenuItem, Modal, Page, PageSection, Pagination, Select, Separator, Skeleton, Stack, TabItem, Tabs, Text, TextArea_default as TextArea, useAnchorPosition, useClickOutside, useTransitionRender };
2502
2636
  //# sourceMappingURL=index.js.map