@pattern-stack/frontend-patterns 0.0.3 → 0.0.5

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 (406) hide show
  1. package/dist/frontend-patterns.css +1 -1
  2. package/dist/index.es.js +1918 -3
  3. package/dist/index.es.js.map +1 -1
  4. package/dist/index.js +1917 -1
  5. package/dist/index.js.map +1 -1
  6. package/package.json +10 -5
  7. package/src/App.css +42 -0
  8. package/src/App.tsx +64 -0
  9. package/src/__tests__/README.md +221 -0
  10. package/src/__tests__/atoms/hooks/simple-hooks.test.ts +44 -0
  11. package/src/__tests__/atoms/ui/button.test.tsx +68 -0
  12. package/src/__tests__/atoms/utils/simple.test.ts +18 -0
  13. package/src/__tests__/atoms/utils/utils.test.ts +77 -0
  14. package/src/__tests__/features/auth/simple-auth.test.tsx +40 -0
  15. package/src/__tests__/molecules/layout/simple-layout.test.tsx +81 -0
  16. package/src/__tests__/organisms/showcase/simple-showcase.test.tsx +167 -0
  17. package/src/__tests__/setup.ts +51 -0
  18. package/src/__tests__/utils.tsx +123 -0
  19. package/src/atoms/composed/Accordion/Accordion.tsx +271 -0
  20. package/{dist/atoms/composed/Accordion/index.d.ts → src/atoms/composed/Accordion/index.ts} +1 -2
  21. package/src/atoms/composed/Alert/Alert.tsx +132 -0
  22. package/src/atoms/composed/Alert/index.ts +1 -0
  23. package/src/atoms/composed/Breadcrumb/Breadcrumb.tsx +83 -0
  24. package/src/atoms/composed/Breadcrumb/index.ts +1 -0
  25. package/src/atoms/composed/Chart/Chart.tsx +425 -0
  26. package/{dist/atoms/composed/Chart/index.d.ts → src/atoms/composed/Chart/index.ts} +1 -2
  27. package/src/atoms/composed/ColorSwatch/ColorSwatch.tsx +72 -0
  28. package/{dist/atoms/composed/ColorSwatch/index.d.ts → src/atoms/composed/ColorSwatch/index.ts} +1 -2
  29. package/src/atoms/composed/DarkModeToggle.tsx +66 -0
  30. package/src/atoms/composed/DataBadge/DataBadge.tsx +81 -0
  31. package/src/atoms/composed/DataBadge/index.ts +1 -0
  32. package/src/atoms/composed/DataTable/DataTable.tsx +394 -0
  33. package/src/atoms/composed/DataTable/TableCellWithTooltip.tsx +41 -0
  34. package/src/atoms/composed/DataTable/index.ts +2 -0
  35. package/src/atoms/composed/DateTimePicker/DateTimePicker.tsx +611 -0
  36. package/src/atoms/composed/DateTimePicker/index.ts +2 -0
  37. package/src/atoms/composed/DetailedCard/DetailedCard.tsx +181 -0
  38. package/src/atoms/composed/DetailedCard/index.ts +2 -0
  39. package/src/atoms/composed/EmptyState/EmptyState.tsx +90 -0
  40. package/src/atoms/composed/EmptyState/index.ts +1 -0
  41. package/src/atoms/composed/FileUpload/FileUpload.tsx +477 -0
  42. package/{dist/atoms/composed/FileUpload/index.d.ts → src/atoms/composed/FileUpload/index.ts} +1 -2
  43. package/src/atoms/composed/FormField/FormField.tsx +92 -0
  44. package/src/atoms/composed/FormField/index.ts +1 -0
  45. package/src/atoms/composed/GlobalSearch/GlobalSearch.tsx +37 -0
  46. package/src/atoms/composed/GlobalSearch/index.ts +1 -0
  47. package/src/atoms/composed/IconBadge/IconBadge.tsx +95 -0
  48. package/src/atoms/composed/IconBadge/index.ts +2 -0
  49. package/src/atoms/composed/Modal/Modal.tsx +223 -0
  50. package/src/atoms/composed/Modal/index.ts +2 -0
  51. package/src/atoms/composed/PaletteSwitcher.tsx +386 -0
  52. package/src/atoms/composed/ProgressBar/ProgressBar.tsx +116 -0
  53. package/{dist/atoms/composed/ProgressBar/index.d.ts → src/atoms/composed/ProgressBar/index.ts} +1 -2
  54. package/src/atoms/composed/SalesPanel/SalesPanel.tsx +116 -0
  55. package/src/atoms/composed/SalesPanel/index.ts +1 -0
  56. package/src/atoms/composed/SalesPanel/mockSalesData.ts +151 -0
  57. package/src/atoms/composed/StatCard/StatCard.tsx +219 -0
  58. package/src/atoms/composed/StatCard/index.ts +1 -0
  59. package/src/atoms/composed/StyleGuide.tsx +717 -0
  60. package/src/atoms/composed/Toast/Toast.tsx +219 -0
  61. package/{dist/atoms/composed/Toast/index.d.ts → src/atoms/composed/Toast/index.ts} +1 -2
  62. package/src/atoms/composed/Tooltip/Tooltip.tsx +213 -0
  63. package/src/atoms/composed/Tooltip/index.ts +1 -0
  64. package/src/atoms/composed/UserAvatar/UserAvatar.tsx +139 -0
  65. package/src/atoms/composed/UserAvatar/index.ts +1 -0
  66. package/src/atoms/composed/UserMenu/UserMenu.tsx +16 -0
  67. package/src/atoms/composed/UserMenu/index.ts +1 -0
  68. package/{dist/atoms/composed/index.d.ts → src/atoms/composed/index.ts} +7 -2
  69. package/src/atoms/hooks/useApi.ts +80 -0
  70. package/src/atoms/hooks/useHealth.ts +17 -0
  71. package/{dist/atoms/index.d.ts → src/atoms/index.ts} +6 -2
  72. package/src/atoms/services/api/client.ts +134 -0
  73. package/src/atoms/services/auth-service.ts +248 -0
  74. package/src/atoms/services/health.ts +15 -0
  75. package/{dist/atoms/services/index.d.ts → src/atoms/services/index.ts} +1 -2
  76. package/src/atoms/shared/config/constants.ts +17 -0
  77. package/src/atoms/shared/config/dashboard-sizes.ts +111 -0
  78. package/src/atoms/shared/config/environment.ts +10 -0
  79. package/src/atoms/shared/index.ts +4 -0
  80. package/src/atoms/shared/styles/color-palettes.css +566 -0
  81. package/src/atoms/types/auth.ts +62 -0
  82. package/src/atoms/types/entity-config.ts +127 -0
  83. package/{dist/atoms/types/generated.d.ts → src/atoms/types/generated.ts} +1 -1
  84. package/{dist/atoms/types/index.d.ts → src/atoms/types/index.ts} +2 -1
  85. package/{dist/atoms/types/loading.d.ts → src/atoms/types/loading.ts} +10 -8
  86. package/src/atoms/ui/Badge.tsx +30 -0
  87. package/src/atoms/ui/ErrorBoundary.tsx +59 -0
  88. package/src/atoms/ui/Select.tsx +53 -0
  89. package/src/atoms/ui/Switch.tsx +42 -0
  90. package/src/atoms/ui/Tabs.tsx +118 -0
  91. package/src/atoms/ui/avatar.tsx +48 -0
  92. package/src/atoms/ui/button.tsx +70 -0
  93. package/src/atoms/ui/card.tsx +76 -0
  94. package/src/atoms/ui/dropdown-menu.tsx +199 -0
  95. package/{dist/atoms/ui/index.d.ts → src/atoms/ui/index.ts} +27 -3
  96. package/src/atoms/ui/input.tsx +23 -0
  97. package/src/atoms/ui/label.tsx +23 -0
  98. package/src/atoms/ui/skeleton.tsx +13 -0
  99. package/src/atoms/ui/spinner.tsx +49 -0
  100. package/src/atoms/ui/table.tsx +116 -0
  101. package/src/atoms/utils/animations.ts +135 -0
  102. package/src/atoms/utils/metric-engine.ts +236 -0
  103. package/src/atoms/utils/tooltip-helpers.ts +140 -0
  104. package/src/atoms/utils/utils.ts +10 -0
  105. package/src/features/auth/components/LoginForm.tsx +168 -0
  106. package/src/features/auth/components/LogoutButton.tsx +19 -0
  107. package/src/features/auth/components/ProtectedRoute.tsx +60 -0
  108. package/{dist/features/auth/components/index.d.ts → src/features/auth/components/index.ts} +1 -1
  109. package/src/features/auth/hooks/index.ts +2 -0
  110. package/src/features/auth/hooks/useAuth.tsx +205 -0
  111. package/src/features/auth/hooks/usePermissions.ts +35 -0
  112. package/src/features/auth/index.ts +2 -0
  113. package/src/features/index.ts +2 -0
  114. package/src/index.css +704 -0
  115. package/{dist/index.d.ts → src/index.ts} +5 -2
  116. package/src/main.tsx +48 -0
  117. package/src/molecules/.gitkeep +0 -0
  118. package/src/molecules/forms/FormGroup.tsx +75 -0
  119. package/src/molecules/forms/SearchInput.tsx +259 -0
  120. package/src/molecules/forms/index.ts +4 -0
  121. package/src/molecules/index.ts +4 -0
  122. package/src/molecules/layout/AppHeader/AppHeader.tsx +42 -0
  123. package/src/molecules/layout/AppHeader/index.ts +1 -0
  124. package/src/molecules/layout/AppLayout.tsx +29 -0
  125. package/src/molecules/layout/DashboardWithSidePanel/DashboardWithSidePanel.tsx +42 -0
  126. package/src/molecules/layout/DashboardWithSidePanel/index.ts +1 -0
  127. package/src/molecules/layout/PageTemplate.tsx +87 -0
  128. package/src/molecules/layout/SectionHeader/SectionHeader.tsx +87 -0
  129. package/{dist/molecules/layout/SectionHeader/index.d.ts → src/molecules/layout/SectionHeader/index.ts} +1 -2
  130. package/src/molecules/layout/ShowcaseSection.tsx +57 -0
  131. package/src/molecules/layout/Sidebar.tsx +152 -0
  132. package/src/molecules/layout/SidebarButton/SidebarButton.tsx +99 -0
  133. package/src/molecules/layout/SidebarButton/index.ts +1 -0
  134. package/src/molecules/layout/SidebarContext.tsx +31 -0
  135. package/{dist/molecules/layout/index.d.ts → src/molecules/layout/index.ts} +2 -2
  136. package/src/molecules/navigation/NavMenu.tsx +188 -0
  137. package/src/molecules/navigation/Pagination.tsx +172 -0
  138. package/src/molecules/navigation/index.ts +4 -0
  139. package/src/organisms/entity/CategoryBreakdownPanel.tsx +427 -0
  140. package/src/organisms/entity/EntityListPanel.tsx +339 -0
  141. package/src/organisms/entity/MetricsOverviewPanel.tsx +236 -0
  142. package/src/organisms/entity/TrendAnalysisPanel.tsx +337 -0
  143. package/src/organisms/entity/index.ts +4 -0
  144. package/src/organisms/index.ts +8 -0
  145. package/src/organisms/showcase/ComponentShowcasePage.tsx +2496 -0
  146. package/src/organisms/showcase/index.ts +1 -0
  147. package/src/pages/AdminShowcase/AdminCRUDShowcase.tsx +242 -0
  148. package/src/pages/AdminShowcase/AdminDashboardShowcase.tsx +173 -0
  149. package/src/pages/AdminShowcase/AdminDetailShowcase.tsx +385 -0
  150. package/src/pages/AdminShowcase/SalesPerformanceDashboard.tsx +158 -0
  151. package/src/pages/AdminShowcase/index.tsx +4 -0
  152. package/src/pages/ComponentShowcase/BadgesShowcase.tsx +188 -0
  153. package/src/pages/ComponentShowcase/CardsShowcase.tsx +392 -0
  154. package/src/pages/ComponentShowcase/PalettesShowcase.tsx +207 -0
  155. package/src/pages/ComponentShowcase/StatesShowcase.tsx +485 -0
  156. package/src/pages/ComponentShowcase/TablesShowcase.tsx +134 -0
  157. package/src/pages/ComponentShowcase/TypographyShowcase.tsx +255 -0
  158. package/src/pages/ComponentShowcase/index.tsx +188 -0
  159. package/src/pages/EntityShowcase/EntityManagementShowcase.tsx +137 -0
  160. package/src/pages/EntityShowcase/EntityPerformanceShowcase.tsx +117 -0
  161. package/src/pages/EntityShowcase/index.ts +2 -0
  162. package/src/pages/EntityTemplateExample.tsx +229 -0
  163. package/src/pages/TestEntityTemplate.tsx +40 -0
  164. package/src/pages/index.ts +3 -0
  165. package/src/templates/AuthTemplate.tsx +216 -0
  166. package/src/templates/ComponentShowcaseTemplate.tsx +173 -0
  167. package/src/templates/DashboardTemplate.tsx +232 -0
  168. package/src/templates/DataTemplate.tsx +319 -0
  169. package/src/templates/admin/AdminCRUDTemplate.tsx +630 -0
  170. package/src/templates/admin/AdminDashboardTemplate.tsx +351 -0
  171. package/src/templates/admin/AdminDetailTemplate.tsx +563 -0
  172. package/src/templates/admin/index.ts +29 -0
  173. package/src/templates/entity/EntityManagementTemplate.tsx +430 -0
  174. package/src/templates/entity/EntityPerformanceDashboardTemplate.tsx +277 -0
  175. package/src/templates/entity/configs/financial-config.ts +141 -0
  176. package/src/templates/entity/configs/index.ts +1 -0
  177. package/src/templates/entity/index.ts +3 -0
  178. package/src/templates/factory.tsx +169 -0
  179. package/src/templates/financial/FinancialDashboardTemplate.tsx +326 -0
  180. package/src/templates/index.ts +40 -0
  181. package/src/vite-env.d.ts +1 -0
  182. package/dist/atoms/composed/Accordion/Accordion.d.ts +0 -20
  183. package/dist/atoms/composed/Accordion/Accordion.d.ts.map +0 -1
  184. package/dist/atoms/composed/Accordion/index.d.ts.map +0 -1
  185. package/dist/atoms/composed/Alert/Alert.d.ts +0 -25
  186. package/dist/atoms/composed/Alert/Alert.d.ts.map +0 -1
  187. package/dist/atoms/composed/Alert/index.d.ts +0 -2
  188. package/dist/atoms/composed/Alert/index.d.ts.map +0 -1
  189. package/dist/atoms/composed/Breadcrumb/Breadcrumb.d.ts +0 -17
  190. package/dist/atoms/composed/Breadcrumb/Breadcrumb.d.ts.map +0 -1
  191. package/dist/atoms/composed/Breadcrumb/index.d.ts +0 -2
  192. package/dist/atoms/composed/Breadcrumb/index.d.ts.map +0 -1
  193. package/dist/atoms/composed/Chart/Chart.d.ts +0 -37
  194. package/dist/atoms/composed/Chart/Chart.d.ts.map +0 -1
  195. package/dist/atoms/composed/Chart/index.d.ts.map +0 -1
  196. package/dist/atoms/composed/ColorSwatch/ColorSwatch.d.ts +0 -19
  197. package/dist/atoms/composed/ColorSwatch/ColorSwatch.d.ts.map +0 -1
  198. package/dist/atoms/composed/ColorSwatch/index.d.ts.map +0 -1
  199. package/dist/atoms/composed/DarkModeToggle.d.ts +0 -4
  200. package/dist/atoms/composed/DarkModeToggle.d.ts.map +0 -1
  201. package/dist/atoms/composed/DataBadge/DataBadge.d.ts +0 -13
  202. package/dist/atoms/composed/DataBadge/DataBadge.d.ts.map +0 -1
  203. package/dist/atoms/composed/DataBadge/index.d.ts +0 -2
  204. package/dist/atoms/composed/DataBadge/index.d.ts.map +0 -1
  205. package/dist/atoms/composed/DataTable/DataTable.d.ts +0 -28
  206. package/dist/atoms/composed/DataTable/DataTable.d.ts.map +0 -1
  207. package/dist/atoms/composed/DataTable/TableCellWithTooltip.d.ts +0 -10
  208. package/dist/atoms/composed/DataTable/TableCellWithTooltip.d.ts.map +0 -1
  209. package/dist/atoms/composed/DataTable/index.d.ts +0 -3
  210. package/dist/atoms/composed/DataTable/index.d.ts.map +0 -1
  211. package/dist/atoms/composed/DateTimePicker/DateTimePicker.d.ts +0 -45
  212. package/dist/atoms/composed/DateTimePicker/DateTimePicker.d.ts.map +0 -1
  213. package/dist/atoms/composed/DateTimePicker/index.d.ts +0 -3
  214. package/dist/atoms/composed/DateTimePicker/index.d.ts.map +0 -1
  215. package/dist/atoms/composed/DetailedCard/DetailedCard.d.ts +0 -30
  216. package/dist/atoms/composed/DetailedCard/DetailedCard.d.ts.map +0 -1
  217. package/dist/atoms/composed/DetailedCard/index.d.ts +0 -3
  218. package/dist/atoms/composed/DetailedCard/index.d.ts.map +0 -1
  219. package/dist/atoms/composed/EmptyState/EmptyState.d.ts +0 -18
  220. package/dist/atoms/composed/EmptyState/EmptyState.d.ts.map +0 -1
  221. package/dist/atoms/composed/EmptyState/index.d.ts +0 -2
  222. package/dist/atoms/composed/EmptyState/index.d.ts.map +0 -1
  223. package/dist/atoms/composed/FileUpload/FileUpload.d.ts +0 -46
  224. package/dist/atoms/composed/FileUpload/FileUpload.d.ts.map +0 -1
  225. package/dist/atoms/composed/FileUpload/index.d.ts.map +0 -1
  226. package/dist/atoms/composed/FormField/FormField.d.ts +0 -23
  227. package/dist/atoms/composed/FormField/FormField.d.ts.map +0 -1
  228. package/dist/atoms/composed/FormField/index.d.ts +0 -2
  229. package/dist/atoms/composed/FormField/index.d.ts.map +0 -1
  230. package/dist/atoms/composed/GlobalSearch/GlobalSearch.d.ts +0 -8
  231. package/dist/atoms/composed/GlobalSearch/GlobalSearch.d.ts.map +0 -1
  232. package/dist/atoms/composed/GlobalSearch/index.d.ts +0 -2
  233. package/dist/atoms/composed/GlobalSearch/index.d.ts.map +0 -1
  234. package/dist/atoms/composed/IconBadge/IconBadge.d.ts +0 -16
  235. package/dist/atoms/composed/IconBadge/IconBadge.d.ts.map +0 -1
  236. package/dist/atoms/composed/IconBadge/index.d.ts +0 -3
  237. package/dist/atoms/composed/IconBadge/index.d.ts.map +0 -1
  238. package/dist/atoms/composed/Modal/Modal.d.ts +0 -18
  239. package/dist/atoms/composed/Modal/Modal.d.ts.map +0 -1
  240. package/dist/atoms/composed/Modal/index.d.ts +0 -3
  241. package/dist/atoms/composed/Modal/index.d.ts.map +0 -1
  242. package/dist/atoms/composed/PaletteSwitcher.d.ts +0 -7
  243. package/dist/atoms/composed/PaletteSwitcher.d.ts.map +0 -1
  244. package/dist/atoms/composed/ProgressBar/ProgressBar.d.ts +0 -25
  245. package/dist/atoms/composed/ProgressBar/ProgressBar.d.ts.map +0 -1
  246. package/dist/atoms/composed/ProgressBar/index.d.ts.map +0 -1
  247. package/dist/atoms/composed/StatCard/StatCard.d.ts +0 -21
  248. package/dist/atoms/composed/StatCard/StatCard.d.ts.map +0 -1
  249. package/dist/atoms/composed/StatCard/index.d.ts +0 -2
  250. package/dist/atoms/composed/StatCard/index.d.ts.map +0 -1
  251. package/dist/atoms/composed/StyleGuide.d.ts +0 -3
  252. package/dist/atoms/composed/StyleGuide.d.ts.map +0 -1
  253. package/dist/atoms/composed/Toast/Toast.d.ts +0 -40
  254. package/dist/atoms/composed/Toast/Toast.d.ts.map +0 -1
  255. package/dist/atoms/composed/Toast/index.d.ts.map +0 -1
  256. package/dist/atoms/composed/Tooltip/Tooltip.d.ts +0 -16
  257. package/dist/atoms/composed/Tooltip/Tooltip.d.ts.map +0 -1
  258. package/dist/atoms/composed/Tooltip/index.d.ts +0 -2
  259. package/dist/atoms/composed/Tooltip/index.d.ts.map +0 -1
  260. package/dist/atoms/composed/UserAvatar/UserAvatar.d.ts +0 -8
  261. package/dist/atoms/composed/UserAvatar/UserAvatar.d.ts.map +0 -1
  262. package/dist/atoms/composed/UserAvatar/index.d.ts +0 -2
  263. package/dist/atoms/composed/UserAvatar/index.d.ts.map +0 -1
  264. package/dist/atoms/composed/UserMenu/UserMenu.d.ts +0 -8
  265. package/dist/atoms/composed/UserMenu/UserMenu.d.ts.map +0 -1
  266. package/dist/atoms/composed/UserMenu/index.d.ts +0 -2
  267. package/dist/atoms/composed/UserMenu/index.d.ts.map +0 -1
  268. package/dist/atoms/composed/index.d.ts.map +0 -1
  269. package/dist/atoms/hooks/useApi.d.ts +0 -25
  270. package/dist/atoms/hooks/useApi.d.ts.map +0 -1
  271. package/dist/atoms/hooks/useHealth.d.ts +0 -19
  272. package/dist/atoms/hooks/useHealth.d.ts.map +0 -1
  273. package/dist/atoms/index.d.ts.map +0 -1
  274. package/dist/atoms/services/api/client.d.ts +0 -20
  275. package/dist/atoms/services/api/client.d.ts.map +0 -1
  276. package/dist/atoms/services/auth-service.d.ts +0 -24
  277. package/dist/atoms/services/auth-service.d.ts.map +0 -1
  278. package/dist/atoms/services/health.d.ts +0 -7
  279. package/dist/atoms/services/health.d.ts.map +0 -1
  280. package/dist/atoms/services/index.d.ts.map +0 -1
  281. package/dist/atoms/shared/config/constants.d.ts +0 -15
  282. package/dist/atoms/shared/config/constants.d.ts.map +0 -1
  283. package/dist/atoms/shared/config/dashboard-sizes.d.ts +0 -83
  284. package/dist/atoms/shared/config/dashboard-sizes.d.ts.map +0 -1
  285. package/dist/atoms/shared/config/environment.d.ts +0 -10
  286. package/dist/atoms/shared/config/environment.d.ts.map +0 -1
  287. package/dist/atoms/shared/index.d.ts +0 -4
  288. package/dist/atoms/shared/index.d.ts.map +0 -1
  289. package/dist/atoms/types/auth.d.ts +0 -56
  290. package/dist/atoms/types/auth.d.ts.map +0 -1
  291. package/dist/atoms/types/generated.d.ts.map +0 -1
  292. package/dist/atoms/types/index.d.ts.map +0 -1
  293. package/dist/atoms/types/loading.d.ts.map +0 -1
  294. package/dist/atoms/ui/Badge.d.ts +0 -10
  295. package/dist/atoms/ui/Badge.d.ts.map +0 -1
  296. package/dist/atoms/ui/ErrorBoundary.d.ts +0 -18
  297. package/dist/atoms/ui/ErrorBoundary.d.ts.map +0 -1
  298. package/dist/atoms/ui/Select.d.ts +0 -28
  299. package/dist/atoms/ui/Select.d.ts.map +0 -1
  300. package/dist/atoms/ui/Switch.d.ts +0 -9
  301. package/dist/atoms/ui/Switch.d.ts.map +0 -1
  302. package/dist/atoms/ui/Tabs.d.ts +0 -30
  303. package/dist/atoms/ui/Tabs.d.ts.map +0 -1
  304. package/dist/atoms/ui/avatar.d.ts +0 -7
  305. package/dist/atoms/ui/avatar.d.ts.map +0 -1
  306. package/dist/atoms/ui/button.d.ts +0 -14
  307. package/dist/atoms/ui/button.d.ts.map +0 -1
  308. package/dist/atoms/ui/card.d.ts +0 -12
  309. package/dist/atoms/ui/card.d.ts.map +0 -1
  310. package/dist/atoms/ui/dropdown-menu.d.ts +0 -28
  311. package/dist/atoms/ui/dropdown-menu.d.ts.map +0 -1
  312. package/dist/atoms/ui/index.d.ts.map +0 -1
  313. package/dist/atoms/ui/input.d.ts +0 -5
  314. package/dist/atoms/ui/input.d.ts.map +0 -1
  315. package/dist/atoms/ui/label.d.ts +0 -6
  316. package/dist/atoms/ui/label.d.ts.map +0 -1
  317. package/dist/atoms/ui/skeleton.d.ts +0 -3
  318. package/dist/atoms/ui/skeleton.d.ts.map +0 -1
  319. package/dist/atoms/ui/spinner.d.ts +0 -14
  320. package/dist/atoms/ui/spinner.d.ts.map +0 -1
  321. package/dist/atoms/ui/table.d.ts +0 -11
  322. package/dist/atoms/ui/table.d.ts.map +0 -1
  323. package/dist/atoms/utils/animations.d.ts +0 -65
  324. package/dist/atoms/utils/animations.d.ts.map +0 -1
  325. package/dist/atoms/utils/tooltip-helpers.d.ts +0 -71
  326. package/dist/atoms/utils/tooltip-helpers.d.ts.map +0 -1
  327. package/dist/atoms/utils/utils.d.ts +0 -4
  328. package/dist/atoms/utils/utils.d.ts.map +0 -1
  329. package/dist/features/auth/components/LoginForm.d.ts +0 -2
  330. package/dist/features/auth/components/LoginForm.d.ts.map +0 -1
  331. package/dist/features/auth/components/LogoutButton.d.ts +0 -2
  332. package/dist/features/auth/components/LogoutButton.d.ts.map +0 -1
  333. package/dist/features/auth/components/ProtectedRoute.d.ts +0 -10
  334. package/dist/features/auth/components/ProtectedRoute.d.ts.map +0 -1
  335. package/dist/features/auth/components/index.d.ts.map +0 -1
  336. package/dist/features/auth/hooks/index.d.ts +0 -3
  337. package/dist/features/auth/hooks/index.d.ts.map +0 -1
  338. package/dist/features/auth/hooks/useAuth.d.ts +0 -10
  339. package/dist/features/auth/hooks/useAuth.d.ts.map +0 -1
  340. package/dist/features/auth/hooks/usePermissions.d.ts +0 -13
  341. package/dist/features/auth/hooks/usePermissions.d.ts.map +0 -1
  342. package/dist/features/auth/index.d.ts +0 -3
  343. package/dist/features/auth/index.d.ts.map +0 -1
  344. package/dist/features/index.d.ts +0 -2
  345. package/dist/features/index.d.ts.map +0 -1
  346. package/dist/index.d.ts.map +0 -1
  347. package/dist/molecules/forms/FormGroup.d.ts +0 -17
  348. package/dist/molecules/forms/FormGroup.d.ts.map +0 -1
  349. package/dist/molecules/forms/SearchInput.d.ts +0 -36
  350. package/dist/molecules/forms/SearchInput.d.ts.map +0 -1
  351. package/dist/molecules/forms/index.d.ts +0 -3
  352. package/dist/molecules/forms/index.d.ts.map +0 -1
  353. package/dist/molecules/index.d.ts +0 -4
  354. package/dist/molecules/index.d.ts.map +0 -1
  355. package/dist/molecules/layout/AppHeader/AppHeader.d.ts +0 -7
  356. package/dist/molecules/layout/AppHeader/AppHeader.d.ts.map +0 -1
  357. package/dist/molecules/layout/AppHeader/index.d.ts +0 -2
  358. package/dist/molecules/layout/AppHeader/index.d.ts.map +0 -1
  359. package/dist/molecules/layout/AppLayout.d.ts +0 -2
  360. package/dist/molecules/layout/AppLayout.d.ts.map +0 -1
  361. package/dist/molecules/layout/PageTemplate.d.ts +0 -19
  362. package/dist/molecules/layout/PageTemplate.d.ts.map +0 -1
  363. package/dist/molecules/layout/SectionHeader/SectionHeader.d.ts +0 -24
  364. package/dist/molecules/layout/SectionHeader/SectionHeader.d.ts.map +0 -1
  365. package/dist/molecules/layout/SectionHeader/index.d.ts.map +0 -1
  366. package/dist/molecules/layout/ShowcaseSection.d.ts +0 -22
  367. package/dist/molecules/layout/ShowcaseSection.d.ts.map +0 -1
  368. package/dist/molecules/layout/Sidebar.d.ts +0 -6
  369. package/dist/molecules/layout/Sidebar.d.ts.map +0 -1
  370. package/dist/molecules/layout/SidebarButton/SidebarButton.d.ts +0 -13
  371. package/dist/molecules/layout/SidebarButton/SidebarButton.d.ts.map +0 -1
  372. package/dist/molecules/layout/SidebarButton/index.d.ts +0 -2
  373. package/dist/molecules/layout/SidebarButton/index.d.ts.map +0 -1
  374. package/dist/molecules/layout/SidebarContext.d.ts +0 -12
  375. package/dist/molecules/layout/SidebarContext.d.ts.map +0 -1
  376. package/dist/molecules/layout/index.d.ts.map +0 -1
  377. package/dist/molecules/navigation/NavMenu.d.ts +0 -20
  378. package/dist/molecules/navigation/NavMenu.d.ts.map +0 -1
  379. package/dist/molecules/navigation/Pagination.d.ts +0 -14
  380. package/dist/molecules/navigation/Pagination.d.ts.map +0 -1
  381. package/dist/molecules/navigation/index.d.ts +0 -3
  382. package/dist/molecules/navigation/index.d.ts.map +0 -1
  383. package/dist/organisms/index.d.ts +0 -2
  384. package/dist/organisms/index.d.ts.map +0 -1
  385. package/dist/organisms/showcase/ComponentShowcasePage.d.ts +0 -3
  386. package/dist/organisms/showcase/ComponentShowcasePage.d.ts.map +0 -1
  387. package/dist/templates/AuthTemplate.d.ts +0 -68
  388. package/dist/templates/AuthTemplate.d.ts.map +0 -1
  389. package/dist/templates/ComponentShowcaseTemplate.d.ts +0 -53
  390. package/dist/templates/ComponentShowcaseTemplate.d.ts.map +0 -1
  391. package/dist/templates/DashboardTemplate.d.ts +0 -62
  392. package/dist/templates/DashboardTemplate.d.ts.map +0 -1
  393. package/dist/templates/DataTemplate.d.ts +0 -78
  394. package/dist/templates/DataTemplate.d.ts.map +0 -1
  395. package/dist/templates/admin/AdminCRUDTemplate.d.ts +0 -105
  396. package/dist/templates/admin/AdminCRUDTemplate.d.ts.map +0 -1
  397. package/dist/templates/admin/AdminDashboardTemplate.d.ts +0 -89
  398. package/dist/templates/admin/AdminDashboardTemplate.d.ts.map +0 -1
  399. package/dist/templates/admin/AdminDetailTemplate.d.ts +0 -132
  400. package/dist/templates/admin/AdminDetailTemplate.d.ts.map +0 -1
  401. package/dist/templates/admin/index.d.ts +0 -4
  402. package/dist/templates/admin/index.d.ts.map +0 -1
  403. package/dist/templates/factory.d.ts +0 -28
  404. package/dist/templates/factory.d.ts.map +0 -1
  405. package/dist/templates/index.d.ts +0 -7
  406. package/dist/templates/index.d.ts.map +0 -1
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@pattern-stack/frontend-patterns",
3
3
  "description": "Production-ready React frontend template with atomic architecture patterns. Build ultra-lean applications by importing shared UI foundation patterns.",
