@campxdev/react-blueprint 3.0.0-alpha.2 → 3.0.0-alpha.4
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/dist/cjs/index.js +1 -1
- package/dist/cjs/types/src/components/DataDisplay/DataTable/DataTable.d.ts +3 -0
- package/dist/cjs/types/src/components/DataDisplay/DataTable/components/TableView.d.ts +3 -0
- package/dist/cjs/types/src/components/Input/PasswordField/PasswordField.d.ts +2 -1
- package/dist/cjs/types/src/components/Layout/PageHeader/PageHeader.d.ts +3 -2
- package/dist/cjs/types/src/components/Navigation/Breadcrumbs/Breadcrumbs.d.ts +3 -1
- package/dist/esm/index.js +2 -2
- package/dist/esm/types/src/components/DataDisplay/DataTable/DataTable.d.ts +3 -0
- package/dist/esm/types/src/components/DataDisplay/DataTable/components/TableView.d.ts +3 -0
- package/dist/esm/types/src/components/Input/PasswordField/PasswordField.d.ts +2 -1
- package/dist/esm/types/src/components/Layout/PageHeader/PageHeader.d.ts +3 -2
- package/dist/esm/types/src/components/Navigation/Breadcrumbs/Breadcrumbs.d.ts +3 -1
- package/dist/index.d.ts +12 -6
- package/dist/styles.css +4 -13
- package/package.json +1 -1
- package/src/components/DataDisplay/DataTable/DataTable.tsx +5 -0
- package/src/components/DataDisplay/DataTable/components/TableView.tsx +13 -8
- package/src/components/DataDisplay/DataTable/components/ViewList/ViewButton.tsx +1 -1
- package/src/components/Feedback/Snackbar/Snackbar.tsx +5 -8
- package/src/components/Input/PasswordField/PasswordField.tsx +5 -2
- package/src/components/Layout/AppLayout/components/Sidebar/MenuBar.tsx +1 -0
- package/src/components/Layout/AppLayout/components/Sidebar/MenuItem.tsx +3 -3
- package/src/components/Layout/AppLayout/components/Sidebar/StyledComponents.tsx +1 -1
- package/src/components/Layout/PageHeader/PageHeader.tsx +8 -6
- package/src/components/Navigation/Breadcrumbs/Breadcrumbs.tsx +17 -6
- package/src/components/Navigation/TabsContainer/TabsContainer.tsx +1 -1
- package/src/hooks/usePageHeader.ts +1 -1
- package/src/shadcn-components/DataDisplay/Typography/Typography.tsx +1 -1
|
@@ -19,6 +19,9 @@ type DataTableProps<TData = any> = {
|
|
|
19
19
|
rowSelectionModel?: Record<string, boolean>;
|
|
20
20
|
onRowSelectionModelChange?: (newRowSelectionModel: Record<string, boolean>) => void;
|
|
21
21
|
selectionActions?: React.ReactNode[];
|
|
22
|
+
onRowClick?: (params: {
|
|
23
|
+
row: Row<TData>;
|
|
24
|
+
}) => void;
|
|
22
25
|
enableSorting?: boolean;
|
|
23
26
|
sortingState?: SortingState;
|
|
24
27
|
onSortingChange?: (newSortingState: SortingState) => void;
|
|
@@ -15,6 +15,9 @@ interface TableViewProps<TData = any> {
|
|
|
15
15
|
totalCount?: number;
|
|
16
16
|
onPageChange?: (page: number) => void;
|
|
17
17
|
onLimitChange?: (limit: number) => void;
|
|
18
|
+
onRowClick?: (params: {
|
|
19
|
+
row: Row<TData>;
|
|
20
|
+
}) => void;
|
|
18
21
|
}
|
|
19
22
|
declare const TableView: React.ForwardRefExoticComponent<TableViewProps<any> & React.RefAttributes<HTMLDivElement>>;
|
|
20
23
|
export default TableView;
|
|
@@ -11,5 +11,6 @@ export type PasswordFieldProps = {
|
|
|
11
11
|
error?: boolean;
|
|
12
12
|
helperText?: string;
|
|
13
13
|
className?: string;
|
|
14
|
+
fullWidth?: boolean;
|
|
14
15
|
} & Omit<React.InputHTMLAttributes<HTMLInputElement>, 'type'>;
|
|
15
|
-
export declare const PasswordField: ({ name, label, value, onChange, required, containerProps, description, placeholder, disabled, error, helperText, className, ...rest }: PasswordFieldProps) => import("react/jsx-runtime").JSX.Element;
|
|
16
|
+
export declare const PasswordField: ({ name, label, value, onChange, required, containerProps, description, placeholder, disabled, error, helperText, className, fullWidth, ...rest }: PasswordFieldProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -3,7 +3,8 @@ import { SearchBarProps } from '../../Input/SearchBar/SearchBar';
|
|
|
3
3
|
interface PageHeaderProps {
|
|
4
4
|
uniqueId?: string;
|
|
5
5
|
pathTrimCount: number;
|
|
6
|
-
|
|
6
|
+
breadcrumbAction?: ReactElement;
|
|
7
|
+
searchBarProps?: SearchBarProps;
|
|
7
8
|
filterButtonProps?: {
|
|
8
9
|
label?: string;
|
|
9
10
|
startIcon?: ReactNode;
|
|
@@ -19,5 +20,5 @@ interface PageHeaderProps {
|
|
|
19
20
|
}) => ReactNode[]);
|
|
20
21
|
};
|
|
21
22
|
}
|
|
22
|
-
declare const PageHeader: ({ uniqueId, pathTrimCount,
|
|
23
|
+
declare const PageHeader: ({ uniqueId, pathTrimCount, breadcrumbAction, searchBarProps, filterButtonProps, addButtonProps, actionProps, }: PageHeaderProps) => import("react/jsx-runtime").JSX.Element;
|
|
23
24
|
export { PageHeader, type PageHeaderProps };
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { ReactElement } from 'react';
|
|
1
2
|
export type BreadcrumbsProps = {
|
|
2
3
|
pathTrimCount: number;
|
|
3
4
|
containerClassName?: string;
|
|
5
|
+
action?: ReactElement;
|
|
4
6
|
};
|
|
5
|
-
export declare const Breadcrumbs: ({ pathTrimCount, containerClassName, }: BreadcrumbsProps) => import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
export declare const Breadcrumbs: ({ pathTrimCount, containerClassName, action, }: BreadcrumbsProps) => import("react/jsx-runtime").JSX.Element;
|
package/dist/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { LayoutType, AnimationTiming } from 'recharts/types/util/types';
|
|
|
6
6
|
import { CurveType } from 'recharts/types/shape/Curve';
|
|
7
7
|
import * as class_variance_authority_dist_types from 'class-variance-authority/dist/types';
|
|
8
8
|
import { VariantProps } from 'class-variance-authority';
|
|
9
|
-
import { ColumnDef,
|
|
9
|
+
import { ColumnDef, Row, SortingState } from '@tanstack/react-table';
|
|
10
10
|
export { ColumnDef } from '@tanstack/react-table';
|
|
11
11
|
import { Axios, AxiosInstance } from 'axios';
|
|
12
12
|
import * as SeparatorPrimitive from '@radix-ui/react-separator';
|
|
@@ -488,6 +488,9 @@ type DataTableProps<TData = any> = {
|
|
|
488
488
|
rowSelectionModel?: Record<string, boolean>;
|
|
489
489
|
onRowSelectionModelChange?: (newRowSelectionModel: Record<string, boolean>) => void;
|
|
490
490
|
selectionActions?: React__default.ReactNode[];
|
|
491
|
+
onRowClick?: (params: {
|
|
492
|
+
row: Row<TData>;
|
|
493
|
+
}) => void;
|
|
491
494
|
enableSorting?: boolean;
|
|
492
495
|
sortingState?: SortingState;
|
|
493
496
|
onSortingChange?: (newSortingState: SortingState) => void;
|
|
@@ -613,7 +616,7 @@ declare const Tooltip: ({ children, title, placement, open, defaultOpen, onOpenC
|
|
|
613
616
|
|
|
614
617
|
declare const buttonVariants: (props?: ({
|
|
615
618
|
variant?: "input" | "link" | "default" | "secondary" | "destructive" | "outline" | "ghost" | null | undefined;
|
|
616
|
-
size?: "default" | "
|
|
619
|
+
size?: "default" | "icon" | "sm" | "lg" | "icon-sm" | "icon-lg" | null | undefined;
|
|
617
620
|
} & class_variance_authority_dist_types.ClassProp) | undefined) => string;
|
|
618
621
|
|
|
619
622
|
type ButtonProps = React.ComponentProps<'button'> & VariantProps<typeof buttonVariants> & {
|
|
@@ -849,8 +852,9 @@ type PasswordFieldProps = {
|
|
|
849
852
|
error?: boolean;
|
|
850
853
|
helperText?: string;
|
|
851
854
|
className?: string;
|
|
855
|
+
fullWidth?: boolean;
|
|
852
856
|
} & Omit<React.InputHTMLAttributes<HTMLInputElement>, 'type'>;
|
|
853
|
-
declare const PasswordField: ({ name, label, value, onChange, required, containerProps, description, placeholder, disabled, error, helperText, className, ...rest }: PasswordFieldProps) => react_jsx_runtime.JSX.Element;
|
|
857
|
+
declare const PasswordField: ({ name, label, value, onChange, required, containerProps, description, placeholder, disabled, error, helperText, className, fullWidth, ...rest }: PasswordFieldProps) => react_jsx_runtime.JSX.Element;
|
|
854
858
|
|
|
855
859
|
type RadioGroupProps = {
|
|
856
860
|
containerProps?: React.HTMLAttributes<HTMLDivElement>;
|
|
@@ -1139,7 +1143,8 @@ declare const PageContent: ({ children, className }: PageContentProps) => react_
|
|
|
1139
1143
|
interface PageHeaderProps {
|
|
1140
1144
|
uniqueId?: string;
|
|
1141
1145
|
pathTrimCount: number;
|
|
1142
|
-
|
|
1146
|
+
breadcrumbAction?: ReactElement;
|
|
1147
|
+
searchBarProps?: SearchBarProps;
|
|
1143
1148
|
filterButtonProps?: {
|
|
1144
1149
|
label?: string;
|
|
1145
1150
|
startIcon?: ReactNode;
|
|
@@ -1155,13 +1160,14 @@ interface PageHeaderProps {
|
|
|
1155
1160
|
}) => ReactNode[]);
|
|
1156
1161
|
};
|
|
1157
1162
|
}
|
|
1158
|
-
declare const PageHeader: ({ uniqueId, pathTrimCount,
|
|
1163
|
+
declare const PageHeader: ({ uniqueId, pathTrimCount, breadcrumbAction, searchBarProps, filterButtonProps, addButtonProps, actionProps, }: PageHeaderProps) => react_jsx_runtime.JSX.Element;
|
|
1159
1164
|
|
|
1160
1165
|
type BreadcrumbsProps = {
|
|
1161
1166
|
pathTrimCount: number;
|
|
1162
1167
|
containerClassName?: string;
|
|
1168
|
+
action?: ReactElement;
|
|
1163
1169
|
};
|
|
1164
|
-
declare const Breadcrumbs: ({ pathTrimCount, containerClassName, }: BreadcrumbsProps) => react_jsx_runtime.JSX.Element;
|
|
1170
|
+
declare const Breadcrumbs: ({ pathTrimCount, containerClassName, action, }: BreadcrumbsProps) => react_jsx_runtime.JSX.Element;
|
|
1165
1171
|
|
|
1166
1172
|
interface CalendarEvent {
|
|
1167
1173
|
id: string | number;
|
package/dist/styles.css
CHANGED
|
@@ -495,9 +495,6 @@
|
|
|
495
495
|
.my-6 {
|
|
496
496
|
margin-block: calc(var(--spacing) * 6);
|
|
497
497
|
}
|
|
498
|
-
.mt-0 {
|
|
499
|
-
margin-top: calc(var(--spacing) * 0);
|
|
500
|
-
}
|
|
501
498
|
.mt-0\.5 {
|
|
502
499
|
margin-top: calc(var(--spacing) * 0.5);
|
|
503
500
|
}
|
|
@@ -632,6 +629,10 @@
|
|
|
632
629
|
width: calc(var(--spacing) * 4);
|
|
633
630
|
height: calc(var(--spacing) * 4);
|
|
634
631
|
}
|
|
632
|
+
.size-5 {
|
|
633
|
+
width: calc(var(--spacing) * 5);
|
|
634
|
+
height: calc(var(--spacing) * 5);
|
|
635
|
+
}
|
|
635
636
|
.size-8 {
|
|
636
637
|
width: calc(var(--spacing) * 8);
|
|
637
638
|
height: calc(var(--spacing) * 8);
|
|
@@ -3106,11 +3107,6 @@
|
|
|
3106
3107
|
margin-inline: calc(var(--spacing) * 0);
|
|
3107
3108
|
}
|
|
3108
3109
|
}
|
|
3109
|
-
.md\:mt-2 {
|
|
3110
|
-
@media (width >= 48rem) {
|
|
3111
|
-
margin-top: calc(var(--spacing) * 2);
|
|
3112
|
-
}
|
|
3113
|
-
}
|
|
3114
3110
|
.md\:block {
|
|
3115
3111
|
@media (width >= 48rem) {
|
|
3116
3112
|
display: block;
|
|
@@ -3658,11 +3654,6 @@
|
|
|
3658
3654
|
border-bottom-right-radius: calc(var(--radius) - 2px);
|
|
3659
3655
|
}
|
|
3660
3656
|
}
|
|
3661
|
-
.\[\&\:not\(\:first-child\)\]\:mt-6 {
|
|
3662
|
-
&:not(:first-child) {
|
|
3663
|
-
margin-top: calc(var(--spacing) * 6);
|
|
3664
|
-
}
|
|
3665
|
-
}
|
|
3666
3657
|
.\[\&\:nth-child\(2\)\[data-selected\=true\]_button\]\:rounded-l-md {
|
|
3667
3658
|
&:nth-child(2)[data-selected=true] button {
|
|
3668
3659
|
border-top-left-radius: calc(var(--radius) - 2px);
|
package/package.json
CHANGED
|
@@ -51,6 +51,9 @@ type DataTableProps<TData = any> = {
|
|
|
51
51
|
) => void;
|
|
52
52
|
selectionActions?: React.ReactNode[];
|
|
53
53
|
|
|
54
|
+
// Row click handler
|
|
55
|
+
onRowClick?: (params: { row: Row<TData> }) => void;
|
|
56
|
+
|
|
54
57
|
// Sorting props
|
|
55
58
|
enableSorting?: boolean;
|
|
56
59
|
sortingState?: SortingState;
|
|
@@ -106,6 +109,7 @@ const DataTable = <TData extends Record<string, any> = any>(
|
|
|
106
109
|
cellClassName,
|
|
107
110
|
isLoading = false,
|
|
108
111
|
columnVisibilityModel,
|
|
112
|
+
onRowClick,
|
|
109
113
|
} = props;
|
|
110
114
|
|
|
111
115
|
// Get layout mode and column visibility from Redux if tableActionProps is provided
|
|
@@ -290,6 +294,7 @@ const DataTable = <TData extends Record<string, any> = any>(
|
|
|
290
294
|
totalCount={totalCount}
|
|
291
295
|
onPageChange={onPageChange}
|
|
292
296
|
onLimitChange={onLimitChange}
|
|
297
|
+
onRowClick={onRowClick}
|
|
293
298
|
/>
|
|
294
299
|
)}
|
|
295
300
|
</div>
|
|
@@ -29,6 +29,7 @@ interface TableViewProps<TData = any> {
|
|
|
29
29
|
totalCount?: number;
|
|
30
30
|
onPageChange?: (page: number) => void;
|
|
31
31
|
onLimitChange?: (limit: number) => void;
|
|
32
|
+
onRowClick?: (params: { row: Row<TData> }) => void;
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
const TableView = React.forwardRef<HTMLDivElement, TableViewProps>(
|
|
@@ -48,6 +49,7 @@ const TableView = React.forwardRef<HTMLDivElement, TableViewProps>(
|
|
|
48
49
|
totalCount,
|
|
49
50
|
onPageChange,
|
|
50
51
|
onLimitChange,
|
|
52
|
+
onRowClick,
|
|
51
53
|
},
|
|
52
54
|
ref,
|
|
53
55
|
) => {
|
|
@@ -131,14 +133,16 @@ const TableView = React.forwardRef<HTMLDivElement, TableViewProps>(
|
|
|
131
133
|
className={rowHeightClass}
|
|
132
134
|
>
|
|
133
135
|
{/* Use visible header columns count to render correct number of skeleton cells */}
|
|
134
|
-
{table
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
136
|
+
{table
|
|
137
|
+
.getHeaderGroups()[0]
|
|
138
|
+
?.headers.map((_: any, cellIndex: number) => (
|
|
139
|
+
<TableCell
|
|
140
|
+
key={`skeleton-cell-${rowIndex}-${cellIndex}`}
|
|
141
|
+
className={cn(cellIndex === 0 && 'pl-4', cellClassName)}
|
|
142
|
+
>
|
|
143
|
+
<Skeleton className="h-4 w-full" />
|
|
144
|
+
</TableCell>
|
|
145
|
+
))}
|
|
142
146
|
</TableRow>
|
|
143
147
|
))
|
|
144
148
|
) : table.getRowModel().rows?.length ? (
|
|
@@ -153,6 +157,7 @@ const TableView = React.forwardRef<HTMLDivElement, TableViewProps>(
|
|
|
153
157
|
key={row.id}
|
|
154
158
|
data-state={row.getIsSelected() && 'selected'}
|
|
155
159
|
className={cn(rowHeightClass, customRowClassName)}
|
|
160
|
+
onClick={() => onRowClick?.({ row })}
|
|
156
161
|
>
|
|
157
162
|
{row.getVisibleCells().map((cell: any, index: number) => (
|
|
158
163
|
<TableCell
|
|
@@ -103,7 +103,7 @@ export const ViewButton = ({
|
|
|
103
103
|
/>
|
|
104
104
|
|
|
105
105
|
<ConfirmDialog
|
|
106
|
-
message="Do you really want to delete
|
|
106
|
+
message="Do you really want to delete this view? This action cannot be undone."
|
|
107
107
|
isOpen={dialogOpen}
|
|
108
108
|
onCancel={() => {
|
|
109
109
|
setDialogOpen(false);
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
TriangleAlertIcon,
|
|
6
6
|
XIcon,
|
|
7
7
|
} from 'lucide-react';
|
|
8
|
-
import { useEffect
|
|
8
|
+
import { useEffect } from 'react';
|
|
9
9
|
import { Typography } from '../../DataDisplay/Typography/Typography';
|
|
10
10
|
import { Button } from '../../Input/Button/Button';
|
|
11
11
|
|
|
@@ -33,12 +33,9 @@ export const Snackbar = ({
|
|
|
33
33
|
anchorOrigin,
|
|
34
34
|
autoHideDuration,
|
|
35
35
|
}: SnackbarProps) => {
|
|
36
|
-
const [visible, setVisible] = useState(open);
|
|
37
|
-
|
|
38
36
|
useEffect(() => {
|
|
39
37
|
if (open && autoHideDuration) {
|
|
40
38
|
const timer = setTimeout(() => {
|
|
41
|
-
setVisible(false);
|
|
42
39
|
if (onClose) {
|
|
43
40
|
onClose('timeout');
|
|
44
41
|
}
|
|
@@ -61,13 +58,12 @@ export const Snackbar = ({
|
|
|
61
58
|
};
|
|
62
59
|
|
|
63
60
|
const handleClose = () => {
|
|
64
|
-
setVisible(false);
|
|
65
61
|
if (onClose) {
|
|
66
62
|
onClose('clickaway');
|
|
67
63
|
}
|
|
68
64
|
};
|
|
69
65
|
|
|
70
|
-
if (!
|
|
66
|
+
if (!open) return null;
|
|
71
67
|
|
|
72
68
|
const vertical = anchorOrigin?.vertical || 'top';
|
|
73
69
|
const horizontal = anchorOrigin?.horizontal || 'center';
|
|
@@ -83,12 +79,13 @@ export const Snackbar = ({
|
|
|
83
79
|
|
|
84
80
|
return (
|
|
85
81
|
<div
|
|
86
|
-
className={`fixed ${positionClasses} z-[9999] pointer-events-auto`}
|
|
82
|
+
className={`fixed ${positionClasses} z-[9999] pointer-events-auto w-fit max-w-lg`}
|
|
87
83
|
role="alert"
|
|
88
84
|
aria-live="polite"
|
|
89
85
|
>
|
|
90
86
|
<div
|
|
91
|
-
className={`group pointer-events-auto relative flex
|
|
87
|
+
className={`group pointer-events-auto relative flex bg-background items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 shadow-lg transition-all`}
|
|
88
|
+
style={{ minWidth: '350px' }}
|
|
92
89
|
data-sonner-toast=""
|
|
93
90
|
>
|
|
94
91
|
<div className="flex items-start gap-3 flex-1">
|
|
@@ -18,6 +18,7 @@ export type PasswordFieldProps = {
|
|
|
18
18
|
error?: boolean;
|
|
19
19
|
helperText?: string;
|
|
20
20
|
className?: string;
|
|
21
|
+
fullWidth?: boolean;
|
|
21
22
|
} & Omit<React.InputHTMLAttributes<HTMLInputElement>, 'type'>;
|
|
22
23
|
|
|
23
24
|
export const PasswordField = ({
|
|
@@ -33,6 +34,7 @@ export const PasswordField = ({
|
|
|
33
34
|
error = false,
|
|
34
35
|
helperText,
|
|
35
36
|
className,
|
|
37
|
+
fullWidth,
|
|
36
38
|
...rest
|
|
37
39
|
}: PasswordFieldProps) => {
|
|
38
40
|
const [showPassword, setShowPassword] = useState(false);
|
|
@@ -42,8 +44,8 @@ export const PasswordField = ({
|
|
|
42
44
|
};
|
|
43
45
|
|
|
44
46
|
const content = (
|
|
45
|
-
<div className=
|
|
46
|
-
<div className=
|
|
47
|
+
<div className={cn('flex flex-col gap-2', fullWidth && 'w-full')}>
|
|
48
|
+
<div className={cn('relative', fullWidth && 'w-full')}>
|
|
47
49
|
<Input
|
|
48
50
|
id={name}
|
|
49
51
|
name={name}
|
|
@@ -53,6 +55,7 @@ export const PasswordField = ({
|
|
|
53
55
|
placeholder={placeholder}
|
|
54
56
|
disabled={disabled}
|
|
55
57
|
className={cn(
|
|
58
|
+
fullWidth && 'w-full',
|
|
56
59
|
'pr-10 bg-input-background border-none ',
|
|
57
60
|
error && 'border-destructive focus-visible:ring-destructive',
|
|
58
61
|
className,
|
|
@@ -3,7 +3,7 @@ import { useState } from 'react';
|
|
|
3
3
|
import { useMatch, useResolvedPath } from 'react-router-dom';
|
|
4
4
|
|
|
5
5
|
import { cn } from '@/lib/utils';
|
|
6
|
-
import {
|
|
6
|
+
import { ChevronDown, ChevronUp, Undo2 } from 'lucide-react';
|
|
7
7
|
import { Typography } from '../../../../DataDisplay/Typography/Typography';
|
|
8
8
|
import { Tooltip } from '../../../../Feedback/Tooltip/Tooltip';
|
|
9
9
|
import { MenuItemProps } from './interfaces';
|
|
@@ -113,7 +113,7 @@ export const MenuItem: React.FC<MenuItemProps> = ({
|
|
|
113
113
|
if (subMenu && subMenu.length > 0) {
|
|
114
114
|
const content = (
|
|
115
115
|
<>
|
|
116
|
-
<MenuItemContainer>
|
|
116
|
+
<MenuItemContainer style={{ marginBottom: 1 }}>
|
|
117
117
|
<SubMenuContainer
|
|
118
118
|
match={!!match}
|
|
119
119
|
onClick={handleSubMenuToggle}
|
|
@@ -135,7 +135,7 @@ export const MenuItem: React.FC<MenuItemProps> = ({
|
|
|
135
135
|
<Typography variant={'small'}>{name}</Typography>
|
|
136
136
|
</div>
|
|
137
137
|
<div className="flex flex-col">
|
|
138
|
-
{expanded ? <
|
|
138
|
+
{expanded ? <ChevronUp /> : <ChevronDown />}
|
|
139
139
|
</div>
|
|
140
140
|
</div>
|
|
141
141
|
)}
|
|
@@ -17,7 +17,8 @@ import { PageHeaderSearchBar } from './components/SearchBar';
|
|
|
17
17
|
interface PageHeaderProps {
|
|
18
18
|
uniqueId?: string;
|
|
19
19
|
pathTrimCount: number;
|
|
20
|
-
|
|
20
|
+
breadcrumbAction?: ReactElement;
|
|
21
|
+
searchBarProps?: SearchBarProps;
|
|
21
22
|
filterButtonProps?: {
|
|
22
23
|
label?: string;
|
|
23
24
|
startIcon?: ReactNode;
|
|
@@ -35,7 +36,8 @@ interface PageHeaderProps {
|
|
|
35
36
|
const PageHeader = ({
|
|
36
37
|
uniqueId,
|
|
37
38
|
pathTrimCount,
|
|
38
|
-
|
|
39
|
+
breadcrumbAction,
|
|
40
|
+
searchBarProps,
|
|
39
41
|
filterButtonProps,
|
|
40
42
|
addButtonProps,
|
|
41
43
|
actionProps,
|
|
@@ -44,7 +46,7 @@ const PageHeader = ({
|
|
|
44
46
|
const dispatch = useDispatch();
|
|
45
47
|
|
|
46
48
|
const showActionBar =
|
|
47
|
-
|
|
49
|
+
searchBarProps || filterButtonProps || addButtonProps || actionProps;
|
|
48
50
|
|
|
49
51
|
const wrapProps = (element: ReactElement): ReactElement => {
|
|
50
52
|
const { name } = element.props;
|
|
@@ -66,19 +68,19 @@ const PageHeader = ({
|
|
|
66
68
|
|
|
67
69
|
return (
|
|
68
70
|
<div>
|
|
69
|
-
<Breadcrumbs pathTrimCount={pathTrimCount} />
|
|
71
|
+
<Breadcrumbs pathTrimCount={pathTrimCount} action={breadcrumbAction} />
|
|
70
72
|
<div
|
|
71
73
|
className={cn(
|
|
72
74
|
'flex flex-col md:flex-row gap-1 md:gap-2 items-center w-full px-1 pb-2 md:p-0 border-b',
|
|
73
75
|
showActionBar ? '' : 'hidden',
|
|
74
76
|
)}
|
|
75
77
|
>
|
|
76
|
-
{
|
|
78
|
+
{searchBarProps && (
|
|
77
79
|
<PageHeaderSearchBar
|
|
78
80
|
className="w-full"
|
|
79
81
|
containerClassName="w-full md:w-md"
|
|
80
82
|
uniqueId={uniqueId}
|
|
81
|
-
{...
|
|
83
|
+
{...searchBarProps}
|
|
82
84
|
/>
|
|
83
85
|
)}
|
|
84
86
|
<div className="flex gap-2 items-center w-full px-2 md:p-0">
|
|
@@ -18,17 +18,20 @@ import {
|
|
|
18
18
|
DropdownMenuItem,
|
|
19
19
|
DropdownMenuTrigger,
|
|
20
20
|
} from '@/shadcn-components/Navigation/DropdownMenu/DropdownMenu';
|
|
21
|
+
import { ReactElement } from 'react';
|
|
21
22
|
import { getBreadcrumbsCharacter } from '../../../utils/export';
|
|
22
23
|
import { MenuToggleButton } from '../../Layout/AppLayout/components/MenuToggleButton';
|
|
23
24
|
|
|
24
25
|
export type BreadcrumbsProps = {
|
|
25
26
|
pathTrimCount: number;
|
|
26
27
|
containerClassName?: string;
|
|
28
|
+
action?: ReactElement;
|
|
27
29
|
};
|
|
28
30
|
|
|
29
31
|
export const Breadcrumbs = ({
|
|
30
32
|
pathTrimCount,
|
|
31
33
|
containerClassName,
|
|
34
|
+
action,
|
|
32
35
|
}: BreadcrumbsProps) => {
|
|
33
36
|
const specialCharacter = getBreadcrumbsCharacter();
|
|
34
37
|
const currentPathArray = window.location.pathname.split('/');
|
|
@@ -87,7 +90,7 @@ export const Breadcrumbs = ({
|
|
|
87
90
|
<BreadcrumbItem>
|
|
88
91
|
<DropdownMenu>
|
|
89
92
|
<DropdownMenuTrigger className="flex items-center gap-1">
|
|
90
|
-
<BreadcrumbEllipsis />
|
|
93
|
+
<BreadcrumbEllipsis className="size-5" />
|
|
91
94
|
</DropdownMenuTrigger>
|
|
92
95
|
<DropdownMenuContent align="start">
|
|
93
96
|
{middleItems.map((item, index) => (
|
|
@@ -112,14 +115,22 @@ export const Breadcrumbs = ({
|
|
|
112
115
|
return (
|
|
113
116
|
<div
|
|
114
117
|
className={cn(
|
|
115
|
-
'flex w-full flex-row items-center px-2 pt-2 gap-1 md:px-3',
|
|
118
|
+
'flex w-full flex-row items-center justify-between px-2 pt-2 gap-1 md:px-3',
|
|
116
119
|
containerClassName,
|
|
117
120
|
)}
|
|
118
121
|
>
|
|
119
|
-
<
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
122
|
+
<div
|
|
123
|
+
className={cn(
|
|
124
|
+
'flex w-full flex-row items-center gap-1',
|
|
125
|
+
containerClassName,
|
|
126
|
+
)}
|
|
127
|
+
>
|
|
128
|
+
<MenuToggleButton />
|
|
129
|
+
<Breadcrumb>
|
|
130
|
+
<BreadcrumbList>{renderBreadcrumbs()}</BreadcrumbList>
|
|
131
|
+
</Breadcrumb>
|
|
132
|
+
</div>
|
|
133
|
+
{action}
|
|
123
134
|
</div>
|
|
124
135
|
);
|
|
125
136
|
};
|
|
@@ -55,7 +55,7 @@ export const TabsContainer = ({
|
|
|
55
55
|
<Tabs
|
|
56
56
|
value={currentTab}
|
|
57
57
|
onValueChange={handleTabsChange}
|
|
58
|
-
className={
|
|
58
|
+
className={className}
|
|
59
59
|
>
|
|
60
60
|
<TabsList className={cn(tabsListClassName)} style={{ margin: '4px 8px' }}>
|
|
61
61
|
{tabs.map(({ key, label, highlight, disabled, icon }) => (
|
|
@@ -6,9 +6,9 @@ import {
|
|
|
6
6
|
PageHeaderSingleState,
|
|
7
7
|
resetStateForUniqueId,
|
|
8
8
|
setDefaultFiltersForUniqueId,
|
|
9
|
+
setLayoutModeForUniqueId,
|
|
9
10
|
setLimitForUniqueId,
|
|
10
11
|
setOffsetForUniqueId,
|
|
11
|
-
setLayoutModeForUniqueId,
|
|
12
12
|
} from '../redux/slices/pageHeaderSlice';
|
|
13
13
|
import { RootState } from '../redux/store';
|
|
14
14
|
|