@aurora-ds/components 0.18.2 → 0.19.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 +1 -0
- package/dist/cjs/components/data-display/avatar/Avatar.props.d.ts +1 -1
- package/dist/cjs/components/forms/date-picker/calendar/Calendar.props.d.ts +2 -2
- package/dist/cjs/components/index.d.ts +2 -0
- package/dist/cjs/components/overlay/alert/Alert.d.ts +32 -0
- package/dist/cjs/components/overlay/alert/Alert.props.d.ts +56 -0
- package/dist/cjs/components/overlay/alert/Alert.styles.d.ts +4 -0
- package/dist/cjs/components/overlay/alert/index.d.ts +2 -0
- package/dist/cjs/constants/globalConstants.d.ts +1 -0
- package/dist/cjs/hooks/index.d.ts +2 -0
- package/dist/cjs/hooks/useAlert.d.ts +23 -0
- package/dist/cjs/hooks/useAlert.types.d.ts +56 -0
- package/dist/cjs/index.js +336 -2
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/interfaces/alert.types.d.ts +8 -0
- package/dist/cjs/interfaces/index.d.ts +1 -0
- package/dist/cjs/resources/Icons.d.ts +4 -1
- package/dist/cjs/resources/icons/AlertCircleIcon.d.ts +2 -0
- package/dist/cjs/resources/icons/AlertTriangleIcon.d.ts +2 -0
- package/dist/cjs/resources/icons/CheckCircleIcon.d.ts +2 -0
- package/dist/cjs/utils/ui/components/foundation/text/getTruncateTextStyles.utils.d.ts +5 -1
- package/dist/cjs/utils/ui/components/overlay/alert/getAlertIcon.utils.d.ts +8 -0
- package/dist/cjs/utils/ui/components/overlay/alert/getAlertPositionStyles.utils.d.ts +8 -0
- package/dist/cjs/utils/ui/components/overlay/alert/getAlertVariantColors.utils.d.ts +14 -0
- package/dist/esm/components/data-display/avatar/Avatar.props.d.ts +1 -1
- package/dist/esm/components/forms/date-picker/calendar/Calendar.props.d.ts +2 -2
- package/dist/esm/components/index.d.ts +2 -0
- package/dist/esm/components/overlay/alert/Alert.d.ts +32 -0
- package/dist/esm/components/overlay/alert/Alert.props.d.ts +56 -0
- package/dist/esm/components/overlay/alert/Alert.styles.d.ts +4 -0
- package/dist/esm/components/overlay/alert/index.d.ts +2 -0
- package/dist/esm/constants/globalConstants.d.ts +1 -0
- package/dist/esm/hooks/index.d.ts +2 -0
- package/dist/esm/hooks/useAlert.d.ts +23 -0
- package/dist/esm/hooks/useAlert.types.d.ts +56 -0
- package/dist/esm/index.js +335 -4
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/interfaces/alert.types.d.ts +8 -0
- package/dist/esm/interfaces/index.d.ts +1 -0
- package/dist/esm/resources/Icons.d.ts +4 -1
- package/dist/esm/resources/icons/AlertCircleIcon.d.ts +2 -0
- package/dist/esm/resources/icons/AlertTriangleIcon.d.ts +2 -0
- package/dist/esm/resources/icons/CheckCircleIcon.d.ts +2 -0
- package/dist/esm/utils/ui/components/foundation/text/getTruncateTextStyles.utils.d.ts +5 -1
- package/dist/esm/utils/ui/components/overlay/alert/getAlertIcon.utils.d.ts +8 -0
- package/dist/esm/utils/ui/components/overlay/alert/getAlertPositionStyles.utils.d.ts +8 -0
- package/dist/esm/utils/ui/components/overlay/alert/getAlertVariantColors.utils.d.ts +14 -0
- package/dist/index.d.ts +153 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -47,6 +47,7 @@ function App() {
|
|
|
47
47
|
| Component | Description |
|
|
48
48
|
|-----------|-------------|
|
|
49
49
|
| **Accordion** | Collapsible container to show/hide content |
|
|
50
|
+
| **Alert** | Notification component with variants (default, info, warning, error, success) and auto-dismiss |
|
|
50
51
|
| **Avatar** | User avatar display component with image or initials |
|
|
51
52
|
| **AvatarGroup** | Group of avatars with overlapping display |
|
|
52
53
|
| **Breadcrumb** | Navigation component for hierarchical page structures |
|
|
@@ -6,7 +6,7 @@ export type AvatarProps = {
|
|
|
6
6
|
/** Fallback text to display when no image */
|
|
7
7
|
label?: string;
|
|
8
8
|
/** Click handler */
|
|
9
|
-
onClick?: (e: MouseEvent<
|
|
9
|
+
onClick?: (e: MouseEvent<HTMLDivElement>) => void;
|
|
10
10
|
/** Size of the avatar */
|
|
11
11
|
size?: AvatarSize;
|
|
12
12
|
/** Text color for the label */
|
|
@@ -5,9 +5,9 @@ export type CalendarProps = {
|
|
|
5
5
|
/** Callback when a date is selected */
|
|
6
6
|
onDateSelect: (date: Date) => void;
|
|
7
7
|
/** Minimum selectable date */
|
|
8
|
-
minDate?: Date;
|
|
8
|
+
minDate?: Date | null;
|
|
9
9
|
/** Maximum selectable date */
|
|
10
|
-
maxDate?: Date;
|
|
10
|
+
maxDate?: Date | null;
|
|
11
11
|
/** Locale for month/year display */
|
|
12
12
|
locale?: string;
|
|
13
13
|
};
|
|
@@ -17,12 +17,14 @@ export * from '@components/layout/separator';
|
|
|
17
17
|
export * from '@components/layout/page-construction/page-section';
|
|
18
18
|
export * from '@components/layout/page-construction/page';
|
|
19
19
|
export * from '@components/overlay/accordion';
|
|
20
|
+
export * from '@components/overlay/alert';
|
|
20
21
|
export * from '@components/overlay/menu';
|
|
21
22
|
export * from '@components/overlay/modal';
|
|
22
23
|
export * from '@components/navigation/drawer-item';
|
|
23
24
|
export * from '@components/navigation/breadcrumb';
|
|
24
25
|
export * from '@components/navigation/tabs';
|
|
25
26
|
export * from '@components/navigation/pagination';
|
|
27
|
+
export type { AlertVariant, AlertPosition } from '@interfaces/alert.types';
|
|
26
28
|
export type { ButtonVariants, ButtonVariantStyle } from '@interfaces/button.types';
|
|
27
29
|
export type { TextVariants, TextVariantStyle } from '@interfaces/text.types';
|
|
28
30
|
export type { ChipVariant, ChipColor, ChipSize } from '@interfaces/chip.types';
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { FC } from 'react';
|
|
2
|
+
import { AlertProps } from '@components/overlay/alert/Alert.props';
|
|
3
|
+
/**
|
|
4
|
+
* Alert component - Display notifications with different variants
|
|
5
|
+
*
|
|
6
|
+
* **Variants:**
|
|
7
|
+
* - `default`: Standard alert with neutral styling
|
|
8
|
+
* - `info`: Informational alert with blue styling
|
|
9
|
+
* - `warning`: Warning alert with yellow/orange styling
|
|
10
|
+
* - `error`: Error alert with red styling
|
|
11
|
+
* - `success`: Success alert with green styling
|
|
12
|
+
*
|
|
13
|
+
* **Features:**
|
|
14
|
+
* - Auto-dismisses after 3 seconds
|
|
15
|
+
* - Positioned at screen corners
|
|
16
|
+
* - Supports stacking with offsetY
|
|
17
|
+
* - Icon based on variant
|
|
18
|
+
* - Smooth animations
|
|
19
|
+
* - Dynamic height calculation for proper stacking
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```tsx
|
|
23
|
+
* <Alert
|
|
24
|
+
* text="Operation completed successfully"
|
|
25
|
+
* variant="success"
|
|
26
|
+
* position="top-right"
|
|
27
|
+
* isVisible={true}
|
|
28
|
+
* />
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
declare const Alert: FC<AlertProps>;
|
|
32
|
+
export { Alert };
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { AlertPosition, AlertVariant } from '@interfaces/alert.types';
|
|
2
|
+
/**
|
|
3
|
+
* Alert component props
|
|
4
|
+
*/
|
|
5
|
+
export interface AlertProps {
|
|
6
|
+
/**
|
|
7
|
+
* Text content of the alert
|
|
8
|
+
*/
|
|
9
|
+
text: string;
|
|
10
|
+
/**
|
|
11
|
+
* Variant of the alert determining its color and icon
|
|
12
|
+
* @default 'default'
|
|
13
|
+
*/
|
|
14
|
+
variant?: AlertVariant;
|
|
15
|
+
/**
|
|
16
|
+
* Position of the alert on screen
|
|
17
|
+
* @default 'top-right'
|
|
18
|
+
*/
|
|
19
|
+
position?: AlertPosition;
|
|
20
|
+
/**
|
|
21
|
+
* Whether the alert is visible
|
|
22
|
+
* @default false
|
|
23
|
+
*/
|
|
24
|
+
isVisible?: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Vertical offset for stacking alerts (in pixels)
|
|
27
|
+
* @default 0
|
|
28
|
+
*/
|
|
29
|
+
offsetY?: number;
|
|
30
|
+
/**
|
|
31
|
+
* Maximum width of the alert in pixels
|
|
32
|
+
* @default 300
|
|
33
|
+
*/
|
|
34
|
+
maxWidth?: number;
|
|
35
|
+
/**
|
|
36
|
+
* Unique identifier for the alert
|
|
37
|
+
* @internal
|
|
38
|
+
*/
|
|
39
|
+
alertId?: string;
|
|
40
|
+
/**
|
|
41
|
+
* Callback when alert height changes
|
|
42
|
+
* @internal
|
|
43
|
+
*/
|
|
44
|
+
onHeightChange?: (alertId: string, height: number) => void;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Internal style parameters for Alert component
|
|
48
|
+
* @internal
|
|
49
|
+
*/
|
|
50
|
+
export interface AlertStyleParams {
|
|
51
|
+
variant: AlertVariant;
|
|
52
|
+
position: AlertPosition;
|
|
53
|
+
isVisible: boolean;
|
|
54
|
+
offsetY: number;
|
|
55
|
+
maxWidth: number;
|
|
56
|
+
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
export { useAlert, AlertProvider } from '@hooks/useAlert.tsx';
|
|
2
|
+
export type { ShowAlertOptions, AlertContextValue, AlertProviderProps } from '@hooks/useAlert.types';
|
|
1
3
|
export { useAnchorPosition } from '@hooks/useAnchorPosition';
|
|
2
4
|
export type { AnchorOrigin, AnchorPosition } from '@hooks/useAnchorPosition.types';
|
|
3
5
|
export { useClickOutside } from '@hooks/useClickOutside';
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { FC } from 'react';
|
|
2
|
+
import { AlertContextValue, AlertProviderProps } from '@hooks/useAlert.types';
|
|
3
|
+
/**
|
|
4
|
+
* Alert Provider Component
|
|
5
|
+
* Manages alert queue and renders alerts in a portal
|
|
6
|
+
*/
|
|
7
|
+
declare const AlertProvider: FC<AlertProviderProps>;
|
|
8
|
+
/**
|
|
9
|
+
* Hook to access alert functionality
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```tsx
|
|
13
|
+
* const { showAlert } = useAlert()
|
|
14
|
+
*
|
|
15
|
+
* showAlert({
|
|
16
|
+
* text: 'Operation completed',
|
|
17
|
+
* variant: 'success',
|
|
18
|
+
* position: 'top-right'
|
|
19
|
+
* })
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
declare const useAlert: () => AlertContextValue;
|
|
23
|
+
export { AlertProvider, useAlert };
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { AlertPosition, AlertVariant } from '@interfaces/alert.types';
|
|
2
|
+
/**
|
|
3
|
+
* Alert item in the queue
|
|
4
|
+
*/
|
|
5
|
+
export interface AlertItem {
|
|
6
|
+
id: string;
|
|
7
|
+
text: string;
|
|
8
|
+
variant: AlertVariant;
|
|
9
|
+
position: AlertPosition;
|
|
10
|
+
timestamp: number;
|
|
11
|
+
maxWidth: number;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Options for showing an alert
|
|
15
|
+
*/
|
|
16
|
+
export interface ShowAlertOptions {
|
|
17
|
+
/**
|
|
18
|
+
* Text content of the alert
|
|
19
|
+
*/
|
|
20
|
+
text: string;
|
|
21
|
+
/**
|
|
22
|
+
* Variant of the alert
|
|
23
|
+
* @default 'default'
|
|
24
|
+
*/
|
|
25
|
+
variant?: AlertVariant;
|
|
26
|
+
/**
|
|
27
|
+
* Position of the alert on screen
|
|
28
|
+
* @default 'top-right'
|
|
29
|
+
*/
|
|
30
|
+
position?: AlertPosition;
|
|
31
|
+
/**
|
|
32
|
+
* Duration before auto-dismiss in milliseconds
|
|
33
|
+
* @default 3000
|
|
34
|
+
*/
|
|
35
|
+
duration?: number;
|
|
36
|
+
/**
|
|
37
|
+
* Maximum width of the alert in pixels
|
|
38
|
+
* @default 300
|
|
39
|
+
*/
|
|
40
|
+
maxWidth?: number;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Alert context value
|
|
44
|
+
*/
|
|
45
|
+
export interface AlertContextValue {
|
|
46
|
+
/**
|
|
47
|
+
* Show an alert
|
|
48
|
+
*/
|
|
49
|
+
showAlert: (options: ShowAlertOptions) => void;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Alert provider props
|
|
53
|
+
*/
|
|
54
|
+
export interface AlertProviderProps {
|
|
55
|
+
children: React.ReactNode;
|
|
56
|
+
}
|
package/dist/cjs/index.js
CHANGED
|
@@ -143,6 +143,10 @@ const getTruncateTextStyles = (maxLines) => (maxLines === 1
|
|
|
143
143
|
display: '-webkit-box',
|
|
144
144
|
WebkitLineClamp: maxLines,
|
|
145
145
|
WebkitBoxOrient: 'vertical',
|
|
146
|
+
// Improve wrapping behavior for multi-line clamp compatibility
|
|
147
|
+
whiteSpace: 'normal',
|
|
148
|
+
overflowWrap: 'break-word',
|
|
149
|
+
wordBreak: 'break-word',
|
|
146
150
|
lineClamp: maxLines,
|
|
147
151
|
});
|
|
148
152
|
|
|
@@ -218,8 +222,11 @@ const Text = ({ children, variant = 'span', color, fontSize, fontFamily, maxLine
|
|
|
218
222
|
const variantStyles = React.useMemo(() => getTextVariantStyles(theme$1), [theme$1]);
|
|
219
223
|
const tag = variantStyles[variant].tag;
|
|
220
224
|
const parsedChildren = React.useMemo(() => parseTextWithBold(children), [children]);
|
|
225
|
+
// Force inline truncate styles when needed (fix for multi-line clamp not applied in some envs)
|
|
226
|
+
const truncateStyles = maxLines ? getTruncateTextStyles(maxLines) : undefined;
|
|
221
227
|
return React.createElement(tag, {
|
|
222
228
|
className: TEXT_STYLES.root({ variant, color, fontSize, fontFamily, maxLines, underline, preserveWhitespace }),
|
|
229
|
+
style: truncateStyles,
|
|
223
230
|
'aria-label': ariaLabel,
|
|
224
231
|
'aria-labelledby': ariaLabelledBy,
|
|
225
232
|
'aria-describedby': ariaDescribedBy,
|
|
@@ -420,6 +427,7 @@ const Chip = ({ label, icon, variant = 'filled', color = 'default', size = 'md',
|
|
|
420
427
|
Chip.displayName = 'Chip';
|
|
421
428
|
|
|
422
429
|
const BUTTON_SIZE = 36;
|
|
430
|
+
const ALERT_MAX_WIDTH = 320;
|
|
423
431
|
const MENU_ITEM_SIZE = 32;
|
|
424
432
|
const DRAWER_ITEM_HEIGHT = 32;
|
|
425
433
|
const DEFAULT_TRANSITION_DURATION_MS = 150;
|
|
@@ -478,7 +486,11 @@ const Avatar = ({ image, label, onClick, size = 'medium', color, borderColor, ba
|
|
|
478
486
|
const AVATAR_SIZES = getAvatarSizes(theme$1);
|
|
479
487
|
const hasImage = !!image;
|
|
480
488
|
const clickable = !!onClick;
|
|
481
|
-
return (jsxRuntime.jsx("div", { className: AVATAR_STYLES.root({ hasImage, clickable, size, color, borderColor, backgroundColor }), onClick:
|
|
489
|
+
return (jsxRuntime.jsx("div", { className: AVATAR_STYLES.root({ hasImage, clickable, size, color, borderColor, backgroundColor }), onClick: (event) => {
|
|
490
|
+
if (onClick) {
|
|
491
|
+
onClick(event);
|
|
492
|
+
}
|
|
493
|
+
}, children: hasImage ? (jsxRuntime.jsx("img", { src: image, alt: label || 'Avatar', className: AVATAR_STYLES.image })) : (jsxRuntime.jsx(Text, { variant: 'label', fontSize: AVATAR_SIZES[size].fontSize, children: label || '?' })) }));
|
|
482
494
|
};
|
|
483
495
|
Avatar.displayName = 'Avatar';
|
|
484
496
|
|
|
@@ -937,10 +949,22 @@ const Stack = ({ children, direction = 'row', gap = 'sm', width, height, align =
|
|
|
937
949
|
};
|
|
938
950
|
Stack.displayName = 'Stack';
|
|
939
951
|
|
|
952
|
+
const AlertCircleIcon = () => {
|
|
953
|
+
return (jsxRuntime.jsxs("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', children: [jsxRuntime.jsx("circle", { cx: '12', cy: '12', r: '10' }), jsxRuntime.jsx("line", { x1: '12', y1: '8', x2: '12', y2: '12' }), jsxRuntime.jsx("line", { x1: '12', y1: '16', x2: '12.01', y2: '16' })] }));
|
|
954
|
+
};
|
|
955
|
+
|
|
956
|
+
const AlertTriangleIcon = () => {
|
|
957
|
+
return (jsxRuntime.jsxs("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', children: [jsxRuntime.jsx("path", { d: 'M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z' }), jsxRuntime.jsx("line", { x1: '12', y1: '9', x2: '12', y2: '13' }), jsxRuntime.jsx("line", { x1: '12', y1: '17', x2: '12.01', y2: '17' })] }));
|
|
958
|
+
};
|
|
959
|
+
|
|
940
960
|
const CalendarIcon = () => {
|
|
941
961
|
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', children: [jsxRuntime.jsx("path", { d: 'M8 2v4' }), jsxRuntime.jsx("path", { d: 'M16 2v4' }), jsxRuntime.jsx("rect", { width: '18', height: '18', x: '3', y: '4', rx: '2' }), jsxRuntime.jsx("path", { d: 'M3 10h18' })] }));
|
|
942
962
|
};
|
|
943
963
|
|
|
964
|
+
const CheckCircleIcon = () => {
|
|
965
|
+
return (jsxRuntime.jsxs("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', children: [jsxRuntime.jsx("circle", { cx: '12', cy: '12', r: '10' }), jsxRuntime.jsx("polyline", { points: '9 12 11 14 15 10' })] }));
|
|
966
|
+
};
|
|
967
|
+
|
|
944
968
|
const ChevronDownIcon = () => {
|
|
945
969
|
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
970
|
};
|
|
@@ -963,6 +987,10 @@ const EyeOffIcon = () => {
|
|
|
963
987
|
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' })] }));
|
|
964
988
|
};
|
|
965
989
|
|
|
990
|
+
const InfoIcon = () => {
|
|
991
|
+
return (jsxRuntime.jsxs("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', children: [jsxRuntime.jsx("circle", { cx: '12', cy: '12', r: '10' }), jsxRuntime.jsx("line", { x1: '12', y1: '16', x2: '12', y2: '12' }), jsxRuntime.jsx("line", { x1: '12', y1: '8', x2: '12.01', y2: '8' })] }));
|
|
992
|
+
};
|
|
993
|
+
|
|
966
994
|
const MoreHorizontalIcon = () => {
|
|
967
995
|
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' })] }));
|
|
968
996
|
};
|
|
@@ -1669,7 +1697,7 @@ const Calendar = ({ value, onDateSelect, minDate, maxDate, locale = 'fr-FR', })
|
|
|
1669
1697
|
const year = value?.getFullYear() ?? new Date().getFullYear();
|
|
1670
1698
|
return Math.floor(year / 12) * 12;
|
|
1671
1699
|
});
|
|
1672
|
-
const calendarDays = React.useMemo(() => getCalendarDays(currentMonth.getFullYear(), currentMonth.getMonth(), value, minDate, maxDate), [currentMonth, value, minDate, maxDate]);
|
|
1700
|
+
const calendarDays = React.useMemo(() => getCalendarDays(currentMonth.getFullYear(), currentMonth.getMonth(), value, minDate ?? undefined, maxDate ?? undefined), [currentMonth, value, minDate, maxDate]);
|
|
1673
1701
|
const headerLabel = React.useMemo(() => {
|
|
1674
1702
|
if (view === 'days') {
|
|
1675
1703
|
return currentMonth.toLocaleDateString(locale, { month: 'long', year: 'numeric' });
|
|
@@ -2131,6 +2159,160 @@ const Accordion = ({ title, children, expanded, defaultExpanded = false, onChang
|
|
|
2131
2159
|
};
|
|
2132
2160
|
Accordion.displayName = 'Accordion';
|
|
2133
2161
|
|
|
2162
|
+
const ALERT_OFFSET = 16;
|
|
2163
|
+
/**
|
|
2164
|
+
* Get position styles for alert
|
|
2165
|
+
* @param position - Alert position
|
|
2166
|
+
* @param offsetY - Vertical offset for stacking (in pixels)
|
|
2167
|
+
* @returns Object with CSS position styles (top/bottom + left/right)
|
|
2168
|
+
*/
|
|
2169
|
+
const getAlertPositionStyles = (position, offsetY) => {
|
|
2170
|
+
const verticalPosition = `${ALERT_OFFSET + offsetY}px`;
|
|
2171
|
+
switch (position) {
|
|
2172
|
+
case 'top-left':
|
|
2173
|
+
return { top: verticalPosition, left: `${ALERT_OFFSET}px` };
|
|
2174
|
+
case 'top-right':
|
|
2175
|
+
return { top: verticalPosition, right: `${ALERT_OFFSET}px` };
|
|
2176
|
+
case 'bottom-left':
|
|
2177
|
+
return { bottom: verticalPosition, left: `${ALERT_OFFSET}px` };
|
|
2178
|
+
case 'bottom-right':
|
|
2179
|
+
return { bottom: verticalPosition, right: `${ALERT_OFFSET}px` };
|
|
2180
|
+
default:
|
|
2181
|
+
return { top: verticalPosition, right: `${ALERT_OFFSET}px` };
|
|
2182
|
+
}
|
|
2183
|
+
};
|
|
2184
|
+
|
|
2185
|
+
/**
|
|
2186
|
+
* Get colors for alert variants
|
|
2187
|
+
* @param theme - Aurora theme
|
|
2188
|
+
* @param variant - Alert variant
|
|
2189
|
+
* @returns Colors for the variant
|
|
2190
|
+
*/
|
|
2191
|
+
const getAlertVariantColors = (theme, variant) => {
|
|
2192
|
+
const variantColors = {
|
|
2193
|
+
default: {
|
|
2194
|
+
background: theme.colors.surface,
|
|
2195
|
+
border: theme.colors.border,
|
|
2196
|
+
iconColor: 'text'
|
|
2197
|
+
},
|
|
2198
|
+
info: {
|
|
2199
|
+
background: theme.colors.infoSubtle,
|
|
2200
|
+
border: theme.colors.info,
|
|
2201
|
+
iconColor: 'info'
|
|
2202
|
+
},
|
|
2203
|
+
warning: {
|
|
2204
|
+
background: theme.colors.warningSubtle,
|
|
2205
|
+
border: theme.colors.warning,
|
|
2206
|
+
iconColor: 'warning'
|
|
2207
|
+
},
|
|
2208
|
+
error: {
|
|
2209
|
+
background: theme.colors.errorSubtle,
|
|
2210
|
+
border: theme.colors.error,
|
|
2211
|
+
iconColor: 'error'
|
|
2212
|
+
},
|
|
2213
|
+
success: {
|
|
2214
|
+
background: theme.colors.successSubtle,
|
|
2215
|
+
border: theme.colors.success,
|
|
2216
|
+
iconColor: 'success'
|
|
2217
|
+
}
|
|
2218
|
+
};
|
|
2219
|
+
return variantColors[variant];
|
|
2220
|
+
};
|
|
2221
|
+
|
|
2222
|
+
const ALERT_STYLES = theme.createStyles((theme) => ({
|
|
2223
|
+
root: ({ variant, position, isVisible, offsetY, maxWidth }) => {
|
|
2224
|
+
const colors = getAlertVariantColors(theme, variant);
|
|
2225
|
+
const positionStyles = getAlertPositionStyles(position, offsetY);
|
|
2226
|
+
return {
|
|
2227
|
+
position: 'fixed',
|
|
2228
|
+
...positionStyles,
|
|
2229
|
+
display: 'flex',
|
|
2230
|
+
alignItems: 'center',
|
|
2231
|
+
gap: theme.spacing.sm,
|
|
2232
|
+
padding: theme.spacing.sm,
|
|
2233
|
+
backgroundColor: colors.background,
|
|
2234
|
+
border: `1px solid ${colors.border}`,
|
|
2235
|
+
borderRadius: theme.radius.md,
|
|
2236
|
+
boxShadow: theme.shadows.lg,
|
|
2237
|
+
minWidth: ALERT_MAX_WIDTH,
|
|
2238
|
+
maxWidth,
|
|
2239
|
+
overflow: 'hidden',
|
|
2240
|
+
zIndex: theme.zIndex.toast,
|
|
2241
|
+
opacity: isVisible ? 1 : 0,
|
|
2242
|
+
transform: isVisible ? 'translateY(0)' :
|
|
2243
|
+
(position.startsWith('top') ? 'translateY(-8px)' : 'translateY(8px)'),
|
|
2244
|
+
transition: `all ${theme.transition.normal}, opacity ${theme.transition.fast}`,
|
|
2245
|
+
pointerEvents: isVisible ? 'auto' : 'none'
|
|
2246
|
+
};
|
|
2247
|
+
}
|
|
2248
|
+
}));
|
|
2249
|
+
|
|
2250
|
+
// Pre-create icon instances to avoid recreation on every call
|
|
2251
|
+
const ALERT_ICONS = {
|
|
2252
|
+
default: jsxRuntime.jsx(InfoIcon, {}),
|
|
2253
|
+
info: jsxRuntime.jsx(InfoIcon, {}),
|
|
2254
|
+
warning: jsxRuntime.jsx(AlertTriangleIcon, {}),
|
|
2255
|
+
error: jsxRuntime.jsx(AlertCircleIcon, {}),
|
|
2256
|
+
success: jsxRuntime.jsx(CheckCircleIcon, {})
|
|
2257
|
+
};
|
|
2258
|
+
/**
|
|
2259
|
+
* Get icon component for alert variant
|
|
2260
|
+
* @param variant - Alert variant
|
|
2261
|
+
* @returns JSX Element for the icon
|
|
2262
|
+
*/
|
|
2263
|
+
const getAlertIcon = (variant) => {
|
|
2264
|
+
return ALERT_ICONS[variant];
|
|
2265
|
+
};
|
|
2266
|
+
|
|
2267
|
+
/**
|
|
2268
|
+
* Alert component - Display notifications with different variants
|
|
2269
|
+
*
|
|
2270
|
+
* **Variants:**
|
|
2271
|
+
* - `default`: Standard alert with neutral styling
|
|
2272
|
+
* - `info`: Informational alert with blue styling
|
|
2273
|
+
* - `warning`: Warning alert with yellow/orange styling
|
|
2274
|
+
* - `error`: Error alert with red styling
|
|
2275
|
+
* - `success`: Success alert with green styling
|
|
2276
|
+
*
|
|
2277
|
+
* **Features:**
|
|
2278
|
+
* - Auto-dismisses after 3 seconds
|
|
2279
|
+
* - Positioned at screen corners
|
|
2280
|
+
* - Supports stacking with offsetY
|
|
2281
|
+
* - Icon based on variant
|
|
2282
|
+
* - Smooth animations
|
|
2283
|
+
* - Dynamic height calculation for proper stacking
|
|
2284
|
+
*
|
|
2285
|
+
* @example
|
|
2286
|
+
* ```tsx
|
|
2287
|
+
* <Alert
|
|
2288
|
+
* text="Operation completed successfully"
|
|
2289
|
+
* variant="success"
|
|
2290
|
+
* position="top-right"
|
|
2291
|
+
* isVisible={true}
|
|
2292
|
+
* />
|
|
2293
|
+
* ```
|
|
2294
|
+
*/
|
|
2295
|
+
const Alert = React.memo(({ text, variant = 'default', position = 'top-right', isVisible = false, offsetY = 0, maxWidth = ALERT_MAX_WIDTH, alertId, onHeightChange }) => {
|
|
2296
|
+
const theme$1 = theme.useTheme();
|
|
2297
|
+
const alertRef = React.useRef(null);
|
|
2298
|
+
const lastHeightRef = React.useRef(0);
|
|
2299
|
+
const icon = React.useMemo(() => getAlertIcon(variant), [variant]);
|
|
2300
|
+
const colors = React.useMemo(() => getAlertVariantColors(theme$1, variant), [theme$1, variant]);
|
|
2301
|
+
// Report height changes to parent (only when height actually changes)
|
|
2302
|
+
React.useEffect(() => {
|
|
2303
|
+
if (alertRef.current && onHeightChange && isVisible && alertId) {
|
|
2304
|
+
const height = alertRef.current.offsetHeight;
|
|
2305
|
+
// Only call onHeightChange if height has actually changed
|
|
2306
|
+
if (height !== lastHeightRef.current) {
|
|
2307
|
+
lastHeightRef.current = height;
|
|
2308
|
+
onHeightChange(alertId, height);
|
|
2309
|
+
}
|
|
2310
|
+
}
|
|
2311
|
+
}, [isVisible, text, maxWidth, alertId, onHeightChange]);
|
|
2312
|
+
return (jsxRuntime.jsxs("div", { ref: alertRef, className: ALERT_STYLES.root({ variant, position, isVisible, offsetY, maxWidth }), role: 'alert', "aria-live": 'polite', children: [jsxRuntime.jsx(Icon, { size: 'sm', color: colors.iconColor, children: icon }), jsxRuntime.jsx(Text, { variant: 'span', fontSize: 'sm', color: colors.iconColor, maxLines: 4, children: text })] }));
|
|
2313
|
+
});
|
|
2314
|
+
Alert.displayName = 'Alert';
|
|
2315
|
+
|
|
2134
2316
|
const MODAL_STYLES = theme.createStyles((theme) => ({
|
|
2135
2317
|
background: (isFadingIn) => ({
|
|
2136
2318
|
background: 'rgba(0, 0, 0, 0.6)',
|
|
@@ -2641,7 +2823,158 @@ const Pagination = ({ currentPage, totalPages, onPageChange, onPrevious, onNext,
|
|
|
2641
2823
|
};
|
|
2642
2824
|
Pagination.displayName = 'Pagination';
|
|
2643
2825
|
|
|
2826
|
+
const AlertContext = React.createContext(undefined);
|
|
2827
|
+
const ALERT_DURATION = 3000;
|
|
2828
|
+
const MAX_ALERTS = 2;
|
|
2829
|
+
const ALERT_HEIGHT = 48; // Approximate height with padding (px)
|
|
2830
|
+
const ALERT_SPACING = 6; // Spacing between alerts (px)
|
|
2831
|
+
/**
|
|
2832
|
+
* Alert Provider Component
|
|
2833
|
+
* Manages alert queue and renders alerts in a portal
|
|
2834
|
+
*/
|
|
2835
|
+
const AlertProvider = ({ children }) => {
|
|
2836
|
+
const [alerts, setAlerts] = React.useState([]);
|
|
2837
|
+
const [visibleAlerts, setVisibleAlerts] = React.useState(new Set());
|
|
2838
|
+
const [alertHeights, setAlertHeights] = React.useState(new Map());
|
|
2839
|
+
const timersRef = React.useRef(new Map());
|
|
2840
|
+
const showAlert = React.useCallback((options) => {
|
|
2841
|
+
const { text, variant = 'default', position = 'top-right', duration = ALERT_DURATION, maxWidth = 300 } = options;
|
|
2842
|
+
const id = `alert-${Date.now()}-${Math.random()}`;
|
|
2843
|
+
const newAlert = {
|
|
2844
|
+
id,
|
|
2845
|
+
text,
|
|
2846
|
+
variant,
|
|
2847
|
+
position,
|
|
2848
|
+
timestamp: Date.now(),
|
|
2849
|
+
maxWidth
|
|
2850
|
+
};
|
|
2851
|
+
setAlerts((prev) => {
|
|
2852
|
+
const updatedAlerts = [...prev, newAlert];
|
|
2853
|
+
// Keep only MAX_ALERTS for the same position
|
|
2854
|
+
const samePositionAlerts = updatedAlerts.filter(a => a.position === position);
|
|
2855
|
+
if (samePositionAlerts.length > MAX_ALERTS) {
|
|
2856
|
+
// Remove the oldest alert for this position
|
|
2857
|
+
const oldestAlert = samePositionAlerts[0];
|
|
2858
|
+
const timerToRemove = timersRef.current.get(oldestAlert.id);
|
|
2859
|
+
if (timerToRemove) {
|
|
2860
|
+
clearTimeout(timerToRemove);
|
|
2861
|
+
timersRef.current.delete(oldestAlert.id);
|
|
2862
|
+
}
|
|
2863
|
+
setVisibleAlerts((prevVisible) => {
|
|
2864
|
+
const newVisible = new Set(prevVisible);
|
|
2865
|
+
newVisible.delete(oldestAlert.id);
|
|
2866
|
+
return newVisible;
|
|
2867
|
+
});
|
|
2868
|
+
// Remove from alerts array after animation
|
|
2869
|
+
setTimeout(() => {
|
|
2870
|
+
setAlerts((current) => current.filter(a => a.id !== oldestAlert.id));
|
|
2871
|
+
setAlertHeights((prevHeights) => {
|
|
2872
|
+
const newMap = new Map(prevHeights);
|
|
2873
|
+
newMap.delete(oldestAlert.id);
|
|
2874
|
+
return newMap;
|
|
2875
|
+
});
|
|
2876
|
+
}, 300);
|
|
2877
|
+
return updatedAlerts.filter(a => a.id !== oldestAlert.id);
|
|
2878
|
+
}
|
|
2879
|
+
return updatedAlerts;
|
|
2880
|
+
});
|
|
2881
|
+
// Show alert after a small delay for animation
|
|
2882
|
+
setTimeout(() => {
|
|
2883
|
+
setVisibleAlerts((prev) => new Set(prev).add(id));
|
|
2884
|
+
}, 10);
|
|
2885
|
+
// Auto-dismiss timer
|
|
2886
|
+
const timer = setTimeout(() => {
|
|
2887
|
+
setVisibleAlerts((prev) => {
|
|
2888
|
+
const newVisible = new Set(prev);
|
|
2889
|
+
newVisible.delete(id);
|
|
2890
|
+
return newVisible;
|
|
2891
|
+
});
|
|
2892
|
+
// Remove from DOM after animation
|
|
2893
|
+
setTimeout(() => {
|
|
2894
|
+
setAlerts((prev) => prev.filter(a => a.id !== id));
|
|
2895
|
+
setAlertHeights((prev) => {
|
|
2896
|
+
const newMap = new Map(prev);
|
|
2897
|
+
newMap.delete(id);
|
|
2898
|
+
return newMap;
|
|
2899
|
+
});
|
|
2900
|
+
timersRef.current.delete(id);
|
|
2901
|
+
}, 300);
|
|
2902
|
+
}, duration);
|
|
2903
|
+
timersRef.current.set(id, timer);
|
|
2904
|
+
}, []);
|
|
2905
|
+
// Handle height changes from alerts (memoized to avoid re-creating on every render)
|
|
2906
|
+
const handleHeightChange = React.useCallback((alertId, height) => {
|
|
2907
|
+
setAlertHeights((prev) => {
|
|
2908
|
+
const currentHeight = prev.get(alertId);
|
|
2909
|
+
// Only update if height actually changed
|
|
2910
|
+
if (currentHeight !== height) {
|
|
2911
|
+
const newMap = new Map(prev);
|
|
2912
|
+
newMap.set(alertId, height);
|
|
2913
|
+
return newMap;
|
|
2914
|
+
}
|
|
2915
|
+
return prev;
|
|
2916
|
+
});
|
|
2917
|
+
}, []);
|
|
2918
|
+
// Cleanup timers on unmount
|
|
2919
|
+
React.useEffect(() => {
|
|
2920
|
+
return () => {
|
|
2921
|
+
timersRef.current.forEach(timer => clearTimeout(timer));
|
|
2922
|
+
timersRef.current.clear();
|
|
2923
|
+
};
|
|
2924
|
+
}, []);
|
|
2925
|
+
const contextValue = React.useMemo(() => ({ showAlert }), [showAlert]);
|
|
2926
|
+
// Group alerts by position
|
|
2927
|
+
const alertsByPosition = React.useMemo(() => {
|
|
2928
|
+
const grouped = {};
|
|
2929
|
+
alerts.forEach(alert => {
|
|
2930
|
+
if (!grouped[alert.position]) {
|
|
2931
|
+
grouped[alert.position] = [];
|
|
2932
|
+
}
|
|
2933
|
+
grouped[alert.position].push(alert);
|
|
2934
|
+
});
|
|
2935
|
+
return grouped;
|
|
2936
|
+
}, [alerts]);
|
|
2937
|
+
return (jsxRuntime.jsxs(AlertContext.Provider, { value: contextValue, children: [children, typeof window !== 'undefined' && reactDom.createPortal(jsxRuntime.jsx(jsxRuntime.Fragment, { children: Object.entries(alertsByPosition).map(([position, positionAlerts]) => {
|
|
2938
|
+
// positionAlerts is ordered from oldest -> newest
|
|
2939
|
+
const isTopPosition = position.startsWith('top');
|
|
2940
|
+
const ordered = isTopPosition ? [...positionAlerts].reverse() : positionAlerts;
|
|
2941
|
+
return ordered.map((alert, index) => {
|
|
2942
|
+
// Calculate offset based on actual heights of previous alerts
|
|
2943
|
+
let offset = 0;
|
|
2944
|
+
for (let i = 0; i < index; i++) {
|
|
2945
|
+
const prevAlert = ordered[i];
|
|
2946
|
+
const height = alertHeights.get(prevAlert.id) || ALERT_HEIGHT;
|
|
2947
|
+
offset += height + ALERT_SPACING;
|
|
2948
|
+
}
|
|
2949
|
+
return (jsxRuntime.jsx(Alert, { text: alert.text, variant: alert.variant, position: alert.position, isVisible: visibleAlerts.has(alert.id), offsetY: offset, maxWidth: alert.maxWidth, alertId: alert.id, onHeightChange: handleHeightChange }, alert.id));
|
|
2950
|
+
});
|
|
2951
|
+
}) }), document.body)] }));
|
|
2952
|
+
};
|
|
2953
|
+
/**
|
|
2954
|
+
* Hook to access alert functionality
|
|
2955
|
+
*
|
|
2956
|
+
* @example
|
|
2957
|
+
* ```tsx
|
|
2958
|
+
* const { showAlert } = useAlert()
|
|
2959
|
+
*
|
|
2960
|
+
* showAlert({
|
|
2961
|
+
* text: 'Operation completed',
|
|
2962
|
+
* variant: 'success',
|
|
2963
|
+
* position: 'top-right'
|
|
2964
|
+
* })
|
|
2965
|
+
* ```
|
|
2966
|
+
*/
|
|
2967
|
+
const useAlert = () => {
|
|
2968
|
+
const context = React.useContext(AlertContext);
|
|
2969
|
+
if (!context) {
|
|
2970
|
+
throw new Error('useAlert must be used within an AlertProvider');
|
|
2971
|
+
}
|
|
2972
|
+
return context;
|
|
2973
|
+
};
|
|
2974
|
+
|
|
2644
2975
|
exports.Accordion = Accordion;
|
|
2976
|
+
exports.Alert = Alert;
|
|
2977
|
+
exports.AlertProvider = AlertProvider;
|
|
2645
2978
|
exports.Avatar = Avatar;
|
|
2646
2979
|
exports.AvatarGroup = AvatarGroup;
|
|
2647
2980
|
exports.Breadcrumb = Breadcrumb;
|
|
@@ -2674,6 +3007,7 @@ exports.TabItem = TabItem;
|
|
|
2674
3007
|
exports.Tabs = Tabs;
|
|
2675
3008
|
exports.Text = Text;
|
|
2676
3009
|
exports.TextArea = TextArea_default;
|
|
3010
|
+
exports.useAlert = useAlert;
|
|
2677
3011
|
exports.useAnchorPosition = useAnchorPosition;
|
|
2678
3012
|
exports.useClickOutside = useClickOutside;
|
|
2679
3013
|
exports.useTransitionRender = useTransitionRender;
|