4
4
  "private": false,
5
- "version": "0.0.3",
5
+ "version": "0.0.5",
6
6
  "keywords": [
7
7
  "react",
8
8
  "typescript",
@@ -33,16 +33,18 @@
33
33
  "import": "./dist/index.es.js",
34
34
  "require": "./dist/index.js"
35
35
  },
36
- "./styles": "./dist/frontend-patterns.css"
36
+ "./styles": "./dist/frontend-patterns.css",
37
+ "./src/*": "./src/*"
37
38
  },
38
39
  "files": [
39
- "dist"
40
+ "dist",
41
+ "src"
40
42
  ],
41
43
  "type": "module",
42
44
  "scripts": {
43
45
  "dev": "vite",
44
46
  "build": "tsc -b && vite build",
45
- "build:lib": "npm run clean && vite build --mode library && tsc -p tsconfig.lib.json",
47
+ "build:lib": "npm run clean && vite build --mode library",
46
48
  "clean": "rm -rf dist",
47
49
  "lint": "eslint .",
48
50
  "lint:fix": "eslint . --fix",
@@ -100,9 +102,12 @@
100
102
  "@vitejs/plugin-react": "^4.4.1",
101
103
  "@vitest/coverage-v8": "^3.2.1",
102
104
  "autoprefixer": "^10.4.21",
105
+ "concurrently": "^9.1.2",
106
+ "cors": "^2.8.5",
103
107
  "eslint": "^9.25.0",
104
108
  "eslint-plugin-react-hooks": "^5.2.0",
105
109
  "eslint-plugin-react-refresh": "^0.4.19",
110
+ "express": "^5.1.0",
106
111
  "globals": "^16.0.0",
107
112
  "jsdom": "^26.1.0",
108
113
  "postcss": "^8.5.3",
@@ -113,4 +118,4 @@
113
118
  "vite": "^6.3.5",
114
119
  "vitest": "^3.2.1"
115
120
  }
