@tsiky/components-r19 1.0.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.
Files changed (287) hide show
  1. package/.prettierignore +4 -0
  2. package/.prettierrc +9 -0
  3. package/.storybook/main.ts +17 -0
  4. package/.storybook/preview.ts +21 -0
  5. package/.storybook/vitest.setup.ts +7 -0
  6. package/README.md +69 -0
  7. package/chart.ts +1 -0
  8. package/eslint.config.js +40 -0
  9. package/index.html +13 -0
  10. package/index.ts +33 -0
  11. package/package.json +63 -0
  12. package/public/vite.svg +1 -0
  13. package/src/App.css +42 -0
  14. package/src/App.tsx +12 -0
  15. package/src/assets/accessibility.png +0 -0
  16. package/src/assets/accessibility.svg +1 -0
  17. package/src/assets/addon-library.png +0 -0
  18. package/src/assets/assets.png +0 -0
  19. package/src/assets/avif-test-image.avif +0 -0
  20. package/src/assets/context.png +0 -0
  21. package/src/assets/discord.svg +1 -0
  22. package/src/assets/docs.png +0 -0
  23. package/src/assets/figma-plugin.png +0 -0
  24. package/src/assets/github.svg +1 -0
  25. package/src/assets/react.svg +1 -0
  26. package/src/assets/share.png +0 -0
  27. package/src/assets/styling.png +0 -0
  28. package/src/assets/testing.png +0 -0
  29. package/src/assets/theming.png +0 -0
  30. package/src/assets/tutorials.svg +1 -0
  31. package/src/assets/youtube.svg +1 -0
  32. package/src/components/AddItemModal/AddItemModal.module.css +72 -0
  33. package/src/components/AddItemModal/AddItemModal.tsx +82 -0
  34. package/src/components/AddItemModal/index.ts +1 -0
  35. package/src/components/Alert/Alert.css +54 -0
  36. package/src/components/Alert/Alert.stories.tsx +82 -0
  37. package/src/components/Alert/Alert.tsx +85 -0
  38. package/src/components/Alert/AlertContext.tsx +200 -0
  39. package/src/components/Alert/AlertModels.ts +34 -0
  40. package/src/components/Alert/index.ts +3 -0
  41. package/src/components/AnnouncementPanel/FlexRowContainer.css +17 -0
  42. package/src/components/AnnouncementPanel/FlexRowContainer.stories.tsx +329 -0
  43. package/src/components/AnnouncementPanel/FlexRowContainer.tsx +24 -0
  44. package/src/components/AnnouncementPanel/ListBox/CounterListBox.css +56 -0
  45. package/src/components/AnnouncementPanel/ListBox/CounterListBox.stories.tsx +292 -0
  46. package/src/components/AnnouncementPanel/ListBox/CounterListBox.tsx +106 -0
  47. package/src/components/AnnouncementPanel/ListBox/SimpleListBox.css +57 -0
  48. package/src/components/AnnouncementPanel/ListBox/SimpleListBox.stories.tsx +189 -0
  49. package/src/components/AnnouncementPanel/ListBox/SimpleListBox.tsx +138 -0
  50. package/src/components/AnnouncementPanel/ListBox/TrendListBox.css +61 -0
  51. package/src/components/AnnouncementPanel/ListBox/TrendListBox.stories.tsx +257 -0
  52. package/src/components/AnnouncementPanel/ListBox/TrendListBox.tsx +90 -0
  53. package/src/components/AnnouncementPanel/ListBox/index.ts +3 -0
  54. package/src/components/AnnouncementPanel/ListContentContainer.css +23 -0
  55. package/src/components/AnnouncementPanel/ListContentContainer.stories.tsx +212 -0
  56. package/src/components/AnnouncementPanel/ListContentContainer.tsx +33 -0
  57. package/src/components/AnnouncementPanel/index.ts +3 -0
  58. package/src/components/BandChart/index.tsx +282 -0
  59. package/src/components/Button/Button.module.css +165 -0
  60. package/src/components/Button/Button.stories.ts +132 -0
  61. package/src/components/Button/Button.tsx +55 -0
  62. package/src/components/Button/button.css +29 -0
  63. package/src/components/Button/index.ts +2 -0
  64. package/src/components/ChartContainer/ChartContainer.css +116 -0
  65. package/src/components/ChartContainer/ChartContainer.stories.tsx +159 -0
  66. package/src/components/ChartContainer/ChartContainer.tsx +155 -0
  67. package/src/components/ChartContainer/index.ts +1 -0
  68. package/src/components/Charts/area-chart-admission/AreaChartAdmission.stories.tsx +65 -0
  69. package/src/components/Charts/area-chart-admission/AreaChartAdmission.tsx +89 -0
  70. package/src/components/Charts/area-chart-admission/content.json +48 -0
  71. package/src/components/Charts/area-chart-hospitalisation/AreaChartHospitalisation.stories.tsx +141 -0
  72. package/src/components/Charts/area-chart-hospitalisation/AreaChartHospitalisation.tsx +262 -0
  73. package/src/components/Charts/area-chart-hospitalisation/content.json +55 -0
  74. package/src/components/Charts/bar-chart/BarChart.stories.tsx +50 -0
  75. package/src/components/Charts/bar-chart/BarChart.tsx +132 -0
  76. package/src/components/Charts/bar-chart/content.json +15 -0
  77. package/src/components/Charts/boxplot-chart/BoxPlotChart.stories.tsx +63 -0
  78. package/src/components/Charts/boxplot-chart/BoxPlotChart.tsx +114 -0
  79. package/src/components/Charts/boxplot-chart/boxUtils.ts +22 -0
  80. package/src/components/Charts/boxplot-chart/content.json +11 -0
  81. package/src/components/Charts/mixed-chart/MixedChart.stories.tsx +83 -0
  82. package/src/components/Charts/mixed-chart/MixedChart.tsx +625 -0
  83. package/src/components/Charts/mixed-chart/content.json +34 -0
  84. package/src/components/Charts/sankey-adaptation/sankey.tsx +70 -0
  85. package/src/components/Charts/sankey-chart/SankeyChart.stories.tsx +69 -0
  86. package/src/components/Charts/sankey-chart/SankeyChart.tsx +155 -0
  87. package/src/components/Charts/sankey-chart/content.json +15 -0
  88. package/src/components/Charts/stacked-column/StackedColumn.stories.tsx +72 -0
  89. package/src/components/Charts/stacked-column/StackedColumn.tsx +406 -0
  90. package/src/components/Charts/stacked-column/content.json +37 -0
  91. package/src/components/Charts/stacked-column-one-hundred-percent/StackedColumnOneHundredPercent.stories.tsx +43 -0
  92. package/src/components/Charts/stacked-column-one-hundred-percent/StackedColumnOneHundredPercent.tsx +75 -0
  93. package/src/components/Charts/stacked-column-one-hundred-percent/content.json +6 -0
  94. package/src/components/CircularProgress/CircularProgress.css +79 -0
  95. package/src/components/CircularProgress/CircularProgress.stories.tsx +251 -0
  96. package/src/components/CircularProgress/CircularProgress.tsx +101 -0
  97. package/src/components/CircularProgress/index.ts +2 -0
  98. package/src/components/Configure.mdx +369 -0
  99. package/src/components/DayStatCard/DayStatCard.css +50 -0
  100. package/src/components/DayStatCard/DayStatCard.stories.tsx +273 -0
  101. package/src/components/DayStatCard/DayStatCard.tsx +69 -0
  102. package/src/components/DayStatCard/index.ts +2 -0
  103. package/src/components/DraggableSwitcher/DraggableSwitcherButton.tsx +58 -0
  104. package/src/components/DraggableSwitcher/context/useDraggableSwitcher.tsx +45 -0
  105. package/src/components/DraggableSwitcher/index.ts +2 -0
  106. package/src/components/DropdownMenu/DropdownMenu.css +100 -0
  107. package/src/components/DropdownMenu/DropdownMenu.stories.tsx +174 -0
  108. package/src/components/DropdownMenu/DropdownMenu.tsx +106 -0
  109. package/src/components/DropdownMenu/index.ts +1 -0
  110. package/src/components/DynamicForm/DynamicFom.stories.ts +773 -0
  111. package/src/components/DynamicForm/DynamicForm.module.css +468 -0
  112. package/src/components/DynamicForm/DynamicForm.tsx +224 -0
  113. package/src/components/DynamicForm/index.ts +3 -0
  114. package/src/components/DynamicForm/tools/form-metadata.ts +82 -0
  115. package/src/components/DynamicForm/tools/validation.ts +168 -0
  116. package/src/components/DynamicInput/DynamicInput.module.css +126 -0
  117. package/src/components/DynamicInput/DynamicInput.stories.ts +350 -0
  118. package/src/components/DynamicInput/DynamicInput.tsx +144 -0
  119. package/src/components/DynamicInput/index.ts +2 -0
  120. package/src/components/DynamicInput/input/CheckboxInput.tsx +41 -0
  121. package/src/components/DynamicInput/input/ColorInput.tsx +46 -0
  122. package/src/components/DynamicInput/input/DateInput.tsx +57 -0
  123. package/src/components/DynamicInput/input/FileInput.tsx +174 -0
  124. package/src/components/DynamicInput/input/InputWrapper.tsx +26 -0
  125. package/src/components/DynamicInput/input/RadioInput.tsx +46 -0
  126. package/src/components/DynamicInput/input/RangeInput.tsx +46 -0
  127. package/src/components/DynamicInput/input/SelectInput.tsx +75 -0
  128. package/src/components/DynamicInput/input/TextInput.tsx +101 -0
  129. package/src/components/DynamicInput/input/TextareaInput.tsx +47 -0
  130. package/src/components/DynamicInput/input/assets/ColorInput.module.css +48 -0
  131. package/src/components/DynamicInput/input/assets/DateInput.module.css +83 -0
  132. package/src/components/DynamicInput/input/assets/FileInput.module.css +133 -0
  133. package/src/components/DynamicInput/input/assets/RangeInput.module.css +169 -0
  134. package/src/components/DynamicInput/input/assets/SelectInput.module.css +95 -0
  135. package/src/components/DynamicInput/input/index.ts +10 -0
  136. package/src/components/DynamicTable/AdvancedFilters.tsx +196 -0
  137. package/src/components/DynamicTable/ColumnSorter.tsx +185 -0
  138. package/src/components/DynamicTable/Pagination.tsx +115 -0
  139. package/src/components/DynamicTable/TableBody.tsx +42 -0
  140. package/src/components/DynamicTable/TableCell.tsx +30 -0
  141. package/src/components/DynamicTable/TableHeader.tsx +34 -0
  142. package/src/components/DynamicTable/TableRow.tsx +56 -0
  143. package/src/components/DynamicTable/TableauDynamic.stories.ts +1014 -0
  144. package/src/components/DynamicTable/TableauDynamique.module.css +1287 -0
  145. package/src/components/DynamicTable/TableauDynamique.tsx +154 -0
  146. package/src/components/DynamicTable/filters/BooleanFilter.tsx +30 -0
  147. package/src/components/DynamicTable/filters/DateFilter.tsx +28 -0
  148. package/src/components/DynamicTable/filters/DateRangeFilter.tsx +51 -0
  149. package/src/components/DynamicTable/filters/FilterRenderer.tsx +117 -0
  150. package/src/components/DynamicTable/filters/MultiSelectFilter.tsx +59 -0
  151. package/src/components/DynamicTable/filters/NumberFilter.tsx +37 -0
  152. package/src/components/DynamicTable/filters/OperatorFilter.tsx +64 -0
  153. package/src/components/DynamicTable/filters/SelectFilter.tsx +69 -0
  154. package/src/components/DynamicTable/filters/TextFilter.tsx +39 -0
  155. package/src/components/DynamicTable/filters/index.ts +9 -0
  156. package/src/components/DynamicTable/hooks/index.ts +2 -0
  157. package/src/components/DynamicTable/hooks/useAsyncActions.ts +36 -0
  158. package/src/components/DynamicTable/hooks/useFilters.ts +142 -0
  159. package/src/components/DynamicTable/hooks/useTableData.ts +216 -0
  160. package/src/components/DynamicTable/index.ts +11 -0
  161. package/src/components/DynamicTable/tools/filterTypes.ts +118 -0
  162. package/src/components/DynamicTable/tools/index.ts +3 -0
  163. package/src/components/DynamicTable/tools/tableConfig.ts +96 -0
  164. package/src/components/DynamicTable/tools/tableTypes.ts +63 -0
  165. package/src/components/EntryControl/EntryControl.module.css +218 -0
  166. package/src/components/EntryControl/EntryControl.stories.tsx +71 -0
  167. package/src/components/EntryControl/EntryControl.tsx +117 -0
  168. package/src/components/EntryControl/index.ts +2 -0
  169. package/src/components/Grid/Grid.stories.tsx +94 -0
  170. package/src/components/Grid/Grid.tsx +214 -0
  171. package/src/components/Grid/grid.css +285 -0
  172. package/src/components/Grid/index.ts +2 -0
  173. package/src/components/Header/Header.stories.tsx +164 -0
  174. package/src/components/Header/Header.tsx +59 -0
  175. package/src/components/Header/header.css +31 -0
  176. package/src/components/Header/index.ts +1 -0
  177. package/src/components/IconText/IconText..stories.tsx +135 -0
  178. package/src/components/IconText/IconText.css +43 -0
  179. package/src/components/IconText/IconText.tsx +43 -0
  180. package/src/components/IconText/index.ts +1 -0
  181. package/src/components/LanguageSelector/LanguageSelector.css +31 -0
  182. package/src/components/LanguageSelector/LanguageSelector.stories.tsx +38 -0
  183. package/src/components/LanguageSelector/LanguageSelector.tsx +37 -0
  184. package/src/components/LanguageSelector/index.ts +1 -0
  185. package/src/components/Logo/Logo.css +89 -0
  186. package/src/components/Logo/Logo.stories.tsx +79 -0
  187. package/src/components/Logo/Logo.tsx +22 -0
  188. package/src/components/Logo/index.ts +2 -0
  189. package/src/components/MetricsPanel/MetricsItem.tsx +128 -0
  190. package/src/components/MetricsPanel/MetricsPanel.module.css +636 -0
  191. package/src/components/MetricsPanel/MetricsPanel.stories.tsx +692 -0
  192. package/src/components/MetricsPanel/MetricsPanel.tsx +282 -0
  193. package/src/components/MetricsPanel/PanelHeader.tsx +19 -0
  194. package/src/components/MetricsPanel/SummaryCard.tsx +61 -0
  195. package/src/components/MetricsPanel/index.ts +4 -0
  196. package/src/components/MetricsPanel/renderers/CompactRenderer.tsx +125 -0
  197. package/src/components/MetricsPanel/renderers/ImageCard.tsx +62 -0
  198. package/src/components/MetricsPanel/renderers/PertinenceCard.tsx +55 -0
  199. package/src/components/MetricsPanel/tools/MetricsPanelTypes.ts +62 -0
  200. package/src/components/MetricsPanel/tools/chooseDefaultRender.ts +50 -0
  201. package/src/components/MetricsPanel/tools/colorUtils.ts +39 -0
  202. package/src/components/MetricsPanel/tools/index.ts +2 -0
  203. package/src/components/ModuleHeader/ModuleHeader.css +37 -0
  204. package/src/components/ModuleHeader/ModuleHeader.stories.tsx +37 -0
  205. package/src/components/ModuleHeader/ModuleHeader.tsx +42 -0
  206. package/src/components/ModuleHeader/index.ts +1 -0
  207. package/src/components/ModuleSideBar/ModuleSideBar.css +227 -0
  208. package/src/components/ModuleSideBar/ModuleSideBar.stories.tsx +40 -0
  209. package/src/components/ModuleSideBar/ModuleSideBar.tsx +155 -0
  210. package/src/components/ModuleSideBar/index.ts +1 -0
  211. package/src/components/NavBar/NavBar.css +58 -0
  212. package/src/components/NavBar/NavBar.stories.tsx +169 -0
  213. package/src/components/NavBar/NavBar.tsx +100 -0
  214. package/src/components/NavBar/NavContext.tsx +30 -0
  215. package/src/components/NavBar/index.ts +2 -0
  216. package/src/components/NavItem/NavItem.css +29 -0
  217. package/src/components/NavItem/NavItem.tsx +58 -0
  218. package/src/components/NavItem/index.ts +1 -0
  219. package/src/components/Page/Dashboard.tsx +93 -0
  220. package/src/components/Page/Page.stories.ts +33 -0
  221. package/src/components/Page/Page.tsx +73 -0
  222. package/src/components/Page/page.css +81 -0
  223. package/src/components/PerformanceCard/PerformanceCard.module.css +232 -0
  224. package/src/components/PerformanceCard/PerformanceCard.stories.tsx +441 -0
  225. package/src/components/PerformanceCard/PerformanceCard.tsx +198 -0
  226. package/src/components/PerformanceCard/defaultHistogramRenderer.tsx +32 -0
  227. package/src/components/PerformanceCard/tools/types.ts +50 -0
  228. package/src/components/PerformanceCard/tools/usePerformanceCard.ts +93 -0
  229. package/src/components/PeriodRange/PeriodRange.module.css +158 -0
  230. package/src/components/PeriodRange/PeriodRange.stories.tsx +66 -0
  231. package/src/components/PeriodRange/PeriodRange.tsx +130 -0
  232. package/src/components/PeriodSelect/PeriodSelect.module.css +65 -0
  233. package/src/components/PeriodSelect/PeriodSelect.stories.tsx +40 -0
  234. package/src/components/PeriodSelect/PeriodSelect.tsx +42 -0
  235. package/src/components/PeriodSelect/index.ts +1 -0
  236. package/src/components/ScrollableHorizontale/ScrollableHorizontale.css +40 -0
  237. package/src/components/ScrollableHorizontale/ScrollableHorizontale.stories.tsx +133 -0
  238. package/src/components/ScrollableHorizontale/ScrollableHorizontale.tsx +29 -0
  239. package/src/components/ScrollableHorizontale/index.ts +1 -0
  240. package/src/components/SearchBar/SearchBar.css +40 -0
  241. package/src/components/SearchBar/SearchBar.stories.tsx +36 -0
  242. package/src/components/SearchBar/SearchBar.tsx +30 -0
  243. package/src/components/SearchBar/index.ts +1 -0
  244. package/src/components/SectionTitle/SectionTitle.css +21 -0
  245. package/src/components/SectionTitle/SectionTitle.stories.tsx +39 -0
  246. package/src/components/SectionTitle/SectionTitle.tsx +18 -0
  247. package/src/components/SideComponent/PatientEditor.tsx +64 -0
  248. package/src/components/SideComponent/SideComponent.css +179 -0
  249. package/src/components/SideComponent/SideComponent.stories.tsx +547 -0
  250. package/src/components/SideComponent/SideComponent.tsx +243 -0
  251. package/src/components/SideComponent/hooks/useBodyScrollLock.ts +15 -0
  252. package/src/components/SideComponent/index.ts +2 -0
  253. package/src/components/SideComponent/portal.ts +11 -0
  254. package/src/components/SubNavBar/SubNavBar.tsx +41 -0
  255. package/src/components/SubNavBar/index.ts +1 -0
  256. package/src/components/Switcher/Switcher.css +65 -0
  257. package/src/components/Switcher/Switcher.stories.tsx +153 -0
  258. package/src/components/Switcher/Switcher.tsx +83 -0
  259. package/src/components/Switcher/index.ts +1 -0
  260. package/src/components/Title/Title.stories.tsx +18 -0
  261. package/src/components/Title/Title.tsx +26 -0
  262. package/src/components/Title/index.ts +1 -0
  263. package/src/components/TranslationKey/TranslationKey.css +272 -0
  264. package/src/components/TranslationKey/TranslationKey.stories.tsx +50 -0
  265. package/src/components/TranslationKey/TranslationKey.tsx +245 -0
  266. package/src/components/TranslationKey/index.ts +1 -0
  267. package/src/components/TrendItem/TrendItem.css +36 -0
  268. package/src/components/TrendItem/TrendItem.stories.tsx +276 -0
  269. package/src/components/TrendItem/TrendItem.tsx +46 -0
  270. package/src/components/TrendItem/index.ts +1 -0
  271. package/src/components/TrendList/TrendList.css +16 -0
  272. package/src/components/TrendList/TrendList.stories.tsx +337 -0
  273. package/src/components/TrendList/TrendList.tsx +45 -0
  274. package/src/components/TrendList/index.ts +1 -0
  275. package/src/components/theme/ThemeSwitcherButton.tsx +64 -0
  276. package/src/components/theme/context/ThemeContext.tsx +61 -0
  277. package/src/components/theme/context/index.ts +2 -0
  278. package/src/components/theme/context/useThemeSwitcher.ts +18 -0
  279. package/src/components/theme/index.ts +1 -0
  280. package/src/index.css +68 -0
  281. package/src/main.tsx +10 -0
  282. package/src/vite-env.d.ts +1 -0
  283. package/tsconfig.app.json +27 -0
  284. package/tsconfig.json +4 -0
  285. package/tsconfig.node.json +25 -0
  286. package/vite.config.ts +43 -0
  287. package/vitest.shims.d.ts +1 -0
