@ashwa-io/ui 0.0.5 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/molecule/FacetFilter/FacetFilter.d.ts +14 -0
- package/dist/components/molecule/FacetFilter/FacetFilter.js +30 -0
- package/dist/components/molecule/FacetFilter/FacetList.d.ts +10 -0
- package/dist/components/molecule/FacetFilter/FacetList.js +103 -0
- package/dist/components/molecule/FacetFilter/FacetTrigger.d.ts +2 -0
- package/dist/components/molecule/FacetFilter/FacetTrigger.js +35 -0
- package/dist/components/molecule/FacetFilter/index.d.ts +3 -0
- package/dist/components/molecule/FacetFilterNumber/FacetFilterNumber.d.ts +29 -0
- package/dist/components/molecule/FacetFilterNumber/FacetFilterNumber.js +93 -0
- package/dist/components/molecule/FacetFilterNumber/index.d.ts +2 -0
- package/dist/components/molecule/FacetFilterSelect/FacetFilterSelect.d.ts +15 -0
- package/dist/components/molecule/FacetFilterSelect/FacetFilterSelect.js +41 -0
- package/dist/components/molecule/FacetFilterSelect/index.d.ts +2 -0
- package/dist/components/molecule/FilterMenu/FilterMenu.d.ts +23 -0
- package/dist/components/molecule/FilterMenu/FilterMenu.js +131 -0
- package/dist/components/molecule/FilterMenu/index.d.ts +2 -0
- package/dist/components/ui/combobox.js +78 -0
- package/dist/components/ui/input-group.js +63 -0
- package/dist/index.d.ts +10 -1
- package/dist/index.js +5 -1
- package/package.json +1 -1
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { FacetOption } from "./FacetList.js";
|
|
2
|
+
import { FacetSize } from "./FacetTrigger.js";
|
|
3
|
+
import React from "react";
|
|
4
|
+
export interface FacetFilterProps {
|
|
5
|
+
title: string;
|
|
6
|
+
options: FacetOption[];
|
|
7
|
+
/** Selected option values. */
|
|
8
|
+
value: string[];
|
|
9
|
+
onChange: (value: string[]) => void;
|
|
10
|
+
size?: FacetSize;
|
|
11
|
+
disabled?: boolean;
|
|
12
|
+
'data-testid'?: string;
|
|
13
|
+
}
|
|
14
|
+
export declare const FacetFilter: React.FC<FacetFilterProps>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Popover, PopoverContent } from "../../ui/popover.js";
|
|
2
|
+
import { FacetList } from "./FacetList.js";
|
|
3
|
+
import { FacetTrigger } from "./FacetTrigger.js";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
// src/components/molecule/FacetFilter/FacetFilter.tsx
|
|
6
|
+
const FacetFilter = (props) => {
|
|
7
|
+
const { title, options, value, onChange, size, disabled, "data-testid": testId } = props;
|
|
8
|
+
const selected = options.filter((option) => value.includes(option.value)).length;
|
|
9
|
+
const active = selected > 0 && selected < options.length;
|
|
10
|
+
return /* @__PURE__ */ jsxs(Popover, { children: [/* @__PURE__ */ jsx(FacetTrigger, {
|
|
11
|
+
title,
|
|
12
|
+
summary: active ? String(selected) : "All",
|
|
13
|
+
active,
|
|
14
|
+
size,
|
|
15
|
+
disabled,
|
|
16
|
+
"data-testid": testId
|
|
17
|
+
}), /* @__PURE__ */ jsx(PopoverContent, {
|
|
18
|
+
align: "start",
|
|
19
|
+
"aria-label": title,
|
|
20
|
+
className: "w-60 gap-0 p-0",
|
|
21
|
+
children: /* @__PURE__ */ jsx(FacetList, {
|
|
22
|
+
label: title,
|
|
23
|
+
options,
|
|
24
|
+
value,
|
|
25
|
+
onChange,
|
|
26
|
+
showSelectAll: true
|
|
27
|
+
})
|
|
28
|
+
})] });
|
|
29
|
+
};
|
|
30
|
+
export { FacetFilter };
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { Button } from "../../atomic/Button/Button.js";
|
|
2
|
+
import { Combobox, ComboboxEmpty, ComboboxInput, ComboboxItem, ComboboxList } from "../../ui/combobox.js";
|
|
3
|
+
import { cn } from "../../../lib/utils.js";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
import { CheckIcon } from "lucide-react";
|
|
6
|
+
import { useState } from "react";
|
|
7
|
+
// src/components/molecule/FacetFilter/FacetList.tsx
|
|
8
|
+
const CheckBox = (props) => /* @__PURE__ */ jsx("span", {
|
|
9
|
+
"aria-hidden": true,
|
|
10
|
+
className: cn("border-input flex size-4 shrink-0 items-center justify-center rounded-[4px] border", props.checked && "border-primary bg-primary"),
|
|
11
|
+
children: props.checked && /* @__PURE__ */ jsx(CheckIcon, { className: "text-primary-foreground! size-3.5" })
|
|
12
|
+
});
|
|
13
|
+
/** Internal: search box + arrow-key list, shared by the facet filters and FilterMenu. */
|
|
14
|
+
const FacetList = (props) => {
|
|
15
|
+
const { label, options, value, onChange, multiple = true, showSelectAll = false, clearable = true } = props;
|
|
16
|
+
const [query, setQuery] = useState("");
|
|
17
|
+
const byValue = new Map(options.map((option) => [option.value, option]));
|
|
18
|
+
const enabled = options.filter((option) => !option.disabled).map((option) => option.value);
|
|
19
|
+
const allSelected = enabled.length > 0 && enabled.every((item) => value.includes(item));
|
|
20
|
+
const locked = value.filter((item) => byValue.get(item)?.disabled);
|
|
21
|
+
const handleChange = (next) => {
|
|
22
|
+
if (multiple) {
|
|
23
|
+
onChange(next);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
onChange(next.filter((item) => !value.includes(item)).slice(-1));
|
|
27
|
+
};
|
|
28
|
+
return /* @__PURE__ */ jsxs(Combobox, {
|
|
29
|
+
inline: true,
|
|
30
|
+
open: true,
|
|
31
|
+
multiple: true,
|
|
32
|
+
items: options.map((option) => option.value),
|
|
33
|
+
itemToStringLabel: (item) => byValue.get(item)?.label ?? item,
|
|
34
|
+
value,
|
|
35
|
+
onValueChange: handleChange,
|
|
36
|
+
inputValue: query,
|
|
37
|
+
onInputValueChange: (next, details) => {
|
|
38
|
+
if (!details.isItemPress) setQuery(next);
|
|
39
|
+
},
|
|
40
|
+
children: [
|
|
41
|
+
/* @__PURE__ */ jsx("div", {
|
|
42
|
+
className: "border-b p-1",
|
|
43
|
+
children: /* @__PURE__ */ jsx(ComboboxInput, {
|
|
44
|
+
showTrigger: false,
|
|
45
|
+
placeholder: "Search",
|
|
46
|
+
"aria-label": label
|
|
47
|
+
})
|
|
48
|
+
}),
|
|
49
|
+
showSelectAll && query === "" && /* @__PURE__ */ jsx("div", {
|
|
50
|
+
className: "px-1 pt-1",
|
|
51
|
+
children: /* @__PURE__ */ jsxs("button", {
|
|
52
|
+
type: "button",
|
|
53
|
+
"aria-pressed": allSelected,
|
|
54
|
+
onClick: () => onChange(allSelected ? locked : [...locked, ...enabled]),
|
|
55
|
+
className: "hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground flex w-full cursor-default items-center gap-2 rounded-md py-1 pl-1.5 text-sm font-medium outline-none",
|
|
56
|
+
children: [/* @__PURE__ */ jsx(CheckBox, { checked: allSelected }), "Select all"]
|
|
57
|
+
})
|
|
58
|
+
}),
|
|
59
|
+
/* @__PURE__ */ jsx(ComboboxEmpty, {
|
|
60
|
+
className: "flex empty:hidden",
|
|
61
|
+
children: "No results"
|
|
62
|
+
}),
|
|
63
|
+
/* @__PURE__ */ jsx(ComboboxList, {
|
|
64
|
+
className: "max-h-60",
|
|
65
|
+
"aria-multiselectable": multiple,
|
|
66
|
+
children: (item) => {
|
|
67
|
+
const option = byValue.get(item);
|
|
68
|
+
if (!option) return null;
|
|
69
|
+
const Icon = option.icon;
|
|
70
|
+
const selected = value.includes(item);
|
|
71
|
+
return /* @__PURE__ */ jsxs(ComboboxItem, {
|
|
72
|
+
value: item,
|
|
73
|
+
disabled: option.disabled,
|
|
74
|
+
className: cn(selected && "bg-brand-tint text-brand-tint-foreground", multiple && "pr-1.5 [&>.absolute]:hidden"),
|
|
75
|
+
children: [
|
|
76
|
+
multiple && /* @__PURE__ */ jsx(CheckBox, { checked: selected }),
|
|
77
|
+
Icon && /* @__PURE__ */ jsx(Icon, { "aria-hidden": true }),
|
|
78
|
+
/* @__PURE__ */ jsx("span", {
|
|
79
|
+
className: "min-w-0 flex-1 truncate",
|
|
80
|
+
children: option.label
|
|
81
|
+
}),
|
|
82
|
+
option.count !== void 0 && /* @__PURE__ */ jsx("span", {
|
|
83
|
+
className: cn("text-xs tabular-nums", !selected && "text-muted-foreground"),
|
|
84
|
+
children: option.count
|
|
85
|
+
})
|
|
86
|
+
]
|
|
87
|
+
}, item);
|
|
88
|
+
}
|
|
89
|
+
}),
|
|
90
|
+
clearable && value.length > 0 && /* @__PURE__ */ jsx("div", {
|
|
91
|
+
className: "border-t p-1",
|
|
92
|
+
children: /* @__PURE__ */ jsx(Button, {
|
|
93
|
+
variant: "ghost",
|
|
94
|
+
size: "sm",
|
|
95
|
+
fullWidth: true,
|
|
96
|
+
onClick: () => onChange([]),
|
|
97
|
+
children: "Clear filters"
|
|
98
|
+
})
|
|
99
|
+
})
|
|
100
|
+
]
|
|
101
|
+
});
|
|
102
|
+
};
|
|
103
|
+
export { FacetList };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Button } from "../../ui/button.js";
|
|
2
|
+
import { PopoverTrigger } from "../../ui/popover.js";
|
|
3
|
+
import { cn } from "../../../lib/utils.js";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
import { ChevronDownIcon } from "lucide-react";
|
|
6
|
+
// src/components/molecule/FacetFilter/FacetTrigger.tsx
|
|
7
|
+
/** Internal: the dashed filter button; must be rendered inside a popover root. */
|
|
8
|
+
const FacetTrigger = (props) => {
|
|
9
|
+
const { title, summary, active, size = "sm", disabled = false, "data-testid": testId } = props;
|
|
10
|
+
return /* @__PURE__ */ jsxs(PopoverTrigger, {
|
|
11
|
+
disabled,
|
|
12
|
+
"data-testid": testId,
|
|
13
|
+
render: /* @__PURE__ */ jsx(Button, {
|
|
14
|
+
variant: "outline",
|
|
15
|
+
size: size === "sm" ? "sm" : "default",
|
|
16
|
+
className: cn("font-normal", !active && "border-dashed")
|
|
17
|
+
}),
|
|
18
|
+
children: [
|
|
19
|
+
/* @__PURE__ */ jsx("span", { children: title }),
|
|
20
|
+
/* @__PURE__ */ jsx("span", {
|
|
21
|
+
"aria-hidden": true,
|
|
22
|
+
className: "bg-border h-4 w-px"
|
|
23
|
+
}),
|
|
24
|
+
/* @__PURE__ */ jsx("span", {
|
|
25
|
+
className: cn("max-w-40 truncate font-medium", active && "bg-brand-tint text-brand-tint-foreground rounded-sm px-1"),
|
|
26
|
+
children: summary
|
|
27
|
+
}),
|
|
28
|
+
/* @__PURE__ */ jsx(ChevronDownIcon, {
|
|
29
|
+
"data-icon": "inline-end",
|
|
30
|
+
"aria-hidden": true
|
|
31
|
+
})
|
|
32
|
+
]
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
export { FacetTrigger };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { FacetSize } from "../FacetFilter/FacetTrigger.js";
|
|
2
|
+
import React from "react";
|
|
3
|
+
export interface NumberCondition {
|
|
4
|
+
/** e.g. 'gt', 'between'. */
|
|
5
|
+
value: string;
|
|
6
|
+
/** e.g. 'Greater than'. */
|
|
7
|
+
label: string;
|
|
8
|
+
/** Takes two values: from and to. */
|
|
9
|
+
range?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export interface NumberFilterValue {
|
|
12
|
+
condition: string;
|
|
13
|
+
/** As typed; '' when empty. */
|
|
14
|
+
from: string;
|
|
15
|
+
/** Only used by range conditions. */
|
|
16
|
+
to: string;
|
|
17
|
+
}
|
|
18
|
+
export interface FacetFilterNumberProps {
|
|
19
|
+
title: string;
|
|
20
|
+
conditions: NumberCondition[];
|
|
21
|
+
value: NumberFilterValue | null;
|
|
22
|
+
onChange: (value: NumberFilterValue | null) => void;
|
|
23
|
+
/** Formats values in the trigger, e.g. value => `${value} km/h`. */
|
|
24
|
+
format?: (value: string) => string;
|
|
25
|
+
size?: FacetSize;
|
|
26
|
+
disabled?: boolean;
|
|
27
|
+
'data-testid'?: string;
|
|
28
|
+
}
|
|
29
|
+
export declare const FacetFilterNumber: React.FC<FacetFilterNumberProps>;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { Button } from "../../atomic/Button/Button.js";
|
|
2
|
+
import { Select } from "../../atomic/Select/Select.js";
|
|
3
|
+
import { FacetTrigger } from "../FacetFilter/FacetTrigger.js";
|
|
4
|
+
import { FormField } from "../FormField/FormField.js";
|
|
5
|
+
import { Input } from "../../ui/input.js";
|
|
6
|
+
import { Popover, PopoverContent } from "../../ui/popover.js";
|
|
7
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
// src/components/molecule/FacetFilterNumber/FacetFilterNumber.tsx
|
|
9
|
+
const NumberField = (props) => /* @__PURE__ */ jsx(FormField, {
|
|
10
|
+
label: props.label,
|
|
11
|
+
children: (control) => /* @__PURE__ */ jsx(Input, {
|
|
12
|
+
id: control.id,
|
|
13
|
+
type: "number",
|
|
14
|
+
value: props.value,
|
|
15
|
+
onChange: (event) => props.onChange(event.target.value)
|
|
16
|
+
})
|
|
17
|
+
});
|
|
18
|
+
const summarize = (value, condition, format) => {
|
|
19
|
+
if (value.from === "") return condition.label;
|
|
20
|
+
const from = `${condition.label} ${format(value.from)}`;
|
|
21
|
+
return condition.range && value.to !== "" ? `${from} and ${format(value.to)}` : from;
|
|
22
|
+
};
|
|
23
|
+
const FacetFilterNumber = (props) => {
|
|
24
|
+
const { title, conditions, value, onChange, format = (text) => text, size, disabled, "data-testid": testId } = props;
|
|
25
|
+
const condition = conditions.find((item) => item.value === value?.condition);
|
|
26
|
+
const from = value?.from ?? "";
|
|
27
|
+
const to = value?.to ?? "";
|
|
28
|
+
return /* @__PURE__ */ jsxs(Popover, { children: [/* @__PURE__ */ jsx(FacetTrigger, {
|
|
29
|
+
title,
|
|
30
|
+
summary: value && condition ? summarize(value, condition, format) : "All",
|
|
31
|
+
active: condition !== void 0,
|
|
32
|
+
size,
|
|
33
|
+
disabled,
|
|
34
|
+
"data-testid": testId
|
|
35
|
+
}), /* @__PURE__ */ jsxs(PopoverContent, {
|
|
36
|
+
align: "start",
|
|
37
|
+
"aria-label": title,
|
|
38
|
+
className: "w-64",
|
|
39
|
+
children: [
|
|
40
|
+
/* @__PURE__ */ jsx(Select, {
|
|
41
|
+
label: "Condition",
|
|
42
|
+
options: conditions.map((item) => ({
|
|
43
|
+
value: item.value,
|
|
44
|
+
label: item.label
|
|
45
|
+
})),
|
|
46
|
+
value: condition?.value ?? null,
|
|
47
|
+
onChange: (next) => onChange({
|
|
48
|
+
condition: next,
|
|
49
|
+
from,
|
|
50
|
+
to: ""
|
|
51
|
+
}),
|
|
52
|
+
placeholder: "Select condition"
|
|
53
|
+
}),
|
|
54
|
+
value && condition && !condition.range && /* @__PURE__ */ jsx(NumberField, {
|
|
55
|
+
label: "Value",
|
|
56
|
+
value: from,
|
|
57
|
+
onChange: (next) => onChange({
|
|
58
|
+
condition: value.condition,
|
|
59
|
+
from: next,
|
|
60
|
+
to: ""
|
|
61
|
+
})
|
|
62
|
+
}),
|
|
63
|
+
value && condition?.range && /* @__PURE__ */ jsxs("div", {
|
|
64
|
+
className: "grid grid-cols-2 gap-2",
|
|
65
|
+
children: [/* @__PURE__ */ jsx(NumberField, {
|
|
66
|
+
label: "From",
|
|
67
|
+
value: from,
|
|
68
|
+
onChange: (next) => onChange({
|
|
69
|
+
condition: value.condition,
|
|
70
|
+
from: next,
|
|
71
|
+
to
|
|
72
|
+
})
|
|
73
|
+
}), /* @__PURE__ */ jsx(NumberField, {
|
|
74
|
+
label: "To",
|
|
75
|
+
value: to,
|
|
76
|
+
onChange: (next) => onChange({
|
|
77
|
+
condition: value.condition,
|
|
78
|
+
from,
|
|
79
|
+
to: next
|
|
80
|
+
})
|
|
81
|
+
})]
|
|
82
|
+
}),
|
|
83
|
+
value && /* @__PURE__ */ jsx(Button, {
|
|
84
|
+
variant: "ghost",
|
|
85
|
+
size: "sm",
|
|
86
|
+
fullWidth: true,
|
|
87
|
+
onClick: () => onChange(null),
|
|
88
|
+
children: "Clear filter"
|
|
89
|
+
})
|
|
90
|
+
]
|
|
91
|
+
})] });
|
|
92
|
+
};
|
|
93
|
+
export { FacetFilterNumber };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { FacetOption } from "../FacetFilter/FacetList.js";
|
|
2
|
+
import { FacetSize } from "../FacetFilter/FacetTrigger.js";
|
|
3
|
+
import React from "react";
|
|
4
|
+
export interface FacetFilterSelectProps {
|
|
5
|
+
title: string;
|
|
6
|
+
options: FacetOption[];
|
|
7
|
+
value: string | null;
|
|
8
|
+
onChange: (value: string | null) => void;
|
|
9
|
+
/** Always holds a value: no clear option, and onChange never gets null. */
|
|
10
|
+
required?: boolean;
|
|
11
|
+
size?: FacetSize;
|
|
12
|
+
disabled?: boolean;
|
|
13
|
+
'data-testid'?: string;
|
|
14
|
+
}
|
|
15
|
+
export declare const FacetFilterSelect: React.FC<FacetFilterSelectProps>;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { FacetList } from "../FacetFilter/FacetList.js";
|
|
2
|
+
import { FacetTrigger } from "../FacetFilter/FacetTrigger.js";
|
|
3
|
+
import { Popover, PopoverContent } from "../../ui/popover.js";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
import { useState } from "react";
|
|
6
|
+
// src/components/molecule/FacetFilterSelect/FacetFilterSelect.tsx
|
|
7
|
+
const FacetFilterSelect = (props) => {
|
|
8
|
+
const { title, options, value, onChange, required = false, size, disabled, "data-testid": testId } = props;
|
|
9
|
+
const [open, setOpen] = useState(false);
|
|
10
|
+
const selected = options.find((option) => option.value === value);
|
|
11
|
+
const handleChange = (next) => {
|
|
12
|
+
setOpen(false);
|
|
13
|
+
if (next.length > 0) onChange(next[0]);
|
|
14
|
+
else if (!required) onChange(null);
|
|
15
|
+
};
|
|
16
|
+
return /* @__PURE__ */ jsxs(Popover, {
|
|
17
|
+
open,
|
|
18
|
+
onOpenChange: setOpen,
|
|
19
|
+
children: [/* @__PURE__ */ jsx(FacetTrigger, {
|
|
20
|
+
title,
|
|
21
|
+
summary: selected?.label ?? "All",
|
|
22
|
+
active: selected !== void 0,
|
|
23
|
+
size,
|
|
24
|
+
disabled,
|
|
25
|
+
"data-testid": testId
|
|
26
|
+
}), /* @__PURE__ */ jsx(PopoverContent, {
|
|
27
|
+
align: "start",
|
|
28
|
+
"aria-label": title,
|
|
29
|
+
className: "w-60 gap-0 p-0",
|
|
30
|
+
children: /* @__PURE__ */ jsx(FacetList, {
|
|
31
|
+
label: title,
|
|
32
|
+
options,
|
|
33
|
+
value: value === null ? [] : [value],
|
|
34
|
+
onChange: handleChange,
|
|
35
|
+
multiple: false,
|
|
36
|
+
clearable: !required
|
|
37
|
+
})
|
|
38
|
+
})]
|
|
39
|
+
});
|
|
40
|
+
};
|
|
41
|
+
export { FacetFilterSelect };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { FacetOption } from "../FacetFilter/FacetList.js";
|
|
2
|
+
import { Size } from "../../../lib/types.js";
|
|
3
|
+
import React from "react";
|
|
4
|
+
export interface FilterCategory {
|
|
5
|
+
id: string;
|
|
6
|
+
label: string;
|
|
7
|
+
options: FacetOption[];
|
|
8
|
+
/** false: one choice in this category. */
|
|
9
|
+
multiple?: boolean;
|
|
10
|
+
}
|
|
11
|
+
/** Selected option values by category id. */
|
|
12
|
+
export type FilterMenuValue = Record<string, string[]>;
|
|
13
|
+
export interface FilterMenuProps {
|
|
14
|
+
categories: FilterCategory[];
|
|
15
|
+
value: FilterMenuValue;
|
|
16
|
+
/** Always the whole object; keys that aren't categories are kept. */
|
|
17
|
+
onChange: (value: FilterMenuValue) => void;
|
|
18
|
+
label?: string;
|
|
19
|
+
size?: Size;
|
|
20
|
+
disabled?: boolean;
|
|
21
|
+
'data-testid'?: string;
|
|
22
|
+
}
|
|
23
|
+
export declare const FilterMenu: React.FC<FilterMenuProps>;
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { Badge } from "../../atomic/Badge/Badge.js";
|
|
2
|
+
import { Button } from "../../atomic/Button/Button.js";
|
|
3
|
+
import { buttonLook } from "../../atomic/Button/buttonLook.js";
|
|
4
|
+
import { FacetList } from "../FacetFilter/FacetList.js";
|
|
5
|
+
import { Button as Button$1 } from "../../ui/button.js";
|
|
6
|
+
import { Input } from "../../ui/input.js";
|
|
7
|
+
import { Popover, PopoverContent, PopoverTrigger } from "../../ui/popover.js";
|
|
8
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
+
import { ChevronRightIcon, FilterIcon } from "lucide-react";
|
|
10
|
+
import { useState } from "react";
|
|
11
|
+
// src/components/molecule/FilterMenu/FilterMenu.tsx
|
|
12
|
+
const FilterMenu = (props) => {
|
|
13
|
+
const { categories, value, onChange, label = "Filter", size = "sm", disabled = false, "data-testid": testId } = props;
|
|
14
|
+
const [query, setQuery] = useState("");
|
|
15
|
+
const [openId, setOpenId] = useState(null);
|
|
16
|
+
const selectedCount = (category) => category.options.filter((option) => value[category.id]?.includes(option.value)).length;
|
|
17
|
+
const activeCount = categories.filter((category) => selectedCount(category) > 0).length;
|
|
18
|
+
const look = buttonLook("outline", size, false);
|
|
19
|
+
const needle = query.trim().toLowerCase();
|
|
20
|
+
const visible = categories.filter((category) => category.label.toLowerCase().includes(needle));
|
|
21
|
+
const clearAll = () => onChange({
|
|
22
|
+
...value,
|
|
23
|
+
...Object.fromEntries(categories.map(({ id }) => [id, []]))
|
|
24
|
+
});
|
|
25
|
+
return /* @__PURE__ */ jsxs(Popover, {
|
|
26
|
+
onOpenChange: (open) => {
|
|
27
|
+
if (open) return;
|
|
28
|
+
setQuery("");
|
|
29
|
+
setOpenId(null);
|
|
30
|
+
},
|
|
31
|
+
children: [/* @__PURE__ */ jsxs(PopoverTrigger, {
|
|
32
|
+
disabled,
|
|
33
|
+
"data-testid": testId,
|
|
34
|
+
render: /* @__PURE__ */ jsx(Button$1, {
|
|
35
|
+
variant: look.variant,
|
|
36
|
+
size: look.size
|
|
37
|
+
}),
|
|
38
|
+
children: [
|
|
39
|
+
/* @__PURE__ */ jsx(FilterIcon, {
|
|
40
|
+
"data-icon": "inline-start",
|
|
41
|
+
"aria-hidden": true
|
|
42
|
+
}),
|
|
43
|
+
label,
|
|
44
|
+
" ",
|
|
45
|
+
activeCount > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Badge, {
|
|
46
|
+
tone: "brand",
|
|
47
|
+
children: activeCount
|
|
48
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
49
|
+
className: "sr-only",
|
|
50
|
+
children: " active"
|
|
51
|
+
})] })
|
|
52
|
+
]
|
|
53
|
+
}), /* @__PURE__ */ jsxs(PopoverContent, {
|
|
54
|
+
align: "start",
|
|
55
|
+
"aria-label": label,
|
|
56
|
+
className: "w-60 gap-0 p-0",
|
|
57
|
+
children: [
|
|
58
|
+
/* @__PURE__ */ jsx("div", {
|
|
59
|
+
className: "border-b p-1",
|
|
60
|
+
children: /* @__PURE__ */ jsx(Input, {
|
|
61
|
+
"aria-label": "Search filters",
|
|
62
|
+
placeholder: "Search",
|
|
63
|
+
value: query,
|
|
64
|
+
onChange: (event) => setQuery(event.target.value)
|
|
65
|
+
})
|
|
66
|
+
}),
|
|
67
|
+
/* @__PURE__ */ jsxs("div", {
|
|
68
|
+
className: "max-h-60 overflow-y-auto p-1",
|
|
69
|
+
children: [visible.length === 0 && /* @__PURE__ */ jsx("p", {
|
|
70
|
+
className: "text-muted-foreground py-2 text-center text-sm",
|
|
71
|
+
children: "No results"
|
|
72
|
+
}), visible.map((category) => {
|
|
73
|
+
const count = selectedCount(category);
|
|
74
|
+
const multiple = category.multiple !== false;
|
|
75
|
+
return /* @__PURE__ */ jsxs(Popover, {
|
|
76
|
+
open: openId === category.id,
|
|
77
|
+
onOpenChange: (open) => setOpenId(open ? category.id : null),
|
|
78
|
+
children: [/* @__PURE__ */ jsxs(PopoverTrigger, {
|
|
79
|
+
render: /* @__PURE__ */ jsx("button", {
|
|
80
|
+
type: "button",
|
|
81
|
+
className: "hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent data-popup-open:bg-accent data-popup-open:text-accent-foreground flex w-full cursor-default items-center gap-2 rounded-md px-1.5 py-1 text-sm outline-none"
|
|
82
|
+
}),
|
|
83
|
+
children: [
|
|
84
|
+
/* @__PURE__ */ jsx("span", {
|
|
85
|
+
className: "min-w-0 flex-1 truncate text-left",
|
|
86
|
+
children: category.label
|
|
87
|
+
}),
|
|
88
|
+
count > 0 && /* @__PURE__ */ jsx("span", {
|
|
89
|
+
className: "text-xs tabular-nums",
|
|
90
|
+
children: count
|
|
91
|
+
}),
|
|
92
|
+
/* @__PURE__ */ jsx(ChevronRightIcon, {
|
|
93
|
+
"aria-hidden": true,
|
|
94
|
+
className: "size-4 shrink-0"
|
|
95
|
+
})
|
|
96
|
+
]
|
|
97
|
+
}), /* @__PURE__ */ jsx(PopoverContent, {
|
|
98
|
+
side: "right",
|
|
99
|
+
align: "start",
|
|
100
|
+
"aria-label": category.label,
|
|
101
|
+
className: "w-60 gap-0 p-0",
|
|
102
|
+
children: /* @__PURE__ */ jsx(FacetList, {
|
|
103
|
+
label: category.label,
|
|
104
|
+
options: category.options,
|
|
105
|
+
value: value[category.id] ?? [],
|
|
106
|
+
onChange: (next) => onChange({
|
|
107
|
+
...value,
|
|
108
|
+
[category.id]: next
|
|
109
|
+
}),
|
|
110
|
+
multiple,
|
|
111
|
+
showSelectAll: multiple
|
|
112
|
+
})
|
|
113
|
+
})]
|
|
114
|
+
}, category.id);
|
|
115
|
+
})]
|
|
116
|
+
}),
|
|
117
|
+
activeCount > 0 && /* @__PURE__ */ jsx("div", {
|
|
118
|
+
className: "border-t p-1",
|
|
119
|
+
children: /* @__PURE__ */ jsx(Button, {
|
|
120
|
+
variant: "ghost",
|
|
121
|
+
size: "sm",
|
|
122
|
+
fullWidth: true,
|
|
123
|
+
onClick: clearAll,
|
|
124
|
+
children: "Clear all"
|
|
125
|
+
})
|
|
126
|
+
})
|
|
127
|
+
]
|
|
128
|
+
})]
|
|
129
|
+
});
|
|
130
|
+
};
|
|
131
|
+
export { FilterMenu };
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput } from "./input-group.js";
|
|
3
|
+
import { cn } from "cn";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
import { CheckIcon, ChevronDownIcon, XIcon } from "lucide-react";
|
|
6
|
+
import "react";
|
|
7
|
+
import { Combobox } from "@base-ui/react";
|
|
8
|
+
// src/components/ui/combobox.tsx
|
|
9
|
+
const Combobox$1 = Combobox.Root;
|
|
10
|
+
const ComboboxTrigger = ({ className, children, ...props }) => {
|
|
11
|
+
return /* @__PURE__ */ jsxs(Combobox.Trigger, {
|
|
12
|
+
"data-slot": "combobox-trigger",
|
|
13
|
+
className: cn("[&_svg:not([class*='size-'])]:size-4", className),
|
|
14
|
+
...props,
|
|
15
|
+
children: [children, /* @__PURE__ */ jsx(ChevronDownIcon, { className: "text-muted-foreground pointer-events-none size-4" })]
|
|
16
|
+
});
|
|
17
|
+
};
|
|
18
|
+
const ComboboxClear = ({ className, ...props }) => {
|
|
19
|
+
return /* @__PURE__ */ jsx(Combobox.Clear, {
|
|
20
|
+
"data-slot": "combobox-clear",
|
|
21
|
+
render: /* @__PURE__ */ jsx(InputGroupButton, {
|
|
22
|
+
variant: "ghost",
|
|
23
|
+
size: "icon-xs"
|
|
24
|
+
}),
|
|
25
|
+
className: cn(className),
|
|
26
|
+
...props,
|
|
27
|
+
children: /* @__PURE__ */ jsx(XIcon, { className: "pointer-events-none" })
|
|
28
|
+
});
|
|
29
|
+
};
|
|
30
|
+
const ComboboxInput = ({ className, children, disabled = false, showTrigger = true, showClear = false, ...props }) => {
|
|
31
|
+
return /* @__PURE__ */ jsxs(InputGroup, {
|
|
32
|
+
className: cn("w-auto", className),
|
|
33
|
+
children: [
|
|
34
|
+
/* @__PURE__ */ jsx(Combobox.Input, {
|
|
35
|
+
render: /* @__PURE__ */ jsx(InputGroupInput, { disabled }),
|
|
36
|
+
...props
|
|
37
|
+
}),
|
|
38
|
+
/* @__PURE__ */ jsxs(InputGroupAddon, {
|
|
39
|
+
align: "inline-end",
|
|
40
|
+
children: [showTrigger && /* @__PURE__ */ jsx(InputGroupButton, {
|
|
41
|
+
size: "icon-xs",
|
|
42
|
+
variant: "ghost",
|
|
43
|
+
render: /* @__PURE__ */ jsx(ComboboxTrigger, {}),
|
|
44
|
+
"data-slot": "input-group-button",
|
|
45
|
+
className: "group-has-data-[slot=combobox-clear]/input-group:hidden data-pressed:bg-transparent",
|
|
46
|
+
disabled
|
|
47
|
+
}), showClear && /* @__PURE__ */ jsx(ComboboxClear, { disabled })]
|
|
48
|
+
}),
|
|
49
|
+
children
|
|
50
|
+
]
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
const ComboboxList = ({ className, ...props }) => {
|
|
54
|
+
return /* @__PURE__ */ jsx(Combobox.List, {
|
|
55
|
+
"data-slot": "combobox-list",
|
|
56
|
+
className: cn("no-scrollbar max-h-[min(calc(--spacing(72)---spacing(9)),calc(var(--available-height)---spacing(9)))] scroll-py-1 overflow-y-auto overscroll-contain p-1 data-empty:p-0", className),
|
|
57
|
+
...props
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
const ComboboxItem = ({ className, children, ...props }) => {
|
|
61
|
+
return /* @__PURE__ */ jsxs(Combobox.Item, {
|
|
62
|
+
"data-slot": "combobox-item",
|
|
63
|
+
className: cn("data-highlighted:bg-accent data-highlighted:text-accent-foreground not-data-[variant=destructive]:data-highlighted:**:text-accent-foreground relative flex w-full cursor-default items-center gap-2 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", className),
|
|
64
|
+
...props,
|
|
65
|
+
children: [children, /* @__PURE__ */ jsx(Combobox.ItemIndicator, {
|
|
66
|
+
render: /* @__PURE__ */ jsx("span", { className: "pointer-events-none absolute right-2 flex size-4 items-center justify-center" }),
|
|
67
|
+
children: /* @__PURE__ */ jsx(CheckIcon, { className: "pointer-events-none" })
|
|
68
|
+
})]
|
|
69
|
+
});
|
|
70
|
+
};
|
|
71
|
+
const ComboboxEmpty = ({ className, ...props }) => {
|
|
72
|
+
return /* @__PURE__ */ jsx(Combobox.Empty, {
|
|
73
|
+
"data-slot": "combobox-empty",
|
|
74
|
+
className: cn("text-muted-foreground hidden w-full justify-center py-2 text-center text-sm group-data-empty/combobox-content:flex", className),
|
|
75
|
+
...props
|
|
76
|
+
});
|
|
77
|
+
};
|
|
78
|
+
export { Combobox$1 as Combobox, ComboboxEmpty, ComboboxInput, ComboboxItem, ComboboxList, ComboboxTrigger };
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { Button } from "./button.js";
|
|
2
|
+
import { Input } from "./input.js";
|
|
3
|
+
import { cva } from "class-variance-authority";
|
|
4
|
+
import { cn } from "cn";
|
|
5
|
+
import { jsx } from "react/jsx-runtime";
|
|
6
|
+
import "react";
|
|
7
|
+
// src/components/ui/input-group.tsx
|
|
8
|
+
const InputGroup = ({ className, ...props }) => {
|
|
9
|
+
return /* @__PURE__ */ jsx("div", {
|
|
10
|
+
"data-slot": "input-group",
|
|
11
|
+
role: "group",
|
|
12
|
+
className: cn("group/input-group border-input has-disabled:bg-input/50 has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot=input-group-control]:focus-visible]:ring-ring/50 has-[[data-slot][aria-invalid=true]]:border-destructive has-[[data-slot][aria-invalid=true]]:ring-destructive/20 dark:bg-input/30 dark:has-disabled:bg-input/80 dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40 relative flex h-8 w-full min-w-0 items-center rounded-lg border transition-colors outline-none in-data-[slot=combobox-content]:focus-within:border-inherit in-data-[slot=combobox-content]:focus-within:ring-0 has-disabled:opacity-50 has-[[data-slot=input-group-control]:focus-visible]:ring-3 has-[[data-slot][aria-invalid=true]]:ring-3 has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>textarea]:h-auto has-[>[data-align=block-end]]:[&>input]:pt-3 has-[>[data-align=block-start]]:[&>input]:pb-3 has-[>[data-align=inline-end]]:[&>input]:pr-1.5 has-[>[data-align=inline-start]]:[&>input]:pl-1.5", className),
|
|
13
|
+
...props
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
const inputGroupAddonVariants = cva("flex h-auto cursor-text items-center justify-center gap-2 py-1.5 text-sm font-medium text-muted-foreground select-none group-data-[disabled=true]/input-group:opacity-50 [&>kbd]:rounded-[calc(var(--radius)-5px)] [&>svg:not([class*='size-'])]:size-4", {
|
|
17
|
+
variants: { align: {
|
|
18
|
+
"inline-start": "order-first pl-2 has-[>button]:ml-[-0.3rem] has-[>kbd]:ml-[-0.15rem]",
|
|
19
|
+
"inline-end": "order-last pr-2 has-[>button]:mr-[-0.3rem] has-[>kbd]:mr-[-0.15rem]",
|
|
20
|
+
"block-start": "order-first w-full justify-start px-2.5 pt-2 group-has-[>input]/input-group:pt-2 [.border-b]:pb-2",
|
|
21
|
+
"block-end": "order-last w-full justify-start px-2.5 pb-2 group-has-[>input]/input-group:pb-2 [.border-t]:pt-2"
|
|
22
|
+
} },
|
|
23
|
+
defaultVariants: { align: "inline-start" }
|
|
24
|
+
});
|
|
25
|
+
const InputGroupAddon = ({ className, align = "inline-start", ...props }) => {
|
|
26
|
+
return /* @__PURE__ */ jsx("div", {
|
|
27
|
+
role: "group",
|
|
28
|
+
"data-slot": "input-group-addon",
|
|
29
|
+
"data-align": align,
|
|
30
|
+
className: cn(inputGroupAddonVariants({ align }), className),
|
|
31
|
+
onClick: (e) => {
|
|
32
|
+
if (e.target.closest("button")) return;
|
|
33
|
+
e.currentTarget.parentElement?.querySelector("input")?.focus();
|
|
34
|
+
},
|
|
35
|
+
...props
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
const inputGroupButtonVariants = cva("flex items-center gap-2 text-sm shadow-none", {
|
|
39
|
+
variants: { size: {
|
|
40
|
+
xs: "h-6 gap-1 rounded-[calc(var(--radius)-3px)] px-1.5 [&>svg:not([class*='size-'])]:size-3.5",
|
|
41
|
+
sm: "",
|
|
42
|
+
"icon-xs": "size-6 rounded-[calc(var(--radius)-3px)] p-0 has-[>svg]:p-0",
|
|
43
|
+
"icon-sm": "size-8 p-0 has-[>svg]:p-0"
|
|
44
|
+
} },
|
|
45
|
+
defaultVariants: { size: "xs" }
|
|
46
|
+
});
|
|
47
|
+
const InputGroupButton = ({ className, type = "button", variant = "ghost", size = "xs", ...props }) => {
|
|
48
|
+
return /* @__PURE__ */ jsx(Button, {
|
|
49
|
+
type,
|
|
50
|
+
"data-size": size,
|
|
51
|
+
variant,
|
|
52
|
+
className: cn(inputGroupButtonVariants({ size }), className),
|
|
53
|
+
...props
|
|
54
|
+
});
|
|
55
|
+
};
|
|
56
|
+
const InputGroupInput = ({ className, ...props }) => {
|
|
57
|
+
return /* @__PURE__ */ jsx(Input, {
|
|
58
|
+
"data-slot": "input-group-control",
|
|
59
|
+
className: cn("flex-1 rounded-none border-0 bg-transparent shadow-none ring-0 focus-visible:ring-0 disabled:bg-transparent aria-invalid:ring-0 dark:bg-transparent dark:disabled:bg-transparent", className),
|
|
60
|
+
...props
|
|
61
|
+
});
|
|
62
|
+
};
|
|
63
|
+
export { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput };
|
package/dist/index.d.ts
CHANGED
|
@@ -35,6 +35,15 @@ import "./components/molecule/ConfirmDialog/index.js";
|
|
|
35
35
|
import { ConfirmDialog, ConfirmDialogProps } from "./components/molecule/ConfirmDialog/ConfirmDialog.js";
|
|
36
36
|
import "./components/molecule/DropdownMenu/index.js";
|
|
37
37
|
import { DropdownMenu, DropdownMenuProps, MenuItem } from "./components/molecule/DropdownMenu/DropdownMenu.js";
|
|
38
|
+
import "./components/molecule/FacetFilter/index.js";
|
|
39
|
+
import { FacetOption } from "./components/molecule/FacetFilter/FacetList.js";
|
|
40
|
+
import { FacetFilter, FacetFilterProps } from "./components/molecule/FacetFilter/FacetFilter.js";
|
|
41
|
+
import "./components/molecule/FacetFilterSelect/index.js";
|
|
42
|
+
import { FacetFilterSelect, FacetFilterSelectProps } from "./components/molecule/FacetFilterSelect/FacetFilterSelect.js";
|
|
43
|
+
import "./components/molecule/FacetFilterNumber/index.js";
|
|
44
|
+
import { FacetFilterNumber, FacetFilterNumberProps, NumberCondition, NumberFilterValue } from "./components/molecule/FacetFilterNumber/FacetFilterNumber.js";
|
|
45
|
+
import "./components/molecule/FilterMenu/index.js";
|
|
46
|
+
import { FilterCategory, FilterMenu, FilterMenuProps, FilterMenuValue } from "./components/molecule/FilterMenu/FilterMenu.js";
|
|
38
47
|
import "./components/molecule/FormField/index.js";
|
|
39
48
|
import { FormField, FormFieldControlProps, FormFieldProps } from "./components/molecule/FormField/FormField.js";
|
|
40
49
|
import "./components/molecule/Modal/index.js";
|
|
@@ -47,4 +56,4 @@ import { Toaster } from "./components/molecule/Toaster/Toaster.js";
|
|
|
47
56
|
import "./components/layout/Stack/index.js";
|
|
48
57
|
import { HStack, HStackProps, Stack, StackAlign, StackGap, StackJustify, StackProps, VStack, VStackProps } from "./components/layout/Stack/Stack.js";
|
|
49
58
|
import { FieldBaseProps, IconComponent, OverlayAlign, OverlaySide, Size, Tone } from "./lib/types.js";
|
|
50
|
-
export { Badge, type BadgeProps, Button, type ButtonProps, type ButtonVariant, Checkbox, type CheckboxProps, ColorInput, type ColorInputProps, ConfirmDialog, type ConfirmDialogProps, Divider, type DividerProps, DropdownMenu, type DropdownMenuProps, type FieldBaseProps, FormField, type FormFieldControlProps, type FormFieldProps, FormLayout, type FormLayoutDirection, type FormLayoutProps, HStack, type HStackProps, Heading, type HeadingLevel, type HeadingProps, IconButton, type IconButtonProps, type IconButtonVariant, type IconComponent, type MenuItem, Modal, type ModalProps, type ModalSize, type OverlayAlign, type OverlaySide, Popover, type PopoverProps, type PopoverWidth, Select, type SelectOption, type SelectProps, type Size, Skeleton, type SkeletonProps, type SkeletonShape, Spinner, type SpinnerProps, Stack, type StackAlign, type StackGap, type StackJustify, type StackProps, Switch, type SwitchProps, Text, TextArea, type TextAreaProps, TextInput, type TextInputProps, type TextInputType, type TextProps, type TextSize, type TextTone, type TextWeight, type ToastOptions, Toaster, type Tone, Tooltip, type TooltipProps, VStack, type VStackProps, toast };
|
|
59
|
+
export { Badge, type BadgeProps, Button, type ButtonProps, type ButtonVariant, Checkbox, type CheckboxProps, ColorInput, type ColorInputProps, ConfirmDialog, type ConfirmDialogProps, Divider, type DividerProps, DropdownMenu, type DropdownMenuProps, FacetFilter, FacetFilterNumber, type FacetFilterNumberProps, type FacetFilterProps, FacetFilterSelect, type FacetFilterSelectProps, type FacetOption, type FieldBaseProps, type FilterCategory, FilterMenu, type FilterMenuProps, type FilterMenuValue, FormField, type FormFieldControlProps, type FormFieldProps, FormLayout, type FormLayoutDirection, type FormLayoutProps, HStack, type HStackProps, Heading, type HeadingLevel, type HeadingProps, IconButton, type IconButtonProps, type IconButtonVariant, type IconComponent, type MenuItem, Modal, type ModalProps, type ModalSize, type NumberCondition, type NumberFilterValue, type OverlayAlign, type OverlaySide, Popover, type PopoverProps, type PopoverWidth, Select, type SelectOption, type SelectProps, type Size, Skeleton, type SkeletonProps, type SkeletonShape, Spinner, type SpinnerProps, Stack, type StackAlign, type StackGap, type StackJustify, type StackProps, Switch, type SwitchProps, Text, TextArea, type TextAreaProps, TextInput, type TextInputProps, type TextInputType, type TextProps, type TextSize, type TextTone, type TextWeight, type ToastOptions, Toaster, type Tone, Tooltip, type TooltipProps, VStack, type VStackProps, toast };
|
package/dist/index.js
CHANGED
|
@@ -16,10 +16,14 @@ import { Spinner } from "./components/atomic/Spinner/Spinner.js";
|
|
|
16
16
|
import { FormLayout } from "./components/layout/FormLayout/FormLayout.js";
|
|
17
17
|
import { ConfirmDialog } from "./components/molecule/ConfirmDialog/ConfirmDialog.js";
|
|
18
18
|
import { DropdownMenu } from "./components/molecule/DropdownMenu/DropdownMenu.js";
|
|
19
|
+
import { FacetFilter } from "./components/molecule/FacetFilter/FacetFilter.js";
|
|
20
|
+
import { FacetFilterSelect } from "./components/molecule/FacetFilterSelect/FacetFilterSelect.js";
|
|
21
|
+
import { FacetFilterNumber } from "./components/molecule/FacetFilterNumber/FacetFilterNumber.js";
|
|
22
|
+
import { FilterMenu } from "./components/molecule/FilterMenu/FilterMenu.js";
|
|
19
23
|
import { FormField } from "./components/molecule/FormField/FormField.js";
|
|
20
24
|
import { Modal } from "./components/molecule/Modal/Modal.js";
|
|
21
25
|
import { Popover } from "./components/molecule/Popover/Popover.js";
|
|
22
26
|
import { toast } from "./components/molecule/Toaster/toast.js";
|
|
23
27
|
import { Toaster } from "./components/molecule/Toaster/Toaster.js";
|
|
24
28
|
import { HStack, Stack, VStack } from "./components/layout/Stack/Stack.js";
|
|
25
|
-
export { Badge, Button, Checkbox, ColorInput, ConfirmDialog, Divider, DropdownMenu, FormField, FormLayout, HStack, Heading, IconButton, Modal, Popover, Select, Skeleton, Spinner, Stack, Switch, Text, TextArea, TextInput, Toaster, Tooltip, VStack, toast };
|
|
29
|
+
export { Badge, Button, Checkbox, ColorInput, ConfirmDialog, Divider, DropdownMenu, FacetFilter, FacetFilterNumber, FacetFilterSelect, FilterMenu, FormField, FormLayout, HStack, Heading, IconButton, Modal, Popover, Select, Skeleton, Spinner, Stack, Switch, Text, TextArea, TextInput, Toaster, Tooltip, VStack, toast };
|
package/package.json
CHANGED