@vertesia/ui 0.79.0 → 0.79.1
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/Panel.js +8 -0
- package/lib/esm/core/components/Panel.js.map +1 -0
- package/lib/esm/core/components/SelectBox.js +1 -1
- package/lib/esm/core/components/SelectBox.js.map +1 -1
- package/lib/esm/core/components/SidePanel.js +2 -2
- package/lib/esm/core/components/SidePanel.js.map +1 -1
- package/lib/esm/core/components/index.js +1 -1
- package/lib/esm/core/components/index.js.map +1 -1
- package/lib/esm/core/components/shadcn/breadcrumb.js +29 -8
- package/lib/esm/core/components/shadcn/breadcrumb.js.map +1 -1
- package/lib/esm/core/components/shadcn/button.js +3 -2
- package/lib/esm/core/components/shadcn/button.js.map +1 -1
- package/lib/esm/core/components/shadcn/filters/filterBar.js +2 -2
- package/lib/esm/core/components/shadcn/filters/filterBar.js.map +1 -1
- package/lib/esm/core/components/shadcn/index.js +1 -0
- package/lib/esm/core/components/shadcn/index.js.map +1 -1
- package/lib/esm/core/components/shadcn/input.js +4 -1
- package/lib/esm/core/components/shadcn/input.js.map +1 -1
- package/lib/esm/core/components/shadcn/resizeable.js +2 -2
- package/lib/esm/core/components/shadcn/resizeable.js.map +1 -1
- package/lib/esm/core/components/shadcn/selectBox.js +15 -9
- package/lib/esm/core/components/shadcn/selectBox.js.map +1 -1
- package/lib/esm/core/components/shadcn/tabs.js +10 -3
- package/lib/esm/core/components/shadcn/tabs.js.map +1 -1
- package/lib/esm/core/components/shadcn/textarea.js +7 -0
- package/lib/esm/core/components/shadcn/textarea.js.map +1 -0
- package/lib/esm/core/hooks/CompositeState.js +139 -1
- package/lib/esm/core/hooks/CompositeState.js.map +1 -1
- package/lib/esm/core/hooks/index.js +1 -0
- package/lib/esm/core/hooks/index.js.map +1 -1
- package/lib/esm/core/hooks/useScrollableSearch.js +92 -0
- package/lib/esm/core/hooks/useScrollableSearch.js.map +1 -0
- package/lib/esm/env/index.js +1 -1
- package/lib/esm/env/index.js.map +1 -1
- package/lib/esm/features/agent/PayloadBuilder.js +80 -55
- package/lib/esm/features/agent/PayloadBuilder.js.map +1 -1
- package/lib/esm/features/agent/chat/ModernAgentConversation.js +22 -24
- package/lib/esm/features/agent/chat/ModernAgentConversation.js.map +1 -1
- package/lib/esm/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js +2 -3
- package/lib/esm/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js.map +1 -1
- package/lib/esm/features/agent/chat/ModernAgentOutput/Header.js +2 -2
- package/lib/esm/features/agent/chat/ModernAgentOutput/Header.js.map +1 -1
- package/lib/esm/features/agent/chat/ModernAgentOutput/InlineSlidingPlanPanel.js +15 -20
- package/lib/esm/features/agent/chat/ModernAgentOutput/InlineSlidingPlanPanel.js.map +1 -1
- package/lib/esm/features/agent/chat/ModernAgentOutput/PlanPanel.js +1 -0
- package/lib/esm/features/agent/chat/ModernAgentOutput/PlanPanel.js.map +1 -1
- package/lib/esm/features/agent/chat/ModernAgentOutput/SlidingPlanPanel.js +3 -3
- package/lib/esm/features/agent/chat/ModernAgentOutput/SlidingPlanPanel.js.map +1 -1
- package/lib/esm/features/agent/chat/ModernAgentOutput/WorkstreamTabs.js +6 -6
- package/lib/esm/features/agent/chat/ModernAgentOutput/WorkstreamTabs.js.map +1 -1
- package/lib/esm/features/facets/CollectionsFacetsNav.js +19 -0
- package/lib/esm/features/facets/CollectionsFacetsNav.js.map +1 -1
- package/lib/esm/features/facets/InteractionsFacetsNav.js +9 -3
- package/lib/esm/features/facets/InteractionsFacetsNav.js.map +1 -1
- package/lib/esm/features/facets/utils/VTypeFacet.js +4 -1
- package/lib/esm/features/facets/utils/VTypeFacet.js.map +1 -1
- package/lib/esm/features/layout/GenericPageNavHeader.js +58 -5
- package/lib/esm/features/layout/GenericPageNavHeader.js.map +1 -1
- package/lib/esm/features/store/collections/BrowseCollectionView.js +3 -0
- package/lib/esm/features/store/collections/BrowseCollectionView.js.map +1 -1
- package/lib/esm/features/store/collections/CreateCollection.js +2 -2
- package/lib/esm/features/store/collections/CreateCollection.js.map +1 -1
- package/lib/esm/features/store/collections/EditCollectionView.js +29 -30
- package/lib/esm/features/store/collections/EditCollectionView.js.map +1 -1
- package/lib/esm/features/store/collections/SelectCollection.js +46 -45
- package/lib/esm/features/store/collections/SelectCollection.js.map +1 -1
- package/lib/esm/features/store/objects/DocumentSearchResults.js +35 -9
- package/lib/esm/features/store/objects/DocumentSearchResults.js.map +1 -1
- package/lib/esm/features/store/objects/DocumentTable.js +6 -6
- package/lib/esm/features/store/objects/DocumentTable.js.map +1 -1
- package/lib/esm/features/store/objects/components/ContentOverview.js +158 -114
- package/lib/esm/features/store/objects/components/ContentOverview.js.map +1 -1
- package/lib/esm/features/store/objects/components/DocumentIcon.js +5 -3
- package/lib/esm/features/store/objects/components/DocumentIcon.js.map +1 -1
- package/lib/esm/features/store/objects/components/SaveVersionConfirmModal.js +11 -2
- package/lib/esm/features/store/objects/components/SaveVersionConfirmModal.js.map +1 -1
- package/lib/esm/features/store/objects/components/useDownloadObject.js +2 -2
- package/lib/esm/features/store/objects/components/useDownloadObject.js.map +1 -1
- package/lib/esm/features/store/objects/layout/DocumentTableColumn.js +13 -1
- package/lib/esm/features/store/objects/layout/DocumentTableColumn.js.map +1 -1
- package/lib/esm/features/store/objects/layout/documentLayout.js +5 -5
- package/lib/esm/features/store/objects/layout/documentLayout.js.map +1 -1
- package/lib/esm/features/store/objects/layout/renderers.js +28 -12
- package/lib/esm/features/store/objects/layout/renderers.js.map +1 -1
- package/lib/esm/features/store/objects/search/DocumentSearchContext.js +5 -1
- package/lib/esm/features/store/objects/search/DocumentSearchContext.js.map +1 -1
- package/lib/esm/features/store/objects/search/DocumentSearchProvider.js +1 -1
- package/lib/esm/features/store/objects/search/DocumentSearchProvider.js.map +1 -1
- package/lib/esm/features/store/objects/selection/ObjectsActionContext.js +3 -2
- package/lib/esm/features/store/objects/selection/ObjectsActionContext.js.map +1 -1
- package/lib/esm/features/store/objects/selection/SelectionActions.js +2 -0
- package/lib/esm/features/store/objects/selection/SelectionActions.js.map +1 -1
- package/lib/esm/features/store/objects/selection/actions/AddToCollectionAction.js +10 -2
- package/lib/esm/features/store/objects/selection/actions/AddToCollectionAction.js.map +1 -1
- package/lib/esm/features/store/objects/selection/actions/DeleteObjectsAction.js +20 -2
- package/lib/esm/features/store/objects/selection/actions/DeleteObjectsAction.js.map +1 -1
- package/lib/esm/features/store/objects/upload/DocumentUploadModal.js +15 -7
- package/lib/esm/features/store/objects/upload/DocumentUploadModal.js.map +1 -1
- package/lib/esm/features/store/types/CreateOrUpdateTypeModal.js +1 -1
- package/lib/esm/features/store/types/CreateOrUpdateTypeModal.js.map +1 -1
- package/lib/esm/features/user/UserInfo.js +2 -0
- package/lib/esm/features/user/UserInfo.js.map +1 -1
- package/lib/esm/router/HistoryNavigator.js +25 -2
- package/lib/esm/router/HistoryNavigator.js.map +1 -1
- package/lib/esm/router/Nav.js +3 -3
- package/lib/esm/router/Nav.js.map +1 -1
- package/lib/esm/session/UserSession.js +1 -0
- package/lib/esm/session/UserSession.js.map +1 -1
- package/lib/esm/session/UserSessionProvider.js +9 -2
- package/lib/esm/session/UserSessionProvider.js.map +1 -1
- package/lib/esm/session/auth/composable.js +66 -67
- package/lib/esm/session/auth/composable.js.map +1 -1
- package/lib/esm/widgets/form/Form.js +17 -30
- package/lib/esm/widgets/form/Form.js.map +1 -1
- package/lib/esm/widgets/form/FormContext.js +4 -2
- package/lib/esm/widgets/form/FormContext.js.map +1 -1
- package/lib/esm/widgets/form/ManagedObject.js +4 -0
- package/lib/esm/widgets/form/ManagedObject.js.map +1 -1
- package/lib/esm/widgets/form/fields.js +4 -3
- package/lib/esm/widgets/form/fields.js.map +1 -1
- package/lib/esm/widgets/form/inputs.js +2 -0
- package/lib/esm/widgets/form/inputs.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/lib/types/core/components/Panel.d.ts +11 -0
- package/lib/types/core/components/Panel.d.ts.map +1 -0
- package/lib/types/core/components/SidePanel.d.ts.map +1 -1
- package/lib/types/core/components/index.d.ts +1 -1
- package/lib/types/core/components/index.d.ts.map +1 -1
- package/lib/types/core/components/shadcn/breadcrumb.d.ts +3 -2
- package/lib/types/core/components/shadcn/breadcrumb.d.ts.map +1 -1
- package/lib/types/core/components/shadcn/button.d.ts.map +1 -1
- package/lib/types/core/components/shadcn/filters/filterBar.d.ts.map +1 -1
- package/lib/types/core/components/shadcn/index.d.ts +1 -0
- package/lib/types/core/components/shadcn/index.d.ts.map +1 -1
- package/lib/types/core/components/shadcn/input.d.ts.map +1 -1
- package/lib/types/core/components/shadcn/selectBox.d.ts +3 -2
- package/lib/types/core/components/shadcn/selectBox.d.ts.map +1 -1
- package/lib/types/core/components/shadcn/tabs.d.ts.map +1 -1
- package/lib/types/core/components/shadcn/textarea.d.ts +4 -0
- package/lib/types/core/components/shadcn/textarea.d.ts.map +1 -0
- package/lib/types/core/hooks/CompositeState.d.ts +115 -6
- package/lib/types/core/hooks/CompositeState.d.ts.map +1 -1
- package/lib/types/core/hooks/index.d.ts +1 -0
- package/lib/types/core/hooks/index.d.ts.map +1 -1
- package/lib/types/core/hooks/useScrollableSearch.d.ts +82 -0
- package/lib/types/core/hooks/useScrollableSearch.d.ts.map +1 -0
- package/lib/types/env/index.d.ts +3 -1
- package/lib/types/env/index.d.ts.map +1 -1
- package/lib/types/features/agent/PayloadBuilder.d.ts +11 -19
- package/lib/types/features/agent/PayloadBuilder.d.ts.map +1 -1
- package/lib/types/features/agent/chat/ModernAgentConversation.d.ts.map +1 -1
- package/lib/types/features/agent/chat/ModernAgentOutput/AllMessagesMixed.d.ts +1 -1
- package/lib/types/features/agent/chat/ModernAgentOutput/AllMessagesMixed.d.ts.map +1 -1
- package/lib/types/features/agent/chat/ModernAgentOutput/Header.d.ts.map +1 -1
- package/lib/types/features/agent/chat/ModernAgentOutput/InlineSlidingPlanPanel.d.ts.map +1 -1
- package/lib/types/features/agent/chat/ModernAgentOutput/PlanPanel.d.ts.map +1 -1
- package/lib/types/features/facets/CollectionsFacetsNav.d.ts.map +1 -1
- package/lib/types/features/facets/InteractionsFacetsNav.d.ts +1 -0
- package/lib/types/features/facets/InteractionsFacetsNav.d.ts.map +1 -1
- package/lib/types/features/facets/utils/SearchInterface.d.ts +6 -1
- package/lib/types/features/facets/utils/SearchInterface.d.ts.map +1 -1
- package/lib/types/features/facets/utils/VTypeFacet.d.ts +2 -1
- package/lib/types/features/facets/utils/VTypeFacet.d.ts.map +1 -1
- package/lib/types/features/layout/GenericPageNavHeader.d.ts +2 -1
- package/lib/types/features/layout/GenericPageNavHeader.d.ts.map +1 -1
- package/lib/types/features/store/collections/BrowseCollectionView.d.ts.map +1 -1
- package/lib/types/features/store/collections/CreateCollection.d.ts.map +1 -1
- package/lib/types/features/store/collections/EditCollectionView.d.ts.map +1 -1
- package/lib/types/features/store/collections/SelectCollection.d.ts +6 -4
- package/lib/types/features/store/collections/SelectCollection.d.ts.map +1 -1
- package/lib/types/features/store/objects/DocumentSearchResults.d.ts.map +1 -1
- package/lib/types/features/store/objects/DocumentTable.d.ts +4 -0
- package/lib/types/features/store/objects/DocumentTable.d.ts.map +1 -1
- package/lib/types/features/store/objects/components/ContentOverview.d.ts.map +1 -1
- package/lib/types/features/store/objects/components/DocumentIcon.d.ts +3 -1
- package/lib/types/features/store/objects/components/DocumentIcon.d.ts.map +1 -1
- package/lib/types/features/store/objects/components/SaveVersionConfirmModal.d.ts.map +1 -1
- package/lib/types/features/store/objects/components/useDownloadObject.d.ts +1 -1
- package/lib/types/features/store/objects/components/useDownloadObject.d.ts.map +1 -1
- package/lib/types/features/store/objects/layout/DocumentTableColumn.d.ts +2 -1
- package/lib/types/features/store/objects/layout/DocumentTableColumn.d.ts.map +1 -1
- package/lib/types/features/store/objects/layout/documentLayout.d.ts +4 -2
- package/lib/types/features/store/objects/layout/documentLayout.d.ts.map +1 -1
- package/lib/types/features/store/objects/layout/renderers.d.ts +1 -1
- package/lib/types/features/store/objects/layout/renderers.d.ts.map +1 -1
- package/lib/types/features/store/objects/search/DocumentSearchContext.d.ts +1 -0
- package/lib/types/features/store/objects/search/DocumentSearchContext.d.ts.map +1 -1
- package/lib/types/features/store/objects/selection/ObjectsActionContext.d.ts.map +1 -1
- package/lib/types/features/store/objects/selection/SelectionActions.d.ts.map +1 -1
- package/lib/types/features/store/objects/selection/actions/DeleteObjectsAction.d.ts +1 -0
- package/lib/types/features/store/objects/selection/actions/DeleteObjectsAction.d.ts.map +1 -1
- package/lib/types/features/store/objects/upload/DocumentUploadModal.d.ts.map +1 -1
- package/lib/types/features/user/UserInfo.d.ts.map +1 -1
- package/lib/types/router/HistoryNavigator.d.ts.map +1 -1
- package/lib/types/router/Nav.d.ts +2 -1
- package/lib/types/router/Nav.d.ts.map +1 -1
- package/lib/types/session/UserSession.d.ts.map +1 -1
- package/lib/types/session/UserSessionProvider.d.ts.map +1 -1
- package/lib/types/session/auth/composable.d.ts.map +1 -1
- package/lib/types/widgets/form/Form.d.ts +2 -1
- package/lib/types/widgets/form/Form.d.ts.map +1 -1
- package/lib/types/widgets/form/FormContext.d.ts +5 -2
- package/lib/types/widgets/form/FormContext.d.ts.map +1 -1
- package/lib/types/widgets/form/ManagedObject.d.ts.map +1 -1
- package/lib/types/widgets/form/fields.d.ts +2 -2
- package/lib/types/widgets/form/fields.d.ts.map +1 -1
- package/lib/types/widgets/form/inputs.d.ts.map +1 -1
- 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-router.js +1 -1
- package/lib/vertesia-ui-router.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.map +1 -1
- package/lib/vertesia-ui-widgets.js +1 -1
- package/lib/vertesia-ui-widgets.js.map +1 -1
- package/package.json +166 -166
- package/src/core/components/Panel.tsx +34 -0
- package/src/core/components/SidePanel.tsx +5 -3
- package/src/core/components/index.ts +1 -1
- package/src/core/components/shadcn/breadcrumb.tsx +49 -30
- package/src/core/components/shadcn/button.tsx +3 -2
- package/src/core/components/shadcn/filters/filterBar.tsx +3 -3
- package/src/core/components/shadcn/index.ts +2 -1
- package/src/core/components/shadcn/input.tsx +10 -7
- package/src/core/components/shadcn/resizeable.tsx +4 -4
- package/src/core/components/shadcn/selectBox.tsx +87 -67
- package/src/core/components/shadcn/tabs.tsx +10 -3
- package/src/core/components/shadcn/textarea.tsx +21 -0
- package/src/core/hooks/index.ts +1 -0
- package/src/core/hooks/useScrollableSearch.tsx +193 -0
- package/src/features/agent/chat/ModernAgentConversation.tsx +109 -118
- package/src/features/agent/chat/ModernAgentOutput/AllMessagesMixed.tsx +2 -22
- package/src/features/agent/chat/ModernAgentOutput/Header.tsx +1 -9
- package/src/features/agent/chat/ModernAgentOutput/InlineSlidingPlanPanel.tsx +39 -55
- package/src/features/agent/chat/ModernAgentOutput/PlanPanel.tsx +1 -0
- package/src/features/agent/chat/ModernAgentOutput/SlidingPlanPanel.tsx +8 -8
- package/src/features/agent/chat/ModernAgentOutput/WorkstreamTabs.tsx +8 -8
- package/src/features/facets/CollectionsFacetsNav.tsx +21 -0
- package/src/features/facets/InteractionsFacetsNav.tsx +13 -3
- package/src/features/facets/utils/SearchInterface.tsx +5 -1
- package/src/features/facets/utils/VTypeFacet.tsx +6 -2
- package/src/features/layout/GenericPageNavHeader.tsx +73 -10
- package/src/features/store/collections/BrowseCollectionView.tsx +4 -0
- package/src/features/store/collections/CreateCollection.tsx +3 -4
- package/src/features/store/collections/EditCollectionView.tsx +91 -85
- package/src/features/store/collections/SelectCollection.tsx +105 -49
- package/src/features/store/objects/DocumentSearchResults.tsx +117 -51
- package/src/features/store/objects/DocumentTable.tsx +14 -4
- package/src/features/store/objects/components/ContentOverview.tsx +208 -110
- package/src/features/store/objects/components/DocumentIcon.tsx +11 -12
- package/src/features/store/objects/components/SaveVersionConfirmModal.tsx +12 -2
- package/src/features/store/objects/layout/DocumentTableColumn.tsx +16 -1
- package/src/features/store/objects/layout/documentLayout.tsx +7 -5
- package/src/features/store/objects/layout/knowledge.md +10 -10
- package/src/features/store/objects/layout/renderers.tsx +39 -18
- package/src/features/store/objects/search/DocumentSearchContext.ts +6 -1
- package/src/features/store/objects/search/DocumentSearchProvider.tsx +1 -1
- package/src/features/store/objects/selection/ObjectsActionContext.tsx +3 -2
- package/src/features/store/objects/selection/SelectionActions.tsx +2 -0
- package/src/features/store/objects/selection/actions/AddToCollectionAction.tsx +8 -2
- package/src/features/store/objects/selection/actions/DeleteObjectsAction.tsx +22 -2
- package/src/features/store/objects/upload/DocumentUploadModal.tsx +18 -9
- package/src/features/store/objects/upload/useSmartFileUploadProcessing.ts +10 -7
- package/src/features/store/types/CreateOrUpdateTypeModal.tsx +1 -1
- package/src/router/HistoryNavigator.ts +33 -2
- package/src/router/Nav.tsx +4 -3
- package/src/widgets/form/Form.tsx +19 -43
- package/src/widgets/form/FormContext.ts +5 -2
- package/src/widgets/form/fields.tsx +8 -6
- package/src/widgets/form/inputs.tsx +1 -0
- package/lib/esm/core/components/Textarea.js +0 -15
- package/lib/esm/core/components/Textarea.js.map +0 -1
- package/lib/types/core/components/Textarea.d.ts +0 -8
- package/lib/types/core/components/Textarea.d.ts.map +0 -1
- package/src/core/components/Textarea.tsx +0 -25
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from "react"
|
|
2
|
-
import {
|
|
2
|
+
import { Minus } from "lucide-react"
|
|
3
3
|
import * as ResizablePrimitive from "react-resizable-panels"
|
|
4
4
|
|
|
5
5
|
import { cn } from "../libs/utils"
|
|
@@ -37,14 +37,14 @@ function ResizableHandle({
|
|
|
37
37
|
<ResizablePrimitive.PanelResizeHandle
|
|
38
38
|
data-slot="resizable-handle"
|
|
39
39
|
className={cn(
|
|
40
|
-
"bg-
|
|
40
|
+
"bg-muted focus-visible:ring-ring relative flex w-px items-center justify-center after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:ring-1 focus-visible:ring-offset-1 focus-visible:outline-hidden data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:translate-x-0 data-[panel-group-direction=vertical]:after:-translate-y-1/2 [&[data-panel-group-direction=vertical]>div]:rotate-90",
|
|
41
41
|
className
|
|
42
42
|
)}
|
|
43
43
|
{...props}
|
|
44
44
|
>
|
|
45
45
|
{withHandle && (
|
|
46
|
-
<div className="
|
|
47
|
-
<
|
|
46
|
+
<div className="z-10 flex size-4 items-center justify-center rounded-xs font-semibold">
|
|
47
|
+
<Minus className="size-4 rotate-90" />
|
|
48
48
|
</div>
|
|
49
49
|
)}
|
|
50
50
|
</ResizablePrimitive.PanelResizeHandle>
|
|
@@ -6,8 +6,9 @@ import { useState, useEffect, useRef } from 'react';
|
|
|
6
6
|
import { Popover, PopoverContent, PopoverTrigger, PopoverClose } from './popover';
|
|
7
7
|
import { Command, CommandEmpty, CommandGroup, CommandItem, CommandList } from './command';
|
|
8
8
|
import { Input } from './input';
|
|
9
|
+
import { Button } from '@vertesia/ui/core';
|
|
9
10
|
|
|
10
|
-
interface VSelectBoxBaseProps<T> {
|
|
11
|
+
export interface VSelectBoxBaseProps<T> {
|
|
11
12
|
options: T[] | undefined;
|
|
12
13
|
optionLabel?: (option: T) => React.ReactNode;
|
|
13
14
|
onBlur?: () => void;
|
|
@@ -23,6 +24,7 @@ interface VSelectBoxBaseProps<T> {
|
|
|
23
24
|
popupClass?: string;
|
|
24
25
|
isClearable?: boolean;
|
|
25
26
|
border?: boolean;
|
|
27
|
+
inline?: boolean;
|
|
26
28
|
}
|
|
27
29
|
|
|
28
30
|
interface VSelectBoxSingleProps<T> extends VSelectBoxBaseProps<T> {
|
|
@@ -39,7 +41,7 @@ interface VSelectBoxMultipleProps<T> extends VSelectBoxBaseProps<T> {
|
|
|
39
41
|
|
|
40
42
|
type VSelectBoxProps<T> = VSelectBoxSingleProps<T> | VSelectBoxMultipleProps<T>;
|
|
41
43
|
|
|
42
|
-
export function VSelectBox<T = any>({ options, optionLabel, value, onChange, addNew, addNewLabel, disabled, filterBy, label, placeholder, className, popupClass, isClearable, border = true, multiple = false, by }: Readonly<VSelectBoxProps<T>>) {
|
|
44
|
+
export function VSelectBox<T = any>({ options, optionLabel, value, onChange, addNew, addNewLabel, disabled, filterBy, label, placeholder, className, popupClass, isClearable, border = true, multiple = false, by, inline = false }: Readonly<VSelectBoxProps<T>>) {
|
|
43
45
|
const triggerRef = useRef<HTMLDivElement>(null);
|
|
44
46
|
const [open, setOpen] = useState(false);
|
|
45
47
|
const [width, setWidth] = useState<number>(0);
|
|
@@ -169,6 +171,82 @@ export function VSelectBox<T = any>({ options, optionLabel, value, onChange, add
|
|
|
169
171
|
);
|
|
170
172
|
};
|
|
171
173
|
|
|
174
|
+
// Render the options list content
|
|
175
|
+
const renderOptionsContent = () => (
|
|
176
|
+
<>
|
|
177
|
+
{filterBy && (
|
|
178
|
+
<div className='flex justify-start items-center mb-1'>
|
|
179
|
+
<div className='mx-2'>
|
|
180
|
+
<SearchIcon className="size-4" />
|
|
181
|
+
</div>
|
|
182
|
+
<Input variant='unstyled' value={filterValue} onChange={setFilterValue} className="w-full p-1 rounded-md" placeholder="Search..." />
|
|
183
|
+
</div>
|
|
184
|
+
)}
|
|
185
|
+
<Command className="overflow-hidden">
|
|
186
|
+
<CommandList className={inline ? "max-h-full overflow-y-auto" : "max-h-[200px] overflow-y-auto"}>
|
|
187
|
+
<CommandEmpty>No result found.</CommandEmpty>
|
|
188
|
+
<CommandGroup className="overflow-visible">
|
|
189
|
+
{filteredOptions?.map((opt, index) => {
|
|
190
|
+
const isSelected = multiple
|
|
191
|
+
? isOptionSelected(opt, Array.isArray(value) ? value : [])
|
|
192
|
+
: value != null ? isOptionsEqual(value as T, opt) : false;
|
|
193
|
+
|
|
194
|
+
return (
|
|
195
|
+
<CommandItem
|
|
196
|
+
key={index}
|
|
197
|
+
onSelect={() => _onClick(opt)}
|
|
198
|
+
className="w-full"
|
|
199
|
+
>
|
|
200
|
+
{multiple || inline ? (
|
|
201
|
+
<div className='w-full flex justify-between items-center cursor-pointer'>
|
|
202
|
+
<div className='w-full truncate text-left'>
|
|
203
|
+
{optionLabel ? optionLabel(opt) : opt as String}
|
|
204
|
+
</div>
|
|
205
|
+
{isSelected && <Check className="size-4" />}
|
|
206
|
+
</div>
|
|
207
|
+
) : (
|
|
208
|
+
<PopoverClose className='w-full flex justify-between items-center'>
|
|
209
|
+
<div className='w-full truncate text-left'>
|
|
210
|
+
{optionLabel ? optionLabel(opt) : opt as String}
|
|
211
|
+
</div>
|
|
212
|
+
{isSelected && <Check className="size-4" />}
|
|
213
|
+
</PopoverClose>
|
|
214
|
+
)}
|
|
215
|
+
</CommandItem>
|
|
216
|
+
);
|
|
217
|
+
})}
|
|
218
|
+
</CommandGroup>
|
|
219
|
+
</CommandList>
|
|
220
|
+
</Command>
|
|
221
|
+
{addNew && (
|
|
222
|
+
<div className='p-1'>
|
|
223
|
+
<a
|
|
224
|
+
onClick={addNew}
|
|
225
|
+
className={clsx(
|
|
226
|
+
'gap-x-2 px-2 py-1.5 truncate group flex rounded-md items-center text-sm cursor-pointer hover:bg-accent',
|
|
227
|
+
)}
|
|
228
|
+
>
|
|
229
|
+
<SquarePlus size={16} strokeWidth={1.25} absoluteStrokeWidth />
|
|
230
|
+
{addNewLabel}
|
|
231
|
+
</a>
|
|
232
|
+
</div>
|
|
233
|
+
)}
|
|
234
|
+
</>
|
|
235
|
+
);
|
|
236
|
+
|
|
237
|
+
if (inline) {
|
|
238
|
+
return (
|
|
239
|
+
<div className={clsx(
|
|
240
|
+
className,
|
|
241
|
+
border && 'border border-border rounded-md',
|
|
242
|
+
"bg-popover p-1",
|
|
243
|
+
popupClass
|
|
244
|
+
)}>
|
|
245
|
+
{renderOptionsContent()}
|
|
246
|
+
</div>
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
|
|
172
250
|
return (
|
|
173
251
|
<Popover>
|
|
174
252
|
<PopoverTrigger asChild>
|
|
@@ -178,7 +256,7 @@ export function VSelectBox<T = any>({ options, optionLabel, value, onChange, add
|
|
|
178
256
|
className={clsx(
|
|
179
257
|
className,
|
|
180
258
|
border && 'border border-border',
|
|
181
|
-
'flex flex-row gap-2 items-center justify-between p-2 rounded-md group relative',
|
|
259
|
+
'flex flex-row gap-2 items-center justify-between p-2 rounded-md group relative [&:hover_.clear-button]:opacity-100',
|
|
182
260
|
!disabled ? "cursor-pointer hover:bg-muted" : "cursor-not-allowed text-muted",
|
|
183
261
|
)}
|
|
184
262
|
>
|
|
@@ -194,9 +272,10 @@ export function VSelectBox<T = any>({ options, optionLabel, value, onChange, add
|
|
|
194
272
|
{multiple ? renderMultipleValue() : renderSingleValue()}
|
|
195
273
|
</div>
|
|
196
274
|
</div>
|
|
197
|
-
<div className="flex items-center gap-1">
|
|
275
|
+
<div className="flex items-center gap-1 group">
|
|
198
276
|
{isClearable && value && (Array.isArray(value) ? value.length > 0 : true) && (
|
|
199
|
-
<
|
|
277
|
+
<Button variant={"link"} size={"icon"}
|
|
278
|
+
alt="Clear selection"
|
|
200
279
|
onClick={(e) => {
|
|
201
280
|
e.stopPropagation();
|
|
202
281
|
if (multiple) {
|
|
@@ -205,10 +284,10 @@ export function VSelectBox<T = any>({ options, optionLabel, value, onChange, add
|
|
|
205
284
|
(onChange as (option: T) => void)(undefined as any);
|
|
206
285
|
}
|
|
207
286
|
}}
|
|
208
|
-
className="cursor-pointer hover:bg-muted/20 rounded p-1"
|
|
287
|
+
className="cursor-pointer hover:bg-muted/20 clear-button opacity-0 transition-opacity duration-200 rounded p-1"
|
|
209
288
|
>
|
|
210
289
|
<X className="size-4" />
|
|
211
|
-
</
|
|
290
|
+
</Button>
|
|
212
291
|
)}
|
|
213
292
|
{!disabled && (
|
|
214
293
|
<ChevronsUpDown className="size-4 opacity-50" />
|
|
@@ -225,66 +304,7 @@ export function VSelectBox<T = any>({ options, optionLabel, value, onChange, add
|
|
|
225
304
|
popupClass
|
|
226
305
|
)}
|
|
227
306
|
>
|
|
228
|
-
{
|
|
229
|
-
|
|
230
|
-
<div className='flex justify-start items-center mb-1'>
|
|
231
|
-
<div className='mx-2'>
|
|
232
|
-
<SearchIcon className="size-4" />
|
|
233
|
-
</div>
|
|
234
|
-
<Input variant='unstyled' value={filterValue} onChange={setFilterValue} className="w-full p-1 rounded-md" placeholder="Search..." />
|
|
235
|
-
</div>
|
|
236
|
-
)}
|
|
237
|
-
<Command className="overflow-hidden">
|
|
238
|
-
<CommandList className="max-h-[200px] overflow-y-auto">
|
|
239
|
-
<CommandEmpty>No result found.</CommandEmpty>
|
|
240
|
-
<CommandGroup className="overflow-visible">
|
|
241
|
-
{filteredOptions?.map((opt, index) => {
|
|
242
|
-
const isSelected = multiple
|
|
243
|
-
? isOptionSelected(opt, Array.isArray(value) ? value : [])
|
|
244
|
-
: value != null ? isOptionsEqual(value as T, opt) : false;
|
|
245
|
-
|
|
246
|
-
return (
|
|
247
|
-
<CommandItem
|
|
248
|
-
key={index}
|
|
249
|
-
onSelect={() => _onClick(opt)}
|
|
250
|
-
className="w-full"
|
|
251
|
-
>
|
|
252
|
-
{multiple ? (
|
|
253
|
-
<div className='w-full flex justify-between items-center cursor-pointer'>
|
|
254
|
-
<div className='w-full truncate text-left'>
|
|
255
|
-
{optionLabel ? optionLabel(opt) : opt as String}
|
|
256
|
-
</div>
|
|
257
|
-
{isSelected && <Check className="size-4" />}
|
|
258
|
-
</div>
|
|
259
|
-
) : (
|
|
260
|
-
<PopoverClose className='w-full flex justify-between items-center'>
|
|
261
|
-
<div className='w-full truncate text-left'>
|
|
262
|
-
{optionLabel ? optionLabel(opt) : opt as String}
|
|
263
|
-
</div>
|
|
264
|
-
{isSelected && <Check className="size-4" />}
|
|
265
|
-
</PopoverClose>
|
|
266
|
-
)}
|
|
267
|
-
</CommandItem>
|
|
268
|
-
);
|
|
269
|
-
})}
|
|
270
|
-
</CommandGroup>
|
|
271
|
-
</CommandList>
|
|
272
|
-
</Command>
|
|
273
|
-
{
|
|
274
|
-
addNew && (
|
|
275
|
-
<div className='p-1'>
|
|
276
|
-
<a
|
|
277
|
-
onClick={addNew}
|
|
278
|
-
className={clsx(
|
|
279
|
-
'gap-x-2 px-2 py-1.5 truncate group flex rounded-md items-center text-sm cursor-pointer hover:bg-accent',
|
|
280
|
-
)}
|
|
281
|
-
>
|
|
282
|
-
<SquarePlus size={16} strokeWidth={1.25} absoluteStrokeWidth />
|
|
283
|
-
{addNewLabel}
|
|
284
|
-
</a>
|
|
285
|
-
</div>
|
|
286
|
-
)
|
|
287
|
-
}
|
|
307
|
+
{renderOptionsContent()}
|
|
288
308
|
</PopoverContent>
|
|
289
309
|
</Popover>
|
|
290
310
|
);
|
|
@@ -106,7 +106,10 @@ const VTabs = ({
|
|
|
106
106
|
|
|
107
107
|
// Update the URL hash when tab changes (only if updateHash is true and not controlled by parent)
|
|
108
108
|
if (updateHash && !current) {
|
|
109
|
-
|
|
109
|
+
// Preserve existing history state when changing hash
|
|
110
|
+
const currentState = window.history.state;
|
|
111
|
+
const newUrl = window.location.pathname + window.location.search + '#' + newValue;
|
|
112
|
+
window.history.pushState(currentState, '', newUrl);
|
|
110
113
|
}
|
|
111
114
|
|
|
112
115
|
if (onTabChange) {
|
|
@@ -143,7 +146,9 @@ const VTabsBar = ({ className }: { className?: string }) => {
|
|
|
143
146
|
const tab = tabs.find(t => t.name === tabName);
|
|
144
147
|
|
|
145
148
|
if (tab?.href && updateHash) {
|
|
146
|
-
|
|
149
|
+
// Preserve existing history state when changing tabs
|
|
150
|
+
const currentState = window.history.state;
|
|
151
|
+
window.history.pushState(currentState, '', tab.href);
|
|
147
152
|
}
|
|
148
153
|
|
|
149
154
|
setTab(tabName);
|
|
@@ -236,7 +241,9 @@ const TabsTrigger = React.forwardRef<
|
|
|
236
241
|
const handleClick = React.useCallback((event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
|
|
237
242
|
if (href) {
|
|
238
243
|
event.preventDefault();
|
|
239
|
-
|
|
244
|
+
// Preserve existing history state when changing tabs
|
|
245
|
+
const currentState = window.history.state;
|
|
246
|
+
window.history.pushState(currentState, '', href);
|
|
240
247
|
}
|
|
241
248
|
if (props.onClick) {
|
|
242
249
|
(props.onClick as React.MouseEventHandler<HTMLButtonElement>)(event);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
|
|
3
|
+
import { cn } from "../libs/utils"
|
|
4
|
+
|
|
5
|
+
function Textarea({ className, ...props }: React.ComponentProps<"textarea">) {
|
|
6
|
+
return (
|
|
7
|
+
<textarea
|
|
8
|
+
data-slot="textarea"
|
|
9
|
+
className={cn(
|
|
10
|
+
"py-2 text-sm",
|
|
11
|
+
"flex w-full rounded-md border border-input bg-background ring-offset-background",
|
|
12
|
+
"placeholder:text-muted focus-visible:outline-none focus-visible:ring-1 ring-inset focus-visible:ring-ring",
|
|
13
|
+
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
14
|
+
className
|
|
15
|
+
)}
|
|
16
|
+
{...props}
|
|
17
|
+
/>
|
|
18
|
+
)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export { Textarea }
|
package/src/core/hooks/index.ts
CHANGED
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { useIntersectionObserver } from "@vertesia/ui/core";
|
|
2
|
+
import { useEffect, useRef, useState } from "react";
|
|
3
|
+
|
|
4
|
+
interface SearchResponse<ResultT, PageT> {
|
|
5
|
+
/**
|
|
6
|
+
* The search result
|
|
7
|
+
*/
|
|
8
|
+
result: ResultT[];
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* The next page information or null if no more pages are available
|
|
12
|
+
*/
|
|
13
|
+
nextPage: PageT | null;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* The search function signature.
|
|
18
|
+
* @param payload The search payload
|
|
19
|
+
* @param page The information for the page to fetch. Use null to fetch the first page
|
|
20
|
+
* @param pageSize The number of items per page
|
|
21
|
+
* @returns A promise that resolves to the search response
|
|
22
|
+
*/
|
|
23
|
+
type SearchFn<PayloadT, ResultT, PageT = number> = (payload: PayloadT, page: PageT | null, pageSize: number) => Promise<SearchResponse<ResultT, PageT>>;
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
interface ScrollableSearchOptions<ResultT, PayloadT, PageT = number> {
|
|
27
|
+
/**
|
|
28
|
+
* the search function
|
|
29
|
+
*/
|
|
30
|
+
search: SearchFn<PayloadT, ResultT, PageT>;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Initial paylload for the first search
|
|
34
|
+
*/
|
|
35
|
+
payload: PayloadT;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Which page size to use. Defaults to 50.
|
|
39
|
+
*/
|
|
40
|
+
pageSize?: number;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* A ref to the element that triggers loading the next page when it enters the viewport
|
|
44
|
+
*/
|
|
45
|
+
nextPageTrigger: React.RefObject<HTMLElement | null>;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
interface ScrollableSearchResult<ResultT, PayloadT, PageT = number> {
|
|
49
|
+
/**
|
|
50
|
+
* Initiates a new search with the given payload
|
|
51
|
+
* @param payload The search payload
|
|
52
|
+
*/
|
|
53
|
+
search: (payload: PayloadT) => void;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Refreshes the current search with the last used payload
|
|
57
|
+
*/
|
|
58
|
+
refresh: () => void;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Loads the next page of results
|
|
62
|
+
*/
|
|
63
|
+
searchMore: () => void;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* The current accumulated search result
|
|
67
|
+
*/
|
|
68
|
+
result: ResultT[];
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* The current page information
|
|
72
|
+
*/
|
|
73
|
+
page: PageT | null;
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Whether there are more pages to load
|
|
77
|
+
*/
|
|
78
|
+
hasMore: boolean;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Any error that occurred during the last search
|
|
82
|
+
*/
|
|
83
|
+
error: Error | null;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Whether a search is currently in progress
|
|
87
|
+
*/
|
|
88
|
+
isSearching: boolean;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* A hook that provides paginated search functionality with infinite scrolling support.
|
|
93
|
+
*/
|
|
94
|
+
export function useScrollableSearch<ResultT, PayloadT, PageT = number>(opts: ScrollableSearchOptions<ResultT, PayloadT, PageT>, dependencies: any[] = []): ScrollableSearchResult<ResultT, PayloadT, PageT> {
|
|
95
|
+
const pageSize = opts.pageSize || 50;
|
|
96
|
+
const [page, setPage] = useState<PageT | null>(null);
|
|
97
|
+
const [lastPayload, setLastPayload] = useState<PayloadT>(opts.payload);
|
|
98
|
+
const [error, setError] = useState<Error | null>(null);
|
|
99
|
+
const [results, setResults] = useState<ResultT[]>([]);
|
|
100
|
+
const [nextPage, setNextPage] = useState<PageT | null>(null);
|
|
101
|
+
const [isSearching, setIsSearching] = useState(false);
|
|
102
|
+
|
|
103
|
+
// Track current request to prevent stale results
|
|
104
|
+
const requestIdRef = useRef(0);
|
|
105
|
+
|
|
106
|
+
const search = (payload: PayloadT) => {
|
|
107
|
+
setPage(null);
|
|
108
|
+
setResults([]); // Clear old results immediately
|
|
109
|
+
setNextPage(null);
|
|
110
|
+
setLastPayload(payload);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const searchMore = () => {
|
|
114
|
+
if (nextPage !== null) {
|
|
115
|
+
setPage(nextPage);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
useEffect(() => {
|
|
120
|
+
// Increment request ID to mark previous requests as stale
|
|
121
|
+
requestIdRef.current += 1;
|
|
122
|
+
const currentRequestId = requestIdRef.current;
|
|
123
|
+
|
|
124
|
+
setIsSearching(true);
|
|
125
|
+
opts.search(lastPayload, page, pageSize).then(r => {
|
|
126
|
+
// Only update state if this is still the current request
|
|
127
|
+
if (currentRequestId !== requestIdRef.current) {
|
|
128
|
+
return; // Stale request, ignore results
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// If page is null, it's a new search - replace results
|
|
132
|
+
// Otherwise, it's loading more - append results
|
|
133
|
+
if (page === null) {
|
|
134
|
+
setResults(r.result);
|
|
135
|
+
} else {
|
|
136
|
+
setResults(prev => [...prev, ...r.result]);
|
|
137
|
+
}
|
|
138
|
+
setNextPage(r.nextPage);
|
|
139
|
+
setError(null);
|
|
140
|
+
}).catch(error => {
|
|
141
|
+
// Only update error if this is still the current request
|
|
142
|
+
if (currentRequestId !== requestIdRef.current) {
|
|
143
|
+
return; // Stale request, ignore error
|
|
144
|
+
}
|
|
145
|
+
setError(error);
|
|
146
|
+
}).finally(() => {
|
|
147
|
+
// Only update isSearching if this is still the current request
|
|
148
|
+
if (currentRequestId === requestIdRef.current) {
|
|
149
|
+
setIsSearching(false);
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
}, [...dependencies, lastPayload, page]);
|
|
153
|
+
|
|
154
|
+
// Intersection observer for infinite scrolling
|
|
155
|
+
useIntersectionObserver(opts.nextPageTrigger, () => {
|
|
156
|
+
if (!isSearching && nextPage) {
|
|
157
|
+
searchMore();
|
|
158
|
+
}
|
|
159
|
+
}, { threshold: 0.1, deps: [nextPage, isSearching] });
|
|
160
|
+
|
|
161
|
+
return {
|
|
162
|
+
search,
|
|
163
|
+
refresh: () => search(lastPayload),
|
|
164
|
+
searchMore,
|
|
165
|
+
result: results,
|
|
166
|
+
page,
|
|
167
|
+
hasMore: nextPage !== null,
|
|
168
|
+
error,
|
|
169
|
+
isSearching,
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
type DefaultSearchFn<PayloadT, ResultT> = (payload: PayloadT, offset: number, limit: number) => Promise<ResultT[]>;
|
|
174
|
+
|
|
175
|
+
interface DefaultScrollableSearchOptions<ResultT, PayloadT> extends Omit<ScrollableSearchOptions<ResultT, PayloadT, number>, 'search'> {
|
|
176
|
+
search: DefaultSearchFn<PayloadT, ResultT>;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export function useDefaultScrollableSearch<ResultT, PayloadT>(opts: DefaultScrollableSearchOptions<ResultT, PayloadT>, dependencies: any[] = []): ScrollableSearchResult<ResultT, PayloadT, number> {
|
|
180
|
+
const actualOpts: ScrollableSearchOptions<ResultT, PayloadT, number> = {
|
|
181
|
+
...opts,
|
|
182
|
+
async search(payload, page, pageSize) {
|
|
183
|
+
const currentPage = page ?? 0;
|
|
184
|
+
const offset = currentPage * pageSize;
|
|
185
|
+
const result = await opts.search(payload, offset, pageSize);
|
|
186
|
+
return {
|
|
187
|
+
result,
|
|
188
|
+
nextPage: result.length === 0 ? null : currentPage + 1
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
return useScrollableSearch<ResultT, PayloadT, number>(actualOpts, dependencies);
|
|
193
|
+
}
|