Handle oudside click for filters popover (#4021)
* Oudside click handler * Oudside click handler * Changeset
This commit is contained in:
parent
d08527f7db
commit
436c2af00e
6 changed files with 39 additions and 4 deletions
5
.changeset/rotten-otters-shop.md
Normal file
5
.changeset/rotten-otters-shop.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
"saleor-dashboard": patch
|
||||
---
|
||||
|
||||
Handle oudside click for filters popover
|
|
@ -17,7 +17,11 @@ import { useIntl } from "react-intl";
|
|||
export const ExpressionFilters = () => {
|
||||
const [open, setOpen] = useState(false);
|
||||
const { formatMessage } = useIntl();
|
||||
const { valueProvider } = useConditionalFilterContext();
|
||||
const { valueProvider, containerState } = useConditionalFilterContext();
|
||||
|
||||
const clickOutside = () => {
|
||||
containerState.clearEmpty()
|
||||
}
|
||||
|
||||
return (
|
||||
<Popover open={open} onOpenChange={open => setOpen(open)}>
|
||||
|
@ -28,7 +32,7 @@ export const ExpressionFilters = () => {
|
|||
})}
|
||||
</DropdownButton>
|
||||
</Popover.Trigger>
|
||||
<Popover.Content align="start">
|
||||
<Popover.Content align="start" onInteractOutside={clickOutside}>
|
||||
<Box
|
||||
__minHeight="250px"
|
||||
__minWidth="636px"
|
||||
|
|
|
@ -164,6 +164,10 @@ export class FilterElement {
|
|||
return UrlEntry.forStatic(this.condition.selected, this.value.value);
|
||||
}
|
||||
|
||||
public equals(element: FilterElement) {
|
||||
return this.value.value === element.value.value
|
||||
}
|
||||
|
||||
public static isCompatible(element: unknown): element is FilterElement {
|
||||
return (
|
||||
typeof element === "object" &&
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import { FilterContainer } from "./FilterElement";
|
||||
import { FilterContainer, FilterElement } from "./FilterElement";
|
||||
|
||||
export interface FilterValueProvider {
|
||||
value: FilterContainer;
|
||||
loading: boolean;
|
||||
persist: (newValue: FilterContainer) => void;
|
||||
isPersisted: (element: FilterElement) => boolean;
|
||||
clear: () => void;
|
||||
count: number;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ import { useEffect, useState } from "react";
|
|||
import useRouter from "use-react-router";
|
||||
|
||||
import { InitialAPIState } from "../API";
|
||||
import { FilterContainer } from "../FilterElement";
|
||||
import { FilterContainer, FilterElement } from "../FilterElement";
|
||||
import { FilterValueProvider } from "../FilterValueProvider";
|
||||
import { useTokenArray } from "./TokenArray";
|
||||
import { UrlEntry } from "./UrlToken";
|
||||
|
@ -61,6 +61,10 @@ export const useUrlValueProvider = (
|
|||
setValue([]);
|
||||
};
|
||||
|
||||
const isPersisted = (element: FilterElement) => {
|
||||
return value.some(p => FilterElement.isCompatible(p) && p.equals(element))
|
||||
}
|
||||
|
||||
const count = value.filter(v => typeof v !== "string").length;
|
||||
|
||||
return {
|
||||
|
@ -68,6 +72,7 @@ export const useUrlValueProvider = (
|
|||
loading,
|
||||
persist,
|
||||
clear,
|
||||
isPersisted,
|
||||
count,
|
||||
};
|
||||
};
|
||||
|
|
|
@ -49,6 +49,17 @@ const removeElement = (container: FilterContainer, position: number) => {
|
|||
return removeConstraint(newContainer);
|
||||
};
|
||||
|
||||
const removeEmptyElements = (container: FilterContainer, provider: FilterValueProvider): FilterContainer => {
|
||||
const emptyIndex = container.findIndex(el =>
|
||||
FilterElement.isCompatible(el) && (!provider.isPersisted(el) || el.isEmpty())
|
||||
)
|
||||
|
||||
if (emptyIndex < 0) return container
|
||||
|
||||
return removeEmptyElements(removeElement(container, emptyIndex), provider)
|
||||
}
|
||||
|
||||
|
||||
export const useContainerState = (valueProvider: FilterValueProvider) => {
|
||||
const [value, setValue] = useState<FilterContainer>([]);
|
||||
|
||||
|
@ -124,6 +135,10 @@ export const useContainerState = (valueProvider: FilterValueProvider) => {
|
|||
setValue([]);
|
||||
};
|
||||
|
||||
const clearEmpty = () => {
|
||||
setValue(v => removeEmptyElements(v, valueProvider))
|
||||
}
|
||||
|
||||
return {
|
||||
create,
|
||||
exist,
|
||||
|
@ -133,5 +148,6 @@ export const useContainerState = (valueProvider: FilterValueProvider) => {
|
|||
removeAt,
|
||||
value,
|
||||
clear,
|
||||
clearEmpty
|
||||
};
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue