mautourco-components 0.2.4 → 0.2.7

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.
Files changed (297) hide show
  1. package/README.md +190 -190
  2. package/dist/components/atoms/Avatar/Avatar.d.ts +14 -14
  3. package/dist/components/atoms/Avatar/Avatar.js +31 -31
  4. package/dist/components/atoms/Button/Button.css +320 -320
  5. package/dist/components/atoms/Button/Button.d.ts +27 -27
  6. package/dist/components/atoms/Button/Button.js +35 -35
  7. package/dist/components/atoms/Checkbox/Checkbox.d.ts +13 -13
  8. package/dist/components/atoms/Checkbox/Checkbox.js +39 -39
  9. package/dist/components/atoms/Icon/Icon.d.ts +10 -10
  10. package/dist/components/atoms/Icon/Icon.js +123 -123
  11. package/dist/components/atoms/Icon/icons/ArrivalIcon.d.ts +8 -8
  12. package/dist/components/atoms/Icon/icons/ArrivalIcon.js +31 -31
  13. package/dist/components/atoms/Icon/icons/BuildingIcon.d.ts +8 -8
  14. package/dist/components/atoms/Icon/icons/BuildingIcon.js +36 -36
  15. package/dist/components/atoms/Icon/icons/CalendarIcon.d.ts +12 -12
  16. package/dist/components/atoms/Icon/icons/CalendarIcon.js +41 -41
  17. package/dist/components/atoms/Icon/icons/CalendarOutlineIcon.d.ts +8 -8
  18. package/dist/components/atoms/Icon/icons/CalendarOutlineIcon.js +36 -36
  19. package/dist/components/atoms/Icon/icons/CarIcon.d.ts +8 -8
  20. package/dist/components/atoms/Icon/icons/CarIcon.js +30 -30
  21. package/dist/components/atoms/Icon/icons/Check.d.ts +8 -8
  22. package/dist/components/atoms/Icon/icons/Check.js +30 -30
  23. package/dist/components/atoms/Icon/icons/CheckCircleIcon.d.ts +8 -8
  24. package/dist/components/atoms/Icon/icons/CheckCircleIcon.js +30 -30
  25. package/dist/components/atoms/Icon/icons/Chevron.d.ts +9 -9
  26. package/dist/components/atoms/Icon/icons/Chevron.js +54 -54
  27. package/dist/components/atoms/Icon/icons/ChevronDownIcon.d.ts +8 -8
  28. package/dist/components/atoms/Icon/icons/ChevronDownIcon.js +30 -30
  29. package/dist/components/atoms/Icon/icons/Close.d.ts +8 -8
  30. package/dist/components/atoms/Icon/icons/Close.js +30 -30
  31. package/dist/components/atoms/Icon/icons/DeleteIcon.d.ts +8 -8
  32. package/dist/components/atoms/Icon/icons/DeleteIcon.js +30 -30
  33. package/dist/components/atoms/Icon/icons/DepartureIcon.d.ts +8 -8
  34. package/dist/components/atoms/Icon/icons/DepartureIcon.js +30 -30
  35. package/dist/components/atoms/Icon/icons/EyeIcon.d.ts +8 -8
  36. package/dist/components/atoms/Icon/icons/EyeIcon.js +30 -30
  37. package/dist/components/atoms/Icon/icons/FacebookIcon.d.ts +8 -8
  38. package/dist/components/atoms/Icon/icons/FacebookIcon.js +36 -36
  39. package/dist/components/atoms/Icon/icons/HomeIcon.d.ts +8 -8
  40. package/dist/components/atoms/Icon/icons/HomeIcon.js +25 -25
  41. package/dist/components/atoms/Icon/icons/InfoIcon.d.ts +8 -8
  42. package/dist/components/atoms/Icon/icons/InfoIcon.js +30 -30
  43. package/dist/components/atoms/Icon/icons/LinkedInIcon.d.ts +8 -8
  44. package/dist/components/atoms/Icon/icons/LinkedInIcon.js +36 -36
  45. package/dist/components/atoms/Icon/icons/MapPinIcon.d.ts +8 -8
  46. package/dist/components/atoms/Icon/icons/MapPinIcon.js +30 -30
  47. package/dist/components/atoms/Icon/icons/MautoucoLogo.d.ts +8 -8
  48. package/dist/components/atoms/Icon/icons/MautoucoLogo.js +37 -37
  49. package/dist/components/atoms/Icon/icons/MenuIcon.d.ts +8 -8
  50. package/dist/components/atoms/Icon/icons/MenuIcon.js +37 -37
  51. package/dist/components/atoms/Icon/icons/MinusIcon.d.ts +8 -8
  52. package/dist/components/atoms/Icon/icons/MinusIcon.js +25 -25
  53. package/dist/components/atoms/Icon/icons/MoreIcon.d.ts +8 -8
  54. package/dist/components/atoms/Icon/icons/MoreIcon.js +30 -30
  55. package/dist/components/atoms/Icon/icons/PlaneIcon.d.ts +8 -8
  56. package/dist/components/atoms/Icon/icons/PlaneIcon.js +36 -36
  57. package/dist/components/atoms/Icon/icons/PlusIcon.d.ts +8 -8
  58. package/dist/components/atoms/Icon/icons/PlusIcon.js +25 -25
  59. package/dist/components/atoms/Icon/icons/Search.d.ts +8 -8
  60. package/dist/components/atoms/Icon/icons/Search.js +30 -30
  61. package/dist/components/atoms/Icon/icons/Settings.d.ts +8 -8
  62. package/dist/components/atoms/Icon/icons/Settings.js +30 -30
  63. package/dist/components/atoms/Icon/icons/ShipIcon.d.ts +8 -8
  64. package/dist/components/atoms/Icon/icons/ShipIcon.js +36 -36
  65. package/dist/components/atoms/Icon/icons/StrollerIcon.d.ts +8 -8
  66. package/dist/components/atoms/Icon/icons/StrollerIcon.js +30 -30
  67. package/dist/components/atoms/Icon/icons/TwitterIcon.d.ts +8 -8
  68. package/dist/components/atoms/Icon/icons/TwitterIcon.js +36 -36
  69. package/dist/components/atoms/Icon/icons/User.d.ts +8 -8
  70. package/dist/components/atoms/Icon/icons/User.js +30 -30
  71. package/dist/components/atoms/Icon/icons/UserIcon.d.ts +12 -12
  72. package/dist/components/atoms/Icon/icons/UserIcon.js +41 -41
  73. package/dist/components/atoms/Icon/icons/Youtube.d.ts +8 -8
  74. package/dist/components/atoms/Icon/icons/Youtube.js +36 -36
  75. package/dist/components/atoms/Illustration/Illustration.d.ts +14 -14
  76. package/dist/components/atoms/Illustration/Illustration.js +33 -33
  77. package/dist/components/atoms/Illustration/illustrations.d.ts +51 -51
  78. package/dist/components/atoms/Illustration/illustrations.js +97 -97
  79. package/dist/components/atoms/Inputs/DropdownInput/DropdownInput.d.ts +12 -12
  80. package/dist/components/atoms/Inputs/DropdownInput/DropdownInput.js +53 -53
  81. package/dist/components/atoms/Inputs/Input/Input.d.ts +15 -15
  82. package/dist/components/atoms/Inputs/Input/Input.js +27 -27
  83. package/dist/components/atoms/Inputs/Textarea/Textarea.d.ts +14 -14
  84. package/dist/components/atoms/Inputs/Textarea/Textarea.js +15 -15
  85. package/dist/components/atoms/Link/Link.d.ts +44 -44
  86. package/dist/components/atoms/Link/Link.js +76 -76
  87. package/dist/components/atoms/RatingStar/RatingStar.d.ts +40 -40
  88. package/dist/components/atoms/RatingStar/RatingStar.js +54 -54
  89. package/dist/components/atoms/SegmentedButton/SegmentedButton.d.ts +27 -27
  90. package/dist/components/atoms/SegmentedButton/SegmentedButton.js +49 -49
  91. package/dist/components/atoms/SelectedValue/SelectedValue.d.ts +11 -11
  92. package/dist/components/atoms/SelectedValue/SelectedValue.js +29 -29
  93. package/dist/components/atoms/Slider/Slider.d.ts +52 -52
  94. package/dist/components/atoms/Slider/Slider.js +30 -30
  95. package/dist/components/atoms/Spinner/Spinner.d.ts +9 -9
  96. package/dist/components/atoms/Spinner/Spinner.js +38 -38
  97. package/dist/components/atoms/Spinner/variants/ButtonSpinner.d.ts +8 -8
  98. package/dist/components/atoms/Spinner/variants/ButtonSpinner.js +19 -19
  99. package/dist/components/atoms/Spinner/variants/LoadingSpinner.d.ts +7 -7
  100. package/dist/components/atoms/Spinner/variants/LoadingSpinner.js +7 -7
  101. package/dist/components/atoms/Tab/Tab.css +266 -266
  102. package/dist/components/atoms/Tab/Tab.d.ts +22 -22
  103. package/dist/components/atoms/Tab/Tab.js +54 -54
  104. package/dist/components/atoms/Typography/Typography.d.ts +24 -24
  105. package/dist/components/atoms/Typography/Typography.js +100 -100
  106. package/dist/components/molecules/Calendar/CalendarInput.d.ts +34 -34
  107. package/dist/components/molecules/Calendar/CalendarInput.js +49 -49
  108. package/dist/components/molecules/Calendar/DateTime.d.ts +25 -25
  109. package/dist/components/molecules/Calendar/DateTime.js +106 -106
  110. package/dist/components/molecules/Calendar/TimePicker.d.ts +16 -16
  111. package/dist/components/molecules/Calendar/TimePicker.js +91 -91
  112. package/dist/components/molecules/LocationDropdown/LocationDropdown.d.ts +34 -34
  113. package/dist/components/molecules/LocationDropdown/LocationDropdown.js +120 -120
  114. package/dist/components/molecules/LocationDropdown/index.d.ts +2 -2
  115. package/dist/components/molecules/LocationDropdown/index.js +1 -1
  116. package/dist/components/molecules/MultiSelectDropdown/MultiSelectDropdown.d.ts +29 -29
  117. package/dist/components/molecules/MultiSelectDropdown/MultiSelectDropdown.js +106 -106
  118. package/dist/components/molecules/RatingTab/RatingTab.d.ts +39 -39
  119. package/dist/components/molecules/RatingTab/RatingTab.js +41 -41
  120. package/dist/components/molecules/TabGroup/TabGroup.d.ts +17 -17
  121. package/dist/components/molecules/TabGroup/TabGroup.js +30 -30
  122. package/dist/components/molecules/UserCard/UserCard.d.ts +20 -20
  123. package/dist/components/molecules/UserCard/UserCard.js +57 -57
  124. package/dist/components/organisms/CardContainer/CardContainer.d.ts +37 -37
  125. package/dist/components/organisms/CardContainer/CardContainer.js +27 -27
  126. package/dist/components/organisms/DateTimePicker/DateTimePicker.d.ts +15 -15
  127. package/dist/components/organisms/DateTimePicker/DateTimePicker.js +66 -66
  128. package/dist/components/organisms/Dialog/Dialog.d.ts +103 -103
  129. package/dist/components/organisms/Dialog/Dialog.js +162 -162
  130. package/dist/components/organisms/Footer/Footer.d.ts +38 -38
  131. package/dist/components/organisms/Footer/Footer.js +74 -74
  132. package/dist/components/organisms/PaxSelector/PaxSelector.d.ts +63 -63
  133. package/dist/components/organisms/PaxSelector/PaxSelector.js +402 -402
  134. package/dist/components/organisms/RoundTrip/RoundTrip.d.ts +54 -54
  135. package/dist/components/organisms/RoundTrip/RoundTrip.js +179 -179
  136. package/dist/components/organisms/RoundTrip/index.d.ts +2 -2
  137. package/dist/components/organisms/RoundTrip/index.js +1 -1
  138. package/dist/components/organisms/SearchBarTransfer/SearchBarTransfer.d.ts +35 -35
  139. package/dist/components/organisms/SearchBarTransfer/SearchBarTransfer.js +192 -192
  140. package/dist/components/organisms/SearchBarTransfer/index.d.ts +2 -2
  141. package/dist/components/organisms/SearchBarTransfer/index.js +1 -1
  142. package/dist/components/organisms/TopNavigation/DesktopNav.d.ts +33 -33
  143. package/dist/components/organisms/TopNavigation/DesktopNav.js +32 -26
  144. package/dist/components/organisms/TopNavigation/MobileNav.d.ts +32 -32
  145. package/dist/components/organisms/TopNavigation/MobileNav.js +45 -45
  146. package/dist/components/organisms/TopNavigation/TopNavigation.d.ts +33 -33
  147. package/dist/components/organisms/TopNavigation/TopNavigation.js +20 -20
  148. package/dist/components/organisms/TransferLine/TransferLine.d.ts +53 -53
  149. package/dist/components/organisms/TransferLine/TransferLine.js +179 -179
  150. package/dist/components/ui/button.d.ts +10 -10
  151. package/dist/components/ui/button.js +56 -56
  152. package/dist/components/ui/calendar.d.ts +8 -8
  153. package/dist/components/ui/calendar.js +87 -87
  154. package/dist/components/ui/popover.d.ts +7 -7
  155. package/dist/components/ui/popover.js +42 -42
  156. package/dist/hooks/useMobile.d.ts +5 -5
  157. package/dist/hooks/useMobile.js +26 -26
  158. package/dist/index.d.ts +49 -49
  159. package/dist/index.js +46 -46
  160. package/dist/lib/utils.d.ts +7 -7
  161. package/dist/lib/utils.js +13 -13
  162. package/dist/styles/components/avatar.css +122 -122
  163. package/dist/styles/components/calendar.css +140 -140
  164. package/dist/styles/components/checkbox.css +206 -206
  165. package/dist/styles/components/dropdown.css +269 -269
  166. package/dist/styles/components/forms.css +209 -209
  167. package/dist/styles/components/illustration.css +123 -123
  168. package/dist/styles/components/molecule/calendarInput.css +133 -133
  169. package/dist/styles/components/molecule/dateTime.css +126 -126
  170. package/dist/styles/components/molecule/location-dropdown.css +132 -132
  171. package/dist/styles/components/molecule/timePicker.css +122 -122
  172. package/dist/styles/components/multiselect-dropdown.css +286 -286
  173. package/dist/styles/components/organism/card-container.css +148 -148
  174. package/dist/styles/components/organism/dialog.css +168 -168
  175. package/dist/styles/components/organism/footer.css +119 -119
  176. package/dist/styles/components/organism/pax-selector.css +617 -617
  177. package/dist/styles/components/organism/round-trip.css +139 -139
  178. package/dist/styles/components/organism/search-bar-transfer.css +158 -161
  179. package/dist/styles/components/organism/topnavigation.css +143 -143
  180. package/dist/styles/components/organism/transfer-line.css +138 -138
  181. package/dist/styles/components/rating-star.css +145 -145
  182. package/dist/styles/components/rating-tab.css +179 -179
  183. package/dist/styles/components/scrollbar.css +155 -155
  184. package/dist/styles/components/segmented-button.css +214 -214
  185. package/dist/styles/components/selected-value.css +175 -175
  186. package/dist/styles/components/slider.css +182 -182
  187. package/dist/styles/components/typography.css +245 -245
  188. package/dist/styles/tokens/tokens.css +119 -119
  189. package/dist/styles/tokens/tokens.d.ts +3108 -3108
  190. package/dist/styles/tokens/tokens.js +2652 -2652
  191. package/package.json +103 -103
  192. package/src/components/atoms/Avatar/Avatar.tsx +60 -60
  193. package/src/components/atoms/Button/Button.css +200 -200
  194. package/src/components/atoms/Button/Button.tsx +82 -82
  195. package/src/components/atoms/Checkbox/Checkbox.tsx +83 -83
  196. package/src/components/atoms/Icon/Icon.tsx +163 -163
  197. package/src/components/atoms/Icon/icons/ArrivalIcon.tsx +52 -52
  198. package/src/components/atoms/Icon/icons/BuildingIcon.tsx +50 -50
  199. package/src/components/atoms/Icon/icons/CalendarIcon.tsx +63 -63
  200. package/src/components/atoms/Icon/icons/CalendarOutlineIcon.tsx +50 -50
  201. package/src/components/atoms/Icon/icons/CarIcon.tsx +44 -44
  202. package/src/components/atoms/Icon/icons/Check.tsx +36 -36
  203. package/src/components/atoms/Icon/icons/CheckCircleIcon.tsx +48 -48
  204. package/src/components/atoms/Icon/icons/Chevron.tsx +73 -73
  205. package/src/components/atoms/Icon/icons/ChevronDownIcon.tsx +46 -46
  206. package/src/components/atoms/Icon/icons/Close.tsx +39 -39
  207. package/src/components/atoms/Icon/icons/DeleteIcon.tsx +44 -44
  208. package/src/components/atoms/Icon/icons/DepartureIcon.tsx +50 -50
  209. package/src/components/atoms/Icon/icons/EyeIcon.tsx +44 -44
  210. package/src/components/atoms/Icon/icons/FacebookIcon.tsx +50 -50
  211. package/src/components/atoms/Icon/icons/HomeIcon.tsx +52 -52
  212. package/src/components/atoms/Icon/icons/InfoIcon.tsx +44 -44
  213. package/src/components/atoms/Icon/icons/LinkedInIcon.tsx +50 -50
  214. package/src/components/atoms/Icon/icons/MapPinIcon.tsx +44 -44
  215. package/src/components/atoms/Icon/icons/MautoucoLogo.tsx +93 -93
  216. package/src/components/atoms/Icon/icons/MenuIcon.tsx +49 -49
  217. package/src/components/atoms/Icon/icons/MinusIcon.tsx +45 -45
  218. package/src/components/atoms/Icon/icons/MoreIcon.tsx +44 -44
  219. package/src/components/atoms/Icon/icons/PlaneIcon.tsx +50 -50
  220. package/src/components/atoms/Icon/icons/PlusIcon.tsx +45 -45
  221. package/src/components/atoms/Icon/icons/Search.tsx +37 -37
  222. package/src/components/atoms/Icon/icons/Settings.tsx +38 -38
  223. package/src/components/atoms/Icon/icons/ShipIcon.tsx +50 -50
  224. package/src/components/atoms/Icon/icons/StrollerIcon.tsx +44 -44
  225. package/src/components/atoms/Icon/icons/TwitterIcon.tsx +50 -50
  226. package/src/components/atoms/Icon/icons/User.tsx +37 -37
  227. package/src/components/atoms/Icon/icons/UserIcon.tsx +63 -63
  228. package/src/components/atoms/Icon/icons/Youtube.tsx +50 -50
  229. package/src/components/atoms/Illustration/Illustration.tsx +28 -28
  230. package/src/components/atoms/Illustration/illustrations.ts +116 -116
  231. package/src/components/atoms/Inputs/DropdownInput/DropdownInput.tsx +96 -96
  232. package/src/components/atoms/Inputs/Textarea/Textarea.tsx +51 -51
  233. package/src/components/atoms/Link/Link.tsx +168 -168
  234. package/src/components/atoms/RatingStar/RatingStar.tsx +114 -114
  235. package/src/components/atoms/SegmentedButton/SegmentedButton.tsx +94 -94
  236. package/src/components/atoms/SelectedValue/SelectedValue.tsx +59 -59
  237. package/src/components/atoms/Slider/Slider.tsx +95 -95
  238. package/src/components/atoms/Spinner/Spinner.tsx +56 -56
  239. package/src/components/atoms/Spinner/variants/ButtonSpinner.tsx +37 -37
  240. package/src/components/atoms/Spinner/variants/LoadingSpinner.tsx +22 -22
  241. package/src/components/atoms/Tab/Tab.css +147 -147
  242. package/src/components/atoms/Tab/Tab.tsx +96 -96
  243. package/src/components/atoms/Typography/Typography.tsx +153 -153
  244. package/src/components/molecules/Calendar/CalendarInput.tsx +135 -135
  245. package/src/components/molecules/Calendar/DateTime.tsx +172 -172
  246. package/src/components/molecules/Calendar/TimePicker.tsx +174 -174
  247. package/src/components/molecules/LocationDropdown/LocationDropdown.tsx +234 -234
  248. package/src/components/molecules/LocationDropdown/index.ts +2 -2
  249. package/src/components/molecules/RatingTab/RatingTab.tsx +96 -96
  250. package/src/components/molecules/TabGroup/TabGroup.tsx +60 -60
  251. package/src/components/molecules/UserCard/UserCard.stories.tsx +36 -36
  252. package/src/components/molecules/UserCard/UserCard.tsx +173 -173
  253. package/src/components/organisms/CardContainer/CardContainer.tsx +66 -66
  254. package/src/components/organisms/DateTimePicker/DateTimePicker.tsx +110 -110
  255. package/src/components/organisms/Dialog/Dialog.tsx +352 -352
  256. package/src/components/organisms/Footer/Footer.tsx +290 -290
  257. package/src/components/organisms/PaxSelector/PaxSelector.tsx +979 -979
  258. package/src/components/organisms/RoundTrip/RoundTrip.tsx +335 -335
  259. package/src/components/organisms/RoundTrip/index.ts +2 -2
  260. package/src/components/organisms/SearchBarTransfer/SearchBarTransfer.tsx +388 -388
  261. package/src/components/organisms/SearchBarTransfer/index.ts +2 -2
  262. package/src/components/organisms/TopNavigation/DesktopNav.tsx +133 -122
  263. package/src/components/organisms/TopNavigation/MobileNav.tsx +212 -212
  264. package/src/components/organisms/TopNavigation/TopNavigation.tsx +45 -45
  265. package/src/components/organisms/TransferLine/TransferLine.tsx +369 -369
  266. package/src/components/ui/button.tsx +60 -60
  267. package/src/components/ui/calendar.tsx +246 -246
  268. package/src/components/ui/popover.tsx +46 -46
  269. package/src/styles/components/avatar.css +58 -58
  270. package/src/styles/components/calendar.css +85 -85
  271. package/src/styles/components/checkbox.css +130 -130
  272. package/src/styles/components/dropdown.css +214 -214
  273. package/src/styles/components/forms.css +147 -147
  274. package/src/styles/components/illustration.css +7 -7
  275. package/src/styles/components/molecule/calendarInput.css +156 -156
  276. package/src/styles/components/molecule/dateTime.css +14 -14
  277. package/src/styles/components/molecule/location-dropdown.css +204 -204
  278. package/src/styles/components/molecule/timePicker.css +78 -78
  279. package/src/styles/components/multiselect-dropdown.css +230 -230
  280. package/src/styles/components/organism/card-container.css +49 -49
  281. package/src/styles/components/organism/dialog.css +241 -241
  282. package/src/styles/components/organism/footer.css +113 -113
  283. package/src/styles/components/organism/pax-selector.css +702 -702
  284. package/src/styles/components/organism/round-trip.css +55 -55
  285. package/src/styles/components/organism/search-bar-transfer.css +128 -127
  286. package/src/styles/components/organism/topnavigation.css +161 -161
  287. package/src/styles/components/organism/transfer-line.css +86 -86
  288. package/src/styles/components/rating-star.css +39 -39
  289. package/src/styles/components/rating-tab.css +83 -83
  290. package/src/styles/components/scrollbar.css +63 -63
  291. package/src/styles/components/segmented-button.css +134 -134
  292. package/src/styles/components/selected-value.css +80 -80
  293. package/src/styles/components/slider.css +86 -86
  294. package/src/styles/components/typography.css +251 -251
  295. package/src/styles/fonts.css +50 -0
  296. package/src/styles/tokens/tokens.css +119 -119
  297. package/src/styles/tokens/tokens.js +12 -6
