@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,329 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import { ArrowUp, ArrowDown, TrendingUp, Users } from 'lucide-react';
3
+ import { FlexRowContainer } from './FlexRowContainer';
4
+ import { ListContentContainer } from './ListContentContainer';
5
+ import { CounterListBox } from './ListBox/CounterListBox';
6
+ import { SimpleListBox } from './ListBox/SimpleListBox';
7
+ import { TrendListBox } from './ListBox/TrendListBox';
8
+
9
+ const meta: Meta<typeof FlexRowContainer> = {
10
+ title: 'Components/FlexRowContainer',
11
+ component: FlexRowContainer,
12
+ parameters: {
13
+ layout: 'fullscreen',
14
+ docs: {
15
+ description: {
16
+ component:
17
+ 'An adaptive flex container that allows children to take their natural size and wrap to new lines when needed.',
18
+ },
19
+ },
20
+ },
21
+ tags: ['autodocs'],
22
+ argTypes: {
23
+ gap: {
24
+ control: 'text',
25
+ description: 'Space between items',
26
+ },
27
+ },
28
+ };
29
+
30
+ export default meta;
31
+ type Story = StoryObj<typeof meta>;
32
+
33
+ export const AdaptiveDashboard: Story = {
34
+ name: 'Adaptive Dashboard',
35
+ args: {
36
+ gap: '1.5rem',
37
+ style: {
38
+ padding: '2rem',
39
+ background: '#f8fafc',
40
+ },
41
+ },
42
+ render: (args) => (
43
+ <FlexRowContainer {...args}>
44
+ {/* Small counter box */}
45
+ <ListContentContainer background='#0ea5e9'>
46
+ <CounterListBox title='Patients' data={[['63', 'Total']]} badgeColor='#0ea5e9' />
47
+ </ListContentContainer>
48
+
49
+ {/* Medium box with multiple lists */}
50
+ <ListContentContainer background='#0ea5e9'>
51
+ <SimpleListBox
52
+ title='Available beds'
53
+ data={[
54
+ ['MED', '21 beds'],
55
+ ['SURG', '2 beds'],
56
+ ['ER', '12 beds'],
57
+ ]}
58
+ />
59
+ <SimpleListBox title='Overdue patients' data={['623152385 - MED', '623168542 - SURG']} />
60
+ <SimpleListBox title='Overdue patients' data={['623152385 - MED', '623168542 - SURG']} />
61
+ <SimpleListBox title='Overdue patients' data={['623152385 - MED', '623168542 - SURG']} />
62
+ </ListContentContainer>
63
+
64
+ {/* Large trend box */}
65
+ <ListContentContainer background='#0ea5e9'>
66
+ <TrendListBox
67
+ title='3h Trend'
68
+ items={[
69
+ { label: 'MED', value: '+3', delta: 3, icon: <ArrowUp size={16} /> },
70
+ { label: 'SURG', value: '-2', delta: -2, icon: <ArrowDown size={16} /> },
71
+ { label: 'ER', value: '+5', delta: 5, icon: <ArrowUp size={16} /> },
72
+ { label: 'PED', value: '+1', delta: 1, icon: <ArrowUp size={16} /> },
73
+ ]}
74
+ />
75
+ </ListContentContainer>
76
+
77
+ {/* Very wide box */}
78
+ <ListContentContainer background='#0ea5e9'>
79
+ <SimpleListBox
80
+ title='General information'
81
+ data={[
82
+ 'All services are operating normally',
83
+ 'Planned maintenance tonight at 10pm',
84
+ 'Daily report available',
85
+ ]}
86
+ />
87
+ </ListContentContainer>
88
+ </FlexRowContainer>
89
+ ),
90
+ };
91
+
92
+ export const MixedSizes: Story = {
93
+ name: 'Mixed Content Sizes',
94
+ args: {
95
+ gap: '1rem',
96
+ style: {
97
+ padding: '1.5rem',
98
+ background: '#f1f5f9',
99
+ },
100
+ },
101
+ render: (args) => (
102
+ <FlexRowContainer {...args}>
103
+ {/* Tiny box */}
104
+ <ListContentContainer background='#10b981'>
105
+ <CounterListBox title='Alerts' data={[['3', 'Critical']]} badgeColor='#ef4444' />
106
+ </ListContentContainer>
107
+
108
+ {/* Small box */}
109
+ <ListContentContainer background='#10b981'>
110
+ <TrendListBox
111
+ title='Stats'
112
+ items={[{ label: 'Up', value: '+5', icon: <ArrowUp size={14} /> }]}
113
+ />
114
+ </ListContentContainer>
115
+
116
+ {/* Medium box */}
117
+ <ListContentContainer background='#10b981'>
118
+ <SimpleListBox
119
+ title='Status'
120
+ data={[
121
+ ['System', 'Operational'],
122
+ ['Database', 'Connected'],
123
+ ]}
124
+ />
125
+ </ListContentContainer>
126
+
127
+ {/* Large box */}
128
+ <ListContentContainer background='#10b981'>
129
+ <CounterListBox
130
+ title='Details'
131
+ data={[
132
+ ['156', 'Orders processed'],
133
+ ['42', 'New customers'],
134
+ ['24', 'Pending'],
135
+ ['8', 'Overdue'],
136
+ ]}
137
+ badgeColor='#8b5cf6'
138
+ />
139
+ </ListContentContainer>
140
+
141
+ {/* Extra large box */}
142
+ <ListContentContainer background='#10b981'>
143
+ <TrendListBox
144
+ title='Detailed Performance'
145
+ items={[
146
+ { label: 'Response time', value: '125ms', delta: -12, icon: <ArrowDown size={16} /> },
147
+ { label: 'CPU usage', value: '45%', delta: 2, icon: <ArrowUp size={16} /> },
148
+ { label: 'Memory', value: '68%', delta: 5, icon: <ArrowUp size={16} /> },
149
+ { label: 'Storage', value: '82%', delta: 8, icon: <ArrowUp size={16} /> },
150
+ ]}
151
+ />
152
+ </ListContentContainer>
153
+ </FlexRowContainer>
154
+ ),
155
+ };
156
+
157
+ export const BusinessAdaptive: Story = {
158
+ name: 'Business Adaptive Layout',
159
+ args: {
160
+ gap: '1.5rem',
161
+ style: {
162
+ padding: '2rem',
163
+ background: '#f8fafc',
164
+ minHeight: '100vh',
165
+ },
166
+ },
167
+ render: (args) => (
168
+ <FlexRowContainer {...args}>
169
+ {/* Sales metrics */}
170
+ <ListContentContainer background='#0ea5e9'>
171
+ <CounterListBox
172
+ title='Sales'
173
+ data={[
174
+ ['156', 'Orders'],
175
+ ['€2.4K', 'Revenue'],
176
+ ['42', 'Customers'],
177
+ ]}
178
+ badgeColor='#0ea5e9'
179
+ />
180
+ </ListContentContainer>
181
+
182
+ {/* Performance trends */}
183
+ <ListContentContainer background='#0ea5e9'>
184
+ <TrendListBox
185
+ title='Performance'
186
+ items={[
187
+ { label: 'Revenue', value: '+12%', delta: 12, icon: <TrendingUp size={16} /> },
188
+ { label: 'Users', value: '+8%', delta: 8, icon: <Users size={16} /> },
189
+ { label: 'Engagement', value: '-2%', delta: -2, icon: <ArrowDown size={16} /> },
190
+ ]}
191
+ />
192
+ </ListContentContainer>
193
+
194
+ {/* Quick stats */}
195
+ <ListContentContainer background='#0ea5e9'>
196
+ <SimpleListBox
197
+ title='Quick metrics'
198
+ data={[
199
+ ['Conversion rate', '3.2%'],
200
+ ['Average order value', '€68.50'],
201
+ ['Customer satisfaction', '4.8/5'],
202
+ ]}
203
+ />
204
+ </ListContentContainer>
205
+
206
+ {/* System status */}
207
+ <ListContentContainer background='#0ea5e9'>
208
+ <SimpleListBox
209
+ title='System status'
210
+ data={['All services operational', 'Backup successful', 'Update available']}
211
+ />
212
+ </ListContentContainer>
213
+
214
+ {/* Detailed analytics */}
215
+ <ListContentContainer background='#0ea5e9'>
216
+ <TrendListBox
217
+ title='Detailed analytics'
218
+ items={[
219
+ { label: 'New signups', value: '24', delta: 4, icon: <ArrowUp size={16} /> },
220
+ { label: 'Retention', value: '88%', delta: 2, icon: <ArrowUp size={16} /> },
221
+ { label: 'Bounce rate', value: '32%', delta: -3, icon: <ArrowDown size={16} /> },
222
+ { label: 'Avg. session time', value: '4:12', delta: 0.5, icon: <ArrowUp size={16} /> },
223
+ ]}
224
+ />
225
+ </ListContentContainer>
226
+ </FlexRowContainer>
227
+ ),
228
+ };
229
+
230
+ export const CompactAdaptive: Story = {
231
+ name: 'Compact Adaptive',
232
+ args: {
233
+ gap: '0.8rem',
234
+ style: {
235
+ padding: '1rem',
236
+ background: '#f1f5f9',
237
+ },
238
+ },
239
+ render: (args) => (
240
+ <FlexRowContainer {...args}>
241
+ <ListContentContainer background='#0ea5e9'>
242
+ <CounterListBox title='Active' data={[['42', 'Users']]} badgeColor='#0ea5e9' />
243
+ </ListContentContainer>
244
+
245
+ <ListContentContainer background='#0ea5e9'>
246
+ <SimpleListBox title='Status' data={['System normal']} />
247
+ </ListContentContainer>
248
+
249
+ <ListContentContainer background='#0ea5e9'>
250
+ <TrendListBox
251
+ title='Trends'
252
+ items={[
253
+ { label: 'Up', value: '+3', icon: <ArrowUp size={14} /> },
254
+ { label: 'Down', value: '-1', icon: <ArrowDown size={14} /> },
255
+ ]}
256
+ />
257
+ </ListContentContainer>
258
+
259
+ <ListContentContainer background='#0ea5e9'>
260
+ <CounterListBox title='Alerts' data={[['2', 'Minor']]} badgeColor='#f59e0b' />
261
+ </ListContentContainer>
262
+ </FlexRowContainer>
263
+ ),
264
+ };
265
+
266
+ export const ResponsiveBehavior: Story = {
267
+ name: 'Responsive Behavior Demo',
268
+ args: {
269
+ gap: '1rem',
270
+ style: {
271
+ padding: '1.5rem',
272
+ background: '#f8fafc',
273
+ border: '2px dashed #cbd5e1',
274
+ },
275
+ },
276
+ parameters: {
277
+ docs: {
278
+ description: {
279
+ story:
280
+ 'This demo shows how items naturally wrap to new lines based on their content size and available space. Resize the browser window to see the adaptive behavior.',
281
+ },
282
+ },
283
+ },
284
+ render: (args) => (
285
+ <div>
286
+ <div
287
+ style={{
288
+ textAlign: 'center',
289
+ marginBottom: '1rem',
290
+ color: '#64748b',
291
+ fontStyle: 'italic',
292
+ }}
293
+ >
294
+ ↓ Resize the window to see adaptive behavior ↓
295
+ </div>
296
+ <FlexRowContainer {...args}>
297
+ <ListContentContainer background='#0ea5e9'>
298
+ <SimpleListBox title='Small' data={['Short content']} />
299
+ </ListContentContainer>
300
+
301
+ <ListContentContainer background='#0ea5e9'>
302
+ <SimpleListBox title='Medium' data={['Medium-length content', 'Another line here']} />
303
+ </ListContentContainer>
304
+
305
+ <ListContentContainer background='#0ea5e9'>
306
+ <SimpleListBox
307
+ title='Large'
308
+ data={[
309
+ 'Very long content that takes more space',
310
+ 'Another line with extra text',
311
+ 'Yet another line to show behavior',
312
+ ]}
313
+ />
314
+ </ListContentContainer>
315
+
316
+ <ListContentContainer background='#0ea5e9'>
317
+ <SimpleListBox
318
+ title='Extra Large'
319
+ data={[
320
+ 'Extremely long content that will take up a lot of width in the layout',
321
+ 'A second line also with lots of text for demonstration',
322
+ 'Third line to complete the showcase',
323
+ ]}
324
+ />
325
+ </ListContentContainer>
326
+ </FlexRowContainer>
327
+ </div>
328
+ ),
329
+ };
@@ -0,0 +1,24 @@
1
+ import React from 'react';
2
+ import './FlexRowContainer.css';
3
+
4
+ export type FlexRowContainerProps = {
5
+ className?: string;
6
+ style?: React.CSSProperties;
7
+ children?: React.ReactNode; // normally ListContentContainer nodes
8
+ gap?: string;
9
+ };
10
+
11
+ export const FlexRowContainer: React.FC<FlexRowContainerProps> = ({
12
+ className = '',
13
+ style = {},
14
+ children,
15
+ gap = '1rem',
16
+ }) => {
17
+ return (
18
+ <div className={`frc-root ${className}`} style={{ ...style, ['--frc-gap' as any]: gap }}>
19
+ {React.Children.map(children, (child) => (
20
+ <div className='frc-item'>{child}</div>
21
+ ))}
22
+ </div>
23
+ );
24
+ };
@@ -0,0 +1,56 @@
1
+ .clb-root {
2
+ padding: 0.125rem;
3
+ }
4
+ .clb-title {
5
+ font-weight: var(--font-bold);
6
+ padding: 0.0625rem 0.125rem;
7
+ margin-bottom: 0.0625rem;
8
+ }
9
+
10
+ .clb-grid {
11
+ display: flex;
12
+ flex-direction: column;
13
+ gap: 0.125rem;
14
+ }
15
+
16
+ .clb-row {
17
+ display: grid;
18
+ grid-template-columns: 1fr 1fr;
19
+ gap: var(--col-gap, 0.5rem);
20
+ align-items: center;
21
+ padding: 0;
22
+ }
23
+
24
+ .clb-badge-col {
25
+ display: flex;
26
+ justify-content: flex-end;
27
+ align-items: center;
28
+ }
29
+ .counter-badge {
30
+ display: flex;
31
+ align-items: center;
32
+ justify-content: center;
33
+ border-radius: 9999px;
34
+ color: #fff;
35
+ min-width: 0;
36
+ white-space: nowrap;
37
+ line-height: 1;
38
+ padding: 0.25rem 0.5rem;
39
+ box-sizing: border-box;
40
+ }
41
+ .clb-text {
42
+ padding: 0.25rem 0;
43
+ min-width: 0;
44
+ overflow: hidden;
45
+ word-wrap: break-word;
46
+ overflow-wrap: break-word;
47
+ }
48
+
49
+ .clb-fullrow {
50
+ grid-column: 1 / -1;
51
+ padding: 0.25rem 0.125rem;
52
+ text-align: center;
53
+ }
54
+ .clb-empty-badge {
55
+ min-height: 1px;
56
+ }
@@ -0,0 +1,292 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import { CounterListBox } from './CounterListBox';
3
+
4
+ const meta: Meta<typeof CounterListBox> = {
5
+ title: 'Components/ListBox/CounterListBox',
6
+ component: CounterListBox,
7
+ parameters: {
8
+ layout: 'centered',
9
+ docs: {
10
+ description: {
11
+ component: 'A list component with circular badges for displaying counters and metrics.',
12
+ },
13
+ },
14
+ },
15
+ tags: ['autodocs'],
16
+ argTypes: {
17
+ badgeColor: {
18
+ control: 'color',
19
+ description: 'Default badge color',
20
+ },
21
+ badgePadding: {
22
+ control: 'text',
23
+ description: 'Badge padding (e.g., "8px 16px")',
24
+ },
25
+ badgeWidth: {
26
+ control: 'text',
27
+ description: 'Forced badge width (e.g., "40px", "60px")',
28
+ },
29
+ data: {
30
+ control: 'object',
31
+ description: 'Array of strings or [badge, text] tuples',
32
+ },
33
+ },
34
+ };
35
+
36
+ export default meta;
37
+ type Story = StoryObj<typeof meta>;
38
+
39
+ export const Default: Story = {
40
+ name: 'Default',
41
+ args: {
42
+ title: 'Statistics',
43
+ data: [
44
+ ['15', 'New messages'],
45
+ ['42', 'Active users'],
46
+ ['128', 'Total visits'],
47
+ ['7', 'Pending'],
48
+ ],
49
+ badgeColor: '#0ea5e9',
50
+ },
51
+ };
52
+
53
+ export const MixedTypes: Story = {
54
+ name: 'Mixed Types',
55
+ args: {
56
+ title: 'System Dashboard',
57
+ data: [
58
+ ['99+', 'Unread notifications'],
59
+ 'No action required currently',
60
+ ['7', 'Overdue tasks'],
61
+ 'All systems functioning normally',
62
+ ['3', 'Unresolved alerts'],
63
+ 'Maintenance scheduled this weekend',
64
+ ],
65
+ badgeColor: '#8b5cf6',
66
+ },
67
+ };
68
+
69
+ export const ColorfulBadges: Story = {
70
+ name: 'Colorful Badges',
71
+ args: {
72
+ title: 'Performance Evaluation',
73
+ data: [
74
+ ['A+', 'Excellent'],
75
+ ['B', 'Good'],
76
+ ['C', 'Average'],
77
+ ['D', 'Needs improvement'],
78
+ ['F', 'Critical'],
79
+ ],
80
+ badgeColor: '#6b7280',
81
+ badgeColors: {
82
+ 0: '#10b981',
83
+ 1: '#22c55e',
84
+ 2: '#f59e0b',
85
+ 3: '#f97316',
86
+ 4: '#ef4444',
87
+ },
88
+ },
89
+ };
90
+
91
+ export const TicketPriorities: Story = {
92
+ name: 'Ticket Priorities',
93
+ args: {
94
+ title: 'Tickets by Priority',
95
+ data: [
96
+ ['5', 'Critical - Immediate intervention required'],
97
+ ['12', 'High - Resolution within 24h'],
98
+ ['28', 'Medium - Resolution within 48h'],
99
+ ['45', 'Low - Resolution within 7 days'],
100
+ ],
101
+ badgeColor: '#ef4444',
102
+ badgeColors: {
103
+ 0: '#dc2626',
104
+ 1: '#f97316',
105
+ 2: '#eab308',
106
+ 3: '#84cc16',
107
+ },
108
+ lineClasses: {
109
+ 0: 'ticket-critical',
110
+ 1: 'ticket-high',
111
+ 2: 'ticket-medium',
112
+ },
113
+ },
114
+ decorators: [
115
+ (Story) => (
116
+ <>
117
+ <style>
118
+ {`
119
+ .ticket-critical { background-color: #fef2f2; }
120
+ .ticket-high { background-color: #fffbeb; }
121
+ .ticket-medium { background-color: #f0f9ff; }
122
+ `}
123
+ </style>
124
+ <Story />
125
+ </>
126
+ ),
127
+ ],
128
+ };
129
+
130
+ export const ProgressIndicators: Story = {
131
+ name: 'Progress Indicators',
132
+ args: {
133
+ title: 'Project Progress',
134
+ data: [
135
+ ['75%', 'Website - Frontend development'],
136
+ ['90%', 'Mobile app - User testing'],
137
+ ['50%', 'API backend - Service integration'],
138
+ ['25%', 'Documentation - Writing in progress'],
139
+ ],
140
+ badgeColor: '#3b82f6',
141
+ badgePadding: '0.5rem 0.75rem',
142
+ },
143
+ };
144
+
145
+ export const RatingSystem: Story = {
146
+ name: 'Rating System',
147
+ args: {
148
+ title: 'Customer Reviews',
149
+ data: [
150
+ ['4.8', '⭐ Excellent - Exceptional service'],
151
+ ['4.2', '⭐ Very good - Very satisfied'],
152
+ ['3.5', '⭐ Average - Could be better'],
153
+ ['2.1', '⭐ Poor - Disappointed'],
154
+ ],
155
+ badgeColor: '#f59e0b',
156
+ },
157
+ };
158
+
159
+ export const SmallCounters: Story = {
160
+ name: 'Small Counters',
161
+ args: {
162
+ title: 'System Logs',
163
+ data: [
164
+ ['1', 'Critical error'],
165
+ ['5', 'Warnings'],
166
+ ['42', 'Information'],
167
+ ['128', 'Debug messages'],
168
+ ],
169
+ badgeColor: '#6366f1',
170
+ badgePadding: '0.25rem 0.5rem',
171
+ },
172
+ };
173
+
174
+ export const StatusIndicators: Story = {
175
+ name: 'Status Indicators',
176
+ args: {
177
+ title: 'Server Status',
178
+ data: [
179
+ ['🟢', 'Main server - Online'],
180
+ ['🟢', 'Database - Online'],
181
+ ['🟡', 'Cache - Degraded'],
182
+ ['🔴', 'Backup - Offline'],
183
+ ['🟢', 'CDN - Online'],
184
+ ],
185
+ badgeColor: '#6b7280',
186
+ badgePadding: '0.375rem 0.5rem',
187
+ },
188
+ };
189
+
190
+ export const LargeNumbers: Story = {
191
+ name: 'Large Numbers',
192
+ args: {
193
+ title: 'Global Statistics',
194
+ data: [
195
+ ['1.2K', 'Active users'],
196
+ ['45.8K', 'Total views'],
197
+ ['2.4M', 'Impressions'],
198
+ ['156.7K', 'Interactions'],
199
+ ],
200
+ badgeColor: '#8b5cf6',
201
+ badgePadding: '0.5rem 0.75rem',
202
+ },
203
+ };
204
+
205
+ export const FixedWidthBadges: Story = {
206
+ name: 'Fixed Width Badges',
207
+ args: {
208
+ title: 'Controlled Width Badges',
209
+ data: [
210
+ ['1', 'Single digit'],
211
+ ['42', 'Two digits'],
212
+ ['999', 'Three digits'],
213
+ ['1K', 'Short text'],
214
+ ['10K+', 'Longer text'],
215
+ ],
216
+ badgeColor: '#8b5cf6',
217
+ badgeWidth: '48px',
218
+ badgePadding: '0.5rem 0.25rem',
219
+ },
220
+ parameters: {
221
+ docs: {
222
+ description: {
223
+ story:
224
+ 'Using the `badgeWidth` prop to force a fixed width on all badges, creating perfect alignment.',
225
+ },
226
+ },
227
+ },
228
+ };
229
+
230
+ export const CompactFixedBadges: Story = {
231
+ name: 'Compact Fixed Badges',
232
+ args: {
233
+ title: 'System Metrics',
234
+ data: [
235
+ ['CPU', '45%'],
236
+ ['RAM', '68%'],
237
+ ['SSD', '82%'],
238
+ ['NET', '24%'],
239
+ ],
240
+ badgeColor: '#06b6d4',
241
+ badgeWidth: '40px',
242
+ badgePadding: '0.375rem',
243
+ },
244
+ };
245
+
246
+ export const UniformBadges: Story = {
247
+ name: 'Uniform Badges',
248
+ args: {
249
+ title: 'Uniform Statistics',
250
+ data: [
251
+ ['A+', 'Excellent'],
252
+ ['B', 'Good'],
253
+ ['C', 'Average'],
254
+ ['D', 'Poor'],
255
+ ],
256
+ badgeColor: '#f59e0b',
257
+ badgeWidth: '44px',
258
+ badgePadding: '0.375rem 0.25rem',
259
+ badgeColors: {
260
+ 0: '#10b981',
261
+ 1: '#22c55e',
262
+ 2: '#f59e0b',
263
+ 3: '#ef4444',
264
+ },
265
+ },
266
+ };
267
+
268
+ export const AdaptiveVsFixed: Story = {
269
+ name: 'Adaptive vs Fixed Comparison',
270
+ args: {
271
+ title: 'Adaptive (without badgeWidth)',
272
+ data: [
273
+ ['1', 'Small'],
274
+ ['42', 'Medium'],
275
+ ['999', 'Large'],
276
+ ['1K+', 'Very large'],
277
+ ],
278
+ badgeColor: '#0ea5e9',
279
+ },
280
+ render: (args) => (
281
+ <div style={{ display: 'flex', gap: '2rem', alignItems: 'flex-start' }}>
282
+ <div>
283
+ <h4 style={{ marginBottom: '0.5rem' }}>Adaptive (without badgeWidth)</h4>
284
+ <CounterListBox {...args} />
285
+ </div>
286
+ <div>
287
+ <h4 style={{ marginBottom: '0.5rem' }}>Fixed (with badgeWidth="48px")</h4>
288
+ <CounterListBox {...args} badgeWidth='48px' />
289
+ </div>
290
+ </div>
291
+ ),
292
+ };