import { jsx as _jsx } from "react/jsx-runtime";
import { forwardRef, useCallback } from 'react';
import styled, { css } from 'styled-components';
import Flex from '../../Flex';
import { getFocusables } from '../../../utils';
import { defaultThemeProp } from '../../../theme';
import { hasNonNullProp } from './utils';
/** CSS Class name for GridEditor resize-handles */
export const resizeHandleClassName = 'gridLayoutCustomResizeHandle';
// To appear above the child contents at all times
const StyledWrapper = styled(Flex)(({ theme }) => {
    const { base, components } = theme;
    return css `
    position: relative;

    /* To create a new stacking context */
    z-index: 0;
    background-color: ${base.palette['primary-background']};

    .${resizeHandleClassName} {
      opacity: 0;
    }

    /* To mask the child content from getting clicked when dragging a grid item */
    &::after {
      content: '';
      position: absolute;
      z-index: ${base['z-index'].max - 1};
      inset: 0;
    }

    &:focus,
    &:hover {
      &::after {
        border: 0.125rem solid ${base.palette.interactive};

        /* For widgets where the interactive border might not be visible */
        outline: 0.125rem solid ${components.card.background};
        outline-offset: -0.25rem;
      }
      .${resizeHandleClassName} {
        opacity: 1;
      }
    }
  `;
});
StyledWrapper.defaultProps = defaultThemeProp;
const axisWiseStyles = {
    n: css `
    inset-block-start: 0;
    inset-inline-start: 50%;
    margin-inline-start: -0.625rem;
    border-block-start-width: 0;
    border-inline-start-width: 0.375rem;
    border-inline-end-width: 0.375rem;
    border-block-end-width: 0.875rem;
    cursor: n-resize;
  `,
    s: css `
    inset-block-end: 0;
    inset-inline-start: 50%;
    margin-inline-start: -0.625rem;
    border-block-start-width: 0.875rem;
    border-inline-start-width: 0.375rem;
    border-inline-end-width: 0.375rem;
    border-block-end-width: 0;
    cursor: s-resize;
  `,
    e: css `
    inset-inline-end: 0;
    inset-block-start: 50%;
    margin-block-start: -0.625rem;
    border-block-start-width: 0.375rem;
    border-inline-start-width: 0.875rem;
    border-inline-end-width: 0;
    border-block-end-width: 0.375rem;
    cursor: e-resize;
  `,
    w: css `
    inset-inline-start: 0;
    inset-block-start: 50%;
    margin-block-start: -0.625rem;
    border-block-start-width: 0.375rem;
    border-inline-start-width: 0;
    border-inline-end-width: 0.875rem;
    border-block-end-width: 0.375rem;
    cursor: w-resize;
  `,
    ne: css `
    inset-block-start: 0;
    inset-inline-end: 0;
    border-block-start-width: 0;
    border-inline-start-width: 0.875rem;
    border-inline-end-width: 0;
    border-block-end-width: 0.875rem;
    cursor: ne-resize;
  `,
    nw: css `
    inset-block-start: 0;
    inset-inline-start: 0;
    border-block-start-width: 0;
    border-inline-start-width: 0;
    border-inline-end-width: 0.875rem;
    border-block-end-width: 0.875rem;
    cursor: nw-resize;
  `,
    sw: css `
    inset-block-end: 0;
    inset-inline-start: 0;
    border-block-start-width: 0.875rem;
    border-inline-start-width: 0;
    border-inline-end-width: 0.875rem;
    border-block-end-width: 0;
    cursor: sw-resize;
  `,
    se: css `
    inset-block-end: 0;
    inset-inline-end: 0;
    border-block-start-width: 0.875rem;
    border-inline-start-width: 0.875rem;
    border-inline-end-width: 0;
    border-block-end-width: 0;
    cursor: se-resize;
  `
};
const StyledHandle = styled.div(({ theme, axis }) => {
    const { base } = theme;
    return css `
    position: absolute;
    z-index: ${base['z-index'].max};
    inline-size: 1.25rem;
    block-size: 1.25rem;
    border: solid transparent;

    /* Using box-shadow instead of background coz the latter will be visible underneath the border as well. */
    /* We still want the 20x20 clickable region, but an 8x8 visible region. */
    box-shadow:
      inset 0.25rem 0.25rem 0 ${base.palette.interactive},
      inset -0.25rem -0.25rem 0 ${base.palette.interactive};

    ${axisWiseStyles[axis]}
  `;
});
StyledHandle.defaultProps = defaultThemeProp;
/** Custom resize-handle for GridLayoutEditor */
export const ResizeHandle = forwardRef((props, ref) => {
    const { handleAxis, ...restProps } = props;
    return (_jsx(StyledHandle, { ref: ref, axis: handleAxis, className: resizeHandleClassName, ...restProps }));
});
/**
 * Wrapper on top of GridItems to provide custom styling etc.
 * https://github.com/react-grid-layout/react-grid-layout#custom-child-components-and-draggable-handles
 */
const EditorGridItem = forwardRef(({ children, itemKey, itemLabel, moveItem, addOrSubtractItemSize, ...restProps }, ref) => {
    const handleKeyUp = useCallback((e) => {
        switch (e.key) {
            case 'ArrowUp':
                if (e.shiftKey)
                    addOrSubtractItemSize(itemKey, 0, -1);
                else
                    moveItem(itemKey, 0, -1);
                break;
            case 'ArrowDown':
                if (e.shiftKey)
                    addOrSubtractItemSize(itemKey, 0, 1);
                else
                    moveItem(itemKey, 0, 1);
                break;
            case 'ArrowLeft':
                if (e.shiftKey)
                    addOrSubtractItemSize(itemKey, -1, 0);
                else
                    moveItem(itemKey, -1, 0);
                break;
            case 'ArrowRight':
                if (e.shiftKey)
                    addOrSubtractItemSize(itemKey, 1, 0);
                else
                    moveItem(itemKey, 1, 0);
                break;
            // Do nothing
            default:
        }
    }, [addOrSubtractItemSize, itemKey, moveItem]);
    // To keep the experience smoother, disabling all interactions on the child content of grid items.
    // The CSS `::after` mask prevents interactions through mouse clicks.
    // This method prevents interactions through keyboard navigation.
    // Not doing this from a `useEffect` since some of the child content can render after server calls etc.
    const disableChildrenFocus = useCallback(() => {
        if (!ref)
            return;
        // In case RGL ever uses a RefCallback instead of a RefObject
        if (!hasNonNullProp(ref, 'current'))
            return;
        const focusables = getFocusables(ref);
        focusables.forEach(elem => {
            elem.tabIndex = -1;
        });
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, []);
    return (_jsx(StyledWrapper, { container: { direction: 'column' }, ref: ref, ...restProps, role: 'listitem', tabIndex: 0, "aria-label": itemLabel, onKeyUp: handleKeyUp, onFocus: disableChildrenFocus, children: children }));
});
export default EditorGridItem;
//# sourceMappingURL=EditorGridItem.js.map