"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.DataFilters = void 0;
var _Popover2 = _interopRequireDefault(require("@mui/material/Popover"));
var _IconButton2 = _interopRequireDefault(require("@mui/material/IconButton"));
var _Menu2 = _interopRequireDefault(require("@mui/material/Menu"));
var _MenuItem2 = _interopRequireDefault(require("@mui/material/MenuItem"));
var _Typography2 = _interopRequireDefault(require("@mui/material/Typography"));
var _styled = _interopRequireDefault(require("@emotion/styled"));
var _react = require("react");
var _Autocomplete = require("../Autocomplete.cjs");
var _Box = require("../Box.cjs");
var _Button = require("../Buttons/Button.cjs");
var _Checkbox = require("../Fields/Checkbox.cjs");
var _CheckboxGroup = require("../Fields/CheckboxGroup.cjs");
var _Radio = require("../Fields/Radio.cjs");
var _RadioGroup = require("../Fields/RadioGroup.cjs");
var _i18n = require("../i18n.generated/i18n.cjs");
var _index = require("../icons.generated/index.cjs");
var _OdysseyDesignTokensContext = require("../OdysseyDesignTokensContext.cjs");
var _SearchField = require("../SearchField.cjs");
var _Tag = require("../Tag.cjs");
var _TagList = require("../TagList.cjs");
var _TextField = require("../TextField.cjs");
var _Typography3 = require("../Typography.cjs");
var _jsxRuntime = require("react/jsx-runtime");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/*!
 * Copyright (c) 2023-present, Okta, Inc. and/or its affiliates. All rights reserved.
 * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.")
 *
 * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *
 * See the License for the specific language governing permissions and limitations under the License.
 */

