'use strict';

var React = require('react');
var classnames = require('classnames');
var floatingUi_react = require('./floating-ui.react-cjs.js');
var FilterPickerContentSearch = require('./FilterPickerContentSearch-cjs.js');
var FilterPickerContentList = require('./FilterPickerContentList-cjs.js');
var FilterPickerContentHeader = require('./FilterPickerContentHeader-cjs.js');
var FilterPickerProvider = require('./FilterPickerProvider-cjs.js');
var jobberHooks = require('@jobber/hooks');
var floatingUi_reactDom = require('./floating-ui.react-dom-cjs.js');
var constants = require('./constants-cjs.js');

var styles = {"content":"bog6pntD050-","hidden":"CLGExWp0HOc-","actions":"Tuw6ng4mYhg-","actionPadding":"uC0PW9BRcl4-","spinning":"TWLS2ZoEtnQ-"};

function useFilterPickerContent(open, selected) {
    const { onClear, onSelectAll, shouldScroll } = React.useContext(FilterPickerProvider.FilterPickerContext);
    const optionsListRef = React.useRef(null);
    React.useEffect(() => {
        var _a;
        if (open && shouldScroll.current && optionsListRef.current) {
            const firstSelected = Array.from((_a = optionsListRef === null || optionsListRef === void 0 ? void 0 : optionsListRef.current) === null || _a === void 0 ? void 0 : _a.children).find(child => {
                if (child instanceof HTMLElement) {
                    return child.dataset.selected === "true";
                }
            });
            scrollToFirstSelected(firstSelected, shouldScroll);
        }
    }, [open, selected]);
    return {
        onClear,
        onSelectAll,
        optionsListRef,
    };
}
function scrollToFirstSelected(firstSelected, shouldScroll) {
    if (firstSelected) {
        firstSelected.scrollIntoView({
            block: "nearest",
        });
        shouldScroll.current = false;
    }
}

const FILTER_PICKER_OFFSET = 8;
// eslint-disable-next-line max-statements
function useFilterPickerAccessibility(selectionCallback, filteredOptions, optionsListRef, open, wrapperRef) {
    const { handleClose } = React.useContext(FilterPickerProvider.FilterPickerContext);
    const hasOptionsVisible = open && filteredOptions.length > 0;
    const focusedIndex = React.useRef(null);
    const parentNodeId = floatingUi_react.useFloatingParentNodeId();
    const nodeId = floatingUi_react.useFloatingNodeId();
    jobberHooks.useRefocusOnActivator(open);
    const floatingRef = jobberHooks.useFocusTrap(open);
    const { floatingStyles, update, context, elements } = floatingUi_react.useFloating({
        nodeId,
        elements: {
            reference: wrapperRef.current,
            floating: floatingRef.current,
        },
        placement: "bottom-start",
        open,
        onOpenChange: openState => {
            if (!openState)
                handleClose();
        },
        middleware: [
            floatingUi_reactDom.offset(FILTER_PICKER_OFFSET),
            floatingUi_reactDom.flip({ fallbackPlacements: ["top-start", "bottom-end", "top-end"] }),
        ],
    });
    const dismiss = floatingUi_react.useDismiss(context);
    const { getFloatingProps } = floatingUi_react.useInteractions([dismiss]);
    // Floating element is hidden via CSS (not conditionally rendered),
    // set up and tear down autoUpdate manually to avoid unnecessary observers.
    React.useEffect(() => {
        if (open && elements.reference && elements.floating) {
            const cleanup = floatingUi_reactDom.autoUpdate(elements.reference, elements.floating, update);
            return cleanup;
        }
    }, [open, floatingUi_reactDom.autoUpdate, elements, update]);
    React.useEffect(() => {
        focusedIndex.current = null;
        if (open) {
            update === null || update === void 0 ? void 0 : update();
        }
    }, [open, filteredOptions.length, update]);
    React.useEffect(() => {
        var _a;
        if (open) {
            (_a = floatingRef.current) === null || _a === void 0 ? void 0 : _a.addEventListener("keydown", handleContentKeydown);
        }
        return () => {
            var _a;
            (_a = floatingRef.current) === null || _a === void 0 ? void 0 : _a.removeEventListener("keydown", handleContentKeydown);
        };
    }, [open, optionsListRef, filteredOptions]);
    function handleContentKeydown(event) {
        var _a;
        if (!hasOptionsVisible)
            return;
        if (event.key === "Enter" || event.key === " ") {
            const activeElementInList = (_a = optionsListRef.current) === null || _a === void 0 ? void 0 : _a.contains(document.activeElement);
            if (!activeElementInList)
                return;
            handleKeyboardSelection(event);
        }
        if (event.key === "ArrowDown") {
            handleKeyboardNavigation(event, 1);
        }
        if (event.key === "ArrowUp") {
            handleKeyboardNavigation(event, -1);
        }
    }
    function handleKeyboardNavigation(event, indexChange) {
        var _a;
        const newIndex = focusedIndex.current === null ? 0 : focusedIndex.current + indexChange;
        if (newIndex < 0 || newIndex >= filteredOptions.length)
            return;
        const optionElement = (_a = optionsListRef.current) === null || _a === void 0 ? void 0 : _a.children[newIndex];
        optionElement === null || optionElement === void 0 ? void 0 : optionElement.focus();
        focusedIndex.current = newIndex;
        event.preventDefault();
        event.stopPropagation();
    }
    function handleKeyboardSelection(event) {
        event.preventDefault();
        event.stopPropagation();
        if (focusedIndex.current !== null) {
            selectionCallback(filteredOptions[focusedIndex.current]);
        }
    }
    return {
        floatingRef,
        floatingStyles,
        floatingProps: getFloatingProps(),
        nodeId,
        parentNodeId,
    };
}

