@shohojdhara/atomix 0.1.30 → 0.2.1

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 (469) hide show
  1. package/CHANGELOG.md +0 -0
  2. package/LICENSE +0 -0
  3. package/README.md +151 -39
  4. package/dist/atomix.css +13529 -0
  5. package/dist/atomix.min.css +15 -0
  6. package/dist/index.d.ts +6112 -1757
  7. package/dist/index.esm.js +16852 -8364
  8. package/dist/index.esm.js.map +1 -1
  9. package/dist/index.js +16892 -8369
  10. package/dist/index.js.map +1 -1
  11. package/dist/index.min.js +1 -1
  12. package/dist/index.min.js.map +1 -1
  13. package/dist/themes/boomdevs.css +13241 -0
  14. package/dist/themes/boomdevs.min.css +353 -0
  15. package/dist/themes/esrar.css +15374 -0
  16. package/dist/themes/esrar.min.css +189 -0
  17. package/dist/themes/mashroom.css +28079 -0
  18. package/dist/themes/mashroom.min.css +403 -0
  19. package/dist/themes/shaj-default.css +14203 -0
  20. package/dist/themes/shaj-default.min.css +500 -0
  21. package/dist/themes/yabai.css +13711 -0
  22. package/dist/themes/yabai.min.css +189 -0
  23. package/package.json +126 -99
  24. package/src/components/Accordion/Accordion.stories.tsx +271 -0
  25. package/src/components/Accordion/Accordion.tsx +131 -0
  26. package/src/components/Accordion/index.ts +3 -0
  27. package/src/components/AtomixLogo/AtomixLogo.tsx +36 -0
  28. package/src/components/AtomixLogo/index.ts +3 -0
  29. package/src/components/AtomixLogo.tsx +40 -0
  30. package/src/components/Avatar/Avatar.stories.tsx +257 -0
  31. package/src/components/Avatar/Avatar.tsx +68 -0
  32. package/src/components/Avatar/AvatarGroup.tsx +73 -0
  33. package/src/components/Avatar/index.ts +3 -0
  34. package/src/components/Badge/Badge.stories.tsx +371 -0
  35. package/src/components/Badge/Badge.tsx +39 -0
  36. package/src/components/Badge/index.ts +3 -0
  37. package/src/components/Block/Block.stories.tsx +408 -0
  38. package/src/components/Block/Block.tsx +137 -0
  39. package/src/components/Block/index.ts +1 -0
  40. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +106 -0
  41. package/src/components/Breadcrumb/Breadcrumb.tsx +112 -0
  42. package/src/components/Breadcrumb/index.ts +3 -0
  43. package/src/components/Button/Button.stories.tsx +312 -0
  44. package/src/components/Button/Button.tsx +69 -0
  45. package/src/components/Button/index.ts +3 -0
  46. package/src/components/Callout/Callout.stories.tsx +588 -0
  47. package/src/components/Callout/Callout.tsx +78 -0
  48. package/src/components/Callout/index.ts +1 -0
  49. package/src/components/Card/Card.stories.tsx +105 -0
  50. package/src/components/Card/Card.tsx +69 -0
  51. package/src/components/Card/ElevationCard.tsx +47 -0
  52. package/src/components/Card/index.ts +15 -0
  53. package/src/components/Chart/AdvancedChart.tsx +624 -0
  54. package/src/components/Chart/AnimatedChart.tsx +206 -0
  55. package/src/components/Chart/AreaChart.tsx +27 -0
  56. package/src/components/Chart/BarChart.tsx +148 -0
  57. package/src/components/Chart/BubbleChart.tsx +411 -0
  58. package/src/components/Chart/CandlestickChart.tsx +765 -0
  59. package/src/components/Chart/Chart.stories.tsx +527 -0
  60. package/src/components/Chart/Chart.tsx +218 -0
  61. package/src/components/Chart/ChartRenderer.tsx +322 -0
  62. package/src/components/Chart/ChartToolbar.tsx +436 -0
  63. package/src/components/Chart/ChartTooltip.tsx +101 -0
  64. package/src/components/Chart/DonutChart.tsx +370 -0
  65. package/src/components/Chart/FunnelChart.tsx +393 -0
  66. package/src/components/Chart/GaugeChart.tsx +550 -0
  67. package/src/components/Chart/HeatmapChart.tsx +614 -0
  68. package/src/components/Chart/LineChart.tsx +172 -0
  69. package/src/components/Chart/LineChartNew.tsx +167 -0
  70. package/src/components/Chart/MultiAxisChart.tsx +498 -0
  71. package/src/components/Chart/PieChart.tsx +103 -0
  72. package/src/components/Chart/RadarChart.tsx +332 -0
  73. package/src/components/Chart/RealTimeChart.tsx +436 -0
  74. package/src/components/Chart/ScatterChart.tsx +152 -0
  75. package/src/components/Chart/TreemapChart.tsx +574 -0
  76. package/src/components/Chart/WaterfallChart.tsx +450 -0
  77. package/src/components/Chart/index.ts +119 -0
  78. package/src/components/Chart/types.ts +338 -0
  79. package/src/components/ColorModeToggle/ColorModeToggle.stories.tsx +44 -0
  80. package/src/components/ColorModeToggle/ColorModeToggle.tsx +85 -0
  81. package/src/components/ColorModeToggle/index.ts +2 -0
  82. package/src/components/Countdown/Countdown.stories.tsx +46 -0
  83. package/src/components/Countdown/Countdown.tsx +90 -0
  84. package/src/components/Countdown/index.ts +2 -0
  85. package/src/components/DataTable/DataTable.stories.tsx +248 -0
  86. package/src/components/DataTable/DataTable.tsx +213 -0
  87. package/src/components/DataTable/index.ts +3 -0
  88. package/src/components/DatePicker/DatePicker.stories.tsx +364 -0
  89. package/src/components/DatePicker/DatePicker.tsx +504 -0
  90. package/src/components/DatePicker/index.ts +4 -0
  91. package/src/components/DatePicker/readme.md +106 -0
  92. package/src/components/DatePicker/types.ts +167 -0
  93. package/src/components/DatePicker/utils.ts +185 -0
  94. package/src/components/Dropdown/Dropdown.stories.tsx +358 -0
  95. package/src/components/Dropdown/Dropdown.tsx +352 -0
  96. package/src/components/Dropdown/index.ts +14 -0
  97. package/src/components/Dropdown/readme.md +151 -0
  98. package/src/components/EdgePanel/EdgePanel.stories.tsx +266 -0
  99. package/src/components/EdgePanel/EdgePanel.tsx +73 -0
  100. package/src/components/EdgePanel/index.ts +1 -0
  101. package/src/components/Form/Checkbox.stories.tsx +76 -0
  102. package/src/components/Form/Checkbox.tsx +69 -0
  103. package/src/components/Form/Form.stories.tsx +497 -0
  104. package/src/components/Form/Form.tsx +46 -0
  105. package/src/components/Form/FormGroup.stories.tsx +162 -0
  106. package/src/components/Form/FormGroup.tsx +53 -0
  107. package/src/components/Form/Input.stories.tsx +106 -0
  108. package/src/components/Form/Input.tsx +87 -0
  109. package/src/components/Form/Radio.stories.tsx +94 -0
  110. package/src/components/Form/Radio.tsx +65 -0
  111. package/src/components/Form/Select.stories.tsx +151 -0
  112. package/src/components/Form/Select.tsx +191 -0
  113. package/src/components/Form/Textarea.stories.tsx +123 -0
  114. package/src/components/Form/Textarea.tsx +78 -0
  115. package/src/components/Form/index.ts +7 -0
  116. package/src/components/Hero/Hero.stories.tsx +295 -0
  117. package/src/components/Hero/Hero.tsx +175 -0
  118. package/src/components/Hero/index.ts +6 -0
  119. package/src/components/Icon/Icon.tsx +87 -0
  120. package/src/components/Icon/index.ts +2 -0
  121. package/src/components/List/List.stories.tsx +122 -0
  122. package/src/components/List/List.tsx +35 -0
  123. package/src/components/List/ListGroup.tsx +35 -0
  124. package/src/components/List/index.ts +2 -0
  125. package/src/components/Messages/Messages.stories.tsx +160 -0
  126. package/src/components/Messages/Messages.tsx +172 -0
  127. package/src/components/Messages/index.ts +3 -0
  128. package/src/components/Modal/Modal.stories.tsx +284 -0
  129. package/src/components/Modal/Modal.tsx +198 -0
  130. package/src/components/Modal/README.md +169 -0
  131. package/src/components/Modal/index.ts +1 -0
  132. package/src/components/Navigation/Menu/MegaMenu.tsx +109 -0
  133. package/src/components/Navigation/Menu/Menu.stories.tsx +339 -0
  134. package/src/components/Navigation/Menu/Menu.tsx +111 -0
  135. package/src/components/Navigation/Nav/Nav.stories.tsx +456 -0
  136. package/src/components/Navigation/Nav/Nav.tsx +51 -0
  137. package/src/components/Navigation/Nav/NavDropdown.tsx +105 -0
  138. package/src/components/Navigation/Nav/NavItem.tsx +168 -0
  139. package/src/components/Navigation/Navbar/Navbar.stories.tsx +569 -0
  140. package/src/components/Navigation/Navbar/Navbar.tsx +150 -0
  141. package/src/components/Navigation/README.md +314 -0
  142. package/src/components/Navigation/SideMenu/SideMenu.README.md +494 -0
  143. package/src/components/Navigation/SideMenu/SideMenu.stories.tsx +609 -0
  144. package/src/components/Navigation/SideMenu/SideMenu.tsx +101 -0
  145. package/src/components/Navigation/SideMenu/SideMenuItem.tsx +103 -0
  146. package/src/components/Navigation/SideMenu/SideMenuList.tsx +41 -0
  147. package/src/components/Navigation/index.ts +23 -0
  148. package/src/components/Pagination/Pagination.stories.tsx +188 -0
  149. package/src/components/Pagination/Pagination.tsx +162 -0
  150. package/src/components/Pagination/index.ts +1 -0
  151. package/src/components/PhotoViewer/PhotoViewer.stories.tsx +397 -0
  152. package/src/components/PhotoViewer/PhotoViewer.tsx +246 -0
  153. package/src/components/PhotoViewer/PhotoViewerHeader.tsx +184 -0
  154. package/src/components/PhotoViewer/PhotoViewerImage.tsx +173 -0
  155. package/src/components/PhotoViewer/PhotoViewerInfo.tsx +91 -0
  156. package/src/components/PhotoViewer/PhotoViewerNavigation.tsx +85 -0
  157. package/src/components/PhotoViewer/PhotoViewerThumbnails.tsx +63 -0
  158. package/src/components/PhotoViewer/README.md +358 -0
  159. package/src/components/PhotoViewer/examples/ImageGallery.tsx +187 -0
  160. package/src/components/PhotoViewer/examples/SimpleGallery.tsx +73 -0
  161. package/src/components/PhotoViewer/examples/index.ts +2 -0
  162. package/src/components/PhotoViewer/index.ts +14 -0
  163. package/src/components/Popover/Popover.stories.tsx +143 -0
  164. package/src/components/Popover/Popover.tsx +137 -0
  165. package/src/components/Popover/index.ts +5 -0
  166. package/src/components/Popover/readme.md +120 -0
  167. package/src/components/ProductReview/ProductReview.stories.tsx +88 -0
  168. package/src/components/ProductReview/ProductReview.tsx +169 -0
  169. package/src/components/ProductReview/index.ts +3 -0
  170. package/src/components/Progress/Progress.stories.tsx +75 -0
  171. package/src/components/Progress/Progress.tsx +45 -0
  172. package/src/components/Progress/index.ts +1 -0
  173. package/src/components/Rating/Rating.stories.tsx +109 -0
  174. package/src/components/Rating/Rating.tsx +286 -0
  175. package/src/components/Rating/index.ts +6 -0
  176. package/src/components/River/River.stories.tsx +230 -0
  177. package/src/components/River/River.tsx +134 -0
  178. package/src/components/River/index.ts +2 -0
  179. package/src/components/SectionIntro/SectionIntro.stories.tsx +143 -0
  180. package/src/components/SectionIntro/SectionIntro.tsx +184 -0
  181. package/src/components/SectionIntro/index.ts +3 -0
  182. package/src/components/Slider/Slider.stories.tsx +241 -0
  183. package/src/components/Slider/Slider.tsx +225 -0
  184. package/src/components/Slider/index.ts +24 -0
  185. package/src/components/Spinner/Spinner.stories.tsx +65 -0
  186. package/src/components/Spinner/Spinner.tsx +36 -0
  187. package/src/components/Spinner/index.ts +2 -0
  188. package/src/components/Steps/Steps.stories.tsx +158 -0
  189. package/src/components/Steps/Steps.tsx +115 -0
  190. package/src/components/Steps/index.ts +3 -0
  191. package/src/components/Tab/Tab.stories.tsx +129 -0
  192. package/src/components/Tab/Tab.tsx +111 -0
  193. package/src/components/Tab/index.ts +2 -0
  194. package/src/components/Testimonial/Testimonial.stories.tsx +180 -0
  195. package/src/components/Testimonial/Testimonial.tsx +138 -0
  196. package/src/components/Testimonial/index.ts +3 -0
  197. package/src/components/Todo/Todo.stories.tsx +103 -0
  198. package/src/components/Todo/Todo.tsx +158 -0
  199. package/src/components/Todo/index.ts +1 -0
  200. package/src/components/Toggle/Toggle.stories.tsx +49 -0
  201. package/src/components/Toggle/Toggle.tsx +84 -0
  202. package/src/components/Toggle/index.ts +2 -0
  203. package/src/components/Tooltip/Tooltip.stories.tsx +115 -0
  204. package/src/components/Tooltip/Tooltip.tsx +150 -0
  205. package/src/components/Tooltip/index.ts +3 -0
  206. package/src/components/Upload/Upload.stories.tsx +220 -0
  207. package/src/components/Upload/Upload.tsx +354 -0
  208. package/src/components/Upload/index.ts +3 -0
  209. package/src/components/VideoPlayer/VideoPlayer.stories.tsx +484 -0
  210. package/src/components/VideoPlayer/VideoPlayer.tsx +574 -0
  211. package/src/components/VideoPlayer/index.ts +7 -0
  212. package/src/components/index.ts +111 -0
  213. package/src/layouts/Grid/Container.tsx +58 -0
  214. package/src/layouts/Grid/Grid.stories.tsx +861 -0
  215. package/src/layouts/Grid/Grid.tsx +68 -0
  216. package/src/layouts/Grid/GridCol.tsx +161 -0
  217. package/src/layouts/Grid/README.md +108 -0
  218. package/src/layouts/Grid/Row.tsx +70 -0
  219. package/src/layouts/Grid/index.ts +8 -0
  220. package/src/layouts/MasonryGrid/MasonryGrid.stories.tsx +387 -0
  221. package/src/layouts/MasonryGrid/MasonryGrid.tsx +408 -0
  222. package/src/layouts/MasonryGrid/MasonryGridItem.tsx +44 -0
  223. package/src/layouts/MasonryGrid/README.md +117 -0
  224. package/src/layouts/MasonryGrid/index.ts +4 -0
  225. package/src/layouts/index.ts +7 -0
  226. package/src/lib/README.md +89 -0
  227. package/src/lib/composables/index.ts +63 -0
  228. package/src/lib/composables/useAccordion.ts +129 -0
  229. package/src/lib/composables/useAmbientMode.ts +90 -0
  230. package/src/lib/composables/useBadge.ts +42 -0
  231. package/src/lib/composables/useBarChart.ts +365 -0
  232. package/src/lib/composables/useBlock.ts +56 -0
  233. package/src/lib/composables/useBreadcrumb.ts +81 -0
  234. package/src/lib/composables/useButton.ts +59 -0
  235. package/src/lib/composables/useCallout.ts +55 -0
  236. package/src/lib/composables/useCard.ts +155 -0
  237. package/src/lib/composables/useChart.ts +1082 -0
  238. package/src/lib/composables/useChartAnalytics.ts +505 -0
  239. package/src/lib/composables/useChartData.ts +38 -0
  240. package/src/lib/composables/useChartExport.ts +392 -0
  241. package/src/lib/composables/useChartInteraction.ts +34 -0
  242. package/src/lib/composables/useChartInteractions.ts +123 -0
  243. package/src/lib/composables/useChartPerformance.ts +323 -0
  244. package/src/lib/composables/useChartScale.ts +48 -0
  245. package/src/lib/composables/useChartToolbar.ts +532 -0
  246. package/src/lib/composables/useCheckbox.ts +70 -0
  247. package/src/lib/composables/useDataTable.ts +208 -0
  248. package/src/lib/composables/useDatePicker.ts +564 -0
  249. package/src/lib/composables/useDropdown.ts +272 -0
  250. package/src/lib/composables/useEdgePanel.ts +261 -0
  251. package/src/lib/composables/useForm.ts +62 -0
  252. package/src/lib/composables/useFormGroup.ts +51 -0
  253. package/src/lib/composables/useHero.ts +250 -0
  254. package/src/lib/composables/useInput.ts +58 -0
  255. package/src/lib/composables/useLineChart.ts +319 -0
  256. package/src/lib/composables/useMessages.ts +77 -0
  257. package/src/lib/composables/useModal.ts +110 -0
  258. package/src/lib/composables/useNavbar.ts +288 -0
  259. package/src/lib/composables/usePagination.ts +101 -0
  260. package/src/lib/composables/usePhotoViewer.ts +937 -0
  261. package/src/lib/composables/usePieChart.ts +362 -0
  262. package/src/lib/composables/usePopover.ts +354 -0
  263. package/src/lib/composables/useProgress.ts +74 -0
  264. package/src/lib/composables/useRadio.ts +47 -0
  265. package/src/lib/composables/useRating.ts +174 -0
  266. package/src/lib/composables/useRiver.ts +205 -0
  267. package/src/lib/composables/useSelect.ts +52 -0
  268. package/src/lib/composables/useSideMenu.ts +197 -0
  269. package/src/lib/composables/useSlider.ts +339 -0
  270. package/src/lib/composables/useSpinner.ts +42 -0
  271. package/src/lib/composables/useTextarea.ts +55 -0
  272. package/src/lib/composables/useTodo.ts +141 -0
  273. package/src/lib/composables/useVideoPlayer.ts +398 -0
  274. package/src/lib/constants/components.ts +1433 -0
  275. package/src/lib/constants/index.ts +4 -0
  276. package/src/lib/index.ts +11 -0
  277. package/src/lib/types/components.ts +4750 -0
  278. package/src/lib/types/index.ts +2 -0
  279. package/src/lib/utils/dom.ts +41 -0
  280. package/src/lib/utils/icons.ts +74 -0
  281. package/src/lib/utils/index.ts +55 -0
  282. package/src/lib/utils/useForkRef.test.tsx +64 -0
  283. package/src/lib/utils/useForkRef.ts +36 -0
  284. package/src/lib/utils.test.ts +14 -0
  285. package/src/styles/01-settings/_index.scss +2 -0
  286. package/src/styles/01-settings/_settings.accordion.scss +7 -5
  287. package/src/styles/01-settings/_settings.animations.scss +0 -0
  288. package/src/styles/01-settings/_settings.avatar-group.scss +6 -3
  289. package/src/styles/01-settings/_settings.avatar.scss +2 -2
  290. package/src/styles/01-settings/_settings.badge.scss +15 -9
  291. package/src/styles/01-settings/_settings.block.scss +11 -0
  292. package/src/styles/01-settings/_settings.border-radius.scss +12 -9
  293. package/src/styles/01-settings/_settings.border.scss +4 -1
  294. package/src/styles/01-settings/_settings.box-shadow.scss +1 -1
  295. package/src/styles/01-settings/_settings.breadcrumb.scss +9 -8
  296. package/src/styles/01-settings/_settings.breakpoints.scss +0 -0
  297. package/src/styles/01-settings/_settings.btn-group.scss +4 -1
  298. package/src/styles/01-settings/_settings.button.scss +19 -21
  299. package/src/styles/01-settings/_settings.callout.scss +42 -24
  300. package/src/styles/01-settings/_settings.card.scss +12 -10
  301. package/src/styles/01-settings/_settings.chart.scss +199 -0
  302. package/src/styles/01-settings/_settings.checkbox-group.scss +0 -0
  303. package/src/styles/01-settings/_settings.checkbox.scss +0 -0
  304. package/src/styles/01-settings/_settings.color-mode.scss +0 -0
  305. package/src/styles/01-settings/_settings.colors.scss +20 -0
  306. package/src/styles/01-settings/_settings.config.scss +1 -1
  307. package/src/styles/01-settings/_settings.countdown.scss +0 -0
  308. package/src/styles/01-settings/_settings.data-table.scss +0 -0
  309. package/src/styles/01-settings/_settings.datepicker.scss +0 -0
  310. package/src/styles/01-settings/_settings.dropdown.scss +0 -0
  311. package/src/styles/01-settings/_settings.edge-panel.scss +0 -0
  312. package/src/styles/01-settings/_settings.fonts.scss +1 -1
  313. package/src/styles/01-settings/_settings.form-group.scss +0 -0
  314. package/src/styles/01-settings/_settings.form.scss +0 -0
  315. package/src/styles/01-settings/_settings.grid.scss +3 -3
  316. package/src/styles/01-settings/_settings.hero.scss +1 -1
  317. package/src/styles/01-settings/_settings.input.scss +1 -1
  318. package/src/styles/01-settings/_settings.link.scss +0 -0
  319. package/src/styles/01-settings/_settings.list-group.scss +0 -0
  320. package/src/styles/01-settings/_settings.list.scss +0 -0
  321. package/src/styles/01-settings/_settings.maps.scss +43 -8
  322. package/src/styles/01-settings/_settings.masonry-grid.scss +0 -0
  323. package/src/styles/01-settings/_settings.menu.scss +0 -0
  324. package/src/styles/01-settings/_settings.messages.scss +0 -0
  325. package/src/styles/01-settings/_settings.modal.scss +1 -1
  326. package/src/styles/01-settings/_settings.nav.scss +0 -0
  327. package/src/styles/01-settings/_settings.navbar.scss +0 -0
  328. package/src/styles/01-settings/_settings.pagination.scss +0 -0
  329. package/src/styles/01-settings/_settings.photoviewer.scss +89 -23
  330. package/src/styles/01-settings/_settings.popover.scss +0 -0
  331. package/src/styles/01-settings/_settings.position.scss +0 -0
  332. package/src/styles/01-settings/_settings.progress.scss +0 -0
  333. package/src/styles/01-settings/_settings.rating.scss +0 -0
  334. package/src/styles/01-settings/_settings.river.scss +0 -0
  335. package/src/styles/01-settings/_settings.sectionintro.scss +0 -0
  336. package/src/styles/01-settings/_settings.select.scss +0 -0
  337. package/src/styles/01-settings/_settings.side-menu.scss +0 -0
  338. package/src/styles/01-settings/_settings.skeleton.scss +0 -0
  339. package/src/styles/01-settings/_settings.slider.scss +59 -0
  340. package/src/styles/01-settings/_settings.spacing.scss +11 -3
  341. package/src/styles/01-settings/_settings.spinner.scss +0 -0
  342. package/src/styles/01-settings/_settings.steps.scss +1 -1
  343. package/src/styles/01-settings/_settings.tabs.scss +4 -4
  344. package/src/styles/01-settings/_settings.testimonials.scss +0 -0
  345. package/src/styles/01-settings/_settings.todo.scss +0 -0
  346. package/src/styles/01-settings/_settings.toggle.scss +1 -1
  347. package/src/styles/01-settings/_settings.tooltip.scss +0 -0
  348. package/src/styles/01-settings/_settings.typography.scss +2 -0
  349. package/src/styles/01-settings/_settings.upload.scss +0 -0
  350. package/src/styles/01-settings/_settings.video-player.scss +64 -0
  351. package/src/styles/01-settings/_settings.z-layers.scss +0 -0
  352. package/src/styles/02-tools/_index.scss +1 -0
  353. package/src/styles/02-tools/_tools.animations.scss +82 -0
  354. package/src/styles/02-tools/_tools.border-radius.scss +0 -0
  355. package/src/styles/02-tools/_tools.breakpoints.scss +0 -0
  356. package/src/styles/02-tools/_tools.button.scss +5 -0
  357. package/src/styles/02-tools/_tools.clearfix.scss +0 -0
  358. package/src/styles/02-tools/_tools.color-functions.scss +0 -0
  359. package/src/styles/02-tools/_tools.color-mode.scss +1 -1
  360. package/src/styles/02-tools/_tools.component.scss +479 -0
  361. package/src/styles/02-tools/_tools.event.scss +0 -0
  362. package/src/styles/02-tools/_tools.grid.scss +0 -0
  363. package/src/styles/02-tools/_tools.hidden-visually.scss +0 -0
  364. package/src/styles/02-tools/_tools.hidden.scss +0 -0
  365. package/src/styles/02-tools/_tools.map-loop.scss +0 -0
  366. package/src/styles/02-tools/_tools.media-queries.scss +0 -0
  367. package/src/styles/02-tools/_tools.object-fit.scss +0 -0
  368. package/src/styles/02-tools/_tools.placeholder.scss +0 -0
  369. package/src/styles/02-tools/_tools.rem.scss +5 -1
  370. package/src/styles/02-tools/_tools.size.scss +0 -0
  371. package/src/styles/02-tools/_tools.spacing.scss +0 -0
  372. package/src/styles/02-tools/_tools.to-rgb.scss +0 -0
  373. package/src/styles/02-tools/_tools.transition.scss +0 -0
  374. package/src/styles/02-tools/_tools.utilities.scss +0 -0
  375. package/src/styles/02-tools/_tools.utility-api.scss +23 -2
  376. package/src/styles/03-generic/_generic.fonts.scss +0 -0
  377. package/src/styles/03-generic/_generic.reset.scss +0 -0
  378. package/src/styles/03-generic/_generic.root.scss +5 -1
  379. package/src/styles/03-generic/_generic.selection.scss +0 -0
  380. package/src/styles/03-generic/_index.scss +0 -0
  381. package/src/styles/04-elements/_elements.all.scss +0 -0
  382. package/src/styles/04-elements/_elements.body.scss +0 -0
  383. package/src/styles/04-elements/_elements.heading.scss +0 -0
  384. package/src/styles/04-elements/_elements.html.scss +0 -0
  385. package/src/styles/04-elements/_elements.links.scss +0 -0
  386. package/src/styles/04-elements/_index.scss +0 -0
  387. package/src/styles/05-objects/_index.scss +1 -0
  388. package/src/styles/05-objects/_objects.block.scss +122 -0
  389. package/src/styles/05-objects/_objects.container.scss +14 -10
  390. package/src/styles/05-objects/_objects.grid.scss +0 -0
  391. package/src/styles/05-objects/_objects.masonry-grid.scss +0 -0
  392. package/src/styles/06-components/_components.accordion.scss +3 -1
  393. package/src/styles/06-components/_components.avatar-group.scss +0 -0
  394. package/src/styles/06-components/_components.avatar.scss +0 -0
  395. package/src/styles/06-components/_components.badge.scss +9 -9
  396. package/src/styles/06-components/_components.breadcrumb.scss +0 -0
  397. package/src/styles/06-components/_components.btn-group.scss +0 -0
  398. package/src/styles/06-components/_components.button.scss +0 -0
  399. package/src/styles/06-components/_components.callout.scss +2 -1
  400. package/src/styles/06-components/_components.card.scss +0 -1
  401. package/src/styles/06-components/_components.chart.scss +2102 -0
  402. package/src/styles/06-components/_components.checkbox-group.scss +0 -0
  403. package/src/styles/06-components/_components.checkbox.scss +0 -0
  404. package/src/styles/06-components/_components.color-mode-toggle.scss +0 -0
  405. package/src/styles/06-components/_components.countdown.scss +0 -0
  406. package/src/styles/06-components/_components.data-table.scss +0 -0
  407. package/src/styles/06-components/_components.datepicker.scss +0 -0
  408. package/src/styles/06-components/_components.dropdown.scss +0 -0
  409. package/src/styles/06-components/_components.edge-panel.scss +0 -0
  410. package/src/styles/06-components/_components.form-group.scss +0 -0
  411. package/src/styles/06-components/_components.form.scss +0 -0
  412. package/src/styles/06-components/_components.hero.scss +1 -0
  413. package/src/styles/06-components/_components.icon.scss +2 -2
  414. package/src/styles/06-components/_components.image-gallery.scss +0 -0
  415. package/src/styles/06-components/_components.input.scss +0 -0
  416. package/src/styles/06-components/_components.list-group.scss +0 -0
  417. package/src/styles/06-components/_components.list.scss +0 -0
  418. package/src/styles/06-components/_components.menu.scss +0 -0
  419. package/src/styles/06-components/_components.messages.scss +0 -0
  420. package/src/styles/06-components/_components.modal.scss +3 -0
  421. package/src/styles/06-components/_components.nav.scss +0 -0
  422. package/src/styles/06-components/_components.navbar.scss +0 -0
  423. package/src/styles/06-components/_components.pagination.scss +0 -0
  424. package/src/styles/06-components/_components.photoviewer.scss +603 -545
  425. package/src/styles/06-components/_components.popover.scss +0 -0
  426. package/src/styles/06-components/_components.product-review.scss +0 -0
  427. package/src/styles/06-components/_components.progress.scss +0 -0
  428. package/src/styles/06-components/_components.rating.scss +0 -0
  429. package/src/styles/06-components/_components.river.scss +0 -0
  430. package/src/styles/06-components/_components.sectionintro.scss +0 -0
  431. package/src/styles/06-components/_components.select.scss +0 -0
  432. package/src/styles/06-components/_components.side-menu.scss +0 -0
  433. package/src/styles/06-components/_components.skeleton.scss +0 -0
  434. package/src/styles/06-components/_components.slider.scss +273 -0
  435. package/src/styles/06-components/_components.spinner.scss +0 -0
  436. package/src/styles/06-components/_components.steps.scss +1 -0
  437. package/src/styles/06-components/_components.tabs.scss +0 -0
  438. package/src/styles/06-components/_components.testimonials.scss +0 -0
  439. package/src/styles/06-components/_components.todo.scss +0 -0
  440. package/src/styles/06-components/_components.toggle.scss +0 -0
  441. package/src/styles/06-components/_components.tooltip.scss +4 -9
  442. package/src/styles/06-components/_components.upload.scss +0 -0
  443. package/src/styles/06-components/_components.video-player.scss +623 -0
  444. package/src/styles/06-components/_index.scss +3 -0
  445. package/src/styles/06-components/old.chart.styles.scss +2819 -0
  446. package/src/styles/99-utilities/_index.scss +0 -0
  447. package/src/styles/99-utilities/_utilities.background.scss +0 -0
  448. package/src/styles/99-utilities/_utilities.border.scss +0 -0
  449. package/src/styles/99-utilities/_utilities.clearfix.scss +0 -0
  450. package/src/styles/99-utilities/_utilities.display.scss +0 -0
  451. package/src/styles/99-utilities/_utilities.flex.scss +0 -0
  452. package/src/styles/99-utilities/_utilities.link.scss +0 -0
  453. package/src/styles/99-utilities/_utilities.object-fit.scss +0 -0
  454. package/src/styles/99-utilities/_utilities.opacity.scss +0 -0
  455. package/src/styles/99-utilities/_utilities.overflow.scss +0 -0
  456. package/src/styles/99-utilities/_utilities.position.scss +0 -0
  457. package/src/styles/99-utilities/_utilities.scss +2 -1
  458. package/src/styles/99-utilities/_utilities.shadow.scss +0 -0
  459. package/src/styles/99-utilities/_utilities.sizes.scss +0 -0
  460. package/src/styles/99-utilities/_utilities.spacing.scss +0 -0
  461. package/src/styles/99-utilities/_utilities.text.scss +5 -0
  462. package/src/styles/99-utilities/_utilities.visibility.scss +0 -0
  463. package/src/styles/99-utilities/_utilities.visually-hidden.scss +0 -0
  464. package/src/styles/99-utilities/_utilities.z-index.scss +0 -0
  465. package/src/styles/css-modules.d.ts +0 -0
  466. package/src/styles/index.scss +0 -0
  467. package/dist/index.css +0 -15
  468. package/dist/index.esm.css +0 -15
  469. package/dist/index.min.css +0 -15
