/* @oracle/oraclejet-preact: undefined */
'use strict';

var jsxRuntime = require('preact/jsx-runtime');
var preact = require('preact');
var hooks = require('preact/hooks');
var compat = require('preact/compat');
var classNames = require('./classNames-c14c6ef3.js');
var useId = require('./useId-6c0eeb27.js');
var useTranslationBundle = require('./useTranslationBundle-38c0edae.js');
var keys = require('./keys-25710458.js');
var HiddenAccessible = require('./HiddenAccessible-087eb49a.js');
var ChevronDown = require('./ChevronDown-1600efef.js');
var CollapseIcon = require('./CollapseIcon-dae29332.js');
var LiveRegion = require('./LiveRegion-e3c8541c.js');
var useUser = require('./useUser-c85f9587.js');
var collectionUtils = require('./collectionUtils-7ae57f89.js');
var Button = require('./Button-2427b7df.js');
var GroupLoadingIndicator = require('./GroupLoadingIndicator-824d658f.js');
var List = require('./List-bad74e43.js');

/**
 * @license
 * Copyright (c) %FIRST_YEAR% %CURRENT_YEAR%, Oracle and/or its affiliates.
 * The Universal Permissive License (UPL), Version 1.0
 * as shown at https://oss.oracle.com/licenses/upl/
 * @ignore
 */
/**
 * A hook that handles mouse and keyboard gesture that toggles the expanded state.
 * @param keyExtractor
 * @param expanded
 * @param onToggle
 * @returns
 */
function useExpandCollapse(keyExtractor, expanded, onToggle) {
    const { direction } = useUser.useUser();
    const onClick = hooks.useCallback((event) => {
        handleToggle(event, keyExtractor, onToggle);
    }, [keyExtractor, onToggle]);
    const onKeyUp = hooks.useCallback((event) => {
        if (event.key === 'Enter' || event.key === ' ') {
            handleToggle(event, keyExtractor, onToggle);
        }
        else if (event.key === 'ArrowLeft' || event.key === 'ArrowRight') {
            const isRtl = direction === 'rtl';
            const isLeftArrow = event.key === 'ArrowLeft' && !isRtl;
            handleArrowKey(isLeftArrow, event.target, expanded, keyExtractor, onToggle);
            // arrow key might cause it to scroll horizontally
            event.preventDefault();
            event.stopPropagation();
        }
    }, [keyExtractor, onToggle, expanded, direction]);
    return onToggle ? { onClick, onKeyDown, onKeyUp } : {};
}
// prevent default (propagation) for keyDown to prevent scrolling the container
const onKeyDown = (event) => {
    if (event.key === 'Enter' ||
        event.key === ' ' ||
        event.key === 'ArrowLeft' ||
        event.key === 'ArrowRight') {
        event.preventDefault();
    }
};
const handleArrowKey = (isLeftArrow, target, expanded, keyExtractor, onToggle) => {
    const itemKey = keyExtractor(target);
    if (onToggle && itemKey) {
        const contains = keys.containsKey(expanded, itemKey);
        if ((isLeftArrow && contains) || (!isLeftArrow && !contains)) {
            onToggle({ value: itemKey });
        }
    }
};
const handleToggle = (event, keyExtractor, onToggle) => {
    const itemKey = keyExtractor(event.target);
    if (onToggle && itemKey) {
        onToggle({ value: itemKey });
        if (event.type === 'click') {
            event.stopPropagation();
        }
    }
};

/**
 * An ExpandableList shows a two-level group of items where each group header can be expand or collapse.
 */
