@@ -27,6 +27,7 @@ import {
2727 PrimaryButton ,
2828} from '@epam/ai-dial-ui-kit' ;
2929import type { Meta , StoryObj } from '@storybook/react-vite' ;
30+ import { userEvent , within } from 'storybook/test' ;
3031import {
3132 IconBuildingCommunity ,
3233 IconFileDescription ,
@@ -274,6 +275,109 @@ export const HandleTableFileClick: Story = {
274275 } ,
275276} ;
276277
278+ const destinationPopupCaretItems : DialFile [ ] = [
279+ {
280+ id : 'destination-root' ,
281+ name : 'All files' ,
282+ path : 'All files' ,
283+ parentPath : '' ,
284+ nodeType : DialFileNodeType . FOLDER ,
285+ folderId : 'destination-root' ,
286+ items : [
287+ {
288+ id : 'source-file' ,
289+ name : 'source.txt' ,
290+ path : 'All files/source.txt' ,
291+ parentPath : 'All files' ,
292+ nodeType : DialFileNodeType . ITEM ,
293+ resourceType : DialFileResourceType . FILE ,
294+ folderId : 'destination-root' ,
295+ } ,
296+ {
297+ id : 'loaded-empty-folder' ,
298+ name : 'Loaded empty folder' ,
299+ path : 'All files/Loaded empty folder' ,
300+ parentPath : 'All files' ,
301+ nodeType : DialFileNodeType . FOLDER ,
302+ folderId : 'destination-root' ,
303+ items : [ ] ,
304+ } ,
305+ {
306+ id : 'not-loaded-folder' ,
307+ name : 'Not loaded folder' ,
308+ path : 'All files/Not loaded folder' ,
309+ parentPath : 'All files' ,
310+ nodeType : DialFileNodeType . FOLDER ,
311+ folderId : 'destination-root' ,
312+ items : [ ] ,
313+ } ,
314+ ] ,
315+ } ,
316+ ] ;
317+
318+ const destinationPopupCaretRootItem : DialRootFolder = {
319+ ...destinationPopupCaretItems [ 0 ] ,
320+ label : 'All files' ,
321+ } ;
322+
323+ const DestinationPopupLoadedEmptyFolderComponent = (
324+ args : DialFileManagerProps ,
325+ ) => {
326+ const [ destinationPath , setDestinationPath ] = useState ( 'All files' ) ;
327+
328+ return (
329+ < div className = "h-[720px] min-h-[480px]" >
330+ < DialFileManager
331+ { ...args }
332+ items = { destinationPopupCaretItems }
333+ rootItem = { destinationPopupCaretRootItem }
334+ defaultPath = "All files"
335+ defaultSelectedPaths = { new Set ( [ 'All files/source.txt' ] ) }
336+ gridOptions = { {
337+ ...args . gridOptions ,
338+ selectionMode : GridSelectionMode . MULTIPLE ,
339+ } }
340+ treeOptions = { {
341+ ...args . treeOptions ,
342+ expandedPaths : new Set ( [ 'All files' ] ) ,
343+ loadedPaths : new Set ( [ 'All files' , 'All files/Loaded empty folder' ] ) ,
344+ header : 'Folder tree' ,
345+ } }
346+ bulkActionsToolbarOptions = { {
347+ getSelectionLabel : ( selectedCount ) =>
348+ `${ selectedCount } item(s) selected` ,
349+ actionLabels : {
350+ [ DialFileManagerActions . Copy ] : 'Copy to' ,
351+ } ,
352+ } }
353+ destinationFolderPopupOptions = { {
354+ destinationFolderPath : destinationPath ,
355+ setDestinationFolderPath : setDestinationPath ,
356+ getCopyHeader : ( ) => 'Copy source.txt' ,
357+ } }
358+ onCopyFiles = { ( ) => undefined }
359+ />
360+ </ div >
361+ ) ;
362+ } ;
363+
364+ export const DestinationPopupLoadedEmptyFolder : Story = {
365+ render : DestinationPopupLoadedEmptyFolderComponent ,
366+ play : async ( { canvasElement } ) => {
367+ await userEvent . click (
368+ await within ( canvasElement ) . findByRole ( 'button' , { name : 'Copy to' } ) ,
369+ ) ;
370+ } ,
371+ parameters : {
372+ docs : {
373+ description : {
374+ story :
375+ 'Click "Copy to" to open the destination popup. "Loaded empty folder" must not show a caret, while "Not loaded folder" keeps its caret until its contents are loaded. Resize the canvas to verify the same state in the mobile layout.' ,
376+ } ,
377+ } ,
378+ } ,
379+ } ;
380+
277381const PopupComponent = ( args : DialFileManagerProps ) => {
278382 const [ isOpen , setIsOpen ] = useState ( false ) ;
279383 const { activeTab, handleTabChange, tabs } = useDialFileManagerTabs ( {
0 commit comments