mautourco-components 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/atoms/Checkbox/Checkbox.js +7 -1
- package/dist/components/atoms/Icon/Icon.d.ts +1 -1
- package/dist/components/atoms/Icon/Icon.js +22 -1
- package/dist/components/atoms/Icon/icons/BuildingIcon.d.ts +8 -0
- package/dist/components/atoms/Icon/icons/BuildingIcon.js +36 -0
- package/dist/components/atoms/Icon/icons/CalendarOutlineIcon.d.ts +8 -0
- package/dist/components/atoms/Icon/icons/CalendarOutlineIcon.js +36 -0
- package/dist/components/atoms/Icon/icons/HomeIcon.d.ts +8 -0
- package/dist/components/atoms/Icon/icons/HomeIcon.js +25 -0
- package/dist/components/atoms/Icon/icons/MinusIcon.d.ts +8 -0
- package/dist/components/atoms/Icon/icons/MinusIcon.js +25 -0
- package/dist/components/atoms/Icon/icons/PlaneIcon.d.ts +8 -0
- package/dist/components/atoms/Icon/icons/PlaneIcon.js +36 -0
- package/dist/components/atoms/Icon/icons/PlusIcon.d.ts +8 -0
- package/dist/components/atoms/Icon/icons/PlusIcon.js +25 -0
- package/dist/components/atoms/Icon/icons/ShipIcon.d.ts +8 -0
- package/dist/components/atoms/Icon/icons/ShipIcon.js +36 -0
- package/dist/components/atoms/Illustration/Illustration.d.ts +14 -0
- package/dist/components/atoms/Illustration/Illustration.js +33 -0
- package/dist/components/atoms/Illustration/illustrations.d.ts +51 -0
- package/dist/components/atoms/Illustration/illustrations.js +97 -0
- package/dist/components/atoms/RatingStar/RatingStar.d.ts +40 -0
- package/dist/components/atoms/RatingStar/RatingStar.js +54 -0
- package/dist/components/atoms/SegmentedButton/SegmentedButton.d.ts +27 -0
- package/dist/components/atoms/SegmentedButton/SegmentedButton.js +49 -0
- package/dist/components/atoms/Slider/Slider.d.ts +52 -0
- package/dist/components/atoms/Slider/Slider.js +30 -0
- package/dist/components/molecules/Calendar/CalendarInput.d.ts +34 -0
- package/dist/components/molecules/Calendar/CalendarInput.js +49 -0
- package/dist/components/molecules/Calendar/DateTime.d.ts +25 -0
- package/dist/components/molecules/Calendar/DateTime.js +106 -0
- package/dist/components/molecules/Calendar/TimePicker.d.ts +16 -0
- package/dist/components/molecules/Calendar/TimePicker.js +91 -0
- package/dist/components/molecules/LocationDropdown/LocationDropdown.d.ts +34 -0
- package/dist/components/molecules/LocationDropdown/LocationDropdown.js +120 -0
- package/dist/components/molecules/LocationDropdown/index.d.ts +2 -0
- package/dist/components/molecules/LocationDropdown/index.js +1 -0
- package/dist/components/molecules/RatingTab/RatingTab.d.ts +39 -0
- package/dist/components/molecules/RatingTab/RatingTab.js +41 -0
- package/dist/components/molecules/TabGroup/TabGroup.d.ts +17 -0
- package/dist/components/molecules/TabGroup/TabGroup.js +30 -0
- package/dist/components/organisms/CardContainer/CardContainer.d.ts +37 -0
- package/dist/components/organisms/CardContainer/CardContainer.js +27 -0
- package/dist/components/organisms/DateTimePicker/DateTimePicker.d.ts +15 -0
- package/dist/components/organisms/DateTimePicker/DateTimePicker.js +66 -0
- package/dist/components/organisms/Dialog/Dialog.d.ts +103 -0
- package/dist/components/organisms/Dialog/Dialog.js +162 -0
- package/dist/components/organisms/PaxSelector/PaxSelector.d.ts +63 -0
- package/dist/components/organisms/PaxSelector/PaxSelector.js +402 -0
- package/dist/components/organisms/RoundTrip/RoundTrip.d.ts +54 -0
- package/dist/components/organisms/RoundTrip/RoundTrip.js +179 -0
- package/dist/components/organisms/RoundTrip/index.d.ts +2 -0
- package/dist/components/organisms/RoundTrip/index.js +1 -0
- package/dist/components/organisms/SearchBarTransfer/SearchBarTransfer.d.ts +35 -0
- package/dist/components/organisms/SearchBarTransfer/SearchBarTransfer.js +192 -0
- package/dist/components/organisms/SearchBarTransfer/index.d.ts +2 -0
- package/dist/components/organisms/SearchBarTransfer/index.js +1 -0
- package/dist/components/organisms/TransferLine/TransferLine.d.ts +53 -0
- package/dist/components/organisms/TransferLine/TransferLine.js +179 -0
- package/dist/components/ui/button.d.ts +10 -0
- package/dist/components/ui/button.js +56 -0
- package/dist/components/ui/calendar.d.ts +8 -0
- package/dist/components/ui/calendar.js +87 -0
- package/dist/components/ui/popover.d.ts +7 -0
- package/dist/components/ui/popover.js +42 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.js +18 -0
- package/dist/lib/utils.d.ts +7 -0
- package/dist/lib/utils.js +13 -0
- package/package.json +21 -12
- package/src/components/atoms/Button/Button.css +34 -34
- package/src/components/atoms/Checkbox/Checkbox.tsx +83 -69
- package/src/components/atoms/Icon/Icon.tsx +30 -2
- package/src/components/atoms/Icon/icons/BuildingIcon.tsx +50 -0
- package/src/components/atoms/Icon/icons/CalendarOutlineIcon.tsx +50 -0
- package/src/components/atoms/Icon/icons/HomeIcon.tsx +52 -0
- package/src/components/atoms/Icon/icons/MinusIcon.tsx +45 -0
- package/src/components/atoms/Icon/icons/PlaneIcon.tsx +50 -0
- package/src/components/atoms/Icon/icons/PlusIcon.tsx +45 -0
- package/src/components/atoms/Icon/icons/ShipIcon.tsx +50 -0
- package/src/components/atoms/Illustration/Illustration.tsx +28 -0
- package/src/components/atoms/Illustration/illustrations.ts +116 -0
- package/src/components/atoms/RatingStar/RatingStar.tsx +114 -0
- package/src/components/atoms/SegmentedButton/SegmentedButton.tsx +94 -0
- package/src/components/atoms/Slider/Slider.tsx +95 -0
- package/src/components/molecules/Calendar/CalendarInput.tsx +135 -0
- package/src/components/molecules/Calendar/DateTime.tsx +172 -0
- package/src/components/molecules/Calendar/TimePicker.tsx +174 -0
- package/src/components/molecules/LocationDropdown/LocationDropdown.tsx +234 -0
- package/src/components/molecules/LocationDropdown/index.ts +2 -0
- package/src/components/molecules/RatingTab/RatingTab.tsx +96 -0
- package/src/components/molecules/TabGroup/TabGroup.tsx +60 -0
- package/src/components/molecules/UserCard/UserCard.stories.tsx +2 -2
- package/src/components/organisms/CardContainer/CardContainer.tsx +66 -0
- package/src/components/organisms/DateTimePicker/DateTimePicker.tsx +110 -0
- package/src/components/organisms/Dialog/Dialog.tsx +352 -0
- package/src/components/organisms/PaxSelector/PaxSelector.tsx +979 -0
- package/src/components/organisms/RoundTrip/RoundTrip.tsx +335 -0
- package/src/components/organisms/RoundTrip/index.ts +2 -0
- package/src/components/organisms/SearchBarTransfer/SearchBarTransfer.tsx +388 -0
- package/src/components/organisms/SearchBarTransfer/index.ts +2 -0
- package/src/components/organisms/TransferLine/TransferLine.tsx +369 -0
- package/src/components/ui/button.tsx +60 -0
- package/src/components/ui/calendar.tsx +246 -0
- package/src/components/ui/popover.tsx +46 -0
- package/src/styles/components/calendar.css +86 -0
- package/src/styles/components/checkbox.css +130 -132
- package/src/styles/components/dropdown.css +40 -40
- package/src/styles/components/forms.css +51 -51
- package/src/styles/components/illustration.css +7 -0
- package/src/styles/components/molecule/calendarInput.css +157 -0
- package/src/styles/components/molecule/dateTime.css +14 -0
- package/src/styles/components/molecule/location-dropdown.css +204 -0
- package/src/styles/components/molecule/timePicker.css +79 -0
- package/src/styles/components/multiselect-dropdown.css +230 -231
- package/src/styles/components/organism/card-container.css +49 -0
- package/src/styles/components/organism/dialog.css +241 -0
- package/src/styles/components/organism/pax-selector.css +702 -0
- package/src/styles/components/organism/round-trip.css +55 -0
- package/src/styles/components/organism/search-bar-transfer.css +128 -0
- package/src/styles/components/organism/transfer-line.css +86 -0
- package/src/styles/components/rating-star.css +39 -0
- package/src/styles/components/rating-tab.css +83 -0
- package/src/styles/components/segmented-button.css +134 -0
- package/src/styles/components/selected-value.css +16 -16
- package/src/styles/components/slider.css +86 -0
- package/src/styles/components/typography.css +36 -36
- package/src/styles/tokens/tokens.css +1093 -1093
- package/dist/components/atoms/Typography/Heading/Heading.d.ts +0 -9
- package/dist/components/atoms/Typography/Heading/Heading.js +0 -25
- package/dist/components/atoms/Typography/Text/Text.d.ts +0 -10
- package/dist/components/atoms/Typography/Text/Text.js +0 -77
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
interface ShipIconProps {
|
|
4
|
+
size?: "xs" | "sm" | "md" | "lg" | "xl";
|
|
5
|
+
className?: string;
|
|
6
|
+
color?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const ShipIcon: React.FC<ShipIconProps> = ({
|
|
10
|
+
size = "md",
|
|
11
|
+
className = "",
|
|
12
|
+
color,
|
|
13
|
+
}) => {
|
|
14
|
+
const getSizeClasses = () => {
|
|
15
|
+
switch (size) {
|
|
16
|
+
case "xs":
|
|
17
|
+
return "w-3 h-3";
|
|
18
|
+
case "sm":
|
|
19
|
+
return "w-4 h-4";
|
|
20
|
+
case "md":
|
|
21
|
+
return "w-5 h-5";
|
|
22
|
+
case "lg":
|
|
23
|
+
return "w-6 h-6";
|
|
24
|
+
case "xl":
|
|
25
|
+
return "w-8 h-8";
|
|
26
|
+
default:
|
|
27
|
+
return "w-5 h-5";
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const sizeClasses = getSizeClasses();
|
|
32
|
+
const colorClass = color ? `text-${color}` : "text-current";
|
|
33
|
+
const classes = `${sizeClasses} ${colorClass} ${className}`;
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<svg
|
|
37
|
+
className={classes}
|
|
38
|
+
viewBox="0 0 16 16"
|
|
39
|
+
fill="none"
|
|
40
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
41
|
+
>
|
|
42
|
+
<path
|
|
43
|
+
d="M11.9159 4.66638C11.9158 4.51179 11.8543 4.36359 11.745 4.25427C11.6356 4.14498 11.4875 4.08337 11.3329 4.08337H4.66586C4.51127 4.08346 4.36307 4.14495 4.25375 4.25427C4.14443 4.36359 4.08294 4.51179 4.08285 4.66638V7.5863L7.15316 6.22205H7.15414C7.42075 6.10366 7.70904 6.04236 7.99984 6.04236C8.29067 6.0424 8.57894 6.1036 8.84555 6.22205L11.9159 7.5863V4.66638ZM7.24984 9.33337V7.82068L2.75961 9.8158C2.82788 11.1514 3.27724 12.4381 4.05453 13.5238C4.09858 13.4896 4.14754 13.4549 4.19809 13.4144C4.39883 13.2538 4.66983 13.033 5.0184 12.8656C5.38322 12.6905 5.80735 12.5834 6.33285 12.5834C6.87026 12.5834 7.29979 12.6885 7.66781 12.8666C8.02062 13.0373 8.28638 13.2634 8.47934 13.4242C8.68632 13.5967 8.82043 13.7043 8.98422 13.7836C9.13281 13.8555 9.33681 13.9163 9.66586 13.9164C9.97342 13.9164 10.1749 13.8574 10.3309 13.7826C10.5028 13.7001 10.6483 13.587 10.8641 13.4144C11.0649 13.2538 11.3366 13.033 11.6854 12.8656C11.915 12.7554 12.1679 12.6719 12.4549 12.6254C12.9105 11.7536 13.1766 10.7959 13.2362 9.81482L8.74984 7.82068V9.33337C8.74984 9.74748 8.41391 10.0832 7.99984 10.0834C7.58563 10.0834 7.24984 9.74759 7.24984 9.33337ZM13.4159 8.25232L14.3045 8.64783L14.4002 8.69958C14.6138 8.83453 14.7478 9.07003 14.7498 9.32751C14.7587 10.5081 14.5199 11.6734 14.0555 12.7504C14.1526 12.7845 14.2456 12.8234 14.3348 12.8666C14.6875 13.0373 14.9534 13.2634 15.1463 13.4242C15.4644 13.6894 15.5071 14.1617 15.242 14.4799C14.977 14.7979 14.5046 14.8414 14.1864 14.5765C13.9795 14.4041 13.8452 14.2964 13.6815 14.2172C13.5329 14.1453 13.3289 14.0834 12.9998 14.0834C12.6921 14.0834 12.4908 14.1433 12.3348 14.2181C12.1629 14.3007 12.0173 14.4128 11.8016 14.5853C11.6008 14.746 11.3291 14.9667 10.9803 15.1342C10.6155 15.3093 10.1914 15.4164 9.66586 15.4164C9.12859 15.4163 8.69885 15.3112 8.3309 15.1332C7.97834 14.9625 7.71226 14.7373 7.51938 14.5765C7.31239 14.404 7.17828 14.2964 7.01449 14.2172C6.86585 14.1452 6.66209 14.0834 6.33285 14.0834C6.02502 14.0834 5.82383 14.1433 5.66781 14.2181C5.4959 14.3007 5.35034 14.4127 5.13461 14.5853C4.93379 14.746 4.66216 14.9667 4.31332 15.1342C3.9486 15.3092 3.52514 15.4163 2.99984 15.4164C2.4625 15.4164 2.03287 15.3112 1.66488 15.1332C1.4004 15.0052 1.18428 14.8467 1.01156 14.7074L0.852383 14.5765L0.796719 14.5238C0.530729 14.2522 0.508067 13.8182 0.75668 13.5199C1.00526 13.2216 1.43668 13.1648 1.7518 13.3773L1.81332 13.4242L2.08188 13.6381C2.16176 13.6965 2.23626 13.7439 2.3182 13.7836C2.36307 13.8053 2.4137 13.8238 2.47055 13.8422C1.65272 12.4872 1.22378 10.922 1.24984 9.32068C1.25478 9.02894 1.4285 8.76634 1.69516 8.64783L2.58285 8.2533V4.66638C2.58294 4.11396 2.80258 3.58435 3.1932 3.19373C3.58383 2.8031 4.11344 2.58346 4.66586 2.58337H7.24984V1.33337C7.24984 0.91916 7.58563 0.583374 7.99984 0.583374C8.41391 0.58355 8.74984 0.919269 8.74984 1.33337V2.58337H11.3329C11.8853 2.58337 12.4148 2.80313 12.8055 3.19373C13.1961 3.58435 13.4158 4.11396 13.4159 4.66638V8.25232Z"
|
|
44
|
+
fill="currentColor"
|
|
45
|
+
/>
|
|
46
|
+
</svg>
|
|
47
|
+
);
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export default ShipIcon;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
export interface IllustrationProps
|
|
4
|
+
extends React.ImgHTMLAttributes<HTMLImageElement> {
|
|
5
|
+
/**
|
|
6
|
+
* Source of the illustration.
|
|
7
|
+
* This will typically be an imported SVG/PNG from the assets directory.
|
|
8
|
+
*/
|
|
9
|
+
src: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Generic Illustration atom.
|
|
14
|
+
* It focuses on consistent rendering (responsive, block-level) while
|
|
15
|
+
* letting the caller control which asset is used.
|
|
16
|
+
*/
|
|
17
|
+
export const Illustration: React.FC<IllustrationProps> = ({
|
|
18
|
+
src,
|
|
19
|
+
className = '',
|
|
20
|
+
...rest
|
|
21
|
+
}) => {
|
|
22
|
+
const classes = ['illustration', className].filter(Boolean).join(' ');
|
|
23
|
+
|
|
24
|
+
return <img src={src} className={classes} {...rest} />;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Illustrations disponibles depuis Figma
|
|
3
|
+
* Les images sont servies depuis le serveur MCP Figma (localhost:3845)
|
|
4
|
+
*
|
|
5
|
+
* Note: Ces URLs sont temporaires et servies par le serveur MCP Figma local.
|
|
6
|
+
* En production, ces images devront être exportées et hébergées séparément.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export interface IllustrationInfo {
|
|
10
|
+
/** Nom de l'illustration */
|
|
11
|
+
name: string;
|
|
12
|
+
/** URL de l'image depuis le serveur MCP Figma */
|
|
13
|
+
url: string;
|
|
14
|
+
/** Catégorie de l'illustration */
|
|
15
|
+
category: 'success' | 'background' | 'error' | 'alert';
|
|
16
|
+
/** Description de l'illustration */
|
|
17
|
+
description?: string;
|
|
18
|
+
/** Dimensions (largeur x hauteur) */
|
|
19
|
+
dimensions?: { width: number; height: number };
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Illustrations de succès (Quotation Success)
|
|
24
|
+
*/
|
|
25
|
+
export const SUCCESS_ILLUSTRATIONS: Record<string, IllustrationInfo> = {
|
|
26
|
+
quotationSuccessOption1: {
|
|
27
|
+
name: 'Quotation Success - Option 1',
|
|
28
|
+
url: 'http://localhost:3845/assets/undraw_graduation_re_gthn_1', // À remplacer par l'URL réelle
|
|
29
|
+
category: 'success',
|
|
30
|
+
description: 'Illustration de succès pour l\'ajout d\'une voiture à une quotation',
|
|
31
|
+
dimensions: { width: 426, height: 212 },
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Illustrations de fond (Background)
|
|
37
|
+
*/
|
|
38
|
+
export const BACKGROUND_ILLUSTRATIONS: Record<string, IllustrationInfo> = {
|
|
39
|
+
bgSun: {
|
|
40
|
+
name: 'BG_Sun',
|
|
41
|
+
url: 'http://localhost:3845/assets/8b482904d4764abeaaa5276f661a8bbabd874df2.png',
|
|
42
|
+
category: 'background',
|
|
43
|
+
description: 'Illustration de fond - Soleil',
|
|
44
|
+
dimensions: { width: 316, height: 314 },
|
|
45
|
+
},
|
|
46
|
+
bgCocktail: {
|
|
47
|
+
name: 'BG_Cocktail',
|
|
48
|
+
url: 'http://localhost:3845/assets/51130ed9197c5d6b4323a7e134aae153aa7cec61.png',
|
|
49
|
+
category: 'background',
|
|
50
|
+
description: 'Illustration de fond - Cocktail',
|
|
51
|
+
dimensions: { width: 624, height: 624 },
|
|
52
|
+
},
|
|
53
|
+
bgCoconut: {
|
|
54
|
+
name: 'BG_Coconut',
|
|
55
|
+
url: 'http://localhost:3845/assets/40b9073c72d20eed316693d7435c1199b3dbcf0a.png',
|
|
56
|
+
category: 'background',
|
|
57
|
+
description: 'Illustration de fond - Coco',
|
|
58
|
+
dimensions: { width: 624, height: 624 },
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Illustrations d'erreur
|
|
64
|
+
*/
|
|
65
|
+
export const ERROR_ILLUSTRATIONS: Record<string, IllustrationInfo> = {
|
|
66
|
+
illustrationError: {
|
|
67
|
+
name: 'Illustration_Error',
|
|
68
|
+
url: 'http://localhost:3845/assets/group_46', // À remplacer par l'URL réelle
|
|
69
|
+
category: 'error',
|
|
70
|
+
description: 'Illustration d\'erreur - Aucun résultat trouvé',
|
|
71
|
+
dimensions: { width: 840, height: 463 },
|
|
72
|
+
},
|
|
73
|
+
error: {
|
|
74
|
+
name: 'Error',
|
|
75
|
+
url: 'http://localhost:3845/assets/undraw_cancel_7zdh_1', // À remplacer par l'URL réelle
|
|
76
|
+
category: 'error',
|
|
77
|
+
description: 'Illustration d\'erreur - Action bloquée',
|
|
78
|
+
dimensions: { width: 350, height: 350 },
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Illustrations d'alerte
|
|
84
|
+
*/
|
|
85
|
+
export const ALERT_ILLUSTRATIONS: Record<string, IllustrationInfo> = {
|
|
86
|
+
illustrationAlert: {
|
|
87
|
+
name: 'Illustration_Alert',
|
|
88
|
+
url: 'http://localhost:3845/assets/group_47', // À remplacer par l'URL réelle
|
|
89
|
+
category: 'alert',
|
|
90
|
+
description: 'Illustration d\'alerte - Capacité dépassée',
|
|
91
|
+
dimensions: { width: 426, height: 358 },
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Toutes les illustrations regroupées par catégorie
|
|
97
|
+
*/
|
|
98
|
+
export const ALL_ILLUSTRATIONS = {
|
|
99
|
+
success: SUCCESS_ILLUSTRATIONS,
|
|
100
|
+
background: BACKGROUND_ILLUSTRATIONS,
|
|
101
|
+
error: ERROR_ILLUSTRATIONS,
|
|
102
|
+
alert: ALERT_ILLUSTRATIONS,
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Helper pour obtenir une illustration par son nom
|
|
107
|
+
*/
|
|
108
|
+
export function getIllustration(name: string): IllustrationInfo | undefined {
|
|
109
|
+
for (const category of Object.values(ALL_ILLUSTRATIONS)) {
|
|
110
|
+
if (category[name]) {
|
|
111
|
+
return category[name];
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return undefined;
|
|
115
|
+
}
|
|
116
|
+
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
export interface RatingStarProps {
|
|
4
|
+
/**
|
|
5
|
+
* Current value (0–max). For display-only, you can omit onChange.
|
|
6
|
+
*/
|
|
7
|
+
value: number;
|
|
8
|
+
/**
|
|
9
|
+
* Maximum number of stars.
|
|
10
|
+
*/
|
|
11
|
+
max?: number;
|
|
12
|
+
/**
|
|
13
|
+
* Whether the component is interactive (hover / click).
|
|
14
|
+
*/
|
|
15
|
+
interactive?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Called when the user selects a new rating (1–max).
|
|
18
|
+
*/
|
|
19
|
+
onChange?: (value: number) => void;
|
|
20
|
+
/**
|
|
21
|
+
* Whether the control is disabled.
|
|
22
|
+
*/
|
|
23
|
+
disabled?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Additional CSS classes for the root container.
|
|
26
|
+
*/
|
|
27
|
+
className?: string;
|
|
28
|
+
/**
|
|
29
|
+
* Accessible label describing the rating.
|
|
30
|
+
*/
|
|
31
|
+
'aria-label'?: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Star Rating atom
|
|
36
|
+
*
|
|
37
|
+
* Displays a row of stars from 0 to `max` (default: 5),
|
|
38
|
+
* using tokens from Components/rating-star.
|
|
39
|
+
* Can be used in read-only mode or interactive mode.
|
|
40
|
+
*/
|
|
41
|
+
export const RatingStar: React.FC<RatingStarProps> = ({
|
|
42
|
+
value,
|
|
43
|
+
max = 5,
|
|
44
|
+
interactive = false,
|
|
45
|
+
onChange,
|
|
46
|
+
disabled = false,
|
|
47
|
+
className = '',
|
|
48
|
+
'aria-label': ariaLabel,
|
|
49
|
+
}) => {
|
|
50
|
+
const handleClick = (index: number) => {
|
|
51
|
+
if (!interactive || disabled || !onChange) return;
|
|
52
|
+
onChange(index + 1);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {
|
|
56
|
+
if (!interactive || disabled || !onChange) return;
|
|
57
|
+
|
|
58
|
+
if (event.key === 'ArrowRight' || event.key === 'ArrowUp') {
|
|
59
|
+
event.preventDefault();
|
|
60
|
+
onChange(Math.min(max, value + 1));
|
|
61
|
+
}
|
|
62
|
+
if (event.key === 'ArrowLeft' || event.key === 'ArrowDown') {
|
|
63
|
+
event.preventDefault();
|
|
64
|
+
onChange(Math.max(0, value - 1));
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const stars = Array.from({ length: max }, (_, index) => {
|
|
69
|
+
const isSelected = index < value;
|
|
70
|
+
const starClass = [
|
|
71
|
+
'rating-star__icon',
|
|
72
|
+
isSelected ? 'rating-star__icon--selected' : 'rating-star__icon--default',
|
|
73
|
+
]
|
|
74
|
+
.filter(Boolean)
|
|
75
|
+
.join(' ');
|
|
76
|
+
|
|
77
|
+
return (
|
|
78
|
+
<button
|
|
79
|
+
key={index}
|
|
80
|
+
type="button"
|
|
81
|
+
className="rating-star__button"
|
|
82
|
+
onClick={() => handleClick(index)}
|
|
83
|
+
disabled={disabled || !interactive}
|
|
84
|
+
aria-hidden={!interactive}
|
|
85
|
+
tabIndex={interactive ? 0 : -1}
|
|
86
|
+
>
|
|
87
|
+
<span className={starClass}>★</span>
|
|
88
|
+
</button>
|
|
89
|
+
);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
const containerClasses = ['rating-star', interactive ? 'rating-star--interactive' : '', className]
|
|
93
|
+
.filter(Boolean)
|
|
94
|
+
.join(' ');
|
|
95
|
+
|
|
96
|
+
return (
|
|
97
|
+
<div
|
|
98
|
+
className={containerClasses}
|
|
99
|
+
role={interactive ? 'slider' : 'img'}
|
|
100
|
+
aria-valuemin={interactive ? 0 : undefined}
|
|
101
|
+
aria-valuemax={interactive ? max : undefined}
|
|
102
|
+
aria-valuenow={interactive ? value : undefined}
|
|
103
|
+
aria-label={ariaLabel}
|
|
104
|
+
tabIndex={interactive && !disabled ? 0 : -1}
|
|
105
|
+
onKeyDown={handleKeyDown}
|
|
106
|
+
>
|
|
107
|
+
{stars}
|
|
108
|
+
</div>
|
|
109
|
+
);
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
export default RatingStar;
|
|
113
|
+
|
|
114
|
+
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
export interface SegmentedButtonOption {
|
|
4
|
+
/** Valeur de l'option */
|
|
5
|
+
value: string;
|
|
6
|
+
/** Libellé affiché */
|
|
7
|
+
label: string;
|
|
8
|
+
/** État désactivé */
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface SegmentedButtonProps {
|
|
13
|
+
/** Options du bouton segmenté */
|
|
14
|
+
options: SegmentedButtonOption[];
|
|
15
|
+
/** Valeur sélectionnée */
|
|
16
|
+
value: string;
|
|
17
|
+
/** Handler de changement */
|
|
18
|
+
onChange: (value: string) => void;
|
|
19
|
+
/** Orientation du bouton segmenté */
|
|
20
|
+
orientation?: 'horizontal' | 'vertical';
|
|
21
|
+
/** État désactivé pour tout le groupe */
|
|
22
|
+
disabled?: boolean;
|
|
23
|
+
/** Classes CSS supplémentaires */
|
|
24
|
+
className?: string;
|
|
25
|
+
/** Nom du groupe pour l'accessibilité */
|
|
26
|
+
name?: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const SegmentedButton: React.FC<SegmentedButtonProps> = ({
|
|
30
|
+
options,
|
|
31
|
+
value,
|
|
32
|
+
onChange,
|
|
33
|
+
orientation = 'horizontal',
|
|
34
|
+
disabled = false,
|
|
35
|
+
className = '',
|
|
36
|
+
name,
|
|
37
|
+
}) => {
|
|
38
|
+
const containerClasses = [
|
|
39
|
+
'segmented-button',
|
|
40
|
+
`segmented-button--${orientation}`,
|
|
41
|
+
disabled && 'segmented-button--disabled',
|
|
42
|
+
className,
|
|
43
|
+
]
|
|
44
|
+
.filter(Boolean)
|
|
45
|
+
.join(' ');
|
|
46
|
+
|
|
47
|
+
const handleClick = (optionValue: string, optionDisabled?: boolean) => {
|
|
48
|
+
if (!disabled && !optionDisabled && optionValue !== value) {
|
|
49
|
+
onChange(optionValue);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const getButtonClasses = (option: SegmentedButtonOption, index: number) => {
|
|
54
|
+
const isSelected = option.value === value;
|
|
55
|
+
const isFirst = index === 0;
|
|
56
|
+
const isLast = index === options.length - 1;
|
|
57
|
+
const isDisabled = disabled || option.disabled;
|
|
58
|
+
|
|
59
|
+
return [
|
|
60
|
+
'segmented-button__item',
|
|
61
|
+
isSelected && 'segmented-button__item--selected',
|
|
62
|
+
isFirst && 'segmented-button__item--first',
|
|
63
|
+
isLast && 'segmented-button__item--last',
|
|
64
|
+
isDisabled && 'segmented-button__item--disabled',
|
|
65
|
+
]
|
|
66
|
+
.filter(Boolean)
|
|
67
|
+
.join(' ');
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
return (
|
|
71
|
+
<div className={containerClasses} role="group" aria-label={name}>
|
|
72
|
+
{options.map((option, index) => {
|
|
73
|
+
const isSelected = option.value === value;
|
|
74
|
+
const isDisabled = disabled || option.disabled;
|
|
75
|
+
|
|
76
|
+
return (
|
|
77
|
+
<button
|
|
78
|
+
key={option.value}
|
|
79
|
+
type="button"
|
|
80
|
+
className={getButtonClasses(option, index)}
|
|
81
|
+
onClick={() => handleClick(option.value, option.disabled)}
|
|
82
|
+
disabled={isDisabled}
|
|
83
|
+
aria-pressed={isSelected}
|
|
84
|
+
aria-label={option.label}
|
|
85
|
+
>
|
|
86
|
+
<span className="segmented-button__label">{option.label}</span>
|
|
87
|
+
</button>
|
|
88
|
+
);
|
|
89
|
+
})}
|
|
90
|
+
</div>
|
|
91
|
+
);
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
export default SegmentedButton;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
export type SliderVariant = 'full' | 'half';
|
|
4
|
+
|
|
5
|
+
export interface SliderProps {
|
|
6
|
+
/**
|
|
7
|
+
* Current value of the slider (controlled mode).
|
|
8
|
+
*/
|
|
9
|
+
value: number;
|
|
10
|
+
/**
|
|
11
|
+
* Minimum value.
|
|
12
|
+
*/
|
|
13
|
+
min?: number;
|
|
14
|
+
/**
|
|
15
|
+
* Maximum value.
|
|
16
|
+
*/
|
|
17
|
+
max?: number;
|
|
18
|
+
/**
|
|
19
|
+
* Step between values.
|
|
20
|
+
*/
|
|
21
|
+
step?: number;
|
|
22
|
+
/**
|
|
23
|
+
* Called when the value changes.
|
|
24
|
+
*/
|
|
25
|
+
onChange: (value: number) => void;
|
|
26
|
+
/**
|
|
27
|
+
* Visual variant (from Figma: Type=Full | Type=Half).
|
|
28
|
+
*/
|
|
29
|
+
variant?: SliderVariant;
|
|
30
|
+
/**
|
|
31
|
+
* Whether the slider is disabled.
|
|
32
|
+
*/
|
|
33
|
+
disabled?: boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Accessible label (aria-label) if no visible label is provided.
|
|
36
|
+
*/
|
|
37
|
+
'aria-label'?: string;
|
|
38
|
+
/**
|
|
39
|
+
* Optional id to link with an external label.
|
|
40
|
+
*/
|
|
41
|
+
id?: string;
|
|
42
|
+
/**
|
|
43
|
+
* Additional CSS classes.
|
|
44
|
+
*/
|
|
45
|
+
className?: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Slider atom.
|
|
50
|
+
*
|
|
51
|
+
* Represents a single horizontal slider control (rail + thumb),
|
|
52
|
+
* matching the Figma Slider component (Full / Half variants).
|
|
53
|
+
*/
|
|
54
|
+
export const Slider: React.FC<SliderProps> = ({
|
|
55
|
+
value,
|
|
56
|
+
min = 0,
|
|
57
|
+
max = 100,
|
|
58
|
+
step = 1,
|
|
59
|
+
onChange,
|
|
60
|
+
variant = 'full',
|
|
61
|
+
disabled = false,
|
|
62
|
+
id,
|
|
63
|
+
className = '',
|
|
64
|
+
'aria-label': ariaLabel,
|
|
65
|
+
}) => {
|
|
66
|
+
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
67
|
+
const next = Number(event.target.value);
|
|
68
|
+
onChange(next);
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const classes = ['slider', `slider--${variant}`, disabled ? 'slider--disabled' : '', className]
|
|
72
|
+
.filter(Boolean)
|
|
73
|
+
.join(' ');
|
|
74
|
+
|
|
75
|
+
return (
|
|
76
|
+
<div className="slider-container">
|
|
77
|
+
<input
|
|
78
|
+
id={id}
|
|
79
|
+
type="range"
|
|
80
|
+
className={classes}
|
|
81
|
+
min={min}
|
|
82
|
+
max={max}
|
|
83
|
+
step={step}
|
|
84
|
+
value={value}
|
|
85
|
+
onChange={handleChange}
|
|
86
|
+
disabled={disabled}
|
|
87
|
+
aria-label={ariaLabel}
|
|
88
|
+
/>
|
|
89
|
+
</div>
|
|
90
|
+
);
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
export default Slider;
|
|
94
|
+
|
|
95
|
+
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import React, { useState } from "react";
|
|
2
|
+
import Icon from "../../atoms/Icon/Icon";
|
|
3
|
+
|
|
4
|
+
export interface CalendarInputProps {
|
|
5
|
+
/** Placeholder text */
|
|
6
|
+
placeholder?: string;
|
|
7
|
+
/** Selected date value (formatted as string) */
|
|
8
|
+
value?: string;
|
|
9
|
+
/** State of the input: default, active, typing, disabled, success, error */
|
|
10
|
+
state?: "default" | "active" | "typing" | "disabled" | "success" | "error";
|
|
11
|
+
/** Helper/support text below input */
|
|
12
|
+
/** Whether the input is disabled */
|
|
13
|
+
disabled?: boolean;
|
|
14
|
+
/** Callback when the input is clicked */
|
|
15
|
+
onClick?: () => void;
|
|
16
|
+
/** Callback when calendar icon is clicked */
|
|
17
|
+
onCalendarClick?: () => void;
|
|
18
|
+
/** Callback when input value changes */
|
|
19
|
+
onChange?: (value: string) => void;
|
|
20
|
+
/** Callback when input gains focus */
|
|
21
|
+
onFocus?: () => void;
|
|
22
|
+
/** Callback when input loses focus */
|
|
23
|
+
onBlur?: () => void;
|
|
24
|
+
/** Additional CSS classes */
|
|
25
|
+
className?: string;
|
|
26
|
+
/** Whether the calendar icon has full bg*/
|
|
27
|
+
iconBGFull?: boolean;
|
|
28
|
+
/** Position of the calendar icon: left or right */
|
|
29
|
+
iconPosition?: "left" | "right";
|
|
30
|
+
/** Show chevron on the right when icon is on the left */
|
|
31
|
+
showChevron?: boolean;
|
|
32
|
+
/** Whether the calendar popover is open */
|
|
33
|
+
isOpen?: boolean;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const CalendarInput: React.FC<CalendarInputProps> = ({
|
|
37
|
+
placeholder = "Select date",
|
|
38
|
+
value = "",
|
|
39
|
+
state = "default",
|
|
40
|
+
disabled = false,
|
|
41
|
+
onClick,
|
|
42
|
+
onCalendarClick,
|
|
43
|
+
onChange,
|
|
44
|
+
onFocus,
|
|
45
|
+
onBlur,
|
|
46
|
+
className = "",
|
|
47
|
+
iconBGFull = true,
|
|
48
|
+
iconPosition = "right",
|
|
49
|
+
showChevron = false,
|
|
50
|
+
isOpen = false,
|
|
51
|
+
}) => {
|
|
52
|
+
const [isFocused, setIsFocused] = useState(false);
|
|
53
|
+
const [localValue, setLocalValue] = useState(value);
|
|
54
|
+
const [isTyping, setIsTyping] = useState(false);
|
|
55
|
+
|
|
56
|
+
const finalState = disabled ? "disabled" : state;
|
|
57
|
+
const displayState =
|
|
58
|
+
isFocused && isTyping ? "typing" : isFocused ? "active" : finalState;
|
|
59
|
+
|
|
60
|
+
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
61
|
+
const newValue = e.target.value;
|
|
62
|
+
setLocalValue(newValue);
|
|
63
|
+
setIsTyping(true);
|
|
64
|
+
onChange?.(newValue);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const handleFocus = () => {
|
|
68
|
+
setIsFocused(true);
|
|
69
|
+
onFocus?.();
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const handleBlur = () => {
|
|
73
|
+
setIsFocused(false);
|
|
74
|
+
setIsTyping(false);
|
|
75
|
+
onBlur?.();
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const handleCalendarClick = () => {
|
|
79
|
+
if (!disabled) {
|
|
80
|
+
onCalendarClick?.();
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
// keep localValue in sync when parent changes `value` (controlled)
|
|
85
|
+
React.useEffect(() => {
|
|
86
|
+
setLocalValue(value);
|
|
87
|
+
}, [value]);
|
|
88
|
+
|
|
89
|
+
const iconButton = (
|
|
90
|
+
<button
|
|
91
|
+
type="button"
|
|
92
|
+
className={`calendar-input__icon-button ${iconBGFull ? " calendar-input__icon-button--full-bg" : ""} calendar-input__icon-button--${iconPosition}`}
|
|
93
|
+
onClick={handleCalendarClick}
|
|
94
|
+
disabled={disabled}
|
|
95
|
+
aria-label="Open calendar picker"
|
|
96
|
+
title="Select date"
|
|
97
|
+
>
|
|
98
|
+
<Icon name="calendar" size="sm" className="calendar-input__icon" />
|
|
99
|
+
</button>
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
return (
|
|
103
|
+
<div
|
|
104
|
+
className={`calendar-input calendar-input--${displayState} calendar-input--icon-${iconPosition} ${className}`.trim()}
|
|
105
|
+
data-node-id="3425:11289"
|
|
106
|
+
onClick={onClick}
|
|
107
|
+
>
|
|
108
|
+
{iconPosition === "left" && iconButton}
|
|
109
|
+
|
|
110
|
+
<div className="calendar-input__input-wrapper">
|
|
111
|
+
<input
|
|
112
|
+
type="text"
|
|
113
|
+
className="calendar-input__field"
|
|
114
|
+
placeholder={placeholder}
|
|
115
|
+
value={localValue || placeholder}
|
|
116
|
+
disabled={disabled}
|
|
117
|
+
onChange={handleInputChange}
|
|
118
|
+
onFocus={handleFocus}
|
|
119
|
+
onBlur={handleBlur}
|
|
120
|
+
readOnly={true}
|
|
121
|
+
aria-label={"Select date"}
|
|
122
|
+
/>
|
|
123
|
+
{iconPosition === "left" && showChevron && (
|
|
124
|
+
<div className={`calendar-input__chevron ${isOpen ? 'calendar-input__chevron--open' : ''}`}>
|
|
125
|
+
<Icon name={"chevron-down"} size="sm" />
|
|
126
|
+
</div>
|
|
127
|
+
)}
|
|
128
|
+
</div>
|
|
129
|
+
|
|
130
|
+
{iconPosition === "right" && iconButton}
|
|
131
|
+
</div>
|
|
132
|
+
);
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
export default CalendarInput;
|