@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.
- package/README.md +44 -0
- package/dist/FieldRenderer.d.ts +13 -0
- package/dist/FieldRenderer.js +62 -0
- package/dist/FormRenderer.d.ts +7 -0
- package/dist/FormRenderer.js +78 -0
- package/dist/TableRenderer.d.ts +2 -0
- package/dist/TableRenderer.js +1 -0
- package/dist/api/actionsApi.d.ts +23 -0
- package/dist/api/actionsApi.js +46 -0
- package/dist/api/authenticatedFetch.d.ts +8 -0
- package/dist/api/authenticatedFetch.js +31 -0
- package/dist/api/exportApi.d.ts +18 -0
- package/dist/api/exportApi.js +50 -0
- package/dist/api/http.d.ts +24 -0
- package/dist/api/http.js +52 -0
- package/dist/api/resourceApi.d.ts +37 -0
- package/dist/api/resourceApi.js +52 -0
- package/dist/api/tableApi.d.ts +83 -0
- package/dist/api/tableApi.js +51 -0
- package/dist/api/urls.d.ts +19 -0
- package/dist/api/urls.js +46 -0
- package/dist/app.d.ts +101 -0
- package/dist/app.js +89 -0
- package/dist/auth/AuthContext.d.ts +22 -0
- package/dist/auth/AuthContext.js +147 -0
- package/dist/auth/LoginPage.d.ts +10 -0
- package/dist/auth/LoginPage.js +179 -0
- package/dist/auth/ProtectedRoute.d.ts +12 -0
- package/dist/auth/ProtectedRoute.js +22 -0
- package/dist/auth/authApiClient.d.ts +24 -0
- package/dist/auth/authApiClient.js +95 -0
- package/dist/auth/types.d.ts +103 -0
- package/dist/auth/types.js +1 -0
- package/dist/components/ActionFormModal.d.ts +22 -0
- package/dist/components/ActionFormModal.js +8 -0
- package/dist/components/AdminPanel.d.ts +11 -0
- package/dist/components/AdminPanel.js +194 -0
- package/dist/components/Checkbox.d.ts +10 -0
- package/dist/components/Checkbox.js +8 -0
- package/dist/components/CheckboxField.d.ts +7 -0
- package/dist/components/CheckboxField.js +26 -0
- package/dist/components/ColorPickerField.d.ts +7 -0
- package/dist/components/ColorPickerField.js +26 -0
- package/dist/components/DateTimePickerField.d.ts +7 -0
- package/dist/components/DateTimePickerField.js +64 -0
- package/dist/components/FileUploadField.d.ts +9 -0
- package/dist/components/FileUploadField.js +478 -0
- package/dist/components/GlobalSearch.d.ts +22 -0
- package/dist/components/GlobalSearch.js +181 -0
- package/dist/components/GroupField.d.ts +7 -0
- package/dist/components/GroupField.js +23 -0
- package/dist/components/HiddenField.d.ts +3 -0
- package/dist/components/HiddenField.js +10 -0
- package/dist/components/ModalBreadcrumb.d.ts +5 -0
- package/dist/components/ModalBreadcrumb.js +33 -0
- package/dist/components/ModalDrawer.d.ts +15 -0
- package/dist/components/ModalDrawer.js +40 -0
- package/dist/components/RadioField.d.ts +7 -0
- package/dist/components/RadioField.js +26 -0
- package/dist/components/RepeaterField.d.ts +3 -0
- package/dist/components/RepeaterField.js +191 -0
- package/dist/components/ResourceModalRenderer.d.ts +10 -0
- package/dist/components/ResourceModalRenderer.js +80 -0
- package/dist/components/RichEditorField.d.ts +3 -0
- package/dist/components/RichEditorField.js +655 -0
- package/dist/components/SectionField.d.ts +9 -0
- package/dist/components/SectionField.js +111 -0
- package/dist/components/SelectField.d.ts +8 -0
- package/dist/components/SelectField.js +523 -0
- package/dist/components/TabsField.d.ts +10 -0
- package/dist/components/TabsField.js +214 -0
- package/dist/components/TagsInputField.d.ts +7 -0
- package/dist/components/TagsInputField.js +172 -0
- package/dist/components/TextInputField.d.ts +7 -0
- package/dist/components/TextInputField.js +44 -0
- package/dist/components/TextareaField.d.ts +7 -0
- package/dist/components/TextareaField.js +31 -0
- package/dist/components/ToggleField.d.ts +7 -0
- package/dist/components/ToggleField.js +57 -0
- package/dist/components/ViewModal.d.ts +25 -0
- package/dist/components/ViewModal.js +159 -0
- package/dist/components/blocks/BlockRenderer.d.ts +7 -0
- package/dist/components/blocks/BlockRenderer.js +36 -0
- package/dist/components/blocks/FormBlockRenderer.d.ts +6 -0
- package/dist/components/blocks/FormBlockRenderer.js +110 -0
- package/dist/components/blocks/TableBlockRenderer.d.ts +6 -0
- package/dist/components/blocks/TableBlockRenderer.js +12 -0
- package/dist/components/blocks/TabsBlockRenderer.d.ts +7 -0
- package/dist/components/blocks/TabsBlockRenderer.js +11 -0
- package/dist/components/blocks/WidgetBlockRenderer.d.ts +6 -0
- package/dist/components/blocks/WidgetBlockRenderer.js +11 -0
- package/dist/components/columns/CheckboxColumnComponent.d.ts +6 -0
- package/dist/components/columns/CheckboxColumnComponent.js +21 -0
- package/dist/components/columns/ColorColumnComponent.d.ts +3 -0
- package/dist/components/columns/ColorColumnComponent.js +11 -0
- package/dist/components/columns/DeeplinkWrapper.d.ts +15 -0
- package/dist/components/columns/DeeplinkWrapper.js +85 -0
- package/dist/components/columns/IconColumnComponent.d.ts +3 -0
- package/dist/components/columns/IconColumnComponent.js +52 -0
- package/dist/components/columns/ImageColumnComponent.d.ts +3 -0
- package/dist/components/columns/ImageColumnComponent.js +98 -0
- package/dist/components/columns/MediaColumnComponent.d.ts +3 -0
- package/dist/components/columns/MediaColumnComponent.js +160 -0
- package/dist/components/columns/SelectColumnComponent.d.ts +6 -0
- package/dist/components/columns/SelectColumnComponent.js +26 -0
- package/dist/components/columns/TagsColumnComponent.d.ts +3 -0
- package/dist/components/columns/TagsColumnComponent.js +18 -0
- package/dist/components/columns/TextColumnComponent.d.ts +11 -0
- package/dist/components/columns/TextColumnComponent.js +107 -0
- package/dist/components/columns/TextInputColumnComponent.d.ts +6 -0
- package/dist/components/columns/TextInputColumnComponent.js +18 -0
- package/dist/components/columns/ToggleColumnComponent.d.ts +6 -0
- package/dist/components/columns/ToggleColumnComponent.js +25 -0
- package/dist/components/columns/VideoColumnComponent.d.ts +3 -0
- package/dist/components/columns/VideoColumnComponent.js +125 -0
- package/dist/components/columns/ViewColumnComponent.d.ts +3 -0
- package/dist/components/columns/ViewColumnComponent.js +7 -0
- package/dist/components/errors/ErrorBoundary.d.ts +23 -0
- package/dist/components/errors/ErrorBoundary.js +33 -0
- package/dist/components/filters/CustomFilterComponent.d.ts +10 -0
- package/dist/components/filters/CustomFilterComponent.js +33 -0
- package/dist/components/filters/DateFilterComponent.d.ts +15 -0
- package/dist/components/filters/DateFilterComponent.js +132 -0
- package/dist/components/filters/QueryBuilderFilterComponent.d.ts +11 -0
- package/dist/components/filters/QueryBuilderFilterComponent.js +200 -0
- package/dist/components/layout/Header.d.ts +10 -0
- package/dist/components/layout/Header.js +70 -0
- package/dist/components/layout/PanelBrandMark.d.ts +8 -0
- package/dist/components/layout/PanelBrandMark.js +28 -0
- package/dist/components/layout/Sidebar.d.ts +35 -0
- package/dist/components/layout/Sidebar.js +125 -0
- package/dist/components/modals/RelationCreateModal.d.ts +19 -0
- package/dist/components/modals/RelationCreateModal.js +57 -0
- package/dist/components/modals/ResourceFormModal.d.ts +37 -0
- package/dist/components/modals/ResourceFormModal.js +44 -0
- package/dist/components/modals/useResourceForm.d.ts +40 -0
- package/dist/components/modals/useResourceForm.js +138 -0
- package/dist/components/modals/view/RecordActions.d.ts +17 -0
- package/dist/components/modals/view/RecordActions.js +16 -0
- package/dist/components/modals/view/RecordDetails.d.ts +13 -0
- package/dist/components/modals/view/RecordDetails.js +29 -0
- package/dist/components/modals/view/RelationPanel.d.ts +18 -0
- package/dist/components/modals/view/RelationPanel.js +16 -0
- package/dist/components/modals/view/RelationTabs.d.ts +32 -0
- package/dist/components/modals/view/RelationTabs.js +42 -0
- package/dist/components/modals/view/useRecordView.d.ts +18 -0
- package/dist/components/modals/view/useRecordView.js +114 -0
- package/dist/components/pages/PageRenderer.d.ts +6 -0
- package/dist/components/pages/PageRenderer.js +107 -0
- package/dist/components/table/ColumnTogglePopup.d.ts +11 -0
- package/dist/components/table/ColumnTogglePopup.js +16 -0
- package/dist/components/table/GridCard.d.ts +21 -0
- package/dist/components/table/GridCard.js +30 -0
- package/dist/components/table/GridView.d.ts +23 -0
- package/dist/components/table/GridView.js +49 -0
- package/dist/components/table/LayoutToggle.d.ts +7 -0
- package/dist/components/table/LayoutToggle.js +9 -0
- package/dist/components/table/TableActionsDropdown.d.ts +13 -0
- package/dist/components/table/TableActionsDropdown.js +46 -0
- package/dist/components/table/TableBulkActions.d.ts +11 -0
- package/dist/components/table/TableBulkActions.js +21 -0
- package/dist/components/table/TableHeader.d.ts +14 -0
- package/dist/components/table/TableHeader.js +23 -0
- package/dist/components/table/TablePagination.d.ts +13 -0
- package/dist/components/table/TablePagination.js +55 -0
- package/dist/components/table/TableRow.d.ts +21 -0
- package/dist/components/table/TableRow.js +32 -0
- package/dist/components/table/TableSearchBar.d.ts +11 -0
- package/dist/components/table/TableSearchBar.js +12 -0
- package/dist/components/table/TableTabs.d.ts +14 -0
- package/dist/components/table/TableTabs.js +8 -0
- package/dist/components/ui/Badge.d.ts +6 -0
- package/dist/components/ui/Badge.js +12 -0
- package/dist/components/ui/Button.d.ts +22 -0
- package/dist/components/ui/Button.js +22 -0
- package/dist/components/ui/Card.d.ts +7 -0
- package/dist/components/ui/Card.js +5 -0
- package/dist/components/ui/ConfirmDialog.d.ts +19 -0
- package/dist/components/ui/ConfirmDialog.js +45 -0
- package/dist/components/ui/EmptyState.d.ts +9 -0
- package/dist/components/ui/EmptyState.js +6 -0
- package/dist/components/ui/ErrorAlert.d.ts +7 -0
- package/dist/components/ui/ErrorAlert.js +9 -0
- package/dist/components/ui/Input.d.ts +11 -0
- package/dist/components/ui/Input.js +10 -0
- package/dist/components/ui/Label.d.ts +5 -0
- package/dist/components/ui/Label.js +5 -0
- package/dist/components/ui/PillButton.d.ts +14 -0
- package/dist/components/ui/PillButton.js +19 -0
- package/dist/components/ui/Select.d.ts +7 -0
- package/dist/components/ui/Select.js +7 -0
- package/dist/components/ui/Spinner.d.ts +8 -0
- package/dist/components/ui/Spinner.js +14 -0
- package/dist/components/ui/Toast.d.ts +21 -0
- package/dist/components/ui/Toast.js +47 -0
- package/dist/components/ui/index.d.ts +24 -0
- package/dist/components/ui/index.js +12 -0
- package/dist/components/utils/HintDisplay.d.ts +11 -0
- package/dist/components/utils/HintDisplay.js +12 -0
- package/dist/components/utils/Icon.d.ts +22 -0
- package/dist/components/utils/Icon.js +22 -0
- package/dist/components/utils/MediaPreviewModal.d.ts +14 -0
- package/dist/components/utils/MediaPreviewModal.js +32 -0
- package/dist/components/utils/ViewFieldWrapper.d.ts +11 -0
- package/dist/components/utils/ViewFieldWrapper.js +9 -0
- package/dist/components/utils/layoutHelpers.d.ts +19 -0
- package/dist/components/utils/layoutHelpers.js +257 -0
- package/dist/components/widgets/ChartWidget.d.ts +16 -0
- package/dist/components/widgets/ChartWidget.js +192 -0
- package/dist/components/widgets/StatsWidget.d.ts +16 -0
- package/dist/components/widgets/StatsWidget.js +39 -0
- package/dist/components/widgets/WidgetRenderer.d.ts +10 -0
- package/dist/components/widgets/WidgetRenderer.js +50 -0
- package/dist/components/widgets/WidgetShell.d.ts +9 -0
- package/dist/components/widgets/WidgetShell.js +7 -0
- package/dist/contexts/AuthChallengeRegistryContext.d.ts +15 -0
- package/dist/contexts/AuthChallengeRegistryContext.js +15 -0
- package/dist/contexts/BlockRegistryContext.d.ts +18 -0
- package/dist/contexts/BlockRegistryContext.js +8 -0
- package/dist/contexts/ColumnRegistryContext.d.ts +8 -0
- package/dist/contexts/ColumnRegistryContext.js +30 -0
- package/dist/contexts/FieldRegistryContext.d.ts +13 -0
- package/dist/contexts/FieldRegistryContext.js +46 -0
- package/dist/contexts/PanelMetadataContext.d.ts +26 -0
- package/dist/contexts/PanelMetadataContext.js +26 -0
- package/dist/contexts/PanelProviders.d.ts +27 -0
- package/dist/contexts/PanelProviders.js +24 -0
- package/dist/contexts/ResourceModalContext.d.ts +26 -0
- package/dist/contexts/ResourceModalContext.js +76 -0
- package/dist/contexts/SlotRegistryContext.d.ts +19 -0
- package/dist/contexts/SlotRegistryContext.js +24 -0
- package/dist/contexts/TableRefreshContext.d.ts +10 -0
- package/dist/contexts/TableRefreshContext.js +30 -0
- package/dist/contexts/WidgetRegistryContext.d.ts +17 -0
- package/dist/contexts/WidgetRegistryContext.js +14 -0
- package/dist/contexts/createRegistryContext.d.ts +19 -0
- package/dist/contexts/createRegistryContext.js +20 -0
- package/dist/hooks/useAfterStateUpdated.d.ts +6 -0
- package/dist/hooks/useAfterStateUpdated.js +62 -0
- package/dist/hooks/useValidation.d.ts +26 -0
- package/dist/hooks/useValidation.js +76 -0
- package/dist/i18n/I18nProvider.d.ts +27 -0
- package/dist/i18n/I18nProvider.js +101 -0
- package/dist/i18n/LocaleSwitcher.d.ts +10 -0
- package/dist/i18n/LocaleSwitcher.js +30 -0
- package/dist/i18n/activeLocale.d.ts +11 -0
- package/dist/i18n/activeLocale.js +34 -0
- package/dist/i18n/buildClientI18n.d.ts +28 -0
- package/dist/i18n/buildClientI18n.js +67 -0
- package/dist/i18n/index.d.ts +11 -0
- package/dist/i18n/index.js +9 -0
- package/dist/i18n/locales/core/en.d.ts +225 -0
- package/dist/i18n/locales/core/en.js +252 -0
- package/dist/i18n/locales/core/index.d.ts +2 -0
- package/dist/i18n/locales/core/index.js +4 -0
- package/dist/i18n/locales/core/sq.d.ts +253 -0
- package/dist/i18n/locales/core/sq.js +255 -0
- package/dist/i18n/useFormatter.d.ts +18 -0
- package/dist/i18n/useFormatter.js +37 -0
- package/dist/i18n/useLocale.d.ts +11 -0
- package/dist/i18n/useLocale.js +11 -0
- package/dist/i18n/useTranslation.d.ts +12 -0
- package/dist/i18n/useTranslation.js +12 -0
- package/dist/index.d.ts +106 -0
- package/dist/index.js +101 -0
- package/dist/pages/ResourceListPage.d.ts +8 -0
- package/dist/pages/ResourceListPage.js +139 -0
- package/dist/plugin.d.ts +79 -0
- package/dist/plugin.js +34 -0
- package/dist/runtime/conditions.d.ts +35 -0
- package/dist/runtime/conditions.js +97 -0
- package/dist/runtime/formTraversal.d.ts +25 -0
- package/dist/runtime/formTraversal.js +37 -0
- package/dist/runtime/serializedFunctions.d.ts +41 -0
- package/dist/runtime/serializedFunctions.js +264 -0
- package/dist/slots/Slot.d.ts +24 -0
- package/dist/slots/Slot.js +29 -0
- package/dist/slots/SlotCluster.d.ts +22 -0
- package/dist/slots/SlotCluster.js +49 -0
- package/dist/slots/index.d.ts +7 -0
- package/dist/slots/index.js +4 -0
- package/dist/slots/mergeSlots.d.ts +18 -0
- package/dist/slots/mergeSlots.js +35 -0
- package/dist/slots/types.d.ts +87 -0
- package/dist/slots/types.js +30 -0
- package/dist/styles.css +1 -0
- package/dist/table/TableContext.d.ts +36 -0
- package/dist/table/TableContext.js +13 -0
- package/dist/table/TableRenderer.d.ts +29 -0
- package/dist/table/TableRenderer.js +159 -0
- package/dist/table/components/FiltersPanel.d.ts +11 -0
- package/dist/table/components/FiltersPanel.js +52 -0
- package/dist/table/components/TableToolbar.d.ts +28 -0
- package/dist/table/components/TableToolbar.js +27 -0
- package/dist/table/components/TableToolbarButton.d.ts +6 -0
- package/dist/table/components/TableToolbarButton.js +9 -0
- package/dist/table/components/TableView.d.ts +12 -0
- package/dist/table/components/TableView.js +21 -0
- package/dist/table/defaultRowActions.d.ts +21 -0
- package/dist/table/defaultRowActions.js +37 -0
- package/dist/table/hooks/useColumnVisibility.d.ts +13 -0
- package/dist/table/hooks/useColumnVisibility.js +59 -0
- package/dist/table/hooks/useEditableRows.d.ts +22 -0
- package/dist/table/hooks/useEditableRows.js +63 -0
- package/dist/table/hooks/useTableActions.d.ts +54 -0
- package/dist/table/hooks/useTableActions.js +313 -0
- package/dist/table/hooks/useTableData.d.ts +28 -0
- package/dist/table/hooks/useTableData.js +63 -0
- package/dist/table/hooks/useTableLayout.d.ts +12 -0
- package/dist/table/hooks/useTableLayout.js +31 -0
- package/dist/table/hooks/useTableQuery.d.ts +29 -0
- package/dist/table/hooks/useTableQuery.js +135 -0
- package/dist/types/index.d.ts +224 -0
- package/dist/types/index.js +6 -0
- package/dist/utils/classNames.d.ts +7 -0
- package/dist/utils/classNames.js +9 -0
- package/dist/utils/columnMediaDimensions.d.ts +13 -0
- package/dist/utils/columnMediaDimensions.js +29 -0
- package/dist/utils/columnVisibilityStorage.d.ts +22 -0
- package/dist/utils/columnVisibilityStorage.js +56 -0
- package/dist/utils/fieldErrors.d.ts +13 -0
- package/dist/utils/fieldErrors.js +25 -0
- package/dist/utils/formatValue.d.ts +28 -0
- package/dist/utils/formatValue.js +109 -0
- package/dist/utils/layoutStorage.d.ts +23 -0
- package/dist/utils/layoutStorage.js +53 -0
- package/dist/utils/redirectHandler.d.ts +7 -0
- package/dist/utils/redirectHandler.js +25 -0
- package/dist/utils/tableFormatters.d.ts +14 -0
- package/dist/utils/tableFormatters.js +93 -0
- package/dist/utils/widgetVisibilityStorage.d.ts +11 -0
- package/dist/utils/widgetVisibilityStorage.js +39 -0
- package/package.json +101 -0
- package/src/FieldRenderer.test.tsx +44 -0
- package/src/FieldRenderer.tsx +104 -0
- package/src/FormRenderer.containers.test.tsx +121 -0
- package/src/FormRenderer.test.tsx +174 -0
- package/src/FormRenderer.tsx +140 -0
- package/src/TableRenderer.tsx +2 -0
- package/src/api/actionsApi.ts +76 -0
- package/src/api/authenticatedFetch.ts +40 -0
- package/src/api/exportApi.ts +66 -0
- package/src/api/http.test.ts +58 -0
- package/src/api/http.ts +68 -0
- package/src/api/resourceApi.ts +88 -0
- package/src/api/tableApi.test.ts +108 -0
- package/src/api/tableApi.ts +107 -0
- package/src/api/urls.ts +50 -0
- package/src/app.test.tsx +67 -0
- package/src/app.tsx +181 -0
- package/src/auth/AuthContext.tsx +188 -0
- package/src/auth/LoginPage.tsx +380 -0
- package/src/auth/ProtectedRoute.tsx +39 -0
- package/src/auth/authApiClient.ts +109 -0
- package/src/auth/authFlow.test.tsx +168 -0
- package/src/auth/types.ts +104 -0
- package/src/components/ActionFormModal.tsx +45 -0
- package/src/components/AdminPanel.tsx +368 -0
- package/src/components/Checkbox.tsx +59 -0
- package/src/components/CheckboxField.tsx +88 -0
- package/src/components/ColorPickerField.tsx +93 -0
- package/src/components/DateTimePickerField.tsx +112 -0
- package/src/components/FileUploadField.tsx +841 -0
- package/src/components/GlobalSearch.tsx +436 -0
- package/src/components/GroupField.tsx +85 -0
- package/src/components/HiddenField.tsx +14 -0
- package/src/components/ModalBreadcrumb.tsx +74 -0
- package/src/components/ModalDrawer.tsx +137 -0
- package/src/components/RadioField.tsx +80 -0
- package/src/components/RepeaterField.tsx +546 -0
- package/src/components/ResourceModalRenderer.tsx +144 -0
- package/src/components/RichEditorField.tsx +942 -0
- package/src/components/SectionField.tsx +242 -0
- package/src/components/SelectField.tsx +843 -0
- package/src/components/TabsField.test.tsx +151 -0
- package/src/components/TabsField.tsx +386 -0
- package/src/components/TagsInputField.tsx +411 -0
- package/src/components/TextInputField.tsx +91 -0
- package/src/components/TextareaField.tsx +110 -0
- package/src/components/ToggleField.tsx +126 -0
- package/src/components/ViewModal.tsx +353 -0
- package/src/components/blocks/BlockRenderer.tsx +56 -0
- package/src/components/blocks/FormBlockRenderer.tsx +160 -0
- package/src/components/blocks/TableBlockRenderer.tsx +33 -0
- package/src/components/blocks/TabsBlockRenderer.tsx +49 -0
- package/src/components/blocks/WidgetBlockRenderer.tsx +19 -0
- package/src/components/columns/CheckboxColumnComponent.tsx +38 -0
- package/src/components/columns/ColorColumnComponent.tsx +23 -0
- package/src/components/columns/CustomColumn.test.tsx +55 -0
- package/src/components/columns/DeeplinkWrapper.tsx +103 -0
- package/src/components/columns/IconColumnComponent.tsx +55 -0
- package/src/components/columns/ImageColumnComponent.tsx +220 -0
- package/src/components/columns/MediaColumnComponent.tsx +294 -0
- package/src/components/columns/SelectColumnComponent.tsx +49 -0
- package/src/components/columns/TagsColumnComponent.tsx +46 -0
- package/src/components/columns/TextColumnComponent.tsx +191 -0
- package/src/components/columns/TextInputColumnComponent.tsx +35 -0
- package/src/components/columns/ToggleColumnComponent.tsx +56 -0
- package/src/components/columns/VideoColumnComponent.tsx +236 -0
- package/src/components/columns/ViewColumnComponent.tsx +9 -0
- package/src/components/errors/ErrorBoundary.tsx +58 -0
- package/src/components/filters/CustomFilterComponent.tsx +130 -0
- package/src/components/filters/DateFilterComponent.tsx +272 -0
- package/src/components/filters/QueryBuilderFilterComponent.tsx +502 -0
- package/src/components/layout/Header.tsx +212 -0
- package/src/components/layout/PanelBrandMark.tsx +61 -0
- package/src/components/layout/Sidebar.tsx +283 -0
- package/src/components/modals/RelationCreateModal.tsx +107 -0
- package/src/components/modals/ResourceFormModal.test.tsx +119 -0
- package/src/components/modals/ResourceFormModal.tsx +128 -0
- package/src/components/modals/useResourceForm.ts +207 -0
- package/src/components/modals/view/RecordActions.tsx +69 -0
- package/src/components/modals/view/RecordDetails.tsx +60 -0
- package/src/components/modals/view/RelationPanel.tsx +76 -0
- package/src/components/modals/view/RelationTabs.tsx +145 -0
- package/src/components/modals/view/useRecordView.ts +134 -0
- package/src/components/pages/PageRenderer.tsx +173 -0
- package/src/components/table/ColumnTogglePopup.tsx +85 -0
- package/src/components/table/GridCard.tsx +155 -0
- package/src/components/table/GridView.tsx +138 -0
- package/src/components/table/LayoutToggle.tsx +24 -0
- package/src/components/table/TableActionsDropdown.tsx +114 -0
- package/src/components/table/TableBulkActions.tsx +65 -0
- package/src/components/table/TableHeader.tsx +96 -0
- package/src/components/table/TablePagination.tsx +169 -0
- package/src/components/table/TableRow.tsx +155 -0
- package/src/components/table/TableSearchBar.tsx +66 -0
- package/src/components/table/TableTabs.tsx +49 -0
- package/src/components/ui/Badge.tsx +30 -0
- package/src/components/ui/Button.test.tsx +78 -0
- package/src/components/ui/Button.tsx +102 -0
- package/src/components/ui/Card.tsx +23 -0
- package/src/components/ui/ConfirmDialog.tsx +112 -0
- package/src/components/ui/EmptyState.tsx +24 -0
- package/src/components/ui/ErrorAlert.tsx +37 -0
- package/src/components/ui/Input.tsx +48 -0
- package/src/components/ui/Label.tsx +15 -0
- package/src/components/ui/PillButton.tsx +72 -0
- package/src/components/ui/Select.tsx +33 -0
- package/src/components/ui/Spinner.tsx +39 -0
- package/src/components/ui/Toast.tsx +105 -0
- package/src/components/ui/index.ts +24 -0
- package/src/components/utils/HintDisplay.tsx +26 -0
- package/src/components/utils/Icon.tsx +36 -0
- package/src/components/utils/MediaPreviewModal.tsx +114 -0
- package/src/components/utils/ViewFieldWrapper.tsx +23 -0
- package/src/components/utils/layoutHelpers.ts +267 -0
- package/src/components/widgets/ChartWidget.tsx +247 -0
- package/src/components/widgets/StatsWidget.tsx +72 -0
- package/src/components/widgets/WidgetRenderer.tsx +108 -0
- package/src/components/widgets/WidgetShell.tsx +37 -0
- package/src/contexts/AuthChallengeRegistryContext.tsx +29 -0
- package/src/contexts/BlockRegistryContext.tsx +28 -0
- package/src/contexts/ColumnRegistryContext.tsx +38 -0
- package/src/contexts/FieldRegistryContext.tsx +56 -0
- package/src/contexts/PanelMetadataContext.tsx +60 -0
- package/src/contexts/PanelProviders.tsx +85 -0
- package/src/contexts/ResourceModalContext.tsx +137 -0
- package/src/contexts/SlotRegistryContext.tsx +35 -0
- package/src/contexts/TableRefreshContext.tsx +44 -0
- package/src/contexts/WidgetRegistryContext.tsx +34 -0
- package/src/contexts/createRegistryContext.tsx +29 -0
- package/src/hooks/useAfterStateUpdated.ts +70 -0
- package/src/hooks/useValidation.test.ts +59 -0
- package/src/hooks/useValidation.ts +95 -0
- package/src/i18n/I18nProvider.tsx +128 -0
- package/src/i18n/LocaleSwitcher.tsx +50 -0
- package/src/i18n/activeLocale.ts +39 -0
- package/src/i18n/buildClientI18n.ts +101 -0
- package/src/i18n/i18n.test.tsx +140 -0
- package/src/i18n/index.ts +12 -0
- package/src/i18n/locales/core/en.ts +274 -0
- package/src/i18n/locales/core/index.ts +5 -0
- package/src/i18n/locales/core/sq.ts +275 -0
- package/src/i18n/useFormatter.ts +42 -0
- package/src/i18n/useLocale.ts +16 -0
- package/src/i18n/useTranslation.ts +17 -0
- package/src/index.ts +244 -0
- package/src/pages/ResourceListPage.tsx +205 -0
- package/src/plugin.ts +110 -0
- package/src/runtime/conditions.test.ts +99 -0
- package/src/runtime/conditions.ts +148 -0
- package/src/runtime/formTraversal.ts +41 -0
- package/src/runtime/serializedFunctions.test.ts +59 -0
- package/src/runtime/serializedFunctions.ts +284 -0
- package/src/slots/Slot.test.tsx +89 -0
- package/src/slots/Slot.tsx +47 -0
- package/src/slots/SlotCluster.test.tsx +95 -0
- package/src/slots/SlotCluster.tsx +107 -0
- package/src/slots/index.ts +15 -0
- package/src/slots/mergeSlots.test.ts +71 -0
- package/src/slots/mergeSlots.ts +40 -0
- package/src/slots/slotNames.test.ts +21 -0
- package/src/slots/types.ts +119 -0
- package/src/styles.css +437 -0
- package/src/table/TableContext.tsx +41 -0
- package/src/table/TableRenderer.test.tsx +197 -0
- package/src/table/TableRenderer.tsx +390 -0
- package/src/table/components/FiltersPanel.tsx +193 -0
- package/src/table/components/TableToolbar.tsx +153 -0
- package/src/table/components/TableToolbarButton.tsx +14 -0
- package/src/table/components/TableView.tsx +106 -0
- package/src/table/defaultRowActions.ts +43 -0
- package/src/table/hooks/useColumnVisibility.test.ts +51 -0
- package/src/table/hooks/useColumnVisibility.ts +71 -0
- package/src/table/hooks/useEditableRows.test.ts +69 -0
- package/src/table/hooks/useEditableRows.ts +89 -0
- package/src/table/hooks/useTableActions.ts +393 -0
- package/src/table/hooks/useTableData.ts +89 -0
- package/src/table/hooks/useTableLayout.ts +45 -0
- package/src/table/hooks/useTableQuery.test.ts +116 -0
- package/src/table/hooks/useTableQuery.ts +172 -0
- package/src/test/mockFetch.ts +67 -0
- package/src/test/setup.ts +25 -0
- package/src/types/index.ts +228 -0
- package/src/utils/classNames.ts +10 -0
- package/src/utils/columnMediaDimensions.ts +45 -0
- package/src/utils/columnVisibilityStorage.ts +55 -0
- package/src/utils/fieldErrors.test.ts +35 -0
- package/src/utils/fieldErrors.ts +27 -0
- package/src/utils/formatValue.test.tsx +65 -0
- package/src/utils/formatValue.tsx +117 -0
- package/src/utils/layoutStorage.ts +52 -0
- package/src/utils/redirectHandler.ts +29 -0
- package/src/utils/tableFormatters.test.ts +54 -0
- package/src/utils/tableFormatters.ts +104 -0
- package/src/utils/widgetVisibilityStorage.ts +38 -0
- package/tailwind.config.js +9 -0
- package/vite.config.ts +17 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { apiPost } from './http';
|
|
2
|
+
/**
|
|
3
|
+
* API client for communicating with the table backend
|
|
4
|
+
*/
|
|
5
|
+
export class TableApiClient {
|
|
6
|
+
/**
|
|
7
|
+
* @param apiBaseUrl - Base URL for the panel API (used for token refresh)
|
|
8
|
+
* @param baseUrl - Base URL of the resource endpoint (e.g. 'http://localhost:3001/api/users')
|
|
9
|
+
* @param fetchPath - Path appended for list queries ('/list' for resources, '' for custom endpoints)
|
|
10
|
+
*/
|
|
11
|
+
constructor(apiBaseUrl, baseUrl, fetchPath = '') {
|
|
12
|
+
this.baseUrl = baseUrl.replace(/\/$/, ''); // Remove trailing slash
|
|
13
|
+
this.fetchPath = fetchPath;
|
|
14
|
+
this.apiBaseUrl = apiBaseUrl;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Fetch table data with filtering, sorting, and pagination
|
|
18
|
+
*/
|
|
19
|
+
async fetchData(params) {
|
|
20
|
+
return apiPost(this.baseUrl + this.fetchPath, params, this.apiBaseUrl);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Update a single record. Unwraps the `{ data, metadata }` envelope.
|
|
24
|
+
*/
|
|
25
|
+
async updateRecord(id, data) {
|
|
26
|
+
const result = await apiPost(`${this.baseUrl}/update/${id}`, data, this.apiBaseUrl);
|
|
27
|
+
return result?.data || result;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Delete records (bulk or single).
|
|
31
|
+
* Returns the full response body (including metadata e.g. refreshBadges) so callers can react to it.
|
|
32
|
+
*/
|
|
33
|
+
async deleteRecords(ids) {
|
|
34
|
+
return apiPost(`${this.baseUrl}/bulk-delete`, { ids }, this.apiBaseUrl);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Bulk delete records (alias for deleteRecords)
|
|
38
|
+
*/
|
|
39
|
+
async bulkDelete(ids) {
|
|
40
|
+
return this.deleteRecords(ids);
|
|
41
|
+
}
|
|
42
|
+
getBaseUrl() {
|
|
43
|
+
return this.baseUrl;
|
|
44
|
+
}
|
|
45
|
+
getFetchPath() {
|
|
46
|
+
return this.fetchPath;
|
|
47
|
+
}
|
|
48
|
+
getApiBaseUrl() {
|
|
49
|
+
return this.apiBaseUrl;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* URL derivation helpers shared by the table, modals and API clients.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Derive the panel API base URL from a resource API URL.
|
|
6
|
+
*
|
|
7
|
+
* - `.../api/users` -> `.../api`
|
|
8
|
+
* - `.../api/users/1/relations/posts` -> `.../api`
|
|
9
|
+
*/
|
|
10
|
+
export declare function deriveApiBaseUrl(apiUrl: string): string;
|
|
11
|
+
/** Last path segment of a resource API URL (the resource slug). */
|
|
12
|
+
export declare function resourceSlugFromUrl(apiUrl: string): string;
|
|
13
|
+
/** Deterministic, short, filesystem/localStorage-safe hash of a string. */
|
|
14
|
+
export declare function hashString(str: string): string;
|
|
15
|
+
/**
|
|
16
|
+
* Stable key for per-resource localStorage entries (column visibility, layout).
|
|
17
|
+
* Non-resource tables hash the URL; relation tables use the relation slug.
|
|
18
|
+
*/
|
|
19
|
+
export declare function resourceStorageKey(apiUrl: string, isResource: boolean, relatedResourceSlug?: string): string;
|
package/dist/api/urls.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* URL derivation helpers shared by the table, modals and API clients.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Derive the panel API base URL from a resource API URL.
|
|
6
|
+
*
|
|
7
|
+
* - `.../api/users` -> `.../api`
|
|
8
|
+
* - `.../api/users/1/relations/posts` -> `.../api`
|
|
9
|
+
*/
|
|
10
|
+
export function deriveApiBaseUrl(apiUrl) {
|
|
11
|
+
if (apiUrl.includes('/relations/')) {
|
|
12
|
+
const baseUrl = apiUrl.substring(0, apiUrl.indexOf('/relations/'));
|
|
13
|
+
// Remove the record id segment to get back to the api base
|
|
14
|
+
return baseUrl.substring(0, baseUrl.lastIndexOf('/'));
|
|
15
|
+
}
|
|
16
|
+
return apiUrl.substring(0, apiUrl.lastIndexOf('/'));
|
|
17
|
+
}
|
|
18
|
+
/** Last path segment of a resource API URL (the resource slug). */
|
|
19
|
+
export function resourceSlugFromUrl(apiUrl) {
|
|
20
|
+
return apiUrl.split('/').filter(Boolean).pop() || '';
|
|
21
|
+
}
|
|
22
|
+
/** Deterministic, short, filesystem/localStorage-safe hash of a string. */
|
|
23
|
+
export function hashString(str) {
|
|
24
|
+
let hash = 0;
|
|
25
|
+
for (let i = 0; i < str.length; i++) {
|
|
26
|
+
const char = str.charCodeAt(i);
|
|
27
|
+
hash = (hash << 5) - hash + char;
|
|
28
|
+
hash = hash & hash; // Convert to 32-bit integer
|
|
29
|
+
}
|
|
30
|
+
return Math.abs(hash).toString(36);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Stable key for per-resource localStorage entries (column visibility, layout).
|
|
34
|
+
* Non-resource tables hash the URL; relation tables use the relation slug.
|
|
35
|
+
*/
|
|
36
|
+
export function resourceStorageKey(apiUrl, isResource, relatedResourceSlug) {
|
|
37
|
+
if (!isResource) {
|
|
38
|
+
return hashString(apiUrl);
|
|
39
|
+
}
|
|
40
|
+
if (relatedResourceSlug) {
|
|
41
|
+
return relatedResourceSlug.replace(/[^a-zA-Z0-9_]/g, '_');
|
|
42
|
+
}
|
|
43
|
+
const segments = apiUrl.split('/').filter(Boolean);
|
|
44
|
+
const lastSegment = segments[segments.length - 1] || segments[segments.length - 2] || 'resource';
|
|
45
|
+
return lastSegment.replace(/[^a-zA-Z0-9_]/g, '_');
|
|
46
|
+
}
|
package/dist/app.d.ts
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import type { KratosPluginClient, MergedPluginRegistries } from './plugin';
|
|
2
|
+
import type { FieldRegistry, WidgetRegistry, BlockRegistry } from './types';
|
|
3
|
+
import type { ColumnRegistry } from './contexts/ColumnRegistryContext';
|
|
4
|
+
import type { AuthChallengeRegistry } from './contexts/AuthChallengeRegistryContext';
|
|
5
|
+
import type { RuleDefinition } from '@maxal_studio/kratosjs';
|
|
6
|
+
import type { ClientI18nConfig } from './i18n/buildClientI18n';
|
|
7
|
+
import type { SlotMap } from './slots/types';
|
|
8
|
+
export interface MountAdminPanelOptions {
|
|
9
|
+
/** Client manifests of the plugins used by this panel */
|
|
10
|
+
plugins?: KratosPluginClient[];
|
|
11
|
+
/**
|
|
12
|
+
* Custom field components keyed by field type (e.g. `'star-rating'`).
|
|
13
|
+
* Registered directly by the app — no plugin required. The key must match the
|
|
14
|
+
* `componentType` emitted by the backend builder. App entries override plugins.
|
|
15
|
+
*/
|
|
16
|
+
fields?: FieldRegistry;
|
|
17
|
+
/** Custom table column components keyed by column type. App entries override plugins. */
|
|
18
|
+
columns?: ColumnRegistry;
|
|
19
|
+
/** Custom widget components keyed by widget type. App entries override plugins. */
|
|
20
|
+
widgets?: WidgetRegistry;
|
|
21
|
+
/** Custom page block components keyed by block type. App entries override plugins. */
|
|
22
|
+
blocks?: BlockRegistry;
|
|
23
|
+
/** Challenge UI components keyed by challenge type. App entries override plugins. */
|
|
24
|
+
authChallenges?: AuthChallengeRegistry;
|
|
25
|
+
/**
|
|
26
|
+
* Custom validation rules keyed by rule name. Authored once and shared with the
|
|
27
|
+
* server (via `panel.registerValidationRule`) so they validate identically on
|
|
28
|
+
* both sides. App entries override plugins.
|
|
29
|
+
*/
|
|
30
|
+
rules?: Record<string, RuleDefinition>;
|
|
31
|
+
/**
|
|
32
|
+
* UI slot contributions keyed by slot name (e.g. `'header.right'`). Slots are
|
|
33
|
+
* 1:many — app contributions stack alongside any from plugins. A value is a
|
|
34
|
+
* single `SlotContribution` or an array.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* mountAdminPanel({
|
|
38
|
+
* slots: { 'header.right': { id: 'help', render: () => <HelpButton /> } },
|
|
39
|
+
* });
|
|
40
|
+
*/
|
|
41
|
+
slots?: SlotMap;
|
|
42
|
+
/**
|
|
43
|
+
* API base URL. Defaults to the base path injected by the KratosJs server
|
|
44
|
+
* (window.__VALAJS_API_BASE_PATH__) on the current origin.
|
|
45
|
+
*/
|
|
46
|
+
apiBaseUrl?: string;
|
|
47
|
+
/**
|
|
48
|
+
* Optional i18n override. Locales and every app/plugin catalog are authored once
|
|
49
|
+
* on the server and injected into the page (`window.__VALAJS_I18N__`) — you rarely
|
|
50
|
+
* need this. Use it only to override built-in `core:` chrome or add React-only
|
|
51
|
+
* strings; `translations` keys may target any namespace via a `ns:` prefix
|
|
52
|
+
* (e.g. `core:common.save`), unprefixed keys → `app`. It layers over the injected config.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* mountAdminPanel({ i18n: { translations: { en: { 'core:common.save': 'Store' } } } });
|
|
56
|
+
*/
|
|
57
|
+
i18n?: ClientI18nConfig;
|
|
58
|
+
/** Panel id when serving multiple panels */
|
|
59
|
+
panelId?: string;
|
|
60
|
+
/** DOM element id to mount into (default: 'root') */
|
|
61
|
+
rootElementId?: string;
|
|
62
|
+
/**
|
|
63
|
+
* Accent color override (any CSS color). Sets the --kratos-accent tokens
|
|
64
|
+
* on the document root; hover/soft shades are derived automatically.
|
|
65
|
+
*/
|
|
66
|
+
accentColor?: string;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Resolve the merged component/rule registries from mount options.
|
|
70
|
+
*
|
|
71
|
+
* Plugin manifests are merged first, then the app's own direct registrations
|
|
72
|
+
* (`fields`/`columns`/`widgets`/`blocks`/`rules`) are applied last so an app
|
|
73
|
+
* always wins over a plugin on a key collision.
|
|
74
|
+
*/
|
|
75
|
+
export declare function resolveRegistries(options?: MountAdminPanelOptions): MergedPluginRegistries;
|
|
76
|
+
/**
|
|
77
|
+
* Mount the KratosJs admin panel into the DOM.
|
|
78
|
+
*
|
|
79
|
+
* This is the entry point apps use in their admin client bundle:
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```typescript
|
|
83
|
+
* // src/admin/main.tsx — register custom components directly, no plugin needed
|
|
84
|
+
* import { mountAdminPanel } from '@maxal_studio/kratosjs-react';
|
|
85
|
+
* import '@maxal_studio/kratosjs-react/styles.css';
|
|
86
|
+
* import StarRatingField from './components/StarRatingField';
|
|
87
|
+
*
|
|
88
|
+
* mountAdminPanel({
|
|
89
|
+
* fields: { 'star-rating': StarRatingField },
|
|
90
|
+
* });
|
|
91
|
+
* ```
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```typescript
|
|
95
|
+
* // Packaged plugins still work, and can be combined with app registrations:
|
|
96
|
+
* import starRating from '@maxal_studio/kratosjs-plugin-star-rating/client';
|
|
97
|
+
*
|
|
98
|
+
* mountAdminPanel({ plugins: [starRating] });
|
|
99
|
+
* ```
|
|
100
|
+
*/
|
|
101
|
+
export declare function mountAdminPanel(options?: MountAdminPanelOptions): void;
|
package/dist/app.js
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import ReactDOM from 'react-dom/client';
|
|
4
|
+
import { AdminPanel } from './components/AdminPanel';
|
|
5
|
+
import { mergePluginClients } from './plugin';
|
|
6
|
+
import { ValidationEngine } from '@maxal_studio/kratosjs/dist/validation';
|
|
7
|
+
/**
|
|
8
|
+
* Resolve the merged component/rule registries from mount options.
|
|
9
|
+
*
|
|
10
|
+
* Plugin manifests are merged first, then the app's own direct registrations
|
|
11
|
+
* (`fields`/`columns`/`widgets`/`blocks`/`rules`) are applied last so an app
|
|
12
|
+
* always wins over a plugin on a key collision.
|
|
13
|
+
*/
|
|
14
|
+
export function resolveRegistries(options = {}) {
|
|
15
|
+
const appManifest = {
|
|
16
|
+
name: 'app',
|
|
17
|
+
fields: options.fields,
|
|
18
|
+
columns: options.columns,
|
|
19
|
+
widgets: options.widgets,
|
|
20
|
+
blocks: options.blocks,
|
|
21
|
+
authChallenges: options.authChallenges,
|
|
22
|
+
rules: options.rules,
|
|
23
|
+
slots: options.slots,
|
|
24
|
+
};
|
|
25
|
+
return mergePluginClients([...(options.plugins ?? []), appManifest]);
|
|
26
|
+
}
|
|
27
|
+
function applyAccentColor(accentColor) {
|
|
28
|
+
const root = document.documentElement;
|
|
29
|
+
root.style.setProperty('--kratos-accent', accentColor);
|
|
30
|
+
root.style.setProperty('--kratos-accent-hover', `color-mix(in srgb, ${accentColor} 85%, black)`);
|
|
31
|
+
root.style.setProperty('--kratos-accent-soft', `color-mix(in srgb, ${accentColor} 15%, transparent)`);
|
|
32
|
+
}
|
|
33
|
+
function resolveApiBaseUrl() {
|
|
34
|
+
const basePath = window.__VALAJS_API_BASE_PATH__ || '/api';
|
|
35
|
+
return `${window.location.origin}${basePath}`;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* The i18n config the KratosJs server injects into the admin HTML
|
|
39
|
+
* (`window.__VALAJS_I18N__`). This is the source of truth for locales and every
|
|
40
|
+
* app/plugin catalog — authored once on the server.
|
|
41
|
+
*/
|
|
42
|
+
function resolveInjectedI18n() {
|
|
43
|
+
return window.__VALAJS_I18N__ ?? {};
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Mount the KratosJs admin panel into the DOM.
|
|
47
|
+
*
|
|
48
|
+
* This is the entry point apps use in their admin client bundle:
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```typescript
|
|
52
|
+
* // src/admin/main.tsx — register custom components directly, no plugin needed
|
|
53
|
+
* import { mountAdminPanel } from '@maxal_studio/kratosjs-react';
|
|
54
|
+
* import '@maxal_studio/kratosjs-react/styles.css';
|
|
55
|
+
* import StarRatingField from './components/StarRatingField';
|
|
56
|
+
*
|
|
57
|
+
* mountAdminPanel({
|
|
58
|
+
* fields: { 'star-rating': StarRatingField },
|
|
59
|
+
* });
|
|
60
|
+
* ```
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```typescript
|
|
64
|
+
* // Packaged plugins still work, and can be combined with app registrations:
|
|
65
|
+
* import starRating from '@maxal_studio/kratosjs-plugin-star-rating/client';
|
|
66
|
+
*
|
|
67
|
+
* mountAdminPanel({ plugins: [starRating] });
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
export function mountAdminPanel(options = {}) {
|
|
71
|
+
const rootElement = document.getElementById(options.rootElementId ?? 'root');
|
|
72
|
+
if (!rootElement) {
|
|
73
|
+
throw new Error(`Root element "#${options.rootElementId ?? 'root'}" not found`);
|
|
74
|
+
}
|
|
75
|
+
const registries = resolveRegistries(options);
|
|
76
|
+
// Register plugin-provided validation rules into the shared engine so the
|
|
77
|
+
// client validates them exactly as the server does.
|
|
78
|
+
for (const definition of Object.values(registries.rules)) {
|
|
79
|
+
ValidationEngine.register(definition);
|
|
80
|
+
}
|
|
81
|
+
const apiBaseUrl = options.apiBaseUrl ?? resolveApiBaseUrl();
|
|
82
|
+
// The server-injected config (locales + app/plugin catalogs) is the base; any
|
|
83
|
+
// explicit `options.i18n` from the mount call layers on top as an override.
|
|
84
|
+
const i18nConfig = { ...resolveInjectedI18n(), ...options.i18n };
|
|
85
|
+
if (options.accentColor) {
|
|
86
|
+
applyAccentColor(options.accentColor);
|
|
87
|
+
}
|
|
88
|
+
ReactDOM.createRoot(rootElement).render(_jsx(React.StrictMode, { children: _jsx(AdminPanel, { apiBaseUrl: apiBaseUrl, panelId: options.panelId, customFields: registries.fields, customColumns: registries.columns, customWidgets: registries.widgets, customBlocks: registries.blocks, customAuthChallenges: registries.authChallenges, customSlots: registries.slots, i18nConfig: i18nConfig }) }));
|
|
89
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { AuthUser, LoginCredentials, PendingChallenge } from './types';
|
|
3
|
+
interface AuthContextValue {
|
|
4
|
+
user: AuthUser | null;
|
|
5
|
+
loading: boolean;
|
|
6
|
+
/** A challenge (e.g. 2FA) awaiting the user's response, or null. */
|
|
7
|
+
pendingChallenge: PendingChallenge | null;
|
|
8
|
+
login: (provider: string, credentials: LoginCredentials) => Promise<void>;
|
|
9
|
+
/** Submit a response to the active `pendingChallenge`. */
|
|
10
|
+
verifyChallenge: (payload: unknown) => Promise<void>;
|
|
11
|
+
/** Abandon the active challenge and return to the login form. */
|
|
12
|
+
cancelChallenge: () => void;
|
|
13
|
+
logout: () => Promise<void>;
|
|
14
|
+
refreshUser: () => Promise<void>;
|
|
15
|
+
}
|
|
16
|
+
interface AuthProviderProps {
|
|
17
|
+
children: React.ReactNode;
|
|
18
|
+
apiBaseUrl: string;
|
|
19
|
+
}
|
|
20
|
+
export declare function AuthProvider({ children, apiBaseUrl }: AuthProviderProps): React.JSX.Element;
|
|
21
|
+
export declare function useAuth(): AuthContextValue;
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { createContext, useContext, useState, useEffect, useCallback, useRef } from 'react';
|
|
3
|
+
import { AuthApiClient } from './authApiClient';
|
|
4
|
+
const AuthContext = createContext(null);
|
|
5
|
+
export function AuthProvider({ children, apiBaseUrl }) {
|
|
6
|
+
const [user, setUser] = useState(null);
|
|
7
|
+
const [loading, setLoading] = useState(true);
|
|
8
|
+
const [pendingChallenge, setPendingChallenge] = useState(null);
|
|
9
|
+
const apiClient = useRef(new AuthApiClient(apiBaseUrl));
|
|
10
|
+
const refreshTimerRef = useRef(null);
|
|
11
|
+
const scheduleTokenRefresh = useCallback((expiresIn) => {
|
|
12
|
+
if (refreshTimerRef.current) {
|
|
13
|
+
clearTimeout(refreshTimerRef.current);
|
|
14
|
+
}
|
|
15
|
+
// Refresh 1 minute before expiry, minimum 1 minute
|
|
16
|
+
const refreshTime = Math.max((expiresIn - 60) * 1000, 60000);
|
|
17
|
+
refreshTimerRef.current = setTimeout(async () => {
|
|
18
|
+
try {
|
|
19
|
+
const tokens = await apiClient.current.refreshToken();
|
|
20
|
+
if (tokens?.expiresIn) {
|
|
21
|
+
scheduleTokenRefresh(tokens.expiresIn);
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
setUser(null);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
setUser(null);
|
|
29
|
+
}
|
|
30
|
+
}, refreshTime);
|
|
31
|
+
}, []);
|
|
32
|
+
/**
|
|
33
|
+
* Fetch the current user from /auth/me.
|
|
34
|
+
* On 401, attempts a silent token refresh via the cookie before giving up.
|
|
35
|
+
* Seeds the proactive refresh timer when a refresh response includes expiresIn.
|
|
36
|
+
*/
|
|
37
|
+
const fetchUser = useCallback(async () => {
|
|
38
|
+
try {
|
|
39
|
+
const currentUser = await apiClient.current.getCurrentUser();
|
|
40
|
+
setUser(currentUser);
|
|
41
|
+
return currentUser;
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
if (error?.status === 401) {
|
|
45
|
+
try {
|
|
46
|
+
const tokens = await apiClient.current.refreshToken();
|
|
47
|
+
if (tokens) {
|
|
48
|
+
if (tokens.expiresIn)
|
|
49
|
+
scheduleTokenRefresh(tokens.expiresIn);
|
|
50
|
+
const currentUser = await apiClient.current.getCurrentUser();
|
|
51
|
+
setUser(currentUser);
|
|
52
|
+
return currentUser;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
// refresh failed — fall through to null
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
setUser(null);
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
}, [scheduleTokenRefresh]);
|
|
63
|
+
/** Apply an `authenticated` result: set the user and seed the refresh timer. */
|
|
64
|
+
const applyAuthenticated = useCallback((authUser, expiresIn) => {
|
|
65
|
+
setPendingChallenge(null);
|
|
66
|
+
setUser(authUser);
|
|
67
|
+
if (expiresIn) {
|
|
68
|
+
scheduleTokenRefresh(expiresIn);
|
|
69
|
+
}
|
|
70
|
+
}, [scheduleTokenRefresh]);
|
|
71
|
+
const login = useCallback(async (provider, credentials) => {
|
|
72
|
+
const result = await apiClient.current.login(provider, credentials);
|
|
73
|
+
if (result.status === 'authenticated') {
|
|
74
|
+
applyAuthenticated(result.user, result.tokens?.expiresIn);
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
// Pause here: a challenge (e.g. 2FA) must be satisfied before tokens are issued.
|
|
78
|
+
setPendingChallenge(result.challenge);
|
|
79
|
+
}
|
|
80
|
+
}, [applyAuthenticated]);
|
|
81
|
+
const verifyChallenge = useCallback(async (payload) => {
|
|
82
|
+
if (!pendingChallenge) {
|
|
83
|
+
throw new Error('No challenge in progress');
|
|
84
|
+
}
|
|
85
|
+
const result = await apiClient.current.verifyChallenge(pendingChallenge.challengeToken, pendingChallenge.type, payload);
|
|
86
|
+
if (result.status === 'authenticated') {
|
|
87
|
+
applyAuthenticated(result.user, result.tokens?.expiresIn);
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
// Chained step: replace with the next pending challenge.
|
|
91
|
+
setPendingChallenge(result.challenge);
|
|
92
|
+
}
|
|
93
|
+
}, [pendingChallenge, applyAuthenticated]);
|
|
94
|
+
const cancelChallenge = useCallback(() => {
|
|
95
|
+
setPendingChallenge(null);
|
|
96
|
+
}, []);
|
|
97
|
+
const logout = useCallback(async () => {
|
|
98
|
+
try {
|
|
99
|
+
await apiClient.current.logout();
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
// ignore
|
|
103
|
+
}
|
|
104
|
+
finally {
|
|
105
|
+
setUser(null);
|
|
106
|
+
setPendingChallenge(null);
|
|
107
|
+
if (refreshTimerRef.current) {
|
|
108
|
+
clearTimeout(refreshTimerRef.current);
|
|
109
|
+
refreshTimerRef.current = null;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}, []);
|
|
113
|
+
const refreshUser = useCallback(async () => {
|
|
114
|
+
await fetchUser();
|
|
115
|
+
}, [fetchUser]);
|
|
116
|
+
useEffect(() => {
|
|
117
|
+
const init = async () => {
|
|
118
|
+
setLoading(true);
|
|
119
|
+
await fetchUser();
|
|
120
|
+
setLoading(false);
|
|
121
|
+
};
|
|
122
|
+
init();
|
|
123
|
+
return () => {
|
|
124
|
+
if (refreshTimerRef.current) {
|
|
125
|
+
clearTimeout(refreshTimerRef.current);
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
}, [fetchUser]);
|
|
129
|
+
const value = {
|
|
130
|
+
user,
|
|
131
|
+
loading,
|
|
132
|
+
pendingChallenge,
|
|
133
|
+
login,
|
|
134
|
+
verifyChallenge,
|
|
135
|
+
cancelChallenge,
|
|
136
|
+
logout,
|
|
137
|
+
refreshUser,
|
|
138
|
+
};
|
|
139
|
+
return _jsx(AuthContext.Provider, { value: value, children: children });
|
|
140
|
+
}
|
|
141
|
+
export function useAuth() {
|
|
142
|
+
const context = useContext(AuthContext);
|
|
143
|
+
if (!context) {
|
|
144
|
+
throw new Error('useAuth must be used within an AuthProvider');
|
|
145
|
+
}
|
|
146
|
+
return context;
|
|
147
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
interface LoginPageProps {
|
|
3
|
+
apiBaseUrl: string;
|
|
4
|
+
onSuccess?: () => void;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* LoginPage - Displays authentication providers and handles login
|
|
8
|
+
*/
|
|
9
|
+
export declare function LoginPage({ apiBaseUrl, onSuccess }: LoginPageProps): React.JSX.Element;
|
|
10
|
+
export {};
|