@maxal_studio/kratosjs-react 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (529) hide show
  1. package/README.md +44 -0
  2. package/dist/FieldRenderer.d.ts +13 -0
  3. package/dist/FieldRenderer.js +62 -0
  4. package/dist/FormRenderer.d.ts +7 -0
  5. package/dist/FormRenderer.js +78 -0
  6. package/dist/TableRenderer.d.ts +2 -0
  7. package/dist/TableRenderer.js +1 -0
  8. package/dist/api/actionsApi.d.ts +23 -0
  9. package/dist/api/actionsApi.js +46 -0
  10. package/dist/api/authenticatedFetch.d.ts +8 -0
  11. package/dist/api/authenticatedFetch.js +31 -0
  12. package/dist/api/exportApi.d.ts +18 -0
  13. package/dist/api/exportApi.js +50 -0
  14. package/dist/api/http.d.ts +24 -0
  15. package/dist/api/http.js +52 -0
  16. package/dist/api/resourceApi.d.ts +37 -0
  17. package/dist/api/resourceApi.js +52 -0
  18. package/dist/api/tableApi.d.ts +83 -0
  19. package/dist/api/tableApi.js +51 -0
  20. package/dist/api/urls.d.ts +19 -0
  21. package/dist/api/urls.js +46 -0
  22. package/dist/app.d.ts +101 -0
  23. package/dist/app.js +89 -0
  24. package/dist/auth/AuthContext.d.ts +22 -0
  25. package/dist/auth/AuthContext.js +147 -0
  26. package/dist/auth/LoginPage.d.ts +10 -0
  27. package/dist/auth/LoginPage.js +179 -0
  28. package/dist/auth/ProtectedRoute.d.ts +12 -0
  29. package/dist/auth/ProtectedRoute.js +22 -0
  30. package/dist/auth/authApiClient.d.ts +24 -0
  31. package/dist/auth/authApiClient.js +95 -0
  32. package/dist/auth/types.d.ts +103 -0
  33. package/dist/auth/types.js +1 -0
  34. package/dist/components/ActionFormModal.d.ts +22 -0
  35. package/dist/components/ActionFormModal.js +8 -0
  36. package/dist/components/AdminPanel.d.ts +11 -0
  37. package/dist/components/AdminPanel.js +194 -0
  38. package/dist/components/Checkbox.d.ts +10 -0
  39. package/dist/components/Checkbox.js +8 -0
  40. package/dist/components/CheckboxField.d.ts +7 -0
  41. package/dist/components/CheckboxField.js +26 -0
  42. package/dist/components/ColorPickerField.d.ts +7 -0
  43. package/dist/components/ColorPickerField.js +26 -0
  44. package/dist/components/DateTimePickerField.d.ts +7 -0
  45. package/dist/components/DateTimePickerField.js +64 -0
  46. package/dist/components/FileUploadField.d.ts +9 -0
  47. package/dist/components/FileUploadField.js +478 -0
  48. package/dist/components/GlobalSearch.d.ts +22 -0
  49. package/dist/components/GlobalSearch.js +181 -0
  50. package/dist/components/GroupField.d.ts +7 -0
  51. package/dist/components/GroupField.js +23 -0
  52. package/dist/components/HiddenField.d.ts +3 -0
  53. package/dist/components/HiddenField.js +10 -0
  54. package/dist/components/ModalBreadcrumb.d.ts +5 -0
  55. package/dist/components/ModalBreadcrumb.js +33 -0
  56. package/dist/components/ModalDrawer.d.ts +15 -0
  57. package/dist/components/ModalDrawer.js +40 -0
  58. package/dist/components/RadioField.d.ts +7 -0
  59. package/dist/components/RadioField.js +26 -0
  60. package/dist/components/RepeaterField.d.ts +3 -0
  61. package/dist/components/RepeaterField.js +191 -0
  62. package/dist/components/ResourceModalRenderer.d.ts +10 -0
  63. package/dist/components/ResourceModalRenderer.js +80 -0
  64. package/dist/components/RichEditorField.d.ts +3 -0
  65. package/dist/components/RichEditorField.js +655 -0
  66. package/dist/components/SectionField.d.ts +9 -0
  67. package/dist/components/SectionField.js +111 -0
  68. package/dist/components/SelectField.d.ts +8 -0
  69. package/dist/components/SelectField.js +523 -0
  70. package/dist/components/TabsField.d.ts +10 -0
  71. package/dist/components/TabsField.js +214 -0
  72. package/dist/components/TagsInputField.d.ts +7 -0
  73. package/dist/components/TagsInputField.js +172 -0
  74. package/dist/components/TextInputField.d.ts +7 -0
  75. package/dist/components/TextInputField.js +44 -0
  76. package/dist/components/TextareaField.d.ts +7 -0
  77. package/dist/components/TextareaField.js +31 -0
  78. package/dist/components/ToggleField.d.ts +7 -0
  79. package/dist/components/ToggleField.js +57 -0
  80. package/dist/components/ViewModal.d.ts +25 -0
  81. package/dist/components/ViewModal.js +159 -0
  82. package/dist/components/blocks/BlockRenderer.d.ts +7 -0
  83. package/dist/components/blocks/BlockRenderer.js +36 -0
  84. package/dist/components/blocks/FormBlockRenderer.d.ts +6 -0
  85. package/dist/components/blocks/FormBlockRenderer.js +110 -0
  86. package/dist/components/blocks/TableBlockRenderer.d.ts +6 -0
  87. package/dist/components/blocks/TableBlockRenderer.js +12 -0
  88. package/dist/components/blocks/TabsBlockRenderer.d.ts +7 -0
  89. package/dist/components/blocks/TabsBlockRenderer.js +11 -0
  90. package/dist/components/blocks/WidgetBlockRenderer.d.ts +6 -0
  91. package/dist/components/blocks/WidgetBlockRenderer.js +11 -0
  92. package/dist/components/columns/CheckboxColumnComponent.d.ts +6 -0
  93. package/dist/components/columns/CheckboxColumnComponent.js +21 -0
  94. package/dist/components/columns/ColorColumnComponent.d.ts +3 -0
  95. package/dist/components/columns/ColorColumnComponent.js +11 -0
  96. package/dist/components/columns/DeeplinkWrapper.d.ts +15 -0
  97. package/dist/components/columns/DeeplinkWrapper.js +85 -0
  98. package/dist/components/columns/IconColumnComponent.d.ts +3 -0
  99. package/dist/components/columns/IconColumnComponent.js +52 -0
  100. package/dist/components/columns/ImageColumnComponent.d.ts +3 -0
  101. package/dist/components/columns/ImageColumnComponent.js +98 -0
  102. package/dist/components/columns/MediaColumnComponent.d.ts +3 -0
  103. package/dist/components/columns/MediaColumnComponent.js +160 -0
  104. package/dist/components/columns/SelectColumnComponent.d.ts +6 -0
  105. package/dist/components/columns/SelectColumnComponent.js +26 -0
  106. package/dist/components/columns/TagsColumnComponent.d.ts +3 -0
  107. package/dist/components/columns/TagsColumnComponent.js +18 -0
  108. package/dist/components/columns/TextColumnComponent.d.ts +11 -0
  109. package/dist/components/columns/TextColumnComponent.js +107 -0
  110. package/dist/components/columns/TextInputColumnComponent.d.ts +6 -0
  111. package/dist/components/columns/TextInputColumnComponent.js +18 -0
  112. package/dist/components/columns/ToggleColumnComponent.d.ts +6 -0
  113. package/dist/components/columns/ToggleColumnComponent.js +25 -0
  114. package/dist/components/columns/VideoColumnComponent.d.ts +3 -0
  115. package/dist/components/columns/VideoColumnComponent.js +125 -0
  116. package/dist/components/columns/ViewColumnComponent.d.ts +3 -0
  117. package/dist/components/columns/ViewColumnComponent.js +7 -0
  118. package/dist/components/errors/ErrorBoundary.d.ts +23 -0
  119. package/dist/components/errors/ErrorBoundary.js +33 -0
  120. package/dist/components/filters/CustomFilterComponent.d.ts +10 -0
  121. package/dist/components/filters/CustomFilterComponent.js +33 -0
  122. package/dist/components/filters/DateFilterComponent.d.ts +15 -0
  123. package/dist/components/filters/DateFilterComponent.js +132 -0
  124. package/dist/components/filters/QueryBuilderFilterComponent.d.ts +11 -0
  125. package/dist/components/filters/QueryBuilderFilterComponent.js +200 -0
  126. package/dist/components/layout/Header.d.ts +10 -0
  127. package/dist/components/layout/Header.js +70 -0
  128. package/dist/components/layout/PanelBrandMark.d.ts +8 -0
  129. package/dist/components/layout/PanelBrandMark.js +28 -0
  130. package/dist/components/layout/Sidebar.d.ts +35 -0
  131. package/dist/components/layout/Sidebar.js +125 -0
  132. package/dist/components/modals/RelationCreateModal.d.ts +19 -0
  133. package/dist/components/modals/RelationCreateModal.js +57 -0
  134. package/dist/components/modals/ResourceFormModal.d.ts +37 -0
  135. package/dist/components/modals/ResourceFormModal.js +44 -0
  136. package/dist/components/modals/useResourceForm.d.ts +40 -0
  137. package/dist/components/modals/useResourceForm.js +138 -0
  138. package/dist/components/modals/view/RecordActions.d.ts +17 -0
  139. package/dist/components/modals/view/RecordActions.js +16 -0
  140. package/dist/components/modals/view/RecordDetails.d.ts +13 -0
  141. package/dist/components/modals/view/RecordDetails.js +29 -0
  142. package/dist/components/modals/view/RelationPanel.d.ts +18 -0
  143. package/dist/components/modals/view/RelationPanel.js +16 -0
  144. package/dist/components/modals/view/RelationTabs.d.ts +32 -0
  145. package/dist/components/modals/view/RelationTabs.js +42 -0
  146. package/dist/components/modals/view/useRecordView.d.ts +18 -0
  147. package/dist/components/modals/view/useRecordView.js +114 -0
  148. package/dist/components/pages/PageRenderer.d.ts +6 -0
  149. package/dist/components/pages/PageRenderer.js +107 -0
  150. package/dist/components/table/ColumnTogglePopup.d.ts +11 -0
  151. package/dist/components/table/ColumnTogglePopup.js +16 -0
  152. package/dist/components/table/GridCard.d.ts +21 -0
  153. package/dist/components/table/GridCard.js +30 -0
  154. package/dist/components/table/GridView.d.ts +23 -0
  155. package/dist/components/table/GridView.js +49 -0
  156. package/dist/components/table/LayoutToggle.d.ts +7 -0
  157. package/dist/components/table/LayoutToggle.js +9 -0
  158. package/dist/components/table/TableActionsDropdown.d.ts +13 -0
  159. package/dist/components/table/TableActionsDropdown.js +46 -0
  160. package/dist/components/table/TableBulkActions.d.ts +11 -0
  161. package/dist/components/table/TableBulkActions.js +21 -0
  162. package/dist/components/table/TableHeader.d.ts +14 -0
  163. package/dist/components/table/TableHeader.js +23 -0
  164. package/dist/components/table/TablePagination.d.ts +13 -0
  165. package/dist/components/table/TablePagination.js +55 -0
  166. package/dist/components/table/TableRow.d.ts +21 -0
  167. package/dist/components/table/TableRow.js +32 -0
  168. package/dist/components/table/TableSearchBar.d.ts +11 -0
  169. package/dist/components/table/TableSearchBar.js +12 -0
  170. package/dist/components/table/TableTabs.d.ts +14 -0
  171. package/dist/components/table/TableTabs.js +8 -0
  172. package/dist/components/ui/Badge.d.ts +6 -0
  173. package/dist/components/ui/Badge.js +12 -0
  174. package/dist/components/ui/Button.d.ts +22 -0
  175. package/dist/components/ui/Button.js +22 -0
  176. package/dist/components/ui/Card.d.ts +7 -0
  177. package/dist/components/ui/Card.js +5 -0
  178. package/dist/components/ui/ConfirmDialog.d.ts +19 -0
  179. package/dist/components/ui/ConfirmDialog.js +45 -0
  180. package/dist/components/ui/EmptyState.d.ts +9 -0
  181. package/dist/components/ui/EmptyState.js +6 -0
  182. package/dist/components/ui/ErrorAlert.d.ts +7 -0
  183. package/dist/components/ui/ErrorAlert.js +9 -0
  184. package/dist/components/ui/Input.d.ts +11 -0
  185. package/dist/components/ui/Input.js +10 -0
  186. package/dist/components/ui/Label.d.ts +5 -0
  187. package/dist/components/ui/Label.js +5 -0
  188. package/dist/components/ui/PillButton.d.ts +14 -0
  189. package/dist/components/ui/PillButton.js +19 -0
  190. package/dist/components/ui/Select.d.ts +7 -0
  191. package/dist/components/ui/Select.js +7 -0
  192. package/dist/components/ui/Spinner.d.ts +8 -0
  193. package/dist/components/ui/Spinner.js +14 -0
  194. package/dist/components/ui/Toast.d.ts +21 -0
  195. package/dist/components/ui/Toast.js +47 -0
  196. package/dist/components/ui/index.d.ts +24 -0
  197. package/dist/components/ui/index.js +12 -0
  198. package/dist/components/utils/HintDisplay.d.ts +11 -0
  199. package/dist/components/utils/HintDisplay.js +12 -0
  200. package/dist/components/utils/Icon.d.ts +22 -0
  201. package/dist/components/utils/Icon.js +22 -0
  202. package/dist/components/utils/MediaPreviewModal.d.ts +14 -0
  203. package/dist/components/utils/MediaPreviewModal.js +32 -0
  204. package/dist/components/utils/ViewFieldWrapper.d.ts +11 -0
  205. package/dist/components/utils/ViewFieldWrapper.js +9 -0
  206. package/dist/components/utils/layoutHelpers.d.ts +19 -0
  207. package/dist/components/utils/layoutHelpers.js +257 -0
  208. package/dist/components/widgets/ChartWidget.d.ts +16 -0
  209. package/dist/components/widgets/ChartWidget.js +192 -0
  210. package/dist/components/widgets/StatsWidget.d.ts +16 -0
  211. package/dist/components/widgets/StatsWidget.js +39 -0
  212. package/dist/components/widgets/WidgetRenderer.d.ts +10 -0
  213. package/dist/components/widgets/WidgetRenderer.js +50 -0
  214. package/dist/components/widgets/WidgetShell.d.ts +9 -0
  215. package/dist/components/widgets/WidgetShell.js +7 -0
  216. package/dist/contexts/AuthChallengeRegistryContext.d.ts +15 -0
  217. package/dist/contexts/AuthChallengeRegistryContext.js +15 -0
  218. package/dist/contexts/BlockRegistryContext.d.ts +18 -0
  219. package/dist/contexts/BlockRegistryContext.js +8 -0
  220. package/dist/contexts/ColumnRegistryContext.d.ts +8 -0
  221. package/dist/contexts/ColumnRegistryContext.js +30 -0
  222. package/dist/contexts/FieldRegistryContext.d.ts +13 -0
  223. package/dist/contexts/FieldRegistryContext.js +46 -0
  224. package/dist/contexts/PanelMetadataContext.d.ts +26 -0
  225. package/dist/contexts/PanelMetadataContext.js +26 -0
  226. package/dist/contexts/PanelProviders.d.ts +27 -0
  227. package/dist/contexts/PanelProviders.js +24 -0
  228. package/dist/contexts/ResourceModalContext.d.ts +26 -0
  229. package/dist/contexts/ResourceModalContext.js +76 -0
  230. package/dist/contexts/SlotRegistryContext.d.ts +19 -0
  231. package/dist/contexts/SlotRegistryContext.js +24 -0
  232. package/dist/contexts/TableRefreshContext.d.ts +10 -0
  233. package/dist/contexts/TableRefreshContext.js +30 -0
  234. package/dist/contexts/WidgetRegistryContext.d.ts +17 -0
  235. package/dist/contexts/WidgetRegistryContext.js +14 -0
  236. package/dist/contexts/createRegistryContext.d.ts +19 -0
  237. package/dist/contexts/createRegistryContext.js +20 -0
  238. package/dist/hooks/useAfterStateUpdated.d.ts +6 -0
  239. package/dist/hooks/useAfterStateUpdated.js +62 -0
  240. package/dist/hooks/useValidation.d.ts +26 -0
  241. package/dist/hooks/useValidation.js +76 -0
  242. package/dist/i18n/I18nProvider.d.ts +27 -0
  243. package/dist/i18n/I18nProvider.js +101 -0
  244. package/dist/i18n/LocaleSwitcher.d.ts +10 -0
  245. package/dist/i18n/LocaleSwitcher.js +30 -0
  246. package/dist/i18n/activeLocale.d.ts +11 -0
  247. package/dist/i18n/activeLocale.js +34 -0
  248. package/dist/i18n/buildClientI18n.d.ts +28 -0
  249. package/dist/i18n/buildClientI18n.js +67 -0
  250. package/dist/i18n/index.d.ts +11 -0
  251. package/dist/i18n/index.js +9 -0
  252. package/dist/i18n/locales/core/en.d.ts +225 -0
  253. package/dist/i18n/locales/core/en.js +252 -0
  254. package/dist/i18n/locales/core/index.d.ts +2 -0
  255. package/dist/i18n/locales/core/index.js +4 -0
  256. package/dist/i18n/locales/core/sq.d.ts +253 -0
  257. package/dist/i18n/locales/core/sq.js +255 -0
  258. package/dist/i18n/useFormatter.d.ts +18 -0
  259. package/dist/i18n/useFormatter.js +37 -0
  260. package/dist/i18n/useLocale.d.ts +11 -0
  261. package/dist/i18n/useLocale.js +11 -0
  262. package/dist/i18n/useTranslation.d.ts +12 -0
  263. package/dist/i18n/useTranslation.js +12 -0
  264. package/dist/index.d.ts +106 -0
  265. package/dist/index.js +101 -0
  266. package/dist/pages/ResourceListPage.d.ts +8 -0
  267. package/dist/pages/ResourceListPage.js +139 -0
  268. package/dist/plugin.d.ts +79 -0
  269. package/dist/plugin.js +34 -0
  270. package/dist/runtime/conditions.d.ts +35 -0
  271. package/dist/runtime/conditions.js +97 -0
  272. package/dist/runtime/formTraversal.d.ts +25 -0
  273. package/dist/runtime/formTraversal.js +37 -0
  274. package/dist/runtime/serializedFunctions.d.ts +41 -0
  275. package/dist/runtime/serializedFunctions.js +264 -0
  276. package/dist/slots/Slot.d.ts +24 -0
  277. package/dist/slots/Slot.js +29 -0
  278. package/dist/slots/SlotCluster.d.ts +22 -0
  279. package/dist/slots/SlotCluster.js +49 -0
  280. package/dist/slots/index.d.ts +7 -0
  281. package/dist/slots/index.js +4 -0
  282. package/dist/slots/mergeSlots.d.ts +18 -0
  283. package/dist/slots/mergeSlots.js +35 -0
  284. package/dist/slots/types.d.ts +87 -0
  285. package/dist/slots/types.js +30 -0
  286. package/dist/styles.css +1 -0
  287. package/dist/table/TableContext.d.ts +36 -0
  288. package/dist/table/TableContext.js +13 -0
  289. package/dist/table/TableRenderer.d.ts +29 -0
  290. package/dist/table/TableRenderer.js +159 -0
  291. package/dist/table/components/FiltersPanel.d.ts +11 -0
  292. package/dist/table/components/FiltersPanel.js +52 -0
  293. package/dist/table/components/TableToolbar.d.ts +28 -0
  294. package/dist/table/components/TableToolbar.js +27 -0
  295. package/dist/table/components/TableToolbarButton.d.ts +6 -0
  296. package/dist/table/components/TableToolbarButton.js +9 -0
  297. package/dist/table/components/TableView.d.ts +12 -0
  298. package/dist/table/components/TableView.js +21 -0
  299. package/dist/table/defaultRowActions.d.ts +21 -0
  300. package/dist/table/defaultRowActions.js +37 -0
  301. package/dist/table/hooks/useColumnVisibility.d.ts +13 -0
  302. package/dist/table/hooks/useColumnVisibility.js +59 -0
  303. package/dist/table/hooks/useEditableRows.d.ts +22 -0
  304. package/dist/table/hooks/useEditableRows.js +63 -0
  305. package/dist/table/hooks/useTableActions.d.ts +54 -0
  306. package/dist/table/hooks/useTableActions.js +313 -0
  307. package/dist/table/hooks/useTableData.d.ts +28 -0
  308. package/dist/table/hooks/useTableData.js +63 -0
  309. package/dist/table/hooks/useTableLayout.d.ts +12 -0
  310. package/dist/table/hooks/useTableLayout.js +31 -0
  311. package/dist/table/hooks/useTableQuery.d.ts +29 -0
  312. package/dist/table/hooks/useTableQuery.js +135 -0
  313. package/dist/types/index.d.ts +224 -0
  314. package/dist/types/index.js +6 -0
  315. package/dist/utils/classNames.d.ts +7 -0
  316. package/dist/utils/classNames.js +9 -0
  317. package/dist/utils/columnMediaDimensions.d.ts +13 -0
  318. package/dist/utils/columnMediaDimensions.js +29 -0
  319. package/dist/utils/columnVisibilityStorage.d.ts +22 -0
  320. package/dist/utils/columnVisibilityStorage.js +56 -0
  321. package/dist/utils/fieldErrors.d.ts +13 -0
  322. package/dist/utils/fieldErrors.js +25 -0
  323. package/dist/utils/formatValue.d.ts +28 -0
  324. package/dist/utils/formatValue.js +109 -0
  325. package/dist/utils/layoutStorage.d.ts +23 -0
  326. package/dist/utils/layoutStorage.js +53 -0
  327. package/dist/utils/redirectHandler.d.ts +7 -0
  328. package/dist/utils/redirectHandler.js +25 -0
  329. package/dist/utils/tableFormatters.d.ts +14 -0
  330. package/dist/utils/tableFormatters.js +93 -0
  331. package/dist/utils/widgetVisibilityStorage.d.ts +11 -0
  332. package/dist/utils/widgetVisibilityStorage.js +39 -0
  333. package/package.json +101 -0
  334. package/src/FieldRenderer.test.tsx +44 -0
  335. package/src/FieldRenderer.tsx +104 -0
  336. package/src/FormRenderer.containers.test.tsx +121 -0
  337. package/src/FormRenderer.test.tsx +174 -0
  338. package/src/FormRenderer.tsx +140 -0
  339. package/src/TableRenderer.tsx +2 -0
  340. package/src/api/actionsApi.ts +76 -0
  341. package/src/api/authenticatedFetch.ts +40 -0
  342. package/src/api/exportApi.ts +66 -0
  343. package/src/api/http.test.ts +58 -0
  344. package/src/api/http.ts +68 -0
  345. package/src/api/resourceApi.ts +88 -0
  346. package/src/api/tableApi.test.ts +108 -0
  347. package/src/api/tableApi.ts +107 -0
  348. package/src/api/urls.ts +50 -0
  349. package/src/app.test.tsx +67 -0
  350. package/src/app.tsx +181 -0
  351. package/src/auth/AuthContext.tsx +188 -0
  352. package/src/auth/LoginPage.tsx +380 -0
  353. package/src/auth/ProtectedRoute.tsx +39 -0
  354. package/src/auth/authApiClient.ts +109 -0
  355. package/src/auth/authFlow.test.tsx +168 -0
  356. package/src/auth/types.ts +104 -0
  357. package/src/components/ActionFormModal.tsx +45 -0
  358. package/src/components/AdminPanel.tsx +368 -0
  359. package/src/components/Checkbox.tsx +59 -0
  360. package/src/components/CheckboxField.tsx +88 -0
  361. package/src/components/ColorPickerField.tsx +93 -0
  362. package/src/components/DateTimePickerField.tsx +112 -0
  363. package/src/components/FileUploadField.tsx +841 -0
  364. package/src/components/GlobalSearch.tsx +436 -0
  365. package/src/components/GroupField.tsx +85 -0
  366. package/src/components/HiddenField.tsx +14 -0
  367. package/src/components/ModalBreadcrumb.tsx +74 -0
  368. package/src/components/ModalDrawer.tsx +137 -0
  369. package/src/components/RadioField.tsx +80 -0
  370. package/src/components/RepeaterField.tsx +546 -0
  371. package/src/components/ResourceModalRenderer.tsx +144 -0
  372. package/src/components/RichEditorField.tsx +942 -0
  373. package/src/components/SectionField.tsx +242 -0
  374. package/src/components/SelectField.tsx +843 -0
  375. package/src/components/TabsField.test.tsx +151 -0
  376. package/src/components/TabsField.tsx +386 -0
  377. package/src/components/TagsInputField.tsx +411 -0
  378. package/src/components/TextInputField.tsx +91 -0
  379. package/src/components/TextareaField.tsx +110 -0
  380. package/src/components/ToggleField.tsx +126 -0
  381. package/src/components/ViewModal.tsx +353 -0
  382. package/src/components/blocks/BlockRenderer.tsx +56 -0
  383. package/src/components/blocks/FormBlockRenderer.tsx +160 -0
  384. package/src/components/blocks/TableBlockRenderer.tsx +33 -0
  385. package/src/components/blocks/TabsBlockRenderer.tsx +49 -0
  386. package/src/components/blocks/WidgetBlockRenderer.tsx +19 -0
  387. package/src/components/columns/CheckboxColumnComponent.tsx +38 -0
  388. package/src/components/columns/ColorColumnComponent.tsx +23 -0
  389. package/src/components/columns/CustomColumn.test.tsx +55 -0
  390. package/src/components/columns/DeeplinkWrapper.tsx +103 -0
  391. package/src/components/columns/IconColumnComponent.tsx +55 -0
  392. package/src/components/columns/ImageColumnComponent.tsx +220 -0
  393. package/src/components/columns/MediaColumnComponent.tsx +294 -0
  394. package/src/components/columns/SelectColumnComponent.tsx +49 -0
  395. package/src/components/columns/TagsColumnComponent.tsx +46 -0
  396. package/src/components/columns/TextColumnComponent.tsx +191 -0
  397. package/src/components/columns/TextInputColumnComponent.tsx +35 -0
  398. package/src/components/columns/ToggleColumnComponent.tsx +56 -0
  399. package/src/components/columns/VideoColumnComponent.tsx +236 -0
  400. package/src/components/columns/ViewColumnComponent.tsx +9 -0
  401. package/src/components/errors/ErrorBoundary.tsx +58 -0
  402. package/src/components/filters/CustomFilterComponent.tsx +130 -0
  403. package/src/components/filters/DateFilterComponent.tsx +272 -0
  404. package/src/components/filters/QueryBuilderFilterComponent.tsx +502 -0
  405. package/src/components/layout/Header.tsx +212 -0
  406. package/src/components/layout/PanelBrandMark.tsx +61 -0
  407. package/src/components/layout/Sidebar.tsx +283 -0
  408. package/src/components/modals/RelationCreateModal.tsx +107 -0
  409. package/src/components/modals/ResourceFormModal.test.tsx +119 -0
  410. package/src/components/modals/ResourceFormModal.tsx +128 -0
  411. package/src/components/modals/useResourceForm.ts +207 -0
  412. package/src/components/modals/view/RecordActions.tsx +69 -0
  413. package/src/components/modals/view/RecordDetails.tsx +60 -0
  414. package/src/components/modals/view/RelationPanel.tsx +76 -0
  415. package/src/components/modals/view/RelationTabs.tsx +145 -0
  416. package/src/components/modals/view/useRecordView.ts +134 -0
  417. package/src/components/pages/PageRenderer.tsx +173 -0
  418. package/src/components/table/ColumnTogglePopup.tsx +85 -0
  419. package/src/components/table/GridCard.tsx +155 -0
  420. package/src/components/table/GridView.tsx +138 -0
  421. package/src/components/table/LayoutToggle.tsx +24 -0
  422. package/src/components/table/TableActionsDropdown.tsx +114 -0
  423. package/src/components/table/TableBulkActions.tsx +65 -0
  424. package/src/components/table/TableHeader.tsx +96 -0
  425. package/src/components/table/TablePagination.tsx +169 -0
  426. package/src/components/table/TableRow.tsx +155 -0
  427. package/src/components/table/TableSearchBar.tsx +66 -0
  428. package/src/components/table/TableTabs.tsx +49 -0
  429. package/src/components/ui/Badge.tsx +30 -0
  430. package/src/components/ui/Button.test.tsx +78 -0
  431. package/src/components/ui/Button.tsx +102 -0
  432. package/src/components/ui/Card.tsx +23 -0
  433. package/src/components/ui/ConfirmDialog.tsx +112 -0
  434. package/src/components/ui/EmptyState.tsx +24 -0
  435. package/src/components/ui/ErrorAlert.tsx +37 -0
  436. package/src/components/ui/Input.tsx +48 -0
  437. package/src/components/ui/Label.tsx +15 -0
  438. package/src/components/ui/PillButton.tsx +72 -0
  439. package/src/components/ui/Select.tsx +33 -0
  440. package/src/components/ui/Spinner.tsx +39 -0
  441. package/src/components/ui/Toast.tsx +105 -0
  442. package/src/components/ui/index.ts +24 -0
  443. package/src/components/utils/HintDisplay.tsx +26 -0
  444. package/src/components/utils/Icon.tsx +36 -0
  445. package/src/components/utils/MediaPreviewModal.tsx +114 -0
  446. package/src/components/utils/ViewFieldWrapper.tsx +23 -0
  447. package/src/components/utils/layoutHelpers.ts +267 -0
  448. package/src/components/widgets/ChartWidget.tsx +247 -0
  449. package/src/components/widgets/StatsWidget.tsx +72 -0
  450. package/src/components/widgets/WidgetRenderer.tsx +108 -0
  451. package/src/components/widgets/WidgetShell.tsx +37 -0
  452. package/src/contexts/AuthChallengeRegistryContext.tsx +29 -0
  453. package/src/contexts/BlockRegistryContext.tsx +28 -0
  454. package/src/contexts/ColumnRegistryContext.tsx +38 -0
  455. package/src/contexts/FieldRegistryContext.tsx +56 -0
  456. package/src/contexts/PanelMetadataContext.tsx +60 -0
  457. package/src/contexts/PanelProviders.tsx +85 -0
  458. package/src/contexts/ResourceModalContext.tsx +137 -0
  459. package/src/contexts/SlotRegistryContext.tsx +35 -0
  460. package/src/contexts/TableRefreshContext.tsx +44 -0
  461. package/src/contexts/WidgetRegistryContext.tsx +34 -0
  462. package/src/contexts/createRegistryContext.tsx +29 -0
  463. package/src/hooks/useAfterStateUpdated.ts +70 -0
  464. package/src/hooks/useValidation.test.ts +59 -0
  465. package/src/hooks/useValidation.ts +95 -0
  466. package/src/i18n/I18nProvider.tsx +128 -0
  467. package/src/i18n/LocaleSwitcher.tsx +50 -0
  468. package/src/i18n/activeLocale.ts +39 -0
  469. package/src/i18n/buildClientI18n.ts +101 -0
  470. package/src/i18n/i18n.test.tsx +140 -0
  471. package/src/i18n/index.ts +12 -0
  472. package/src/i18n/locales/core/en.ts +274 -0
  473. package/src/i18n/locales/core/index.ts +5 -0
  474. package/src/i18n/locales/core/sq.ts +275 -0
  475. package/src/i18n/useFormatter.ts +42 -0
  476. package/src/i18n/useLocale.ts +16 -0
  477. package/src/i18n/useTranslation.ts +17 -0
  478. package/src/index.ts +244 -0
  479. package/src/pages/ResourceListPage.tsx +205 -0
  480. package/src/plugin.ts +110 -0
  481. package/src/runtime/conditions.test.ts +99 -0
  482. package/src/runtime/conditions.ts +148 -0
  483. package/src/runtime/formTraversal.ts +41 -0
  484. package/src/runtime/serializedFunctions.test.ts +59 -0
  485. package/src/runtime/serializedFunctions.ts +284 -0
  486. package/src/slots/Slot.test.tsx +89 -0
  487. package/src/slots/Slot.tsx +47 -0
  488. package/src/slots/SlotCluster.test.tsx +95 -0
  489. package/src/slots/SlotCluster.tsx +107 -0
  490. package/src/slots/index.ts +15 -0
  491. package/src/slots/mergeSlots.test.ts +71 -0
  492. package/src/slots/mergeSlots.ts +40 -0
  493. package/src/slots/slotNames.test.ts +21 -0
  494. package/src/slots/types.ts +119 -0
  495. package/src/styles.css +437 -0
  496. package/src/table/TableContext.tsx +41 -0
  497. package/src/table/TableRenderer.test.tsx +197 -0
  498. package/src/table/TableRenderer.tsx +390 -0
  499. package/src/table/components/FiltersPanel.tsx +193 -0
  500. package/src/table/components/TableToolbar.tsx +153 -0
  501. package/src/table/components/TableToolbarButton.tsx +14 -0
  502. package/src/table/components/TableView.tsx +106 -0
  503. package/src/table/defaultRowActions.ts +43 -0
  504. package/src/table/hooks/useColumnVisibility.test.ts +51 -0
  505. package/src/table/hooks/useColumnVisibility.ts +71 -0
  506. package/src/table/hooks/useEditableRows.test.ts +69 -0
  507. package/src/table/hooks/useEditableRows.ts +89 -0
  508. package/src/table/hooks/useTableActions.ts +393 -0
  509. package/src/table/hooks/useTableData.ts +89 -0
  510. package/src/table/hooks/useTableLayout.ts +45 -0
  511. package/src/table/hooks/useTableQuery.test.ts +116 -0
  512. package/src/table/hooks/useTableQuery.ts +172 -0
  513. package/src/test/mockFetch.ts +67 -0
  514. package/src/test/setup.ts +25 -0
  515. package/src/types/index.ts +228 -0
  516. package/src/utils/classNames.ts +10 -0
  517. package/src/utils/columnMediaDimensions.ts +45 -0
  518. package/src/utils/columnVisibilityStorage.ts +55 -0
  519. package/src/utils/fieldErrors.test.ts +35 -0
  520. package/src/utils/fieldErrors.ts +27 -0
  521. package/src/utils/formatValue.test.tsx +65 -0
  522. package/src/utils/formatValue.tsx +117 -0
  523. package/src/utils/layoutStorage.ts +52 -0
  524. package/src/utils/redirectHandler.ts +29 -0
  525. package/src/utils/tableFormatters.test.ts +54 -0
  526. package/src/utils/tableFormatters.ts +104 -0
  527. package/src/utils/widgetVisibilityStorage.ts +38 -0
  528. package/tailwind.config.js +9 -0
  529. package/vite.config.ts +17 -0
