@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
package/src/index.ts ADDED
@@ -0,0 +1,244 @@
1
+ // Main exports
2
+ export { FormRenderer } from './FormRenderer';
3
+ export { FieldRenderer } from './FieldRenderer';
4
+
5
+ // Plugin-author API
6
+ export { definePluginClient, mergePluginClients } from './plugin';
7
+ export type { KratosPluginClient, MergedPluginRegistries } from './plugin';
8
+
9
+ // App entry (mount the admin SPA)
10
+ export { mountAdminPanel } from './app';
11
+ export type { MountAdminPanelOptions } from './app';
12
+
13
+ // Field registry
14
+ export { FieldRegistryProvider, FieldRegistryContext, useFieldRegistry } from './contexts/FieldRegistryContext';
15
+ export type { FieldRegistryProviderProps } from './contexts/FieldRegistryContext';
16
+
17
+ // Hooks
18
+ export { useValidation } from './hooks/useValidation';
19
+
20
+ // Field utilities (for custom field components)
21
+ export { getFieldError } from './utils/fieldErrors';
22
+
23
+ // HTTP / API layer
24
+ export { ApiError, apiFetch, apiGet, apiPost } from './api/http';
25
+ export { TableApiClient } from './api/tableApi';
26
+ export type { QueryParams, QueryResult, PaginationMeta } from './api/tableApi';
27
+ export { executeAction, executeBulkAction } from './api/actionsApi';
28
+ export type { ActionResult } from './api/actionsApi';
29
+ export * as resourceApi from './api/resourceApi';
30
+ export { authenticatedFetch } from './api/authenticatedFetch';
31
+ export { deriveApiBaseUrl, resourceSlugFromUrl } from './api/urls';
32
+
33
+ // Condition / serialized-function runtime
34
+ export { evaluateCondition, evaluateConditionAst } from './runtime/conditions';
35
+ export type { Condition, ConditionAst, ConditionOperator } from './runtime/conditions';
36
+ export { executeSerializedFunction, compileSerializedFunction } from './runtime/serializedFunctions';
37
+
38
+ // UI primitives (stable styling contract for plugin authors)
39
+ export {
40
+ Button,
41
+ IconButton,
42
+ Input,
43
+ Textarea,
44
+ Select,
45
+ Label,
46
+ Badge,
47
+ Card,
48
+ Spinner,
49
+ EmptyState,
50
+ ErrorAlert,
51
+ ToastProvider,
52
+ useToast,
53
+ ConfirmProvider,
54
+ useConfirm,
55
+ } from './components/ui';
56
+ export type {
57
+ ButtonProps,
58
+ IconButtonProps,
59
+ ButtonVariant,
60
+ ButtonSize,
61
+ InputProps,
62
+ TextareaProps,
63
+ SelectProps,
64
+ LabelProps,
65
+ BadgeProps,
66
+ BadgeVariant,
67
+ CardProps,
68
+ SpinnerProps,
69
+ EmptyStateProps,
70
+ ErrorAlertProps,
71
+ ToastApi,
72
+ ToastOptions,
73
+ ToastVariant,
74
+ ConfirmOptions,
75
+ } from './components/ui';
76
+ export { ErrorBoundary } from './components/errors/ErrorBoundary';
77
+ export type { ErrorBoundaryProps } from './components/errors/ErrorBoundary';
78
+
79
+ // Filter Components
80
+ export { QueryBuilderFilterComponent } from './components/filters/QueryBuilderFilterComponent';
81
+ export { CustomFilterComponent } from './components/filters/CustomFilterComponent';
82
+
83
+ // Types
84
+ export type {
85
+ FieldProps,
86
+ FieldComponent,
87
+ FieldRegistry,
88
+ FormRendererProps,
89
+ FieldRendererProps,
90
+ RHFValidationRules,
91
+ SerializedRelation,
92
+ } from './types';
93
+
94
+ // Built-in field components (for custom rendering or extending)
95
+ export { TextInputField } from './components/TextInputField';
96
+ export { SelectField } from './components/SelectField';
97
+ export { TextareaField } from './components/TextareaField';
98
+ export { CheckboxField } from './components/CheckboxField';
99
+ export { ToggleField } from './components/ToggleField';
100
+ export { RadioField } from './components/RadioField';
101
+ export { DateTimePickerField } from './components/DateTimePickerField';
102
+ export { ColorPickerField } from './components/ColorPickerField';
103
+ export { RepeaterField } from './components/RepeaterField';
104
+ export { HiddenField } from './components/HiddenField';
105
+ export { FileUploadField } from './components/FileUploadField';
106
+ export { RichEditorField } from './components/RichEditorField';
107
+ export { SectionField } from './components/SectionField';
108
+ export { GroupField } from './components/GroupField';
109
+ export { HintDisplay } from './components/utils/HintDisplay';
110
+ export type { HintDisplayProps } from './components/utils/HintDisplay';
111
+ export { ViewFieldWrapper } from './components/utils/ViewFieldWrapper';
112
+ export type { ViewFieldWrapperProps } from './components/utils/ViewFieldWrapper';
113
+
114
+ // Utilities
115
+ export { cn } from './utils/classNames';
116
+
117
+ // Icon component and types
118
+ export { Icon } from './components/utils/Icon';
119
+ export type { IconName, IconProps } from './components/utils/Icon';
120
+ // Re-export all Lucide icons for convenience
121
+ export * from 'lucide-react';
122
+
123
+ // Table
124
+ export { TableRenderer } from './TableRenderer';
125
+ export type { TableRendererProps } from './TableRenderer';
126
+ export { useTableContext } from './table/TableContext';
127
+ export type { TableContextValue } from './table/TableContext';
128
+
129
+ // Modals
130
+ export { ViewModal } from './components/ViewModal';
131
+ export { ResourceFormModal } from './components/modals/ResourceFormModal';
132
+ export type { ResourceFormModalProps } from './components/modals/ResourceFormModal';
133
+ export { RelationCreateModal } from './components/modals/RelationCreateModal';
134
+ export { ActionFormModal } from './components/ActionFormModal';
135
+ export { ModalDrawer } from './components/ModalDrawer';
136
+ export { useResourceForm } from './components/modals/useResourceForm';
137
+ export type { UseResourceFormOptions, ResourceFormApi, ResourceFormMode } from './components/modals/useResourceForm';
138
+
139
+ // Table context
140
+ export { ColumnRegistryProvider, useColumnRegistry } from './contexts/ColumnRegistryContext';
141
+ export type { ColumnRegistry, ColumnComponent } from './contexts/ColumnRegistryContext';
142
+
143
+ // Modal context
144
+ export { ResourceModalProvider, useResourceModal } from './contexts/ResourceModalContext';
145
+ export type { ModalState } from './contexts/ResourceModalContext';
146
+
147
+ // Panel metadata context
148
+ export { PanelMetadataProvider, usePanelMetadata } from './contexts/PanelMetadataContext';
149
+ export type { PageMetadata } from './contexts/PanelMetadataContext';
150
+
151
+ // Table column components (for custom rendering or extending)
152
+ export { TextColumnComponent } from './components/columns/TextColumnComponent';
153
+ export type { ColumnProps } from './components/columns/TextColumnComponent';
154
+ export { IconColumnComponent } from './components/columns/IconColumnComponent';
155
+ export { ImageColumnComponent } from './components/columns/ImageColumnComponent';
156
+ export { VideoColumnComponent } from './components/columns/VideoColumnComponent';
157
+ export { MediaColumnComponent } from './components/columns/MediaColumnComponent';
158
+ export { ColorColumnComponent } from './components/columns/ColorColumnComponent';
159
+ export { TagsColumnComponent } from './components/columns/TagsColumnComponent';
160
+ export { ViewColumnComponent } from './components/columns/ViewColumnComponent';
161
+ export { CheckboxColumnComponent } from './components/columns/CheckboxColumnComponent';
162
+ export { ToggleColumnComponent } from './components/columns/ToggleColumnComponent';
163
+ export { SelectColumnComponent } from './components/columns/SelectColumnComponent';
164
+ export { TextInputColumnComponent } from './components/columns/TextInputColumnComponent';
165
+
166
+ // AdminPanel component
167
+ export { AdminPanel } from './components/AdminPanel';
168
+ export type { AdminPanelProps, BlockRegistry } from './types';
169
+
170
+ // Internationalization (i18n)
171
+ export {
172
+ I18nProvider,
173
+ useI18nContext,
174
+ useTranslation,
175
+ useLocale,
176
+ useFormatter,
177
+ LocaleSwitcher,
178
+ getActiveLocale,
179
+ translate,
180
+ buildClientI18n,
181
+ } from './i18n';
182
+ export type {
183
+ I18nContextValue,
184
+ I18nProviderProps,
185
+ ClientI18nConfig,
186
+ ClientTranslations,
187
+ LocaleSwitcherProps,
188
+ } from './i18n';
189
+
190
+ // Auth components
191
+ export { AuthProvider, useAuth } from './auth/AuthContext';
192
+ export { LoginPage } from './auth/LoginPage';
193
+ export { ProtectedRoute } from './auth/ProtectedRoute';
194
+ export { AuthApiClient } from './auth/authApiClient';
195
+ export type {
196
+ AuthUser,
197
+ AuthProvider as AuthProviderType,
198
+ AuthTokens,
199
+ LoginCredentials,
200
+ LoginResult,
201
+ PendingChallenge,
202
+ AuthChallengeProps,
203
+ AuthChallengeComponent,
204
+ } from './auth/types';
205
+ export {
206
+ AuthChallengeRegistryProvider,
207
+ AuthChallengeRegistryContext,
208
+ useAuthChallengeRegistry,
209
+ } from './contexts/AuthChallengeRegistryContext';
210
+ export type { AuthChallengeRegistry } from './contexts/AuthChallengeRegistryContext';
211
+
212
+ // Widget exports
213
+ export { WidgetRegistryProvider, useWidgetRegistry } from './contexts/WidgetRegistryContext';
214
+ export { StatsWidget } from './components/widgets/StatsWidget';
215
+ export { ChartWidget } from './components/widgets/ChartWidget';
216
+ export { WidgetRenderer } from './components/widgets/WidgetRenderer';
217
+ export type { WidgetComponentProps } from './contexts/WidgetRegistryContext';
218
+ export type { StatsWidgetProps } from './components/widgets/StatsWidget';
219
+ export type { ChartWidgetProps } from './components/widgets/ChartWidget';
220
+ export type { WidgetRendererProps } from './components/widgets/WidgetRenderer';
221
+
222
+ // Slots (additive UI injection points)
223
+ export { Slot, SlotCluster, renderSlot, SLOT_NAMES } from './slots';
224
+ export type {
225
+ SlotProps,
226
+ SlotClusterProps,
227
+ SlotName,
228
+ BuiltInSlotName,
229
+ SlotContext,
230
+ SlotRender,
231
+ SlotContribution,
232
+ SlotMap,
233
+ ResolvedSlots,
234
+ } from './slots';
235
+ export { SlotRegistryProvider, SlotRegistryContext, useSlot, useSlotRegistry } from './contexts/SlotRegistryContext';
236
+ export type { SlotRegistryProviderProps } from './contexts/SlotRegistryContext';
237
+
238
+ // Block registry (custom blocks)
239
+ export { BlockRegistryProvider, useBlockRegistry } from './contexts/BlockRegistryContext';
240
+ export type {
241
+ CustomBlockComponentProps,
242
+ CustomBlockComponent,
243
+ BlockRegistry as BlockRegistryType,
244
+ } from './contexts/BlockRegistryContext';
@@ -0,0 +1,205 @@
1
+ import React, { useState, useEffect, useCallback } from 'react';
2
+ import { useParams, useNavigate, useLocation } from 'react-router-dom';
3
+ import { Loader2 } from 'lucide-react';
4
+ import { SerializedTable } from '@maxal_studio/kratosjs';
5
+ import { TableRenderer } from '../TableRenderer';
6
+ import { authenticatedFetch } from '../api/authenticatedFetch';
7
+ import { useResourceModal } from '../contexts/ResourceModalContext';
8
+ import { useTableRefresh } from '../contexts/TableRefreshContext';
9
+ import { PillButton } from '../components/ui/PillButton';
10
+ import { translate } from '../i18n/activeLocale';
11
+
12
+ export interface ResourceListPageProps {
13
+ apiBaseUrl: string;
14
+ resourceSlug: string;
15
+ resourceName: string;
16
+ pluralLabel: string;
17
+ }
18
+
19
+ export function ResourceListPage({ apiBaseUrl, resourceSlug, resourceName, pluralLabel }: ResourceListPageProps) {
20
+ const navigate = useNavigate();
21
+ const location = useLocation();
22
+ const { openModal, closeAllModals, clearModalsForResource } = useResourceModal();
23
+ const [tableSchema, setTableSchema] = useState<SerializedTable | null>(null);
24
+ // Track which resource the current tableSchema belongs to, to avoid mismatches on navigation
25
+ const [tableSchemaResource, setTableSchemaResource] = useState<string | null>(null);
26
+ const [canCreate, setCanCreate] = useState<boolean>(true);
27
+ const [canEdit, setCanEdit] = useState<boolean>(true);
28
+ const [canDelete, setCanDelete] = useState<boolean>(true);
29
+ const [canView, setCanView] = useState<boolean>(true);
30
+ const [loading, setLoading] = useState(true);
31
+ const [error, setError] = useState<string | null>(null);
32
+ const [refreshKey, setRefreshKey] = useState(0);
33
+ const { registerRefresh } = useTableRefresh();
34
+
35
+ // Register refresh callback for this resource
36
+ useEffect(() => {
37
+ const unregister = registerRefresh(resourceSlug, () => {
38
+ setRefreshKey(prev => prev + 1);
39
+ });
40
+ return unregister;
41
+ }, [resourceSlug, registerRefresh]);
42
+
43
+ // Parse route to determine which modal to show via context
44
+ // This only manages modals for THIS resource (URL-based modals)
45
+ useEffect(() => {
46
+ const pathParts = location.pathname.split('/').filter(Boolean);
47
+ const resourceIndex = pathParts.indexOf(resourceSlug);
48
+
49
+ if (resourceIndex === -1) {
50
+ // Not on this resource page anymore, clear only this resource's modals
51
+ clearModalsForResource(resourceSlug);
52
+ return;
53
+ }
54
+
55
+ const nextPart = pathParts[resourceIndex + 1];
56
+ const thirdPart = pathParts[resourceIndex + 2];
57
+
58
+ // Check for edit route: /resourceSlug/:id/edit
59
+ if (nextPart && thirdPart === 'edit') {
60
+ if (canEdit) {
61
+ openModal(resourceSlug, 'edit', nextPart);
62
+ }
63
+ } else if (nextPart === 'create') {
64
+ // Check for create route: /resourceSlug/create
65
+ if (canCreate) {
66
+ openModal(resourceSlug, 'create');
67
+ }
68
+ } else if (nextPart && nextPart !== 'create' && nextPart !== 'edit') {
69
+ // It's an ID for view: /resourceSlug/:id
70
+ if (canView) {
71
+ openModal(resourceSlug, 'view', nextPart);
72
+ }
73
+ } else {
74
+ // Just the resource slug, no modals in URL: /resourceSlug
75
+ // Clear only this resource's URL-based modals (keeps cross-resource modals open)
76
+ clearModalsForResource(resourceSlug);
77
+ }
78
+ // location.key is included so the effect re-fires even when the pathname
79
+ // hasn't changed from React Router's perspective — this happens after a
80
+ // replaceState (back/breadcrumb) when the user clicks the same row again.
81
+ // navigate() always produces a new location.key, replaceState never does.
82
+ }, [location.pathname, location.key, resourceSlug, canCreate, canEdit, canView, openModal, clearModalsForResource]);
83
+
84
+ // Fetch table schema
85
+ useEffect(() => {
86
+ const fetchTableSchema = async () => {
87
+ setError(null);
88
+ try {
89
+ const response = await authenticatedFetch(
90
+ `${apiBaseUrl}/${resourceSlug}/schema/table`,
91
+ {
92
+ headers: {
93
+ 'Content-Type': 'application/json',
94
+ },
95
+ },
96
+ apiBaseUrl,
97
+ );
98
+ if (!response.ok) {
99
+ if (response.status === 401) {
100
+ throw new Error('Unauthorized - Please login again');
101
+ }
102
+ const error = await response.json();
103
+ throw new Error(`Failed to fetch table schema: ${error.message || response.statusText}`);
104
+ }
105
+ const data = await response.json();
106
+ setTableSchema(data.schema);
107
+ setTableSchemaResource(resourceSlug);
108
+ // Extract canCreate, canEdit, canDelete, and canView from API response
109
+ setCanCreate(data.canCreate !== false); // Default to true if undefined
110
+ setCanEdit(data.canEdit !== false); // Default to true if undefined
111
+ setCanDelete(data.canDelete !== false); // Default to true if undefined
112
+ setCanView(data.canView !== false); // Default to true if undefined
113
+ } catch (err) {
114
+ setError(err instanceof Error ? err.message : translate('core:error.load_schema'));
115
+ } finally {
116
+ setLoading(false);
117
+ }
118
+ };
119
+
120
+ if (resourceSlug) {
121
+ // Set loading and clear schema together to prevent race conditions
122
+ // This prevents TableRenderer from rendering with mismatched schema/resourceKey
123
+ setLoading(true);
124
+ setTableSchema(null);
125
+ setTableSchemaResource(null);
126
+ fetchTableSchema();
127
+ }
128
+ }, [apiBaseUrl, resourceSlug]);
129
+
130
+ // Handlers for table actions - navigate to update URL (these are always same-resource)
131
+ const handleCreateClick = () => {
132
+ navigate(`/${resourceSlug}/create`);
133
+ };
134
+
135
+ const handleViewClick = (rowId: any) => {
136
+ navigate(`/${resourceSlug}/${rowId}`);
137
+ };
138
+
139
+ const handleEditClick = (rowId: any) => {
140
+ navigate(`/${resourceSlug}/${rowId}/edit`);
141
+ };
142
+
143
+ // Guard against rendering a schema that belongs to a previous resource
144
+ if (tableSchema && tableSchemaResource !== resourceSlug) {
145
+ return (
146
+ <div className="flex items-center justify-center py-12">
147
+ <Loader2 className="w-8 h-8 text-accent animate-spin" />
148
+ <span className="ml-3 text-fg-secondary">{translate('core:common.loading_ellipsis')}</span>
149
+ </div>
150
+ );
151
+ }
152
+
153
+ if (loading) {
154
+ return (
155
+ <div className="flex items-center justify-center py-12">
156
+ <Loader2 className="w-8 h-8 text-accent animate-spin" />
157
+ <span className="ml-3 text-fg-secondary">{translate('core:common.loading_ellipsis')}</span>
158
+ </div>
159
+ );
160
+ }
161
+
162
+ if (error) {
163
+ return (
164
+ <div className="">
165
+ <div className="text-center py-12">
166
+ <p className="text-red-600 mb-4">{error}</p>
167
+ <PillButton variant="primary" onClick={() => window.location.reload()}>
168
+ {translate('core:common.retry')}
169
+ </PillButton>
170
+ </div>
171
+ </div>
172
+ );
173
+ }
174
+
175
+ if (!tableSchema) {
176
+ return (
177
+ <div className="">
178
+ <div className="text-center py-12 text-fg-secondary">{translate('core:state.no_table_schema')}</div>
179
+ </div>
180
+ );
181
+ }
182
+
183
+ return (
184
+ <>
185
+ <div className="w-full max-w-7xl mx-auto">
186
+ <div className="w-full">
187
+ <TableRenderer
188
+ isResource={true}
189
+ schema={tableSchema}
190
+ apiUrl={`${apiBaseUrl}/${resourceSlug}`}
191
+ apiBaseUrl={apiBaseUrl}
192
+ onCreateClick={canCreate ? handleCreateClick : undefined}
193
+ onEditClick={canEdit ? handleEditClick : undefined}
194
+ onViewClick={canView ? handleViewClick : undefined}
195
+ canCreate={canCreate}
196
+ canEdit={canEdit}
197
+ canDelete={canDelete}
198
+ canView={canView}
199
+ refreshKey={refreshKey}
200
+ />
201
+ </div>
202
+ </div>
203
+ </>
204
+ );
205
+ }
package/src/plugin.ts ADDED
@@ -0,0 +1,110 @@
1
+ import type { FieldRegistry, WidgetRegistry, BlockRegistry } from './types';
2
+ import type { ColumnRegistry } from './contexts/ColumnRegistryContext';
3
+ import type { AuthChallengeRegistry } from './contexts/AuthChallengeRegistryContext';
4
+ import type { RuleDefinition } from '@maxal_studio/kratosjs';
5
+ import type { SlotMap, ResolvedSlots } from './slots/types';
6
+ import { appendSlots, sortSlots } from './slots/mergeSlots';
7
+
8
+ /**
9
+ * Client-side manifest of a KratosJs plugin.
10
+ *
11
+ * Plugins export this from their `/client` entry. Components are statically
12
+ * imported, so the app's bundler (Vite) bundles them with a single shared
13
+ * React instance — no runtime transformation or dynamic URL loading.
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * // my-plugin/src/client/index.ts
18
+ * import { definePluginClient } from '@maxal_studio/kratosjs-react';
19
+ * import StarRatingField from './StarRatingField';
20
+ *
21
+ * export default definePluginClient({
22
+ * name: 'star-rating',
23
+ * fields: { 'star-rating': StarRatingField },
24
+ * });
25
+ * ```
26
+ */
27
+ export interface KratosPluginClient {
28
+ /** Optional plugin name (for debugging) */
29
+ name?: string;
30
+ /** Custom field components keyed by field type (e.g. 'star-rating') */
31
+ fields?: FieldRegistry;
32
+ /** Custom column components keyed by column type */
33
+ columns?: ColumnRegistry;
34
+ /** Custom widget components keyed by widget type */
35
+ widgets?: WidgetRegistry;
36
+ /** Custom page block components keyed by block type */
37
+ blocks?: BlockRegistry;
38
+ /**
39
+ * Challenge UI components keyed by challenge `type` (e.g. '2fa-totp'). Rendered on the
40
+ * login screen when the server returns a matching pending challenge. Pairs with the
41
+ * plugin's server-side `panel.registerAuthChallenge(...)`.
42
+ */
43
+ authChallenges?: AuthChallengeRegistry;
44
+ /**
45
+ * Custom validation rules keyed by rule name (e.g. 'phone'). Authored once as
46
+ * a `RuleDefinition` and referenced from both the plugin's server `register()`
47
+ * (via `panel.registerValidationRule`) and this client manifest, so the rule
48
+ * behaves identically on both sides.
49
+ */
50
+ rules?: Record<string, RuleDefinition>;
51
+ /**
52
+ * UI slot contributions keyed by slot name (e.g. `'header.right'`). Unlike the
53
+ * component registries above (which are 1:1 and override-based), slots are
54
+ * 1:many — every plugin and the app can stack elements into the same slot.
55
+ * A value is a single `SlotContribution` or an array of them.
56
+ *
57
+ * @example
58
+ * slots: {
59
+ * 'header.right': { id: 'docs-link', render: () => <a href="/docs">Docs</a> },
60
+ * }
61
+ */
62
+ slots?: SlotMap;
63
+ }
64
+
65
+ /**
66
+ * Identity helper that provides type inference for plugin client manifests.
67
+ */
68
+ export function definePluginClient(client: KratosPluginClient): KratosPluginClient {
69
+ return client;
70
+ }
71
+
72
+ export interface MergedPluginRegistries {
73
+ fields: FieldRegistry;
74
+ columns: ColumnRegistry;
75
+ widgets: WidgetRegistry;
76
+ blocks: BlockRegistry;
77
+ authChallenges: AuthChallengeRegistry;
78
+ rules: Record<string, RuleDefinition>;
79
+ slots: ResolvedSlots;
80
+ }
81
+
82
+ /**
83
+ * Merge multiple plugin client manifests into flat component registries.
84
+ * Later plugins win on name collisions.
85
+ */
86
+ export function mergePluginClients(plugins: KratosPluginClient[] = []): MergedPluginRegistries {
87
+ const merged: MergedPluginRegistries = {
88
+ fields: {},
89
+ columns: {},
90
+ widgets: {},
91
+ blocks: {},
92
+ authChallenges: {},
93
+ rules: {},
94
+ slots: {},
95
+ };
96
+
97
+ for (const plugin of plugins) {
98
+ Object.assign(merged.fields, plugin.fields ?? {});
99
+ Object.assign(merged.columns, plugin.columns ?? {});
100
+ Object.assign(merged.widgets, plugin.widgets ?? {});
101
+ Object.assign(merged.blocks, plugin.blocks ?? {});
102
+ Object.assign(merged.authChallenges, plugin.authChallenges ?? {});
103
+ Object.assign(merged.rules, plugin.rules ?? {});
104
+ // Slots stack (1:many) rather than override; later plugins append after earlier ones.
105
+ appendSlots(merged.slots, plugin.slots);
106
+ }
107
+
108
+ sortSlots(merged.slots);
109
+ return merged;
110
+ }
@@ -0,0 +1,99 @@
1
+ import { describe, expect, it, vi } from 'vitest';
2
+ import { evaluateCondition } from '../runtime/conditions';
3
+
4
+ describe('evaluateCondition', () => {
5
+ it('returns false for undefined', () => {
6
+ expect(evaluateCondition(undefined, {})).toBe(false);
7
+ });
8
+
9
+ it('returns boolean conditions as-is', () => {
10
+ expect(evaluateCondition(true, {})).toBe(true);
11
+ expect(evaluateCondition(false, {})).toBe(false);
12
+ });
13
+
14
+ it('evaluates a function string using get()', () => {
15
+ const condition = "({ get }) => get('status') === 'draft'";
16
+ expect(evaluateCondition(condition, { status: 'draft' })).toBe(true);
17
+ expect(evaluateCondition(condition, { status: 'published' })).toBe(false);
18
+ });
19
+
20
+ it('supports dot notation in get()', () => {
21
+ const condition = "({ get }) => get('author.name') === 'Jane'";
22
+ expect(evaluateCondition(condition, { author: { name: 'Jane' } })).toBe(true);
23
+ expect(evaluateCondition(condition, { author: null })).toBe(false);
24
+ });
25
+
26
+ it('exposes the operation to function conditions', () => {
27
+ const condition = "({ operation }) => operation === 'edit'";
28
+ expect(evaluateCondition(condition, {}, 'edit')).toBe(true);
29
+ expect(evaluateCondition(condition, {}, 'create')).toBe(false);
30
+ });
31
+
32
+ it('returns false when the function string throws', () => {
33
+ const errorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
34
+ expect(evaluateCondition('({ get }) => { throw new Error("boom"); }', {})).toBe(false);
35
+ expect(errorSpy).toHaveBeenCalled();
36
+ errorSpy.mockRestore();
37
+ });
38
+
39
+ it('returns false for invalid function strings', () => {
40
+ const errorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
41
+ expect(evaluateCondition('this is not js (', {})).toBe(false);
42
+ expect(errorSpy).toHaveBeenCalled();
43
+ errorSpy.mockRestore();
44
+ });
45
+ });
46
+
47
+ describe('evaluateCondition with structured AST', () => {
48
+ it('evaluates simple operators', () => {
49
+ expect(evaluateCondition({ op: 'eq', field: 'status', value: 'draft' }, { status: 'draft' })).toBe(true);
50
+ expect(evaluateCondition({ op: 'ne', field: 'status', value: 'draft' }, { status: 'live' })).toBe(true);
51
+ expect(evaluateCondition({ op: 'truthy', field: 'active' }, { active: 1 })).toBe(true);
52
+ expect(evaluateCondition({ op: 'falsy', field: 'active' }, { active: 0 })).toBe(true);
53
+ expect(evaluateCondition({ op: 'gt', field: 'age', value: 18 }, { age: 21 })).toBe(true);
54
+ expect(evaluateCondition({ op: 'lte', field: 'age', value: 18 }, { age: 18 })).toBe(true);
55
+ });
56
+
57
+ it('evaluates in/nin', () => {
58
+ expect(evaluateCondition({ op: 'in', field: 'role', value: ['admin', 'editor'] }, { role: 'admin' })).toBe(
59
+ true,
60
+ );
61
+ expect(evaluateCondition({ op: 'nin', field: 'role', value: ['admin'] }, { role: 'user' })).toBe(true);
62
+ });
63
+
64
+ it('evaluates the operation operator', () => {
65
+ expect(evaluateCondition({ op: 'operation', value: 'edit' }, {}, 'edit')).toBe(true);
66
+ expect(evaluateCondition({ op: 'operation', value: 'edit' }, {}, 'create')).toBe(false);
67
+ });
68
+
69
+ it('supports dot-notation fields', () => {
70
+ expect(evaluateCondition({ op: 'eq', field: 'author.name', value: 'Jane' }, { author: { name: 'Jane' } })).toBe(
71
+ true,
72
+ );
73
+ });
74
+
75
+ it('combines with all/any/not', () => {
76
+ const cond = {
77
+ all: [
78
+ { op: 'eq' as const, field: 'status', value: 'draft' },
79
+ {
80
+ any: [
81
+ { op: 'eq' as const, field: 'role', value: 'admin' },
82
+ { op: 'truthy' as const, field: 'owner' },
83
+ ],
84
+ },
85
+ ],
86
+ };
87
+ expect(evaluateCondition(cond, { status: 'draft', role: 'admin' })).toBe(true);
88
+ expect(evaluateCondition(cond, { status: 'draft', owner: true })).toBe(true);
89
+ expect(evaluateCondition(cond, { status: 'live', role: 'admin' })).toBe(false);
90
+ expect(evaluateCondition({ not: { op: 'truthy', field: 'x' } }, { x: false })).toBe(true);
91
+ });
92
+
93
+ it('returns false for unknown operators', () => {
94
+ const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
95
+ expect(evaluateCondition({ op: 'wat' as never, field: 'x' }, { x: 1 })).toBe(false);
96
+ expect(warnSpy).toHaveBeenCalled();
97
+ warnSpy.mockRestore();
98
+ });
99
+ });