@@ -0,0 +1,169 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import { NavBar } from './NavBar';
3
+ import { NavProvider } from './NavContext';
4
+
5
+ const meta = {
6
+ title: 'Components/NavBar',
7
+ component: NavBar,
8
+ parameters: {
9
+ layout: 'fullscreen',
10
+ },
11
+ tags: ['autodocs'],
12
+ argTypes: {
13
+ items: {
14
+ control: 'object',
15
+ description: 'Array of navigation items',
16
+ table: {
17
+ category: 'Content',
18
+ },
19
+ },
20
+ highlightColor: {
21
+ control: 'color',
22
+ description: 'Highlight color for active items',
23
+ table: {
24
+ category: 'Appearance',
25
+ },
26
+ },
27
+ onNavClick: {
28
+ action: 'navItemClicked',
29
+ description: 'Callback function when a navigation item is clicked',
30
+ table: {
31
+ category: 'Events',
32
+ },
33
+ },
34
+ },
35
+ args: {
36
+ onNavClick: (item: string) => console.log(`Clicked on ${item}`),
37
+ items: [
38
+ { id: 'home', label: 'Home' },
39
+ { id: 'about', label: 'About' },
40
+ { id: 'services', label: 'Services' },
41
+ { id: 'contact', label: 'Contact' },
42
+ ],
43
+ },
44
+ decorators: [
45
+ (Story) => (
46
+ <NavProvider>
47
+ <div style={{ padding: '20px', background: '#f5f5f5', minHeight: '100px' }}>
48
+ <Story />
49
+ </div>
50
+ </NavProvider>
51
+ ),
52
+ ],
53
+ } satisfies Meta<typeof NavBar>;
54
+
55
+ export default meta;
56
+ type Story = StoryObj<typeof meta>;
57
+
58
+ export const Default: Story = {
59
+ args: {
60
+ highlightColor: '#008CBA',
61
+ },
62
+ parameters: {
63
+ docs: {
64
+ description: {
65
+ story: 'Default navigation bar with basic navigation items',
66
+ },
67
+ },
68
+ },
69
+ };
70
+
71
+ export const WithLinks: Story = {
72
+ args: {
73
+ items: [
74
+ { id: 'home', label: 'Home', href: '/' },
75
+ { id: 'about', label: 'About', href: '/about' },
76
+ { id: 'services', label: 'Services', href: '/services' },
77
+ { id: 'contact', label: 'Contact', href: '/contact' },
78
+ ],
79
+ },
80
+ parameters: {
81
+ docs: {
82
+ description: {
83
+ story: 'Navigation bar with items that function as links',
84
+ },
85
+ },
86
+ },
87
+ };
88
+
89
+ export const WithCustomHighlight: Story = {
90
+ args: {
91
+ highlightColor: '#ff5733',
92
+ items: [
93
+ { id: 'home', label: 'Home' },
94
+ { id: 'about', label: 'About' },
95
+ { id: 'services', label: 'Services' },
96
+ { id: 'contact', label: 'Contact' },
97
+ ],
98
+ },
99
+ parameters: {
100
+ docs: {
101
+ description: {
102
+ story: 'Navigation bar with custom highlight color for active items',
103
+ },
104
+ },
105
+ },
106
+ };
107
+
108
+ export const ManyItems: Story = {
109
+ args: {
110
+ items: [
111
+ { id: 'home', label: 'Home' },
112
+ { id: 'about', label: 'About' },
113
+ { id: 'services', label: 'Services' },
114
+ { id: 'products', label: 'Products' },
115
+ { id: 'blog', label: 'Blog' },
116
+ { id: 'gallery', label: 'Gallery' },
117
+ { id: 'testimonials', label: 'Testimonials' },
118
+ { id: 'team', label: 'Our Team' },
119
+ { id: 'careers', label: 'Careers' },
120
+ { id: 'contact', label: 'Contact Us' },
121
+ ],
122
+ },
123
+ parameters: {
124
+ docs: {
125
+ description: {
126
+ story: 'Navigation bar with many items that will trigger mobile view on smaller screens',
127
+ },
128
+ },
129
+ },
130
+ };
131
+
132
+ export const MobileView: Story = {
133
+ args: {
134
+ items: [
135
+ { id: 'home', label: 'Home' },
136
+ { id: 'about', label: 'About' },
137
+ { id: 'services', label: 'Services' },
138
+ { id: 'contact', label: 'Contact' },
139
+ ],
140
+ },
141
+ parameters: {
142
+ viewport: {
143
+ defaultViewport: 'mobile1',
144
+ },
145
+ docs: {
146
+ description: {
147
+ story: 'Navigation bar in mobile view with dropdown menu',
148
+ },
149
+ },
150
+ },
151
+ };
152
+
153
+ export const MixedItems: Story = {
154
+ args: {
155
+ items: [
156
+ { id: 'home', label: 'Home', href: '/' },
157
+ { id: 'about', label: 'About' },
158
+ { id: 'services', label: 'Services', href: '/services' },
159
+ { id: 'contact', label: 'Contact' },
160
+ ],
161
+ },
162
+ parameters: {
163
+ docs: {
164
+ description: {
165
+ story: 'Navigation bar with a mix of items with and without href attributes',
166
+ },
167
+ },
168
+ },
169
+ };
@@ -0,0 +1,100 @@
1
+ import React, { useState, useEffect, useRef } from 'react';
2
+ import './NavBar.css';
3
+ import { NavItem } from '../NavItem/NavItem';
4
+ import type { NavItemType } from '../NavItem/NavItem';
5
+ import { useNavigation } from './NavContext';
6
+
7
+ export type NavBarProps = {
8
+ items: NavItemType[];
9
+ onNavClick?: (id: string) => void;
10
+ highlightColor?: string;
11
+ moduleConfig?: Record<string, boolean>;
12
+ };
13
+
14
+ export const NavBar: React.FC<NavBarProps> = ({
15
+ items,
16
+ onNavClick,
17
+ highlightColor = '#008CBA',
18
+ moduleConfig = {},
19
+ }) => {
20
+ const { activeNav } = useNavigation();
21
+ const [isMobile, setIsMobile] = useState(true);
22
+ const [dropdownOpen, setDropdownOpen] = useState(false);
23
+ const navRef = useRef<HTMLDivElement | null>(null);
24
+
25
+ useEffect(() => {
26
+ const checkNavSize = () => {
27
+ if (navRef.current && navRef.current.parentElement) {
28
+ const parentWidth = navRef.current.parentNode?.parentElement?.offsetWidth || 0;
29
+ setIsMobile(parentWidth * 0.6 < navRef.current.offsetWidth);
30
+ }
31
+ };
32
+
33
+ checkNavSize();
34
+ window.addEventListener('resize', checkNavSize);
35
+
36
+ return () => window.removeEventListener('resize', checkNavSize);
37
+ }, []);
38
+
39
+ const handleClick = (id: string) => {
40
+ onNavClick?.(id);
41
+ setDropdownOpen(false);
42
+ };
43
+
44
+ const activeItem = items.find((item) => item.id === activeNav) || items[0];
45
+
46
+ return (
47
+ <div ref={navRef}>
48
+ {isMobile ? (
49
+ <div className='navbar-mobile'>
50
+ <button
51
+ className='navbar-dropdown-toggle'
52
+ onClick={() => setDropdownOpen(!dropdownOpen)}
53
+ style={{ backgroundColor: highlightColor, color: '#fff' }}
54
+ >
55
+ {activeItem.label}
56
+ <span className={`dropdown-arrow ${dropdownOpen ? 'open' : ''}`}></span>
57
+ </button>
58
+
59
+ {dropdownOpen && (
60
+ <div className='navbar-dropdown'>
61
+ {items.map((item) => (
62
+ <NavItem
63
+ key={item.id}
64
+ id={item.id}
65
+ label={item.label}
66
+ href={item.moduleKey && moduleConfig[item.moduleKey] ? item.href : undefined}
67
+ isActive={
68
+ activeNav === item.id &&
69
+ item.moduleKey !== undefined &&
70
+ moduleConfig[item.moduleKey]
71
+ }
72
+ onClick={handleClick}
73
+ highlightColor={highlightColor}
74
+ />
75
+ ))}
76
+ </div>
77
+ )}
78
+ </div>
79
+ ) : (
80
+ <nav className='navbar'>
81
+ {items.map((item) => (
82
+ <NavItem
83
+ key={item.id}
84
+ id={item.id}
85
+ label={item.label}
86
+ href={item.moduleKey && moduleConfig[item.moduleKey] ? item.href : undefined}
87
+ isActive={
88
+ activeNav === item.id &&
89
+ item.moduleKey !== undefined &&
90
+ moduleConfig[item.moduleKey]
91
+ }
92
+ onClick={handleClick}
93
+ highlightColor={highlightColor}
94
+ />
95
+ ))}
96
+ </nav>
97
+ )}
98
+ </div>
99
+ );
100
+ };
@@ -0,0 +1,30 @@
1
+ // context/NavContext.tsx
2
+ import React, { createContext, useContext, useState, type ReactNode } from 'react';
3
+
4
+ interface NavContextType {
5
+ activeNav: string;
6
+ setActiveNav: (id: string) => void;
7
+ activeSubNav: string;
8
+ setActiveSubNav: (id: string) => void;
9
+ }
10
+
11
+ const NavContext = createContext<NavContextType | undefined>(undefined);
12
+ export const useNavigation = () => {
13
+ const ctx = useContext(NavContext);
14
+ if (!ctx) throw new Error('useNavigation must be used within a NavProvider');
15
+ return ctx;
16
+ };
17
+
18
+ export const NavProvider: React.FC<{ children: ReactNode; defaultActive?: string }> = ({
19
+ children,
20
+ defaultActive = '',
21
+ }) => {
22
+ const [activeNav, setActiveNav] = useState<string>(defaultActive);
23
+ const [activeSubNav, setActiveSubNav] = useState<string>(defaultActive);
24
+
25
+ return (
26
+ <NavContext.Provider value={{ activeNav, setActiveNav, activeSubNav, setActiveSubNav }}>
27
+ {children}
28
+ </NavContext.Provider>
29
+ );
30
+ };
@@ -0,0 +1,2 @@
1
+ export * from './NavBar';
2
+ export * from './NavContext';
@@ -0,0 +1,29 @@
1
+ /* item de nav */
2
+ .nav-item {
3
+ text-decoration: none;
4
+ padding: 10px 12px;
5
+ border-radius: 8px;
6
+ cursor: pointer;
7
+ transition:
8
+ background 180ms ease,
9
+ transform 120ms ease,
10
+ color 180ms ease;
11
+ letter-spacing: 0.06em;
12
+ text-transform: uppercase;
13
+ background: rgba(0, 0, 0, 0.04);
14
+ transform: translateY(-1px);
15
+ color: rgba(0, 0, 0, 0.1);
16
+ }
17
+
18
+ /* item actif : pill rempli */
19
+ .nav-item.active,
20
+ .nav-item[aria-current='page'] {
21
+ background: var(--highlightColor, #1387c8);
22
+ box-shadow: 0 6px 18px rgba(19, 135, 200, 0.14);
23
+ }
24
+
25
+ /* si tu veux un style lien <a> différent (évite outlines moches) */
26
+ .nav-item:focus {
27
+ outline: none;
28
+ box-shadow: 0 0 0 3px rgba(19, 135, 200, 0.12);
29
+ }
@@ -0,0 +1,58 @@
1
+ import React from 'react';
2
+ import './NavItem.css';
3
+ import { useNavigation } from '../NavBar';
4
+
5
+ export type NavItemType = {
6
+ id: string;
7
+ label: string;
8
+ isActive?: boolean;
9
+ onClick?: (id: string) => void;
10
+ href?: string;
11
+ highlightColor?: string;
12
+ moduleKey?: string;
13
+ };
14
+
15
+ export const NavItem: React.FC<NavItemType> = ({
16
+ id,
17
+ label,
18
+ isActive = false,
19
+ onClick,
20
+ href,
21
+ highlightColor = '#008CBA',
22
+ moduleKey = '',
23
+ ...props
24
+ }) => {
25
+ // Determine which element to render
26
+ const { setActiveNav } = useNavigation();
27
+ const handleClick = () => {
28
+ setActiveNav(id); // ✅ met à jour la nav active
29
+ onClick?.(id); // ✅ appelle le callback externe si défini
30
+ };
31
+ if (href) {
32
+ // Render as anchor tag if href is provided and no onClick handler
33
+ return (
34
+ <a
35
+ href={href}
36
+ className={`nav-item ${isActive ? 'active' : ''}`}
37
+ style={isActive ? { backgroundColor: highlightColor, color: '#fff' } : {}}
38
+ onClick={handleClick}
39
+ {...props}
40
+ >
41
+ {label}
42
+ </a>
43
+ );
44
+ } else {
45
+ return (
46
+ <div
47
+ className={`nav-item ${isActive ? 'active' : ''}`}
48
+ style={isActive ? { backgroundColor: highlightColor, color: '#fff' } : {}}
49
+ onClick={handleClick}
50
+ role={onClick ? 'button' : 'presentation'}
51
+ tabIndex={onClick ? 0 : -1}
52
+ {...props}
53
+ >
54
+ {label}
55
+ </div>
56
+ );
57
+ }
58
+ };
@@ -0,0 +1 @@
1
+ export * from './NavItem';
@@ -0,0 +1,93 @@
1
+ import React from 'react';
2
+ import BandChart, { type BandChartData, type BandChartConfig } from '../BandChart';
3
+
4
+ const chartData: BandChartData = {
5
+ labels: [
6
+ '00h',
7
+ '01h',
8
+ '02h',
9
+ '03h',
10
+ '04h',
11
+ '05h',
12
+ '06h',
13
+ '07h',
14
+ '08h',
15
+ '09h',
16
+ '10h',
17
+ '11h',
18
+ '12h',
19
+ '13h',
20
+ '14h',
21
+ '15h',
22
+ '16h',
23
+ '17h',
24
+ '18h',
25
+ '19h',
26
+ '20h',
27
+ '21h',
28
+ '22h',
29
+ '23h',
30
+ ],
31
+ // prédictions principales (main) = moyenne des admissions attendues
32
+ main: [3, 2, 1, 1, 1, 2, 4, 7, 11, 14, 18, 20, 18, 17, 16, 16, 17, 18, 17, 15, 12, 10, 8, 6],
33
+
34
+ // borne supérieure (upper) = main + variation
35
+ upper: [5, 3, 2, 2, 2, 4, 7, 11, 16, 20, 25, 28, 24, 22, 21, 21, 23, 24, 22, 19, 15, 13, 10, 8],
36
+
37
+ // borne inférieure (lower) = main - variation (min 0)
38
+ lower: [2, 1, 0, 0, 0, 1, 3, 5, 8, 11, 14, 15, 15, 14, 13, 13, 14, 15, 14, 12, 10, 8, 6, 5],
39
+
40
+ // histogram = valeurs observées réelles (avec bruit et quelques dépassements aux pics)
41
+ histogram: [2, 1, 1, 0, 0, 1, 3, 6, 10, 13, 16, 22, 17, 15, 14, 15, 16, 17, 15, 14, 11, 10, 7, 5],
42
+ };
43
+
44
+ const config: BandChartConfig = {
45
+ rangeBands: [
46
+ {
47
+ id: 'Ongoing',
48
+ lowerKey: 'lower',
49
+ upperKey: 'upper',
50
+ visible: true,
51
+ color: '#cbd7ea',
52
+ opacity: 0.22,
53
+ },
54
+ ],
55
+ lines: [
56
+ { id: 'Max', key: 'upper', label: 'Max', visible: true, color: '#082b4d', width: 1 },
57
+ {
58
+ id: 'Predictions',
59
+ key: 'main',
60
+ label: 'Predictions',
61
+ visible: true,
62
+ color: '#6fb0ff',
63
+ width: 1.5,
64
+ },
65
+ { id: 'Min', key: 'lower', label: 'Min', visible: true, color: '#082b4d', width: 1, dash: 6 },
66
+ ],
67
+ showHistogram: true,
68
+ histogramKey: 'histogram',
69
+ histogramColor: '#6f6f6f',
70
+ bubble: {
71
+ visible: true,
72
+ values: [2, 1, 1, 0, 0, 1, 3, 6, 10, 13, 16, 22, 17, 15, 14, 15, 16, 17, 15, 14, 11, 10, 7, 5], // ex: correct predictions positions
73
+ size: 4,
74
+ },
75
+ displayCondition: null,
76
+ responsive: true,
77
+ };
78
+
79
+ const Dashboard: React.FC = () => (
80
+ <div
81
+ style={{
82
+ border: '1px solid #ccc',
83
+ borderRadius: '18px',
84
+ padding: '0px 30px',
85
+ backgroundColor: '#fff',
86
+ }}
87
+ >
88
+ <h2 style={{ marginBottom: 15, textAlign: 'left', fontStyle: 'normal' }}>Admissions 14.08</h2>
89
+ <BandChart data={chartData} config={config} height={350} />
90
+ </div>
91
+ );
92
+
93
+ export default Dashboard;
@@ -0,0 +1,33 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+
3
+ import { expect, userEvent, within } from 'storybook/test';
4
+
5
+ import { Page } from './Page';
6
+
7
+ const meta = {
8
+ title: 'Example/Page',
9
+ component: Page,
10
+ parameters: {
11
+ // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout
12
+ layout: 'fullscreen',
13
+ },
14
+ } satisfies Meta<typeof Page>;
15
+
16
+ export default meta;
17
+ type Story = StoryObj<typeof meta>;
18
+
19
+ export const LoggedOut: Story = {};
20
+
21
+ // More on component testing: https://storybook.js.org/docs/writing-tests/interaction-testing
22
+ export const LoggedIn: Story = {
23
+ play: async ({ canvasElement }) => {
24
+ const canvas = within(canvasElement);
25
+ const loginButton = canvas.getByRole('button', { name: /Log in/i });
26
+ await expect(loginButton).toBeInTheDocument();
27
+ await userEvent.click(loginButton);
28
+ await expect(loginButton).not.toBeInTheDocument();
29
+
30
+ const logoutButton = canvas.getByRole('button', { name: /Log out/i });
31
+ await expect(logoutButton).toBeInTheDocument();
32
+ },
33
+ };
@@ -0,0 +1,73 @@
1
+ import React from 'react';
2
+
3
+ import { Header } from '../Header/Header';
4
+ import './page.css';
5
+
6
+ type User = {
7
+ name: string;
8
+ };
9
+
10
+ export const Page: React.FC = () => {
11
+ const [user, setUser] = React.useState<User>();
12
+
13
+ return (
14
+ <article>
15
+ <Header
16
+ user={user}
17
+ onLogin={() => setUser({ name: 'Jane Doe' })}
18
+ onLogout={() => setUser(undefined)}
19
+ onCreateAccount={() => setUser({ name: 'Jane Doe' })}
20
+ />
21
+
22
+ <section className='storybook-page'>
23
+ <h2>Pages in Storybook</h2>
24
+ <p>
25
+ We recommend building UIs with a{' '}
26
+ <a href='https://componentdriven.org' target='_blank' rel='noopener noreferrer'>
27
+ <strong>component-driven</strong>
28
+ </a>{' '}
29
+ process starting with atomic components and ending with pages.
30
+ </p>
31
+ <p>
32
+ Render pages with mock data. This makes it easy to build and review page states without
33
+ needing to navigate to them in your app. Here are some handy patterns for managing page
34
+ data in Storybook:
35
+ </p>
36
+ <ul>
37
+ <li>
38
+ Use a higher-level connected component. Storybook helps you compose such data from the
39
+ "args" of child component stories
40
+ </li>
41
+ <li>
42
+ Assemble data in the page component from your services. You can mock these services out
43
+ using Storybook.
44
+ </li>
45
+ </ul>
46
+ <p>
47
+ Get a guided tutorial on component-driven development at{' '}
48
+ <a href='https://storybook.js.org/tutorials/' target='_blank' rel='noopener noreferrer'>
49
+ Storybook tutorials
50
+ </a>
51
+ . Read more in the{' '}
52
+ <a href='https://storybook.js.org/docs' target='_blank' rel='noopener noreferrer'>
53
+ docs
54
+ </a>
55
+ .
56
+ </p>
57
+ <div className='tip-wrapper'>
58
+ <span className='tip'>Tip</span> Adjust the width of the canvas with the{' '}
59
+ <svg width='10' height='10' viewBox='0 0 12 12' xmlns='http://www.w3.org/2000/svg'>
60
+ <g fill='none' fillRule='evenodd'>
61
+ <path
62
+ d='M1.5 5.2h4.8c.3 0 .5.2.5.4v5.1c-.1.2-.3.3-.4.3H1.4a.5.5 0 01-.5-.4V5.7c0-.3.2-.5.5-.5zm0-2.1h6.9c.3 0 .5.2.5.4v7a.5.5 0 01-1 0V4H1.5a.5.5 0 010-1zm0-2.1h9c.3 0 .5.2.5.4v9.1a.5.5 0 01-1 0V2H1.5a.5.5 0 010-1zm4.3 5.2H2V10h3.8V6.2z'
63
+ id='a'
64
+ fill='#999'
65
+ />
66
+ </g>
67
+ </svg>
68
+ Viewports addon in the toolbar
69
+ </div>
70
+ </section>
71
+ </article>
72
+ );
73
+ };
@@ -0,0 +1,81 @@
1
+ .storybook-page {
2
+ margin: 0 auto;
3
+ padding: 48px 20px;
4
+ max-width: 600px;
5
+ color: #333;
6
+ font-family: var(--font-primary);
7
+ font-size: var(--text-small); /* remplace 14px */
8
+ line-height: 1.6; /* équivalent à 24px pour 14px */
9
+ }
10
+
11
+ .storybook-page h2 {
12
+ display: inline-block;
13
+ vertical-align: top;
14
+ margin: 0 0 0.25rem; /* remplace 4px */
15
+ font-family: var(--font-primary);
16
+ font-weight: var(--font-bold); /* remplace 700 */
17
+ font-size: var(--h2); /* remplace 32px */
18
+ line-height: 1;
19
+ }
20
+
21
+ .storybook-page p {
22
+ font-family: var(--font-primary);
23
+ font-size: var(--text-paragraph); /* remplace la taille statique des paragraphes */
24
+ line-height: 1.6;
25
+ margin: 1em 0;
26
+ }
27
+
28
+ .storybook-page a {
29
+ color: inherit;
30
+ font-family: var(--font-primary);
31
+ }
32
+
33
+ .storybook-page ul {
34
+ margin: 1em 0;
35
+ padding-left: 1.875rem; /* 30px → en rem approximatif */
36
+ font-family: var(--font-primary);
37
+ font-size: var(--text-paragraph);
38
+ line-height: 1.6;
39
+ }
40
+
41
+ .storybook-page li {
42
+ margin-bottom: 0.5rem; /* 8px → en rem */
43
+ font-family: var(--font-primary);
44
+ font-size: var(--text-paragraph);
45
+ line-height: 1.6;
46
+ }
47
+
48
+ .storybook-page .tip {
49
+ display: inline-block;
50
+ vertical-align: top;
51
+ margin-right: 0.625rem; /* 10px → rem */
52
+ border-radius: 1em;
53
+ background: #e7fdd8;
54
+ padding: 0.25rem 0.75rem; /* 4px 12px → rem */
55
+ color: #357a14;
56
+ font-family: var(--font-primary);
57
+ font-weight: var(--font-bold); /* 700 */
58
+ font-size: var(--text-small); /* 11px → arrondi sur --text-small */
59
+ line-height: 1.1; /* 12px → approx */
60
+ }
61
+
62
+ .storybook-page .tip-wrapper {
63
+ margin-top: 2.5rem; /* 40px → rem */
64
+ margin-bottom: 2.5rem;
65
+ font-family: var(--font-primary);
66
+ font-size: var(--text-small); /* 13px → arrondi sur --text-small */
67
+ line-height: 1.5; /* 20px → approx */
68
+ }
69
+
70
+ .storybook-page .tip-wrapper svg {
71
+ display: inline-block;
72
+ vertical-align: top;
73
+ margin-top: 0.1875rem; /* 3px → rem */
74
+ margin-right: 0.25rem; /* 4px → rem */
75
+ width: 0.75rem; /* 12px → rem */
76
+ height: 0.75rem; /* 12px → rem */
77
+ }
78
+
79
+ .storybook-page .tip-wrapper svg path {
80
+ fill: #1ea7fd;
81
+ }