@@ -0,0 +1,294 @@
1
+ import React, { useState } from 'react';
2
+ import { ColumnProps } from './TextColumnComponent';
3
+ import { formatValue } from '../../utils/tableFormatters';
4
+ import { getColumnMediaDimensions } from '../../utils/columnMediaDimensions';
5
+ import { Icon } from '../utils/Icon';
6
+ import { MediaPreviewModal } from '../utils/MediaPreviewModal';
7
+ import { translate } from '../../i18n/activeLocale';
8
+
9
+ type MediaType = 'image' | 'video' | 'audio' | null;
10
+
11
+ /**
12
+ * Resolve media type from column config
13
+ */
14
+ function resolveMediaType(column: ColumnProps['column'], record: Record<string, any>): MediaType {
15
+ const rawValue = record[column.name];
16
+
17
+ // Check for media type function (serialized as string)
18
+ if (column.mediaTypeFn) {
19
+ try {
20
+ // eslint-disable-next-line no-new-func
21
+ const mediaTypeFn = new Function('return ' + column.mediaTypeFn)();
22
+ const result = mediaTypeFn(rawValue, record);
23
+ if (result === 'image' || result === 'video' || result === 'audio') return result;
24
+ return 'image';
25
+ } catch {
26
+ console.warn('Failed to execute mediaType function');
27
+ return 'image';
28
+ }
29
+ }
30
+
31
+ // Static media type
32
+ if (column.mediaType === 'image' || column.mediaType === 'video' || column.mediaType === 'audio') {
33
+ return column.mediaType;
34
+ }
35
+
36
+ // Default to image
37
+ return 'image';
38
+ }
39
+
40
+ /**
41
+ * Resolve thumbnail URL from column config
42
+ * Supports: field name string, function string (serialized), variants, or default thumbnail
43
+ */
44
+ function resolveThumbnail(column: ColumnProps['column'], record: Record<string, any>): string | null {
45
+ const rawValue = record[column.name];
46
+
47
+ // Check for variants.thumbnail.url in new format
48
+ if (rawValue && typeof rawValue === 'object' && rawValue.variants?.thumbnail?.url) {
49
+ return rawValue.variants.thumbnail.url;
50
+ }
51
+
52
+ // Check for thumbnail function (serialized as string)
53
+ if (column.thumbnailFn) {
54
+ try {
55
+ // eslint-disable-next-line no-new-func
56
+ const thumbnailFn = new Function('return ' + column.thumbnailFn)();
57
+ const result = thumbnailFn(rawValue, record);
58
+ if (result) return result;
59
+ } catch {
60
+ console.warn('Failed to execute thumbnail function');
61
+ }
62
+ }
63
+
64
+ // Check for thumbnail field name
65
+ if (column.thumbnailField) {
66
+ const fieldName = column.thumbnailField as string;
67
+ // Support nested field access (e.g., 'mediaFile.thumbnailUrl')
68
+ const fieldValue = fieldName.split('.').reduce((obj: any, key) => obj?.[key], record);
69
+ if (fieldValue) {
70
+ // If it's a string, use it directly; otherwise check for new format
71
+ if (typeof fieldValue === 'string') {
72
+ return fieldValue;
73
+ }
74
+ if (typeof fieldValue === 'object' && fieldValue?.url) {
75
+ return fieldValue.url;
76
+ }
77
+ }
78
+ }
79
+
80
+ // Fallback to default thumbnail
81
+ if (column.defaultThumbnail) {
82
+ return column.defaultThumbnail as string;
83
+ }
84
+
85
+ return null;
86
+ }
87
+
88
+ export function MediaColumnComponent({ column, record }: ColumnProps) {
89
+ const [previewOpen, setPreviewOpen] = useState(false);
90
+
91
+ const rawValue = record[column.name];
92
+ // Apply formatter if present
93
+ const formattedValue = formatValue(rawValue, column, record);
94
+
95
+ // Extract URL from new format: { key, storage, url }
96
+ let mediaUrl: string | null = null;
97
+ if (formattedValue) {
98
+ if (typeof formattedValue === 'object' && formattedValue !== null && formattedValue.url) {
99
+ mediaUrl = formattedValue.url;
100
+ } else if (typeof formattedValue === 'string') {
101
+ mediaUrl = formattedValue;
102
+ }
103
+ }
104
+
105
+ // Resolve media type
106
+ const mediaType = resolveMediaType(column, record);
107
+
108
+ // Get thumbnail URL (for videos)
109
+ const thumbnailUrl = resolveThumbnail(column, record);
110
+
111
+ // Get default image URL (for images)
112
+ const defaultImageUrl = column.defaultImageUrl as string | undefined;
113
+
114
+ // Aspect ratio (default 16/9; circular columns force 1:1 via getColumnMediaDimensions)
115
+ const dimensions = getColumnMediaDimensions(column, 40);
116
+ const placeholderIcon =
117
+ (column.placeholderIcon as string) ||
118
+ (mediaType === 'video' ? 'Video' : mediaType === 'audio' ? 'Music' : 'Image');
119
+ const isClickable = column.clickable !== false;
120
+
121
+ const getContainerClasses = () => {
122
+ const classes = ['relative', 'flex', 'items-center', 'justify-center', 'overflow-hidden'];
123
+
124
+ if (column.circular) {
125
+ classes.push('rounded-full');
126
+ } else if (column.square) {
127
+ classes.push('rounded-none');
128
+ } else {
129
+ classes.push('rounded');
130
+ }
131
+
132
+ if (isClickable && mediaUrl) {
133
+ classes.push('cursor-pointer', 'hover:opacity-80', 'transition-opacity');
134
+ }
135
+
136
+ if (mediaType === 'video') {
137
+ classes.push('bg-gray-100', 'dark:bg-gray-800', 'group');
138
+ }
139
+
140
+ return classes.join(' ');
141
+ };
142
+
143
+ const handleClick = () => {
144
+ if (!isClickable || !mediaUrl) return;
145
+
146
+ if (column.clickAction === 'link') {
147
+ window.open(mediaUrl, '_blank');
148
+ } else {
149
+ setPreviewOpen(true);
150
+ }
151
+ };
152
+
153
+ // If media type is null (hidden), show nothing
154
+ if (mediaType === null) {
155
+ return <span className="text-fg-secondary">-</span>;
156
+ }
157
+
158
+ // If no media URL
159
+ if (!mediaUrl) {
160
+ // For images, check default image URL
161
+ if (mediaType === 'image' && defaultImageUrl) {
162
+ return (
163
+ <>
164
+ <img
165
+ src={defaultImageUrl}
166
+ alt=""
167
+ className={`object-cover ${getContainerClasses()}`}
168
+ style={dimensions}
169
+ onClick={handleClick}
170
+ />
171
+ {isClickable && (
172
+ <MediaPreviewModal
173
+ isOpen={previewOpen}
174
+ onClose={() => setPreviewOpen(false)}
175
+ mediaUrl={defaultImageUrl}
176
+ mediaType="image"
177
+ title={column.previewTitle as string | undefined}
178
+ />
179
+ )}
180
+ </>
181
+ );
182
+ }
183
+
184
+ // Show placeholder for video/audio
185
+ if (mediaType === 'video' || mediaType === 'audio') {
186
+ return (
187
+ <div
188
+ className={`${getContainerClasses()} opacity-50 cursor-not-allowed bg-gray-100 dark:bg-gray-800`}
189
+ style={dimensions}>
190
+ <Icon name={placeholderIcon} size={20} className="text-gray-400" />
191
+ </div>
192
+ );
193
+ }
194
+
195
+ return <span className="text-fg-secondary">{translate('core:file.no_image')}</span>;
196
+ }
197
+
198
+ // Render video
199
+ if (mediaType === 'video') {
200
+ return (
201
+ <>
202
+ <div
203
+ className={`${getContainerClasses()} bg-gray-100 dark:bg-gray-800`}
204
+ style={dimensions}
205
+ onClick={handleClick}>
206
+ {thumbnailUrl ? (
207
+ <>
208
+ <img
209
+ src={thumbnailUrl}
210
+ alt={translate('core:common.video_thumbnail')}
211
+ className="w-full h-full object-cover"
212
+ />
213
+ {/* Play overlay */}
214
+ <div className="absolute inset-0 flex items-center justify-center bg-black/30 group-hover:bg-black/40 transition-colors">
215
+ <div className="w-8 h-8 flex items-center justify-center bg-white/90 rounded-full">
216
+ <Icon name="Play" size={16} className="text-gray-800 ml-0.5" />
217
+ </div>
218
+ </div>
219
+ </>
220
+ ) : (
221
+ <>
222
+ <Icon name={placeholderIcon} size={24} className="text-gray-500 dark:text-gray-400" />
223
+ {/* Play indicator */}
224
+ <div className="absolute bottom-1 right-1 w-4 h-4 flex items-center justify-center bg-accent rounded-full">
225
+ <Icon name="Play" size={10} className="text-white ml-0.5" />
226
+ </div>
227
+ </>
228
+ )}
229
+ </div>
230
+
231
+ <MediaPreviewModal
232
+ isOpen={previewOpen}
233
+ onClose={() => setPreviewOpen(false)}
234
+ mediaUrl={mediaUrl}
235
+ mediaType="video"
236
+ title={column.previewTitle as string | undefined}
237
+ autoplay={column.autoplay as boolean | undefined}
238
+ controls={column.controls !== false}
239
+ loop={column.loop as boolean | undefined}
240
+ muted={column.muted as boolean | undefined}
241
+ />
242
+ </>
243
+ );
244
+ }
245
+
246
+ // Render audio
247
+ if (mediaType === 'audio') {
248
+ return (
249
+ <>
250
+ <div
251
+ className={`${getContainerClasses()} bg-linear-to-br from-blue-600 to-purple-600`}
252
+ style={dimensions}
253
+ onClick={handleClick}>
254
+ <Icon name={placeholderIcon} size={24} className="text-white" />
255
+ {/* Play indicator */}
256
+ <div className="absolute bottom-1 right-1 w-4 h-4 flex items-center justify-center bg-white/90 rounded-full">
257
+ <Icon name="Play" size={10} className="text-gray-800 ml-0.5" />
258
+ </div>
259
+ </div>
260
+
261
+ <MediaPreviewModal
262
+ isOpen={previewOpen}
263
+ onClose={() => setPreviewOpen(false)}
264
+ mediaUrl={mediaUrl}
265
+ mediaType="audio"
266
+ title={column.previewTitle as string | undefined}
267
+ autoplay={column.autoplay as boolean | undefined}
268
+ controls={column.controls !== false}
269
+ loop={column.loop as boolean | undefined}
270
+ />
271
+ </>
272
+ );
273
+ }
274
+
275
+ // Render single image
276
+ return (
277
+ <>
278
+ <img
279
+ src={mediaUrl}
280
+ alt=""
281
+ className={`object-cover ${getContainerClasses()}`}
282
+ style={dimensions}
283
+ onClick={handleClick}
284
+ />
285
+ <MediaPreviewModal
286
+ isOpen={previewOpen}
287
+ onClose={() => setPreviewOpen(false)}
288
+ mediaUrl={mediaUrl}
289
+ mediaType="image"
290
+ title={column.previewTitle as string | undefined}
291
+ />
292
+ </>
293
+ );
294
+ }
@@ -0,0 +1,49 @@
1
+ import React, { useState, useEffect } from 'react';
2
+ import { ColumnProps } from './TextColumnComponent';
3
+
4
+ export interface EditableColumnProps extends ColumnProps {
5
+ onCellChange?: (value: any) => void;
6
+ }
7
+
8
+ export function SelectColumnComponent({ column, record, onCellChange }: EditableColumnProps) {
9
+ const [value, setValue] = useState(record[column.name] || '');
10
+ const isDisabled = column.disabled;
11
+
12
+ // Update local value when record changes (e.g., after reset)
13
+ useEffect(() => {
14
+ setValue(record[column.name] || '');
15
+ }, [record[column.name]]);
16
+
17
+ const handleChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
18
+ if (isDisabled) return;
19
+
20
+ const newValue = e.target.value;
21
+ setValue(newValue);
22
+
23
+ // Notify parent of change
24
+ if (onCellChange) {
25
+ onCellChange(newValue);
26
+ }
27
+ };
28
+
29
+ return (
30
+ <select
31
+ value={value}
32
+ onChange={handleChange}
33
+ disabled={isDisabled}
34
+ className="k-input text-sm py-1.5 px-3 pr-8 rounded-md border border-border focus:outline-none focus:ring-2 focus:ring-ring focus:border-accent disabled:opacity-50 disabled:cursor-not-allowed transition-colors appearance-none bg-no-repeat bg-right"
35
+ style={{
36
+ backgroundImage: `url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3E%3Cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3E%3C/svg%3E")`,
37
+ backgroundPosition: 'right 0.5rem center',
38
+ backgroundSize: '1.5em 1.5em',
39
+ }}>
40
+ {column.placeholder && column.selectablePlaceholder && <option value="">{column.placeholder}</option>}
41
+ {column.options &&
42
+ Object.entries(column.options).map(([key, label]) => (
43
+ <option key={key} value={key}>
44
+ {label}
45
+ </option>
46
+ ))}
47
+ </select>
48
+ );
49
+ }
@@ -0,0 +1,46 @@
1
+ import React from 'react';
2
+ import { ColumnProps } from './TextColumnComponent';
3
+ import { cn } from '../../utils/classNames';
4
+ import { formatValue } from '../../utils/tableFormatters';
5
+
6
+ export function TagsColumnComponent({ column, record }: ColumnProps) {
7
+ const rawValue = record[column.name];
8
+ // Apply formatter if present
9
+ const value = formatValue(rawValue, column, record);
10
+
11
+ if (!value || (Array.isArray(value) && value.length === 0)) {
12
+ return <span className="text-fg-secondary">-</span>;
13
+ }
14
+
15
+ const tags = Array.isArray(value) ? value : [value];
16
+ const displayTags = column.limit ? tags.slice(0, column.limit) : tags;
17
+
18
+ // If no tags to display, return empty
19
+ if (!displayTags || displayTags.length === 0) {
20
+ return <></>;
21
+ }
22
+
23
+ return (
24
+ <div className="flex flex-wrap gap-1">
25
+ {displayTags.map((tag, idx) => (
26
+ <span
27
+ key={idx}
28
+ className={cn(
29
+ 'inline-flex items-center px-2 py-0.5 rounded text-xs font-medium',
30
+ 'bg-accent-soft dark:bg-accent-soft text-accent',
31
+ )}>
32
+ {String(tag)}
33
+ </span>
34
+ ))}
35
+ {column.limit && tags.length > column.limit && (
36
+ <span
37
+ className={cn(
38
+ 'inline-flex items-center px-2 py-0.5 rounded text-xs font-medium',
39
+ 'bg-gray-100 dark:bg-gray-800 text-gray-600 dark:text-gray-300',
40
+ )}>
41
+ +{tags.length - column.limit}
42
+ </span>
43
+ )}
44
+ </div>
45
+ );
46
+ }
@@ -0,0 +1,191 @@
1
+ import React from 'react';
2
+ import { SerializedColumn } from '@maxal_studio/kratosjs';
3
+ import { cn } from '../../utils/classNames';
4
+ import { formatValue } from '../../utils/tableFormatters';
5
+ import { DeeplinkWrapper } from './DeeplinkWrapper';
6
+
7
+ export interface ColumnProps {
8
+ column: SerializedColumn;
9
+ record: any;
10
+ rowIndex: number;
11
+ }
12
+
13
+ /**
14
+ * TextColumn component for displaying text values
15
+ */
16
+ export function TextColumnComponent({ column, record, rowIndex }: ColumnProps) {
17
+ const value = record[column.name];
18
+
19
+ // Handle row index
20
+ if (column.rowIndex) {
21
+ const displayIndex = column.rowIndexFromZero ? rowIndex : rowIndex + 1;
22
+ return <span className="text-fg">{displayIndex}</span>;
23
+ }
24
+
25
+ // Format value (pass entire record for formatStateUsing function)
26
+ const formattedValue = formatValue(value, column, record);
27
+
28
+ if (!formattedValue) {
29
+ return <></>;
30
+ }
31
+
32
+ const hasDeeplink = !!column.deeplink;
33
+
34
+ // Handle arrays
35
+ if (Array.isArray(formattedValue)) {
36
+ const items = column.limit ? formattedValue.slice(0, column.limit) : formattedValue;
37
+ const shouldRenderHtml = column.stripHtml === false;
38
+
39
+ if (column.bulleted) {
40
+ return (
41
+ <ul className="list-disc list-inside space-y-1">
42
+ {items.map((item, idx) => {
43
+ const itemText = String(item);
44
+ return (
45
+ <li key={idx} className="text-fg text-sm">
46
+ {shouldRenderHtml ? <span dangerouslySetInnerHTML={{ __html: itemText }} /> : itemText}
47
+ </li>
48
+ );
49
+ })}
50
+ {column.limit && formattedValue.length > column.limit && (
51
+ <li className="text-fg-secondary text-sm italic">
52
+ +{formattedValue.length - column.limit} more
53
+ </li>
54
+ )}
55
+ </ul>
56
+ );
57
+ }
58
+
59
+ if (column.listWithLineBreaks) {
60
+ return (
61
+ <div className="space-y-1">
62
+ {items.map((item, idx) => {
63
+ const itemText = String(item);
64
+ return (
65
+ <div key={idx} className="text-fg text-sm">
66
+ {shouldRenderHtml ? <span dangerouslySetInnerHTML={{ __html: itemText }} /> : itemText}
67
+ </div>
68
+ );
69
+ })}
70
+ {column.limit && formattedValue.length > column.limit && (
71
+ <div className="text-fg-secondary text-sm italic">
72
+ +{formattedValue.length - column.limit} more
73
+ </div>
74
+ )}
75
+ </div>
76
+ );
77
+ }
78
+
79
+ // Default: comma-separated
80
+ const joinedText = items.join(', ');
81
+ return (
82
+ <span className="text-fg">
83
+ {shouldRenderHtml ? <span dangerouslySetInnerHTML={{ __html: joinedText }} /> : joinedText}
84
+ </span>
85
+ );
86
+ }
87
+
88
+ // Get styling classes
89
+ const getTextClasses = () => {
90
+ const classes = ['text-fg'];
91
+
92
+ if (column.weight) {
93
+ classes.push(`font-${column.weight}`);
94
+ }
95
+
96
+ if (column.fontFamily) {
97
+ classes.push(`font-${column.fontFamily}`);
98
+ }
99
+
100
+ if (column.size) {
101
+ if (typeof column.size === 'string') {
102
+ classes.push(`text-${column.size}`);
103
+ }
104
+ }
105
+
106
+ if (column.lineClamp) {
107
+ classes.push(`line-clamp-${column.lineClamp}`);
108
+ }
109
+
110
+ if (!column.wrap) {
111
+ classes.push('truncate');
112
+ }
113
+
114
+ return cn(classes);
115
+ };
116
+
117
+ // Check if HTML should be rendered (stripHtml defaults to true in backend)
118
+ const shouldRenderHtml = column.stripHtml === false;
119
+ const textContent = String(formattedValue);
120
+
121
+ // Render badge
122
+ if (column.badge) {
123
+ let badgeColor = 'bg-gray-100 dark:bg-gray-800 text-gray-800 dark:text-gray-200';
124
+
125
+ if (column.color) {
126
+ if (typeof column.color === 'object') {
127
+ // Color mapping based on value
128
+ const colorKey = column.color[value];
129
+ if (colorKey) {
130
+ badgeColor = getBadgeColorClasses(colorKey);
131
+ }
132
+ } else {
133
+ badgeColor = getBadgeColorClasses(column.color);
134
+ }
135
+ }
136
+
137
+ const badgeElement = (
138
+ <span
139
+ className={cn(
140
+ 'inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium',
141
+ badgeColor,
142
+ hasDeeplink && 'hover:opacity-80',
143
+ )}>
144
+ {shouldRenderHtml ? <span dangerouslySetInnerHTML={{ __html: textContent }} /> : textContent}
145
+ </span>
146
+ );
147
+
148
+ // Wrap badge in deeplink if exists
149
+ if (hasDeeplink) {
150
+ return (
151
+ <DeeplinkWrapper column={column} record={record} value={value} className="inline-block">
152
+ {badgeElement}
153
+ </DeeplinkWrapper>
154
+ );
155
+ }
156
+
157
+ return badgeElement;
158
+ }
159
+
160
+ // Regular text - render as HTML if stripHtml is false
161
+ const textElement = shouldRenderHtml ? <span dangerouslySetInnerHTML={{ __html: textContent }} /> : textContent;
162
+
163
+ // Wrap in deeplink if exists
164
+ if (hasDeeplink) {
165
+ return (
166
+ <DeeplinkWrapper column={column} record={record} value={value} className={getTextClasses()}>
167
+ {textElement}
168
+ </DeeplinkWrapper>
169
+ );
170
+ }
171
+
172
+ return (
173
+ <span className={getTextClasses()}>
174
+ {shouldRenderHtml ? <span dangerouslySetInnerHTML={{ __html: textContent }} /> : textContent}
175
+ </span>
176
+ );
177
+ }
178
+
179
+ function getBadgeColorClasses(color: string): string {
180
+ const colorMap: Record<string, string> = {
181
+ primary: 'bg-accent-soft dark:bg-accent-soft text-accent',
182
+ secondary: 'bg-gray-100 dark:bg-gray-800 text-gray-800 dark:text-gray-200',
183
+ success: 'bg-green-100 dark:bg-green-900/30 text-green-800 dark:text-green-300',
184
+ danger: 'bg-red-100 dark:bg-red-900/30 text-red-800 dark:text-red-300',
185
+ warning: 'bg-yellow-100 dark:bg-yellow-900/30 text-yellow-800 dark:text-yellow-300',
186
+ info: 'bg-cyan-100 dark:bg-cyan-900/30 text-cyan-800 dark:text-cyan-300',
187
+ gray: 'bg-gray-100 dark:bg-gray-800 text-gray-800 dark:text-gray-200',
188
+ };
189
+
190
+ return colorMap[color] || colorMap.gray;
191
+ }
@@ -0,0 +1,35 @@
1
+ import React, { useState, useEffect } from 'react';
2
+ import { ColumnProps } from './TextColumnComponent';
3
+
4
+ export interface EditableColumnProps extends ColumnProps {
5
+ onCellChange?: (value: any) => void;
6
+ }
7
+
8
+ export function TextInputColumnComponent({ column, record, onCellChange }: EditableColumnProps) {
9
+ const [value, setValue] = useState(record[column.name] || '');
10
+ const isDisabled = column.disabled;
11
+
12
+ // Update local value when record changes (e.g., after reset)
13
+ useEffect(() => {
14
+ setValue(record[column.name] || '');
15
+ }, [record[column.name]]);
16
+
17
+ const handleChange = (newValue: string) => {
18
+ setValue(newValue);
19
+ // Notify parent of change
20
+ if (onCellChange) {
21
+ onCellChange(newValue);
22
+ }
23
+ };
24
+
25
+ return (
26
+ <input
27
+ type={column.inputType || 'text'}
28
+ value={value}
29
+ onChange={e => handleChange(e.target.value)}
30
+ disabled={isDisabled}
31
+ placeholder={column.placeholder}
32
+ className="k-input text-sm py-1.5 px-3 w-full rounded-md border border-border focus:outline-none focus:ring-2 focus:ring-ring focus:border-accent disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
33
+ />
34
+ );
35
+ }
@@ -0,0 +1,56 @@
1
+ import React, { useState, useEffect } from 'react';
2
+ import { ColumnProps } from './TextColumnComponent';
3
+ import { Icon } from '../utils/Icon';
4
+ import { cn } from '../../utils/classNames';
5
+
6
+ export interface EditableColumnProps extends ColumnProps {
7
+ onCellChange?: (value: any) => void;
8
+ }
9
+
10
+ export function ToggleColumnComponent({ column, record, onCellChange }: EditableColumnProps) {
11
+ const [value, setValue] = useState(Boolean(record[column.name]));
12
+ const isDisabled = column.disabled;
13
+
14
+ // Update local value when record changes (e.g., after reset)
15
+ useEffect(() => {
16
+ setValue(Boolean(record[column.name]));
17
+ }, [record[column.name]]);
18
+
19
+ const handleToggle = () => {
20
+ if (isDisabled) return;
21
+
22
+ const newValue = !value;
23
+ setValue(newValue);
24
+
25
+ // Notify parent of change
26
+ if (onCellChange) {
27
+ onCellChange(newValue);
28
+ }
29
+ };
30
+
31
+ // Get colors
32
+ const trackClasses =
33
+ (value ? column.onColor : column.offColor) ?? (value ? 'bg-accent' : 'bg-gray-200 dark:bg-gray-700');
34
+
35
+ return (
36
+ <button
37
+ type="button"
38
+ onClick={handleToggle}
39
+ disabled={isDisabled}
40
+ className={cn(
41
+ 'relative inline-flex h-6 w-11 items-center rounded-full transition-colors',
42
+ 'focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2',
43
+ 'disabled:opacity-50 disabled:cursor-not-allowed',
44
+ ...trackClasses.split(/\s+/),
45
+ )}>
46
+ <span
47
+ className={cn(
48
+ 'inline-flex items-center justify-center h-4 w-4 transform rounded-full bg-white transition-transform',
49
+ value ? 'translate-x-6' : 'translate-x-1',
50
+ )}>
51
+ {column.onIcon && value && <Icon name={column.onIcon} size={10} className="text-green-600" />}
52
+ {column.offIcon && !value && <Icon name={column.offIcon} size={10} className="text-gray-400" />}
53
+ </span>
54
+ </button>
55
+ );
56
+ }