116
- }
121
+ }
package/src/App.css ADDED
@@ -0,0 +1,42 @@
1
+ #root {
2
+ max-width: 1280px;
3
+ margin: 0 auto;
4
+ padding: 2rem;
5
+ text-align: center;
6
+ }
7
+
8
+ .logo {
9
+ height: 6em;
10
+ padding: 1.5em;
11
+ will-change: filter;
12
+ transition: filter 300ms;
13
+ }
14
+ .logo:hover {
15
+ filter: drop-shadow(0 0 2em #646cffaa);
16
+ }
17
+ .logo.react:hover {
18
+ filter: drop-shadow(0 0 2em #61dafbaa);
19
+ }
20
+
21
+ @keyframes logo-spin {
22
+ from {
23
+ transform: rotate(0deg);
24
+ }
25
+ to {
26
+ transform: rotate(360deg);
27
+ }
28
+ }
29
+
30
+ @media (prefers-reduced-motion: no-preference) {
31
+ a:nth-of-type(2) .logo {
32
+ animation: logo-spin infinite 20s linear;
33
+ }
34
+ }
35
+
36
+ .card {
37
+ padding: 2em;
38
+ }
39
+
40
+ .read-the-docs {
41
+ color: #888;
42
+ }
package/src/App.tsx ADDED
@@ -0,0 +1,64 @@
1
+ import { BrowserRouter, Routes, Route } from 'react-router-dom';
2
+
3
+ // Atoms
4
+ import { ErrorBoundary } from './atoms/ui';
5
+
6
+ // Features
7
+ import { ProtectedRoute } from './features/auth';
8
+
9
+ // Organisms
10
+ import { AppLayout } from './molecules/layout/AppLayout';
11
+ import { ComponentShowcasePage } from './organisms/showcase';
12
+
13
+ // Pages
14
+ import {
15
+ ComponentShowcase,
16
+ AdminDashboardShowcase,
17
+ AdminCRUDShowcase,
18
+ AdminDetailShowcase,
19
+ SalesPerformanceDashboard,
20
+ EntityPerformanceShowcase,
21
+ EntityManagementShowcase
22
+ } from './pages';
23
+ import { EntityTemplateExample } from './pages/EntityTemplateExample';
24
+
25
+ function App() {
26
+ return (
27
+ <ErrorBoundary>
28
+ <BrowserRouter>
29
+ <Routes>
30
+ <Route path="/" element={
31
+ <ProtectedRoute>
32
+ <AppLayout />
33
+ </ProtectedRoute>
34
+ }>
35
+ {/* Default to Component Showcase */}
36
+ <Route index element={<ErrorBoundary><ComponentShowcasePage /></ErrorBoundary>} />
37
+
38
+ {/* Component Showcase - Complete with Navigation/Forms/Feedback */}
39
+ <Route path="showcase" element={<ErrorBoundary><ComponentShowcasePage /></ErrorBoundary>} />
40
+
41
+ {/* Template-driven Showcase (alternative version) */}
42
+ <Route path="showcase-alt" element={<ErrorBoundary><ComponentShowcase /></ErrorBoundary>} />
43
+
44
+ {/* Admin Template Showcases */}
45
+ <Route path="admin/dashboard" element={<ErrorBoundary><AdminDashboardShowcase /></ErrorBoundary>} />
46
+ <Route path="admin/users" element={<ErrorBoundary><AdminCRUDShowcase /></ErrorBoundary>} />
47
+ <Route path="admin/user/:id" element={<ErrorBoundary><AdminDetailShowcase /></ErrorBoundary>} />
48
+ <Route path="admin/sales" element={<ErrorBoundary><SalesPerformanceDashboard /></ErrorBoundary>} />
49
+
50
+ {/* Entity Template Showcases */}
51
+ <Route path="entity/performance" element={<ErrorBoundary><EntityPerformanceShowcase /></ErrorBoundary>} />
52
+ <Route path="entity/management" element={<ErrorBoundary><EntityManagementShowcase /></ErrorBoundary>} />
53
+ <Route path="entity/template-example" element={<ErrorBoundary><EntityTemplateExample /></ErrorBoundary>} />
54
+
55
+ {/* Fallback */}
56
+ <Route path="*" element={<ErrorBoundary><ComponentShowcasePage /></ErrorBoundary>} />
57
+ </Route>
58
+ </Routes>
59
+ </BrowserRouter>
60
+ </ErrorBoundary>
61
+ );
62
+ }
63
+
64
+ export default App;
@@ -0,0 +1,221 @@
1
+ # Frontend Testing Strategy
2
+
3
+ > Atomic design testing that mirrors your backend testing architecture
4
+
5
+ ## 🏗️ Testing Architecture
6
+
7
+ Our frontend tests follow the **same atomic structure** as your backend tests:
8
+
9
+ ```
10
+ src/__tests__/
11
+ ├── atoms/ # Unit tests (like backend atoms/)
12
+ │ ├── ui/ # UI component tests
13
+ │ ├── business/ # Business component tests
14
+ │ ├── hooks/ # React hooks tests
15
+ │ ├── utils/ # Utility function tests
16
+ │ └── services/ # API client tests
17
+ ├── molecules/ # Component integration tests
18
+ │ ├── forms/ # Form component tests
19
+ │ ├── layout/ # Layout component tests
20
+ │ └── navigation/ # Navigation tests
21
+ ├── organisms/ # Page/complex component tests
22
+ │ └── showcase/ # Full page tests
23
+ ├── features/ # Feature integration tests
24
+ │ └── auth/ # Auth system tests
25
+ ├── setup.ts # Test setup (like conftest.py)
26
+ └── utils.tsx # Test utilities (like pytest fixtures)
27
+ ```
28
+
29
+ ## 🧪 Testing Stack
30
+
31
+ **Framework**: Vitest (Vite-native, fast)
32
+ **React Testing**: @testing-library/react
33
+ **User Interaction**: @testing-library/user-event
34
+ **Environment**: jsdom (browser simulation)
35
+ **Assertions**: jest-dom matchers
36
+
37
+ ## 📋 Test Commands
38
+
39
+ ```bash
40
+ # Run all tests
41
+ npm run test
42
+
43
+ # Run with UI (visual test runner)
44
+ npm run test:ui
45
+
46
+ # Run once (CI mode)
47
+ npm run test:run
48
+
49
+ # Watch mode (development)
50
+ npm run test:watch
51
+
52
+ # Coverage report
53
+ npm run test:coverage
54
+
55
+ # Test by atomic level (like backend)
56
+ npm run test:atoms # Unit tests
57
+ npm run test:molecules # Component integration
58
+ npm run test:organisms # Page tests
59
+ npm run test:features # Feature integration
60
+ ```
61
+
62
+ ## 🎯 Testing Patterns
63
+
64
+ ### Atoms (Unit Tests)
65
+ ```typescript
66
+ // UI Components
67
+ describe('Button (Atom)', () => {
68
+ it('renders with correct variant styles', () => {
69
+ render(<Button variant="primary">Click me</Button>)
70
+ expect(screen.getByRole('button')).toHaveClass('bg-primary')
71
+ })
72
+ })
73
+
74
+ // Hooks
75
+ describe('useApi (Atom)', () => {
76
+ it('handles API calls correctly', async () => {
77
+ const { result } = renderHook(() => useApiQuery(['test'], mockFn))
78
+ await waitFor(() => expect(result.current.isSuccess).toBe(true))
79
+ })
80
+ })
81
+
82
+ // Utils
83
+ describe('cn utility (Atom)', () => {
84
+ it('merges classes correctly', () => {
85
+ expect(cn('px-4', 'py-2')).toBe('px-4 py-2')
86
+ })
87
+ })
88
+ ```
89
+
90
+ ### Molecules (Component Integration)
91
+ ```typescript
92
+ describe('AppHeader (Molecule)', () => {
93
+ it('integrates auth, navigation, and UI atoms', () => {
94
+ render(<AppHeader />)
95
+ expect(screen.getByRole('banner')).toBeInTheDocument()
96
+ expect(screen.getByTestId('user-menu')).toBeInTheDocument()
97
+ })
98
+ })
99
+ ```
100
+
101
+ ### Organisms (Page Tests)
102
+ ```typescript
103
+ describe('ComponentShowcasePage (Organism)', () => {
104
+ it('renders complete page with all sections', () => {
105
+ render(<ComponentShowcasePage />)
106
+ expect(screen.getByRole('main')).toBeInTheDocument()
107
+ // Test full page functionality
108
+ })
109
+ })
110
+ ```
111
+
112
+ ### Features (Integration Tests)
113
+ ```typescript
114
+ describe('useAuth (Feature)', () => {
115
+ it('handles complete auth flow', async () => {
116
+ const { result } = renderHook(() => useAuth())
117
+ await act(() => result.current.login(credentials))
118
+ expect(result.current.isAuthenticated).toBe(true)
119
+ })
120
+ })
121
+ ```
122
+
123
+ ## 🛠️ Test Utilities
124
+
125
+ ### Setup (`setup.ts`)
126
+ - Global test configuration
127
+ - Mock browser APIs
128
+ - Environment setup
129
+ - Like your `conftest.py`
130
+
131
+ ### Utils (`utils.tsx`)
132
+ - Custom render with providers
133
+ - Mock factories (users, API clients)
134
+ - Test helpers and fixtures
135
+ - Like your pytest fixtures
136
+
137
+ ### Example Usage
138
+ ```typescript
139
+ import { render, createMockUser, createMockApiClient } from '../utils'
140
+
141
+ describe('MyComponent', () => {
142
+ it('works with test utilities', () => {
143
+ const mockUser = createMockUser({ name: 'Test User' })
144
+ const mockApi = createMockApiClient()
145
+
146
+ render(<MyComponent />, {
147
+ initialRoute: '/dashboard',
148
+ queryClient: new QueryClient()
149
+ })
150
+ })
151
+ })
152
+ ```
153
+
154
+ ## 🎨 Design System Testing
155
+
156
+ Our tests enforce design system compliance:
157
+
158
+ ```typescript
159
+ it('uses design system classes only', () => {
160
+ render(<Component />)
161
+ const element = screen.getByRole('button')
162
+
163
+ // ✅ Should use design system
164
+ expect(element).toHaveClass('bg-primary')
165
+
166
+ // ❌ Should NOT use hardcoded colors
167
+ expect(element.className).not.toMatch(/bg-blue-\d+/)
168
+ })
169
+ ```
170
+
171
+ ## 📊 Coverage Goals
172
+
173
+ - **Atoms**: 90%+ (pure functions, UI components)
174
+ - **Molecules**: 80%+ (component integration)
175
+ - **Organisms**: 70%+ (complex pages)
176
+ - **Features**: 85%+ (business logic)
177
+
178
+ ## 🔄 CI/CD Integration
179
+
180
+ Tests run in pre-commit hooks:
181
+ ```bash
182
+ npm run pre-commit # style:check + test:run + build
183
+ ```
184
+
185
+ ## 🚀 Running Tests
186
+
187
+ ```bash
188
+ # Development workflow
189
+ npm run test:watch # Watch mode while coding
190
+
191
+ # Before committing
192
+ npm run test:run # Full test suite
193
+ npm run test:coverage # Check coverage
194
+
195
+ # Debugging specific areas
196
+ npm run test:atoms # Just unit tests
197
+ npm run test:features # Just integration tests
198
+
199
+ # Visual debugging
200
+ npm run test:ui # Vitest UI runner
201
+ ```
202
+
203
+ ## 🎯 Best Practices
204
+
205
+ 1. **Mirror Backend Structure**: Tests follow atomic design
206
+ 2. **Design System Compliance**: Test CSS class usage
207
+ 3. **Integration Focus**: Test component interactions
208
+ 4. **User-Centric**: Test user workflows, not implementation
209
+ 5. **Mock External Dependencies**: API calls, localStorage, etc.
210
+ 6. **Accessibility**: Test keyboard navigation, ARIA attributes
211
+
212
+ ## 🔧 Configuration
213
+
214
+ - **vitest.config.ts**: Main test configuration
215
+ - **setup.ts**: Global test setup and mocks
216
+ - **utils.tsx**: Reusable test utilities and providers
217
+ - **package.json**: Test scripts and atomic-level commands
218
+
219
+ ---
220
+
221
+ **Result**: Frontend testing that mirrors your backend's atomic architecture with comprehensive coverage and design system enforcement! 🧪⚛️
@@ -0,0 +1,44 @@
1
+ import { describe, it, expect } from 'vitest'
2
+ import { renderHook } from '@testing-library/react'
3
+ import { useState } from 'react'
4
+
5
+ describe('Simple Hook Tests (Example)', () => {
6
+ it('useState hook works correctly', () => {
7
+ const { result } = renderHook(() => useState(0))
8
+
9
+ const [count, setCount] = result.current
10
+ expect(count).toBe(0)
11
+
12
+ // Test that hook function is returned
13
+ expect(typeof setCount).toBe('function')
14
+ })
15
+
16
+ it('useEffect-like behavior can be tested', () => {
17
+ const { result, rerender } = renderHook(
18
+ ({ initialValue }) => useState(initialValue),
19
+ { initialProps: { initialValue: 10 } }
20
+ )
21
+
22
+ expect(result.current[0]).toBe(10)
23
+
24
+ // Test re-render with new props
25
+ rerender({ initialValue: 20 })
26
+ // Note: useState doesn't re-initialize on prop changes, this is just testing the pattern
27
+ expect(result.current[0]).toBe(10) // Still 10 because useState doesn't re-init
28
+ })
29
+
30
+ it('custom hook pattern testing', () => {
31
+ const useCounter = (initial = 0) => {
32
+ const [count, setCount] = useState(initial)
33
+ const increment = () => setCount(c => c + 1)
34
+ const decrement = () => setCount(c => c - 1)
35
+ return { count, increment, decrement }
36
+ }
37
+
38
+ const { result } = renderHook(() => useCounter(5))
39
+
40
+ expect(result.current.count).toBe(5)
41
+ expect(typeof result.current.increment).toBe('function')
42
+ expect(typeof result.current.decrement).toBe('function')
43
+ })
44
+ })
@@ -0,0 +1,68 @@
1
+ import React from 'react'
2
+ import { describe, it, expect } from 'vitest'
3
+ import { render, screen, userEvent } from '../../utils'
4
+ import { Button } from '../../../atoms/ui/button'
5
+
6
+ describe('Button (Atom)', () => {
7
+ it('renders with default variant', () => {
8
+ render(<Button>Click me</Button>)
9
+ const button = screen.getByRole('button', { name: /click me/i })
10
+ expect(button).toBeInTheDocument()
11
+ // The button uses gradient, so check for primary color reference
12
+ expect(button.className).toContain('from-primary')
13
+ })
14
+
15
+ it('renders with different variants', () => {
16
+ const { rerender } = render(<Button variant="secondary">Secondary</Button>)
17
+ expect(screen.getByRole('button')).toHaveClass('bg-gray-100')
18
+
19
+ rerender(<Button variant="destructive">Destructive</Button>)
20
+ expect(screen.getByRole('button').className).toContain('from-destructive')
21
+ })
22
+
23
+ it('renders with different sizes', () => {
24
+ const { rerender } = render(<Button size="sm">Small</Button>)
25
+ expect(screen.getByRole('button')).toHaveClass('h-9')
26
+
27
+ rerender(<Button size="lg">Large</Button>)
28
+ expect(screen.getByRole('button')).toHaveClass('h-12')
29
+ })
30
+
31
+ it('handles click events', async () => {
32
+ const user = userEvent.setup()
33
+ const handleClick = vi.fn()
34
+
35
+ render(<Button onClick={handleClick}>Click me</Button>)
36
+
37
+ await user.click(screen.getByRole('button'))
38
+ expect(handleClick).toHaveBeenCalledOnce()
39
+ })
40
+
41
+ it('is disabled when disabled prop is true', () => {
42
+ render(<Button disabled>Disabled</Button>)
43
+ const button = screen.getByRole('button')
44
+ expect(button).toBeDisabled()
45
+ expect(button).toHaveClass('disabled:pointer-events-none')
46
+ })
47
+
48
+ it('renders as child component when asChild is true', () => {
49
+ render(
50
+ <Button asChild>
51
+ <a href="/test">Link button</a>
52
+ </Button>
53
+ )
54
+
55
+ const link = screen.getByRole('link')
56
+ expect(link).toBeInTheDocument()
57
+ expect(link.className).toContain('from-primary')
58
+ expect(link).toHaveAttribute('href', '/test')
59
+ })
60
+
61
+ it('forwards ref correctly', () => {
62
+ const ref = React.createRef<HTMLButtonElement>()
63
+ render(<Button ref={ref}>Button</Button>)
64
+
65
+ expect(ref.current).toBeInstanceOf(HTMLButtonElement)
66
+ expect(ref.current).toHaveTextContent('Button')
67
+ })
68
+ })
@@ -0,0 +1,18 @@
1
+ import { describe, it, expect } from 'vitest'
2
+
3
+ describe('Simple Test (Example)', () => {
4
+ it('basic arithmetic works', () => {
5
+ expect(2 + 2).toBe(4)
6
+ })
7
+
8
+ it('string manipulation works', () => {
9
+ const str = 'hello world'
10
+ expect(str.toUpperCase()).toBe('HELLO WORLD')
11
+ })
12
+
13
+ it('array operations work', () => {
14
+ const arr = [1, 2, 3]
15
+ expect(arr.length).toBe(3)
16
+ expect(arr.includes(2)).toBe(true)
17
+ })
18
+ })
@@ -0,0 +1,77 @@
1
+ import { describe, it, expect } from 'vitest'
2
+ import { cn } from '../../../atoms/utils/utils'
3
+
4
+ describe('Utils (Atoms)', () => {
5
+ describe('cn (className utility)', () => {
6
+ it('merges class names correctly', () => {
7
+ const result = cn('px-4 py-2', 'bg-blue-500')
8
+ expect(result).toBe('px-4 py-2 bg-blue-500')
9
+ })
10
+
11
+ it('handles conditional classes', () => {
12
+ const isActive = true
13
+ const isDisabled = false
14
+
15
+ const result = cn(
16
+ 'base-class',
17
+ isActive && 'active-class',
18
+ isDisabled && 'disabled-class'
19
+ )
20
+
21
+ expect(result).toBe('base-class active-class')
22
+ })
23
+
24
+ it('resolves conflicting Tailwind classes', () => {
25
+ // tailwind-merge should resolve conflicts
26
+ const result = cn('px-2 px-4') // px-4 should win
27
+ expect(result).toBe('px-4')
28
+ })
29
+
30
+ it('handles arrays of classes', () => {
31
+ const result = cn(['px-4', 'py-2'], ['bg-blue-500', 'text-white'])
32
+ expect(result).toBe('px-4 py-2 bg-blue-500 text-white')
33
+ })
34
+
35
+ it('handles object syntax', () => {
36
+ const result = cn({
37
+ 'px-4': true,
38
+ 'py-2': true,
39
+ 'bg-red-500': false,
40
+ 'bg-blue-500': true,
41
+ })
42
+ expect(result).toBe('px-4 py-2 bg-blue-500')
43
+ })
44
+
45
+ it('handles undefined and null values', () => {
46
+ const result = cn('px-4', undefined, null, 'py-2')
47
+ expect(result).toBe('px-4 py-2')
48
+ })
49
+
50
+ it('handles empty strings', () => {
51
+ const result = cn('', 'px-4', '', 'py-2')
52
+ expect(result).toBe('px-4 py-2')
53
+ })
54
+
55
+ it('maintains design system classes', () => {
56
+ // Test that design system classes are preserved
57
+ const result = cn('bg-primary text-primary-foreground', 'hover:bg-primary-hover')
58
+ expect(result).toBe('bg-primary text-primary-foreground hover:bg-primary-hover')
59
+ })
60
+
61
+ it('works with status classes', () => {
62
+ const status = 'success'
63
+ const result = cn(
64
+ 'base-class',
65
+ status === 'success' && 'status-success',
66
+ status === 'error' && 'status-error'
67
+ )
68
+ expect(result).toBe('base-class status-success')
69
+ })
70
+
71
+ it('works with category classes', () => {
72
+ const category = 2
73
+ const result = cn('base-class', `category-${category}`)
74
+ expect(result).toBe('base-class category-2')
75
+ })
76
+ })
77
+ })
@@ -0,0 +1,40 @@
1
+ import React from 'react'
2
+ import { describe, it, expect } from 'vitest'
3
+ import { render, screen } from '../../utils'
4
+
5
+ // Simple auth component for testing
6
+ const AuthStatus = ({ isAuthenticated }: { isAuthenticated: boolean }) => (
7
+ <div>
8
+ {isAuthenticated ? (
9
+ <span data-testid="authenticated">User is logged in</span>
10
+ ) : (
11
+ <span data-testid="not-authenticated">Please log in</span>
12
+ )}
13
+ </div>
14
+ )
15
+
16
+ describe('Auth Components (Feature)', () => {
17
+ it('displays authenticated state correctly', () => {
18
+ render(<AuthStatus isAuthenticated={true} />)
19
+
20
+ expect(screen.getByTestId('authenticated')).toBeInTheDocument()
21
+ expect(screen.getByText('User is logged in')).toBeInTheDocument()
22
+ })
23
+
24
+ it('displays unauthenticated state correctly', () => {
25
+ render(<AuthStatus isAuthenticated={false} />)
26
+
27
+ expect(screen.getByTestId('not-authenticated')).toBeInTheDocument()
28
+ expect(screen.getByText('Please log in')).toBeInTheDocument()
29
+ })
30
+
31
+ it('toggles between states correctly', () => {
32
+ const { rerender } = render(<AuthStatus isAuthenticated={false} />)
33
+
34
+ expect(screen.getByText('Please log in')).toBeInTheDocument()
35
+
36
+ rerender(<AuthStatus isAuthenticated={true} />)
37
+
38
+ expect(screen.getByText('User is logged in')).toBeInTheDocument()
39
+ })
40
+ })