@liorian/sdk 0.28.0-alpha.56010ca

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 (362) hide show
  1. package/README.md +483 -0
  2. package/package.json +94 -0
  3. package/schemas/module.schema.json +818 -0
  4. package/src/application/index.ts +3 -0
  5. package/src/application/module-instance.ts +36 -0
  6. package/src/application/service/auth-api-service.ts +291 -0
  7. package/src/application/service/auth-user.service.ts +108 -0
  8. package/src/application/service/index.ts +12 -0
  9. package/src/application/service/module-activation-api.service.ts +105 -0
  10. package/src/application/service/notifications-api-service.ts +38 -0
  11. package/src/application/service/notifications-push.service.ts +299 -0
  12. package/src/application/service/notifications-socket-service.ts +76 -0
  13. package/src/application/service/organizations-api-service.ts +104 -0
  14. package/src/application/service/otp-api-service.ts +11 -0
  15. package/src/application/service/storage-api-service.ts +77 -0
  16. package/src/application/service/storefront-api.service.ts +72 -0
  17. package/src/application/service/user-preferences-api.service.ts +57 -0
  18. package/src/domain/config/app.config.ts +35 -0
  19. package/src/domain/config/auth.config.ts +30 -0
  20. package/src/domain/config/index.ts +4 -0
  21. package/src/domain/config/logo.config.ts +17 -0
  22. package/src/domain/entities/activities.interface.ts +18 -0
  23. package/src/domain/entities/catalog.interface.ts +96 -0
  24. package/src/domain/entities/index.ts +13 -0
  25. package/src/domain/entities/media.ts +22 -0
  26. package/src/domain/entities/module-activation.interface.ts +173 -0
  27. package/src/domain/entities/module.interface.ts +101 -0
  28. package/src/domain/entities/notification.interface.ts +23 -0
  29. package/src/domain/entities/objectable.type.ts +3 -0
  30. package/src/domain/entities/organization.interface.ts +81 -0
  31. package/src/domain/entities/user-auth.interface.ts +17 -0
  32. package/src/domain/entities/user-phone.interface.ts +11 -0
  33. package/src/domain/entities/user-profile.interface.ts +23 -0
  34. package/src/domain/entities/user.interface.ts +79 -0
  35. package/src/domain/enums/coloring.enum.ts +6 -0
  36. package/src/domain/enums/domains.enum.ts +282 -0
  37. package/src/domain/enums/index.ts +8 -0
  38. package/src/domain/enums/module-category.enum.ts +57 -0
  39. package/src/domain/enums/module.enum.ts +97 -0
  40. package/src/domain/enums/routine.enum.ts +12 -0
  41. package/src/domain/enums/user-profile.enum.ts +25 -0
  42. package/src/domain/enums/user-status.enum.ts +7 -0
  43. package/src/domain/index.ts +6 -0
  44. package/src/domain/typing/auth-caches.ts +12 -0
  45. package/src/domain/typing/auth-oauth.types.ts +172 -0
  46. package/src/domain/typing/devise.ts +2 -0
  47. package/src/domain/typing/index.ts +10 -0
  48. package/src/domain/typing/response.ts +30 -0
  49. package/src/domain/typing/routine.types.ts +113 -0
  50. package/src/domain/typing/session.interface.ts +28 -0
  51. package/src/domain/typing/statisticals.ts +11 -0
  52. package/src/domain/typing/user-media-upload.ts +9 -0
  53. package/src/domain/typing/values.ts +6 -0
  54. package/src/index.tsx +168 -0
  55. package/src/infrastructure/capabilities/cache-storage/capability.ts +129 -0
  56. package/src/infrastructure/capabilities/cache-storage/enum.ts +5 -0
  57. package/src/infrastructure/capabilities/cache-storage/index.ts +4 -0
  58. package/src/infrastructure/capabilities/cache-storage/types.ts +13 -0
  59. package/src/infrastructure/capabilities/index.ts +3 -0
  60. package/src/infrastructure/capabilities/stackable/capability.ts +55 -0
  61. package/src/infrastructure/capabilities/stackable/index.ts +3 -0
  62. package/src/infrastructure/capabilities/stackable/types.ts +24 -0
  63. package/src/infrastructure/common-classname.constant.ts +4 -0
  64. package/src/infrastructure/data/countries.ts +208 -0
  65. package/src/infrastructure/data/gender.ts +5 -0
  66. package/src/infrastructure/data/index.ts +3 -0
  67. package/src/infrastructure/dataset/index.ts +3 -0
  68. package/src/infrastructure/dataset/sign-in.dataset.ts +21 -0
  69. package/src/infrastructure/dataset/sign-up.dataset.ts +64 -0
  70. package/src/infrastructure/hooks/index.ts +10 -0
  71. package/src/infrastructure/hooks/use-activity-lock-draft.ts +69 -0
  72. package/src/infrastructure/hooks/use-auth.ts +24 -0
  73. package/src/infrastructure/hooks/use-elastic-interaction.ts +180 -0
  74. package/src/infrastructure/hooks/use-is-desktop.ts +25 -0
  75. package/src/infrastructure/hooks/use-is-tauri.ts +17 -0
  76. package/src/infrastructure/hooks/use-mobile.ts +19 -0
  77. package/src/infrastructure/hooks/use-notifications.ts +128 -0
  78. package/src/infrastructure/hooks/use-recent-colors.ts +113 -0
  79. package/src/infrastructure/hooks/use-recent-modules.ts +76 -0
  80. package/src/infrastructure/index.tsx +11 -0
  81. package/src/infrastructure/library/design-system.ts +95 -0
  82. package/src/infrastructure/library/index.tsx +5 -0
  83. package/src/infrastructure/library/motion-utils.ts +77 -0
  84. package/src/infrastructure/library/motion.tsx +31 -0
  85. package/src/infrastructure/library/scroll-progress.tsx +93 -0
  86. package/src/infrastructure/providers/auth-guard.provider.tsx +47 -0
  87. package/src/infrastructure/providers/auth.provider.tsx +168 -0
  88. package/src/infrastructure/providers/index.tsx +8 -0
  89. package/src/infrastructure/providers/module-usage.provider.tsx +95 -0
  90. package/src/infrastructure/providers/modules-guard.provider.tsx +64 -0
  91. package/src/infrastructure/providers/modules-routines.provider.tsx +33 -0
  92. package/src/infrastructure/providers/modules-switcher.provider.tsx +25 -0
  93. package/src/infrastructure/providers/query.provider.tsx +27 -0
  94. package/src/infrastructure/routines/__tests__/routine.test.ts +368 -0
  95. package/src/infrastructure/routines/index.tsx +3 -0
  96. package/src/infrastructure/routines/routine.hook.ts +121 -0
  97. package/src/infrastructure/routines/routine.ts +283 -0
  98. package/src/infrastructure/routines/routine.tsx +283 -0
  99. package/src/infrastructure/stores/activity-lock.store.ts +22 -0
  100. package/src/infrastructure/stores/auth-user-connected.store.ts +24 -0
  101. package/src/infrastructure/stores/dataset.store.ts +106 -0
  102. package/src/infrastructure/stores/index.ts +6 -0
  103. package/src/infrastructure/stores/module.store.ts +266 -0
  104. package/src/infrastructure/stores/upload.store.ts +198 -0
  105. package/src/infrastructure/utilities/access-label.util.ts +158 -0
  106. package/src/infrastructure/utilities/activities.util.tsx +54 -0
  107. package/src/infrastructure/utilities/activity-lock.service.ts +263 -0
  108. package/src/infrastructure/utilities/activity-tracker.service.ts +205 -0
  109. package/src/infrastructure/utilities/api-service.ts +237 -0
  110. package/src/infrastructure/utilities/auth-logout.util.ts +23 -0
  111. package/src/infrastructure/utilities/classname.util.ts +7 -0
  112. package/src/infrastructure/utilities/encryption.service.ts +125 -0
  113. package/src/infrastructure/utilities/form-snapshot.service.ts +304 -0
  114. package/src/infrastructure/utilities/format.util.ts +40 -0
  115. package/src/infrastructure/utilities/index.tsx +23 -0
  116. package/src/infrastructure/utilities/media-label.service.ts +47 -0
  117. package/src/infrastructure/utilities/modules.ts +11 -0
  118. package/src/infrastructure/utilities/permission.util.ts +22 -0
  119. package/src/infrastructure/utilities/push-permission.util.ts +43 -0
  120. package/src/infrastructure/utilities/route-access.ts +38 -0
  121. package/src/infrastructure/utilities/socket-service.ts +123 -0
  122. package/src/infrastructure/utilities/sso-auth.util.ts +188 -0
  123. package/src/infrastructure/utilities/stringable.util.ts +16 -0
  124. package/src/infrastructure/utilities/strings.util.ts +18 -0
  125. package/src/infrastructure/utilities/tauri.util.ts +15 -0
  126. package/src/infrastructure/utilities/utils.ts +6 -0
  127. package/src/infrastructure/utilities/values.ts +5 -0
  128. package/src/presentation/8starlabs-ui/button.tsx +94 -0
  129. package/src/presentation/8starlabs-ui/flip-clock.tsx +368 -0
  130. package/src/presentation/8starlabs-ui/heatmap.tsx +430 -0
  131. package/src/presentation/8starlabs-ui/hooks/index.tsx +2 -0
  132. package/src/presentation/8starlabs-ui/hooks/use-mobile.ts +21 -0
  133. package/src/presentation/8starlabs-ui/index.tsx +20 -0
  134. package/src/presentation/8starlabs-ui/json-viewer.tsx +972 -0
  135. package/src/presentation/8starlabs-ui/marquee.tsx +134 -0
  136. package/src/presentation/8starlabs-ui/partition-bar.tsx +198 -0
  137. package/src/presentation/8starlabs-ui/scroll-fade.tsx +158 -0
  138. package/src/presentation/8starlabs-ui/status-indicator.tsx +86 -0
  139. package/src/presentation/8starlabs-ui/system-banner.tsx +50 -0
  140. package/src/presentation/8starlabs-ui/timeline.tsx +576 -0
  141. package/src/presentation/8starlabs-ui/transport-badge.tsx +249 -0
  142. package/src/presentation/8starlabs-ui/ui/copy-button.tsx +60 -0
  143. package/src/presentation/8starlabs-ui/ui/index.tsx +2 -0
  144. package/src/presentation/analytics-section.tsx +85 -0
  145. package/src/presentation/app-sidebar.tsx +234 -0
  146. package/src/presentation/charts/area-widget.chart-skeleton.tsx +61 -0
  147. package/src/presentation/charts/area-widget.chart.tsx +128 -0
  148. package/src/presentation/charts/chart-widgets.types.ts +81 -0
  149. package/src/presentation/charts/index.tsx +16 -0
  150. package/src/presentation/charts/line-widget.chart-skeleton.tsx +64 -0
  151. package/src/presentation/charts/line-widget.chart.tsx +105 -0
  152. package/src/presentation/charts/pie-widget.chart-skeleton.tsx +56 -0
  153. package/src/presentation/charts/pie-widget.chart.tsx +168 -0
  154. package/src/presentation/charts/radar-widget.chart-skeleton.tsx +67 -0
  155. package/src/presentation/charts/radar-widget.chart.tsx +80 -0
  156. package/src/presentation/charts/radial-stacked-widget.chart-skeleton.tsx +66 -0
  157. package/src/presentation/charts/radial-stacked-widget.chart.tsx +120 -0
  158. package/src/presentation/charts/radial-widget.chart-skeleton.tsx +61 -0
  159. package/src/presentation/charts/radial-widget.chart.tsx +87 -0
  160. package/src/presentation/charts/tooltip-widget.chart-skeleton.tsx +64 -0
  161. package/src/presentation/charts/tooltip-widget.chart.tsx +89 -0
  162. package/src/presentation/components/activity-actions.tsx +20 -0
  163. package/src/presentation/components/activity-container.tsx +55 -0
  164. package/src/presentation/components/activity-content.tsx +20 -0
  165. package/src/presentation/components/activity-descriptor-parser.tsx +37 -0
  166. package/src/presentation/components/activity-header.tsx +20 -0
  167. package/src/presentation/components/activity-loader.tsx +19 -0
  168. package/src/presentation/components/activity-title.tsx +32 -0
  169. package/src/presentation/components/activity.tsx +22 -0
  170. package/src/presentation/components/auth/index.tsx +4 -0
  171. package/src/presentation/components/auth/sso-callback.view.tsx +44 -0
  172. package/src/presentation/components/auth/sso-disconnect.view.tsx +41 -0
  173. package/src/presentation/components/auth/sso-sign-in.view.tsx +29 -0
  174. package/src/presentation/components/auth-lock-screen.tsx +309 -0
  175. package/src/presentation/components/auth-session.view.tsx +17 -0
  176. package/src/presentation/components/data-table.tsx +814 -0
  177. package/src/presentation/components/dynamic-icon.tsx +16 -0
  178. package/src/presentation/components/floating-upload.tsx +291 -0
  179. package/src/presentation/components/index.tsx +40 -0
  180. package/src/presentation/components/local-time.tsx +170 -0
  181. package/src/presentation/components/markdown-parser.tsx +201 -0
  182. package/src/presentation/components/message-scroller.tsx +131 -0
  183. package/src/presentation/components/module-first-access-config.view.tsx +181 -0
  184. package/src/presentation/components/module-first-access-pending.view.tsx +38 -0
  185. package/src/presentation/components/module-guard.tsx +34 -0
  186. package/src/presentation/components/modules-first-access.guard.tsx +88 -0
  187. package/src/presentation/components/modules-guard-forbidden.tsx +46 -0
  188. package/src/presentation/components/notification-details.modal.tsx +145 -0
  189. package/src/presentation/components/notification-item.tsx +127 -0
  190. package/src/presentation/components/notifications-popover.tsx +128 -0
  191. package/src/presentation/components/push-notifications.provider.tsx +65 -0
  192. package/src/presentation/components/upload-progress-dialog.tsx +140 -0
  193. package/src/presentation/components/waiting-bar.tsx +22 -0
  194. package/src/presentation/components/waiting-section.tsx +15 -0
  195. package/src/presentation/components/waiting.tsx +14 -0
  196. package/src/presentation/data-grid/data-grid-empty.tsx +24 -0
  197. package/src/presentation/data-grid/data-grid-search-engine.tsx +32 -0
  198. package/src/presentation/data-grid/data-grid.tsx +892 -0
  199. package/src/presentation/data-grid/index.tsx +4 -0
  200. package/src/presentation/form-screen.tsx +95 -0
  201. package/src/presentation/icons/custom.tsx +20 -0
  202. package/src/presentation/icons/glyphIcons.tsx +53 -0
  203. package/src/presentation/icons/icons.enum.ts +4 -0
  204. package/src/presentation/icons/icons.util.ts +6 -0
  205. package/src/presentation/icons/index.tsx +8 -0
  206. package/src/presentation/icons/lucide.tsx +17 -0
  207. package/src/presentation/icons/remix.tsx +33 -0
  208. package/src/presentation/icons/types.ts +27 -0
  209. package/src/presentation/index.tsx +45 -0
  210. package/src/presentation/modals/components/ModalBox.tsx +74 -0
  211. package/src/presentation/modals/components/ModalPortal.tsx +31 -0
  212. package/src/presentation/modals/components/ModalStepper.tsx +319 -0
  213. package/src/presentation/modals/components/ModalWrapper.tsx +65 -0
  214. package/src/presentation/modals/components/index.tsx +5 -0
  215. package/src/presentation/modals/hooks/index.ts +2 -0
  216. package/src/presentation/modals/hooks/useModal.ts +38 -0
  217. package/src/presentation/modals/index.tsx +5 -0
  218. package/src/presentation/modals/stores/index.ts +2 -0
  219. package/src/presentation/modals/stores/useModalStore.ts +90 -0
  220. package/src/presentation/modals/types/index.ts +2 -0
  221. package/src/presentation/modals/types/modal.type.ts +33 -0
  222. package/src/presentation/module-menubar.tsx +300 -0
  223. package/src/presentation/module-widget.tsx +233 -0
  224. package/src/presentation/nav-documents.tsx +89 -0
  225. package/src/presentation/nav-main.tsx +62 -0
  226. package/src/presentation/nav-secondary.tsx +41 -0
  227. package/src/presentation/nav-user.tsx +109 -0
  228. package/src/presentation/permission-action-badge.tsx +35 -0
  229. package/src/presentation/reui/index.tsx +3 -0
  230. package/src/presentation/reui/stepper.tsx +508 -0
  231. package/src/presentation/reui/timeline.tsx +226 -0
  232. package/src/presentation/sheets/index.tsx +2 -0
  233. package/src/presentation/sheets/legacy-sheet-header.tsx +0 -0
  234. package/src/presentation/sheets/legacy-sheet.tsx +37 -0
  235. package/src/presentation/size.enum.ts +19 -0
  236. package/src/presentation/system/index.tsx +3 -0
  237. package/src/presentation/system/logo.theme.tsx +21 -0
  238. package/src/presentation/system/types.ts +10 -0
  239. package/src/presentation/theme/index.tsx +6 -0
  240. package/src/presentation/theme/prefer-color-scheme.tsx +50 -0
  241. package/src/presentation/theme/switch-color-scheme.tsx +16 -0
  242. package/src/presentation/theme/theme-switcher-button.tsx +20 -0
  243. package/src/presentation/theme/theme.enum.ts +4 -0
  244. package/src/presentation/theme/theme.store.ts +87 -0
  245. package/src/presentation/themes/index.tsx +2 -0
  246. package/src/presentation/themes/katon/dashboard-layout.tsx +1080 -0
  247. package/src/presentation/themes/katon/edge-section.tsx +19 -0
  248. package/src/presentation/themes/katon/header-menubar.tsx +270 -0
  249. package/src/presentation/themes/katon/header-modules-available.tsx +44 -0
  250. package/src/presentation/themes/katon/header-modules-recents.tsx +52 -0
  251. package/src/presentation/themes/katon/header-modules-store.tsx +25 -0
  252. package/src/presentation/themes/katon/header-options.tsx +13 -0
  253. package/src/presentation/themes/katon/header-organization-select.tsx +146 -0
  254. package/src/presentation/themes/katon/header-routines.tsx +74 -0
  255. package/src/presentation/themes/katon/header-tasks-connected-user.tsx +150 -0
  256. package/src/presentation/themes/katon/index.tsx +16 -0
  257. package/src/presentation/themes/katon/main-wrapper.tsx +34 -0
  258. package/src/presentation/themes/katon/module-item-link.tsx +32 -0
  259. package/src/presentation/themes/katon/view-frame.tsx +25 -0
  260. package/src/presentation/themes/katon/view-helmet.tsx +53 -0
  261. package/src/presentation/themes/katon/view-status.tsx +32 -0
  262. package/src/presentation/themes/katon/view-wrapper.tsx +15 -0
  263. package/src/presentation/themes/katon/view.tsx +42 -0
  264. package/src/presentation/ui/accordion-multiselect.tsx +206 -0
  265. package/src/presentation/ui/accordion.tsx +81 -0
  266. package/src/presentation/ui/alert-dialog.tsx +199 -0
  267. package/src/presentation/ui/alert.tsx +76 -0
  268. package/src/presentation/ui/aspect-ratio.tsx +11 -0
  269. package/src/presentation/ui/attachment.tsx +204 -0
  270. package/src/presentation/ui/avatar.tsx +112 -0
  271. package/src/presentation/ui/badge.tsx +49 -0
  272. package/src/presentation/ui/breadcrumb.tsx +122 -0
  273. package/src/presentation/ui/bubble.tsx +125 -0
  274. package/src/presentation/ui/button-group.tsx +83 -0
  275. package/src/presentation/ui/button.tsx +87 -0
  276. package/src/presentation/ui/calendar.tsx +222 -0
  277. package/src/presentation/ui/card.tsx +106 -0
  278. package/src/presentation/ui/carousel.tsx +242 -0
  279. package/src/presentation/ui/chart.tsx +373 -0
  280. package/src/presentation/ui/checkbox.tsx +33 -0
  281. package/src/presentation/ui/clickable.tsx +58 -0
  282. package/src/presentation/ui/collapsible.tsx +33 -0
  283. package/src/presentation/ui/color-swatch-selector.tsx +81 -0
  284. package/src/presentation/ui/combobox.tsx +299 -0
  285. package/src/presentation/ui/command.tsx +195 -0
  286. package/src/presentation/ui/context-menu.tsx +263 -0
  287. package/src/presentation/ui/dialog.tsx +168 -0
  288. package/src/presentation/ui/direction.tsx +22 -0
  289. package/src/presentation/ui/drawer.tsx +134 -0
  290. package/src/presentation/ui/dropdown-menu.tsx +269 -0
  291. package/src/presentation/ui/empty.tsx +104 -0
  292. package/src/presentation/ui/field.tsx +238 -0
  293. package/src/presentation/ui/granularity-selector.tsx +58 -0
  294. package/src/presentation/ui/hover-card.tsx +44 -0
  295. package/src/presentation/ui/index.tsx +74 -0
  296. package/src/presentation/ui/input-group.tsx +156 -0
  297. package/src/presentation/ui/input-otp.tsx +87 -0
  298. package/src/presentation/ui/input.tsx +19 -0
  299. package/src/presentation/ui/item.tsx +196 -0
  300. package/src/presentation/ui/kpi-card.tsx +203 -0
  301. package/src/presentation/ui/label-selector.tsx +100 -0
  302. package/src/presentation/ui/label.tsx +24 -0
  303. package/src/presentation/ui/legacy-birth-date-input.tsx +43 -0
  304. package/src/presentation/ui/legacy-color-picker/index.tsx +42 -0
  305. package/src/presentation/ui/legacy-color-picker/legacy-color-picker.content.tsx +37 -0
  306. package/src/presentation/ui/legacy-color-picker/legacy-color-picker.context.tsx +42 -0
  307. package/src/presentation/ui/legacy-color-picker/legacy-color-picker.hex-input.tsx +97 -0
  308. package/src/presentation/ui/legacy-color-picker/legacy-color-picker.picker.tsx +266 -0
  309. package/src/presentation/ui/legacy-color-picker/legacy-color-picker.presets.ts +22 -0
  310. package/src/presentation/ui/legacy-color-picker/legacy-color-picker.quick-list.tsx +49 -0
  311. package/src/presentation/ui/legacy-color-picker/legacy-color-picker.recent.tsx +43 -0
  312. package/src/presentation/ui/legacy-color-picker/legacy-color-picker.swatches.tsx +111 -0
  313. package/src/presentation/ui/legacy-color-picker/legacy-color-picker.trigger.tsx +128 -0
  314. package/src/presentation/ui/legacy-color-picker/legacy-color-picker.tsx +110 -0
  315. package/src/presentation/ui/legacy-color-picker/legacy-color-picker.types.ts +1 -0
  316. package/src/presentation/ui/legacy-color-picker/legacy-color-picker.utils.ts +114 -0
  317. package/src/presentation/ui/legacy-country-input.tsx +171 -0
  318. package/src/presentation/ui/legacy-gender-input.tsx +22 -0
  319. package/src/presentation/ui/legacy-input.tsx +106 -0
  320. package/src/presentation/ui/legacy-phone-input.tsx +213 -0
  321. package/src/presentation/ui/legacy-select-input.tsx +114 -0
  322. package/src/presentation/ui/legacy-text-area.tsx +111 -0
  323. package/src/presentation/ui/list-items.tsx +59 -0
  324. package/src/presentation/ui/marker.tsx +69 -0
  325. package/src/presentation/ui/media-player/index.tsx +12 -0
  326. package/src/presentation/ui/media-player/media-player.context.tsx +36 -0
  327. package/src/presentation/ui/media-player/media-player.tsx +167 -0
  328. package/src/presentation/ui/media-player/player-controls.tsx +207 -0
  329. package/src/presentation/ui/media-player/players/audio-player.tsx +78 -0
  330. package/src/presentation/ui/media-player/players/index.tsx +4 -0
  331. package/src/presentation/ui/media-player/players/video-player.tsx +193 -0
  332. package/src/presentation/ui/media-player/players/voice-note-player.tsx +108 -0
  333. package/src/presentation/ui/media-player/use-media-player.hook.ts +263 -0
  334. package/src/presentation/ui/menubar.tsx +281 -0
  335. package/src/presentation/ui/message.tsx +92 -0
  336. package/src/presentation/ui/navigation-menu.tsx +172 -0
  337. package/src/presentation/ui/pagination.tsx +129 -0
  338. package/src/presentation/ui/popover.tsx +89 -0
  339. package/src/presentation/ui/progress.tsx +31 -0
  340. package/src/presentation/ui/resizable.tsx +50 -0
  341. package/src/presentation/ui/select.tsx +192 -0
  342. package/src/presentation/ui/separator.tsx +28 -0
  343. package/src/presentation/ui/sheet.tsx +147 -0
  344. package/src/presentation/ui/sidebar.tsx +702 -0
  345. package/src/presentation/ui/skeleton.tsx +13 -0
  346. package/src/presentation/ui/slide-to-confirm.tsx +129 -0
  347. package/src/presentation/ui/slider.tsx +59 -0
  348. package/src/presentation/ui/sonner.tsx +58 -0
  349. package/src/presentation/ui/switch.tsx +33 -0
  350. package/src/presentation/ui/table.tsx +116 -0
  351. package/src/presentation/ui/tabs.tsx +90 -0
  352. package/src/presentation/ui/text-gradient.tsx +84 -0
  353. package/src/presentation/ui/textarea.tsx +18 -0
  354. package/src/presentation/ui/timeline-steps.tsx +235 -0
  355. package/src/presentation/ui/toggle-group.tsx +89 -0
  356. package/src/presentation/ui/toggle.tsx +47 -0
  357. package/src/presentation/ui/tooltip.tsx +57 -0
  358. package/src/presentation/uploading/index.tsx +3 -0
  359. package/src/presentation/uploading/media-upload-field.tsx +152 -0
  360. package/src/presentation/uploading/storage-media.tsx +210 -0
  361. package/src/styles.css +403 -0
  362. package/src/themes.css +1038 -0
