Skip to content

Commit b012ea4

Browse files
committed
add stories for using with useDraggableCollectionState and useDragAndDrop
1 parent 1c16a2d commit b012ea4

File tree

2 files changed

+148
-2
lines changed

2 files changed

+148
-2
lines changed

packages/@react-aria/dnd/stories/dnd.stories.tsx

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,7 @@ function DraggableCollectionExample(props) {
385385
};
386386

387387
return (
388-
<DraggableCollection items={list.items} selectedKeys={list.selectedKeys} onSelectionChange={list.setSelectedKeys} onDragEnd={onDragEnd} onCut={onCut} isDisabled={props.isDisabled}>
388+
<DraggableCollection items={list.items} selectedKeys={list.selectedKeys} onSelectionChange={list.setSelectedKeys} onDragEnd={onDragEnd} onCut={onCut} isDisabled={props.isDisabled} getPreviewOffset={props.getPreviewOffset}>
389389
{item => (
390390
<Item textValue={item.text}>
391391
{item.type === 'folder' && <Folder size="S" />}
@@ -397,7 +397,7 @@ function DraggableCollectionExample(props) {
397397
}
398398

399399
function DraggableCollection(props) {
400-
let {isDisabled} = props;
400+
let {isDisabled, getPreviewOffset} = props;
401401
let ref = React.useRef<HTMLDivElement>(null);
402402
let state = useListState<ItemValue>(props);
403403
let gridState = useGridState({
@@ -440,6 +440,7 @@ function DraggableCollection(props) {
440440
}).filter(item => item != null);
441441
},
442442
preview,
443+
getPreviewOffset,
443444
onDragStart: action('onDragStart'),
444445
onDragEnd: chain(action('onDragEnd'), props.onDragEnd)
445446
});
@@ -647,6 +648,24 @@ function DraggableWithPreview({mode, offsetX, offsetY}: PreviewOffsetArgs): JSX.
647648
);
648649
}
649650

651+
function DraggableCollectionWithPreview({mode, offsetX, offsetY}: PreviewOffsetArgs): JSX.Element {
652+
const getPreviewOffset = React.useCallback(({previewRect, defaultOffset}: any) => {
653+
switch (mode) {
654+
case 'center':
655+
return {x: previewRect.width / 2, y: previewRect.height / 2};
656+
case 'custom':
657+
return {x: offsetX, y: offsetY};
658+
case 'default':
659+
default:
660+
return defaultOffset;
661+
}
662+
}, [mode, offsetX, offsetY]);
663+
664+
return (
665+
<DraggableCollectionExample getPreviewOffset={getPreviewOffset} />
666+
);
667+
}
668+
650669
export const PreviewOffset: DnDStoryObj = {
651670
render: (args) => (
652671
<Flex direction="column" gap="size-200" alignItems="center">
@@ -676,3 +695,33 @@ export const PreviewOffset: DnDStoryObj = {
676695
offsetY: 20
677696
}
678697
};
698+
699+
export const CollectionPreviewOffset: DnDStoryObj = {
700+
render: (args) => (
701+
<Flex direction="column" gap="size-200" alignItems="center">
702+
<DraggableCollectionWithPreview {...args} />
703+
<Droppable />
704+
</Flex>
705+
),
706+
name: 'Collection preview offset',
707+
argTypes: {
708+
mode: {
709+
control: 'select',
710+
options: ['default', 'center', 'custom'],
711+
defaultValue: 'default'
712+
},
713+
offsetX: {
714+
control: 'number',
715+
defaultValue: 20
716+
},
717+
offsetY: {
718+
control: 'number',
719+
defaultValue: 20
720+
}
721+
},
722+
args: {
723+
mode: 'default',
724+
offsetX: 20,
725+
offsetY: 20
726+
}
727+
};

packages/react-aria-components/stories/ListBox.stories.tsx

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,103 @@ ListBoxDnd.story = {
181181
}
182182
};
183183

184+
interface PreviewOffsetArgs {
185+
/** Strategy for positioning the preview. */
186+
mode: 'default' | 'center' | 'custom',
187+
/** X offset in pixels (only used when mode = custom). */
188+
offsetX: number,
189+
/** Y offset in pixels (only used when mode = custom). */
190+
offsetY: number
191+
}
192+
193+
function ListBoxDndWithPreview({mode, offsetX, offsetY, ...props}: PreviewOffsetArgs & ListBoxProps<typeof albums[0]>) {
194+
let list = useListData({
195+
initialItems: albums
196+
});
197+
198+
let getPreviewOffset = React.useCallback(({previewRect, defaultOffset}: any) => {
199+
switch (mode) {
200+
case 'center':
201+
return {x: previewRect.width / 2, y: previewRect.height / 2};
202+
case 'custom':
203+
return {x: offsetX, y: offsetY};
204+
case 'default':
205+
default:
206+
return defaultOffset;
207+
}
208+
}, [mode, offsetX, offsetY]);
209+
210+
let {dragAndDropHooks} = useDragAndDrop({
211+
getItems: (keys) => [...keys].map(key => ({'text/plain': list.getItem(key)?.title ?? ''})),
212+
onReorder(e) {
213+
if (e.target.dropPosition === 'before') {
214+
list.moveBefore(e.target.key, e.keys);
215+
} else if (e.target.dropPosition === 'after') {
216+
list.moveAfter(e.target.key, e.keys);
217+
}
218+
},
219+
getPreviewOffset,
220+
renderDragPreview(items) {
221+
return (
222+
<div style={{display: 'flex', alignItems: 'center', padding: 4, background: 'white', border: '1px solid gray'}}>
223+
<Text>{items[0]['text/plain']}</Text>
224+
{items.length > 1 && <span style={{marginLeft: 4, fontSize: 12}}>+{items.length - 1}</span>}
225+
</div>
226+
);
227+
}
228+
});
229+
230+
return (
231+
<ListBox
232+
{...props}
233+
aria-label="Albums with preview offset"
234+
items={list.items}
235+
selectionMode="multiple"
236+
dragAndDropHooks={dragAndDropHooks}>
237+
{item => (
238+
<ListBoxItem>
239+
<img src={item.image} alt="" />
240+
<Text slot="label">{item.title}</Text>
241+
<Text slot="description">{item.artist}</Text>
242+
</ListBoxItem>
243+
)}
244+
</ListBox>
245+
);
246+
}
247+
248+
export const ListBoxPreviewOffset = {
249+
render(args) {
250+
return <ListBoxDndWithPreview {...args} />;
251+
},
252+
args: {
253+
layout: 'stack',
254+
orientation: 'horizontal',
255+
mode: 'default',
256+
offsetX: 20,
257+
offsetY: 20
258+
},
259+
argTypes: {
260+
layout: {
261+
control: 'radio',
262+
options: ['stack', 'grid']
263+
},
264+
orientation: {
265+
control: 'radio',
266+
options: ['horizontal', 'vertical']
267+
},
268+
mode: {
269+
control: 'select',
270+
options: ['default', 'center', 'custom']
271+
},
272+
offsetX: {
273+
control: 'number'
274+
},
275+
offsetY: {
276+
control: 'number'
277+
}
278+
}
279+
};
280+
184281
export const ListBoxHover = () => (
185282
<ListBox className={styles.menu} aria-label="test listbox" onAction={action('onAction')} >
186283
<MyListBoxItem onHoverStart={action('onHoverStart')} onHoverChange={action('onHoverChange')} onHoverEnd={action('onHoverEnd')}>Hover</MyListBoxItem>

0 commit comments

Comments
 (0)