@@ -0,0 +1,172 @@
1
+ import React from 'react';
2
+ import { Icon } from '../Icon/Icon';
3
+ import { Avatar } from '../Avatar/Avatar';
4
+ import { MESSAGES } from '../../lib/constants/components';
5
+ import { MessagesProps } from '../../lib/types/components';
6
+ import { useMessages } from '../../lib/composables/useMessages';
7
+
8
+ /**
9
+ * Messages component for displaying a chat interface with messages, images, and file attachments
10
+ */
11
+ export const Messages: React.FC<MessagesProps> = ({
12
+ messages = [],
13
+ otherAvatar,
14
+ selfAvatar,
15
+ otherName,
16
+ width = '100%',
17
+ onSendMessage,
18
+ placeholder = 'Type a message',
19
+ className = '',
20
+ bodyHeight,
21
+ disabled = false,
22
+ id,
23
+ }) => {
24
+ const { inputValue, handleInputChange, handleSubmit, handleKeyDown } = useMessages({
25
+ onSendMessage,
26
+ });
27
+
28
+ // Generate unique ID for accessibility
29
+ const messagesId = id || `messages-${Math.random().toString(36).substr(2, 9)}`;
30
+ const inputId = `${messagesId}-input`;
31
+
32
+ return (
33
+ <div
34
+ className={`${MESSAGES.CLASSES.BASE} ${disabled ? 'is-disabled' : ''} ${className}`}
35
+ style={{ '--atomix-messages-width': width } as React.CSSProperties}
36
+ id={messagesId}
37
+ aria-label="Chat messages"
38
+ role="log"
39
+ aria-live="polite"
40
+ >
41
+ <div
42
+ className={MESSAGES.CLASSES.BODY}
43
+ style={
44
+ bodyHeight
45
+ ? ({ '--atomix-messages-body-height': bodyHeight } as React.CSSProperties)
46
+ : undefined
47
+ }
48
+ >
49
+ {messages.map(message => (
50
+ <div
51
+ key={message.id}
52
+ className={`${MESSAGES.CLASSES.CONTENT} ${message.isSelf ? MESSAGES.CLASSES.CONTENT_SELF : ''}`}
53
+ aria-label={`${message.isSelf ? 'You' : otherName || 'Other person'} sent a message at ${message.time}`}
54
+ >
55
+ <Avatar
56
+ src={message.isSelf ? selfAvatar : otherAvatar}
57
+ size="xl"
58
+ circle
59
+ className={MESSAGES.CLASSES.AVATAR}
60
+ alt={message.isSelf ? 'Your avatar' : `${otherName || 'Other person'}'s avatar`}
61
+ />
62
+ <div className={MESSAGES.CLASSES.ITEMS}>
63
+ {!message.isSelf && otherName && (
64
+ <div className={MESSAGES.CLASSES.NAME}>{otherName}</div>
65
+ )}
66
+
67
+ {message.text && (
68
+ <div className={MESSAGES.CLASSES.TEXT}>
69
+ {message.text}
70
+ <span className={MESSAGES.CLASSES.TIME} aria-label={`Sent at ${message.time}`}>
71
+ {message.time}
72
+ </span>
73
+ </div>
74
+ )}
75
+
76
+ {message.image && (
77
+ <img
78
+ className={MESSAGES.CLASSES.IMAGE}
79
+ src={message.image}
80
+ alt="Message attachment"
81
+ loading="lazy"
82
+ />
83
+ )}
84
+
85
+ {message.file && (
86
+ <div
87
+ className={MESSAGES.CLASSES.FILE}
88
+ aria-label={`File attachment: ${message.file.name}, size: ${message.file.size}`}
89
+ >
90
+ <span className={MESSAGES.CLASSES.FILE_ICON}>
91
+ <Icon name="File" aria-hidden="true" />
92
+ </span>
93
+ <div className={MESSAGES.CLASSES.FILE_DETAILS}>
94
+ <div className={MESSAGES.CLASSES.FILE_NAME}>{message.file.name}</div>
95
+ <div className={MESSAGES.CLASSES.FILE_SIZE}>{message.file.size}</div>
96
+ </div>
97
+ </div>
98
+ )}
99
+ </div>
100
+ </div>
101
+ ))}
102
+ </div>
103
+
104
+ <form
105
+ className={MESSAGES.CLASSES.FORM}
106
+ onSubmit={handleSubmit}
107
+ aria-label="Message input form"
108
+ >
109
+ <div className={MESSAGES.CLASSES.INPUT_GROUP}>
110
+ <label htmlFor={inputId} className="u-visually-hidden">
111
+ Type a message
112
+ </label>
113
+ <input
114
+ id={inputId}
115
+ type="text"
116
+ className={MESSAGES.CLASSES.INPUT}
117
+ placeholder={placeholder}
118
+ value={inputValue}
119
+ onChange={handleInputChange}
120
+ onKeyDown={handleKeyDown}
121
+ disabled={disabled}
122
+ aria-label="Message input"
123
+ />
124
+ <div className={MESSAGES.CLASSES.OPTIONS} aria-label="Message options">
125
+ <button
126
+ type="button"
127
+ className={MESSAGES.CLASSES.OPTION}
128
+ aria-label="Attach file"
129
+ disabled={disabled}
130
+ >
131
+ <Icon
132
+ name="PaperclipHorizontal"
133
+ aria-hidden="true"
134
+ className={MESSAGES.CLASSES.OPTION_ICON}
135
+ />
136
+ </button>
137
+ <button
138
+ type="button"
139
+ className={MESSAGES.CLASSES.OPTION}
140
+ aria-label="Attach image"
141
+ disabled={disabled}
142
+ >
143
+ <Icon name="Image" aria-hidden="true" className={MESSAGES.CLASSES.OPTION_ICON} />
144
+ </button>
145
+ <button
146
+ type="button"
147
+ className={MESSAGES.CLASSES.OPTION}
148
+ aria-label="Insert link"
149
+ disabled={disabled}
150
+ >
151
+ <Icon name="Link" aria-hidden="true" className={MESSAGES.CLASSES.OPTION_ICON} />
152
+ </button>
153
+ </div>
154
+ </div>
155
+ <button
156
+ type="submit"
157
+ className={MESSAGES.CLASSES.SUBMIT}
158
+ aria-label="Send message"
159
+ disabled={disabled}
160
+ >
161
+ <Icon name="PaperPlaneTilt" aria-hidden="true" size={24} />
162
+ </button>
163
+ </form>
164
+ </div>
165
+ );
166
+ };
167
+
168
+ export type { MessagesProps };
169
+
170
+ Messages.displayName = 'Messages';
171
+
172
+ export default Messages;
@@ -0,0 +1,3 @@
1
+ export { Messages } from './Messages';
2
+ export { default } from './Messages';
3
+ export type { MessagesProps } from './Messages';
@@ -0,0 +1,284 @@
1
+ import { Meta, StoryObj } from '@storybook/react';
2
+ import { useState } from 'react';
3
+ import Modal from './Modal';
4
+
5
+ const meta: Meta<typeof Modal> = {
6
+ title: 'Components/Modal',
7
+ component: Modal,
8
+ parameters: {
9
+ layout: 'centered',
10
+ },
11
+ argTypes: {
12
+ size: {
13
+ control: 'select',
14
+ options: ['sm', 'md', 'lg', 'xl'],
15
+ description: 'Size of the modal',
16
+ defaultValue: 'md',
17
+ },
18
+ backdrop: {
19
+ control: 'boolean',
20
+ description: 'Whether clicking the backdrop closes the modal',
21
+ defaultValue: true,
22
+ },
23
+ keyboard: {
24
+ control: 'boolean',
25
+ description: 'Whether pressing Escape key closes the modal',
26
+ defaultValue: true,
27
+ },
28
+ closeButton: {
29
+ control: 'boolean',
30
+ description: 'Whether to show the close button',
31
+ defaultValue: true,
32
+ },
33
+ },
34
+ };
35
+
36
+ export default meta;
37
+ type Story = StoryObj<typeof Modal>;
38
+
39
+ /**
40
+ * Basic modal example with a button to trigger opening.
41
+ */
42
+ export const Basic: Story = {
43
+ render: args => {
44
+ const [isOpen, setIsOpen] = useState(false);
45
+
46
+ return (
47
+ <>
48
+ <div
49
+ className="c-btn c-btn--primary"
50
+ onClick={() => setIsOpen(true)}
51
+ style={{ cursor: 'pointer', padding: '8px 16px', display: 'inline-block' }}
52
+ >
53
+ Open Modal
54
+ </div>
55
+
56
+ <Modal
57
+ {...args}
58
+ isOpen={isOpen}
59
+ onOpenChange={setIsOpen}
60
+ title="Title"
61
+ subtitle="This is some description text. This text is only a placeholder and should be replaced with the actual content of the modal."
62
+ >
63
+ <p>
64
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam auctor, odio vitae
65
+ faucibus luctus, elit nisi tincidunt justo, in malesuada enim nisl eget nisl.
66
+ Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis
67
+ egestas.
68
+ </p>
69
+ </Modal>
70
+ </>
71
+ );
72
+ },
73
+ };
74
+
75
+ /**
76
+ * Modal with a title, subtitle, and footer actions.
77
+ */
78
+ export const WithFooter: Story = {
79
+ render: args => {
80
+ const [isOpen, setIsOpen] = useState(false);
81
+
82
+ return (
83
+ <>
84
+ <div
85
+ className="c-btn c-btn--primary"
86
+ onClick={() => setIsOpen(true)}
87
+ style={{ cursor: 'pointer', padding: '8px 16px', display: 'inline-block' }}
88
+ >
89
+ Open Modal with Footer
90
+ </div>
91
+
92
+ <Modal
93
+ {...args}
94
+ isOpen={isOpen}
95
+ onOpenChange={setIsOpen}
96
+ title="Modal with Footer"
97
+ subtitle="This is some description text. This text is only a placeholder and should be replaced with the actual content of the modal."
98
+ footer={
99
+ <>
100
+ <div
101
+ className="c-btn c-btn--outline-secondary"
102
+ onClick={() => setIsOpen(false)}
103
+ style={{
104
+ cursor: 'pointer',
105
+ padding: '8px 16px',
106
+ display: 'inline-block',
107
+ marginRight: '8px',
108
+ }}
109
+ >
110
+ Cancel
111
+ </div>
112
+ <div
113
+ className="c-btn c-btn--primary"
114
+ onClick={() => {
115
+ alert('Action confirmed!');
116
+ setIsOpen(false);
117
+ }}
118
+ style={{ cursor: 'pointer', padding: '8px 16px', display: 'inline-block' }}
119
+ >
120
+ Confirm
121
+ </div>
122
+ </>
123
+ }
124
+ >
125
+ <p>This modal has a title, subtitle, and footer with action buttons.</p>
126
+ <p>The footer is ideal for placing action buttons or other controls.</p>
127
+ </Modal>
128
+ </>
129
+ );
130
+ },
131
+ };
132
+
133
+ /**
134
+ * Small size modal variant.
135
+ */
136
+ export const Small: Story = {
137
+ render: args => {
138
+ const [isOpen, setIsOpen] = useState(false);
139
+
140
+ return (
141
+ <>
142
+ <div
143
+ className="c-btn c-btn--primary"
144
+ onClick={() => setIsOpen(true)}
145
+ style={{ cursor: 'pointer', padding: '8px 16px', display: 'inline-block' }}
146
+ >
147
+ Open Small Modal
148
+ </div>
149
+
150
+ <Modal
151
+ {...args}
152
+ isOpen={isOpen}
153
+ onOpenChange={setIsOpen}
154
+ title="Small Modal"
155
+ subtitle="This is some description text."
156
+ size="sm"
157
+ footer={
158
+ <>
159
+ <div
160
+ className="c-btn c-btn--outline-secondary"
161
+ onClick={() => setIsOpen(false)}
162
+ style={{
163
+ cursor: 'pointer',
164
+ padding: '8px 16px',
165
+ display: 'inline-block',
166
+ marginRight: '8px',
167
+ }}
168
+ >
169
+ Cancel
170
+ </div>
171
+ <div
172
+ className="c-btn c-btn--primary"
173
+ onClick={() => setIsOpen(false)}
174
+ style={{ cursor: 'pointer', padding: '8px 16px', display: 'inline-block' }}
175
+ >
176
+ OK
177
+ </div>
178
+ </>
179
+ }
180
+ >
181
+ <img
182
+ src="https://unsplash.it/g/400/200"
183
+ alt="Example image"
184
+ style={{ maxWidth: '100%' }}
185
+ />
186
+ </Modal>
187
+ </>
188
+ );
189
+ },
190
+ };
191
+
192
+ /**
193
+ * Different size variants of the modal component.
194
+ */
195
+ export const Sizes: Story = {
196
+ render: () => {
197
+ const [size, setSize] = useState<'sm' | 'md' | 'lg' | 'xl'>('md');
198
+ const [isOpen, setIsOpen] = useState(false);
199
+
200
+ return (
201
+ <div className="u-d-flex u-flex-column u-gap-4">
202
+ <div className="u-d-flex u-gap-4">
203
+ <div
204
+ className={`c-btn ${size === 'sm' ? 'c-btn--primary' : 'c-btn--secondary'}`}
205
+ onClick={() => {
206
+ setSize('sm');
207
+ setIsOpen(true);
208
+ }}
209
+ style={{ cursor: 'pointer', padding: '8px 16px', display: 'inline-block' }}
210
+ >
211
+ Small Modal
212
+ </div>
213
+
214
+ <div
215
+ className={`c-btn ${size === 'md' ? 'c-btn--primary' : 'c-btn--secondary'}`}
216
+ onClick={() => {
217
+ setSize('md');
218
+ setIsOpen(true);
219
+ }}
220
+ style={{ cursor: 'pointer', padding: '8px 16px', display: 'inline-block' }}
221
+ >
222
+ Medium Modal
223
+ </div>
224
+
225
+ <div
226
+ className={`c-btn ${size === 'lg' ? 'c-btn--primary' : 'c-btn--secondary'}`}
227
+ onClick={() => {
228
+ setSize('lg');
229
+ setIsOpen(true);
230
+ }}
231
+ style={{ cursor: 'pointer', padding: '8px 16px', display: 'inline-block' }}
232
+ >
233
+ Large Modal
234
+ </div>
235
+
236
+ <div
237
+ className={`c-btn ${size === 'xl' ? 'c-btn--primary' : 'c-btn--secondary'}`}
238
+ onClick={() => {
239
+ setSize('xl');
240
+ setIsOpen(true);
241
+ }}
242
+ style={{ cursor: 'pointer', padding: '8px 16px', display: 'inline-block' }}
243
+ >
244
+ Extra Large Modal
245
+ </div>
246
+ </div>
247
+
248
+ <Modal
249
+ isOpen={isOpen}
250
+ onOpenChange={setIsOpen}
251
+ title={`${size.toUpperCase()} Modal`}
252
+ subtitle="This modal demonstrates different size variants."
253
+ size={size}
254
+ footer={
255
+ <>
256
+ <div
257
+ className="c-btn c-btn--outline-secondary"
258
+ onClick={() => setIsOpen(false)}
259
+ style={{
260
+ cursor: 'pointer',
261
+ padding: '8px 16px',
262
+ display: 'inline-block',
263
+ marginRight: '8px',
264
+ }}
265
+ >
266
+ Button
267
+ </div>
268
+ <div
269
+ className="c-btn c-btn--primary"
270
+ onClick={() => setIsOpen(false)}
271
+ style={{ cursor: 'pointer', padding: '8px 16px', display: 'inline-block' }}
272
+ >
273
+ Button
274
+ </div>
275
+ </>
276
+ }
277
+ >
278
+ <p>This is a {size.toUpperCase()} sized modal.</p>
279
+ <p>Modal sizes can be adjusted based on the content needs.</p>
280
+ </Modal>
281
+ </div>
282
+ );
283
+ },
284
+ };
@@ -0,0 +1,198 @@
1
+ import React, { useEffect, useRef, useState, useCallback } from 'react';
2
+ import { ModalProps } from '../../lib/types/components';
3
+ import { MODAL } from '../../lib/constants/components';
4
+
5
+ /**
6
+ * Hook for managing modal state
7
+ */
8
+ function useModal({
9
+ isOpen: isOpenProp,
10
+ onOpenChange,
11
+ onOpen,
12
+ onClose,
13
+ }: {
14
+ isOpen?: boolean;
15
+ onOpenChange?: (isOpen: boolean) => void;
16
+ onOpen?: () => void;
17
+ onClose?: () => void;
18
+ } = {}) {
19
+ // For uncontrolled usage
20
+ const [isOpenState, setIsOpenState] = useState(false);
21
+
22
+ // Determine if we're in controlled or uncontrolled mode
23
+ const isControlled = isOpenProp !== undefined;
24
+ const isOpen = isControlled ? !!isOpenProp : isOpenState;
25
+
26
+ // Update internal state when prop changes (for controlled mode)
27
+ useEffect(() => {
28
+ if (isControlled) {
29
+ setIsOpenState(!!isOpenProp);
30
+ }
31
+ }, [isOpenProp, isControlled]);
32
+
33
+ const updateOpen = useCallback(
34
+ (nextIsOpen: boolean) => {
35
+ // For uncontrolled mode, update internal state
36
+ if (!isControlled) {
37
+ setIsOpenState(nextIsOpen);
38
+ }
39
+
40
+ // Call the change handler in either mode
41
+ if (onOpenChange) {
42
+ onOpenChange(nextIsOpen);
43
+ }
44
+
45
+ // Call the specific handler
46
+ if (nextIsOpen && onOpen) {
47
+ onOpen();
48
+ } else if (!nextIsOpen && onClose) {
49
+ onClose();
50
+ }
51
+ },
52
+ [isControlled, onOpenChange, onOpen, onClose]
53
+ );
54
+
55
+ const open = useCallback(() => {
56
+ updateOpen(true);
57
+ }, [updateOpen]);
58
+
59
+ const close = useCallback(() => {
60
+ updateOpen(false);
61
+ }, [updateOpen]);
62
+
63
+ const toggle = useCallback(() => {
64
+ updateOpen(!isOpen);
65
+ }, [isOpen, updateOpen]);
66
+
67
+ return {
68
+ isOpen,
69
+ open,
70
+ close,
71
+ toggle,
72
+ };
73
+ }
74
+
75
+ /**
76
+ * Modal component for displaying overlay content
77
+ */
78
+ export const Modal: React.FC<ModalProps> = ({
79
+ children,
80
+ isOpen = false,
81
+ onOpenChange,
82
+ onClose,
83
+ onOpen,
84
+ title,
85
+ subtitle,
86
+ size = 'md',
87
+ backdrop = true,
88
+ keyboard = true,
89
+ className = '',
90
+ closeButton = true,
91
+ footer,
92
+ ...props
93
+ }) => {
94
+ const modalRef = useRef<HTMLDivElement>(null);
95
+ const dialogRef = useRef<HTMLDivElement>(null);
96
+ const backdropRef = useRef<HTMLDivElement>(null);
97
+
98
+ const {
99
+ isOpen: isOpenState,
100
+ open,
101
+ close,
102
+ } = useModal({
103
+ isOpen,
104
+ onOpenChange,
105
+ onClose,
106
+ onOpen,
107
+ });
108
+
109
+ // Handle keyboard events for Escape key
110
+ useEffect(() => {
111
+ if (!keyboard) return undefined;
112
+
113
+ const handleKeydown = (event: KeyboardEvent) => {
114
+ if (event.key === 'Escape' && isOpenState) {
115
+ close();
116
+ }
117
+ };
118
+
119
+ document.addEventListener('keydown', handleKeydown);
120
+ return () => {
121
+ document.removeEventListener('keydown', handleKeydown);
122
+ };
123
+ }, [isOpenState, close, keyboard]);
124
+
125
+ // Handle backdrop click
126
+ const handleBackdropClick = (event: React.MouseEvent<HTMLDivElement>) => {
127
+ if (backdrop && event.target === event.currentTarget) {
128
+ close();
129
+ }
130
+ };
131
+
132
+ // Assemble classes
133
+ const modalClasses = [
134
+ 'c-modal',
135
+ isOpenState ? MODAL.CLASSES.IS_OPEN : '',
136
+ size ? `c-modal--${size}` : '',
137
+ className,
138
+ ]
139
+ .filter(Boolean)
140
+ .join(' ');
141
+
142
+ return (
143
+ <div
144
+ ref={modalRef}
145
+ className={modalClasses}
146
+ style={{ display: isOpenState ? 'block' : 'none' }}
147
+ role="dialog"
148
+ aria-modal="true"
149
+ aria-hidden={!isOpenState}
150
+ {...props}
151
+ >
152
+ <div ref={backdropRef} className="c-modal__backdrop" onClick={handleBackdropClick} />
153
+ <div ref={dialogRef} className="c-modal__dialog">
154
+ <div className="c-modal__content">
155
+ {(title || closeButton) && (
156
+ <div className="c-modal__header">
157
+ <div className="c-modal__header-content">
158
+ {title && <h3 className="c-modal__title">{title}</h3>}
159
+ {subtitle && <p className="c-modal__sub">{subtitle}</p>}
160
+ </div>
161
+ {closeButton && (
162
+ <button
163
+ type="button"
164
+ className="c-modal__close c-btn js-modal-close"
165
+ onClick={close}
166
+ aria-label="Close modal"
167
+ >
168
+ <svg
169
+ width="20"
170
+ height="20"
171
+ viewBox="0 0 20 20"
172
+ fill="none"
173
+ xmlns="http://www.w3.org/2000/svg"
174
+ >
175
+ <path
176
+ d="M16.0672 15.1828C16.1253 15.2409 16.1713 15.3098 16.2028 15.3857C16.2342 15.4615 16.2504 15.5429 16.2504 15.625C16.2504 15.7071 16.2342 15.7884 16.2028 15.8643C16.1713 15.9402 16.1253 16.0091 16.0672 16.0672C16.0091 16.1252 15.9402 16.1713 15.8643 16.2027C15.7885 16.2342 15.7071 16.2503 15.625 16.2503C15.5429 16.2503 15.4616 16.2342 15.3857 16.2027C15.3098 16.1713 15.2409 16.1252 15.1828 16.0672L10 10.8836L4.8172 16.0672C4.69992 16.1844 4.54086 16.2503 4.37501 16.2503C4.20916 16.2503 4.0501 16.1844 3.93282 16.0672C3.81555 15.9499 3.74966 15.7908 3.74966 15.625C3.74966 15.4591 3.81555 15.3001 3.93282 15.1828L9.11642 9.99998L3.93282 4.81717C3.81555 4.69989 3.74966 4.54083 3.74966 4.37498C3.74966 4.20913 3.81555 4.05007 3.93282 3.93279C4.0501 3.81552 4.20916 3.74963 4.37501 3.74963C4.54086 3.74963 4.69992 3.81552 4.8172 3.93279L10 9.11639L15.1828 3.93279C15.3001 3.81552 15.4592 3.74963 15.625 3.74963C15.7909 3.74963 15.9499 3.81552 16.0672 3.93279C16.1845 4.05007 16.2504 4.20913 16.2504 4.37498C16.2504 4.54083 16.1845 4.69989 16.0672 4.81717L10.8836 9.99998L16.0672 15.1828Z"
177
+ fill="#141414"
178
+ />
179
+ </svg>
180
+ </button>
181
+ )}
182
+ </div>
183
+ )}
184
+
185
+ <div className="c-modal__body">{children}</div>
186
+
187
+ {footer && <div className="c-modal__footer">{footer}</div>}
188
+ </div>
189
+ </div>
190
+ </div>
191
+ );
192
+ };
193
+
194
+ Modal.displayName = 'Modal';
195
+
196
+ export type { ModalProps };
197
+
198
+ export default Modal;