@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,172 @@
1
+ import { useEffect, useMemo, useState } from 'react';
2
+ import { SerializedTable } from '@maxal_studio/kratosjs';
3
+ import { QueryParams } from '../../api/tableApi';
4
+
5
+ export interface TableQueryState {
6
+ searchQuery: string;
7
+ sortColumn: string | undefined;
8
+ sortDirection: 'asc' | 'desc';
9
+ filters: Record<string, any>;
10
+ queryBuilders: Record<string, any[]>;
11
+ activeTab: string | null;
12
+ currentPage: number;
13
+ perPage: number;
14
+ }
15
+
16
+ export interface TableQueryApi extends TableQueryState {
17
+ handleSearch: (query: string) => void;
18
+ handleSort: (column: string) => void;
19
+ handleFilterChange: (name: string, value: any, isQueryBuilder?: boolean) => void;
20
+ handleTabClick: (tabKey: string | null) => void;
21
+ handleClearFilters: () => void;
22
+ handlePageChange: (page: number) => void;
23
+ handlePageSizeChange: (size: number) => void;
24
+ /** Request payload for TableApiClient.fetchData, with tab rules merged in */
25
+ queryParams: QueryParams;
26
+ }
27
+
28
+ /**
29
+ * All list-query state for a table: search, sort, filters, query builders,
30
+ * tabs, and pagination — plus the handlers that keep them consistent
31
+ * (changing any criterion resets to page 1; manual filtering clears the tab).
32
+ */
33
+ export function useTableQuery(schema: SerializedTable): TableQueryApi {
34
+ // Filter defaults come from the schema
35
+ const initialFilters = useMemo(() => {
36
+ const defaults: Record<string, any> = {};
37
+ schema.filters?.forEach(filter => {
38
+ if (filter.default !== undefined && filter.type !== 'queryBuilder') {
39
+ defaults[filter.name] = filter.default;
40
+ }
41
+ });
42
+ return defaults;
43
+ }, [schema.filters]);
44
+
45
+ const initialQueryBuilders = useMemo(() => {
46
+ const defaults: Record<string, any[]> = {};
47
+ schema.filters?.forEach(filter => {
48
+ if (filter.type === 'queryBuilder' && Array.isArray(filter.default)) {
49
+ defaults[filter.name] = filter.default;
50
+ }
51
+ });
52
+ return defaults;
53
+ }, [schema.filters]);
54
+
55
+ const [searchQuery, setSearchQuery] = useState('');
56
+ const [sortColumn, setSortColumn] = useState<string | undefined>(schema.defaultSort?.column);
57
+ const [sortDirection, setSortDirection] = useState<'asc' | 'desc'>(schema.defaultSort?.direction || 'asc');
58
+ const [filters, setFilters] = useState<Record<string, any>>(initialFilters);
59
+ const [queryBuilders, setQueryBuilders] = useState<Record<string, any[]>>(initialQueryBuilders);
60
+ const [activeTab, setActiveTab] = useState<string | null>(() => {
61
+ const tabs = schema.tabs as Array<{ default?: boolean; key: string }> | undefined;
62
+ return tabs?.find(tab => tab.default === true)?.key ?? null;
63
+ });
64
+ const [currentPage, setCurrentPage] = useState(1);
65
+ const [perPage, setPerPage] = useState(schema.recordsPerPage || 10);
66
+
67
+ // Reset filters to defaults when the schema changes
68
+ useEffect(() => {
69
+ setFilters(initialFilters);
70
+ setQueryBuilders(initialQueryBuilders);
71
+ }, [initialFilters, initialQueryBuilders]);
72
+
73
+ const handleSearch = (query: string) => {
74
+ setSearchQuery(query);
75
+ setCurrentPage(1);
76
+ };
77
+
78
+ const handleSort = (column: string) => {
79
+ setSortDirection(sortColumn === column && sortDirection === 'asc' ? 'desc' : 'asc');
80
+ setSortColumn(column);
81
+ setCurrentPage(1);
82
+ };
83
+
84
+ const handleFilterChange = (name: string, value: any, isQueryBuilder: boolean = false) => {
85
+ // Manual filtering clears the active tab
86
+ setActiveTab(null);
87
+
88
+ if (isQueryBuilder) {
89
+ setQueryBuilders(prev => {
90
+ const next = { ...prev };
91
+ if (value === undefined || (Array.isArray(value) && value.length === 0)) {
92
+ delete next[name];
93
+ } else {
94
+ next[name] = value;
95
+ }
96
+ return next;
97
+ });
98
+ } else {
99
+ setFilters(prev => {
100
+ const next = { ...prev };
101
+ if (value === '' || value === undefined) {
102
+ delete next[name];
103
+ } else {
104
+ next[name] = value;
105
+ }
106
+ return next;
107
+ });
108
+ }
109
+ setCurrentPage(1);
110
+ };
111
+
112
+ const handleTabClick = (tabKey: string | null) => {
113
+ setActiveTab(tabKey);
114
+ setCurrentPage(1);
115
+ };
116
+
117
+ const handleClearFilters = () => {
118
+ setFilters(initialFilters);
119
+ setQueryBuilders(initialQueryBuilders);
120
+ setCurrentPage(1);
121
+ };
122
+
123
+ const handlePageChange = (page: number) => {
124
+ setCurrentPage(page);
125
+ };
126
+
127
+ const handlePageSizeChange = (size: number) => {
128
+ setPerPage(size);
129
+ setCurrentPage(1);
130
+ };
131
+
132
+ const queryParams = useMemo<QueryParams>(() => {
133
+ // Merge the active tab's query-builder rules into the request
134
+ const finalQueryBuilders = { ...queryBuilders };
135
+ const tabs = schema.tabs as Array<{ key: string; queryBuilder?: any[] }> | undefined;
136
+ if (activeTab && tabs) {
137
+ const selectedTab = tabs.find(tab => tab.key === activeTab);
138
+ if (selectedTab?.queryBuilder && selectedTab.queryBuilder.length > 0) {
139
+ finalQueryBuilders.__activeTab = selectedTab.queryBuilder;
140
+ }
141
+ }
142
+
143
+ return {
144
+ page: currentPage,
145
+ perPage,
146
+ search: searchQuery || undefined,
147
+ sort: sortColumn,
148
+ sortDirection,
149
+ filters,
150
+ queryBuilders: Object.keys(finalQueryBuilders).length > 0 ? finalQueryBuilders : undefined,
151
+ };
152
+ }, [queryBuilders, schema.tabs, activeTab, currentPage, perPage, searchQuery, sortColumn, sortDirection, filters]);
153
+
154
+ return {
155
+ searchQuery,
156
+ sortColumn,
157
+ sortDirection,
158
+ filters,
159
+ queryBuilders,
160
+ activeTab,
161
+ currentPage,
162
+ perPage,
163
+ handleSearch,
164
+ handleSort,
165
+ handleFilterChange,
166
+ handleTabClick,
167
+ handleClearFilters,
168
+ handlePageChange,
169
+ handlePageSizeChange,
170
+ queryParams,
171
+ };
172
+ }
@@ -0,0 +1,67 @@
1
+ import { vi } from 'vitest';
2
+
3
+ export interface MockRoute {
4
+ /** Substring or RegExp matched against the request URL */
5
+ match: string | RegExp;
6
+ /** Optional HTTP method filter (defaults to any) */
7
+ method?: string;
8
+ status?: number;
9
+ headers?: Record<string, string>;
10
+ /** JSON body to respond with, or a function of (url, init) */
11
+ body: unknown | ((url: string, init?: RequestInit) => unknown);
12
+ }
13
+
14
+ export interface RecordedRequest {
15
+ url: string;
16
+ method: string;
17
+ body: unknown;
18
+ }
19
+
20
+ /**
21
+ * Stub global fetch with a small route table. Returns the list of recorded
22
+ * requests so tests can assert on payloads. Routes are matched in order;
23
+ * unmatched requests resolve with 404 to surface mistakes loudly.
24
+ */
25
+ export function mockFetch(routes: MockRoute[]): RecordedRequest[] {
26
+ const requests: RecordedRequest[] = [];
27
+
28
+ vi.stubGlobal(
29
+ 'fetch',
30
+ vi.fn(async (input: RequestInfo | URL, init?: RequestInit) => {
31
+ const url = typeof input === 'string' ? input : input instanceof URL ? input.href : input.url;
32
+ const method = (init?.method || 'GET').toUpperCase();
33
+ let parsedBody: unknown = undefined;
34
+ if (typeof init?.body === 'string') {
35
+ try {
36
+ parsedBody = JSON.parse(init.body);
37
+ } catch {
38
+ parsedBody = init.body;
39
+ }
40
+ }
41
+ requests.push({ url, method, body: parsedBody });
42
+
43
+ for (const route of routes) {
44
+ const urlMatches = typeof route.match === 'string' ? url.includes(route.match) : route.match.test(url);
45
+ const methodMatches = !route.method || route.method.toUpperCase() === method;
46
+ if (urlMatches && methodMatches) {
47
+ const body = typeof route.body === 'function' ? route.body(url, init) : route.body;
48
+ return new Response(JSON.stringify(body), {
49
+ status: route.status ?? 200,
50
+ headers: { 'Content-Type': 'application/json', ...route.headers },
51
+ });
52
+ }
53
+ }
54
+
55
+ return new Response(JSON.stringify({ message: `No mock route for ${method} ${url}` }), {
56
+ status: 404,
57
+ headers: { 'Content-Type': 'application/json' },
58
+ });
59
+ }),
60
+ );
61
+
62
+ return requests;
63
+ }
64
+
65
+ export function restoreFetch(): void {
66
+ vi.unstubAllGlobals();
67
+ }
@@ -0,0 +1,25 @@
1
+ import '@testing-library/jest-dom/vitest';
2
+ import { afterEach } from 'vitest';
3
+ import { cleanup } from '@testing-library/react';
4
+
5
+ // Without vitest globals, React Testing Library cannot auto-register its
6
+ // cleanup — do it explicitly so trees don't leak between tests.
7
+ afterEach(() => {
8
+ cleanup();
9
+ });
10
+
11
+ // jsdom does not implement matchMedia; several components consult it for
12
+ // responsive defaults (widgets expanded, dark-mode preference).
13
+ if (typeof window !== 'undefined' && typeof window.matchMedia !== 'function') {
14
+ window.matchMedia = (query: string) =>
15
+ ({
16
+ matches: false,
17
+ media: query,
18
+ onchange: null,
19
+ addListener: () => {},
20
+ removeListener: () => {},
21
+ addEventListener: () => {},
22
+ removeEventListener: () => {},
23
+ dispatchEvent: () => false,
24
+ }) as MediaQueryList;
25
+ }
@@ -0,0 +1,228 @@
1
+ import { SerializedForm, ValidationRules as KratosJsValidationRules } from '@maxal_studio/kratosjs';
2
+ import { ColumnRegistry } from '../contexts/ColumnRegistryContext';
3
+ import { WidgetComponent } from '../contexts/WidgetRegistryContext';
4
+ import type { CustomBlockComponent } from '../contexts/BlockRegistryContext';
5
+ import type { AuthChallengeRegistry } from '../contexts/AuthChallengeRegistryContext';
6
+ import type { ClientI18nConfig } from '../i18n/buildClientI18n';
7
+ import type { ResolvedSlots } from '../slots/types';
8
+
9
+ /**
10
+ * Props passed to all field components
11
+ */
12
+ export interface FieldProps {
13
+ type: string;
14
+ name: string;
15
+ label?: string;
16
+ statePath?: string;
17
+ default?: any;
18
+ hidden?: boolean;
19
+ disabled?: boolean;
20
+ mode?: 'edit' | 'view';
21
+ value?: any;
22
+ extraAttributes?: Record<string, any>;
23
+ validation?: KratosJsValidationRules;
24
+ helperText?: string;
25
+ hint?: string;
26
+ hintIcon?: string;
27
+ hintColor?: string;
28
+ autofocus?: boolean;
29
+ placeholder?: string;
30
+ readOnly?: boolean;
31
+ /** When true, view mode displays the value as HTML (TextInput, Textarea, TagsInput) */
32
+ renderHtml?: boolean;
33
+ inputType?: string;
34
+ minLength?: number;
35
+ maxLength?: number;
36
+ min?: number;
37
+ max?: number;
38
+ step?: number;
39
+ mask?: string;
40
+ prefix?: string;
41
+ suffix?: string;
42
+ options?: Record<string | number, string>;
43
+ multiple?: boolean;
44
+ isMultiple?: boolean;
45
+ searchable?: boolean;
46
+ creatable?: boolean;
47
+ // Relationship-based select properties
48
+ relationship?: {
49
+ name: string;
50
+ titleAttribute: string;
51
+ resource?: string;
52
+ };
53
+ createOptionForm?: any[]; // Form schema for creating new related records
54
+ createOptionModalHeading?: string;
55
+ optionLabelFormatter?: string; // Serialized function for formatting option labels
56
+ // TagsInput-specific properties
57
+ tags?: string[];
58
+ separator?: string;
59
+ suggestions?: string[];
60
+ /** When true, view mode shows tags in a popup (e.g. "N tags" click to open) */
61
+ showInPopup?: boolean;
62
+ selectablePlaceholder?: boolean;
63
+ rows?: number;
64
+ cols?: number;
65
+ format?: string;
66
+ displayFormat?: string;
67
+ minDate?: string;
68
+ maxDate?: string;
69
+ enableTime?: boolean;
70
+ onColor?: string;
71
+ offColor?: string;
72
+ onIcon?: string;
73
+ offIcon?: string;
74
+ // Repeater-specific properties
75
+ schema?: FieldProps[]; // Schema for Repeater and Group
76
+ defaultItems?: number;
77
+ minItems?: number;
78
+ maxItems?: number;
79
+ addable?: boolean;
80
+ deletable?: boolean;
81
+ reorderable?: boolean;
82
+ itemLabel?: string;
83
+ // FileUpload-specific properties
84
+ acceptedFileTypes?: string[];
85
+ maxSize?: number;
86
+ minSize?: number;
87
+ maxFiles?: number;
88
+ disk?: string;
89
+ directory?: string;
90
+ visibility?: 'public' | 'private';
91
+ // RichEditor-specific properties
92
+ toolbarButtons?: string[];
93
+ fileAttachments?: boolean;
94
+ embeds?: boolean;
95
+ htmlSource?: boolean;
96
+ extensions?: string[];
97
+ // Section-specific properties
98
+ heading?: string;
99
+ icon?: string;
100
+ collapsible?: boolean; // For both Repeater and Section
101
+ collapsed?: boolean;
102
+ compact?: boolean;
103
+ aside?: boolean;
104
+ // Column layout properties
105
+ columns?: number | Record<string, number>;
106
+ columnSpan?: number | string | Record<string, number | string>;
107
+ columnStart?: number | Record<string, number>;
108
+ required?: boolean;
109
+ /** Operation for conditional visibility (e.g. hidden(context => context.operation === 'view')) */
110
+ operation?: 'create' | 'edit' | 'view';
111
+ [key: string]: any;
112
+ }
113
+
114
+ /**
115
+ * Field component type
116
+ */
117
+ export type FieldComponent = React.ComponentType<FieldProps>;
118
+
119
+ /**
120
+ * Field registry mapping field types to components
121
+ */
122
+ export type FieldRegistry = Record<string, FieldComponent>;
123
+
124
+ /**
125
+ * Props for FormRenderer component
126
+ */
127
+ export interface FormRendererProps {
128
+ schema: SerializedForm;
129
+ onSubmit: (data: any) => void | Promise<void>;
130
+ defaultValues?: Record<string, any>;
131
+ className?: string;
132
+ /** Base URL for API requests (e.g., 'http://localhost:3001/kratosjs/api') */
133
+ apiBaseUrl?: string;
134
+ /** Resource slug for media endpoints (e.g., 'users') */
135
+ resource?: string;
136
+ /** Operation type for conditional field visibility (e.g., 'create' | 'edit' | 'view') */
137
+ operation?: 'create' | 'edit' | 'view';
138
+ /** Children to render inside FormProvider (for watching form values) */
139
+ children?: React.ReactNode;
140
+ }
141
+
142
+ /**
143
+ * Props for FieldRenderer component
144
+ */
145
+ export interface FieldRendererProps {
146
+ field: FieldProps;
147
+ }
148
+
149
+ /**
150
+ * Validation rules from React Hook Form (converted format)
151
+ */
152
+ export interface RHFValidationRules {
153
+ required?: string | { value: boolean; message: string };
154
+ pattern?: { value: RegExp; message: string };
155
+ minLength?: { value: number; message: string };
156
+ maxLength?: { value: number; message: string };
157
+ min?: { value: number; message: string };
158
+ max?: { value: number; message: string };
159
+ validate?: Record<string, (value: any, formValues?: any) => boolean | string>;
160
+ }
161
+
162
+ /**
163
+ * Redirect response from API
164
+ */
165
+ export interface RedirectResponse {
166
+ redirect: string;
167
+ message?: string;
168
+ [key: string]: any;
169
+ }
170
+
171
+ /**
172
+ * Type guard to check if response is a redirect response
173
+ */
174
+ export function isRedirectResponse(data: any): data is RedirectResponse {
175
+ return typeof data === 'object' && data !== null && typeof data.redirect === 'string';
176
+ }
177
+
178
+ /**
179
+ * Relation metadata served by GET /:slug/relations, consumed by the view modal
180
+ */
181
+ export interface SerializedRelation {
182
+ name: string;
183
+ type: 'hasMany';
184
+ canCreate?: boolean;
185
+ canEdit?: boolean;
186
+ canDelete?: boolean;
187
+ canView?: boolean;
188
+ resourceSlug: string;
189
+ /** Full API URL for the related resource */
190
+ resourceApiUrl?: string;
191
+ label: string;
192
+ pluralLabel: string;
193
+ icon?: string;
194
+ localKey: string;
195
+ foreignKey: string;
196
+ relatedKey: string;
197
+ // Optional grouping metadata (when backend RelationConfig defines a group)
198
+ groupKey?: string;
199
+ groupLabel?: string;
200
+ groupIcon?: string;
201
+ }
202
+
203
+ /**
204
+ * Widget registry mapping widget types to components
205
+ */
206
+ export type WidgetRegistry = Record<string, WidgetComponent>;
207
+
208
+ /**
209
+ * Block registry mapping custom block types to components
210
+ */
211
+ export type BlockRegistry = Record<string, CustomBlockComponent>;
212
+
213
+ /**
214
+ * Props for AdminPanel component
215
+ */
216
+ export interface AdminPanelProps {
217
+ apiBaseUrl: string;
218
+ panelId?: string;
219
+ customFields?: FieldRegistry;
220
+ customColumns?: ColumnRegistry;
221
+ customWidgets?: WidgetRegistry;
222
+ customBlocks?: BlockRegistry;
223
+ customAuthChallenges?: AuthChallengeRegistry;
224
+ /** Merged, resolved slot contributions keyed by slot name. */
225
+ customSlots?: ResolvedSlots;
226
+ /** i18n config for UI chrome + app frontend strings (server-injected). */
227
+ i18nConfig?: ClientI18nConfig;
228
+ }
@@ -0,0 +1,10 @@
1
+ import clsx, { ClassValue } from 'clsx';
2
+
3
+ /**
4
+ * Utility function to combine class names
5
+ * @param classes Class names to combine
6
+ * @returns Combined class name string
7
+ */
8
+ export function cn(...classes: ClassValue[]): string {
9
+ return clsx(classes);
10
+ }
@@ -0,0 +1,45 @@
1
+ import type { CSSProperties } from 'react';
2
+
3
+ interface ColumnMediaSizeOptions {
4
+ width?: number | string;
5
+ height?: number | string;
6
+ ratio?: string;
7
+ circular?: boolean;
8
+ }
9
+
10
+ /**
11
+ * Dimensions for image/media/video column thumbnails.
12
+ * Circular columns always render as a true square (1:1) so rounded-full clips a circle.
13
+ */
14
+ export function getColumnMediaDimensions(
15
+ column: ColumnMediaSizeOptions,
16
+ defaultSize: number | string = 40,
17
+ ): CSSProperties {
18
+ if (column.circular) {
19
+ const raw = column.width ?? column.height ?? defaultSize;
20
+ const size = typeof raw === 'number' ? `${raw}px` : raw;
21
+ return {
22
+ width: size,
23
+ height: size,
24
+ minWidth: size,
25
+ minHeight: size,
26
+ flexShrink: 0,
27
+ aspectRatio: '1 / 1',
28
+ };
29
+ }
30
+
31
+ const ratio = column.ratio || '16/9';
32
+
33
+ if (column.width) {
34
+ const w = typeof column.width === 'number' ? `${column.width}px` : column.width;
35
+ return { width: w, minWidth: w, flexShrink: 0, aspectRatio: ratio };
36
+ }
37
+
38
+ if (column.height) {
39
+ const h = typeof column.height === 'number' ? `${column.height}px` : column.height;
40
+ return { height: h, minHeight: h, flexShrink: 0, aspectRatio: ratio };
41
+ }
42
+
43
+ const w = typeof defaultSize === 'number' ? `${defaultSize}px` : defaultSize;
44
+ return { width: w, minWidth: w, flexShrink: 0, aspectRatio: ratio };
45
+ }
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Column visibility storage utilities for managing column visibility preferences in localStorage
3
+ */
4
+ export const columnVisibilityStorage = {
5
+ /**
6
+ * Get hidden columns for a resource
7
+ * @param resourceKey Unique identifier for the resource (e.g., 'users', 'users_posts')
8
+ * @returns Array of hidden column names, or null if not found (never been set)
9
+ */
10
+ getHiddenColumns(resourceKey: string): string[] | null {
11
+ try {
12
+ const key = `kratosjs_column_visibility_${resourceKey}`;
13
+ const stored = localStorage.getItem(key);
14
+ if (stored === null) {
15
+ return null;
16
+ }
17
+ const parsed = JSON.parse(stored);
18
+ if (Array.isArray(parsed)) {
19
+ return parsed;
20
+ }
21
+ return null;
22
+ } catch (error) {
23
+ console.warn('Failed to parse column visibility from localStorage:', error);
24
+ return null;
25
+ }
26
+ },
27
+
28
+ /**
29
+ * Set hidden columns for a resource
30
+ * @param resourceKey Unique identifier for the resource
31
+ * @param hiddenColumns Array of column names that should be hidden
32
+ */
33
+ setHiddenColumns(resourceKey: string, hiddenColumns: string[]): void {
34
+ try {
35
+ const key = `kratosjs_column_visibility_${resourceKey}`;
36
+ localStorage.setItem(key, JSON.stringify(hiddenColumns));
37
+ } catch (error) {
38
+ // Handle quota exceeded or other localStorage errors
39
+ if (error instanceof Error && error.name === 'QuotaExceededError') {
40
+ console.warn('localStorage quota exceeded, column visibility preferences not saved');
41
+ } else {
42
+ console.warn('Failed to save column visibility to localStorage:', error);
43
+ }
44
+ }
45
+ },
46
+
47
+ /**
48
+ * Clear stored column visibility preferences for a resource
49
+ * @param resourceKey Unique identifier for the resource
50
+ */
51
+ clearHiddenColumns(resourceKey: string): void {
52
+ const key = `kratosjs_column_visibility_${resourceKey}`;
53
+ localStorage.removeItem(key);
54
+ },
55
+ };
@@ -0,0 +1,35 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import type { FieldErrors } from 'react-hook-form';
3
+ import { getFieldError } from './fieldErrors';
4
+
5
+ describe('getFieldError', () => {
6
+ it('resolves a flat field error', () => {
7
+ const errors = { email: { type: 'required', message: 'Required' } } as unknown as FieldErrors;
8
+ expect(getFieldError(errors, 'email')?.message).toBe('Required');
9
+ });
10
+
11
+ it('resolves a nested array (repeater row) error by dotted path', () => {
12
+ const errors = {
13
+ items: [{ name: { type: 'required', message: 'Row name required' } }],
14
+ } as unknown as FieldErrors;
15
+ expect(getFieldError(errors, 'items.0.name')?.message).toBe('Row name required');
16
+ expect(getFieldError(errors, 'items[0].name')?.message).toBe('Row name required');
17
+ });
18
+
19
+ it('returns undefined for a missing path', () => {
20
+ const errors = { items: [{ name: { type: 'min', message: 'x' } }] } as unknown as FieldErrors;
21
+ expect(getFieldError(errors, 'items.1.name')).toBeUndefined();
22
+ expect(getFieldError(errors, 'missing')).toBeUndefined();
23
+ });
24
+
25
+ it('does not treat a container node (array/object) as a field error', () => {
26
+ const errors = { items: [{ name: { type: 'required', message: 'x' } }] } as unknown as FieldErrors;
27
+ // `items` itself is the array container, not a leaf field error
28
+ expect(getFieldError(errors, 'items')).toBeUndefined();
29
+ });
30
+
31
+ it('is safe with undefined inputs', () => {
32
+ expect(getFieldError(undefined, 'a')).toBeUndefined();
33
+ expect(getFieldError({} as FieldErrors, undefined)).toBeUndefined();
34
+ });
35
+ });
@@ -0,0 +1,27 @@
1
+ import type { FieldErrors, FieldError } from 'react-hook-form';
2
+
3
+ /**
4
+ * Resolve a React Hook Form error by its (possibly nested) field-name path.
5
+ *
6
+ * RHF stores errors for nested / array fields as nested objects — e.g. a field
7
+ * registered as `items.0.name` lives at `errors.items[0].name`, NOT at the flat
8
+ * key `errors['items.0.name']`. Field components therefore can't find the error
9
+ * for a Repeater row (or any dotted name) with a plain `errors[name]` lookup.
10
+ *
11
+ * This walks the dot/bracket path so both flat names (`email`) and nested ones
12
+ * (`items.0.name`, `items[0].name`) resolve correctly.
13
+ */
14
+ export function getFieldError(errors: FieldErrors | undefined, name: string | undefined): FieldError | undefined {
15
+ if (!errors || !name) return undefined;
16
+
17
+ const segments = name.split(/[.[\]]+/).filter(Boolean);
18
+ let current: any = errors;
19
+ for (const segment of segments) {
20
+ if (current == null) return undefined;
21
+ current = current[segment];
22
+ }
23
+
24
+ // A resolved node is an error only when it carries a `type`/`message`; nested
25
+ // containers (e.g. the array node `errors.items`) are not field errors.
26
+ return current && (current.type || current.message) ? (current as FieldError) : undefined;
27
+ }