const StyledAutocompleteOuterContainer = (0, _styled.default)("div", {
  shouldForwardProp: prop => prop !== "odysseyDesignTokens"
})(({
  odysseyDesignTokens
}) => ({
  display: "flex",
  alignItems: "flex-end",
  gap: odysseyDesignTokens.Spacing2
}));
const StyledAutocompleteInnerContainer = (0, _styled.default)("div")({
  width: "100%"
});
const FilterTags = ({
  activeFilters,
  updateFilterAndInputValues
}) => {
  const filtersWithValues = activeFilters.filter(activeFilter => activeFilter.value);
  const filtersToRender = [];
  filtersWithValues.forEach(filter => {
    if (Array.isArray(filter.value)) {
      filter.value.forEach(filterValue => {
        const formattedValue = typeof filterValue === "string" ? filterValue : filterValue.value;
        filtersToRender.push({
          id: filter.id,
          label: filter.label,
          value: formattedValue
        });
      });
    }
    if (typeof filter.value === "string") {
      filtersToRender.push({
        id: filter.id,
        label: filter.label,
        value: filter.value
      });
    }
  });
  const getFilter = id => filtersWithValues.find(filter => filter.id === id);
  const removeValueFromFilterAndInput = (id, removedFilterValue) => {
    const currentFilter = getFilter(id);
    if (currentFilter) {
      const {
        value
      } = currentFilter;
      if (Array.isArray(value)) {
        const updatedValues = value.filter(currentValue => {
          return currentValue.value !== removedFilterValue;
        });
        updateFilterAndInputValues({
          filterId: id,
          value: updatedValues.length > 0 ? updatedValues : undefined
        });
      }
      if (typeof value === "string") {
        updateFilterAndInputValues({
          filterId: id,
          value: undefined
        });
      }
    }
  };
  return (0, _jsxRuntime.jsx)(_TagList.TagList, {
    children: filtersToRender.map(filter => (0, _jsxRuntime.jsx)(_Tag.Tag, {
      label: `${filter.label}: ${filter.value}`,
      onRemove: () => removeValueFromFilterAndInput(filter.id, filter.value)
    }, `${filter.label}: ${filter.value}`))
  });
};
const MemoizedFilterTags = (0, _react.memo)(FilterTags);
MemoizedFilterTags.displayName = "FilterTags";
const DataFilters = ({
  onChangeSearch,
  onChangeFilters,
  hasSearchSubmitButton = false,
  searchDelayTime = 200,
  defaultSearchTerm = "",
  additionalActions,
  filters: filtersProp = [],
  isDisabled
}) => {
  const [filters, setFilters] = (0, _react.useState)(filtersProp);
  const {
    t
  } = (0, _i18n.useTranslation)();
  const odysseyDesignTokens = (0, _OdysseyDesignTokensContext.useOdysseyDesignTokens)();
  const initialInputValues = (0, _react.useMemo)(() => {
    return filtersProp.reduce((accumulator, filter) => {
      accumulator[filter.id] = filter.value;
      return accumulator;
    }, {});
  }, [filtersProp]);
  const [inputValues, setInputValues] = (0, _react.useState)(initialInputValues);
  const [searchValue, setSearchValue] = (0, _react.useState)(defaultSearchTerm);
  const activeFilters = (0, _react.useMemo)(() => {
    return filters.filter(filter => filter.value);
  }, [filters]);
  const [isFiltersMenuOpen, setIsFiltersMenuOpen] = (0, _react.useState)(false);
  const [filtersMenuAnchorElement, setFiltersMenuAnchorElement] = (0, _react.useState)();
  const [isFilterPopoverOpen, setIsFilterPopoverOpen] = (0, _react.useState)(false);
  const [filterPopoverAnchorElement, setFilterPopoverAnchorElement] = (0, _react.useState)();
  const [filterPopoverCurrentFilter, setFilterPopoverCurrentFilter] = (0, _react.useState)();
  const menuRef = (0, _react.useRef)();
  (0, _react.useEffect)(() => {
    onChangeFilters?.(filters);
  }, [filters, onChangeFilters]);
  const debouncer = (0, _react.useRef)(undefined);
  (0, _react.useEffect)(() => {
    if (!hasSearchSubmitButton) {
      if (debouncer.current) {
        clearTimeout(debouncer.current);
      }
      debouncer.current = setTimeout(() => {
        onChangeSearch?.(searchValue ?? "");
      }, searchDelayTime);
    }
  }, [onChangeSearch, searchValue, searchDelayTime, hasSearchSubmitButton]);
  const autocompleteOptions = (0, _react.useMemo)(() => {
    return filterPopoverCurrentFilter?.options || [];
  }, [filterPopoverCurrentFilter]);
  const updateInputValue = (0, _react.useCallback)(({
    filterId,
    value
  }) => {
    setInputValues({
      ...inputValues,
      [filterId]: value
    });
  }, [inputValues]);
  const updateFilters = (0, _react.useCallback)(({
    filterId,
    value
  }) => {
    setInputValues(prevInputValues => ({
      ...prevInputValues,
      [filterId]: value
    }));
    const updatedFilters = filtersProp.map(filter => ({
      ...filter,
      value: filter.id === filterId ? value : inputValues[filter.id]
    }));
    setFilters(updatedFilters);
  }, [inputValues, filtersProp]);
  const updateFilterAndInputValues = (0, _react.useCallback)(({
    filterId,
    value
  }) => {
    updateInputValue({
      filterId,
      value
    });
    updateFilters({
      filterId,
      value
    });
  }, [updateFilters, updateInputValue]);
  const handleCheckboxFilterAndInputValueChange = (0, _react.useCallback)((filterId, option, checked) => {
    const currentValues = inputValues[filterId] || [];
    const updatedValues = checked ? [...currentValues, option] : currentValues.filter(inputValue => inputValue.value !== option.value);
    const normalizedUpdatedValues = updatedValues.length > 0 ? updatedValues : undefined;
    setInputValues({
      ...inputValues,
      [filterId]: normalizedUpdatedValues
    });
    const updatedFilters = filters.map(filter => ({
      ...filter,
      value: filter.id === filterId ? normalizedUpdatedValues : inputValues[filter.id]
    }));
    setFilters(updatedFilters);
  }, [filters, inputValues]);
  const handleAutocompleteFilterChange = (0, _react.useCallback)((filterId, option) => {
    setInputValues({
      ...inputValues,
      [filterId]: option
    });
  }, [inputValues]);
  const clearAllFilters = (0, _react.useCallback)(() => {
    const updatedInputValues = filtersProp.reduce((accumulator, filter) => {
      accumulator[filter.id] = undefined;
      return accumulator;
    }, {});
    setInputValues(updatedInputValues);
    const updatedFilters = filtersProp.map(filter => ({
      ...filter,
      value: undefined
    }));
    setFilters(updatedFilters);
  }, [filtersProp]);
  const handleFilterSubmit = (0, _react.useCallback)(() => {
    const updatedFilters = filtersProp.map(filter => ({
      ...filter,
      value: inputValues[filter.id]
    }));
    setFilters(updatedFilters);
  }, [inputValues, filtersProp]);
  const filterMenu = (0, _react.useMemo)(() => (0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
    children: [(0, _jsxRuntime.jsx)(_Box.Box, {
      children: (0, _jsxRuntime.jsx)(_Button.Button, {
        ariaControls: isFiltersMenuOpen ? "filters-menu" : undefined,
        ariaExpanded: isFiltersMenuOpen ? "true" : undefined,
        ariaHasPopup: "true",
        ariaLabel: t("filters.filters.arialabel"),
        endIcon: (0, _jsxRuntime.jsx)(_index.FilterIcon, {}),
        isDisabled: isDisabled,
        onClick: event => {
          setFiltersMenuAnchorElement(event.currentTarget);
          setIsFiltersMenuOpen(true);
        },
        variant: "secondary"
      })
    }), (0, _jsxRuntime.jsx)(_Menu2.default, {
      anchorEl: filtersMenuAnchorElement,
      anchorOrigin: {
        horizontal: "left",
        vertical: "bottom"
      },
      id: "filters-menu",
      onClose: () => setIsFiltersMenuOpen(false),
      open: isFiltersMenuOpen,
      PaperProps: {
        ref: menuRef
      },
      transformOrigin: {
        horizontal: "left",
        vertical: "top"
      },
      children: filtersProp.map(filter => {
        const latestFilterValue = filters.find(f => f.id === filter.id)?.value;
        return (0, _jsxRuntime.jsx)(_MenuItem2.default, {
          "aria-controls": isFilterPopoverOpen ? "filter-form" : undefined,
          className: filterPopoverCurrentFilter === filter && isFilterPopoverOpen === true ? "isVisiblySelected" : undefined,
          onClick: event => {
            setIsFilterPopoverOpen(true);
            setFilterPopoverAnchorElement(event.currentTarget);
            setFilterPopoverCurrentFilter(filter);
          },
          selected: filterPopoverCurrentFilter === filter && isFilterPopoverOpen === true,
          children: (0, _jsxRuntime.jsxs)(_Box.Box, {
            sx: {
              display: "flex",
              alignItems: "center",
              justifyContent: "space-between",
              width: "100%",
              minWidth: 180,
              paddingBlock: 1,
              paddingInlineStart: 2
            },
            children: [(0, _jsxRuntime.jsxs)(_Box.Box, {
              sx: {
                marginRight: 2
              },
              children: [(0, _jsxRuntime.jsx)(_Typography2.default, {
                fontWeight: "500",
                sx: {
                  marginBlockEnd: 2
                },
                children: filter.label
              }), (0, _jsxRuntime.jsx)(_Typography3.Subordinate, {
                component: "div",
                children: !latestFilterValue || Array.isArray(latestFilterValue) && latestFilterValue.length === 0 ? (0, _jsxRuntime.jsx)(_i18n.Trans, {
                  i18nKey: "filters.menuitem.any",
                  values: {
                    label: filter.label.toLowerCase()
                  }
                }) : Array.isArray(latestFilterValue) ? (0, _jsxRuntime.jsx)(_i18n.Trans, {
                  count: latestFilterValue.length,
                  i18nKey: "filters.menuitem.selected",
                  values: {
                    selected: latestFilterValue.length
                  }
                }) : latestFilterValue
              })]
            }), (0, _jsxRuntime.jsx)(_index.ChevronRightIcon, {})]
          })
        }, filter.id);
      })
    })]
  }), [isFiltersMenuOpen, isDisabled, filterPopoverCurrentFilter, isFilterPopoverOpen, filtersMenuAnchorElement, filtersProp, filters, t]);
  const autoCompleteValue = (0, _react.useMemo)(() => filterPopoverCurrentFilter?.id ? inputValues[filterPopoverCurrentFilter.id] : undefined, [filterPopoverCurrentFilter, inputValues]);
  return (0, _jsxRuntime.jsxs)(_Box.Box, {
    children: [(0, _jsxRuntime.jsxs)(_Box.Box, {
      sx: {
        display: "flex",
        justifyContent: "space-between"
      },
      children: [(0, _jsxRuntime.jsxs)(_Box.Box, {
        sx: {
          display: "flex",
          gap: 2,
          width: "50%",
          maxWidth: 480
        },
        children: [filters.length > 0 && (0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
          children: [filterMenu, (0, _jsxRuntime.jsx)(_Popover2.default, {
            anchorEl: filterPopoverAnchorElement,
            anchorOrigin: {
              vertical: "top",
              horizontal: "right"
            },
            elevation: 2,
            id: "filter-form",
            onClose: ev => {
              if (menuRef.current) {
                const menuRect = menuRef.current.getBoundingClientRect();
                const clickInsideMenu = ev.clientX >= menuRect.left && ev.clientX <= menuRect.right && ev.clientY >= menuRect.top && ev.clientY <= menuRect.bottom;
                if (!clickInsideMenu) {
                  setIsFiltersMenuOpen(false);
                }
              }
              handleFilterSubmit();
              setIsFilterPopoverOpen(false);
            },
            open: isFilterPopoverOpen,
            sx: {
              marginLeft: 2,
              marginTop: -1
            },
            children: (0, _jsxRuntime.jsx)(_Box.Box, {
              sx: {
                padding: 4,
                minWidth: 320
              },
              children: (0, _jsxRuntime.jsx)("form", {
                noValidate: true,
                onSubmit: ev => {
                  ev.preventDefault();
                  handleFilterSubmit();
                  setIsFilterPopoverOpen(false);
                  setIsFiltersMenuOpen(false);
                },
                children: filterPopoverCurrentFilter?.render ? filterPopoverCurrentFilter.render(updateFilters) : (0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
                  children: [filterPopoverCurrentFilter?.variant === "autocomplete" && filterPopoverCurrentFilter?.options && (0, _jsxRuntime.jsxs)(StyledAutocompleteOuterContainer, {
                    odysseyDesignTokens: odysseyDesignTokens,
                    children: [(0, _jsxRuntime.jsx)(StyledAutocompleteInnerContainer, {
                      children: (0, _jsxRuntime.jsx)(_Autocomplete.Autocomplete, {
                        hasMultipleChoices: true,
                        isCustomValueAllowed: filterPopoverCurrentFilter?.isCustomValueAllowed,
                        label: filterPopoverCurrentFilter.label,
                        onChange: (_, value) => {
                          handleAutocompleteFilterChange(filterPopoverCurrentFilter.id, value);
                        },
                        options: autocompleteOptions,
                        value: autoCompleteValue
                      })
                    }), (0, _jsxRuntime.jsx)(_Button.Button, {
                      ariaLabel: t("filters.submit.label"),
                      endIcon: (0, _jsxRuntime.jsx)(_index.CheckIcon, {}),
                      type: "submit",
                      variant: "primary"
                    })]
                  }), (filterPopoverCurrentFilter?.variant === "text" || filterPopoverCurrentFilter?.variant === "range" || filterPopoverCurrentFilter && filterPopoverCurrentFilter?.variant == undefined) && (0, _jsxRuntime.jsxs)(_Box.Box, {
                    sx: {
                      display: "flex",
                      gap: 2,
                      alignItems: "flex-end"
                    },
                    children: [(0, _jsxRuntime.jsx)(_Box.Box, {
                      sx: {
                        width: "100%"
                      },
                      children: (0, _jsxRuntime.jsx)(_TextField.TextField, {
                        endAdornment: inputValues[filterPopoverCurrentFilter.id] && (0, _jsxRuntime.jsx)(_IconButton2.default, {
                          "aria-label": t("filters.filter.clear"),
                          onClick: () => {
                            updateInputValue({
                              filterId: filterPopoverCurrentFilter.id,
                              value: undefined
                            });
                            updateFilters({
                              filterId: filterPopoverCurrentFilter.id,
                              value: undefined
                            });
                          },
                          size: "small",
                          children: (0, _jsxRuntime.jsx)(_index.CloseCircleFilledIcon, {})
                        }),
                        hasInitialFocus: true,
                        label: filterPopoverCurrentFilter.label,
                        onChange: ev => updateInputValue({
                          filterId: filterPopoverCurrentFilter.id,
                          value: ev.currentTarget.value
                        }),
                        type: filterPopoverCurrentFilter.variant === "range" ? "number" : "text",
                        value: inputValues[filterPopoverCurrentFilter.id] ?? ""
                      })
                    }), (0, _jsxRuntime.jsx)(_Button.Button, {
                      ariaLabel: t("filters.submit.label"),
                      endIcon: (0, _jsxRuntime.jsx)(_index.CheckIcon, {}),
                      type: "submit",
                      variant: "primary"
                    })]
                  }), filterPopoverCurrentFilter?.variant === "multi-select" && filterPopoverCurrentFilter?.options && (0, _jsxRuntime.jsx)(_CheckboxGroup.CheckboxGroup, {
                    isRequired: true,
                    label: filterPopoverCurrentFilter.label,
                    children: filterPopoverCurrentFilter.options.map(option => {
                      const checkFilterInputValuesAsArray = inputValues[filterPopoverCurrentFilter.id] || [];
                      const isOptionValueInInputValues = checkFilterInputValuesAsArray.some(inputValue => inputValue.value === option.value);
                      return (0, _jsxRuntime.jsx)(_Checkbox.Checkbox, {
                        isChecked: isOptionValueInInputValues,
                        label: option.label,
                        onChange: (_, checked) => {
                          handleCheckboxFilterAndInputValueChange(filterPopoverCurrentFilter.id, option, checked);
                        },
                        value: option.value
                      }, option.value);
                    })
                  }), filterPopoverCurrentFilter?.variant === "select" && filterPopoverCurrentFilter?.options && (0, _jsxRuntime.jsxs)(_RadioGroup.RadioGroup, {
                    label: filterPopoverCurrentFilter.label,
                    onChange: (_, value) => {
                      updateFilterAndInputValues({
                        filterId: filterPopoverCurrentFilter.id,
                        value
                      });
                    },
                    children: [(0, _jsxRuntime.jsx)(_Radio.Radio, {
                      isChecked: !inputValues[filterPopoverCurrentFilter.id],
                      label: t("filters.filter.any"),
                      value: ""
                    }), (0, _jsxRuntime.jsx)(_jsxRuntime.Fragment, {
                      children: filterPopoverCurrentFilter.options.map(option => (0, _jsxRuntime.jsx)(_Radio.Radio, {
                        isChecked: inputValues[filterPopoverCurrentFilter.id] === option.value,
                        label: option.label,
                        value: option.value
                      }, option.value))
                    })]
                  })]
                })
              })
            })
          })]
        }), onChangeSearch && (0, _jsxRuntime.jsx)("form", {
          onSubmit: event => {
            event.preventDefault();
            if (hasSearchSubmitButton) {
              onChangeSearch(searchValue);
            }
          },
          style: {
            width: "100%"
          },
          children: (0, _jsxRuntime.jsxs)(_Box.Box, {
            sx: {
              display: "flex",
              gap: 2,
              width: "100%"
            },
            children: [(0, _jsxRuntime.jsx)(_SearchField.SearchField, {
              isDisabled: isDisabled,
              label: t("filters.search.label"),
              onChange: ev => setSearchValue(ev.target.value),
              onClear: () => {
                setSearchValue("");
                onChangeSearch("");
              },
              placeholder: t("filters.search.label"),
              value: searchValue
            }), hasSearchSubmitButton && (0, _jsxRuntime.jsx)(_Box.Box, {
              children: (0, _jsxRuntime.jsx)(_Button.Button, {
                isDisabled: isDisabled,
                label: t("filters.search.label"),
                onClick: () => onChangeSearch(searchValue),
                variant: "primary"
              })
            })]
          })
        })]
      }), (0, _jsxRuntime.jsxs)(_Box.Box, {
        sx: {
          display: "flex",
          gap: 2
        },
        children: [activeFilters.length > 0 && (0, _jsxRuntime.jsx)(_Box.Box, {
          children: (0, _jsxRuntime.jsx)(_Button.Button, {
            label: t("filters.clear.label"),
            onClick: clearAllFilters,
            variant: "secondary"
          })
        }), additionalActions]
      })]
    }), activeFilters.length > 0 && (0, _jsxRuntime.jsx)(_Box.Box, {
      sx: {
        borderTopWidth: 1,
        borderTopColor: "#eeeeee",
        borderTopStyle: "solid",
        paddingTop: 4,
        marginTop: 4
      },
      children: (0, _jsxRuntime.jsx)(MemoizedFilterTags, {
        activeFilters: activeFilters,
        updateFilterAndInputValues: updateFilterAndInputValues
      })
    })]
  });
};
const MemoizedDataFilters = exports.DataFilters = (0, _react.memo)(DataFilters);
MemoizedDataFilters.displayName = "DataFilters";
//# sourceMappingURL=DataFilters.cjs.map