@@ -1,60 +1,60 @@
1
- import React from 'react';
2
- import Tab, { TabProps } from '../../atoms/Tab/Tab';
3
-
4
- export type TabItem<T = string> = {
5
- label: string;
6
- value: T;
7
- disabled?: boolean;
8
- };
9
-
10
- export interface TabGroupProps<T = string> {
11
- items: TabItem<T>[];
12
- size?: TabProps['size'];
13
- variant?: TabProps['variant'];
14
- active?: T;
15
- defaultActive?: T;
16
- onChange?: (value: T) => void;
17
- className?: string;
18
- }
19
-
20
- export function TabGroup<T = string>({
21
- items,
22
- size = 'lg',
23
- variant = 'inline',
24
- active,
25
- defaultActive,
26
- onChange,
27
- className = '',
28
- }: TabGroupProps<T>) {
29
- const [internalActive, setInternalActive] = React.useState<T | undefined>(
30
- defaultActive ?? items[0]?.value
31
- );
32
-
33
- const isControlled = active !== undefined;
34
- const current = (isControlled ? active : internalActive) as T | undefined;
35
-
36
- const handleClick = (item: TabItem<T>) => {
37
- if (item.disabled) return;
38
- if (!isControlled) setInternalActive(item.value);
39
- onChange?.(item.value);
40
- };
41
-
42
- return (
43
- <div className={`tab-group flex ${className}`} role="tablist">
44
- {items.map((it) => (
45
- <Tab
46
- key={String(it.value)}
47
- isActive={current === it.value}
48
- size={size}
49
- variant={variant}
50
- disabled={it.disabled}
51
- onClick={() => handleClick(it)}
52
- >
53
- {it.label}
54
- </Tab>
55
- ))}
56
- </div>
57
- );
58
- }
59
-
60
- export default TabGroup;
1
+ import React from 'react';
2
+ import Tab, { TabProps } from '../../atoms/Tab/Tab';
3
+
4
+ export type TabItem<T = string> = {
5
+ label: string;
6
+ value: T;
7
+ disabled?: boolean;
8
+ };
9
+
10
+ export interface TabGroupProps<T = string> {
11
+ items: TabItem<T>[];
12
+ size?: TabProps['size'];
13
+ variant?: TabProps['variant'];
14
+ active?: T;
15
+ defaultActive?: T;
16
+ onChange?: (value: T) => void;
17
+ className?: string;
18
+ }
19
+
20
+ export function TabGroup<T = string>({
21
+ items,
22
+ size = 'lg',
23
+ variant = 'inline',
24
+ active,
25
+ defaultActive,
26
+ onChange,
27
+ className = '',
28
+ }: TabGroupProps<T>) {
29
+ const [internalActive, setInternalActive] = React.useState<T | undefined>(
30
+ defaultActive ?? items[0]?.value
31
+ );
32
+
33
+ const isControlled = active !== undefined;
34
+ const current = (isControlled ? active : internalActive) as T | undefined;
35
+
36
+ const handleClick = (item: TabItem<T>) => {
37
+ if (item.disabled) return;
38
+ if (!isControlled) setInternalActive(item.value);
39
+ onChange?.(item.value);
40
+ };
41
+
42
+ return (
43
+ <div className={`tab-group flex ${className}`} role="tablist">
44
+ {items.map((it) => (
45
+ <Tab
46
+ key={String(it.value)}
47
+ isActive={current === it.value}
48
+ size={size}
49
+ variant={variant}
50
+ disabled={it.disabled}
51
+ onClick={() => handleClick(it)}
52
+ >
53
+ {it.label}
54
+ </Tab>
55
+ ))}
56
+ </div>
57
+ );
58
+ }
59
+
60
+ export default TabGroup;
@@ -1,36 +1,36 @@
1
- import type { Meta, StoryObj } from '@storybook/react-vite';
2
-
3
- import { UserCard } from './UserCard';
4
-
5
- const meta = {
6
- title: 'Molecules/UserCard',
7
- component: UserCard,
8
- argTypes: {
9
- onSelectAgency: { action: 'agency selected' },
10
- }
11
- } satisfies Meta<typeof UserCard>;
12
-
13
- export default meta;
14
-
15
- type Story = StoryObj<typeof meta>;
16
-
17
- export const Default: Story = {
18
- args:{
19
- user: {
20
- name: "John Doe",
21
- agency: "Beachcomber SA",
22
- isAdmin: true,
23
- },
24
- agencies: [
25
- { id: 1, name: "Beachcomber SA", localisation: "Mauritius" },
26
- { id: 2, name: "Sun Resorts", localisation: "Maldives" },
27
- { id: 3, name: "Tropical Escapes", localisation: "Seychelles" },
28
- ],
29
- selectedAgency: { id: 1, name: "Beachcomber SA", localisation: "Mauritius" },
30
- },
31
- render: (args) => (
32
- <div className='flex justify-center w-full'>
33
- <UserCard {...args} />
34
- </div>
35
- ),
36
- };
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+
3
+ import { UserCard } from './UserCard';
4
+
5
+ const meta = {
6
+ title: 'Molecules/UserCard',
7
+ component: UserCard,
8
+ argTypes: {
9
+ onSelectAgency: { action: 'agency selected' },
10
+ }
11
+ } satisfies Meta<typeof UserCard>;
12
+
13
+ export default meta;
14
+
15
+ type Story = StoryObj<typeof meta>;
16
+
17
+ export const Default: Story = {
18
+ args:{
19
+ user: {
20
+ name: "John Doe",
21
+ agency: "Beachcomber SA",
22
+ isAdmin: true,
23
+ },
24
+ agencies: [
25
+ { id: 1, name: "Beachcomber SA", localisation: "Mauritius" },
26
+ { id: 2, name: "Sun Resorts", localisation: "Maldives" },
27
+ { id: 3, name: "Tropical Escapes", localisation: "Seychelles" },
28
+ ],
29
+ selectedAgency: { id: 1, name: "Beachcomber SA", localisation: "Mauritius" },
30
+ },
31
+ render: (args) => (
32
+ <div className='flex justify-center w-full'>
33
+ <UserCard {...args} />
34
+ </div>
35
+ ),
36
+ };
@@ -1,173 +1,173 @@
1
- import React, { useEffect, useMemo, useRef, useState } from "react";
2
- import { Avatar } from "../../atoms/Avatar/Avatar";
3
-
4
- type User = {
5
- name: string;
6
- agency: string;
7
- isAdmin: boolean;
8
- };
9
-
10
- type Agency = {
11
- id: number;
12
- name: string;
13
- localisation: string;
14
- };
15
-
16
- export interface UserCardProps {
17
- user: User;
18
- agencies: Agency[];
19
- onSelectAgency?: (agency: Agency) => void;
20
- selectedAgency?: Agency; // ✅ keep type as Agency
21
- className?: string;
22
- }
23
-
24
- export const UserCard: React.FC<UserCardProps> = ({
25
- user,
26
- agencies,
27
- onSelectAgency,
28
- selectedAgency,
29
- className = "",
30
- }) => {
31
- const [open, setOpen] = useState(false);
32
- const [query, setQuery] = useState("");
33
- const rootRef = useRef<HTMLDivElement>(null);
34
- const searchRef = useRef<HTMLInputElement>(null);
35
-
36
- // Close dropdown on outside click
37
- useEffect(() => {
38
- if (!user.isAdmin || !open) return;
39
- const handleClickOutside = (e: MouseEvent) => {
40
- if (!rootRef.current?.contains(e.target as Node)) setOpen(false);
41
- };
42
- document.addEventListener("mousedown", handleClickOutside);
43
- return () => document.removeEventListener("mousedown", handleClickOutside);
44
- }, [open, user.isAdmin]);
45
-
46
- // Auto-focus search input when dropdown opens
47
- useEffect(() => {
48
- if (user.isAdmin && open) setTimeout(() => searchRef.current?.focus(), 0);
49
- }, [open, user.isAdmin]);
50
-
51
- // Filter agencies based on query
52
- const filteredAgencies = useMemo(() => {
53
- const q = query.trim().toLowerCase();
54
- if (!q) return agencies;
55
- return agencies.filter(
56
- (a) =>
57
- a.name.toLowerCase().includes(q) ||
58
- a.localisation.toLowerCase().includes(q)
59
- );
60
- }, [agencies, query]);
61
-
62
- const handleSelect = (a: Agency) => {
63
- onSelectAgency?.(a);
64
- setOpen(false);
65
- setQuery("");
66
- };
67
-
68
- return (
69
- <div ref={rootRef} className={`relative inline-flex items-center gap-3 ${className} ${user.isAdmin ? "cursor-pointer rounded-[11px] border border-[#D9D9D9] bg-white px-[13px] py-2" : ""}`}>
70
- {/* Greeting */}
71
- <div className="flex items-center gap-3">
72
- <Avatar name={user.name} size="md" shape="circle" />
73
- <div className="flex flex-col leading-tight">
74
- <div className="text-[13px] text-muted-foreground">
75
- Welcome back,{" "}
76
- <span className="font-medium text-foreground">{user.name}</span>{" "}
77
- <span aria-hidden>👋</span>
78
- </div>
79
- <div className="text-[13px] font-semibold text-foreground">
80
- {selectedAgency ? selectedAgency.name : user.agency}
81
- </div>
82
- </div>
83
- </div>
84
-
85
- {/* Admin-only: Dropdown selector */}
86
- {user.isAdmin && (
87
- <>
88
- <button
89
- type="button"
90
- aria-expanded={open}
91
- aria-haspopup="listbox"
92
- onClick={() => setOpen((v) => !v)}
93
- className="inline-flex h-8 w-8 items-center justify-center rounded-lg bg-teal-600 text-white shadow-[0_2px_6px_rgba(0,0,0,0.15)] outline-none focus-visible:ring-2 focus-visible:ring-teal-300"
94
- title="Open agency selector"
95
- >
96
- <svg
97
- width="18"
98
- height="18"
99
- viewBox="0 0 24 24"
100
- aria-hidden="true"
101
- className={`transition-transform ${open ? "rotate-180" : ""}`}
102
- >
103
- <path
104
- d="M6 9l6 6 6-6"
105
- fill="none"
106
- stroke="currentColor"
107
- strokeWidth="2"
108
- strokeLinecap="round"
109
- strokeLinejoin="round"
110
- />
111
- </svg>
112
- </button>
113
-
114
- {open && (
115
- <div className="absolute right-0 top-12 z-50 w-[340px] rounded-2xl border border-black/5 bg-white p-3 shadow-[0_12px_30px_rgba(0,0,0,0.15)]">
116
- {/* Search */}
117
- <div className="relative mb-3">
118
- <input
119
- ref={searchRef}
120
- value={query}
121
- onChange={(e) => setQuery(e.target.value)}
122
- placeholder="Search"
123
- className="w-full rounded-xl border border-black/10 bg-white px-10 py-2 text-sm outline-none focus:border-black/20 shadow-[inset_0_1px_2px_rgba(0,0,0,0.06)]"
124
- />
125
- <div className="absolute -translate-y-1/2 pointer-events-none left-3 top-1/2">
126
- <svg width="18" height="18" viewBox="0 0 24 24">
127
- <path
128
- d="M21 21l-4.3-4.3M10.5 18a7.5 7.5 0 1 1 0-15 7.5 7.5 0 0 1 0 15z"
129
- fill="none"
130
- stroke="currentColor"
131
- strokeWidth="1.6"
132
- strokeLinecap="round"
133
- />
134
- </svg>
135
- </div>
136
- </div>
137
-
138
- {/* Agency List */}
139
- <ul role="listbox" className="pr-1 overflow-auto max-h-64">
140
- {filteredAgencies.map((a) => {
141
- const isActive = selectedAgency?.id === a.id;
142
- return (
143
- <li key={a.id}>
144
- <button
145
- type="button"
146
- onClick={() => handleSelect(a)}
147
- className={`flex w-full items-center justify-between gap-3 rounded-lg px-2 py-2 text-left hover:bg-black/5 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-teal-300 ${
148
- isActive ? "bg-black/[0.04]" : ""
149
- }`}
150
- aria-selected={isActive}
151
- role="option"
152
- >
153
- <span className="text-[14px]">{a.name}</span>
154
- <span className="text-[13px] font-semibold">
155
- {a.localisation}
156
- </span>
157
- </button>
158
- </li>
159
- );
160
- })}
161
- {filteredAgencies.length === 0 && (
162
- <li className="px-2 py-6 text-sm text-center text-muted-foreground">
163
- No results
164
- </li>
165
- )}
166
- </ul>
167
- </div>
168
- )}
169
- </>
170
- )}
171
- </div>
172
- );
173
- };
1
+ import React, { useEffect, useMemo, useRef, useState } from "react";
2
+ import { Avatar } from "../../atoms/Avatar/Avatar";
3
+
4
+ type User = {
5
+ name: string;
6
+ agency: string;
7
+ isAdmin: boolean;
8
+ };
9
+
10
+ type Agency = {
11
+ id: number;
12
+ name: string;
13
+ localisation: string;
14
+ };
15
+
16
+ export interface UserCardProps {
17
+ user: User;
18
+ agencies: Agency[];
19
+ onSelectAgency?: (agency: Agency) => void;
20
+ selectedAgency?: Agency; // ✅ keep type as Agency
21
+ className?: string;
22
+ }
23
+
24
+ export const UserCard: React.FC<UserCardProps> = ({
25
+ user,
26
+ agencies,
27
+ onSelectAgency,
28
+ selectedAgency,
29
+ className = "",
30
+ }) => {
31
+ const [open, setOpen] = useState(false);
32
+ const [query, setQuery] = useState("");
33
+ const rootRef = useRef<HTMLDivElement>(null);
34
+ const searchRef = useRef<HTMLInputElement>(null);
35
+
36
+ // Close dropdown on outside click
37
+ useEffect(() => {
38
+ if (!user.isAdmin || !open) return;
39
+ const handleClickOutside = (e: MouseEvent) => {
40
+ if (!rootRef.current?.contains(e.target as Node)) setOpen(false);
41
+ };
42
+ document.addEventListener("mousedown", handleClickOutside);
43
+ return () => document.removeEventListener("mousedown", handleClickOutside);
44
+ }, [open, user.isAdmin]);
45
+
46
+ // Auto-focus search input when dropdown opens
47
+ useEffect(() => {
48
+ if (user.isAdmin && open) setTimeout(() => searchRef.current?.focus(), 0);
49
+ }, [open, user.isAdmin]);
50
+
51
+ // Filter agencies based on query
52
+ const filteredAgencies = useMemo(() => {
53
+ const q = query.trim().toLowerCase();
54
+ if (!q) return agencies;
55
+ return agencies.filter(
56
+ (a) =>
57
+ a.name.toLowerCase().includes(q) ||
58
+ a.localisation.toLowerCase().includes(q)
59
+ );
60
+ }, [agencies, query]);
61
+
62
+ const handleSelect = (a: Agency) => {
63
+ onSelectAgency?.(a);
64
+ setOpen(false);
65
+ setQuery("");
66
+ };
67
+
68
+ return (
69
+ <div ref={rootRef} className={`relative inline-flex items-center gap-3 ${className} ${user.isAdmin ? "cursor-pointer rounded-[11px] border border-[#D9D9D9] bg-white px-[13px] py-2" : ""}`}>
70
+ {/* Greeting */}
71
+ <div className="flex items-center gap-3">
72
+ <Avatar name={user.name} size="md" shape="circle" />
73
+ <div className="flex flex-col leading-tight">
74
+ <div className="text-[13px] text-muted-foreground">
75
+ Welcome back,{" "}
76
+ <span className="font-medium text-foreground">{user.name}</span>{" "}
77
+ <span aria-hidden>👋</span>
78
+ </div>
79
+ <div className="text-[13px] font-semibold text-foreground">
80
+ {selectedAgency ? selectedAgency.name : user.agency}
81
+ </div>
82
+ </div>
83
+ </div>
84
+
85
+ {/* Admin-only: Dropdown selector */}
86
+ {user.isAdmin && (
87
+ <>
88
+ <button
89
+ type="button"
90
+ aria-expanded={open}
91
+ aria-haspopup="listbox"
92
+ onClick={() => setOpen((v) => !v)}
93
+ className="inline-flex h-8 w-8 items-center justify-center rounded-lg bg-teal-600 text-white shadow-[0_2px_6px_rgba(0,0,0,0.15)] outline-none focus-visible:ring-2 focus-visible:ring-teal-300"
94
+ title="Open agency selector"
95
+ >
96
+ <svg
97
+ width="18"
98
+ height="18"
99
+ viewBox="0 0 24 24"
100
+ aria-hidden="true"
101
+ className={`transition-transform ${open ? "rotate-180" : ""}`}
102
+ >
103
+ <path
104
+ d="M6 9l6 6 6-6"
105
+ fill="none"
106
+ stroke="currentColor"
107
+ strokeWidth="2"
108
+ strokeLinecap="round"
109
+ strokeLinejoin="round"
110
+ />
111
+ </svg>
112
+ </button>
113
+
114
+ {open && (
115
+ <div className="absolute right-0 top-12 z-50 w-[340px] rounded-2xl border border-black/5 bg-white p-3 shadow-[0_12px_30px_rgba(0,0,0,0.15)]">
116
+ {/* Search */}
117
+ <div className="relative mb-3">
118
+ <input
119
+ ref={searchRef}
120
+ value={query}
121
+ onChange={(e) => setQuery(e.target.value)}
122
+ placeholder="Search"
123
+ className="w-full rounded-xl border border-black/10 bg-white px-10 py-2 text-sm outline-none focus:border-black/20 shadow-[inset_0_1px_2px_rgba(0,0,0,0.06)]"
124
+ />
125
+ <div className="absolute -translate-y-1/2 pointer-events-none left-3 top-1/2">
126
+ <svg width="18" height="18" viewBox="0 0 24 24">
127
+ <path
128
+ d="M21 21l-4.3-4.3M10.5 18a7.5 7.5 0 1 1 0-15 7.5 7.5 0 0 1 0 15z"
129
+ fill="none"
130
+ stroke="currentColor"
131
+ strokeWidth="1.6"
132
+ strokeLinecap="round"
133
+ />
134
+ </svg>
135
+ </div>
136
+ </div>
137
+
138
+ {/* Agency List */}
139
+ <ul role="listbox" className="pr-1 overflow-auto max-h-64">
140
+ {filteredAgencies.map((a) => {
141
+ const isActive = selectedAgency?.id === a.id;
142
+ return (
143
+ <li key={a.id}>
144
+ <button
145
+ type="button"
146
+ onClick={() => handleSelect(a)}
147
+ className={`flex w-full items-center justify-between gap-3 rounded-lg px-2 py-2 text-left hover:bg-black/5 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-teal-300 ${
148
+ isActive ? "bg-black/[0.04]" : ""
149
+ }`}
150
+ aria-selected={isActive}
151
+ role="option"
152
+ >
153
+ <span className="text-[14px]">{a.name}</span>
154
+ <span className="text-[13px] font-semibold">
155
+ {a.localisation}
156
+ </span>
157
+ </button>
158
+ </li>
159
+ );
160
+ })}
161
+ {filteredAgencies.length === 0 && (
162
+ <li className="px-2 py-6 text-sm text-center text-muted-foreground">
163
+ No results
164
+ </li>
165
+ )}
166
+ </ul>
167
+ </div>
168
+ )}
169
+ </>
170
+ )}
171
+ </div>
172
+ );
173
+ };
@@ -1,66 +1,66 @@
1
- import React from 'react';
2
-
3
- export type CardContainerSpacing = 'compact' | 'normal' | 'relaxed' | 'chill';
4
-
5
- export interface CardContainerProps {
6
- /**
7
- * The content to be displayed inside the card container
8
- */
9
- children: React.ReactNode;
10
-
11
- /**
12
- * Spacing variant for the card container padding
13
- * - compact: 8px padding
14
- * - normal: 12px padding
15
- * - relaxed: 16px padding
16
- * - chill: 24px padding
17
- */
18
- spacing?: CardContainerSpacing;
19
-
20
- /**
21
- * Additional CSS classes to apply to the card container
22
- */
23
- className?: string;
24
-
25
- /**
26
- * Optional click handler
27
- */
28
- onClick?: (e: React.MouseEvent<HTMLDivElement>) => void;
29
-
30
- /**
31
- * Optional data attributes for testing or tracking
32
- */
33
- 'data-testid'?: string;
34
- }
35
-
36
- /**
37
- * CardContainer is a versatile UI element that groups related content,
38
- * such as text, images, buttons, or interactive elements.
39
- *
40
- * It supports different spacing variants to control the visual density
41
- * and padding of the container.
42
- */
43
- export const CardContainer: React.FC<CardContainerProps> = ({
44
- children,
45
- spacing = 'normal',
46
- className = '',
47
- onClick,
48
- 'data-testid': testId,
49
- }) => {
50
- const baseClass = 'card-container';
51
- const spacingClass = `card-container--spacing-${spacing}`;
52
- const classes = [baseClass, spacingClass, className].filter(Boolean).join(' ');
53
-
54
- return (
55
- <div
56
- className={classes}
57
- onClick={onClick}
58
- data-testid={testId}
59
- >
60
- {children}
61
- </div>
62
- );
63
- };
64
-
65
- export default CardContainer;
66
-
1
+ import React from 'react';
2
+
3
+ export type CardContainerSpacing = 'compact' | 'normal' | 'relaxed' | 'chill';
4
+
5
+ export interface CardContainerProps {
6
+ /**
7
+ * The content to be displayed inside the card container
8
+ */
9
+ children: React.ReactNode;
10
+
11
+ /**
12
+ * Spacing variant for the card container padding
13
+ * - compact: 8px padding
14
+ * - normal: 12px padding
15
+ * - relaxed: 16px padding
16
+ * - chill: 24px padding
17
+ */
18
+ spacing?: CardContainerSpacing;
19
+
20
+ /**
21
+ * Additional CSS classes to apply to the card container
22
+ */
23
+ className?: string;
24
+
25
+ /**
26
+ * Optional click handler
27
+ */
28
+ onClick?: (e: React.MouseEvent<HTMLDivElement>) => void;
29
+
30
+ /**
31
+ * Optional data attributes for testing or tracking
32
+ */
33
+ 'data-testid'?: string;
34
+ }
35
+
36
+ /**
37
+ * CardContainer is a versatile UI element that groups related content,
38
+ * such as text, images, buttons, or interactive elements.
39
+ *
40
+ * It supports different spacing variants to control the visual density
41
+ * and padding of the container.
42
+ */
43
+ export const CardContainer: React.FC<CardContainerProps> = ({
44
+ children,
45
+ spacing = 'normal',
46
+ className = '',
47
+ onClick,
48
+ 'data-testid': testId,
49
+ }) => {
50
+ const baseClass = 'card-container';
51
+ const spacingClass = `card-container--spacing-${spacing}`;
52
+ const classes = [baseClass, spacingClass, className].filter(Boolean).join(' ');
53
+
54
+ return (
55
+ <div
56
+ className={classes}
57
+ onClick={onClick}
58
+ data-testid={testId}
59
+ >
60
+ {children}
61
+ </div>
62
+ );
63
+ };
64
+
65
+ export default CardContainer;
66
+