function FilterPickerContent(props) {
    const optionsExist = props.options.length > 0;
    const { onClear, onSelectAll, optionsListRef } = useFilterPickerContent(props.open, props.selected);
    const { floatingRef, floatingStyles, floatingProps, nodeId, parentNodeId } = useFilterPickerAccessibility(props.handleSelection, props.options, optionsListRef, props.open, props.wrapperRef);
    // options that are passed back to consumers via onSelectAll callback
    // should only contain id and label
    const optionsData = React.useMemo(() => {
        return props.options.map(option => ({
            id: option.id,
            label: option.label,
        }));
    }, [props.options]);
    const content = (React.createElement("div", Object.assign({ ref: floatingRef, id: constants.FILTER_PICKER_MENU_ID, "data-testid": constants.FILTER_PICKER_MENU_ID, "data-elevation": "elevated", tabIndex: 0, className: classnames(styles.content, {
            [styles.hidden]: !props.open,
        }), style: floatingStyles }, floatingProps),
        React.createElement(FilterPickerContentSearch.FilterPickerContentSearch, { open: props.open, placeholder: props.subjectNoun, searchValue: props.searchValue, setSearchValue: props.setSearchValue, handleSearchChange: props.handleSearchChange }),
        props.multiselect && (optionsExist || props.selected.length > 0) && (React.createElement(FilterPickerContentHeader.FilterPickerContentHeader, { hasOptionsVisible: optionsExist, subjectNoun: props.subjectNoun, selectedCount: props.selected.length, onClearAll: () => {
                props.selectedStateSetter([]);
                onClear === null || onClear === void 0 ? void 0 : onClear();
            }, onSelectAll: () => {
                props.selectedStateSetter(props.options);
                onSelectAll === null || onSelectAll === void 0 ? void 0 : onSelectAll(optionsData);
            } })),
        React.createElement(FilterPickerContentList.FilterPickerContentList, { multiselect: props.multiselect, options: props.options, selected: props.selected, optionsListRef: optionsListRef, searchValue: props.searchValue, subjectNoun: props.subjectNoun, loading: props.loading, onLoadMore: props.onLoadMore }),
        props.actionElements && (React.createElement("div", { className: styles.actions, role: "group" }, props.actionElements.map((child, index, childrenArray) => (React.createElement("div", { key: index, className: classnames({
                [styles.actionPadding]: index === childrenArray.length - 1,
            }) }, child)))))));
    if (parentNodeId) {
        return (React.createElement(floatingUi_react.FloatingTree, null,
            React.createElement(floatingUi_react.FloatingNode, { id: nodeId },
                React.createElement(floatingUi_react.FloatingPortal, null, content))));
    }
    return (globalThis === null || globalThis === void 0 ? void 0 : globalThis.document) ? (React.createElement(floatingUi_react.FloatingPortal, null, content)) : (content);
}

exports.FilterPickerContent = FilterPickerContent;
