fix: hover states on filters and chip groups (#9511)
* fix: hover states on filters and chip groups * fix: create FilterChip component
This commit is contained in:
1 parent
7ec174309a
commit
0e11e89233
7 files changed
+146
-332
No files matched your search
@@ -76,7 +76,7 @@ const Chip = ({ index, className, children }: ChipProps) => {
|
|||||||
return (
|
return (
|
||||||
<li
|
<li
|
||||||
className={clx(
|
className={clx(
|
||||||
"bg-ui-bg-component shadow-borders-base flex items-center divide-x overflow-hidden rounded-md",
|
"bg-ui-bg-component shadow-borders-base flex items-stretch divide-x overflow-hidden rounded-md",
|
||||||
{
|
{
|
||||||
"bg-ui-bg-component": variant === "component",
|
"bg-ui-bg-component": variant === "component",
|
||||||
"bg-ui-bg-base-": variant === "base",
|
"bg-ui-bg-base-": variant === "base",
|
||||||
|
|||||||
+8
-70
@@ -1,8 +1,8 @@
|
|||||||
import { EllipseMiniSolid, XMarkMini } from "@medusajs/icons"
|
import { EllipseMiniSolid } from "@medusajs/icons"
|
||||||
import { DatePicker, Text, clx } from "@medusajs/ui"
|
import { DatePicker, Text, clx } from "@medusajs/ui"
|
||||||
import * as Popover from "@radix-ui/react-popover"
|
import * as Popover from "@radix-ui/react-popover"
|
||||||
import isEqual from "lodash/isEqual"
|
import isEqual from "lodash/isEqual"
|
||||||
import { MouseEvent, useMemo, useState } from "react"
|
import { useMemo, useState } from "react"
|
||||||
|
|
||||||
import { t } from "i18next"
|
import { t } from "i18next"
|
||||||
import { useTranslation } from "react-i18next"
|
import { useTranslation } from "react-i18next"
|
||||||
@@ -10,6 +10,7 @@ import { useDate } from "../../../../hooks/use-date"
|
|||||||
import { useSelectedParams } from "../hooks"
|
import { useSelectedParams } from "../hooks"
|
||||||
import { useDataTableFilterContext } from "./context"
|
import { useDataTableFilterContext } from "./context"
|
||||||
import { IFilter } from "./types"
|
import { IFilter } from "./types"
|
||||||
|
import FilterChip from "./filter-chip"
|
||||||
|
|
||||||
type DateFilterProps = IFilter
|
type DateFilterProps = IFilter
|
||||||
|
|
||||||
@@ -96,6 +97,8 @@ export const DateFilter = ({
|
|||||||
|
|
||||||
const displayValue = getDisplayValueFromPresets() || getCustomDisplayValue()
|
const displayValue = getDisplayValueFromPresets() || getCustomDisplayValue()
|
||||||
|
|
||||||
|
const [previousValue, setPreviousValue] = useState<string | undefined>(displayValue)
|
||||||
|
|
||||||
const handleRemove = () => {
|
const handleRemove = () => {
|
||||||
selectedParams.delete()
|
selectedParams.delete()
|
||||||
removeFilter(key)
|
removeFilter(key)
|
||||||
@@ -105,6 +108,7 @@ export const DateFilter = ({
|
|||||||
|
|
||||||
const handleOpenChange = (open: boolean) => {
|
const handleOpenChange = (open: boolean) => {
|
||||||
setOpen(open)
|
setOpen(open)
|
||||||
|
setPreviousValue(displayValue)
|
||||||
|
|
||||||
if (timeoutId) {
|
if (timeoutId) {
|
||||||
clearTimeout(timeoutId)
|
clearTimeout(timeoutId)
|
||||||
@@ -119,7 +123,8 @@ export const DateFilter = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Popover.Root modal open={open} onOpenChange={handleOpenChange}>
|
<Popover.Root modal open={open} onOpenChange={handleOpenChange}>
|
||||||
<DateDisplay
|
<FilterChip
|
||||||
|
hadPreviousValue={!!previousValue}
|
||||||
label={label}
|
label={label}
|
||||||
value={displayValue}
|
value={displayValue}
|
||||||
onRemove={handleRemove}
|
onRemove={handleRemove}
|
||||||
@@ -236,73 +241,6 @@ export const DateFilter = ({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
type DateDisplayProps = {
|
|
||||||
label: string
|
|
||||||
value?: string
|
|
||||||
readonly?: boolean
|
|
||||||
onRemove: () => void
|
|
||||||
}
|
|
||||||
|
|
||||||
const DateDisplay = ({
|
|
||||||
label,
|
|
||||||
value,
|
|
||||||
readonly,
|
|
||||||
onRemove,
|
|
||||||
}: DateDisplayProps) => {
|
|
||||||
const handleRemove = (e: MouseEvent<HTMLButtonElement>) => {
|
|
||||||
e.stopPropagation()
|
|
||||||
onRemove()
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Popover.Trigger
|
|
||||||
asChild
|
|
||||||
className={clx(
|
|
||||||
"bg-ui-bg-field transition-fg shadow-borders-base text-ui-fg-subtle flex cursor-pointer select-none items-center rounded-md",
|
|
||||||
{
|
|
||||||
"hover:bg-ui-bg-field-hover": !readonly,
|
|
||||||
"data-[state=open]:bg-ui-bg-field-hover": !readonly,
|
|
||||||
}
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
<div
|
|
||||||
className={clx("flex items-center justify-center px-2 py-1", {
|
|
||||||
"border-r": !!value,
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
<Text size="small" weight="plus" leading="compact">
|
|
||||||
{label}
|
|
||||||
</Text>
|
|
||||||
</div>
|
|
||||||
{value && (
|
|
||||||
<div className="flex items-center">
|
|
||||||
<div key={value} className="border-r p-1 px-2">
|
|
||||||
<Text size="small" weight="plus" leading="compact">
|
|
||||||
{value}
|
|
||||||
</Text>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{!readonly && value && (
|
|
||||||
<div>
|
|
||||||
<button
|
|
||||||
onClick={handleRemove}
|
|
||||||
className={clx(
|
|
||||||
"text-ui-fg-muted transition-fg flex items-center justify-center p-1",
|
|
||||||
"hover:bg-ui-bg-subtle-hover",
|
|
||||||
"active:bg-ui-bg-subtle-pressed active:text-ui-fg-base"
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<XMarkMini />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</Popover.Trigger>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const today = new Date()
|
const today = new Date()
|
||||||
today.setHours(0, 0, 0, 0)
|
today.setHours(0, 0, 0, 0)
|
||||||
|
|
||||||
|
|||||||
+97
@@ -0,0 +1,97 @@
|
|||||||
|
import { XMarkMini } from "@medusajs/icons"
|
||||||
|
import { Text, clx } from "@medusajs/ui"
|
||||||
|
import { useTranslation } from "react-i18next"
|
||||||
|
import { MouseEvent } from "react"
|
||||||
|
import * as Popover from "@radix-ui/react-popover"
|
||||||
|
|
||||||
|
export type FilterChipProps = {
|
||||||
|
hadPreviousValue?: boolean
|
||||||
|
label: string
|
||||||
|
value?: string
|
||||||
|
readonly?: boolean
|
||||||
|
hasOperator?: boolean
|
||||||
|
onRemove: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const FilterChip = ({
|
||||||
|
hadPreviousValue,
|
||||||
|
label,
|
||||||
|
value,
|
||||||
|
readonly,
|
||||||
|
hasOperator,
|
||||||
|
onRemove,
|
||||||
|
}: FilterChipProps) => {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
|
||||||
|
const handleRemove = (e: MouseEvent<HTMLButtonElement>) => {
|
||||||
|
e.stopPropagation()
|
||||||
|
onRemove()
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="bg-ui-bg-field transition-fg shadow-borders-base text-ui-fg-subtle flex cursor-default select-none items-stretch overflow-hidden rounded-md"
|
||||||
|
>
|
||||||
|
{!hadPreviousValue && (
|
||||||
|
<Popover.Anchor />
|
||||||
|
)}
|
||||||
|
<div
|
||||||
|
className={clx(
|
||||||
|
"flex items-center justify-center whitespace-nowrap px-2 py-1",
|
||||||
|
{
|
||||||
|
"border-r": !!(value || hadPreviousValue),
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<Text size="small" weight="plus" leading="compact">
|
||||||
|
{label}
|
||||||
|
</Text>
|
||||||
|
</div>
|
||||||
|
<div className="flex w-full items-center overflow-hidden">
|
||||||
|
{hasOperator && !!(value || hadPreviousValue) && (
|
||||||
|
<div className="border-r p-1 px-2">
|
||||||
|
<Text
|
||||||
|
size="small"
|
||||||
|
weight="plus"
|
||||||
|
leading="compact"
|
||||||
|
className="text-ui-fg-muted"
|
||||||
|
>
|
||||||
|
{t("general.is")}
|
||||||
|
</Text>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{!!(value || hadPreviousValue) && (
|
||||||
|
<Popover.Trigger asChild className={clx("flex-1 cursor-pointer overflow-hidden border-r p-1 px-2",
|
||||||
|
{
|
||||||
|
"hover:bg-ui-bg-field-hover": !readonly,
|
||||||
|
"data-[state=open]:bg-ui-bg-field-hover": !readonly,
|
||||||
|
}
|
||||||
|
)}>
|
||||||
|
<Text
|
||||||
|
size="small"
|
||||||
|
leading="compact"
|
||||||
|
weight="plus"
|
||||||
|
className="truncate text-nowrap"
|
||||||
|
>
|
||||||
|
{value || "\u00A0"}
|
||||||
|
</Text>
|
||||||
|
</Popover.Trigger>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
{!readonly && !!(value || hadPreviousValue) && (
|
||||||
|
<button
|
||||||
|
onClick={handleRemove}
|
||||||
|
className={clx(
|
||||||
|
"text-ui-fg-muted transition-fg flex items-center justify-center p-1",
|
||||||
|
"hover:bg-ui-bg-subtle-hover",
|
||||||
|
"active:bg-ui-bg-subtle-pressed active:text-ui-fg-base"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<XMarkMini />
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default FilterChip
|
||||||
+17
-81
@@ -1,11 +1,10 @@
|
|||||||
import { EllipseMiniSolid, XMarkMini } from "@medusajs/icons"
|
import { EllipseMiniSolid } from "@medusajs/icons"
|
||||||
import { Input, Label, Text, clx } from "@medusajs/ui"
|
import { Input, Label, clx } from "@medusajs/ui"
|
||||||
import * as Popover from "@radix-ui/react-popover"
|
import * as Popover from "@radix-ui/react-popover"
|
||||||
import * as RadioGroup from "@radix-ui/react-radio-group"
|
import * as RadioGroup from "@radix-ui/react-radio-group"
|
||||||
import { debounce } from "lodash"
|
import { debounce } from "lodash"
|
||||||
import {
|
import {
|
||||||
ChangeEvent,
|
ChangeEvent,
|
||||||
MouseEvent,
|
|
||||||
useCallback,
|
useCallback,
|
||||||
useEffect,
|
useEffect,
|
||||||
useState,
|
useState,
|
||||||
@@ -15,6 +14,8 @@ import { useTranslation } from "react-i18next"
|
|||||||
import { useSelectedParams } from "../hooks"
|
import { useSelectedParams } from "../hooks"
|
||||||
import { useDataTableFilterContext } from "./context"
|
import { useDataTableFilterContext } from "./context"
|
||||||
import { IFilter } from "./types"
|
import { IFilter } from "./types"
|
||||||
|
import { TFunction } from "i18next"
|
||||||
|
import FilterChip from "./filter-chip"
|
||||||
|
|
||||||
type NumberFilterProps = IFilter
|
type NumberFilterProps = IFilter
|
||||||
|
|
||||||
@@ -40,6 +41,9 @@ export const NumberFilter = ({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const currentValue = selectedParams.get()
|
const currentValue = selectedParams.get()
|
||||||
|
const [previousValue, setPreviousValue] = useState<string[] | undefined>(
|
||||||
|
currentValue
|
||||||
|
)
|
||||||
|
|
||||||
const [operator, setOperator] = useState<Comparison | undefined>(
|
const [operator, setOperator] = useState<Comparison | undefined>(
|
||||||
getOperator(currentValue)
|
getOperator(currentValue)
|
||||||
@@ -99,6 +103,7 @@ export const NumberFilter = ({
|
|||||||
|
|
||||||
const handleOpenChange = (open: boolean) => {
|
const handleOpenChange = (open: boolean) => {
|
||||||
setOpen(open)
|
setOpen(open)
|
||||||
|
setPreviousValue(currentValue)
|
||||||
|
|
||||||
if (timeoutId) {
|
if (timeoutId) {
|
||||||
clearTimeout(timeoutId)
|
clearTimeout(timeoutId)
|
||||||
@@ -131,11 +136,16 @@ export const NumberFilter = ({
|
|||||||
const LT_KEY = `${key}-lt`
|
const LT_KEY = `${key}-lt`
|
||||||
const EQ_KEY = key
|
const EQ_KEY = key
|
||||||
|
|
||||||
|
const displayValue = parseDisplayValue(currentValue, t)
|
||||||
|
const previousDisplayValue = parseDisplayValue(previousValue, t)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Popover.Root modal open={open} onOpenChange={handleOpenChange}>
|
<Popover.Root modal open={open} onOpenChange={handleOpenChange}>
|
||||||
<NumberDisplay
|
<FilterChip
|
||||||
|
hasOperator
|
||||||
|
hadPreviousValue={!!previousDisplayValue}
|
||||||
label={label}
|
label={label}
|
||||||
value={currentValue}
|
value={displayValue}
|
||||||
onRemove={handleRemove}
|
onRemove={handleRemove}
|
||||||
readonly={readonly}
|
readonly={readonly}
|
||||||
/>
|
/>
|
||||||
@@ -242,23 +252,7 @@ export const NumberFilter = ({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const NumberDisplay = ({
|
const parseDisplayValue = (value: string[] | null | undefined, t: TFunction) => {
|
||||||
label,
|
|
||||||
value,
|
|
||||||
readonly,
|
|
||||||
onRemove,
|
|
||||||
}: {
|
|
||||||
label: string
|
|
||||||
value?: string[]
|
|
||||||
readonly?: boolean
|
|
||||||
onRemove: () => void
|
|
||||||
}) => {
|
|
||||||
const { t } = useTranslation()
|
|
||||||
const handleRemove = (e: MouseEvent<HTMLButtonElement>) => {
|
|
||||||
e.stopPropagation()
|
|
||||||
onRemove()
|
|
||||||
}
|
|
||||||
|
|
||||||
const parsed = JSON.parse(value?.join(",") || "{}")
|
const parsed = JSON.parse(value?.join(",") || "{}")
|
||||||
let displayValue = ""
|
let displayValue = ""
|
||||||
|
|
||||||
@@ -283,65 +277,7 @@ const NumberDisplay = ({
|
|||||||
displayValue = parsed.toString()
|
displayValue = parsed.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return displayValue
|
||||||
<Popover.Trigger
|
|
||||||
asChild
|
|
||||||
className={clx(
|
|
||||||
"bg-ui-bg-field transition-fg shadow-borders-base text-ui-fg-subtle flex cursor-pointer select-none items-center rounded-md",
|
|
||||||
{
|
|
||||||
"hover:bg-ui-bg-field-hover": !readonly,
|
|
||||||
"data-[state=open]:bg-ui-bg-field-hover": !readonly,
|
|
||||||
}
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
<div
|
|
||||||
className={clx("flex items-center justify-center px-2 py-1", {
|
|
||||||
"border-r": !!value,
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
<Text size="small" weight="plus" leading="compact">
|
|
||||||
{label}
|
|
||||||
</Text>
|
|
||||||
</div>
|
|
||||||
{!!value && (
|
|
||||||
<div className="border-r p-1 px-2">
|
|
||||||
<Text
|
|
||||||
size="small"
|
|
||||||
weight="plus"
|
|
||||||
leading="compact"
|
|
||||||
className="text-ui-fg-muted"
|
|
||||||
>
|
|
||||||
{t("general.is")}
|
|
||||||
</Text>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{value && (
|
|
||||||
<div className="flex items-center">
|
|
||||||
<div className="border-r p-1 px-2">
|
|
||||||
<Text size="small" weight="plus" leading="compact">
|
|
||||||
{displayValue}
|
|
||||||
</Text>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{!readonly && value && (
|
|
||||||
<div>
|
|
||||||
<button
|
|
||||||
onClick={handleRemove}
|
|
||||||
className={clx(
|
|
||||||
"text-ui-fg-muted transition-fg flex items-center justify-center p-1",
|
|
||||||
"hover:bg-ui-bg-subtle-hover",
|
|
||||||
"active:bg-ui-bg-subtle-pressed active:text-ui-fg-base"
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<XMarkMini />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</Popover.Trigger>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const parseValue = (value: string[] | null | undefined) => {
|
const parseValue = (value: string[] | null | undefined) => {
|
||||||
|
|||||||
+14
-94
@@ -1,13 +1,14 @@
|
|||||||
import { CheckMini, EllipseMiniSolid, XMarkMini } from "@medusajs/icons"
|
import { CheckMini, EllipseMiniSolid, XMarkMini } from "@medusajs/icons"
|
||||||
import { Text, clx } from "@medusajs/ui"
|
import { clx } from "@medusajs/ui"
|
||||||
import * as Popover from "@radix-ui/react-popover"
|
import * as Popover from "@radix-ui/react-popover"
|
||||||
import { Command } from "cmdk"
|
import { Command } from "cmdk"
|
||||||
import { MouseEvent, useState } from "react"
|
import { useState } from "react"
|
||||||
import { useTranslation } from "react-i18next"
|
import { useTranslation } from "react-i18next"
|
||||||
|
|
||||||
import { useSelectedParams } from "../hooks"
|
import { useSelectedParams } from "../hooks"
|
||||||
import { useDataTableFilterContext } from "./context"
|
import { useDataTableFilterContext } from "./context"
|
||||||
import { IFilter } from "./types"
|
import { IFilter } from "./types"
|
||||||
|
import FilterChip from "./filter-chip"
|
||||||
|
|
||||||
interface SelectFilterProps extends IFilter {
|
interface SelectFilterProps extends IFilter {
|
||||||
options: { label: string; value: unknown }[]
|
options: { label: string; value: unknown }[]
|
||||||
@@ -40,6 +41,8 @@ export const SelectFilter = ({
|
|||||||
.map((v) => options.find((o) => o.value === v)?.label)
|
.map((v) => options.find((o) => o.value === v)?.label)
|
||||||
.filter(Boolean) as string[]
|
.filter(Boolean) as string[]
|
||||||
|
|
||||||
|
const [previousValue, setPreviousValue] = useState<string | string[] | undefined>(labelValues)
|
||||||
|
|
||||||
const handleRemove = () => {
|
const handleRemove = () => {
|
||||||
selectedParams.delete()
|
selectedParams.delete()
|
||||||
removeFilter(key)
|
removeFilter(key)
|
||||||
@@ -50,6 +53,8 @@ export const SelectFilter = ({
|
|||||||
const handleOpenChange = (open: boolean) => {
|
const handleOpenChange = (open: boolean) => {
|
||||||
setOpen(open)
|
setOpen(open)
|
||||||
|
|
||||||
|
setPreviousValue(labelValues)
|
||||||
|
|
||||||
if (timeoutId) {
|
if (timeoutId) {
|
||||||
clearTimeout(timeoutId)
|
clearTimeout(timeoutId)
|
||||||
}
|
}
|
||||||
@@ -79,12 +84,17 @@ export const SelectFilter = ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const normalizedValues = labelValues ? (Array.isArray(labelValues) ? labelValues : [labelValues]) : null
|
||||||
|
const normalizedPrev = previousValue ? (Array.isArray(previousValue) ? previousValue : [previousValue]) : null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Popover.Root modal open={open} onOpenChange={handleOpenChange}>
|
<Popover.Root modal open={open} onOpenChange={handleOpenChange}>
|
||||||
<SelectDisplay
|
<FilterChip
|
||||||
|
hasOperator
|
||||||
|
hadPreviousValue={!!normalizedPrev?.length}
|
||||||
readonly={readonly}
|
readonly={readonly}
|
||||||
label={label}
|
label={label}
|
||||||
value={labelValues}
|
value={normalizedValues?.join(", ")}
|
||||||
onRemove={handleRemove}
|
onRemove={handleRemove}
|
||||||
/>
|
/>
|
||||||
{!readonly && (
|
{!readonly && (
|
||||||
@@ -179,93 +189,3 @@ export const SelectFilter = ({
|
|||||||
</Popover.Root>
|
</Popover.Root>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
type SelectDisplayProps = {
|
|
||||||
label: string
|
|
||||||
readonly?: boolean
|
|
||||||
value?: string | string[]
|
|
||||||
onRemove: () => void
|
|
||||||
}
|
|
||||||
|
|
||||||
export const SelectDisplay = ({
|
|
||||||
label,
|
|
||||||
value,
|
|
||||||
onRemove,
|
|
||||||
readonly,
|
|
||||||
}: SelectDisplayProps) => {
|
|
||||||
const { t } = useTranslation()
|
|
||||||
const v = value ? (Array.isArray(value) ? value : [value]) : null
|
|
||||||
const count = v?.length || 0
|
|
||||||
|
|
||||||
const handleRemove = (e: MouseEvent<HTMLButtonElement>) => {
|
|
||||||
e.stopPropagation()
|
|
||||||
onRemove()
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Popover.Trigger asChild>
|
|
||||||
<div
|
|
||||||
className={clx(
|
|
||||||
"bg-ui-bg-field transition-fg shadow-borders-base text-ui-fg-subtle flex cursor-pointer select-none items-center overflow-hidden rounded-md",
|
|
||||||
{
|
|
||||||
"hover:bg-ui-bg-field-hover": !readonly,
|
|
||||||
"data-[state=open]:bg-ui-bg-field-hover": !readonly,
|
|
||||||
}
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className={clx(
|
|
||||||
"flex items-center justify-center whitespace-nowrap px-2 py-1",
|
|
||||||
{
|
|
||||||
"border-r": count > 0,
|
|
||||||
}
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<Text size="small" weight="plus" leading="compact">
|
|
||||||
{label}
|
|
||||||
</Text>
|
|
||||||
</div>
|
|
||||||
<div className="flex w-full items-center overflow-hidden">
|
|
||||||
{count > 0 && (
|
|
||||||
<div className="border-r p-1 px-2">
|
|
||||||
<Text
|
|
||||||
size="small"
|
|
||||||
weight="plus"
|
|
||||||
leading="compact"
|
|
||||||
className="text-ui-fg-muted"
|
|
||||||
>
|
|
||||||
{t("general.is")}
|
|
||||||
</Text>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{count > 0 && (
|
|
||||||
<div className="flex-1 overflow-hidden border-r p-1 px-2">
|
|
||||||
<Text
|
|
||||||
size="small"
|
|
||||||
leading="compact"
|
|
||||||
weight="plus"
|
|
||||||
className="truncate text-nowrap"
|
|
||||||
>
|
|
||||||
{v?.join(", ")}
|
|
||||||
</Text>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
{!readonly && v && v.length > 0 && (
|
|
||||||
<div>
|
|
||||||
<button
|
|
||||||
onClick={handleRemove}
|
|
||||||
className={clx(
|
|
||||||
"text-ui-fg-muted transition-fg flex items-center justify-center p-1",
|
|
||||||
"hover:bg-ui-bg-subtle-hover",
|
|
||||||
"active:bg-ui-bg-subtle-pressed active:text-ui-fg-base"
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<XMarkMini />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</Popover.Trigger>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
+8
-85
@@ -1,12 +1,11 @@
|
|||||||
import { XMarkMini } from "@medusajs/icons"
|
import { Input, Label, clx } from "@medusajs/ui"
|
||||||
import { Input, Label, Text, clx } from "@medusajs/ui"
|
|
||||||
import * as Popover from "@radix-ui/react-popover"
|
import * as Popover from "@radix-ui/react-popover"
|
||||||
import { debounce } from "lodash"
|
import { debounce } from "lodash"
|
||||||
import { ChangeEvent, useCallback, useEffect, useState } from "react"
|
import { ChangeEvent, useCallback, useEffect, useState } from "react"
|
||||||
import { useTranslation } from "react-i18next"
|
|
||||||
import { useSelectedParams } from "../hooks"
|
import { useSelectedParams } from "../hooks"
|
||||||
import { useDataTableFilterContext } from "./context"
|
import { useDataTableFilterContext } from "./context"
|
||||||
import { IFilter } from "./types"
|
import { IFilter } from "./types"
|
||||||
|
import FilterChip from "./filter-chip"
|
||||||
|
|
||||||
type StringFilterProps = IFilter
|
type StringFilterProps = IFilter
|
||||||
|
|
||||||
@@ -25,6 +24,8 @@ export const StringFilter = ({
|
|||||||
|
|
||||||
const query = selectedParams.get()
|
const query = selectedParams.get()
|
||||||
|
|
||||||
|
const [previousValue, setPreviousValue] = useState<string | undefined>(query?.[0])
|
||||||
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
const debouncedOnChange = useCallback(
|
const debouncedOnChange = useCallback(
|
||||||
debounce((e: ChangeEvent<HTMLInputElement>) => {
|
debounce((e: ChangeEvent<HTMLInputElement>) => {
|
||||||
@@ -49,6 +50,7 @@ export const StringFilter = ({
|
|||||||
|
|
||||||
const handleOpenChange = (open: boolean) => {
|
const handleOpenChange = (open: boolean) => {
|
||||||
setOpen(open)
|
setOpen(open)
|
||||||
|
setPreviousValue(query?.[0])
|
||||||
|
|
||||||
if (timeoutId) {
|
if (timeoutId) {
|
||||||
clearTimeout(timeoutId)
|
clearTimeout(timeoutId)
|
||||||
@@ -68,7 +70,9 @@ export const StringFilter = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Popover.Root modal open={open} onOpenChange={handleOpenChange}>
|
<Popover.Root modal open={open} onOpenChange={handleOpenChange}>
|
||||||
<StringDisplay
|
<FilterChip
|
||||||
|
hasOperator
|
||||||
|
hadPreviousValue={!!previousValue}
|
||||||
label={label}
|
label={label}
|
||||||
value={query?.[0]}
|
value={query?.[0]}
|
||||||
onRemove={handleRemove}
|
onRemove={handleRemove}
|
||||||
@@ -117,84 +121,3 @@ export const StringFilter = ({
|
|||||||
</Popover.Root>
|
</Popover.Root>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const StringDisplay = ({
|
|
||||||
label,
|
|
||||||
value,
|
|
||||||
readonly,
|
|
||||||
onRemove,
|
|
||||||
}: {
|
|
||||||
label: string
|
|
||||||
value?: string
|
|
||||||
readonly?: boolean
|
|
||||||
onRemove: () => void
|
|
||||||
}) => {
|
|
||||||
const { t } = useTranslation()
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Popover.Trigger asChild>
|
|
||||||
<div
|
|
||||||
className={clx(
|
|
||||||
"bg-ui-bg-field transition-fg shadow-borders-base text-ui-fg-subtle flex cursor-pointer select-none items-center overflow-hidden rounded-md",
|
|
||||||
{
|
|
||||||
"hover:bg-ui-bg-field-hover": !readonly,
|
|
||||||
"data-[state=open]:bg-ui-bg-field-hover": !readonly,
|
|
||||||
}
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className={clx(
|
|
||||||
"flex items-center justify-center whitespace-nowrap px-2 py-1",
|
|
||||||
{
|
|
||||||
"border-r": !!value,
|
|
||||||
}
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<Text size="small" weight="plus" leading="compact">
|
|
||||||
{label}
|
|
||||||
</Text>
|
|
||||||
</div>
|
|
||||||
<div className="flex w-full items-center overflow-hidden">
|
|
||||||
{!!value && (
|
|
||||||
<div className="border-r p-1 px-2">
|
|
||||||
<Text
|
|
||||||
size="small"
|
|
||||||
weight="plus"
|
|
||||||
leading="compact"
|
|
||||||
className="text-ui-fg-muted"
|
|
||||||
>
|
|
||||||
{t("general.is")}
|
|
||||||
</Text>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{!!value && (
|
|
||||||
<div className="flex-1 overflow-hidden border-r p-1 px-2">
|
|
||||||
<Text
|
|
||||||
size="small"
|
|
||||||
leading="compact"
|
|
||||||
weight="plus"
|
|
||||||
className="truncate text-nowrap"
|
|
||||||
>
|
|
||||||
{value}
|
|
||||||
</Text>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
{!readonly && !!value && (
|
|
||||||
<div>
|
|
||||||
<button
|
|
||||||
onClick={onRemove}
|
|
||||||
className={clx(
|
|
||||||
"text-ui-fg-muted transition-fg flex items-center justify-center p-1",
|
|
||||||
"hover:bg-ui-bg-subtle-hover",
|
|
||||||
"active:bg-ui-bg-subtle-pressed active:text-ui-fg-base"
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<XMarkMini />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</Popover.Trigger>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
+1
-1
@@ -9,7 +9,7 @@ export const LocationServiceZoneManageAreas = () => {
|
|||||||
|
|
||||||
const { stock_location, isPending, isFetching, isError, error } =
|
const { stock_location, isPending, isFetching, isError, error } =
|
||||||
useStockLocation(location_id!, {
|
useStockLocation(location_id!, {
|
||||||
fields: "*fulfillment_sets.service_zones.geo_zones",
|
fields: "*fulfillment_sets.service_zones.geo_zones,fulfillment_sets.service_zones.name",
|
||||||
})
|
})
|
||||||
|
|
||||||
const zone = stock_location?.fulfillment_sets
|
const zone = stock_location?.fulfillment_sets
|
||||||
|
|||||||
Reference in new issue
Block a user