function ExpandableList({ children, data, onSelectionChange, onToggle, onPersistCurrentItem, ...props }) {
    const [statusText, setStatusText] = hooks.useState('');
    const translations = useTranslationBundle.useTranslationBundle('@oracle/oraclejet-preact');
    const currentKey = hooks.useRef();
    const handleOnPersistCurrentItem = hooks.useCallback((detail) => {
        currentKey.current = detail.value;
        onPersistCurrentItem?.(detail);
    }, [onPersistCurrentItem]);
    const updateStateText = hooks.useCallback((detail) => {
        onToggle?.(detail);
        if (data) {
            const previouslyExpanded = keys.containsKey(data?.expanded, detail.value);
            setStatusText(previouslyExpanded
                ? translations.expandableList_groupCollapse()
                : translations.expandableList_groupExpand());
            // we need to clear the live region text otherwise screenreader
            // won't read again if the content did not change the next time
            setTimeout(() => {
                setStatusText('');
            }, 1000);
        }
    }, [onToggle, data, translations]);
    const expandCollapseProps = useExpandCollapse((element) => {
        if (element.getAttribute('role') === 'treegrid') {
            return currentKey.current === undefined ? null : currentKey.current;
        }
        return collectionUtils.keyExtractor(element, GroupLoadingIndicator.GROUP_SELECTOR);
    }, data == null ? emptyKeys : data.expanded, onToggle && updateStateText);
    const descId = useId.useId();
    const stableDescIdRef = hooks.useRef(descId);
    const createHierarchicalContext = (context, options) => {
        const expanderRenderer = options !== undefined
            ? () => (jsxRuntime.jsx(Expander, { itemKey: context.metadata.key, expanded: options.expanded, onToggle: options.onToggle }))
            : undefined;
        return {
            ...context,
            parentKey: context.metadata.parentKey,
            leaf: context.metadata.isLeaf ?? true,
            depth: context.metadata.treeDepth ?? 1,
            expander: expanderRenderer
        };
    };
    const handleSelectionChange = hooks.useCallback((detail) => {
        if (onSelectionChange && data) {
            const keys$1 = List.excludeGroup(data, detail.value);
            if (keys.isSameKey(keys$1, detail.value)) {
                onSelectionChange(detail);
            }
            else if (keys$1.keys && keys$1.keys.size > 0) {
                onSelectionChange({ ...detail, value: keys$1 });
            }
        }
    }, [onSelectionChange, data]);
    const customItemRenderer = (context) => {
        const itemKey = context.listItemContext.metadata.key;
        const options = data && onToggle ? { expanded: keys.containsKey(data.expanded, itemKey), onToggle } : undefined;
        const itemContext = createHierarchicalContext(context.listItemContext, options);
        if (itemContext.leaf) {
            return context.defaultListItem(itemContext, { itemDepth: itemContext.depth + 1 });
        }
        else {
            return (jsxRuntime.jsx(GroupLoadingIndicator.ListGroupHeader, { ariaDescribedBy: stableDescIdRef.current, itemKey: itemContext.metadata.key, itemIndex: itemContext.index, itemDepth: itemContext.depth, isFocused: context.isFocused, isFocusRingVisible: context.isFocusRingVisible, isActive: context.isActive, isGridlineVisible: false, isExpandable: true, expandedKeys: data == null ? emptyKeys : data.expanded, onToggle: onToggle, children: children(itemContext) }, itemContext.metadata.key));
        }
    };
    return (jsxRuntime.jsxs(preact.Fragment, { children: [jsxRuntime.jsx(List.List, { data: data, role: "treegrid", loadingIndicator: jsxRuntime.jsx(GroupLoadingIndicator.GroupLoadingIndicator, {}), onSelectionChange: handleSelectionChange, customItemRenderer: customItemRenderer, onPersistCurrentItem: handleOnPersistCurrentItem, ...props, ...expandCollapseProps, children: (context) => {
                    return children(context);
                } }), onToggle && (jsxRuntime.jsxs(preact.Fragment, { children: [jsxRuntime.jsx(LiveRegion.LiveRegion, { children: statusText }), jsxRuntime.jsx("span", { id: stableDescIdRef.current, children: jsxRuntime.jsx(HiddenAccessible.HiddenAccessible, { children: translations.expandableList_expandCollapseInstructionText() }) })] }))] }));
}
const emptyKeys = { all: false, keys: new Set() };
const Expander = compat.memo((props) => {
    const classes = classNames.classNames(['oj-listview-expander']);
    const actionHandler = () => {
        props.onToggle({ value: props.itemKey });
    };
    return (jsxRuntime.jsx("span", { class: classes, role: "presentation", children: jsxRuntime.jsx(Button.Button, { onAction: actionHandler, variant: "ghost", startIcon: props.expanded ? jsxRuntime.jsx(ChevronDown.SvgChevronDown, { size: "6x" }) : jsxRuntime.jsx(CollapseIcon.CollapseIcon, { size: "6x" }) }) }));
}, (prev, next) => {
    return (prev.itemKey === next.itemKey &&
        prev.expanded === next.expanded &&
        prev.onToggle === next.onToggle);
});

exports.ExpandableList = ExpandableList;
//# sourceMappingURL=ExpandableList-0a0d75b3.js.map