@@ -0,0 +1,814 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import {
5
+ closestCenter,
6
+ DndContext,
7
+ KeyboardSensor,
8
+ MouseSensor,
9
+ TouchSensor,
10
+ useSensor,
11
+ useSensors,
12
+ type DragEndEvent,
13
+ type UniqueIdentifier,
14
+ } from "@dnd-kit/core"
15
+ import { restrictToVerticalAxis } from "@dnd-kit/modifiers"
16
+ import {
17
+ arrayMove,
18
+ SortableContext,
19
+ useSortable,
20
+ verticalListSortingStrategy,
21
+ } from "@dnd-kit/sortable"
22
+ import { CSS } from "@dnd-kit/utilities"
23
+ import {
24
+ flexRender,
25
+ getCoreRowModel,
26
+ getFacetedRowModel,
27
+ getFacetedUniqueValues,
28
+ getFilteredRowModel,
29
+ getPaginationRowModel,
30
+ getSortedRowModel,
31
+ useReactTable,
32
+ type ColumnDef,
33
+ type ColumnFiltersState,
34
+ type Row,
35
+ type SortingState,
36
+ type VisibilityState,
37
+ } from "@tanstack/react-table"
38
+ import { Area, AreaChart, CartesianGrid, XAxis } from "recharts"
39
+ import { toast } from "sonner"
40
+ import { z } from "zod"
41
+
42
+ import { useIsMobile } from "../../infrastructure/hooks/use-mobile"
43
+ import { Badge } from "../ui/badge"
44
+ import { Button } from "../ui/button"
45
+ import {
46
+ ChartContainer,
47
+ ChartTooltip,
48
+ ChartTooltipContent,
49
+ type ChartConfig,
50
+ } from "../ui/chart"
51
+ import { Checkbox } from "../ui/checkbox"
52
+ import {
53
+ Drawer,
54
+ DrawerClose,
55
+ DrawerContent,
56
+ DrawerDescription,
57
+ DrawerFooter,
58
+ DrawerHeader,
59
+ DrawerTitle,
60
+ DrawerTrigger,
61
+ } from "../ui/drawer"
62
+ import {
63
+ DropdownMenu,
64
+ DropdownMenuCheckboxItem,
65
+ DropdownMenuContent,
66
+ DropdownMenuItem,
67
+ DropdownMenuSeparator,
68
+ DropdownMenuTrigger,
69
+ } from "../ui/dropdown-menu"
70
+ import { Input } from "../ui/input"
71
+ import { Label } from "../ui/label"
72
+ import {
73
+ Select,
74
+ SelectContent,
75
+ SelectGroup,
76
+ SelectItem,
77
+ SelectTrigger,
78
+ SelectValue,
79
+ } from "../ui/select"
80
+ import { Separator } from "../ui/separator"
81
+ import {
82
+ Table,
83
+ TableBody,
84
+ TableCell,
85
+ TableHead,
86
+ TableHeader,
87
+ TableRow,
88
+ } from "../ui/table"
89
+ import {
90
+ Tabs,
91
+ TabsContent,
92
+ TabsList,
93
+ TabsTrigger,
94
+ } from "../ui/tabs"
95
+ import { GripVerticalIcon, CircleCheckIcon, LoaderIcon, EllipsisVerticalIcon, Columns3Icon, ChevronDownIcon, PlusIcon, ChevronsLeftIcon, ChevronLeftIcon, ChevronRightIcon, ChevronsRightIcon, TrendingUpIcon } from "lucide-react"
96
+ import {DataGridEmpty} from "../data-grid/data-grid-empty";
97
+
98
+ export const schema = z.object({
99
+ id: z.number(),
100
+ header: z.string(),
101
+ type: z.string(),
102
+ status: z.string(),
103
+ target: z.string(),
104
+ limit: z.string(),
105
+ reviewer: z.string(),
106
+ })
107
+
108
+ // Create a separate component for the drag handle
109
+ function DragHandle({ id }: { id: number }) {
110
+ const { attributes, listeners } = useSortable({
111
+ id,
112
+ })
113
+
114
+ return (
115
+ <Button
116
+ {...attributes}
117
+ {...listeners}
118
+ variant="ghost"
119
+ size="icon"
120
+ className="size-7 text-muted-foreground hover:bg-transparent"
121
+ >
122
+ <GripVerticalIcon className="size-3 text-muted-foreground" />
123
+ <span className="sr-only">Drag to reorder</span>
124
+ </Button>
125
+ )
126
+ }
127
+
128
+ const columns: ColumnDef<z.infer<typeof schema>>[] = [
129
+ {
130
+ id: "drag",
131
+ header: () => null,
132
+ cell: ({ row }) => <DragHandle id={row.original.id} />,
133
+ },
134
+ {
135
+ id: "select",
136
+ header: ({ table }) => (
137
+ <div className="flex items-center justify-center">
138
+ <Checkbox
139
+ checked={
140
+ table.getIsAllPageRowsSelected() ||
141
+ (table.getIsSomePageRowsSelected() && "indeterminate")
142
+ }
143
+ onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}
144
+ aria-label="Select all"
145
+ />
146
+ </div>
147
+ ),
148
+ cell: ({ row }) => (
149
+ <div className="flex items-center justify-center">
150
+ <Checkbox
151
+ checked={row.getIsSelected()}
152
+ onCheckedChange={(value) => row.toggleSelected(!!value)}
153
+ aria-label="Select row"
154
+ />
155
+ </div>
156
+ ),
157
+ enableSorting: false,
158
+ enableHiding: false,
159
+ },
160
+ {
161
+ accessorKey: "header",
162
+ header: "Header",
163
+ cell: ({ row }) => {
164
+ return <TableCellViewer item={row.original} />
165
+ },
166
+ enableHiding: false,
167
+ },
168
+ {
169
+ accessorKey: "type",
170
+ header: "Section Type",
171
+ cell: ({ row }) => (
172
+ <div className="w-32">
173
+ <Badge variant="outline" className="px-1.5 text-muted-foreground">
174
+ {row.original.type}
175
+ </Badge>
176
+ </div>
177
+ ),
178
+ },
179
+ {
180
+ accessorKey: "status",
181
+ header: "Status",
182
+ cell: ({ row }) => (
183
+ <Badge variant="outline" className="px-1.5 text-muted-foreground">
184
+ {row.original.status === "Done" ? (
185
+ <CircleCheckIcon className="fill-green-500 dark:fill-green-400" />
186
+ ) : (
187
+ <LoaderIcon
188
+ />
189
+ )}
190
+ {row.original.status}
191
+ </Badge>
192
+ ),
193
+ },
194
+ {
195
+ accessorKey: "target",
196
+ header: () => <div className="w-full text-right">Target</div>,
197
+ cell: ({ row }) => (
198
+ <form
199
+ onSubmit={(e) => {
200
+ e.preventDefault()
201
+ toast.promise(new Promise((resolve) => setTimeout(resolve, 1000)), {
202
+ loading: `Saving ${row.original.header}`,
203
+ success: "Done",
204
+ error: "Error",
205
+ })
206
+ }}
207
+ >
208
+ <Label htmlFor={`${row.original.id}-target`} className="sr-only">
209
+ Target
210
+ </Label>
211
+ <Input
212
+ className="h-8 w-16 border-transparent bg-transparent text-right shadow-none hover:bg-input/30 focus-visible:border focus-visible:bg-background dark:bg-transparent dark:hover:bg-input/30 dark:focus-visible:bg-input/30"
213
+ defaultValue={row.original.target}
214
+ id={`${row.original.id}-target`}
215
+ />
216
+ </form>
217
+ ),
218
+ },
219
+ {
220
+ accessorKey: "limit",
221
+ header: () => <div className="w-full text-right">Limit</div>,
222
+ cell: ({ row }) => (
223
+ <form
224
+ onSubmit={(e) => {
225
+ e.preventDefault()
226
+ toast.promise(new Promise((resolve) => setTimeout(resolve, 1000)), {
227
+ loading: `Saving ${row.original.header}`,
228
+ success: "Done",
229
+ error: "Error",
230
+ })
231
+ }}
232
+ >
233
+ <Label htmlFor={`${row.original.id}-limit`} className="sr-only">
234
+ Limit
235
+ </Label>
236
+ <Input
237
+ className="h-8 w-16 border-transparent bg-transparent text-right shadow-none hover:bg-input/30 focus-visible:border focus-visible:bg-background dark:bg-transparent dark:hover:bg-input/30 dark:focus-visible:bg-input/30"
238
+ defaultValue={row.original.limit}
239
+ id={`${row.original.id}-limit`}
240
+ />
241
+ </form>
242
+ ),
243
+ },
244
+ {
245
+ accessorKey: "reviewer",
246
+ header: "Reviewer",
247
+ cell: ({ row }) => {
248
+ const isAssigned = row.original.reviewer !== "Assign reviewer"
249
+
250
+ if (isAssigned) {
251
+ return row.original.reviewer
252
+ }
253
+
254
+ return (
255
+ <>
256
+ <Label htmlFor={`${row.original.id}-reviewer`} className="sr-only">
257
+ Reviewer
258
+ </Label>
259
+ <Select>
260
+ <SelectTrigger
261
+ className="w-38 **:data-[slot=select-value]:block **:data-[slot=select-value]:truncate"
262
+ size="sm"
263
+ id={`${row.original.id}-reviewer`}
264
+ >
265
+ <SelectValue placeholder="Assign reviewer" />
266
+ </SelectTrigger>
267
+ <SelectContent align="end">
268
+ <SelectGroup>
269
+ <SelectItem value="Eddie Lake">Eddie Lake</SelectItem>
270
+ <SelectItem value="Jamik Tashpulatov">
271
+ Jamik Tashpulatov
272
+ </SelectItem>
273
+ </SelectGroup>
274
+ </SelectContent>
275
+ </Select>
276
+ </>
277
+ )
278
+ },
279
+ },
280
+ {
281
+ id: "actions",
282
+ cell: () => (
283
+ <DropdownMenu>
284
+ <DropdownMenuTrigger asChild>
285
+ <Button
286
+ variant="ghost"
287
+ className="flex size-8 text-muted-foreground data-[state=open]:bg-muted"
288
+ size="icon"
289
+ >
290
+ <EllipsisVerticalIcon
291
+ />
292
+ <span className="sr-only">Open menu</span>
293
+ </Button>
294
+ </DropdownMenuTrigger>
295
+ <DropdownMenuContent align="end" className="w-32">
296
+ <DropdownMenuItem>Edit</DropdownMenuItem>
297
+ <DropdownMenuItem>Make a copy</DropdownMenuItem>
298
+ <DropdownMenuItem>Favorite</DropdownMenuItem>
299
+ <DropdownMenuSeparator />
300
+ <DropdownMenuItem variant="destructive">Delete</DropdownMenuItem>
301
+ </DropdownMenuContent>
302
+ </DropdownMenu>
303
+ ),
304
+ },
305
+ ]
306
+
307
+ function DraggableRow({ row }: { row: Row<z.infer<typeof schema>> }) {
308
+ const { transform, transition, setNodeRef, isDragging } = useSortable({
309
+ id: row.original.id,
310
+ })
311
+
312
+ return (
313
+ <TableRow
314
+ data-state={row.getIsSelected() && "selected"}
315
+ data-dragging={isDragging}
316
+ ref={setNodeRef}
317
+ className="relative z-0 data-[dragging=true]:z-10 data-[dragging=true]:opacity-80"
318
+ style={{
319
+ transform: CSS.Transform.toString(transform),
320
+ transition: transition,
321
+ }}
322
+ >
323
+ {row.getVisibleCells().map((cell) => (
324
+ <TableCell key={cell.id}>
325
+ {flexRender(cell.column.columnDef.cell, cell.getContext())}
326
+ </TableCell>
327
+ ))}
328
+ </TableRow>
329
+ )
330
+ }
331
+
332
+ export function DataTable({
333
+ data: initialData,
334
+ }: {
335
+ data: z.infer<typeof schema>[]
336
+ }) {
337
+ const [data, setData] = React.useState(() => initialData)
338
+ const [rowSelection, setRowSelection] = React.useState({})
339
+ const [columnVisibility, setColumnVisibility] =
340
+ React.useState<VisibilityState>({})
341
+ const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
342
+ []
343
+ )
344
+ const [sorting, setSorting] = React.useState<SortingState>([])
345
+ const [pagination, setPagination] = React.useState({
346
+ pageIndex: 0,
347
+ pageSize: 10,
348
+ })
349
+ const sortableId = React.useId()
350
+ const sensors = useSensors(
351
+ useSensor(MouseSensor, {}),
352
+ useSensor(TouchSensor, {}),
353
+ useSensor(KeyboardSensor, {})
354
+ )
355
+
356
+ const dataIds = React.useMemo<UniqueIdentifier[]>(
357
+ () => data?.map(({ id }) => id) || [],
358
+ [data]
359
+ )
360
+
361
+ const table = useReactTable({
362
+ data,
363
+ columns,
364
+ state: {
365
+ sorting,
366
+ columnVisibility,
367
+ rowSelection,
368
+ columnFilters,
369
+ pagination,
370
+ },
371
+ getRowId: (row) => row.id.toString(),
372
+ enableRowSelection: true,
373
+ onRowSelectionChange: setRowSelection,
374
+ onSortingChange: setSorting,
375
+ onColumnFiltersChange: setColumnFilters,
376
+ onColumnVisibilityChange: setColumnVisibility,
377
+ onPaginationChange: setPagination,
378
+ getCoreRowModel: getCoreRowModel(),
379
+ getFilteredRowModel: getFilteredRowModel(),
380
+ getPaginationRowModel: getPaginationRowModel(),
381
+ getSortedRowModel: getSortedRowModel(),
382
+ getFacetedRowModel: getFacetedRowModel(),
383
+ getFacetedUniqueValues: getFacetedUniqueValues(),
384
+ })
385
+
386
+ function handleDragEnd(event: DragEndEvent) {
387
+ const { active, over } = event
388
+ if (active && over && active.id !== over.id) {
389
+ setData((data) => {
390
+ const oldIndex = dataIds.indexOf(active.id)
391
+ const newIndex = dataIds.indexOf(over.id)
392
+ return arrayMove(data, oldIndex, newIndex)
393
+ })
394
+ }
395
+ }
396
+
397
+ return (
398
+ <Tabs
399
+ defaultValue="outline"
400
+ className="w-full flex-col justify-start gap-6"
401
+ >
402
+ <div className="flex items-center justify-between px-4 lg:px-6">
403
+ <Label htmlFor="view-selector" className="sr-only">
404
+ View
405
+ </Label>
406
+ <Select defaultValue="outline">
407
+ <SelectTrigger
408
+ className="flex w-fit @4xl/main:hidden"
409
+ size="sm"
410
+ id="view-selector"
411
+ >
412
+ <SelectValue placeholder="Select a view" />
413
+ </SelectTrigger>
414
+ <SelectContent>
415
+ <SelectGroup>
416
+ <SelectItem value="outline">Outline</SelectItem>
417
+ <SelectItem value="past-performance">Past Performance</SelectItem>
418
+ <SelectItem value="key-personnel">Key Personnel</SelectItem>
419
+ <SelectItem value="focus-documents">Focus Documents</SelectItem>
420
+ </SelectGroup>
421
+ </SelectContent>
422
+ </Select>
423
+ <TabsList className="hidden **:data-[slot=badge]:size-5 **:data-[slot=badge]:rounded-full **:data-[slot=badge]:bg-muted-foreground/30 **:data-[slot=badge]:px-1 @4xl/main:flex">
424
+ <TabsTrigger value="outline">Outline</TabsTrigger>
425
+ <TabsTrigger value="past-performance">
426
+ Past Performance <Badge variant="secondary">3</Badge>
427
+ </TabsTrigger>
428
+ <TabsTrigger value="key-personnel">
429
+ Key Personnel <Badge variant="secondary">2</Badge>
430
+ </TabsTrigger>
431
+ <TabsTrigger value="focus-documents">Focus Documents</TabsTrigger>
432
+ </TabsList>
433
+ <div className="flex items-center gap-2">
434
+ <DropdownMenu>
435
+ <DropdownMenuTrigger asChild>
436
+ <Button variant="outline" size="sm">
437
+ <Columns3Icon data-icon="inline-start" />
438
+ Columns
439
+ <ChevronDownIcon data-icon="inline-end" />
440
+ </Button>
441
+ </DropdownMenuTrigger>
442
+ <DropdownMenuContent align="end" className="w-32">
443
+ {table
444
+ .getAllColumns()
445
+ .filter(
446
+ (column) =>
447
+ typeof column.accessorFn !== "undefined" &&
448
+ column.getCanHide()
449
+ )
450
+ .map((column) => {
451
+ return (
452
+ <DropdownMenuCheckboxItem
453
+ key={column.id}
454
+ className="capitalize"
455
+ checked={column.getIsVisible()}
456
+ onCheckedChange={(value) =>
457
+ column.toggleVisibility(!!value)
458
+ }
459
+ >
460
+ {column.id}
461
+ </DropdownMenuCheckboxItem>
462
+ )
463
+ })}
464
+ </DropdownMenuContent>
465
+ </DropdownMenu>
466
+ <Button variant="outline" size="sm">
467
+ <PlusIcon
468
+ />
469
+ <span className="hidden lg:inline">Add Section</span>
470
+ </Button>
471
+ </div>
472
+ </div>
473
+ <TabsContent
474
+ value="outline"
475
+ className="relative flex flex-col gap-4 overflow-auto px-4 lg:px-6"
476
+ >
477
+ <div className="overflow-hidden rounded-lg border">
478
+ <DndContext
479
+ collisionDetection={closestCenter}
480
+ modifiers={[restrictToVerticalAxis]}
481
+ onDragEnd={handleDragEnd}
482
+ sensors={sensors}
483
+ id={sortableId}
484
+ >
485
+ <Table>
486
+ <TableHeader className="sticky top-0 z-10 bg-muted">
487
+ {table.getHeaderGroups().map((headerGroup) => (
488
+ <TableRow key={headerGroup.id}>
489
+ {headerGroup.headers.map((header) => {
490
+ return (
491
+ <TableHead key={header.id} colSpan={header.colSpan}>
492
+ {header.isPlaceholder
493
+ ? null
494
+ : flexRender(
495
+ header.column.columnDef.header,
496
+ header.getContext()
497
+ )}
498
+ </TableHead>
499
+ )
500
+ })}
501
+ </TableRow>
502
+ ))}
503
+ </TableHeader>
504
+ <TableBody className="**:data-[slot=table-cell]:first:w-8">
505
+ {table.getRowModel().rows?.length ? (
506
+ <SortableContext
507
+ items={dataIds}
508
+ strategy={verticalListSortingStrategy}
509
+ >
510
+ {table.getRowModel().rows.map((row) => (
511
+ <DraggableRow key={row.id} row={row} />
512
+ ))}
513
+ </SortableContext>
514
+ ) : (
515
+ <TableRow>
516
+ <TableCell
517
+ colSpan={columns.length}
518
+ className="h-24 text-center"
519
+ >
520
+ <DataGridEmpty/>
521
+ </TableCell>
522
+ </TableRow>
523
+ )}
524
+ </TableBody>
525
+ </Table>
526
+ </DndContext>
527
+ </div>
528
+ <div className="flex items-center justify-between px-4">
529
+ <div className="hidden flex-1 text-sm text-muted-foreground lg:flex">
530
+ {table.getFilteredSelectedRowModel().rows.length} of{" "}
531
+ {table.getFilteredRowModel().rows.length} row(s) selected.
532
+ </div>
533
+ <div className="flex w-full items-center gap-8 lg:w-fit">
534
+ <div className="hidden items-center gap-2 lg:flex">
535
+ <Label htmlFor="rows-per-page" className="text-sm font-medium">
536
+ Rows per page
537
+ </Label>
538
+ <Select
539
+ value={`${table.getState().pagination.pageSize}`}
540
+ onValueChange={(value) => {
541
+ table.setPageSize(Number(value))
542
+ }}
543
+ >
544
+ <SelectTrigger size="sm" className="w-20" id="rows-per-page">
545
+ <SelectValue
546
+ placeholder={table.getState().pagination.pageSize}
547
+ />
548
+ </SelectTrigger>
549
+ <SelectContent side="top">
550
+ <SelectGroup>
551
+ {[10, 20, 30, 40, 50].map((pageSize) => (
552
+ <SelectItem key={pageSize} value={`${pageSize}`}>
553
+ {pageSize}
554
+ </SelectItem>
555
+ ))}
556
+ </SelectGroup>
557
+ </SelectContent>
558
+ </Select>
559
+ </div>
560
+ <div className="flex w-fit items-center justify-center text-sm font-medium">
561
+ Page {table.getState().pagination.pageIndex + 1} of{" "}
562
+ {table.getPageCount()}
563
+ </div>
564
+ <div className="ml-auto flex items-center gap-2 lg:ml-0">
565
+ <Button
566
+ variant="outline"
567
+ className="hidden h-8 w-8 p-0 lg:flex"
568
+ onClick={() => table.setPageIndex(0)}
569
+ disabled={!table.getCanPreviousPage()}
570
+ >
571
+ <span className="sr-only">Go to first page</span>
572
+ <ChevronsLeftIcon
573
+ />
574
+ </Button>
575
+ <Button
576
+ variant="outline"
577
+ className="size-8"
578
+ size="icon"
579
+ onClick={() => table.previousPage()}
580
+ disabled={!table.getCanPreviousPage()}
581
+ >
582
+ <span className="sr-only">Go to previous page</span>
583
+ <ChevronLeftIcon
584
+ />
585
+ </Button>
586
+ <Button
587
+ variant="outline"
588
+ className="size-8"
589
+ size="icon"
590
+ onClick={() => table.nextPage()}
591
+ disabled={!table.getCanNextPage()}
592
+ >
593
+ <span className="sr-only">Go to next page</span>
594
+ <ChevronRightIcon
595
+ />
596
+ </Button>
597
+ <Button
598
+ variant="outline"
599
+ className="hidden size-8 lg:flex"
600
+ size="icon"
601
+ onClick={() => table.setPageIndex(table.getPageCount() - 1)}
602
+ disabled={!table.getCanNextPage()}
603
+ >
604
+ <span className="sr-only">Go to last page</span>
605
+ <ChevronsRightIcon
606
+ />
607
+ </Button>
608
+ </div>
609
+ </div>
610
+ </div>
611
+ </TabsContent>
612
+ <TabsContent
613
+ value="past-performance"
614
+ className="flex flex-col px-4 lg:px-6"
615
+ >
616
+ <div className="aspect-video w-full flex-1 rounded-lg border border-dashed"></div>
617
+ </TabsContent>
618
+ <TabsContent value="key-personnel" className="flex flex-col px-4 lg:px-6">
619
+ <div className="aspect-video w-full flex-1 rounded-lg border border-dashed"></div>
620
+ </TabsContent>
621
+ <TabsContent
622
+ value="focus-documents"
623
+ className="flex flex-col px-4 lg:px-6"
624
+ >
625
+ <div className="aspect-video w-full flex-1 rounded-lg border border-dashed"></div>
626
+ </TabsContent>
627
+ </Tabs>
628
+ )
629
+ }
630
+
631
+ const chartData = [
632
+ { month: "January", desktop: 186, mobile: 80 },
633
+ { month: "February", desktop: 305, mobile: 200 },
634
+ { month: "March", desktop: 237, mobile: 120 },
635
+ { month: "April", desktop: 73, mobile: 190 },
636
+ { month: "May", desktop: 209, mobile: 130 },
637
+ { month: "June", desktop: 214, mobile: 140 },
638
+ ]
639
+
640
+ const chartConfig = {
641
+ desktop: {
642
+ label: "Desktop",
643
+ color: "var(--primary)",
644
+ },
645
+ mobile: {
646
+ label: "Mobile",
647
+ color: "var(--primary)",
648
+ },
649
+ } satisfies ChartConfig
650
+
651
+ function TableCellViewer({ item }: { item: z.infer<typeof schema> }) {
652
+ const isMobile = useIsMobile()
653
+
654
+ return (
655
+ <Drawer direction={isMobile ? "bottom" : "right"}>
656
+ <DrawerTrigger asChild>
657
+ <Button variant="link" className="w-fit px-0 text-left text-foreground">
658
+ {item.header}
659
+ </Button>
660
+ </DrawerTrigger>
661
+ <DrawerContent>
662
+ <DrawerHeader className="gap-1">
663
+ <DrawerTitle>{item.header}</DrawerTitle>
664
+ <DrawerDescription>
665
+ Showing total visitors for the last 6 months
666
+ </DrawerDescription>
667
+ </DrawerHeader>
668
+ <div className="flex flex-col gap-4 overflow-y-auto px-4 text-sm">
669
+ {!isMobile && (
670
+ <>
671
+ <ChartContainer config={chartConfig}>
672
+ <AreaChart
673
+ accessibilityLayer
674
+ data={chartData}
675
+ margin={{
676
+ left: 0,
677
+ right: 10,
678
+ }}
679
+ >
680
+ <CartesianGrid vertical={false} />
681
+ <XAxis
682
+ dataKey="month"
683
+ tickLine={false}
684
+ axisLine={false}
685
+ tickMargin={8}
686
+ tickFormatter={(value) => value.slice(0, 3)}
687
+ hide
688
+ />
689
+ <ChartTooltip
690
+ cursor={false}
691
+ content={<ChartTooltipContent indicator="dot" />}
692
+ />
693
+ <Area
694
+ dataKey="mobile"
695
+ type="natural"
696
+ fill="var(--color-mobile)"
697
+ fillOpacity={0.6}
698
+ stroke="var(--color-mobile)"
699
+ stackId="a"
700
+ />
701
+ <Area
702
+ dataKey="desktop"
703
+ type="natural"
704
+ fill="var(--color-desktop)"
705
+ fillOpacity={0.4}
706
+ stroke="var(--color-desktop)"
707
+ stackId="a"
708
+ />
709
+ </AreaChart>
710
+ </ChartContainer>
711
+ <Separator />
712
+ <div className="grid gap-2">
713
+ <div className="flex gap-2 leading-none font-medium">
714
+ Trending up by 5.2% this month{" "}
715
+ <TrendingUpIcon className="size-4" />
716
+ </div>
717
+ <div className="text-muted-foreground">
718
+ Showing total visitors for the last 6 months. This is just
719
+ some random text to test the layout. It spans multiple lines
720
+ and should wrap around.
721
+ </div>
722
+ </div>
723
+ <Separator />
724
+ </>
725
+ )}
726
+ <form className="flex flex-col gap-4">
727
+ <div className="flex flex-col gap-3">
728
+ <Label htmlFor="header">Header</Label>
729
+ <Input id="header" defaultValue={item.header} />
730
+ </div>
731
+ <div className="grid grid-cols-2 gap-4">
732
+ <div className="flex flex-col gap-3">
733
+ <Label htmlFor="type">Type</Label>
734
+ <Select defaultValue={item.type}>
735
+ <SelectTrigger id="type" className="w-full">
736
+ <SelectValue placeholder="Select a type" />
737
+ </SelectTrigger>
738
+ <SelectContent>
739
+ <SelectGroup>
740
+ <SelectItem value="Table of Contents">
741
+ Table of Contents
742
+ </SelectItem>
743
+ <SelectItem value="Executive Summary">
744
+ Executive Summary
745
+ </SelectItem>
746
+ <SelectItem value="Technical Approach">
747
+ Technical Approach
748
+ </SelectItem>
749
+ <SelectItem value="Design">Design</SelectItem>
750
+ <SelectItem value="Capabilities">Capabilities</SelectItem>
751
+ <SelectItem value="Focus Documents">
752
+ Focus Documents
753
+ </SelectItem>
754
+ <SelectItem value="Narrative">Narrative</SelectItem>
755
+ <SelectItem value="Cover Page">Cover Page</SelectItem>
756
+ </SelectGroup>
757
+ </SelectContent>
758
+ </Select>
759
+ </div>
760
+ <div className="flex flex-col gap-3">
761
+ <Label htmlFor="status">Status</Label>
762
+ <Select defaultValue={item.status}>
763
+ <SelectTrigger id="status" className="w-full">
764
+ <SelectValue placeholder="Select a status" />
765
+ </SelectTrigger>
766
+ <SelectContent>
767
+ <SelectGroup>
768
+ <SelectItem value="Done">Done</SelectItem>
769
+ <SelectItem value="In Progress">In Progress</SelectItem>
770
+ <SelectItem value="Not Started">Not Started</SelectItem>
771
+ </SelectGroup>
772
+ </SelectContent>
773
+ </Select>
774
+ </div>
775
+ </div>
776
+ <div className="grid grid-cols-2 gap-4">
777
+ <div className="flex flex-col gap-3">
778
+ <Label htmlFor="target">Target</Label>
779
+ <Input id="target" defaultValue={item.target} />
780
+ </div>
781
+ <div className="flex flex-col gap-3">
782
+ <Label htmlFor="limit">Limit</Label>
783
+ <Input id="limit" defaultValue={item.limit} />
784
+ </div>
785
+ </div>
786
+ <div className="flex flex-col gap-3">
787
+ <Label htmlFor="reviewer">Reviewer</Label>
788
+ <Select defaultValue={item.reviewer}>
789
+ <SelectTrigger id="reviewer" className="w-full">
790
+ <SelectValue placeholder="Select a reviewer" />
791
+ </SelectTrigger>
792
+ <SelectContent>
793
+ <SelectGroup>
794
+ <SelectItem value="Eddie Lake">Eddie Lake</SelectItem>
795
+ <SelectItem value="Jamik Tashpulatov">
796
+ Jamik Tashpulatov
797
+ </SelectItem>
798
+ <SelectItem value="Emily Whalen">Emily Whalen</SelectItem>
799
+ </SelectGroup>
800
+ </SelectContent>
801
+ </Select>
802
+ </div>
803
+ </form>
804
+ </div>
805
+ <DrawerFooter>
806
+ <Button>Submit</Button>
807
+ <DrawerClose asChild>
808
+ <Button variant="outline">Done</Button>
809
+ </DrawerClose>
810
+ </DrawerFooter>
811
+ </DrawerContent>
812
+ </Drawer>
813
+ )
814
+ }