@goplusvn/core 0.1.0 → 0.1.2

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 (591) hide show
  1. package/package.json +31 -175
  2. package/src/assets/erp_wallpaper.png +0 -0
  3. package/src/assets/goeat_logo.png +0 -0
  4. package/src/audit/audit-manager.ts +139 -0
  5. package/src/audit/index.ts +11 -0
  6. package/src/audit/memory-audit-logger.ts +86 -0
  7. package/src/audit/types.ts +50 -0
  8. package/src/auth/auth-service.ts +97 -0
  9. package/src/auth/index.ts +266 -0
  10. package/src/code-generation/index.ts +69 -0
  11. package/src/configs/auth-routes.ts +17 -0
  12. package/src/configs/crud.ts +136 -0
  13. package/src/configs/data/navigations.ts +781 -0
  14. package/src/configs/data/oauth-links.ts +10 -0
  15. package/src/configs/entities/material-categories.config.ts +125 -0
  16. package/src/configs/i18n.ts +12 -0
  17. package/src/configs/index.ts +26 -0
  18. package/src/configs/status.ts +25 -0
  19. package/src/configs/themes.ts +100 -0
  20. package/src/crud/components/crud-bulk-actions.tsx +91 -0
  21. package/src/crud/components/crud-card-view.tsx +241 -0
  22. package/src/crud/components/crud-context.tsx +122 -0
  23. package/src/crud/components/crud-delete-dialog.tsx +145 -0
  24. package/src/crud/components/crud-dialog.tsx +406 -0
  25. package/src/crud/components/crud-empty-state.tsx +104 -0
  26. package/src/crud/components/crud-export-button.tsx +170 -0
  27. package/src/crud/components/crud-field-renderer.tsx +653 -0
  28. package/src/crud/components/crud-filter-chips.tsx +102 -0
  29. package/src/crud/components/crud-filters/checkbox-filter.tsx +97 -0
  30. package/src/crud/components/crud-filters/datetime-filter.tsx +83 -0
  31. package/src/crud/components/crud-filters/filter-builder.tsx +66 -0
  32. package/src/crud/components/crud-filters/index.tsx +76 -0
  33. package/src/crud/components/crud-filters/radio-filter.tsx +86 -0
  34. package/src/crud/components/crud-filters/select-filter.tsx +141 -0
  35. package/src/crud/components/crud-filters/text-filter.tsx +86 -0
  36. package/src/crud/components/crud-form.tsx +642 -0
  37. package/src/crud/components/crud-import-dialog.tsx +440 -0
  38. package/src/crud/components/crud-infinite-scroll.tsx +116 -0
  39. package/src/crud/components/crud-page.tsx +1017 -0
  40. package/src/crud/components/crud-provider.tsx +277 -0
  41. package/src/crud/components/crud-row-actions.tsx +189 -0
  42. package/src/crud/components/crud-search.tsx +82 -0
  43. package/src/crud/components/crud-sheet.tsx +336 -0
  44. package/src/crud/components/crud-table-skeleton.tsx +26 -0
  45. package/src/crud/components/crud-table-toolbar.tsx +91 -0
  46. package/src/crud/components/crud-table.tsx +352 -0
  47. package/src/crud/components/crud-virtual-table.tsx +55 -0
  48. package/src/crud/components/index.tsx +20 -0
  49. package/src/crud/crud-filters/checkbox-filter.tsx +87 -0
  50. package/src/crud/crud-filters/datetime-filter.tsx +82 -0
  51. package/src/crud/crud-filters/filter-builder.tsx +64 -0
  52. package/src/crud/crud-filters/index.tsx +78 -0
  53. package/src/crud/crud-filters/radio-filter.tsx +79 -0
  54. package/src/crud/crud-filters/select-filter.tsx +148 -0
  55. package/src/crud/crud-filters/text-filter.tsx +81 -0
  56. package/src/crud/index.ts +43 -0
  57. package/src/crud/lib/crud-service.test.ts +334 -0
  58. package/src/crud/lib/crud-service.ts +358 -0
  59. package/src/crud/lib/crud-utils.test.ts +354 -0
  60. package/src/crud/lib/crud-utils.ts +299 -0
  61. package/src/crud/lib/crud-validator.ts +247 -0
  62. package/src/crud/lib/data-loader.ts +234 -0
  63. package/src/crud/lib/field-calculator.ts +241 -0
  64. package/src/crud/lib/field-formatter.ts +240 -0
  65. package/src/crud/lib/import-export-service.test.ts +290 -0
  66. package/src/crud/lib/import-export-service.ts +352 -0
  67. package/src/crud/lib/import-server-utils.ts +109 -0
  68. package/src/crud/lib/lazy-loader.ts +241 -0
  69. package/src/crud/lib/parse-filters.ts +85 -0
  70. package/src/crud/lib/permissions.ts +52 -0
  71. package/src/crud/lib/serialize-config.ts +60 -0
  72. package/src/crud/lib/stream-loader.ts +145 -0
  73. package/src/crud/lib/translate-config.ts +335 -0
  74. package/src/crud/lib/types.ts +11 -0
  75. package/src/crud/pages/entity-crud-page.tsx +144 -0
  76. package/src/crud/server.ts +8 -0
  77. package/src/home/constants.tsx +142 -0
  78. package/src/home/feature-showcase.tsx +171 -0
  79. package/src/home/home-page.tsx +191 -0
  80. package/src/home/hooks/index.ts +1 -0
  81. package/src/home/hooks/useWidgetPreferences.ts +167 -0
  82. package/src/home/index.ts +33 -0
  83. package/src/home/quick-access-dialog.tsx +271 -0
  84. package/src/home/quick-access-menu.tsx +267 -0
  85. package/src/home/types.ts +140 -0
  86. package/src/home/welcome-card.tsx +92 -0
  87. package/src/home/widget-container.tsx +258 -0
  88. package/src/home/widgets/base-widget.tsx +200 -0
  89. package/src/home/widgets/customers-widget.tsx +74 -0
  90. package/src/home/widgets/index.ts +6 -0
  91. package/src/home/widgets/orders-widget.tsx +87 -0
  92. package/src/home/widgets/revenue-widget.tsx +71 -0
  93. package/src/home/widgets/stock-widget.tsx +109 -0
  94. package/src/hooks/index.tsx +598 -0
  95. package/src/hooks/use-tenant.test.tsx +30 -0
  96. package/src/hooks/use-tenant.ts +5 -0
  97. package/src/index.ts +17 -0
  98. package/src/infrastructure/__tests__/architecture-verification.spec.ts +103 -0
  99. package/src/infrastructure/api-service.ts +317 -0
  100. package/src/infrastructure/cache/cache-manager.ts +107 -0
  101. package/src/infrastructure/cache/cache.ts +120 -0
  102. package/src/infrastructure/cache/index.ts +8 -0
  103. package/src/infrastructure/cache/types.ts +48 -0
  104. package/src/infrastructure/cron/cron-manager.ts +239 -0
  105. package/src/infrastructure/cron/index.ts +6 -0
  106. package/src/infrastructure/cron/types.ts +41 -0
  107. package/src/infrastructure/event-bus/event-bus.ts +145 -0
  108. package/src/infrastructure/event-bus/index.ts +2 -0
  109. package/src/infrastructure/event-bus/types.ts +22 -0
  110. package/src/infrastructure/index.ts +32 -0
  111. package/src/infrastructure/lock/decorators.ts +67 -0
  112. package/src/infrastructure/lock/index.ts +2 -0
  113. package/src/infrastructure/lock/lock-manager.ts +33 -0
  114. package/src/infrastructure/logger/index.ts +2 -0
  115. package/src/infrastructure/logger/logger.ts +96 -0
  116. package/src/infrastructure/logger/types.ts +25 -0
  117. package/src/layout/index.tsx +185 -0
  118. package/src/navigation/index.ts +91 -0
  119. package/src/notification/index.ts +14 -0
  120. package/src/notification/notification-service.ts +120 -0
  121. package/src/notification/storage/in-memory.ts +56 -0
  122. package/src/notification/storage/index.ts +1 -0
  123. package/src/notification/types.ts +51 -0
  124. package/src/organization/branch-service.ts +299 -0
  125. package/src/organization/branches.config.ts +154 -0
  126. package/src/organization/index.ts +5 -0
  127. package/src/plugin/apps-registry.ts +97 -0
  128. package/src/plugin/index.ts +5 -0
  129. package/src/plugin/types.ts +41 -0
  130. package/src/providers/index.tsx +109 -0
  131. package/src/providers/tenant-provider.tsx +45 -0
  132. package/src/rbac/components/roles/role-card.tsx +158 -0
  133. package/src/rbac/components/roles/role-stats-cards.tsx +29 -0
  134. package/src/rbac/components/roles/role-toolbar.tsx +123 -0
  135. package/src/rbac/hooks/use-role-operations.ts +159 -0
  136. package/src/rbac/hooks/use-roles-data.ts +59 -0
  137. package/src/rbac/index.ts +297 -0
  138. package/src/rbac/lib/permission-helpers.ts +63 -0
  139. package/src/rbac/pages/action-list-page.tsx +25 -0
  140. package/src/rbac/pages/resource-list-page.tsx +25 -0
  141. package/src/rbac/pages/role-list-page.tsx +378 -0
  142. package/src/rbac/permission-service.ts +140 -0
  143. package/src/rbac/permissions.ts +135 -0
  144. package/src/rbac/resource-service.ts +115 -0
  145. package/src/rbac/resource-validator.ts +119 -0
  146. package/src/rbac/role-service.ts +165 -0
  147. package/src/rbac/server.ts +16 -0
  148. package/src/rbac/types.ts +38 -0
  149. package/src/schemas/action.schema.ts +66 -0
  150. package/src/schemas/branch.schema.ts +52 -0
  151. package/src/schemas/coming-soon-schema.ts +9 -0
  152. package/src/schemas/company.schema.ts +44 -0
  153. package/src/schemas/forgot-passward-schema.ts +9 -0
  154. package/src/schemas/index.ts +30 -0
  155. package/src/schemas/material-category.schema.ts +43 -0
  156. package/src/schemas/material-pricing.schema.ts +74 -0
  157. package/src/schemas/material.schema.ts +76 -0
  158. package/src/schemas/materials.ts +52 -0
  159. package/src/schemas/new-passward-schema.ts +15 -0
  160. package/src/schemas/partner-company.schema.ts +149 -0
  161. package/src/schemas/register-schema.ts +36 -0
  162. package/src/schemas/resource.schema.ts +133 -0
  163. package/src/schemas/role.schema.ts +11 -0
  164. package/src/schemas/sign-in-schema.ts +24 -0
  165. package/src/schemas/supplier-pricing.schema.ts +15 -0
  166. package/src/schemas/supplier.schema.ts +120 -0
  167. package/src/schemas/system-category-group.schema.ts +67 -0
  168. package/src/schemas/system-category.schema.ts +77 -0
  169. package/src/schemas/system-config.schema.ts +118 -0
  170. package/src/schemas/uom.schema.ts +75 -0
  171. package/src/schemas/user-supplier.schema.ts +179 -0
  172. package/src/schemas/user.schema.ts +18 -0
  173. package/src/schemas/verify-email-schema.ts +9 -0
  174. package/src/schemas/warehouse.schema.ts +49 -0
  175. package/src/system/components/categories/category-list.tsx +529 -0
  176. package/src/system/components/categories/category-manager.tsx +89 -0
  177. package/src/system/components/categories/group-sidebar.tsx +308 -0
  178. package/src/system/components/settings/setting-dialogs.tsx +197 -0
  179. package/src/system/components/settings/setting-field.tsx +291 -0
  180. package/src/system/components/settings/setting-form-dialog.tsx +308 -0
  181. package/src/system/components/settings/settings-groups.ts +80 -0
  182. package/src/system/components/settings/settings-search.tsx +71 -0
  183. package/src/system/components/settings/settings-section.tsx +74 -0
  184. package/src/system/components/settings/settings-sidebar.tsx +81 -0
  185. package/src/system/constants.ts +3 -0
  186. package/src/system/index.ts +150 -0
  187. package/src/system/job-manager.ts +176 -0
  188. package/src/system/pages/components/categories/category-list.tsx +537 -0
  189. package/src/system/pages/components/categories/category-manager.tsx +90 -0
  190. package/src/system/pages/components/categories/group-sidebar.tsx +311 -0
  191. package/src/system/pages/components/settings/sales-rules-settings.tsx +222 -0
  192. package/src/system/pages/components/settings/setting-dialogs.tsx +197 -0
  193. package/src/system/pages/components/settings/setting-field.tsx +292 -0
  194. package/src/system/pages/components/settings/setting-form-dialog.tsx +308 -0
  195. package/src/system/pages/components/settings/settings-groups.ts +87 -0
  196. package/src/system/pages/components/settings/settings-page.tsx +372 -0
  197. package/src/system/pages/components/settings/settings-search.tsx +71 -0
  198. package/src/system/pages/components/settings/settings-section.tsx +74 -0
  199. package/src/system/pages/components/settings/settings-sidebar.tsx +81 -0
  200. package/src/system/pages/components/settings/system-settings.tsx +244 -0
  201. package/src/system/pages/system-category-page.tsx +15 -0
  202. package/src/system/pages/system-settings-page.tsx +380 -0
  203. package/src/system/schemas/system-category-group.schema.ts +46 -0
  204. package/src/system/schemas/system-category.schema.ts +56 -0
  205. package/src/system/services/settings-service.ts +127 -0
  206. package/src/system/services/system-category-service.ts +63 -0
  207. package/src/system/types.ts +45 -0
  208. package/src/types/index.ts +703 -0
  209. package/src/ui/auth/auth-layout.tsx +135 -0
  210. package/src/ui/auth/forgot-password-form.tsx +98 -0
  211. package/src/ui/auth/index.tsx +7 -0
  212. package/src/ui/auth/new-password-form.tsx +107 -0
  213. package/src/ui/auth/oauth-links.tsx +30 -0
  214. package/src/ui/auth/register-form.tsx +202 -0
  215. package/src/ui/auth/sign-in-form.tsx +238 -0
  216. package/src/ui/auth/verify-email-form.tsx +104 -0
  217. package/src/ui/crud/index.tsx +10 -0
  218. package/src/ui/data-display/accordion.tsx +65 -0
  219. package/src/ui/data-display/aspect-ratio.tsx +11 -0
  220. package/src/ui/data-display/avatar.tsx +163 -0
  221. package/src/ui/data-display/bento-grid.tsx +77 -0
  222. package/src/ui/data-display/carousel.tsx +249 -0
  223. package/src/ui/data-display/chart.tsx +363 -0
  224. package/src/ui/data-display/code-block-highlight.tsx +54 -0
  225. package/src/ui/data-display/collapsible.tsx +42 -0
  226. package/src/ui/data-display/compact-stat-bar.tsx +149 -0
  227. package/src/ui/data-display/data-table/data-table-context.tsx +255 -0
  228. package/src/ui/data-display/data-table/data-table-empty-state.tsx +133 -0
  229. package/src/ui/data-display/data-table/data-table-skeleton.tsx +145 -0
  230. package/src/ui/data-display/data-table/data-table-toolbar.tsx +353 -0
  231. package/src/ui/data-display/data-table/data-table.tsx +597 -0
  232. package/src/ui/data-display/data-table/index.ts +44 -0
  233. package/src/ui/data-display/data-table-column-header.tsx +75 -0
  234. package/src/ui/data-display/data-table-pagination.tsx +130 -0
  235. package/src/ui/data-display/data-table-view-options.tsx +59 -0
  236. package/src/ui/data-display/formatted-number-input.tsx +210 -0
  237. package/src/ui/data-display/highlight.tsx +20 -0
  238. package/src/ui/data-display/hover-card.tsx +48 -0
  239. package/src/ui/data-display/index.tsx +50 -0
  240. package/src/ui/data-display/iphone-15-pro.tsx +114 -0
  241. package/src/ui/data-display/kanban/index.ts +4 -0
  242. package/src/ui/data-display/kanban/kanban-board.tsx +192 -0
  243. package/src/ui/data-display/kanban/kanban-column.tsx +74 -0
  244. package/src/ui/data-display/kanban/kanban-item.tsx +50 -0
  245. package/src/ui/data-display/kanban/kanban-types.ts +21 -0
  246. package/src/ui/data-display/kpi-card.tsx +68 -0
  247. package/src/ui/data-display/media-grid.tsx +110 -0
  248. package/src/ui/data-display/safari.tsx +175 -0
  249. package/src/ui/data-display/show-more-text.tsx +55 -0
  250. package/src/ui/data-display/tabs.tsx +68 -0
  251. package/src/ui/data-display/timeline.tsx +256 -0
  252. package/src/ui/feedback/alert.tsx +60 -0
  253. package/src/ui/feedback/context-menu.tsx +245 -0
  254. package/src/ui/feedback/drawer.tsx +132 -0
  255. package/src/ui/feedback/error-dialog.tsx +273 -0
  256. package/src/ui/feedback/index.tsx +183 -0
  257. package/src/ui/feedback/progress.tsx +32 -0
  258. package/src/ui/feedback/sheet.tsx +148 -0
  259. package/src/ui/feedback/sonner.tsx +36 -0
  260. package/src/ui/forms/command.tsx +157 -0
  261. package/src/ui/forms/date-picker.tsx +73 -0
  262. package/src/ui/forms/date-range-picker.tsx +76 -0
  263. package/src/ui/forms/date-time-picker.tsx +109 -0
  264. package/src/ui/forms/editor/editor-menu-bar.tsx +394 -0
  265. package/src/ui/forms/editor/index.tsx +130 -0
  266. package/src/ui/forms/editor/multi-select-example.tsx +1234 -0
  267. package/src/ui/forms/emoji-picker.tsx +109 -0
  268. package/src/ui/forms/file-dropzone.tsx +169 -0
  269. package/src/ui/forms/file-thumbnail.tsx +29 -0
  270. package/src/ui/forms/index.tsx +201 -0
  271. package/src/ui/forms/input-file.tsx +99 -0
  272. package/src/ui/forms/input-group.tsx +46 -0
  273. package/src/ui/forms/input-otp.tsx +81 -0
  274. package/src/ui/forms/input-phone.tsx +172 -0
  275. package/src/ui/forms/input-spin.tsx +116 -0
  276. package/src/ui/forms/input-tags.tsx +219 -0
  277. package/src/ui/forms/input-time.tsx +42 -0
  278. package/src/ui/forms/multi-select.tsx +629 -0
  279. package/src/ui/forms/multiple-date-picker.tsx +74 -0
  280. package/src/ui/forms/radio-group.tsx +42 -0
  281. package/src/ui/forms/rating.tsx +158 -0
  282. package/src/ui/forms/time-picker.tsx +57 -0
  283. package/src/ui/index.tsx +17 -0
  284. package/src/ui/layout/animated-list.tsx +77 -0
  285. package/src/ui/layout/animated-sidebar.tsx +294 -0
  286. package/src/ui/layout/command-menu.tsx +355 -0
  287. package/src/ui/layout/customizer.tsx +324 -0
  288. package/src/ui/layout/footer.tsx +43 -0
  289. package/src/ui/layout/full-screen-toggle.tsx +52 -0
  290. package/src/ui/layout/header-breadcrumb.tsx +77 -0
  291. package/src/ui/layout/horizontal-layout-header.tsx +83 -0
  292. package/src/ui/layout/horizontal-layout.tsx +50 -0
  293. package/src/ui/layout/index.tsx +25 -0
  294. package/src/ui/layout/language-dropdown.tsx +103 -0
  295. package/src/ui/layout/logo.tsx +63 -0
  296. package/src/ui/layout/main-layout.tsx +57 -0
  297. package/src/ui/layout/mode-dropdown.tsx +58 -0
  298. package/src/ui/layout/notification-dropdown.tsx +127 -0
  299. package/src/ui/layout/page-tabs.tsx +306 -0
  300. package/src/ui/layout/route-cache.tsx +214 -0
  301. package/src/ui/layout/sidebar-group-icon-menu.tsx +195 -0
  302. package/src/ui/layout/sidebar.tsx +279 -0
  303. package/src/ui/layout/tab-content-cache.tsx +201 -0
  304. package/src/ui/layout/tab-navigation-provider.tsx +536 -0
  305. package/src/ui/layout/toggle-mobile-sidebar.tsx +33 -0
  306. package/src/ui/layout/top-bar-header-menubar.tsx +412 -0
  307. package/src/ui/layout/user-dropdown.tsx +188 -0
  308. package/src/ui/layout/vertical-layout-header.tsx +65 -0
  309. package/src/ui/layout/vertical-layout.tsx +47 -0
  310. package/src/ui/management/audit-log-page.tsx +209 -0
  311. package/src/ui/management/cache-management.tsx +349 -0
  312. package/src/ui/management/index.ts +3 -0
  313. package/src/ui/management/job-management.tsx +308 -0
  314. package/src/ui/pages/not-found.tsx +30 -0
  315. package/src/ui/primitives/badge.tsx +66 -0
  316. package/src/ui/primitives/breadcrumb.tsx +103 -0
  317. package/src/ui/primitives/button.tsx +129 -0
  318. package/src/ui/primitives/calendar.tsx +74 -0
  319. package/src/ui/primitives/card.tsx +86 -0
  320. package/src/ui/primitives/checkbox.tsx +31 -0
  321. package/src/ui/primitives/client.ts +30 -0
  322. package/src/ui/primitives/combobox.tsx +290 -0
  323. package/src/ui/primitives/dialog.tsx +121 -0
  324. package/src/ui/primitives/dropdown-menu.tsx +239 -0
  325. package/src/ui/primitives/dynamic-icon.tsx +24 -0
  326. package/src/ui/primitives/index.tsx +134 -0
  327. package/src/ui/primitives/input-number.tsx +131 -0
  328. package/src/ui/primitives/input.tsx +22 -0
  329. package/src/ui/primitives/keyboard.tsx +23 -0
  330. package/src/ui/primitives/label.tsx +24 -0
  331. package/src/ui/primitives/menubar.tsx +262 -0
  332. package/src/ui/primitives/navigation-menu.tsx +157 -0
  333. package/src/ui/primitives/pagination.tsx +118 -0
  334. package/src/ui/primitives/popover.tsx +56 -0
  335. package/src/ui/primitives/prefetch-link.tsx +60 -0
  336. package/src/ui/primitives/resizable.tsx +59 -0
  337. package/src/ui/primitives/scroll-area.tsx +63 -0
  338. package/src/ui/primitives/select.tsx +172 -0
  339. package/src/ui/primitives/separator.tsx +51 -0
  340. package/src/ui/primitives/sidebar.tsx +844 -0
  341. package/src/ui/primitives/slider.tsx +27 -0
  342. package/src/ui/primitives/status-badge.tsx +47 -0
  343. package/src/ui/primitives/sticky-layout.tsx +50 -0
  344. package/src/ui/primitives/switch.tsx +29 -0
  345. package/src/ui/primitives/table.tsx +116 -0
  346. package/src/ui/primitives/tabs.tsx +55 -0
  347. package/src/ui/primitives/toggle-group.tsx +70 -0
  348. package/src/ui/primitives/toggle.tsx +47 -0
  349. package/src/ui/primitives/tooltip.tsx +59 -0
  350. package/src/user/components/dangerous-zone.tsx +34 -0
  351. package/src/user/components/delete-account-form.tsx +40 -0
  352. package/src/user/components/index.ts +4 -0
  353. package/src/user/components/profile-info-form.tsx +390 -0
  354. package/src/user/components/profile-info.tsx +32 -0
  355. package/src/user/components/unified-profile-dialog.tsx +1019 -0
  356. package/src/user/components/user-stats.tsx +27 -0
  357. package/src/user/components/user-toolbar.tsx +137 -0
  358. package/src/user/components/users-card-view.tsx +253 -0
  359. package/src/user/index.ts +11 -0
  360. package/src/user/pages/user-list-page.tsx +234 -0
  361. package/src/user/pages/users-client-page.tsx +385 -0
  362. package/src/user/profile-page.tsx +19 -0
  363. package/src/user/schemas.ts +68 -0
  364. package/src/user/types.ts +34 -0
  365. package/src/user/user-service.ts +538 -0
  366. package/src/utils/index.ts +906 -0
  367. package/src/workflow/activity-timeline.tsx +412 -0
  368. package/src/workflow/approval-workflow.tsx +31 -0
  369. package/src/workflow/index.ts +2 -0
  370. package/dist/audit/index.d.mts +0 -115
  371. package/dist/audit/index.d.ts +0 -115
  372. package/dist/audit/index.js +0 -204
  373. package/dist/audit/index.js.map +0 -1
  374. package/dist/audit/index.mjs +0 -200
  375. package/dist/audit/index.mjs.map +0 -1
  376. package/dist/auth/index.d.mts +0 -86
  377. package/dist/auth/index.d.ts +0 -86
  378. package/dist/auth/index.js +0 -210
  379. package/dist/auth/index.js.map +0 -1
  380. package/dist/auth/index.mjs +0 -198
  381. package/dist/auth/index.mjs.map +0 -1
  382. package/dist/button-1dWvP9Ib.d.mts +0 -30
  383. package/dist/button-1dWvP9Ib.d.ts +0 -30
  384. package/dist/calendar-2QzdEo1z.d.mts +0 -20
  385. package/dist/calendar-2QzdEo1z.d.ts +0 -20
  386. package/dist/code-generation/index.d.mts +0 -30
  387. package/dist/code-generation/index.d.ts +0 -30
  388. package/dist/code-generation/index.js +0 -31
  389. package/dist/code-generation/index.js.map +0 -1
  390. package/dist/code-generation/index.mjs +0 -28
  391. package/dist/code-generation/index.mjs.map +0 -1
  392. package/dist/configs/index.d.mts +0 -175
  393. package/dist/configs/index.d.ts +0 -175
  394. package/dist/configs/index.js +0 -254
  395. package/dist/configs/index.js.map +0 -1
  396. package/dist/configs/index.mjs +0 -233
  397. package/dist/configs/index.mjs.map +0 -1
  398. package/dist/crud/index.d.mts +0 -646
  399. package/dist/crud/index.d.ts +0 -646
  400. package/dist/crud/index.js +0 -11772
  401. package/dist/crud/index.js.map +0 -1
  402. package/dist/crud/index.mjs +0 -11665
  403. package/dist/crud/index.mjs.map +0 -1
  404. package/dist/crud/server.d.mts +0 -20
  405. package/dist/crud/server.d.ts +0 -20
  406. package/dist/crud/server.js +0 -123
  407. package/dist/crud/server.js.map +0 -1
  408. package/dist/crud/server.mjs +0 -120
  409. package/dist/crud/server.mjs.map +0 -1
  410. package/dist/data-table-skeleton-12NA8Mjx.d.mts +0 -39
  411. package/dist/data-table-skeleton-12NA8Mjx.d.ts +0 -39
  412. package/dist/dialog-bKfjZMTd.d.mts +0 -22
  413. package/dist/dialog-bKfjZMTd.d.ts +0 -22
  414. package/dist/dynamic-icon-DrGIiu2N.d.mts +0 -10
  415. package/dist/dynamic-icon-DrGIiu2N.d.ts +0 -10
  416. package/dist/home/index.d.mts +0 -269
  417. package/dist/home/index.d.ts +0 -269
  418. package/dist/home/index.js +0 -1678
  419. package/dist/home/index.js.map +0 -1
  420. package/dist/home/index.mjs +0 -1635
  421. package/dist/home/index.mjs.map +0 -1
  422. package/dist/hooks/index.d.mts +0 -7
  423. package/dist/hooks/index.d.ts +0 -7
  424. package/dist/hooks/index.js +0 -8316
  425. package/dist/hooks/index.js.map +0 -1
  426. package/dist/hooks/index.mjs +0 -8255
  427. package/dist/hooks/index.mjs.map +0 -1
  428. package/dist/index-50hpiPrV.d.ts +0 -116
  429. package/dist/index-B9zQVEVi.d.mts +0 -116
  430. package/dist/index.d.mts +0 -5
  431. package/dist/index.d.ts +0 -5
  432. package/dist/index.js +0 -123
  433. package/dist/index.js.map +0 -1
  434. package/dist/index.mjs +0 -118
  435. package/dist/index.mjs.map +0 -1
  436. package/dist/infrastructure/index.d.mts +0 -423
  437. package/dist/infrastructure/index.d.ts +0 -423
  438. package/dist/infrastructure/index.js +0 -633
  439. package/dist/infrastructure/index.js.map +0 -1
  440. package/dist/infrastructure/index.mjs +0 -619
  441. package/dist/infrastructure/index.mjs.map +0 -1
  442. package/dist/label-DWTEkNPo.d.ts +0 -226
  443. package/dist/label-LPpdcoBx.d.mts +0 -226
  444. package/dist/layout/index.d.mts +0 -48
  445. package/dist/layout/index.d.ts +0 -48
  446. package/dist/layout/index.js +0 -117
  447. package/dist/layout/index.js.map +0 -1
  448. package/dist/layout/index.mjs +0 -90
  449. package/dist/layout/index.mjs.map +0 -1
  450. package/dist/navigation/index.d.mts +0 -16
  451. package/dist/navigation/index.d.ts +0 -16
  452. package/dist/navigation/index.js +0 -53
  453. package/dist/navigation/index.js.map +0 -1
  454. package/dist/navigation/index.mjs +0 -50
  455. package/dist/navigation/index.mjs.map +0 -1
  456. package/dist/notification/index.d.mts +0 -105
  457. package/dist/notification/index.d.ts +0 -105
  458. package/dist/notification/index.js +0 -278
  459. package/dist/notification/index.js.map +0 -1
  460. package/dist/notification/index.mjs +0 -274
  461. package/dist/notification/index.mjs.map +0 -1
  462. package/dist/organization/index.d.mts +0 -99
  463. package/dist/organization/index.d.ts +0 -99
  464. package/dist/organization/index.js +0 -360
  465. package/dist/organization/index.js.map +0 -1
  466. package/dist/organization/index.mjs +0 -352
  467. package/dist/organization/index.mjs.map +0 -1
  468. package/dist/plugin/index.d.mts +0 -83
  469. package/dist/plugin/index.d.ts +0 -83
  470. package/dist/plugin/index.js +0 -86
  471. package/dist/plugin/index.js.map +0 -1
  472. package/dist/plugin/index.mjs +0 -84
  473. package/dist/plugin/index.mjs.map +0 -1
  474. package/dist/providers/index.d.mts +0 -25
  475. package/dist/providers/index.d.ts +0 -25
  476. package/dist/providers/index.js +0 -84
  477. package/dist/providers/index.js.map +0 -1
  478. package/dist/providers/index.mjs +0 -77
  479. package/dist/providers/index.mjs.map +0 -1
  480. package/dist/rbac/index.d.mts +0 -226
  481. package/dist/rbac/index.d.ts +0 -226
  482. package/dist/rbac/index.js +0 -4784
  483. package/dist/rbac/index.js.map +0 -1
  484. package/dist/rbac/index.mjs +0 -4722
  485. package/dist/rbac/index.mjs.map +0 -1
  486. package/dist/rbac/permissions.d.mts +0 -26
  487. package/dist/rbac/permissions.d.ts +0 -26
  488. package/dist/rbac/permissions.js +0 -94
  489. package/dist/rbac/permissions.js.map +0 -1
  490. package/dist/rbac/permissions.mjs +0 -90
  491. package/dist/rbac/permissions.mjs.map +0 -1
  492. package/dist/rbac/server.d.mts +0 -1
  493. package/dist/rbac/server.d.ts +0 -1
  494. package/dist/rbac/server.js +0 -128
  495. package/dist/rbac/server.js.map +0 -1
  496. package/dist/rbac/server.mjs +0 -124
  497. package/dist/rbac/server.mjs.map +0 -1
  498. package/dist/schemas/index.d.mts +0 -1257
  499. package/dist/schemas/index.d.ts +0 -1257
  500. package/dist/schemas/index.js +0 -572
  501. package/dist/schemas/index.js.map +0 -1
  502. package/dist/schemas/index.mjs +0 -523
  503. package/dist/schemas/index.mjs.map +0 -1
  504. package/dist/server-QuYCTa89.d.mts +0 -83
  505. package/dist/server-QuYCTa89.d.ts +0 -83
  506. package/dist/sonner-C74GlRDQ.d.mts +0 -71
  507. package/dist/sonner-C74GlRDQ.d.ts +0 -71
  508. package/dist/status-BOXZgIqX.d.mts +0 -12
  509. package/dist/status-BOXZgIqX.d.ts +0 -12
  510. package/dist/system/index.d.mts +0 -77
  511. package/dist/system/index.d.ts +0 -77
  512. package/dist/system/index.js +0 -102
  513. package/dist/system/index.js.map +0 -1
  514. package/dist/system/index.mjs +0 -100
  515. package/dist/system/index.mjs.map +0 -1
  516. package/dist/tabs-C6FfBwPY.d.mts +0 -18
  517. package/dist/tabs-C6FfBwPY.d.ts +0 -18
  518. package/dist/tenant-provider-B8eC_Wpb.d.mts +0 -27
  519. package/dist/tenant-provider-B8eC_Wpb.d.ts +0 -27
  520. package/dist/types/index.d.mts +0 -469
  521. package/dist/types/index.d.ts +0 -469
  522. package/dist/types/index.js +0 -25
  523. package/dist/types/index.js.map +0 -1
  524. package/dist/types/index.mjs +0 -21
  525. package/dist/types/index.mjs.map +0 -1
  526. package/dist/ui/auth.d.mts +0 -39
  527. package/dist/ui/auth.d.ts +0 -39
  528. package/dist/ui/auth.js +0 -4941
  529. package/dist/ui/auth.js.map +0 -1
  530. package/dist/ui/auth.mjs +0 -4896
  531. package/dist/ui/auth.mjs.map +0 -1
  532. package/dist/ui/crud.d.mts +0 -2
  533. package/dist/ui/crud.d.ts +0 -2
  534. package/dist/ui/crud.js +0 -4
  535. package/dist/ui/crud.js.map +0 -1
  536. package/dist/ui/crud.mjs +0 -3
  537. package/dist/ui/crud.mjs.map +0 -1
  538. package/dist/ui/data-display.d.mts +0 -596
  539. package/dist/ui/data-display.d.ts +0 -596
  540. package/dist/ui/data-display.js +0 -5307
  541. package/dist/ui/data-display.js.map +0 -1
  542. package/dist/ui/data-display.mjs +0 -5212
  543. package/dist/ui/data-display.mjs.map +0 -1
  544. package/dist/ui/feedback.d.mts +0 -55
  545. package/dist/ui/feedback.d.ts +0 -55
  546. package/dist/ui/feedback.js +0 -2608
  547. package/dist/ui/feedback.js.map +0 -1
  548. package/dist/ui/feedback.mjs +0 -2526
  549. package/dist/ui/feedback.mjs.map +0 -1
  550. package/dist/ui/forms.d.mts +0 -309
  551. package/dist/ui/forms.d.ts +0 -309
  552. package/dist/ui/forms.js +0 -4656
  553. package/dist/ui/forms.js.map +0 -1
  554. package/dist/ui/forms.mjs +0 -4571
  555. package/dist/ui/forms.mjs.map +0 -1
  556. package/dist/ui/index.d.mts +0 -331
  557. package/dist/ui/index.d.ts +0 -331
  558. package/dist/ui/index.js +0 -16953
  559. package/dist/ui/index.js.map +0 -1
  560. package/dist/ui/index.mjs +0 -16598
  561. package/dist/ui/index.mjs.map +0 -1
  562. package/dist/ui/primitives/client.d.mts +0 -61
  563. package/dist/ui/primitives/client.d.ts +0 -61
  564. package/dist/ui/primitives/client.js +0 -3408
  565. package/dist/ui/primitives/client.js.map +0 -1
  566. package/dist/ui/primitives/client.mjs +0 -3256
  567. package/dist/ui/primitives/client.mjs.map +0 -1
  568. package/dist/ui/primitives.d.mts +0 -113
  569. package/dist/ui/primitives.d.ts +0 -113
  570. package/dist/ui/primitives.js +0 -3356
  571. package/dist/ui/primitives.js.map +0 -1
  572. package/dist/ui/primitives.mjs +0 -3227
  573. package/dist/ui/primitives.mjs.map +0 -1
  574. package/dist/user/index.d.mts +0 -228
  575. package/dist/user/index.d.ts +0 -228
  576. package/dist/user/index.js +0 -4306
  577. package/dist/user/index.js.map +0 -1
  578. package/dist/user/index.mjs +0 -4260
  579. package/dist/user/index.mjs.map +0 -1
  580. package/dist/utils/index.d.mts +0 -205
  581. package/dist/utils/index.d.ts +0 -205
  582. package/dist/utils/index.js +0 -574
  583. package/dist/utils/index.js.map +0 -1
  584. package/dist/utils/index.mjs +0 -514
  585. package/dist/utils/index.mjs.map +0 -1
  586. package/dist/workflow/index.d.mts +0 -40
  587. package/dist/workflow/index.d.ts +0 -40
  588. package/dist/workflow/index.js +0 -3710
  589. package/dist/workflow/index.js.map +0 -1
  590. package/dist/workflow/index.mjs +0 -3677
  591. package/dist/workflow/index.mjs.map +0 -1
