@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,65 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { formatDate, formatNumber, formatBoolean, formatSelectLabel } from './formatValue';
|
|
3
|
+
|
|
4
|
+
describe('formatDate', () => {
|
|
5
|
+
it('returns "-" for empty values', () => {
|
|
6
|
+
expect(formatDate(null)).toBe('-');
|
|
7
|
+
expect(formatDate('')).toBe('-');
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
it('returns the raw value for invalid dates', () => {
|
|
11
|
+
expect(formatDate('not-a-date')).toBe('not-a-date');
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it('applies YYYY-MM-DD style format tokens', () => {
|
|
15
|
+
expect(formatDate('2026-01-15T10:30:45', 'YYYY-MM-DD')).toBe('2026-01-15');
|
|
16
|
+
expect(formatDate('2026-01-15T10:30:45', 'DD/MM/YYYY HH:mm')).toBe('15/01/2026 10:30');
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
describe('formatNumber', () => {
|
|
21
|
+
it('returns "-" for null/undefined', () => {
|
|
22
|
+
expect(formatNumber(null)).toBe('-');
|
|
23
|
+
expect(formatNumber(undefined)).toBe('-');
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('returns the raw value as string for non-numbers', () => {
|
|
27
|
+
expect(formatNumber('abc')).toBe('abc');
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('formats currency', () => {
|
|
31
|
+
expect(formatNumber(1234.5, { currency: 'USD' })).toBe('$1,234.50');
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('applies fixed decimals', () => {
|
|
35
|
+
expect(formatNumber(3.14159, { decimals: 2 })).toBe('3.14');
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('falls back to locale formatting', () => {
|
|
39
|
+
expect(formatNumber(1000000)).toBe((1000000).toLocaleString());
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
describe('formatBoolean', () => {
|
|
44
|
+
it('maps booleans to Yes/No and empty to "-"', () => {
|
|
45
|
+
expect(formatBoolean(true)).toBe('Yes');
|
|
46
|
+
expect(formatBoolean(false)).toBe('No');
|
|
47
|
+
expect(formatBoolean(null)).toBe('-');
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
describe('formatSelectLabel', () => {
|
|
52
|
+
it('returns "-" for empty values', () => {
|
|
53
|
+
expect(formatSelectLabel(null)).toBe('-');
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('maps a single value through options', () => {
|
|
57
|
+
expect(formatSelectLabel('a', { a: 'Alpha' })).toBe('Alpha');
|
|
58
|
+
expect(formatSelectLabel('missing', { a: 'Alpha' })).toBe('missing');
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it('joins multiple values with labels', () => {
|
|
62
|
+
expect(formatSelectLabel(['a', 'b'], { a: 'Alpha', b: 'Beta' }, true)).toBe('Alpha, Beta');
|
|
63
|
+
expect(formatSelectLabel([], { a: 'Alpha' }, true)).toBe('-');
|
|
64
|
+
});
|
|
65
|
+
});
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { getActiveLocale, translate } from '../i18n/activeLocale';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Utility functions for formatting field values in view mode
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Format a date value according to the specified format
|
|
10
|
+
*/
|
|
11
|
+
export function formatDate(value: any, format?: string): string {
|
|
12
|
+
if (!value) return '-';
|
|
13
|
+
|
|
14
|
+
try {
|
|
15
|
+
const date = new Date(value);
|
|
16
|
+
if (isNaN(date.getTime())) return String(value);
|
|
17
|
+
|
|
18
|
+
if (format) {
|
|
19
|
+
// Simple format support - can be extended
|
|
20
|
+
const year = date.getFullYear();
|
|
21
|
+
const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
22
|
+
const day = String(date.getDate()).padStart(2, '0');
|
|
23
|
+
const hours = String(date.getHours()).padStart(2, '0');
|
|
24
|
+
const minutes = String(date.getMinutes()).padStart(2, '0');
|
|
25
|
+
const seconds = String(date.getSeconds()).padStart(2, '0');
|
|
26
|
+
|
|
27
|
+
return format
|
|
28
|
+
.replace('YYYY', String(year))
|
|
29
|
+
.replace('MM', month)
|
|
30
|
+
.replace('DD', day)
|
|
31
|
+
.replace('HH', hours)
|
|
32
|
+
.replace('mm', minutes)
|
|
33
|
+
.replace('ss', seconds);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return date.toLocaleString(getActiveLocale());
|
|
37
|
+
} catch {
|
|
38
|
+
return String(value);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Format a number value with optional options
|
|
44
|
+
*/
|
|
45
|
+
export function formatNumber(value: any, options?: { decimals?: number; currency?: string }): string {
|
|
46
|
+
if (value === null || value === undefined) return '-';
|
|
47
|
+
|
|
48
|
+
const num = Number(value);
|
|
49
|
+
if (isNaN(num)) return String(value);
|
|
50
|
+
|
|
51
|
+
if (options?.currency) {
|
|
52
|
+
return new Intl.NumberFormat(getActiveLocale(), {
|
|
53
|
+
style: 'currency',
|
|
54
|
+
currency: options.currency,
|
|
55
|
+
minimumFractionDigits: options.decimals ?? 2,
|
|
56
|
+
maximumFractionDigits: options.decimals ?? 2,
|
|
57
|
+
}).format(num);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (options?.decimals !== undefined) {
|
|
61
|
+
return num.toFixed(options.decimals);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return num.toLocaleString(getActiveLocale());
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Format a boolean value
|
|
69
|
+
*/
|
|
70
|
+
export function formatBoolean(value: any): string {
|
|
71
|
+
if (value === null || value === undefined) return '-';
|
|
72
|
+
return value ? translate('core:common.yes') : translate('core:common.no');
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Format a select value to display option labels
|
|
77
|
+
*/
|
|
78
|
+
export function formatSelectLabel(value: any, options?: Record<string | number, string>, isMultiple?: boolean): string {
|
|
79
|
+
if (!value) return '-';
|
|
80
|
+
|
|
81
|
+
if (isMultiple && Array.isArray(value)) {
|
|
82
|
+
if (value.length === 0) return '-';
|
|
83
|
+
if (!options) return value.join(', ');
|
|
84
|
+
return value
|
|
85
|
+
.map(v => {
|
|
86
|
+
const key = String(v);
|
|
87
|
+
return options[key] || key;
|
|
88
|
+
})
|
|
89
|
+
.join(', ');
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (!options) return String(value);
|
|
93
|
+
const key = String(value);
|
|
94
|
+
return options[key] || key;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Format a textarea value preserving line breaks
|
|
99
|
+
* Returns an array of React elements for rendering
|
|
100
|
+
*/
|
|
101
|
+
export function formatTextarea(value: any): React.ReactNode {
|
|
102
|
+
if (value === null || value === undefined) return '-';
|
|
103
|
+
// If is js object, return json string
|
|
104
|
+
let text = value;
|
|
105
|
+
if (typeof value === 'object') {
|
|
106
|
+
text = JSON.stringify(value, null, 2);
|
|
107
|
+
} else {
|
|
108
|
+
text = String(value);
|
|
109
|
+
}
|
|
110
|
+
const lines = text.split('\n');
|
|
111
|
+
return lines.map((line, i) => (
|
|
112
|
+
<React.Fragment key={i}>
|
|
113
|
+
{line}
|
|
114
|
+
{i < lines.length - 1 && <br />}
|
|
115
|
+
</React.Fragment>
|
|
116
|
+
));
|
|
117
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Layout storage utilities for managing table/grid layout preferences in localStorage
|
|
3
|
+
*/
|
|
4
|
+
export const layoutStorage = {
|
|
5
|
+
/**
|
|
6
|
+
* Get layout preference for a resource
|
|
7
|
+
* @param resourceKey Unique identifier for the resource (e.g., 'users', 'posts')
|
|
8
|
+
* @param defaultLayout Default layout to return if no preference is stored
|
|
9
|
+
* @returns 'table' or 'grid'
|
|
10
|
+
*/
|
|
11
|
+
getLayout(resourceKey: string, defaultLayout: 'table' | 'grid' = 'table'): 'table' | 'grid' {
|
|
12
|
+
try {
|
|
13
|
+
const key = `kratosjs_layout_${resourceKey}`;
|
|
14
|
+
const stored = localStorage.getItem(key);
|
|
15
|
+
if (stored === 'table' || stored === 'grid') {
|
|
16
|
+
return stored;
|
|
17
|
+
}
|
|
18
|
+
return defaultLayout;
|
|
19
|
+
} catch (error) {
|
|
20
|
+
console.warn('Failed to read layout preference from localStorage:', error);
|
|
21
|
+
return defaultLayout;
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Set layout preference for a resource
|
|
27
|
+
* @param resourceKey Unique identifier for the resource
|
|
28
|
+
* @param layout Layout mode - 'table' or 'grid'
|
|
29
|
+
*/
|
|
30
|
+
setLayout(resourceKey: string, layout: 'table' | 'grid'): void {
|
|
31
|
+
try {
|
|
32
|
+
const key = `kratosjs_layout_${resourceKey}`;
|
|
33
|
+
localStorage.setItem(key, layout);
|
|
34
|
+
} catch (error) {
|
|
35
|
+
// Handle quota exceeded or other localStorage errors
|
|
36
|
+
if (error instanceof Error && error.name === 'QuotaExceededError') {
|
|
37
|
+
console.warn('localStorage quota exceeded, layout preference not saved');
|
|
38
|
+
} else {
|
|
39
|
+
console.warn('Failed to save layout preference to localStorage:', error);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Clear stored layout preference for a resource
|
|
46
|
+
* @param resourceKey Unique identifier for the resource
|
|
47
|
+
*/
|
|
48
|
+
clearLayout(resourceKey: string): void {
|
|
49
|
+
const key = `kratosjs_layout_${resourceKey}`;
|
|
50
|
+
localStorage.removeItem(key);
|
|
51
|
+
},
|
|
52
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Handle redirect from API response
|
|
3
|
+
* @param responseData - Response data from API
|
|
4
|
+
* @param navigate - React Router navigate function
|
|
5
|
+
* @returns true if redirect was handled, false otherwise
|
|
6
|
+
*/
|
|
7
|
+
export function handleRedirect(responseData: any, navigate: (path: string) => void): boolean {
|
|
8
|
+
if (responseData?.redirect) {
|
|
9
|
+
const redirectPath = responseData.redirect;
|
|
10
|
+
|
|
11
|
+
// Handle relative paths (client-side navigation)
|
|
12
|
+
if (redirectPath.startsWith('/')) {
|
|
13
|
+
navigate(redirectPath);
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Handle absolute URLs (external redirects)
|
|
18
|
+
if (redirectPath.startsWith('http://') || redirectPath.startsWith('https://')) {
|
|
19
|
+
window.location.href = redirectPath;
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Invalid redirect path
|
|
24
|
+
console.warn('Invalid redirect path:', redirectPath);
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { formatValue, stripHtml } from './tableFormatters';
|
|
3
|
+
|
|
4
|
+
const column = (overrides: Record<string, unknown> = {}) => overrides as any;
|
|
5
|
+
|
|
6
|
+
describe('formatValue', () => {
|
|
7
|
+
it('returns null for null/undefined values', () => {
|
|
8
|
+
expect(formatValue(null, column())).toBeNull();
|
|
9
|
+
expect(formatValue(undefined, column())).toBeNull();
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it('formats dates with dateFormat', () => {
|
|
13
|
+
const value = '2026-01-15T10:30:00';
|
|
14
|
+
expect(formatValue(value, column({ dateFormat: 'date' }))).toBe(new Date(value).toLocaleDateString());
|
|
15
|
+
expect(formatValue(value, column({ dateFormat: 'dateTime' }))).toBe(new Date(value).toLocaleString());
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('returns the raw value for invalid dates', () => {
|
|
19
|
+
expect(formatValue('nope', column({ dateFormat: 'date' }))).toBe('nope');
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('formats relative time for past dates', () => {
|
|
23
|
+
const twoHoursAgo = new Date(Date.now() - 2 * 60 * 60 * 1000).toISOString();
|
|
24
|
+
expect(formatValue(twoHoursAgo, column({ dateFormat: 'since' }))).toBe('2 hours ago');
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('formats money', () => {
|
|
28
|
+
expect(formatValue(12.5, column({ moneyFormat: 'USD' }))).toBe('$12.50');
|
|
29
|
+
expect(formatValue('12.5', column({ moneyFormat: 'EUR' }))).toBe('€12.50');
|
|
30
|
+
expect(formatValue('abc', column({ moneyFormat: 'USD' }))).toBe('abc');
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('strips HTML by default', () => {
|
|
34
|
+
expect(formatValue('<b>bold</b> text', column())).toBe('bold text');
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('keeps HTML when stripHtml is false', () => {
|
|
38
|
+
expect(formatValue('<b>bold</b>', column({ stripHtml: false }))).toBe('<b>bold</b>');
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('strips HTML from array items', () => {
|
|
42
|
+
expect(formatValue(['<i>a</i>', 2], column())).toEqual(['a', 2]);
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
describe('stripHtml', () => {
|
|
47
|
+
it('removes tags and keeps text', () => {
|
|
48
|
+
expect(stripHtml('<div><p>hello</p> <span>world</span></div>')).toBe('hello world');
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('passes through non-strings', () => {
|
|
52
|
+
expect(stripHtml(42 as unknown as string)).toBe(42);
|
|
53
|
+
});
|
|
54
|
+
});
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { SerializedColumn } from '@maxal_studio/kratosjs';
|
|
2
|
+
import { executeSerializedFunction } from '../runtime/serializedFunctions';
|
|
3
|
+
import { getActiveLocale } from '../i18n/activeLocale';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Format a value based on column configuration
|
|
7
|
+
* @param value - The cell value
|
|
8
|
+
* @param column - The column configuration
|
|
9
|
+
* @param row - The entire row data (optional, used by formatStateUsing function)
|
|
10
|
+
*/
|
|
11
|
+
export function formatValue(value: any, column: SerializedColumn, row?: Record<string, any>): any {
|
|
12
|
+
// Only apply placeholder for null/undefined when there's no formatter
|
|
13
|
+
if (value === null || value === undefined) {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Date formatting
|
|
18
|
+
if (column.dateFormat) {
|
|
19
|
+
const date = new Date(value);
|
|
20
|
+
if (isNaN(date.getTime())) return value;
|
|
21
|
+
|
|
22
|
+
const locale = getActiveLocale();
|
|
23
|
+
switch (column.dateFormat) {
|
|
24
|
+
case 'date':
|
|
25
|
+
return date.toLocaleDateString(locale);
|
|
26
|
+
case 'dateTime':
|
|
27
|
+
return date.toLocaleString(locale);
|
|
28
|
+
case 'time':
|
|
29
|
+
return date.toLocaleTimeString(locale);
|
|
30
|
+
case 'since':
|
|
31
|
+
case 'until':
|
|
32
|
+
return getRelativeTime(date);
|
|
33
|
+
default:
|
|
34
|
+
return date.toLocaleDateString(locale);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Money formatting
|
|
39
|
+
if (column.moneyFormat) {
|
|
40
|
+
const numValue = typeof value === 'number' ? value : parseFloat(value);
|
|
41
|
+
if (isNaN(numValue)) return value;
|
|
42
|
+
|
|
43
|
+
return new Intl.NumberFormat(getActiveLocale(), {
|
|
44
|
+
style: 'currency',
|
|
45
|
+
currency: column.moneyFormat || 'USD',
|
|
46
|
+
}).format(numValue);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Strip HTML by default; only skip when stripHtml is explicitly false.
|
|
50
|
+
// column.stripHtml is true (default), false (explicit), or undefined (treated as true).
|
|
51
|
+
const shouldStripHtml = column.stripHtml !== false;
|
|
52
|
+
|
|
53
|
+
if (shouldStripHtml) {
|
|
54
|
+
if (typeof value === 'string') {
|
|
55
|
+
return stripHtml(value);
|
|
56
|
+
}
|
|
57
|
+
// Handle arrays - strip HTML from each string item
|
|
58
|
+
if (Array.isArray(value)) {
|
|
59
|
+
return value.map(item => (typeof item === 'string' ? stripHtml(item) : item));
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return value;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Strip HTML tags from a string
|
|
68
|
+
* @param html - The HTML string to strip
|
|
69
|
+
* @returns Plain text with HTML tags removed
|
|
70
|
+
*/
|
|
71
|
+
export function stripHtml(html: string): string {
|
|
72
|
+
if (typeof html !== 'string') {
|
|
73
|
+
return html;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Create a temporary DOM element to parse HTML
|
|
77
|
+
const tmp = document.createElement('div');
|
|
78
|
+
tmp.innerHTML = html;
|
|
79
|
+
return tmp.textContent || tmp.innerText || '';
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Locale-aware relative time (e.g. "2 hours ago", "in 3 days"), using the active
|
|
84
|
+
* locale via `Intl.RelativeTimeFormat`. The true signed delta (date − now) drives
|
|
85
|
+
* direction, so past dates read "ago" and future dates read "in …".
|
|
86
|
+
*/
|
|
87
|
+
function getRelativeTime(date: Date): string {
|
|
88
|
+
const deltaSec = Math.round((date.getTime() - Date.now()) / 1000);
|
|
89
|
+
const abs = Math.abs(deltaSec);
|
|
90
|
+
const rtf = new Intl.RelativeTimeFormat(getActiveLocale(), { numeric: 'auto' });
|
|
91
|
+
|
|
92
|
+
const units: [Intl.RelativeTimeFormatUnit, number][] = [
|
|
93
|
+
['year', 31536000],
|
|
94
|
+
['month', 2592000],
|
|
95
|
+
['week', 604800],
|
|
96
|
+
['day', 86400],
|
|
97
|
+
['hour', 3600],
|
|
98
|
+
['minute', 60],
|
|
99
|
+
];
|
|
100
|
+
for (const [unit, secs] of units) {
|
|
101
|
+
if (abs >= secs) return rtf.format(Math.round(deltaSec / secs), unit);
|
|
102
|
+
}
|
|
103
|
+
return rtf.format(0, 'second');
|
|
104
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
const WIDGET_VISIBILITY_KEY = 'kratosjs_widgets_expanded';
|
|
2
|
+
|
|
3
|
+
/** Default when no preference stored: desktop expanded, mobile collapsed */
|
|
4
|
+
export function getDefaultWidgetsExpanded(): boolean {
|
|
5
|
+
if (typeof window === 'undefined') return true;
|
|
6
|
+
return window.matchMedia('(min-width: 768px)').matches;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Storage for widgets expanded/collapsed state.
|
|
11
|
+
* When no value is stored, mobile should be collapsed and desktop expanded (handled in component via media query).
|
|
12
|
+
*/
|
|
13
|
+
export const widgetVisibilityStorage = {
|
|
14
|
+
get(): boolean | null {
|
|
15
|
+
try {
|
|
16
|
+
const stored = localStorage.getItem(WIDGET_VISIBILITY_KEY);
|
|
17
|
+
if (stored === 'true') return true;
|
|
18
|
+
if (stored === 'false') return false;
|
|
19
|
+
return null;
|
|
20
|
+
} catch {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
set(expanded: boolean): void {
|
|
26
|
+
try {
|
|
27
|
+
localStorage.setItem(WIDGET_VISIBILITY_KEY, String(expanded));
|
|
28
|
+
} catch (error) {
|
|
29
|
+
if (error instanceof Error && error.name === 'QuotaExceededError') {
|
|
30
|
+
console.warn('localStorage quota exceeded, widgets visibility not saved');
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
clear(): void {
|
|
36
|
+
localStorage.removeItem(WIDGET_VISIBILITY_KEY);
|
|
37
|
+
},
|
|
38
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** @type {import('tailwindcss').Config} */
|
|
2
|
+
/**
|
|
3
|
+
* Tailwind v4 uses CSS-first configuration. Dynamic color and plugin spacing
|
|
4
|
+
* safelists live in src/styles.css via @source inline(). This file is kept
|
|
5
|
+
* for tooling compatibility only.
|
|
6
|
+
*/
|
|
7
|
+
export default {
|
|
8
|
+
content: ['./src/**/*.{js,ts,jsx,tsx}'],
|
|
9
|
+
};
|
package/vite.config.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { defineConfig } from 'vite';
|
|
2
|
+
import tailwindcss from '@tailwindcss/vite';
|
|
3
|
+
|
|
4
|
+
// Vite config for building only the CSS with Tailwind
|
|
5
|
+
export default defineConfig({
|
|
6
|
+
plugins: [tailwindcss()],
|
|
7
|
+
build: {
|
|
8
|
+
outDir: 'dist',
|
|
9
|
+
emptyOutDir: false, // Don't clear dist folder (tsc already created .js/.d.ts files)
|
|
10
|
+
rollupOptions: {
|
|
11
|
+
input: './src/styles.css',
|
|
12
|
+
output: {
|
|
13
|
+
assetFileNames: 'styles.css',
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
});
|