import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { Item as BaseItem, mergeProps, tasty } from '@cube-dev/ui-kit';
import { useRef } from 'react';
import { ListDropTargetDelegate, ListKeyboardDelegate, useDraggableCollection, useDraggableItem, useDropIndicator, useDroppableCollection, useFocusRing, useListBox, useOption, } from 'react-aria';
import { useDraggableCollectionState, useDroppableCollectionState, useListState, } from 'react-stately';
const ReorderableListElement = tasty({
    as: 'ul',
    styles: {
        display: 'contents',
        flow: {
            '': 'row',
            vertical: 'column',
        },
        padding: 0,
        margin: 0,
    },
});
export function ReorderableList(props) {
    let { onMove, direction = 'horizontal', isDisabled, hasDragButton, children, ...itemProps } = props;
    let state = useListState(props);
    let ref = useRef(null);
    let { listBoxProps } = useListBox({
        ...itemProps,
        // Prevent dragging from changing selection.
        shouldSelectOnPressUp: true,
    }, state, ref);
    const onReorder = (e) => {
        if (isDisabled) {
            return null;
        }
        const originalKeys = [...(itemProps.items || [])].map((item) => item.id);
        const { target, keys: movableKeys } = e;
        const { dropPosition, key: targetKey } = target;
        const movableKey = [...movableKeys][0];
        // Get indices for the movable and target keys
        const movableIndex = originalKeys.indexOf(movableKey);
        const targetIndex = originalKeys.indexOf(targetKey);
        // If positions are the same, do nothing
        if (movableIndex === targetIndex) {
            onMove(originalKeys);
            return;
        }
        // Remove the movable key from its original position
        originalKeys.splice(movableIndex, 1);
        // Insert the movable key at the new position
        const insertIndex = dropPosition === 'before' ? targetIndex : targetIndex + 1;
        originalKeys.splice(insertIndex, 0, movableKey);
        onMove(originalKeys);
    };
    // Setup drag state for the collection.
    let dragState = useDraggableCollectionState({
        // Pass through events from props.
        ...itemProps,
        // Collection and selection manager come from list state.
        collection: state.collection,
        selectionManager: state.selectionManager,
        // Provide data for each dragged item. This function could
        // also be provided by the user of the component.
        getItems: (keys) => {
            if (isDisabled) {
                return [];
            }
            return [...keys].map((key) => {
                let item = state.collection.getItem(key);
                return {
                    'text/plain': item?.textValue || '',
                };
            });
        },
        getAllowedDropOperations: () => ['move'],
    });
    useDraggableCollection(props, dragState, ref);
    let dropState = useDroppableCollectionState({
        ...itemProps,
        onReorder,
        collection: state.collection,
        selectionManager: state.selectionManager,
    });
    let { collectionProps } = useDroppableCollection({
        ...itemProps,
        // Provide drop targets for keyboard and pointer-based drag and drop.
        keyboardDelegate: new ListKeyboardDelegate(state.collection, state.disabledKeys, ref),
        dropTargetDelegate: new ListDropTargetDelegate(state.collection, ref),
        onReorder,
    }, dropState, ref);
    return (_jsx(ReorderableListElement, { ...mergeProps(listBoxProps, collectionProps, {
            mods: { vertical: direction === 'vertical' },
        }), ref: ref, children: [...state.collection].map((item) => {
            return (_jsx(ReorderableItem, { item: item, direction: direction, state: state, isDisabled: isDisabled, hasDragButton: hasDragButton, dragState: dragState, dropState: dropState }, item.key));
        }) }));
}
const ReorderableMemberElement = tasty({
    as: 'div',
    styles: {
        position: 'sticky',
        top: 0,
        display: 'block',
        shadow: {
            '': '0',
            focused: '1bw solid #focus inset',
        },
    },
});
function ReorderableItem({ item, state, direction = 'horizontal', hasDragButton, isDisabled, dragState, dropState, }) {
    // Set up the listbox option as normal. See useListBox docs for details.
    let ref = useRef(null);
    let { optionProps } = useOption({ key: item.key }, state, ref);
    let { isFocusVisible, focusProps } = useFocusRing();
    // Register the item as a drag source.
    let { dragProps, dragButtonProps } = useDraggableItem({
        key: item.key,
        hasDragButton,
        hasAction: true,
    }, dragState);
    return (_jsx(_Fragment, { children: _jsxs(ReorderableMemberElement, { ...mergeProps(optionProps, !isDisabled ? dragProps : {}, focusProps), ref: ref, mods: {
                focused: isFocusVisible,
            }, children: [_jsx(DropIndicator, { direction: direction, position: "before", target: { type: 'item', key: item.key, dropPosition: 'before' }, dropState: dropState }), hasDragButton ? item.value?.render(dragButtonProps) : item.rendered, state.collection.getKeyAfter(item.key) == null && (_jsx(DropIndicator, { direction: direction, position: "after", target: { type: 'item', key: item.key, dropPosition: 'after' }, dropState: dropState }))] }) }));
}
const DropIndicatorElement = tasty({
    styles: {
        zIndex: 10,
        position: 'absolute',
        pointerEvents: 'none',
        opacity: {
            '': 0,
            dropTarget: 1,
        },
        fill: '#purple',
        width: {
            '': '.5x',
            vertical: '100%',
        },
        height: {
            '': '.5x',
            horizontal: '100%',
        },
        top: {
            '': 'auto',
            'vertical & before': '-2px',
        },
        bottom: {
            '': 'auto',
            'vertical & after': '-2px',
        },
        left: {
            '': 'auto',
            'horizontal & before': '-2px',
        },
        right: {
            '': 'auto',
            'horizontal & after': '-2px',
        },
    },
});
function DropIndicator(props) {
    const { position, direction = 'horizontal', target } = props;
    let ref = useRef(null);
    let { dropIndicatorProps, isHidden, isDropTarget } = useDropIndicator({ target }, props.dropState, ref);
    if (isHidden) {
        return null;
    }
    return (_jsx(DropIndicatorElement, { ref: ref, role: "option", ...dropIndicatorProps, mods: {
            'drop-target': isDropTarget,
            after: position === 'after',
            before: position === 'before',
            vertical: direction === 'vertical',
            horizontal: direction !== 'vertical',
        } }));
}
ReorderableList.Item = Object.assign(BaseItem, {
    displayName: 'Item',
});
//# sourceMappingURL=ReorderableList.js.map