@@ -0,0 +1,195 @@
1
+ "use client";
2
+
3
+ import { useMemo } from "react";
4
+ import Link from "next/link";
5
+
6
+ import type { DictionaryType } from "../../hooks";
7
+ import type {
8
+ LocaleType,
9
+ NavigationNestedItem,
10
+ NavigationRootItem,
11
+ } from "../../types";
12
+
13
+ import { ensureLocalizedPathname } from "../../utils";
14
+ import {
15
+ cn,
16
+ getDictionaryValue,
17
+ isActivePathname,
18
+ titleCaseToCamelCase,
19
+ } from "../../utils";
20
+
21
+ import {
22
+ Badge,
23
+ DynamicIcon,
24
+ Popover,
25
+ PopoverContent,
26
+ PopoverTrigger,
27
+ PrefetchLink,
28
+ ScrollArea,
29
+ SidebarMenuButton,
30
+ } from "../index";
31
+
32
+ interface SidebarGroupIconMenuProps {
33
+ groupTitle: string;
34
+ items: NavigationRootItem[];
35
+ dictionary: DictionaryType;
36
+ locale: LocaleType;
37
+ pathname: string;
38
+ isRTL: boolean;
39
+ onItemClick?: () => void;
40
+ }
41
+
42
+ export function SidebarGroupIconMenu({
43
+ groupTitle,
44
+ items,
45
+ dictionary,
46
+ locale,
47
+ pathname,
48
+ isRTL,
49
+ onItemClick,
50
+ }: SidebarGroupIconMenuProps) {
51
+ // Get first item with icon for trigger button
52
+ const firstItemWithIcon = useMemo(
53
+ () => items.find((item) => "iconName" in item && item.iconName),
54
+ [items],
55
+ );
56
+
57
+ const renderMenuItem = (
58
+ item: NavigationRootItem | NavigationNestedItem,
59
+ level: number = 0,
60
+ ) => {
61
+ const title = getDictionaryValue(
62
+ // @ts-ignore - dictionary typing might need adjustment or ignore
63
+ titleCaseToCamelCase(item.title),
64
+ dictionary.navigation,
65
+ item.title,
66
+ );
67
+ const label =
68
+ item.label &&
69
+ getDictionaryValue(titleCaseToCamelCase(item.label), dictionary.label);
70
+
71
+ // Handle nested items
72
+ if (item.items && item.items.length > 0) {
73
+ return (
74
+ <div key={item.title} className="space-y-1">
75
+ <div
76
+ className={cn(
77
+ "flex items-center gap-2 rounded-md px-2 py-1.5 text-sm text-sidebar-foreground/70",
78
+ level > 0 && "text-xs",
79
+ )}
80
+ >
81
+ {"iconName" in item && (
82
+ <DynamicIcon name={item.iconName} className="h-4 w-4 shrink-0" />
83
+ )}
84
+ <span className="font-medium">{title}</span>
85
+ {label && (
86
+ <Badge variant="secondary" className="ml-auto text-xs">
87
+ {label}
88
+ </Badge>
89
+ )}
90
+ </div>
91
+ <div className={cn("ml-4 space-y-1", level > 0 && "ml-2")}>
92
+ {item.items.map((subItem) => renderMenuItem(subItem, level + 1))}
93
+ </div>
94
+ </div>
95
+ );
96
+ }
97
+
98
+ // Handle regular link items
99
+ if ("href" in item && item.href) {
100
+ const localizedPathname = ensureLocalizedPathname(item.href, locale);
101
+ const isActive = isActivePathname(localizedPathname, pathname);
102
+ const isCrudLink = localizedPathname.startsWith("/crud/");
103
+ const crudEntity = isCrudLink
104
+ ? localizedPathname.replace("/crud/", "").split("/")[0]
105
+ : undefined;
106
+
107
+ // Need to find where PrefetchLink is defined.
108
+ // Assuming it is exported from "../index".
109
+
110
+ const LinkComponent: any = isCrudLink ? PrefetchLink : Link;
111
+
112
+ return (
113
+ <LinkComponent
114
+ key={item.title}
115
+ href={localizedPathname}
116
+ {...(isCrudLink && crudEntity ? { crudEntity } : {})}
117
+ className={cn(
118
+ "group/menu-item relative flex items-center gap-2 rounded-md px-2 py-1.5 text-sm transition-colors",
119
+ "hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",
120
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-sidebar-ring",
121
+ isActive &&
122
+ "bg-sidebar-accent font-medium text-sidebar-accent-foreground",
123
+ level > 0 && "text-xs pl-6",
124
+ )}
125
+ onClick={onItemClick}
126
+ >
127
+ {"iconName" in item && (
128
+ <DynamicIcon
129
+ name={item.iconName}
130
+ className="h-4 w-4 shrink-0 text-sidebar-foreground/70 group-hover/menu-item:text-sidebar-accent-foreground"
131
+ />
132
+ )}
133
+ <span className="flex-1 truncate">{title}</span>
134
+ {label && (
135
+ <Badge variant="secondary" className="ml-auto shrink-0 text-xs">
136
+ {label}
137
+ </Badge>
138
+ )}
139
+ {isActive && (
140
+ <div className="absolute left-0 top-1/2 h-1.5 w-1 -translate-y-1/2 rounded-r-full bg-sidebar-accent-foreground" />
141
+ )}
142
+ </LinkComponent>
143
+ );
144
+ }
145
+
146
+ return null;
147
+ };
148
+
149
+ if (!firstItemWithIcon || !("iconName" in firstItemWithIcon)) {
150
+ return null;
151
+ }
152
+
153
+ return (
154
+ <Popover>
155
+ <PopoverTrigger asChild>
156
+ <SidebarMenuButton
157
+ className="size-8! p-2! justify-center!"
158
+ tooltip={groupTitle}
159
+ >
160
+ <DynamicIcon name={firstItemWithIcon.iconName} className="h-4 w-4" />
161
+ </SidebarMenuButton>
162
+ </PopoverTrigger>
163
+ <PopoverContent
164
+ side={isRTL ? "left" : "right"}
165
+ align="start"
166
+ sideOffset={12}
167
+ className="w-64 p-0"
168
+ >
169
+ <div className="flex flex-col">
170
+ {/* Header */}
171
+ <div className="border-b px-3 py-2.5">
172
+ <div className="flex items-center gap-2">
173
+ {"iconName" in firstItemWithIcon && (
174
+ <DynamicIcon
175
+ name={firstItemWithIcon.iconName}
176
+ className="h-4 w-4 text-sidebar-foreground/70"
177
+ />
178
+ )}
179
+ <span className="text-sm font-semibold text-sidebar-foreground">
180
+ {groupTitle}
181
+ </span>
182
+ </div>
183
+ </div>
184
+
185
+ {/* Menu Items */}
186
+ <ScrollArea className="max-h-[calc(100vh-12rem)]">
187
+ <div className="p-2 space-y-1">
188
+ {items.map((item) => renderMenuItem(item))}
189
+ </div>
190
+ </ScrollArea>
191
+ </div>
192
+ </PopoverContent>
193
+ </Popover>
194
+ );
195
+ }
@@ -0,0 +1,279 @@
1
+ "use client";
2
+
3
+ import Link from "next/link";
4
+ import { useParams, usePathname } from "next/navigation";
5
+ import { ChevronDown } from "lucide-react";
6
+
7
+ import type { DictionaryType } from "../../hooks"; // Assuming generic type location
8
+ import type {
9
+ LocaleType,
10
+ NavigationNestedItem,
11
+ NavigationRootItem,
12
+ NavigationType,
13
+ } from "../../types";
14
+
15
+ import { i18n } from "../../configs";
16
+ import { ensureLocalizedPathname } from "../../utils";
17
+ import {
18
+ cn,
19
+ getDictionaryValue,
20
+ isActivePathname,
21
+ titleCaseToCamelCase,
22
+ } from "../../utils";
23
+
24
+ import { useSettings } from "../../hooks"; // Exported from core/hooks
25
+
26
+ import {
27
+ Badge,
28
+ Collapsible,
29
+ CollapsibleContent,
30
+ CollapsibleTrigger,
31
+ DynamicIcon,
32
+ PrefetchLink,
33
+ ScrollArea,
34
+ Sidebar as SidebarWrapper,
35
+ SidebarContent,
36
+ SidebarGroup,
37
+ SidebarGroupContent,
38
+ SidebarGroupLabel,
39
+ SidebarHeader,
40
+ SidebarMenu,
41
+ SidebarMenuButton,
42
+ SidebarMenuSubButton, // Added this import
43
+ SidebarMenuItem,
44
+ SidebarMenuSub,
45
+ useSidebar,
46
+ } from "../index"; // Importing from index
47
+
48
+ import { CommandMenu } from "./command-menu";
49
+ import { Logo } from "./logo";
50
+ import { SidebarGroupIconMenu } from "./sidebar-group-icon-menu";
51
+
52
+ interface SidebarProps {
53
+ dictionary: DictionaryType;
54
+ navigation: NavigationType[];
55
+ onGlobalSearch?: (query: string) => void;
56
+ searchResults?: any[]; // SearchGroup[] - using any to avoid import issues for now
57
+ searchLoading?: boolean;
58
+ }
59
+
60
+ export function AppSidebar({
61
+ dictionary,
62
+ navigation,
63
+ onGlobalSearch,
64
+ searchResults,
65
+ searchLoading,
66
+ }: SidebarProps) {
67
+ // Navigation is now REQUIRED prop, no fallback to internal data
68
+ const navData = navigation;
69
+ const pathname = usePathname();
70
+ const params = useParams();
71
+ const { openMobile, setOpenMobile, isMobile, state, isHoverExpanded } =
72
+ useSidebar();
73
+ const { settings } = useSettings();
74
+
75
+ const locale = params.lang as LocaleType;
76
+ const direction = i18n.localeDirection[locale];
77
+ const isRTL = (direction as "ltr" | "rtl") === "rtl";
78
+ const isHoizontalAndDesktop = settings.layout === "horizontal" && !isMobile;
79
+
80
+ // If the layout is horizontal and not on mobile, don't render the sidebar. (We use a menubar for horizontal layout navigation.)
81
+ if (isHoizontalAndDesktop) return null;
82
+
83
+ const renderMenuItem = (
84
+ item: NavigationRootItem | NavigationNestedItem,
85
+ isSub = false,
86
+ ) => {
87
+ const title = getDictionaryValue(
88
+ titleCaseToCamelCase(item.title),
89
+ dictionary.navigation,
90
+ item.title, // Fallback to original title if not found
91
+ );
92
+ const label =
93
+ item.label &&
94
+ getDictionaryValue(titleCaseToCamelCase(item.label), dictionary.label);
95
+
96
+ // If the item has nested items, render it with a collapsible dropdown.
97
+ if (item.items) {
98
+ return (
99
+ <Collapsible className="group/collapsible" defaultOpen={true}>
100
+ <CollapsibleTrigger asChild>
101
+ <SidebarMenuButton className="w-full justify-between [&[data-state=open]>svg]:rotate-180">
102
+ <span className="flex items-center">
103
+ {"iconName" in item && (
104
+ <DynamicIcon name={item.iconName} className="me-2 h-4 w-4" />
105
+ )}
106
+ <span>{title}</span>
107
+ {"label" in item && (
108
+ <Badge variant="secondary" className="me-2">
109
+ {label}
110
+ </Badge>
111
+ )}
112
+ </span>
113
+ <ChevronDown className="h-4 w-4 shrink-0 text-muted-foreground transition-transform duration-200" />
114
+ </SidebarMenuButton>
115
+ </CollapsibleTrigger>
116
+ <CollapsibleContent className="overflow-hidden data-[state=closed]:animate-collapsible-up data-[state=open]:animate-collapsible-down">
117
+ <SidebarMenuSub>
118
+ {item.items.map((subItem: NavigationNestedItem) => (
119
+ <SidebarMenuItem key={subItem.title}>
120
+ {renderMenuItem(subItem, true)}
121
+ </SidebarMenuItem>
122
+ ))}
123
+ </SidebarMenuSub>
124
+ </CollapsibleContent>
125
+ </Collapsible>
126
+ );
127
+ }
128
+
129
+ // Otherwise, render the item with a link.
130
+ if ("href" in item) {
131
+ const localizedPathname = ensureLocalizedPathname(item.href, locale);
132
+ const isExactMatchRequired =
133
+ item.title === "Tổng quan" ||
134
+ item.title === "Overview" ||
135
+ item.title === "Dashboard";
136
+ const isActive = isActivePathname(
137
+ localizedPathname,
138
+ pathname,
139
+ isExactMatchRequired,
140
+ );
141
+
142
+ // ✅ Check if this is a CRUD link for prefetching
143
+ const isCrudLink = localizedPathname.startsWith("/crud/");
144
+ const crudEntity = isCrudLink
145
+ ? localizedPathname.replace("/crud/", "").split("/")[0]
146
+ : undefined;
147
+ const LinkComponent = isCrudLink ? PrefetchLink : Link;
148
+
149
+ const MenuButtonComponent = isSub
150
+ ? SidebarMenuSubButton
151
+ : SidebarMenuButton;
152
+
153
+ return (
154
+ <MenuButtonComponent
155
+ isActive={isActive}
156
+ onClick={() => setOpenMobile(!openMobile)}
157
+ asChild
158
+ >
159
+ <LinkComponent
160
+ href={localizedPathname}
161
+ {...(isCrudLink && crudEntity ? { crudEntity } : {})}
162
+ >
163
+ {"iconName" in item && (
164
+ <DynamicIcon name={item.iconName} className="h-4 w-4" />
165
+ )}
166
+ <span>{title}</span>
167
+ {"label" in item && <Badge variant="secondary">{label}</Badge>}
168
+ </LinkComponent>
169
+ </MenuButtonComponent>
170
+ );
171
+ }
172
+ };
173
+
174
+ // Enforce icon mode for Carbon style consistency if not set explicitly to offcanvas by some override (though we prefer icon)
175
+ const collapsibleMode =
176
+ settings.sidebarCollapsible === "offcanvas"
177
+ ? "icon"
178
+ : settings.sidebarCollapsible || "icon";
179
+
180
+ return (
181
+ <SidebarWrapper
182
+ side={isRTL ? "right" : "left"}
183
+ variant={settings.sidebarVariant}
184
+ collapsible={collapsibleMode}
185
+ >
186
+ <SidebarHeader className="space-y-2 group-data-[collapsible=icon]:items-center group-data-[hover-expanded=true]:!items-stretch">
187
+ <Link
188
+ href={ensureLocalizedPathname("/", locale)}
189
+ className={cn(
190
+ "w-fit pb-0",
191
+ state === "collapsed" && !isHoverExpanded && !isMobile
192
+ ? "p-1"
193
+ : "p-2",
194
+ )}
195
+ onClick={() => isMobile && setOpenMobile(!openMobile)}
196
+ >
197
+ <Logo
198
+ className="group-data-[collapsible=icon]:justify-center group-data-[hover-expanded=true]:!justify-start"
199
+ size={
200
+ state === "collapsed" && !isHoverExpanded && !isMobile
201
+ ? "sm"
202
+ : "md"
203
+ }
204
+ showText={state === "expanded" || isHoverExpanded || isMobile}
205
+ collapsed={state === "collapsed" && !isHoverExpanded && !isMobile}
206
+ />
207
+ </Link>
208
+ <CommandMenu
209
+ dictionary={dictionary}
210
+ navigation={navData}
211
+ variant={
212
+ state === "collapsed" && !isHoverExpanded && !isMobile
213
+ ? "icon"
214
+ : "default"
215
+ }
216
+ buttonClassName={cn(
217
+ "group-data-[collapsible=icon]:mx-auto",
218
+ "group-data-[hover-expanded=true]:!mx-0 group-data-[hover-expanded=true]:!w-full",
219
+ )}
220
+ onSearch={onGlobalSearch}
221
+ searchResults={searchResults}
222
+ loading={searchLoading}
223
+ />
224
+ </SidebarHeader>
225
+ <ScrollArea>
226
+ <SidebarContent className="gap-0">
227
+ {navData.map((nav) => {
228
+ const title = getDictionaryValue(
229
+ titleCaseToCamelCase(nav.title),
230
+ dictionary.navigation,
231
+ nav.title, // Fallback to original title if not found
232
+ );
233
+
234
+ // Only show icon mode if collapsed AND NOT hover expanded AND NOT mobile
235
+ const isIconMode =
236
+ collapsibleMode === "icon" &&
237
+ state === "collapsed" &&
238
+ !isHoverExpanded &&
239
+ !isMobile;
240
+
241
+ const groupContent = (
242
+ <SidebarGroup key={nav.title}>
243
+ <SidebarGroupLabel>{title}</SidebarGroupLabel>
244
+ <SidebarGroupContent>
245
+ <SidebarMenu>
246
+ {nav.items.map((item) => (
247
+ <SidebarMenuItem key={item.title}>
248
+ {renderMenuItem(item)}
249
+ </SidebarMenuItem>
250
+ ))}
251
+ </SidebarMenu>
252
+ </SidebarGroupContent>
253
+ </SidebarGroup>
254
+ );
255
+
256
+ // When in icon mode, show icon menu instead of full group
257
+ if (isIconMode) {
258
+ return (
259
+ <div key={nav.title} className="flex justify-center p-2">
260
+ <SidebarGroupIconMenu
261
+ groupTitle={title}
262
+ items={nav.items}
263
+ dictionary={dictionary}
264
+ locale={locale}
265
+ pathname={pathname}
266
+ isRTL={isRTL}
267
+ onItemClick={() => isMobile && setOpenMobile(false)}
268
+ />
269
+ </div>
270
+ );
271
+ }
272
+
273
+ return groupContent;
274
+ })}
275
+ </SidebarContent>
276
+ </ScrollArea>
277
+ </SidebarWrapper>
278
+ );
279
+ }
@@ -0,0 +1,201 @@
1
+ "use client";
2
+
3
+ import {
4
+ createContext,
5
+ useContext,
6
+ useState,
7
+ useCallback,
8
+ useRef,
9
+ useEffect,
10
+ } from "react";
11
+ import { usePathname } from "next/navigation";
12
+ import type { ReactNode } from "react";
13
+
14
+ interface CachedContent {
15
+ html: string;
16
+ scrollPosition: number;
17
+ timestamp: number;
18
+ data?: unknown;
19
+ }
20
+
21
+ interface TabContentCacheContextValue {
22
+ getCachedContent: (path: string) => CachedContent | null;
23
+ setCachedContent: (path: string, content: CachedContent) => void;
24
+ clearCache: (path?: string) => void;
25
+ clearAllCache: () => void;
26
+ isCached: (path: string) => boolean;
27
+ }
28
+
29
+ const TabContentCacheContext = createContext<
30
+ TabContentCacheContextValue | undefined
31
+ >(undefined);
32
+
33
+ const CACHE_STORAGE_KEY = "tab-content-cache";
34
+ const CACHE_EXPIRY = 30 * 60 * 1000; // 30 minutes
35
+
36
+ export function TabContentCacheProvider({ children }: { children: ReactNode }) {
37
+ const [cache, setCache] = useState<Map<string, CachedContent>>(new Map());
38
+ const pathname = usePathname();
39
+ const scrollPositionsRef = useRef<Map<string, number>>(new Map());
40
+
41
+ // Load cache from sessionStorage on mount
42
+ useEffect(() => {
43
+ if (typeof window === "undefined") return;
44
+
45
+ try {
46
+ const stored = sessionStorage.getItem(CACHE_STORAGE_KEY);
47
+ if (stored) {
48
+ const parsedCache = JSON.parse(stored) as Record<string, CachedContent>;
49
+ const cacheMap = new Map(Object.entries(parsedCache));
50
+
51
+ // Remove expired entries
52
+ const now = Date.now();
53
+ const validCache = new Map<string, CachedContent>();
54
+ for (const [path, content] of cacheMap.entries()) {
55
+ if (now - content.timestamp < CACHE_EXPIRY) {
56
+ validCache.set(path, content);
57
+ }
58
+ }
59
+
60
+ setCache(validCache);
61
+ }
62
+ } catch (error) {
63
+ console.error("Failed to load tab content cache:", error);
64
+ }
65
+ }, []);
66
+
67
+ // Save cache to sessionStorage whenever it changes
68
+ useEffect(() => {
69
+ if (typeof window === "undefined") return;
70
+
71
+ try {
72
+ const cacheObj = Object.fromEntries(cache);
73
+ sessionStorage.setItem(CACHE_STORAGE_KEY, JSON.stringify(cacheObj));
74
+ } catch (error) {
75
+ console.error("Failed to save tab content cache:", error);
76
+ }
77
+ }, [cache]);
78
+
79
+ // Save scroll position before navigation
80
+ useEffect(() => {
81
+ const handleScroll = () => {
82
+ if (pathname) {
83
+ scrollPositionsRef.current.set(pathname, window.scrollY);
84
+ }
85
+ };
86
+
87
+ window.addEventListener("scroll", handleScroll, { passive: true });
88
+ return () => window.removeEventListener("scroll", handleScroll);
89
+ }, [pathname]);
90
+
91
+ // Restore scroll position when pathname changes
92
+ useEffect(() => {
93
+ if (!pathname) return;
94
+
95
+ const cachedContent = cache.get(pathname);
96
+ if (cachedContent) {
97
+ // Restore scroll position after a short delay to ensure content is rendered
98
+ setTimeout(() => {
99
+ window.scrollTo({
100
+ top:
101
+ cachedContent.scrollPosition ||
102
+ scrollPositionsRef.current.get(pathname) ||
103
+ 0,
104
+ behavior: "instant",
105
+ });
106
+ }, 50);
107
+ }
108
+ }, [pathname, cache]);
109
+
110
+ const getCachedContent = useCallback(
111
+ (path: string): CachedContent | null => {
112
+ const cached = cache.get(path);
113
+ if (!cached) return null;
114
+
115
+ // Check if cache is expired
116
+ const now = Date.now();
117
+ if (now - cached.timestamp > CACHE_EXPIRY) {
118
+ cache.delete(path);
119
+ return null;
120
+ }
121
+
122
+ return cached;
123
+ },
124
+ [cache],
125
+ );
126
+
127
+ const setCachedContent = useCallback(
128
+ (path: string, content: CachedContent) => {
129
+ setCache((prev) => {
130
+ const newCache = new Map(prev);
131
+ newCache.set(path, {
132
+ ...content,
133
+ scrollPosition: scrollPositionsRef.current.get(path) || 0,
134
+ timestamp: Date.now(),
135
+ });
136
+ return newCache;
137
+ });
138
+ },
139
+ [],
140
+ );
141
+
142
+ const clearCache = useCallback((path?: string) => {
143
+ if (path) {
144
+ setCache((prev) => {
145
+ const newCache = new Map(prev);
146
+ newCache.delete(path);
147
+ return newCache;
148
+ });
149
+ scrollPositionsRef.current.delete(path);
150
+ } else {
151
+ setCache(new Map());
152
+ scrollPositionsRef.current.clear();
153
+ }
154
+ }, []);
155
+
156
+ const clearAllCache = useCallback(() => {
157
+ setCache(new Map());
158
+ scrollPositionsRef.current.clear();
159
+ if (typeof window !== "undefined") {
160
+ sessionStorage.removeItem(CACHE_STORAGE_KEY);
161
+ }
162
+ }, []);
163
+
164
+ const isCached = useCallback(
165
+ (path: string): boolean => {
166
+ const cached = cache.get(path);
167
+ if (!cached) return false;
168
+
169
+ const now = Date.now();
170
+ return now - cached.timestamp < CACHE_EXPIRY;
171
+ },
172
+ [cache],
173
+ );
174
+
175
+ return (
176
+ <TabContentCacheContext.Provider
177
+ value={{
178
+ getCachedContent,
179
+ setCachedContent,
180
+ clearCache,
181
+ clearAllCache,
182
+ isCached,
183
+ }}
184
+ >
185
+ {children}
186
+ </TabContentCacheContext.Provider>
187
+ );
188
+ }
189
+
190
+ const noopTabContentCache: TabContentCacheContextValue = {
191
+ getCachedContent: () => null,
192
+ setCachedContent: () => {},
193
+ clearCache: () => {},
194
+ clearAllCache: () => {},
195
+ isCached: () => false,
196
+ };
197
+
198
+ export function useTabContentCache() {
199
+ const context = useContext(TabContentCacheContext);
200
+ return context ?? noopTabContentCache;
201
+ }