@vertesia/ui 1.0.0 → 1.1.0-dev.20260427.060440Z
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/lib/esm/core/components/ComboBox.js +23 -24
- package/lib/esm/core/components/ComboBox.js.map +1 -1
- package/lib/esm/core/components/FormItem.js +2 -2
- package/lib/esm/core/components/FormItem.js.map +1 -1
- package/lib/esm/core/components/SidePanel.js +1 -1
- package/lib/esm/core/components/SidePanel.js.map +1 -1
- package/lib/esm/core/components/shadcn/collaspible.js +3 -4
- package/lib/esm/core/components/shadcn/collaspible.js.map +1 -1
- package/lib/esm/core/components/shadcn/dropdown.js +37 -12
- package/lib/esm/core/components/shadcn/dropdown.js.map +1 -1
- package/lib/esm/core/components/shadcn/filters/comboBox/DateCombobox.js +6 -6
- package/lib/esm/core/components/shadcn/filters/comboBox/DateCombobox.js.map +1 -1
- package/lib/esm/core/components/shadcn/filters/filterBar.js +5 -3
- package/lib/esm/core/components/shadcn/filters/filterBar.js.map +1 -1
- package/lib/esm/core/components/shadcn/radioGroup.js +1 -2
- package/lib/esm/core/components/shadcn/radioGroup.js.map +1 -1
- package/lib/esm/core/components/shadcn/switch.js +0 -1
- package/lib/esm/core/components/shadcn/switch.js.map +1 -1
- package/lib/esm/core/components/shadcn/tabs.js +2 -2
- package/lib/esm/core/components/shadcn/tabs.js.map +1 -1
- package/lib/esm/core/components/shadcn/tooltip.js +17 -1
- package/lib/esm/core/components/shadcn/tooltip.js.map +1 -1
- package/lib/esm/core/hooks/PortalContainerProvider.js +9 -3
- package/lib/esm/core/hooks/PortalContainerProvider.js.map +1 -1
- package/lib/esm/env/index.js +5 -8
- package/lib/esm/env/index.js.map +1 -1
- package/lib/esm/features/agent/chat/AgentRightPanel.js +21 -11
- package/lib/esm/features/agent/chat/AgentRightPanel.js.map +1 -1
- package/lib/esm/features/agent/chat/AskUserWidget.js +2 -6
- package/lib/esm/features/agent/chat/AskUserWidget.js.map +1 -1
- package/lib/esm/features/agent/chat/DocumentPanel.js +8 -5
- package/lib/esm/features/agent/chat/DocumentPanel.js.map +1 -1
- package/lib/esm/features/agent/chat/DocumentTabBar.js +5 -13
- package/lib/esm/features/agent/chat/DocumentTabBar.js.map +1 -1
- package/lib/esm/features/agent/chat/ModernAgentConversation.js +57 -26
- package/lib/esm/features/agent/chat/ModernAgentConversation.js.map +1 -1
- package/lib/esm/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js +20 -16
- package/lib/esm/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js.map +1 -1
- package/lib/esm/features/agent/chat/ModernAgentOutput/Header.js +56 -45
- package/lib/esm/features/agent/chat/ModernAgentOutput/Header.js.map +1 -1
- package/lib/esm/features/agent/chat/ModernAgentOutput/MessageItem.js +1 -1
- package/lib/esm/features/agent/chat/ModernAgentOutput/MessageItem.js.map +1 -1
- package/lib/esm/features/agent/chat/SlidingThinkingIndicator.js +3 -9
- package/lib/esm/features/agent/chat/SlidingThinkingIndicator.js.map +1 -1
- package/lib/esm/features/agent/chat/hooks/useAgentStream.js +9 -5
- package/lib/esm/features/agent/chat/hooks/useAgentStream.js.map +1 -1
- package/lib/esm/features/agent/chat/hooks/useDocumentPanel.js +4 -0
- package/lib/esm/features/agent/chat/hooks/useDocumentPanel.js.map +1 -1
- package/lib/esm/features/facets/AgentRunnerFacetsNav.js +1 -1
- package/lib/esm/features/facets/AgentRunnerFacetsNav.js.map +1 -1
- package/lib/esm/features/facets/DocumentsFacetsNav.js +3 -2
- package/lib/esm/features/facets/DocumentsFacetsNav.js.map +1 -1
- package/lib/esm/features/facets/RunsFacetsNav.js +8 -1
- package/lib/esm/features/facets/RunsFacetsNav.js.map +1 -1
- package/lib/esm/features/facets/WorkflowExecutionsFacetsNav.js +1 -1
- package/lib/esm/features/facets/WorkflowExecutionsFacetsNav.js.map +1 -1
- package/lib/esm/features/facets/index.js +1 -0
- package/lib/esm/features/facets/index.js.map +1 -1
- package/lib/esm/features/facets/utils/VInteractionFacet.js +5 -5
- package/lib/esm/features/facets/utils/VInteractionFacet.js.map +1 -1
- package/lib/esm/features/index.js +1 -0
- package/lib/esm/features/index.js.map +1 -1
- package/lib/esm/features/oauth/OAuthProviderConnectButton.js +85 -0
- package/lib/esm/features/oauth/OAuthProviderConnectButton.js.map +1 -0
- package/lib/esm/features/oauth/RemoteMcpConnectionButton.js +119 -0
- package/lib/esm/features/oauth/RemoteMcpConnectionButton.js.map +1 -0
- package/lib/esm/features/oauth/index.js +4 -0
- package/lib/esm/features/oauth/index.js.map +1 -0
- package/lib/esm/features/oauth/useOAuthPopup.js +89 -0
- package/lib/esm/features/oauth/useOAuthPopup.js.map +1 -0
- package/lib/esm/features/store/collections/BrowseCollectionView.js.map +1 -1
- package/lib/esm/features/store/collections/EditCollectionView.js +9 -2
- package/lib/esm/features/store/collections/EditCollectionView.js.map +1 -1
- package/lib/esm/features/store/objects/components/ContentOverview.js +19 -7
- package/lib/esm/features/store/objects/components/ContentOverview.js.map +1 -1
- package/lib/esm/features/store/objects/components/useContentPanelHooks.js +35 -15
- package/lib/esm/features/store/objects/components/useContentPanelHooks.js.map +1 -1
- package/lib/esm/features/store/objects/selection/ObjectsActionContext.js +3 -3
- package/lib/esm/features/store/objects/selection/ObjectsActionContext.js.map +1 -1
- package/lib/esm/features/store/objects/selection/SelectionActions.js +4 -3
- package/lib/esm/features/store/objects/selection/SelectionActions.js.map +1 -1
- package/lib/esm/features/store/objects/selection/actions/ExportPropertiesAction.js +11 -3
- package/lib/esm/features/store/objects/selection/actions/ExportPropertiesAction.js.map +1 -1
- package/lib/esm/features/store/objects/upload/DocumentUploadModal.js +1 -5
- package/lib/esm/features/store/objects/upload/DocumentUploadModal.js.map +1 -1
- package/lib/esm/features/user/UserInfo.js +33 -10
- package/lib/esm/features/user/UserInfo.js.map +1 -1
- package/lib/esm/i18n/locales/ar.json +81 -98
- package/lib/esm/i18n/locales/de.json +44 -73
- package/lib/esm/i18n/locales/en.json +31 -61
- package/lib/esm/i18n/locales/es.json +55 -79
- package/lib/esm/i18n/locales/fr.json +55 -81
- package/lib/esm/i18n/locales/it.json +55 -79
- package/lib/esm/i18n/locales/ja.json +46 -75
- package/lib/esm/i18n/locales/ko.json +44 -73
- package/lib/esm/i18n/locales/pt.json +55 -79
- package/lib/esm/i18n/locales/ru.json +58 -81
- package/lib/esm/i18n/locales/tr.json +46 -75
- package/lib/esm/i18n/locales/zh-TW.json +46 -75
- package/lib/esm/i18n/locales/zh.json +46 -75
- package/lib/esm/session/UserSession.js +2 -4
- package/lib/esm/session/UserSession.js.map +1 -1
- package/lib/esm/session/UserSessionProvider.js +22 -17
- package/lib/esm/session/UserSessionProvider.js.map +1 -1
- package/lib/esm/session/auth/composable.js +20 -2
- package/lib/esm/session/auth/composable.js.map +1 -1
- package/lib/esm/session/auth/domainRouting.js +7 -0
- package/lib/esm/session/auth/domainRouting.js.map +1 -0
- package/lib/esm/shell/login/InviteAcceptModal.js +1 -0
- package/lib/esm/shell/login/InviteAcceptModal.js.map +1 -1
- package/lib/esm/widgets/form/Form.js +2 -2
- package/lib/esm/widgets/form/Form.js.map +1 -1
- package/lib/esm/widgets/markdown/MarkdownRenderer.js +2 -1
- package/lib/esm/widgets/markdown/MarkdownRenderer.js.map +1 -1
- package/lib/esm/widgets/markdown/preprocessMathDelimiters.js +226 -0
- package/lib/esm/widgets/markdown/preprocessMathDelimiters.js.map +1 -0
- package/lib/esm/widgets/monacoEditor/MonacoEditor.js +40 -5
- package/lib/esm/widgets/monacoEditor/MonacoEditor.js.map +1 -1
- package/lib/esm/widgets/monacoEditor/foldingProviders.js +132 -0
- package/lib/esm/widgets/monacoEditor/foldingProviders.js.map +1 -0
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/lib/types/core/components/ComboBox.d.ts +12 -2
- package/lib/types/core/components/ComboBox.d.ts.map +1 -1
- package/lib/types/core/components/FormItem.d.ts +5 -2
- package/lib/types/core/components/FormItem.d.ts.map +1 -1
- package/lib/types/core/components/SidePanel.d.ts.map +1 -1
- package/lib/types/core/components/shadcn/badge.d.ts +2 -2
- package/lib/types/core/components/shadcn/collaspible.d.ts +3 -3
- package/lib/types/core/components/shadcn/collaspible.d.ts.map +1 -1
- package/lib/types/core/components/shadcn/dropdown.d.ts +11 -3
- package/lib/types/core/components/shadcn/dropdown.d.ts.map +1 -1
- package/lib/types/core/components/shadcn/filters/filterBar.d.ts +2 -1
- package/lib/types/core/components/shadcn/filters/filterBar.d.ts.map +1 -1
- package/lib/types/core/components/shadcn/input.d.ts +1 -1
- package/lib/types/core/components/shadcn/radioGroup.d.ts.map +1 -1
- package/lib/types/core/components/shadcn/switch.d.ts.map +1 -1
- package/lib/types/core/components/shadcn/tabs.d.ts +4 -2
- package/lib/types/core/components/shadcn/tabs.d.ts.map +1 -1
- package/lib/types/core/components/shadcn/text.d.ts +1 -1
- package/lib/types/core/components/shadcn/tooltip.d.ts +1 -1
- package/lib/types/core/components/shadcn/tooltip.d.ts.map +1 -1
- package/lib/types/core/hooks/PortalContainerProvider.d.ts +1 -0
- package/lib/types/core/hooks/PortalContainerProvider.d.ts.map +1 -1
- package/lib/types/env/index.d.ts +2 -2
- package/lib/types/env/index.d.ts.map +1 -1
- package/lib/types/features/agent/chat/AgentChart.d.ts +1 -1
- package/lib/types/features/agent/chat/AgentChart.d.ts.map +1 -1
- package/lib/types/features/agent/chat/AgentRightPanel.d.ts +7 -2
- package/lib/types/features/agent/chat/AgentRightPanel.d.ts.map +1 -1
- package/lib/types/features/agent/chat/DocumentPanel.d.ts +2 -2
- package/lib/types/features/agent/chat/DocumentPanel.d.ts.map +1 -1
- package/lib/types/features/agent/chat/DocumentTabBar.d.ts +1 -2
- package/lib/types/features/agent/chat/DocumentTabBar.d.ts.map +1 -1
- package/lib/types/features/agent/chat/ModernAgentConversation.d.ts +5 -3
- package/lib/types/features/agent/chat/ModernAgentConversation.d.ts.map +1 -1
- package/lib/types/features/agent/chat/ModernAgentOutput/AllMessagesMixed.d.ts +4 -2
- package/lib/types/features/agent/chat/ModernAgentOutput/AllMessagesMixed.d.ts.map +1 -1
- package/lib/types/features/agent/chat/ModernAgentOutput/Header.d.ts +4 -4
- package/lib/types/features/agent/chat/ModernAgentOutput/Header.d.ts.map +1 -1
- package/lib/types/features/agent/chat/ModernAgentOutput/MessageItem.d.ts.map +1 -1
- package/lib/types/features/agent/chat/VegaLiteChart.d.ts +1 -1
- package/lib/types/features/agent/chat/VegaLiteChart.d.ts.map +1 -1
- package/lib/types/features/agent/chat/hooks/useAgentStream.d.ts +4 -2
- package/lib/types/features/agent/chat/hooks/useAgentStream.d.ts.map +1 -1
- package/lib/types/features/agent/chat/hooks/useDocumentPanel.d.ts +1 -0
- package/lib/types/features/agent/chat/hooks/useDocumentPanel.d.ts.map +1 -1
- package/lib/types/features/facets/DocumentsFacetsNav.d.ts.map +1 -1
- package/lib/types/features/facets/RunsFacetsNav.d.ts.map +1 -1
- package/lib/types/features/facets/index.d.ts +1 -0
- package/lib/types/features/facets/index.d.ts.map +1 -1
- package/lib/types/features/index.d.ts +1 -0
- package/lib/types/features/index.d.ts.map +1 -1
- package/lib/types/features/oauth/OAuthProviderConnectButton.d.ts +11 -0
- package/lib/types/features/oauth/OAuthProviderConnectButton.d.ts.map +1 -0
- package/lib/types/features/oauth/RemoteMcpConnectionButton.d.ts +25 -0
- package/lib/types/features/oauth/RemoteMcpConnectionButton.d.ts.map +1 -0
- package/lib/types/features/oauth/index.d.ts +4 -0
- package/lib/types/features/oauth/index.d.ts.map +1 -0
- package/lib/types/features/oauth/useOAuthPopup.d.ts +12 -0
- package/lib/types/features/oauth/useOAuthPopup.d.ts.map +1 -0
- package/lib/types/features/store/collections/BrowseCollectionView.d.ts.map +1 -1
- package/lib/types/features/store/collections/EditCollectionView.d.ts.map +1 -1
- package/lib/types/features/store/objects/components/useContentPanelHooks.d.ts.map +1 -1
- package/lib/types/features/store/objects/selection/ObjectsActionContext.d.ts +3 -3
- package/lib/types/features/store/objects/selection/ObjectsActionContext.d.ts.map +1 -1
- package/lib/types/features/store/objects/selection/ObjectsActionSpec.d.ts +2 -1
- package/lib/types/features/store/objects/selection/ObjectsActionSpec.d.ts.map +1 -1
- package/lib/types/features/store/objects/selection/SelectionActions.d.ts +3 -3
- package/lib/types/features/store/objects/selection/SelectionActions.d.ts.map +1 -1
- package/lib/types/features/store/objects/selection/actions/ExportPropertiesAction.d.ts.map +1 -1
- package/lib/types/features/user/UserInfo.d.ts +2 -1
- package/lib/types/features/user/UserInfo.d.ts.map +1 -1
- package/lib/types/session/UserSession.d.ts.map +1 -1
- package/lib/types/session/UserSessionProvider.d.ts +0 -1
- package/lib/types/session/UserSessionProvider.d.ts.map +1 -1
- package/lib/types/session/auth/composable.d.ts +4 -0
- package/lib/types/session/auth/composable.d.ts.map +1 -1
- package/lib/types/session/auth/domainRouting.d.ts +8 -0
- package/lib/types/session/auth/domainRouting.d.ts.map +1 -0
- package/lib/types/shell/login/InviteAcceptModal.d.ts.map +1 -1
- package/lib/types/widgets/markdown/MarkdownRenderer.d.ts.map +1 -1
- package/lib/types/widgets/markdown/preprocessMathDelimiters.d.ts +24 -0
- package/lib/types/widgets/markdown/preprocessMathDelimiters.d.ts.map +1 -0
- package/lib/types/widgets/monacoEditor/MonacoEditor.d.ts +2 -1
- package/lib/types/widgets/monacoEditor/MonacoEditor.d.ts.map +1 -1
- package/lib/types/widgets/monacoEditor/foldingProviders.d.ts +2 -0
- package/lib/types/widgets/monacoEditor/foldingProviders.d.ts.map +1 -0
- package/lib/vertesia-ui-core.js +1 -1
- package/lib/vertesia-ui-core.js.map +1 -1
- package/lib/vertesia-ui-env.js +1 -1
- package/lib/vertesia-ui-env.js.map +1 -1
- package/lib/vertesia-ui-features.js +1 -1
- package/lib/vertesia-ui-features.js.map +1 -1
- package/lib/vertesia-ui-i18n.js +1 -1
- package/lib/vertesia-ui-i18n.js.map +1 -1
- package/lib/vertesia-ui-layout.js +1 -1
- package/lib/vertesia-ui-layout.js.map +1 -1
- package/lib/vertesia-ui-session.js +1 -1
- package/lib/vertesia-ui-session.js.map +1 -1
- package/lib/vertesia-ui-shell.js +1 -1
- package/lib/vertesia-ui-shell.js.map +1 -1
- package/lib/vertesia-ui-widgets.js +1 -1
- package/lib/vertesia-ui-widgets.js.map +1 -1
- package/package.json +15 -15
- package/src/core/components/ComboBox.tsx +66 -29
- package/src/core/components/FormItem.tsx +9 -6
- package/src/core/components/SidePanel.tsx +5 -3
- package/src/core/components/shadcn/collaspible.tsx +5 -7
- package/src/core/components/shadcn/dropdown.tsx +68 -13
- package/src/core/components/shadcn/filters/comboBox/DateCombobox.tsx +6 -6
- package/src/core/components/shadcn/filters/filterBar.tsx +5 -3
- package/src/core/components/shadcn/radioGroup.tsx +1 -3
- package/src/core/components/shadcn/switch.tsx +0 -2
- package/src/core/components/shadcn/tabs.tsx +15 -2
- package/src/core/components/shadcn/tooltip.tsx +20 -3
- package/src/core/hooks/PortalContainerProvider.tsx +11 -3
- package/src/env/index.ts +7 -10
- package/src/features/agent/chat/AgentRightPanel.tsx +43 -23
- package/src/features/agent/chat/DocumentPanel.tsx +21 -19
- package/src/features/agent/chat/DocumentTabBar.tsx +21 -32
- package/src/features/agent/chat/ModernAgentConversation.tsx +72 -27
- package/src/features/agent/chat/ModernAgentOutput/AllMessagesMixed.tsx +21 -9
- package/src/features/agent/chat/ModernAgentOutput/Header.tsx +136 -115
- package/src/features/agent/chat/ModernAgentOutput/MessageItem.tsx +0 -3
- package/src/features/agent/chat/hooks/useAgentStream.ts +13 -7
- package/src/features/agent/chat/hooks/useDocumentPanel.ts +8 -0
- package/src/features/facets/AgentRunnerFacetsNav.tsx +1 -1
- package/src/features/facets/DocumentsFacetsNav.tsx +3 -1
- package/src/features/facets/RunsFacetsNav.tsx +9 -1
- package/src/features/facets/WorkflowExecutionsFacetsNav.tsx +1 -1
- package/src/features/facets/index.ts +1 -0
- package/src/features/facets/utils/VInteractionFacet.tsx +12 -12
- package/src/features/index.ts +1 -0
- package/src/features/oauth/OAuthProviderConnectButton.tsx +125 -0
- package/src/features/oauth/RemoteMcpConnectionButton.tsx +274 -0
- package/src/features/oauth/index.ts +3 -0
- package/src/features/oauth/useOAuthPopup.ts +125 -0
- package/src/features/store/collections/BrowseCollectionView.tsx +3 -3
- package/src/features/store/collections/EditCollectionView.tsx +10 -1
- package/src/features/store/objects/components/ContentOverview.tsx +108 -87
- package/src/features/store/objects/components/useContentPanelHooks.ts +50 -15
- package/src/features/store/objects/selection/ObjectsActionContext.tsx +5 -5
- package/src/features/store/objects/selection/ObjectsActionSpec.ts +2 -1
- package/src/features/store/objects/selection/SelectionActions.tsx +6 -5
- package/src/features/store/objects/selection/actions/ExportPropertiesAction.tsx +12 -3
- package/src/features/user/UserInfo.tsx +82 -10
- package/src/i18n/locales/ar.json +81 -98
- package/src/i18n/locales/de.json +44 -73
- package/src/i18n/locales/en.json +31 -61
- package/src/i18n/locales/es.json +55 -79
- package/src/i18n/locales/fr.json +55 -81
- package/src/i18n/locales/it.json +55 -79
- package/src/i18n/locales/ja.json +46 -75
- package/src/i18n/locales/ko.json +44 -73
- package/src/i18n/locales/pt.json +55 -79
- package/src/i18n/locales/ru.json +58 -81
- package/src/i18n/locales/tr.json +46 -75
- package/src/i18n/locales/zh-TW.json +46 -75
- package/src/i18n/locales/zh.json +46 -75
- package/src/session/UserSession.ts +2 -5
- package/src/session/UserSessionProvider.tsx +23 -18
- package/src/session/auth/auth-flow.md +1 -1
- package/src/session/auth/composable.ts +21 -2
- package/src/session/auth/domainRouting.test.ts +26 -0
- package/src/session/auth/domainRouting.ts +13 -0
- package/src/shell/login/InviteAcceptModal.tsx +1 -0
- package/src/widgets/form/Form.tsx +2 -2
- package/src/widgets/markdown/MarkdownRenderer.tsx +2 -1
- package/src/widgets/markdown/markdown.css +12 -0
- package/src/widgets/markdown/preprocessMathDelimiters.test.ts +87 -0
- package/src/widgets/markdown/preprocessMathDelimiters.ts +229 -0
- package/src/widgets/monacoEditor/MonacoEditor.tsx +47 -4
- package/src/widgets/monacoEditor/foldingProviders.ts +122 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vertesia/ui",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.1.0-dev.20260427.060440Z",
|
|
4
4
|
"description": "Vertesia UI components and and hooks",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
"@floating-ui/react": "^0.27.11",
|
|
25
25
|
"@monaco-editor/react": "^4.7.0",
|
|
26
26
|
"@radix-ui/react-checkbox": "^1.3.1",
|
|
27
|
+
"@radix-ui/react-collapsible": "^1.1.12",
|
|
27
28
|
"@radix-ui/react-dialog": "^1.1.13",
|
|
28
29
|
"@radix-ui/react-dismissable-layer": "^1.1.11",
|
|
29
30
|
"@radix-ui/react-dropdown-menu": "^2.1.16",
|
|
@@ -32,12 +33,12 @@
|
|
|
32
33
|
"@radix-ui/react-label": "^2.1.6",
|
|
33
34
|
"@radix-ui/react-popover": "^1.1.13",
|
|
34
35
|
"@radix-ui/react-portal": "^1.1.9",
|
|
36
|
+
"@radix-ui/react-radio-group": "^1.3.8",
|
|
35
37
|
"@radix-ui/react-separator": "^1.1.6",
|
|
36
38
|
"@radix-ui/react-slot": "^1.2.2",
|
|
39
|
+
"@radix-ui/react-switch": "^1.2.6",
|
|
37
40
|
"@radix-ui/react-tabs": "^1.1.11",
|
|
38
41
|
"@radix-ui/react-tooltip": "^1.2.6",
|
|
39
|
-
"@radix-ui/react-radio-group": "^1.3.8",
|
|
40
|
-
"@radix-ui/react-switch": "^1.2.6",
|
|
41
42
|
"ajv": "^8.17.1",
|
|
42
43
|
"ajv-formats": "^3.0.1",
|
|
43
44
|
"aria-hidden": "^1.2.6",
|
|
@@ -47,10 +48,10 @@
|
|
|
47
48
|
"dayjs": "^1.11.19",
|
|
48
49
|
"debounce": "^2.2.0",
|
|
49
50
|
"dompurify": "^3.3.2",
|
|
50
|
-
"fast-xml-parser": "^5.
|
|
51
|
+
"fast-xml-parser": "^5.7.2",
|
|
51
52
|
"firebase": "^10.12.2",
|
|
52
53
|
"framer-motion": "^12.23.12",
|
|
53
|
-
"i18next": "^
|
|
54
|
+
"i18next": "^26.0.1",
|
|
54
55
|
"jwt-decode": "^4.0.0",
|
|
55
56
|
"katex": "^0.16.28",
|
|
56
57
|
"lodash-es": "^4.17.23",
|
|
@@ -59,13 +60,12 @@
|
|
|
59
60
|
"monaco-editor": "^0.52.2",
|
|
60
61
|
"motion": "^12.12.1",
|
|
61
62
|
"papaparse": "^5.5.3",
|
|
62
|
-
"radix-ui": "^1.4.3",
|
|
63
63
|
"react": "^19.2.3",
|
|
64
64
|
"react-calendar": "^6.0.0",
|
|
65
65
|
"react-date-picker": "^12.0.1",
|
|
66
66
|
"react-dom": "^19.2.3",
|
|
67
67
|
"react-error-boundary": "^6.0.0",
|
|
68
|
-
"react-i18next": "^
|
|
68
|
+
"react-i18next": "^17.0.2",
|
|
69
69
|
"react-markdown": "^10.1.0",
|
|
70
70
|
"react-pdf": "^10.2.0",
|
|
71
71
|
"react-remove-scroll": "^2.7.1",
|
|
@@ -86,10 +86,10 @@
|
|
|
86
86
|
"vega": "^6.2.0",
|
|
87
87
|
"vega-embed": "^7.1.0",
|
|
88
88
|
"vega-lite": "^6.4.1",
|
|
89
|
-
"@vertesia/client": "1.0.
|
|
90
|
-
"@vertesia/
|
|
91
|
-
"@vertesia/
|
|
92
|
-
"@vertesia/json": "1.0.
|
|
89
|
+
"@vertesia/client": "1.1.0-dev.20260427.060440Z",
|
|
90
|
+
"@vertesia/fusion-ux": "1.1.0-dev.20260427.060440Z",
|
|
91
|
+
"@vertesia/common": "1.1.0-dev.20260427.060440Z",
|
|
92
|
+
"@vertesia/json": "1.1.0-dev.20260427.060440Z"
|
|
93
93
|
},
|
|
94
94
|
"devDependencies": {
|
|
95
95
|
"@eslint/compat": "^2.0.2",
|
|
@@ -100,7 +100,7 @@
|
|
|
100
100
|
"@rollup/plugin-terser": "^0.4.4",
|
|
101
101
|
"@types/hast": "^3.0.4",
|
|
102
102
|
"@types/lodash-es": "^4.17.12",
|
|
103
|
-
"@types/node": "^
|
|
103
|
+
"@types/node": "^25.6.0",
|
|
104
104
|
"@types/papaparse": "^5.5.2",
|
|
105
105
|
"@types/react": "^19.2.3",
|
|
106
106
|
"@types/react-dom": "^19.2.3",
|
|
@@ -109,11 +109,11 @@
|
|
|
109
109
|
"eslint-plugin-import": "^2.32.0",
|
|
110
110
|
"eslint-plugin-react": "^7.37.5",
|
|
111
111
|
"eslint-plugin-react-hooks": "^7.0.1",
|
|
112
|
-
"i18next-
|
|
112
|
+
"i18next-cli": "^1.51.5",
|
|
113
113
|
"rimraf": "^6.1.2",
|
|
114
114
|
"rollup": "^4.59.0",
|
|
115
|
-
"typescript": "^
|
|
116
|
-
"typescript-eslint": "^8.
|
|
115
|
+
"typescript": "^6.0.2",
|
|
116
|
+
"typescript-eslint": "^8.58.1",
|
|
117
117
|
"vitest": "^4.0.16"
|
|
118
118
|
},
|
|
119
119
|
"exports": {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { ChevronDownIcon, ChevronUpIcon } from 'lucide-react';
|
|
1
|
+
import { ChevronDownIcon, ChevronUpIcon, XIcon } from 'lucide-react';
|
|
2
2
|
import clsx from 'clsx';
|
|
3
3
|
import React, { ReactNode, useEffect, useRef, useState } from 'react';
|
|
4
4
|
import { AlignType, Popup, PopupController } from "./popup/index";
|
|
5
5
|
|
|
6
|
-
const INPUT_UNSTYLED = "block m-0 p-0 border-0 focus:outline-none focus:ring-0
|
|
7
|
-
const INPUT_NO_PADDING = "block sm:text-sm sm:leading-6 rounded-md border-0
|
|
6
|
+
const INPUT_UNSTYLED = "block m-0 p-0 border-0 focus:outline-none focus:ring-0";
|
|
7
|
+
const INPUT_NO_PADDING = "block sm:text-sm sm:leading-6 bg-muted rounded-md border-0 shadow-sm ring-1 ring-inset ring-muted placeholder:text-muted focus:ring-2 focus:ring-inset focus:ring-primary"
|
|
8
8
|
const INPUT = INPUT_NO_PADDING + " py-1.5";
|
|
9
9
|
const COMBOBOX_POPUP = "combobox-popup";
|
|
10
10
|
|
|
@@ -66,7 +66,7 @@ export function getDefaultComboBoxLayout<T>(fullWidth?: boolean, unstyledInput?:
|
|
|
66
66
|
buttonRight: 4,
|
|
67
67
|
buttonWidth: 24,
|
|
68
68
|
maxMenuHeight: 240,
|
|
69
|
-
menuClass: "w-72
|
|
69
|
+
menuClass: "w-72 mt-1 border-popover bg-popover text-popover-foreground shadow-md overflow-auto p-0 z-10",
|
|
70
70
|
inputClass: clsx(unstyledInput ? INPUT_UNSTYLED : INPUT, fullWidth ? "w-full" : "!w-auto"),
|
|
71
71
|
optionClass: "py-2 px-3 shadow-sm flex flex-col [&.option-selected]:font-semibold [&.option-highlighted]:bg-blue-300",
|
|
72
72
|
Input: ComboInput<T>,
|
|
@@ -84,7 +84,7 @@ export interface ComboBoxApi<T> {
|
|
|
84
84
|
setInputValue: (value: string) => void;
|
|
85
85
|
focus: () => void;
|
|
86
86
|
}
|
|
87
|
-
interface ComboBoxProps<T> {
|
|
87
|
+
export interface ComboBoxProps<T> {
|
|
88
88
|
items: T[];
|
|
89
89
|
adapter: OptionAdapter<T>;
|
|
90
90
|
// if true then the default layout will use an unstyled input
|
|
@@ -103,8 +103,14 @@ interface ComboBoxProps<T> {
|
|
|
103
103
|
focusOnMount?: boolean
|
|
104
104
|
menuGap?: number;
|
|
105
105
|
menuAlign?: AlignType;
|
|
106
|
+
// show X button to clear the current selection
|
|
107
|
+
clearable?: boolean;
|
|
108
|
+
// shown inside the dropdown when filter produces zero results
|
|
109
|
+
noMatchMessage?: ReactNode;
|
|
110
|
+
// open the menu when the input is focused
|
|
111
|
+
openOnFocus?: boolean;
|
|
106
112
|
}
|
|
107
|
-
export function ComboBox<T>({ menuAlign = "fill", menuGap, focusOnMount, onSelect, value, zIndex, unstyledInput, fullWidth, api, layout: layoutOpts, adapter, items, placeholder }: ComboBoxProps<T>) {
|
|
113
|
+
export function ComboBox<T>({ menuAlign = "fill", menuGap, focusOnMount, onSelect, value, zIndex, unstyledInput, fullWidth, api, layout: layoutOpts, adapter, items, placeholder, clearable, noMatchMessage, openOnFocus }: ComboBoxProps<T>) {
|
|
108
114
|
const [popupId] = useState(genComboboxPopupId());
|
|
109
115
|
const popupCtrl = useRef<PopupController | undefined>(undefined);
|
|
110
116
|
const inputRef = useRef<HTMLInputElement>(null);
|
|
@@ -143,11 +149,11 @@ export function ComboBox<T>({ menuAlign = "fill", menuGap, focusOnMount, onSelec
|
|
|
143
149
|
}
|
|
144
150
|
}, [api, ctrl, inputRef.current]);
|
|
145
151
|
|
|
146
|
-
const showMenu = ctrl.isMenuOpen && ctrl.filteredItems.length > 0;
|
|
152
|
+
const showMenu = ctrl.isMenuOpen && (ctrl.filteredItems.length > 0 || !!noMatchMessage);
|
|
147
153
|
|
|
148
154
|
return (
|
|
149
155
|
<>
|
|
150
|
-
<layout.Input boxRef={inputBoxRef} inputRef={inputRef} ctrl={ctrl} layout={layout} placeholder={placeholder} />
|
|
156
|
+
<layout.Input boxRef={inputBoxRef} inputRef={inputRef} ctrl={ctrl} layout={layout} placeholder={placeholder} clearable={clearable} openOnFocus={openOnFocus} />
|
|
151
157
|
<Popup
|
|
152
158
|
id={popupId}
|
|
153
159
|
ctrlRef={popupCtrl}
|
|
@@ -159,7 +165,7 @@ export function ComboBox<T>({ menuAlign = "fill", menuGap, focusOnMount, onSelec
|
|
|
159
165
|
align: menuAlign,
|
|
160
166
|
gap: menuGap != null ? menuGap : 4
|
|
161
167
|
}}>
|
|
162
|
-
<layout.Menu fillWidth={menuAlign === "fill"} items={ctrl.filteredItems} ctrl={ctrl} layout={layout} adapter={adapter} />
|
|
168
|
+
<layout.Menu fillWidth={menuAlign === "fill"} items={ctrl.filteredItems} ctrl={ctrl} layout={layout} adapter={adapter} noMatchMessage={noMatchMessage} />
|
|
163
169
|
</Popup>
|
|
164
170
|
</>
|
|
165
171
|
);
|
|
@@ -171,29 +177,42 @@ export interface ComboInputProps<T> {
|
|
|
171
177
|
placeholder?: string
|
|
172
178
|
boxRef?: React.RefObject<HTMLDivElement | null>;
|
|
173
179
|
inputRef?: React.RefObject<HTMLInputElement | null>;
|
|
180
|
+
clearable?: boolean;
|
|
181
|
+
openOnFocus?: boolean;
|
|
174
182
|
}
|
|
175
|
-
function ComboInput<T>({ inputRef, placeholder, boxRef, ctrl, layout }: ComboInputProps<T>) {
|
|
176
|
-
const buttonWidth = layout.buttonWidth;
|
|
177
|
-
const style = buttonWidth > 0 ? { paddingRight: `${buttonWidth}px` } : undefined;
|
|
183
|
+
function ComboInput<T>({ inputRef, placeholder, boxRef, ctrl, layout, clearable, openOnFocus }: ComboInputProps<T>) {
|
|
178
184
|
const Toggle = layout.Toggle;
|
|
185
|
+
const showClear = clearable && ctrl.selectedItem != null;
|
|
186
|
+
const buttonCount = (Toggle ? 1 : 0) + (showClear ? 1 : 0);
|
|
187
|
+
const style = buttonCount > 0 ? { paddingRight: `${layout.buttonWidth * buttonCount + layout.buttonRight}px` } : undefined;
|
|
179
188
|
return (
|
|
180
189
|
<div className="relative" ref={boxRef}>
|
|
181
|
-
<input
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
190
|
+
<input
|
|
191
|
+
ref={inputRef}
|
|
192
|
+
placeholder={placeholder}
|
|
193
|
+
{...ctrl.getInputProps()}
|
|
194
|
+
onFocus={openOnFocus ? () => ctrl.openMenu() : undefined}
|
|
195
|
+
style={style}
|
|
196
|
+
className={layout.inputClass}
|
|
197
|
+
/>
|
|
198
|
+
<div style={{ position: 'absolute', right: `${layout.buttonRight}px`, top: 0, bottom: 0, display: 'flex', alignItems: 'center', gap: '2px' }}>
|
|
199
|
+
{showClear && (
|
|
200
|
+
<button
|
|
201
|
+
style={{ border: 'none', padding: 0, margin: 0, backgroundColor: 'transparent', cursor: 'pointer', display: 'flex', alignItems: 'center', width: `${layout.buttonWidth}px` }}
|
|
202
|
+
onClick={() => { ctrl.selectedItem = null; }}
|
|
203
|
+
>
|
|
204
|
+
<XIcon className="w-4 h-4" />
|
|
205
|
+
</button>
|
|
206
|
+
)}
|
|
207
|
+
{Toggle && (
|
|
208
|
+
<button
|
|
209
|
+
style={{ width: `${layout.buttonWidth}px`, border: 'none', padding: 0, margin: 0, backgroundColor: 'transparent', display: 'flex', alignItems: 'center', justifyContent: 'center' }}
|
|
210
|
+
{...ctrl.getToggleButtonProps()}
|
|
211
|
+
>
|
|
212
|
+
<Toggle ctrl={ctrl} layout={layout} />
|
|
213
|
+
</button>
|
|
214
|
+
)}
|
|
215
|
+
</div>
|
|
197
216
|
</div>
|
|
198
217
|
)
|
|
199
218
|
}
|
|
@@ -212,9 +231,15 @@ export interface ComboMenuProps<T> {
|
|
|
212
231
|
ctrl: ComboboxController<T>;
|
|
213
232
|
adapter: OptionAdapter<T>;
|
|
214
233
|
fillWidth: boolean;
|
|
234
|
+
noMatchMessage?: ReactNode;
|
|
215
235
|
}
|
|
216
|
-
function ComboMenu<T>({ fillWidth, items, layout, ctrl, adapter }: ComboMenuProps<T>) {
|
|
236
|
+
function ComboMenu<T>({ fillWidth, items, layout, ctrl, adapter, noMatchMessage }: ComboMenuProps<T>) {
|
|
217
237
|
const { highlightedIndex, selectedItem } = ctrl;
|
|
238
|
+
if (items.length === 0) {
|
|
239
|
+
return noMatchMessage
|
|
240
|
+
? <div style={{ width: fillWidth ? '100%' : undefined }} className={layout.menuClass}>{noMatchMessage}</div>
|
|
241
|
+
: null;
|
|
242
|
+
}
|
|
218
243
|
return (
|
|
219
244
|
<ul style={{ width: fillWidth ? "100%" : undefined, maxHeight: layout.maxMenuHeight ? `${layout.maxMenuHeight}px` : '240px' }}
|
|
220
245
|
className={layout.menuClass} {...ctrl.getMenuProps()}>
|
|
@@ -485,4 +510,16 @@ function incrModulo(value: number, max: number) {
|
|
|
485
510
|
}
|
|
486
511
|
function decrModulo(value: number, max: number) {
|
|
487
512
|
return (value - 1 + max) % max;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
export function SimpleCombobox({
|
|
516
|
+
options,
|
|
517
|
+
creatable,
|
|
518
|
+
...rest
|
|
519
|
+
}: Omit<ComboBoxProps<string>, 'adapter' | 'items'> & {
|
|
520
|
+
options: string[];
|
|
521
|
+
creatable?: boolean;
|
|
522
|
+
}) {
|
|
523
|
+
const adapter = creatable ? StringOptionAdapterWithCreate.instance : StringOptionAdapter.instance;
|
|
524
|
+
return <ComboBox adapter={adapter} items={options} {...rest} />;
|
|
488
525
|
}
|
|
@@ -7,17 +7,20 @@ import { Info } from 'lucide-react';
|
|
|
7
7
|
interface FormItemProps {
|
|
8
8
|
label: any;
|
|
9
9
|
children: ReactNode;
|
|
10
|
+
childrenId?: string;
|
|
10
11
|
className?: string;
|
|
11
12
|
description?: ReactNode;
|
|
12
13
|
required?: boolean;
|
|
13
|
-
direction?: "row" | "column";
|
|
14
|
+
direction?: "row" | "column" | "row-reverse";
|
|
14
15
|
disabled?: boolean;
|
|
16
|
+
/** When true, the label row stretches to full width. Useful when placing actions (e.g. buttons) inside the label. */
|
|
17
|
+
fullWidthLabel?: boolean;
|
|
15
18
|
}
|
|
16
|
-
export function FormItem({ description, required, label, className, direction = "column", children, disabled = false }: FormItemProps) {
|
|
19
|
+
export function FormItem({ description, required, label, className, direction = "column", children, disabled = false, fullWidthLabel = false, childrenId }: FormItemProps) {
|
|
17
20
|
return (
|
|
18
|
-
<div className={clsx("flex w-full space-y-1", className, direction === "row" ? "flex-row justify-between items-center gap-2" : "flex-col")}>
|
|
19
|
-
<div className='flex items-center gap-1'>
|
|
20
|
-
<label className={`text-sm font-medium mb-1 ${disabled ? "text-muted" : ""}`}>
|
|
21
|
+
<div className={clsx("flex w-full space-y-1", className, direction === "row" ? "flex-row justify-between items-center gap-2" : direction === "row-reverse" ? "flex-row-reverse justify-between items-center gap-2" : "flex-col")}>
|
|
22
|
+
<div className={clsx('flex items-center gap-1 mb-0', fullWidthLabel && 'w-full')}>
|
|
23
|
+
<label htmlFor={childrenId} className={`text-sm font-medium mb-1 ${disabled ? "text-muted" : ""} ${fullWidthLabel && "flex-1"}`}>
|
|
21
24
|
{label}{required ? <span className='text-destructive -mt-4 ml-1'>*</span> : ""}
|
|
22
25
|
</label>
|
|
23
26
|
{
|
|
@@ -33,4 +36,4 @@ export function FormItem({ description, required, label, className, direction =
|
|
|
33
36
|
{children}
|
|
34
37
|
</div>
|
|
35
38
|
);
|
|
36
|
-
}
|
|
39
|
+
}
|
|
@@ -86,7 +86,7 @@ export function SidePanel({ isOpen, title, onClose, children, panelWidth = 768,
|
|
|
86
86
|
<Minus className="rotate-90 font-semibold" strokeWidth={4} />
|
|
87
87
|
</div>
|
|
88
88
|
)}
|
|
89
|
-
<div className={`flex-1 flex flex-col bg-background shadow-xl ${className}`}>
|
|
89
|
+
<div className={`flex-1 min-w-0 flex flex-col bg-background shadow-xl ${className}`}>
|
|
90
90
|
{/* Sticky header */}
|
|
91
91
|
{title && (
|
|
92
92
|
<div className="sticky top-0 z-10 bg-background px-2 sm:px-4 py-2 border-b">
|
|
@@ -102,8 +102,10 @@ export function SidePanel({ isOpen, title, onClose, children, panelWidth = 768,
|
|
|
102
102
|
)}
|
|
103
103
|
|
|
104
104
|
{/* Scrollable content */}
|
|
105
|
-
<div className={contentClassName ?? "flex-1 overflow-
|
|
106
|
-
|
|
105
|
+
<div className={contentClassName ?? "flex-1 overflow-auto px-2 sm:px-4 py-4"}>
|
|
106
|
+
<div className='w-full h-full flex-1 flex flex-col'>
|
|
107
|
+
{children}
|
|
108
|
+
</div>
|
|
107
109
|
</div>
|
|
108
110
|
</div>
|
|
109
111
|
</div>
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import { Collapsible as CollapsiblePrimitive } from "radix-ui"
|
|
1
|
+
import * as CollapsiblePrimitive from "@radix-ui/react-collapsible"
|
|
4
2
|
|
|
5
3
|
function Collapsible({
|
|
6
4
|
...props
|
|
@@ -10,9 +8,9 @@ function Collapsible({
|
|
|
10
8
|
|
|
11
9
|
function CollapsibleTrigger({
|
|
12
10
|
...props
|
|
13
|
-
}: React.ComponentProps<typeof CollapsiblePrimitive.
|
|
11
|
+
}: React.ComponentProps<typeof CollapsiblePrimitive.Trigger>) {
|
|
14
12
|
return (
|
|
15
|
-
<CollapsiblePrimitive.
|
|
13
|
+
<CollapsiblePrimitive.Trigger
|
|
16
14
|
data-slot="collapsible-trigger"
|
|
17
15
|
{...props}
|
|
18
16
|
/>
|
|
@@ -21,9 +19,9 @@ function CollapsibleTrigger({
|
|
|
21
19
|
|
|
22
20
|
function CollapsibleContent({
|
|
23
21
|
...props
|
|
24
|
-
}: React.ComponentProps<typeof CollapsiblePrimitive.
|
|
22
|
+
}: React.ComponentProps<typeof CollapsiblePrimitive.Content>) {
|
|
25
23
|
return (
|
|
26
|
-
<CollapsiblePrimitive.
|
|
24
|
+
<CollapsiblePrimitive.Content
|
|
27
25
|
data-slot="collapsible-content"
|
|
28
26
|
{...props}
|
|
29
27
|
/>
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
"use client"
|
|
2
|
-
|
|
3
1
|
import * as React from "react"
|
|
4
|
-
import
|
|
2
|
+
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"
|
|
5
3
|
|
|
6
4
|
import { cn } from "../libs/utils"
|
|
7
5
|
|
|
8
6
|
import { CheckIcon, ChevronRightIcon } from "lucide-react"
|
|
9
7
|
|
|
8
|
+
const HoverMenuContext = React.createContext(false);
|
|
9
|
+
|
|
10
10
|
function DropdownMenu({
|
|
11
11
|
...props
|
|
12
12
|
}: React.ComponentProps<typeof DropdownMenuPrimitive.Root>) {
|
|
@@ -74,7 +74,7 @@ function DropdownMenuItem({
|
|
|
74
74
|
data-inset={inset}
|
|
75
75
|
data-variant={variant}
|
|
76
76
|
className={cn(
|
|
77
|
-
"
|
|
77
|
+
"hover:bg-muted focus:bg-muted data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:text-destructive gap-2 rounded-md px-1.5 py-1 text-sm data-inset:pl-7 [&_svg:not([class*='size-'])]:size-4 group/dropdown-menu-item relative flex cursor-default items-center outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
|
78
78
|
className
|
|
79
79
|
)}
|
|
80
80
|
{...props}
|
|
@@ -96,7 +96,7 @@ function DropdownMenuCheckboxItem({
|
|
|
96
96
|
data-slot="dropdown-menu-checkbox-item"
|
|
97
97
|
data-inset={inset}
|
|
98
98
|
className={cn(
|
|
99
|
-
"focus:bg-
|
|
99
|
+
"focus:bg-muted focus:text-muted focus:**:text-muted gap-2 rounded-md py-1 pr-8 pl-1.5 text-sm data-inset:pl-7 [&_svg:not([class*='size-'])]:size-4 relative flex cursor-default items-center outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
|
100
100
|
className
|
|
101
101
|
)}
|
|
102
102
|
checked={checked}
|
|
@@ -140,7 +140,7 @@ function DropdownMenuRadioItem({
|
|
|
140
140
|
data-slot="dropdown-menu-radio-item"
|
|
141
141
|
data-inset={inset}
|
|
142
142
|
className={cn(
|
|
143
|
-
"focus:bg-
|
|
143
|
+
"focus:bg-muted focus:text-muted focus:**:text-muted gap-2 rounded-md py-1 pr-8 pl-1.5 text-sm data-inset:pl-7 [&_svg:not([class*='size-'])]:size-4 relative flex cursor-default items-center outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
|
144
144
|
className
|
|
145
145
|
)}
|
|
146
146
|
{...props}
|
|
@@ -170,7 +170,7 @@ function DropdownMenuLabel({
|
|
|
170
170
|
<DropdownMenuPrimitive.Label
|
|
171
171
|
data-slot="dropdown-menu-label"
|
|
172
172
|
data-inset={inset}
|
|
173
|
-
className={cn("text-muted
|
|
173
|
+
className={cn("text-muted px-1.5 py-1 text-xs font-medium data-inset:pl-7", className)}
|
|
174
174
|
{...props}
|
|
175
175
|
/>
|
|
176
176
|
)
|
|
@@ -196,7 +196,7 @@ function DropdownMenuShortcut({
|
|
|
196
196
|
return (
|
|
197
197
|
<span
|
|
198
198
|
data-slot="dropdown-menu-shortcut"
|
|
199
|
-
className={cn("text-muted
|
|
199
|
+
className={cn("text-muted group-focus/dropdown-menu-item:text-muted ml-auto text-xs tracking-widest", className)}
|
|
200
200
|
{...props}
|
|
201
201
|
/>
|
|
202
202
|
)
|
|
@@ -221,7 +221,7 @@ function DropdownMenuSubTrigger({
|
|
|
221
221
|
data-slot="dropdown-menu-sub-trigger"
|
|
222
222
|
data-inset={inset}
|
|
223
223
|
className={cn(
|
|
224
|
-
"focus:bg-
|
|
224
|
+
"focus:bg-muted focus:text-muted data-open:bg-muted data-open:text-muted not-data-[variant=destructive]:focus:**:text-muted gap-2 rounded-md px-1.5 py-1 text-sm data-inset:pl-7 [&_svg:not([class*='size-'])]:size-4 flex cursor-default items-center outline-hidden select-none [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
|
225
225
|
className
|
|
226
226
|
)}
|
|
227
227
|
{...props}
|
|
@@ -271,8 +271,35 @@ interface DropdownProps {
|
|
|
271
271
|
trigger: React.ReactNode;
|
|
272
272
|
children: React.ReactNode | React.ReactNode[];
|
|
273
273
|
align?: 'left' | 'center' | 'right';
|
|
274
|
+
hover?: boolean;
|
|
274
275
|
}
|
|
275
|
-
export function Dropdown({ trigger, children, align = 'right' }: DropdownProps) {
|
|
276
|
+
export function Dropdown({ trigger, children, align = 'right', hover }: DropdownProps) {
|
|
277
|
+
const [open, setOpen] = React.useState(false);
|
|
278
|
+
const closeTimer = React.useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
279
|
+
|
|
280
|
+
if (hover) {
|
|
281
|
+
const onEnter = () => {
|
|
282
|
+
if (closeTimer.current) clearTimeout(closeTimer.current);
|
|
283
|
+
setOpen(true);
|
|
284
|
+
};
|
|
285
|
+
const onLeave = () => {
|
|
286
|
+
closeTimer.current = setTimeout(() => setOpen(false), 80);
|
|
287
|
+
};
|
|
288
|
+
const alignClass = align === 'right' ? 'right-0' : align === 'center' ? 'left-1/2 -translate-x-1/2' : 'left-0';
|
|
289
|
+
return (
|
|
290
|
+
<div className="relative inline-flex" onMouseEnter={onEnter} onMouseLeave={onLeave}>
|
|
291
|
+
{trigger}
|
|
292
|
+
{open && (
|
|
293
|
+
<div className={cn('absolute top-full pt-1 z-50', alignClass)}>
|
|
294
|
+
<div className="min-w-32 rounded-lg p-1 shadow-md ring-1 ring-foreground/10 bg-popover text-popover-foreground">
|
|
295
|
+
<HoverMenuContext.Provider value={true}>{children}</HoverMenuContext.Provider>
|
|
296
|
+
</div>
|
|
297
|
+
</div>
|
|
298
|
+
)}
|
|
299
|
+
</div>
|
|
300
|
+
);
|
|
301
|
+
}
|
|
302
|
+
|
|
276
303
|
return (
|
|
277
304
|
<DropdownMenu>
|
|
278
305
|
<DropdownMenuTrigger asChild>
|
|
@@ -287,19 +314,47 @@ export function Dropdown({ trigger, children, align = 'right' }: DropdownProps)
|
|
|
287
314
|
);
|
|
288
315
|
}
|
|
289
316
|
|
|
317
|
+
interface MenuGroupProps {
|
|
318
|
+
children: React.ReactNode | React.ReactNode[];
|
|
319
|
+
label?: string;
|
|
320
|
+
}
|
|
321
|
+
export function MenuGroup({ children, label }: MenuGroupProps) {
|
|
322
|
+
return (
|
|
323
|
+
<DropdownMenuGroup>
|
|
324
|
+
{label && <DropdownMenuLabel>{label}</DropdownMenuLabel>}
|
|
325
|
+
{children}
|
|
326
|
+
</DropdownMenuGroup>
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
|
|
290
330
|
interface MenuItemProps {
|
|
291
331
|
children: React.ReactNode | React.ReactNode[];
|
|
292
332
|
onClick?: (ev: React.MouseEvent) => void;
|
|
293
333
|
href?: string;
|
|
294
334
|
closeOnClick?: boolean;
|
|
295
335
|
isDisabled?: boolean;
|
|
336
|
+
variant?: "default" | "destructive";
|
|
337
|
+
className?: string;
|
|
296
338
|
}
|
|
297
|
-
export function MenuItem({ children, href, onClick,
|
|
339
|
+
export function MenuItem({ children, href, onClick, isDisabled = false, variant = "default", className }: MenuItemProps) {
|
|
340
|
+
const isHoverMenu = React.useContext(HoverMenuContext);
|
|
341
|
+
const baseClass = cn(
|
|
342
|
+
"w-full gap-2 rounded-md px-1.5 py-1 text-sm text-nowrap [&_svg:not([class*='size-'])]:size-4 flex cursor-default items-center select-none [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
|
343
|
+
variant === 'destructive' ? 'text-destructive' : '',
|
|
344
|
+
isDisabled ? 'pointer-events-none opacity-50' : 'hover:bg-muted focus:bg-muted',
|
|
345
|
+
className
|
|
346
|
+
);
|
|
347
|
+
if (isHoverMenu) {
|
|
348
|
+
const handleClick = (e: React.MouseEvent) => { e.stopPropagation(); onClick?.(e); };
|
|
349
|
+
return href
|
|
350
|
+
? <a href={href} className={baseClass}>{children}</a>
|
|
351
|
+
: <button className={baseClass} disabled={isDisabled} onClick={handleClick}>{children}</button>;
|
|
352
|
+
}
|
|
298
353
|
return (
|
|
299
354
|
<DropdownMenuItem
|
|
300
|
-
className="
|
|
355
|
+
className={cn("data-[disabled]:pointer-events-none data-[disabled]:opacity-50 text-nowrap", className)}
|
|
301
356
|
disabled={isDisabled}
|
|
302
|
-
|
|
357
|
+
variant={variant}
|
|
303
358
|
onClick={(e) => { e.stopPropagation(); onClick?.(e); }}
|
|
304
359
|
asChild={!!href}
|
|
305
360
|
>
|
|
@@ -19,21 +19,21 @@ export const DateCombobox = ({
|
|
|
19
19
|
const [localDateRange, setLocalDateRange] = useState<[Date | null, Date | null]>([null, null]);
|
|
20
20
|
const { t } = useUITranslation();
|
|
21
21
|
|
|
22
|
-
//
|
|
23
|
-
const selectedDate = filterValues[0] ?
|
|
22
|
+
// Parse with dayjs to interpret bare YYYY-MM-DD as local time (to match UI).
|
|
23
|
+
const selectedDate = filterValues[0] ? dayjs(filterValues[0]).toDate() : undefined;
|
|
24
24
|
|
|
25
25
|
// For date range - use local state for immediate feedback, fall back to filter values
|
|
26
26
|
const dateRange: [Date | null, Date | null] = isRange ? [
|
|
27
|
-
localDateRange[0] || (filterValues[0] ?
|
|
28
|
-
localDateRange[1] || (filterValues[1] ?
|
|
27
|
+
localDateRange[0] || (filterValues[0] ? dayjs(filterValues[0]).toDate() : null),
|
|
28
|
+
localDateRange[1] || (filterValues[1] ? dayjs(filterValues[1]).toDate() : null)
|
|
29
29
|
] : [null, null];
|
|
30
30
|
|
|
31
31
|
// Update local state when filter values change
|
|
32
32
|
useEffect(() => {
|
|
33
33
|
if (isRange) {
|
|
34
34
|
setLocalDateRange([
|
|
35
|
-
filterValues[0] ?
|
|
36
|
-
filterValues[1] ?
|
|
35
|
+
filterValues[0] ? dayjs(filterValues[0]).toDate() : null,
|
|
36
|
+
filterValues[1] ? dayjs(filterValues[1]).toDate() : null
|
|
37
37
|
]);
|
|
38
38
|
}
|
|
39
39
|
}, [filterValues, isRange]);
|
|
@@ -25,6 +25,7 @@ interface FilterProviderProps {
|
|
|
25
25
|
setFilters: Dispatch<SetStateAction<Filter[]>>;
|
|
26
26
|
filterGroups: FilterGroup[];
|
|
27
27
|
children: React.ReactNode;
|
|
28
|
+
inModal?: boolean;
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
// Syncs filters ↔ URL. On mount, captures the initial URL param and restores matching filters
|
|
@@ -33,14 +34,15 @@ interface FilterProviderProps {
|
|
|
33
34
|
// (prevents cross-page URL contamination, e.g. a modal inheriting a parent page's filters).
|
|
34
35
|
|
|
35
36
|
// Parse format with array indicators: filterName:value or filterName:[value1,value2]
|
|
36
|
-
const FilterProvider = ({ filters, setFilters, filterGroups, children }: FilterProviderProps) => {
|
|
37
|
+
const FilterProvider = ({ filters, setFilters, filterGroups, children, inModal }: FilterProviderProps) => {
|
|
37
38
|
const url = new URL(window.location.href);
|
|
38
39
|
const searchParams = url.searchParams;
|
|
39
40
|
const [initialFiltersParam] = React.useState(() => new URLSearchParams(window.location.search).get('filters'));
|
|
40
41
|
const processedUrlFilters = React.useRef<Set<string>>(new Set());
|
|
41
|
-
const hasRestoredFromUrl = React.useRef(!initialFiltersParam);
|
|
42
|
+
const hasRestoredFromUrl = React.useRef(inModal || !initialFiltersParam);
|
|
42
43
|
|
|
43
44
|
useEffect(() => {
|
|
45
|
+
if (inModal) return;
|
|
44
46
|
if (!hasRestoredFromUrl.current) return;
|
|
45
47
|
try {
|
|
46
48
|
const params = new URLSearchParams(searchParams.toString());
|
|
@@ -82,7 +84,7 @@ const FilterProvider = ({ filters, setFilters, filterGroups, children }: FilterP
|
|
|
82
84
|
}, [filters]);
|
|
83
85
|
|
|
84
86
|
useEffect(() => {
|
|
85
|
-
if (!initialFiltersParam || filterGroups.length === 0) return;
|
|
87
|
+
if (inModal || !initialFiltersParam || filterGroups.length === 0) return;
|
|
86
88
|
try {
|
|
87
89
|
const filterPairs = initialFiltersParam.split(';');
|
|
88
90
|
const newFilters: Filter[] = [];
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
"use client"
|
|
2
|
-
|
|
3
1
|
import * as RadioGroupPrimitive from "@radix-ui/react-radio-group"
|
|
4
2
|
import * as React from "react"
|
|
5
3
|
|
|
@@ -52,7 +50,7 @@ function RadioGroup<T = RadioGroupOption>({ onSelect, selected, options, adapter
|
|
|
52
50
|
const getId = (o: T) => adapter ? adapter.idOf(o) : (o as unknown as RadioGroupOption).id
|
|
53
51
|
const getLabel = (o: T) => adapter ? adapter.labelOf(o) : (o as unknown as RadioGroupOption).label
|
|
54
52
|
const getDescription = (o: T) => adapter ? adapter.descriptionOf(o) : (o as unknown as RadioGroupOption).description
|
|
55
|
-
const getSelectedClass = (o: T) => adapter ? adapter.selectedClassName(o) : 'border-
|
|
53
|
+
const getSelectedClass = (o: T) => adapter ? adapter.selectedClassName(o) : 'border-primary'
|
|
56
54
|
|
|
57
55
|
return (
|
|
58
56
|
<RadioGroupPrimitive.Root
|
|
@@ -153,7 +153,13 @@ const Tabs = ({
|
|
|
153
153
|
);
|
|
154
154
|
};
|
|
155
155
|
|
|
156
|
-
|
|
156
|
+
interface TabsBarProps {
|
|
157
|
+
className?: string;
|
|
158
|
+
sticky?: boolean;
|
|
159
|
+
direction?: "vertical" | "horizontal";
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const TabsBar = ({ className, sticky, direction }: TabsBarProps) => {
|
|
157
163
|
const { tabs, size, current, setTab, responsive, variant, updateHash } = React.useContext(TabsContext);
|
|
158
164
|
|
|
159
165
|
const fullWidth = size !== 0;
|
|
@@ -194,10 +200,17 @@ const TabsBar = ({ className, sticky }: { className?: string; sticky?: boolean }
|
|
|
194
200
|
/>
|
|
195
201
|
</div>
|
|
196
202
|
)}
|
|
197
|
-
<TabsList size={size} variant={variant}
|
|
203
|
+
<TabsList size={size} variant={variant}
|
|
204
|
+
className={cn((
|
|
205
|
+
fullWidth ? "w-full" : ""),
|
|
206
|
+
sticky && "sticky top-0 bg-background z-10",
|
|
207
|
+
direction === "vertical" ? "flex-col items-start" : "flex-row",
|
|
208
|
+
responsive ? "hidden lg:flex" : "",
|
|
209
|
+
className)}>
|
|
198
210
|
{tabs.map((tab) => (
|
|
199
211
|
|
|
200
212
|
<TabsTrigger
|
|
213
|
+
className={cn(direction === "vertical" ? "w-full text-left" : "")}
|
|
201
214
|
key={tab.name}
|
|
202
215
|
value={tab.name}
|
|
203
216
|
disabled={tab.disabled}
|