@awsui/components-react
Version:
On July 19th, 2022, we launched [Cloudscape Design System](https://cloudscape.design). Cloudscape is an evolution of AWS-UI. It consists of user interface guidelines, front-end components, design resources, and development tools for building intuitive, en
104 lines • 6.09 kB
JavaScript
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import React, { useEffect, useRef } from 'react';
import { DndContext, DragOverlay } from '@dnd-kit/core';
import { arrayMove, SortableContext, useSortable, verticalListSortingStrategy } from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities';
import clsx from 'clsx';
import Portal from '../../components/portal';
import { fireNonCancelableEvent } from '../../events';
import { joinStrings } from '../../utils/strings';
import useDragAndDropReorder from './use-drag-and-drop-reorder';
import useLiveAnnouncements from './use-live-announcements';
import styles from './styles.css.js';
export default function SortableArea({ items, itemDefinition, renderItem, onItemsChange, disableReorder, i18nStrings, }) {
var _a;
const { activeItemId, setActiveItemId, collisionDetection, handleKeyDown, sensors } = useDragAndDropReorder({
items,
itemDefinition,
});
const activeItem = activeItemId ? items.find(item => itemDefinition.id(item) === activeItemId) : null;
const isDragging = activeItemId !== null;
const announcements = useLiveAnnouncements(Object.assign({ items, itemDefinition, isDragging }, i18nStrings));
const portalContainer = usePortalContainer();
return (React.createElement(DndContext, { sensors: sensors, collisionDetection: collisionDetection, accessibility: {
announcements,
restoreFocus: false,
screenReaderInstructions: (i18nStrings === null || i18nStrings === void 0 ? void 0 : i18nStrings.dragHandleAriaDescription)
? { draggable: i18nStrings.dragHandleAriaDescription }
: undefined,
container: portalContainer !== null && portalContainer !== void 0 ? portalContainer : undefined,
}, onDragStart: ({ active }) => setActiveItemId(active.id), onDragEnd: event => {
setActiveItemId(null);
const { active, over } = event;
if (over && active.id !== over.id) {
const movedItem = items.find(item => itemDefinition.id(item) === active.id);
const oldIndex = items.findIndex(item => itemDefinition.id(item) === active.id);
const newIndex = items.findIndex(item => itemDefinition.id(item) === over.id);
fireNonCancelableEvent(onItemsChange, { items: arrayMove([...items], oldIndex, newIndex), movedItem });
}
}, onDragCancel: () => setActiveItemId(null) },
React.createElement(SortableContext, { disabled: disableReorder, items: items.map(item => itemDefinition.id(item)), strategy: verticalListSortingStrategy }, items.map(item => (React.createElement(DraggableItem, { key: itemDefinition.id(item), item: item, itemDefinition: itemDefinition, renderItem: renderItem, onKeyDown: handleKeyDown, dragHandleAriaLabel: i18nStrings === null || i18nStrings === void 0 ? void 0 : i18nStrings.dragHandleAriaLabel })))),
React.createElement(Portal, { container: portalContainer },
React.createElement(DragOverlay, { className: clsx(styles['drag-overlay'], styles[`drag-overlay-${getBorderRadiusVariant(itemDefinition)}`]), dropAnimation: null, style: { zIndex: 5000 } }, activeItem &&
renderItem({
item: activeItem,
style: {},
className: styles.active,
isDropPlaceholder: true,
isSortingActive: false,
isDragGhost: true,
dragHandleProps: {
ariaLabel: (_a = joinStrings(i18nStrings === null || i18nStrings === void 0 ? void 0 : i18nStrings.dragHandleAriaLabel, itemDefinition.label(activeItem))) !== null && _a !== void 0 ? _a : '',
onKeyDown: handleKeyDown,
},
})))));
}
function usePortalContainer() {
const portalContainerRef = useRef(typeof document !== 'undefined' ? document.createElement('div') : null);
useEffect(() => {
const container = portalContainerRef.current;
if (container && !container.isConnected) {
document.body.appendChild(container);
}
return () => {
if (container && container.isConnected) {
document.body.removeChild(container);
}
};
}, []);
return portalContainerRef.current;
}
function DraggableItem({ item, itemDefinition, dragHandleAriaLabel, onKeyDown, renderItem, }) {
var _a;
const { isDragging, isSorting, listeners, setNodeRef, transform, attributes } = useSortable({
id: itemDefinition.id(item),
});
const style = { transform: CSS.Translate.toString(transform) };
const dragHandleListeners = attributes['aria-disabled']
? {}
: Object.assign(Object.assign({}, listeners), { onKeyDown: (event) => {
if (onKeyDown) {
onKeyDown(event);
}
if (listeners === null || listeners === void 0 ? void 0 : listeners.onKeyDown) {
listeners.onKeyDown(event);
}
} });
const className = clsx(isDragging && clsx(styles.placeholder, styles[`placeholder-${getBorderRadiusVariant(itemDefinition)}`]), isSorting && styles.sorting);
return (React.createElement(React.Fragment, null, renderItem({
item,
ref: setNodeRef,
style,
className,
isDropPlaceholder: isDragging,
isSortingActive: isSorting,
isDragGhost: false,
dragHandleProps: Object.assign(Object.assign({}, dragHandleListeners), { ariaLabel: (_a = joinStrings(dragHandleAriaLabel, itemDefinition.label(item))) !== null && _a !== void 0 ? _a : '', ariaDescribedby: attributes['aria-describedby'], disabled: attributes['aria-disabled'] }),
})));
}
export function getBorderRadiusVariant(itemDefinition) {
var _a;
return (_a = itemDefinition.borderRadius) !== null && _a !== void 0 ? _a : 'item';
}
//# sourceMappingURL=index.js.map