@bearmenu/ui 0.8.52 → 0.8.53

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.
@@ -0,0 +1,177 @@
1
+ import { FilterOptionChip } from './chunk-RKNPPYRU.js';
2
+ import { Separator } from './chunk-NWZGSLPU.js';
3
+ import { Button } from './chunk-GHKTVHQG.js';
4
+ import { Text } from './chunk-ZLMRVBD7.js';
5
+ import { Badge } from './chunk-RYPPN2GZ.js';
6
+ import { cn } from './chunk-FEK5XGZW.js';
7
+ import { useId, useState } from 'react';
8
+ import { ChevronDown } from 'lucide-react';
9
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
10
+
11
+ function FilterOptionGroup({
12
+ title,
13
+ options,
14
+ value,
15
+ onValueChange,
16
+ selection = "multiple",
17
+ name,
18
+ defaultOpen = false,
19
+ collapsible = true,
20
+ visibleLimit = 6,
21
+ showAllLabel,
22
+ showLessLabel,
23
+ children,
24
+ footer,
25
+ clearLabel,
26
+ onClear,
27
+ summaryValues = value,
28
+ className,
29
+ divider = true,
30
+ disabled
31
+ }) {
32
+ const id = useId();
33
+ const [isOpen, setOpen] = useState(defaultOpen);
34
+ const open = !collapsible || isOpen;
35
+ const [expanded, setExpanded] = useState([]);
36
+ const selected = options.filter(
37
+ (option) => summaryValues.includes(option.value)
38
+ );
39
+ const sections = [];
40
+ for (const option of options) {
41
+ const last = sections[sections.length - 1];
42
+ if (!last || last.label !== option.section)
43
+ sections.push({ label: option.section, options: [option] });
44
+ else last.options.push(option);
45
+ }
46
+ const heading = /* @__PURE__ */ jsxs(Fragment, { children: [
47
+ /* @__PURE__ */ jsxs("span", { className: "min-w-0 flex-1", children: [
48
+ /* @__PURE__ */ jsx(
49
+ Text,
50
+ {
51
+ as: "span",
52
+ id: `${id}-title`,
53
+ className: "block",
54
+ variant: "body-sm",
55
+ weight: "semibold",
56
+ children: title
57
+ }
58
+ ),
59
+ !open && selected.length > 0 && /* @__PURE__ */ jsx(
60
+ Text,
61
+ {
62
+ as: "span",
63
+ variant: "caption",
64
+ color: "muted",
65
+ className: "mt-1 block leading-relaxed [overflow-wrap:anywhere]",
66
+ children: selected.map((option) => option.label).join(" \xB7 ")
67
+ }
68
+ )
69
+ ] }),
70
+ selected.length > 0 && /* @__PURE__ */ jsx(Badge, { variant: "secondary", className: "tabular-nums", children: selected.length }),
71
+ collapsible && /* @__PURE__ */ jsx(
72
+ ChevronDown,
73
+ {
74
+ "aria-hidden": true,
75
+ className: cn(
76
+ "size-4 shrink-0 text-muted-foreground transition-transform motion-reduce:transition-none",
77
+ open && "rotate-180"
78
+ )
79
+ }
80
+ )
81
+ ] });
82
+ return /* @__PURE__ */ jsxs("section", { className: cn("min-w-0", className), children: [
83
+ /* @__PURE__ */ jsxs("div", { className: "py-2", children: [
84
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
85
+ collapsible ? /* @__PURE__ */ jsx(
86
+ "button",
87
+ {
88
+ type: "button",
89
+ onClick: () => setOpen((previous) => !previous),
90
+ "aria-expanded": open,
91
+ "aria-controls": id,
92
+ className: "flex min-h-11 min-w-0 flex-1 items-center gap-3 rounded-lg py-2 text-left focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring",
93
+ children: heading
94
+ }
95
+ ) : /* @__PURE__ */ jsx("div", { className: "flex min-h-11 min-w-0 flex-1 items-center gap-3 py-2", children: heading }),
96
+ onClear && clearLabel && summaryValues.length > 0 && /* @__PURE__ */ jsx(
97
+ Button,
98
+ {
99
+ type: "button",
100
+ variant: "ghost",
101
+ className: "min-h-11 shrink-0 px-2 text-xs",
102
+ onClick: onClear,
103
+ children: clearLabel
104
+ }
105
+ )
106
+ ] }),
107
+ /* @__PURE__ */ jsxs("div", { id, hidden: !open, children: [
108
+ children,
109
+ sections.map((section, index) => {
110
+ var _a;
111
+ const sectionId = `${id}-section-${index}`;
112
+ const key = (_a = section.label) != null ? _a : "";
113
+ const isExpanded = expanded.includes(key);
114
+ const limit = showAllLabel ? visibleLimit : Infinity;
115
+ const visible = isExpanded ? section.options : section.options.filter(
116
+ (option, i) => i < limit || value.includes(option.value)
117
+ );
118
+ return /* @__PURE__ */ jsxs("div", { children: [
119
+ section.label && /* @__PURE__ */ jsx(
120
+ Text,
121
+ {
122
+ as: "h4",
123
+ id: sectionId,
124
+ variant: "caption",
125
+ weight: "semibold",
126
+ color: "muted",
127
+ className: "mt-3 mb-1",
128
+ children: section.label
129
+ }
130
+ ),
131
+ /* @__PURE__ */ jsx(
132
+ "fieldset",
133
+ {
134
+ "aria-labelledby": `${id}-title${section.label ? ` ${sectionId}` : ""}`,
135
+ disabled,
136
+ className: "m-0 flex min-w-0 flex-wrap gap-2 border-0 px-0 pt-2 pb-3",
137
+ children: visible.map((option) => /* @__PURE__ */ jsx(
138
+ FilterOptionChip,
139
+ {
140
+ label: option.label,
141
+ count: option.count,
142
+ icon: option.icon,
143
+ type: selection === "single" ? "radio" : "checkbox",
144
+ name: selection === "single" ? name != null ? name : id : void 0,
145
+ value: option.value,
146
+ checked: value.includes(option.value),
147
+ onChange: (event) => onValueChange(
148
+ selection === "single" ? [option.value] : event.target.checked ? [...value, option.value] : value.filter((item) => item !== option.value)
149
+ )
150
+ },
151
+ option.value
152
+ ))
153
+ }
154
+ ),
155
+ section.options.length > limit && /* @__PURE__ */ jsx(
156
+ Button,
157
+ {
158
+ type: "button",
159
+ variant: "link",
160
+ "aria-expanded": isExpanded,
161
+ onClick: () => setExpanded(
162
+ (previous) => isExpanded ? previous.filter((item) => item !== key) : [...previous, key]
163
+ ),
164
+ className: "mb-1 min-h-11 px-0",
165
+ children: isExpanded ? showLessLabel : typeof showAllLabel === "function" ? showAllLabel(section.options.length) : showAllLabel
166
+ }
167
+ )
168
+ ] }, key);
169
+ }),
170
+ footer
171
+ ] })
172
+ ] }),
173
+ divider && /* @__PURE__ */ jsx(Separator, {})
174
+ ] });
175
+ }
176
+
177
+ export { FilterOptionGroup };
@@ -0,0 +1,86 @@
1
+ import { cn } from './chunk-FEK5XGZW.js';
2
+ import { __objRest, __spreadProps, __spreadValues } from './chunk-MMUBH76A.js';
3
+ import { useId } from 'react';
4
+ import { Check } from 'lucide-react';
5
+ import { jsxs, jsx } from 'react/jsx-runtime';
6
+
7
+ function FilterOptionChip(_a) {
8
+ var _b = _a, {
9
+ label,
10
+ type = "checkbox",
11
+ count,
12
+ icon,
13
+ className,
14
+ id,
15
+ disabled
16
+ } = _b, input = __objRest(_b, [
17
+ "label",
18
+ "type",
19
+ "count",
20
+ "icon",
21
+ "className",
22
+ "id",
23
+ "disabled"
24
+ ]);
25
+ var _a2;
26
+ const generatedId = useId();
27
+ const inputId = id != null ? id : generatedId;
28
+ return /* @__PURE__ */ jsxs(
29
+ "label",
30
+ {
31
+ htmlFor: inputId,
32
+ className: cn(
33
+ "relative inline-flex max-w-full min-w-0",
34
+ disabled && "cursor-not-allowed opacity-50",
35
+ className
36
+ ),
37
+ children: [
38
+ /* @__PURE__ */ jsx(
39
+ "input",
40
+ __spreadProps(__spreadValues({}, input), {
41
+ id: inputId,
42
+ type,
43
+ disabled,
44
+ "aria-label": (_a2 = input["aria-label"]) != null ? _a2 : label,
45
+ className: "peer sr-only"
46
+ })
47
+ ),
48
+ /* @__PURE__ */ jsxs(
49
+ "span",
50
+ {
51
+ className: cn(
52
+ "flex min-h-11 min-w-0 max-w-full cursor-pointer items-center gap-2 rounded-2xl border border-border bg-background px-3 py-2 text-sm text-foreground",
53
+ "transition-colors hover:bg-muted motion-reduce:transition-none",
54
+ "peer-checked:border-primary peer-checked:bg-primary/10 peer-checked:shadow-[inset_0_0_0_1px_var(--primary)] peer-checked:text-primary",
55
+ "peer-focus-visible:outline-2 peer-focus-visible:outline-offset-2 peer-focus-visible:outline-ring",
56
+ "peer-disabled:pointer-events-none peer-disabled:cursor-not-allowed",
57
+ "[&_.filter-check]:hidden peer-checked:[&_.filter-check]:block peer-checked:[&_.filter-icon]:hidden"
58
+ ),
59
+ children: [
60
+ /* @__PURE__ */ jsx(
61
+ Check,
62
+ {
63
+ "aria-hidden": true,
64
+ className: "filter-check size-4 shrink-0",
65
+ strokeWidth: 2.5
66
+ }
67
+ ),
68
+ icon && /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "filter-icon shrink-0 [&>svg]:size-4", children: icon }),
69
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 [overflow-wrap:anywhere]", children: label }),
70
+ count != null && /* @__PURE__ */ jsx(
71
+ "span",
72
+ {
73
+ "aria-hidden": true,
74
+ className: "shrink-0 text-xs tabular-nums text-muted-foreground",
75
+ children: count
76
+ }
77
+ )
78
+ ]
79
+ }
80
+ )
81
+ ]
82
+ }
83
+ );
84
+ }
85
+
86
+ export { FilterOptionChip };
@@ -3,10 +3,10 @@ import * as React from 'react';
3
3
  import { VariantProps } from 'class-variance-authority';
4
4
 
5
5
  declare const alertVariants: (props?: ({
6
- variant?: "default" | "success" | "warning" | "destructive" | null | undefined;
6
+ variant?: "default" | "destructive" | "warning" | "success" | null | undefined;
7
7
  } & class_variance_authority_types.ClassProp) | undefined) => string;
8
8
  declare const Alert: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & VariantProps<(props?: ({
9
- variant?: "default" | "success" | "warning" | "destructive" | null | undefined;
9
+ variant?: "default" | "destructive" | "warning" | "success" | null | undefined;
10
10
  } & class_variance_authority_types.ClassProp) | undefined) => string> & React.RefAttributes<HTMLDivElement>>;
11
11
  declare const AlertTitle: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLHeadingElement> & React.RefAttributes<HTMLParagraphElement>>;
12
12
  declare const AlertDescription: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLParagraphElement> & React.RefAttributes<HTMLParagraphElement>>;
@@ -4,7 +4,7 @@ import * as React from 'react';
4
4
  import { VariantProps } from 'class-variance-authority';
5
5
 
6
6
  declare const badgeVariants: (props?: ({
7
- variant?: "secondary" | "default" | "success" | "warning" | "destructive" | "outline" | "glass" | "overlay" | "brown" | "code" | "onPrimary" | "confirmed" | "pending" | "completed" | "assignee" | "softSuccess" | "softWarning" | "softDestructive" | "softNeutral" | null | undefined;
7
+ variant?: "code" | "default" | "destructive" | "outline" | "secondary" | "glass" | "overlay" | "brown" | "warning" | "success" | "onPrimary" | "confirmed" | "pending" | "completed" | "assignee" | "softSuccess" | "softWarning" | "softDestructive" | "softNeutral" | null | undefined;
8
8
  size?: "status" | "chip" | null | undefined;
9
9
  live?: boolean | null | undefined;
10
10
  } & class_variance_authority_types.ClassProp) | undefined) => string;
@@ -31,7 +31,7 @@ import { VariantProps } from 'class-variance-authority';
31
31
  * right edge, centred on the text, and never wraps under it.
32
32
  */
33
33
  declare const bannerVariants: (props?: ({
34
- tone?: "warning" | "destructive" | "info" | null | undefined;
34
+ tone?: "destructive" | "warning" | "info" | null | undefined;
35
35
  } & class_variance_authority_types.ClassProp) | undefined) => string;
36
36
  type BannerProps = Omit<React.HTMLAttributes<HTMLDivElement>, "title"> & VariantProps<typeof bannerVariants> & {
37
37
  /**
@@ -3,8 +3,8 @@ import * as React from 'react';
3
3
  import { VariantProps } from 'class-variance-authority';
4
4
 
5
5
  declare const buttonVariants: (props?: ({
6
- variant?: "secondary" | "default" | "link" | "warning" | "destructive" | "outline" | "ghost" | "glass" | "overlay" | "ink" | "brown" | "cta" | null | undefined;
7
- size?: "default" | "icon" | "cta" | "xs" | "sm" | "lg" | "pill" | "cta-sm" | "icon-xs" | "icon-sm" | "icon-lg" | null | undefined;
6
+ variant?: "link" | "default" | "destructive" | "outline" | "secondary" | "ghost" | "glass" | "overlay" | "ink" | "brown" | "warning" | "cta" | null | undefined;
7
+ size?: "default" | "cta" | "xs" | "sm" | "lg" | "pill" | "cta-sm" | "icon" | "icon-xs" | "icon-sm" | "icon-lg" | null | undefined;
8
8
  fullWidth?: boolean | null | undefined;
9
9
  } & class_variance_authority_types.ClassProp) | undefined) => string;
10
10
  interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
@@ -3,12 +3,12 @@ import * as React from 'react';
3
3
  import { VariantProps } from 'class-variance-authority';
4
4
 
5
5
  declare const cardVariants: (props?: ({
6
- variant?: "outline" | "glass" | "section" | "muted" | "surface" | "elevated" | "elevatedPanel" | null | undefined;
6
+ variant?: "section" | "outline" | "glass" | "muted" | "surface" | "elevated" | "elevatedPanel" | null | undefined;
7
7
  size?: "default" | "sm" | "lg" | null | undefined;
8
8
  interactive?: boolean | null | undefined;
9
9
  } & class_variance_authority_types.ClassProp) | undefined) => string;
10
10
  declare const Card: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & VariantProps<(props?: ({
11
- variant?: "outline" | "glass" | "section" | "muted" | "surface" | "elevated" | "elevatedPanel" | null | undefined;
11
+ variant?: "section" | "outline" | "glass" | "muted" | "surface" | "elevated" | "elevatedPanel" | null | undefined;
12
12
  size?: "default" | "sm" | "lg" | null | undefined;
13
13
  interactive?: boolean | null | undefined;
14
14
  } & class_variance_authority_types.ClassProp) | undefined) => string> & React.RefAttributes<HTMLDivElement>>;
@@ -4,11 +4,11 @@ import { DialogProps } from '@radix-ui/react-dialog';
4
4
 
5
5
  declare const Command: React.ForwardRefExoticComponent<Omit<{
6
6
  children?: React.ReactNode;
7
- } & Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, keyof React.HTMLAttributes<HTMLDivElement> | "key"> & {
7
+ } & Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof React.HTMLAttributes<HTMLDivElement>> & {
8
8
  ref?: React.Ref<HTMLDivElement>;
9
9
  } & {
10
10
  asChild?: boolean;
11
- }, keyof React.HTMLAttributes<HTMLDivElement> | "asChild" | "key"> & {
11
+ }, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild"> & {
12
12
  label?: string;
13
13
  shouldFilter?: boolean;
14
14
  filter?: (value: string, search: string, keywords?: string[]) => number;
@@ -28,61 +28,61 @@ declare const CommandInput: React.ForwardRefExoticComponent<Omit<Omit<Pick<Pick<
28
28
  ref?: React.Ref<HTMLInputElement>;
29
29
  } & {
30
30
  asChild?: boolean;
31
- }, "asChild" | "key" | keyof React.InputHTMLAttributes<HTMLInputElement>>, "onChange" | "value" | "type"> & {
31
+ }, "key" | "asChild" | keyof React.InputHTMLAttributes<HTMLInputElement>>, "onChange" | "type" | "value"> & {
32
32
  value?: string;
33
33
  onValueChange?: (search: string) => void;
34
34
  } & React.RefAttributes<HTMLInputElement>, "ref"> & React.RefAttributes<HTMLInputElement>>;
35
35
  declare const CommandList: React.ForwardRefExoticComponent<Omit<{
36
36
  children?: React.ReactNode;
37
- } & Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, keyof React.HTMLAttributes<HTMLDivElement> | "key"> & {
37
+ } & Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof React.HTMLAttributes<HTMLDivElement>> & {
38
38
  ref?: React.Ref<HTMLDivElement>;
39
39
  } & {
40
40
  asChild?: boolean;
41
- }, keyof React.HTMLAttributes<HTMLDivElement> | "asChild" | "key"> & {
41
+ }, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild"> & {
42
42
  label?: string;
43
43
  } & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
44
44
  declare const CommandEmpty: React.ForwardRefExoticComponent<Omit<{
45
45
  children?: React.ReactNode;
46
- } & Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, keyof React.HTMLAttributes<HTMLDivElement> | "key"> & {
46
+ } & Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof React.HTMLAttributes<HTMLDivElement>> & {
47
47
  ref?: React.Ref<HTMLDivElement>;
48
48
  } & {
49
49
  asChild?: boolean;
50
- }, keyof React.HTMLAttributes<HTMLDivElement> | "asChild" | "key"> & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
50
+ }, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild"> & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
51
51
  declare const CommandLoading: React.ForwardRefExoticComponent<Omit<{
52
52
  children?: React.ReactNode;
53
- } & Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, keyof React.HTMLAttributes<HTMLDivElement> | "key"> & {
53
+ } & Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof React.HTMLAttributes<HTMLDivElement>> & {
54
54
  ref?: React.Ref<HTMLDivElement>;
55
55
  } & {
56
56
  asChild?: boolean;
57
- }, keyof React.HTMLAttributes<HTMLDivElement> | "asChild" | "key"> & {
57
+ }, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild"> & {
58
58
  progress?: number;
59
59
  label?: string;
60
60
  } & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
61
61
  declare const CommandGroup: React.ForwardRefExoticComponent<Omit<{
62
62
  children?: React.ReactNode;
63
- } & Omit<Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, keyof React.HTMLAttributes<HTMLDivElement> | "key"> & {
63
+ } & Omit<Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof React.HTMLAttributes<HTMLDivElement>> & {
64
64
  ref?: React.Ref<HTMLDivElement>;
65
65
  } & {
66
66
  asChild?: boolean;
67
- }, keyof React.HTMLAttributes<HTMLDivElement> | "asChild" | "key">, "heading" | "value"> & {
67
+ }, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild">, "heading" | "value"> & {
68
68
  heading?: React.ReactNode;
69
69
  value?: string;
70
70
  forceMount?: boolean;
71
71
  } & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
72
- declare const CommandSeparator: React.ForwardRefExoticComponent<Omit<Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, keyof React.HTMLAttributes<HTMLDivElement> | "key"> & {
72
+ declare const CommandSeparator: React.ForwardRefExoticComponent<Omit<Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof React.HTMLAttributes<HTMLDivElement>> & {
73
73
  ref?: React.Ref<HTMLDivElement>;
74
74
  } & {
75
75
  asChild?: boolean;
76
- }, keyof React.HTMLAttributes<HTMLDivElement> | "asChild" | "key"> & {
76
+ }, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild"> & {
77
77
  alwaysRender?: boolean;
78
78
  } & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
79
79
  declare const CommandItem: React.ForwardRefExoticComponent<Omit<{
80
80
  children?: React.ReactNode;
81
- } & Omit<Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, keyof React.HTMLAttributes<HTMLDivElement> | "key"> & {
81
+ } & Omit<Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof React.HTMLAttributes<HTMLDivElement>> & {
82
82
  ref?: React.Ref<HTMLDivElement>;
83
83
  } & {
84
84
  asChild?: boolean;
85
- }, keyof React.HTMLAttributes<HTMLDivElement> | "asChild" | "key">, "onSelect" | "value" | "disabled"> & {
85
+ }, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild">, "onSelect" | "disabled" | "value"> & {
86
86
  disabled?: boolean;
87
87
  onSelect?: (value: string) => void;
88
88
  value?: string;
@@ -53,7 +53,7 @@ interface EmptyStateProps {
53
53
  * louder than a load failure the user can retry.
54
54
  */
55
55
  declare const EmptyState: React.ForwardRefExoticComponent<EmptyStateProps & React.RefAttributes<HTMLDivElement>>;
56
- declare const SearchEmptyState: React.ForwardRefExoticComponent<Omit<EmptyStateProps, "icon" | "variant"> & React.RefAttributes<HTMLDivElement>>;
57
- declare const ErrorEmptyState: React.ForwardRefExoticComponent<Omit<EmptyStateProps, "icon" | "variant"> & React.RefAttributes<HTMLDivElement>>;
56
+ declare const SearchEmptyState: React.ForwardRefExoticComponent<Omit<EmptyStateProps, "variant" | "icon"> & React.RefAttributes<HTMLDivElement>>;
57
+ declare const ErrorEmptyState: React.ForwardRefExoticComponent<Omit<EmptyStateProps, "variant" | "icon"> & React.RefAttributes<HTMLDivElement>>;
58
58
 
59
59
  export { EmptyState, ErrorEmptyState, SearchEmptyState };
@@ -58,6 +58,12 @@ type FacetGroupProps = Omit<ComponentPropsWithoutRef<"fieldset">, "title" | "chi
58
58
  */
59
59
  name?: string;
60
60
  size?: FacetGroupSize;
61
+ /** Wrapping native-input chips for filter panels. Rows remain the default. */
62
+ layout?: "rows" | "chips";
63
+ /** Optional bounded chip list; selected options always stay visible. */
64
+ visibleLimit?: number;
65
+ showAllLabel?: string | ((count: number) => string);
66
+ showLessLabel?: string;
61
67
  /**
62
68
  * Turns the legend into a disclosure toggle for this group's options.
63
69
  *
@@ -84,7 +90,7 @@ type FacetGroupProps = Omit<ComponentPropsWithoutRef<"fieldset">, "title" | "chi
84
90
  moreExpanded?: boolean;
85
91
  className?: string;
86
92
  };
87
- declare function FacetGroup({ title, icon: Icon, options, selection, name, size, collapsible, defaultOpen, onToggle, moreLabel, onMore, moreExpanded, className, ...rest }: FacetGroupProps): react_jsx_runtime.JSX.Element;
93
+ declare function FacetGroup({ title, icon: Icon, options, selection, name, size, layout, visibleLimit, showAllLabel, showLessLabel, collapsible, defaultOpen, onToggle, moreLabel, onMore, moreExpanded, className, ...rest }: FacetGroupProps): react_jsx_runtime.JSX.Element;
88
94
  type FacetGroupSkeletonProps = {
89
95
  /** How many option rows to draw — match the expected/last-known option count. */
90
96
  optionCount?: number;
@@ -92,9 +98,10 @@ type FacetGroupSkeletonProps = {
92
98
  showMore?: boolean;
93
99
  /** Must match the `<FacetGroup>` it stands in for, or rows shift when data lands. */
94
100
  size?: FacetGroupSize;
101
+ layout?: "rows" | "chips";
95
102
  className?: string;
96
103
  };
97
104
  /** Mirrors `<FacetGroup>`'s geometry exactly so nothing shifts when data lands. */
98
- declare function FacetGroupSkeleton({ optionCount, showMore, size, className, }: FacetGroupSkeletonProps): react_jsx_runtime.JSX.Element;
105
+ declare function FacetGroupSkeleton({ optionCount, showMore, size, className, layout, }: FacetGroupSkeletonProps): react_jsx_runtime.JSX.Element;
99
106
 
100
107
  export { FacetGroup, type FacetGroupProps, type FacetGroupSelection, type FacetGroupSize, FacetGroupSkeleton, type FacetGroupSkeletonProps, type FacetOption };
@@ -1,9 +1,17 @@
1
+ import { FilterOptionGroup } from '../chunk-GIJGVFGC.js';
2
+ import '../chunk-RKNPPYRU.js';
3
+ import '../chunk-NWZGSLPU.js';
1
4
  import { Skeleton } from '../chunk-XBBEX4SF.js';
5
+ import { Button } from '../chunk-GHKTVHQG.js';
6
+ import '../chunk-RIH2IS7X.js';
7
+ import '../chunk-5YNIQ2BL.js';
8
+ import '../chunk-ZLMRVBD7.js';
9
+ import '../chunk-RYPPN2GZ.js';
2
10
  import { cn } from '../chunk-FEK5XGZW.js';
3
11
  import { __objRest, __spreadProps, __spreadValues } from '../chunk-MMUBH76A.js';
4
12
  import { useId, useState } from 'react';
5
13
  import { ChevronDown, Check } from 'lucide-react';
6
- import { jsxs, jsx } from 'react/jsx-runtime';
14
+ import { jsx, jsxs } from 'react/jsx-runtime';
7
15
 
8
16
  var ROW_SIZE = {
9
17
  comfortable: "-mx-2 min-h-11 rounded-lg px-2",
@@ -21,6 +29,10 @@ function FacetGroup(_a) {
21
29
  selection = "multiple",
22
30
  name,
23
31
  size = "comfortable",
32
+ layout = "rows",
33
+ visibleLimit,
34
+ showAllLabel,
35
+ showLessLabel,
24
36
  collapsible = false,
25
37
  defaultOpen = true,
26
38
  onToggle,
@@ -35,6 +47,10 @@ function FacetGroup(_a) {
35
47
  "selection",
36
48
  "name",
37
49
  "size",
50
+ "layout",
51
+ "visibleLimit",
52
+ "showAllLabel",
53
+ "showLessLabel",
38
54
  "collapsible",
39
55
  "defaultOpen",
40
56
  "onToggle",
@@ -50,6 +66,48 @@ function FacetGroup(_a) {
50
66
  const setOpen = setIsOpen;
51
67
  const fallbackName = useId();
52
68
  const groupName = name != null ? name : fallbackName;
69
+ if (layout === "chips") {
70
+ const value = options.filter((option) => option.checked).map((option) => option.id);
71
+ return /* @__PURE__ */ jsx(
72
+ FilterOptionGroup,
73
+ {
74
+ title,
75
+ options: options.map((option) => __spreadProps(__spreadValues({}, option), { value: option.id })),
76
+ value,
77
+ selection,
78
+ name: groupName,
79
+ defaultOpen,
80
+ collapsible,
81
+ divider: false,
82
+ visibleLimit,
83
+ showAllLabel,
84
+ showLessLabel,
85
+ disabled: rest.disabled,
86
+ className,
87
+ onValueChange: (next) => {
88
+ if (selection === "single") {
89
+ if (next[0] != null) onToggle == null ? void 0 : onToggle(String(next[0]), true);
90
+ return;
91
+ }
92
+ for (const option of options) {
93
+ const checked = next.includes(option.id);
94
+ if (checked !== !!option.checked) onToggle == null ? void 0 : onToggle(option.id, checked);
95
+ }
96
+ },
97
+ footer: moreLabel && /* @__PURE__ */ jsx(
98
+ Button,
99
+ {
100
+ type: "button",
101
+ variant: "link",
102
+ className: "min-h-11 px-0",
103
+ onClick: onMore,
104
+ "aria-expanded": moreExpanded,
105
+ children: moreLabel
106
+ }
107
+ )
108
+ }
109
+ );
110
+ }
53
111
  return (
54
112
  // NO SEPARATOR OF ITS OWN. This drew `<Separator className="absolute
55
113
  // inset-x-0 top-0" />`, which looked like a rule above each group and was
@@ -98,7 +156,14 @@ function FacetGroup(_a) {
98
156
  open ? "mb-[11px]" : "mb-0"
99
157
  ),
100
158
  children: [
101
- Icon && /* @__PURE__ */ jsx(Icon, { "aria-hidden": true, className: "size-3.5 shrink-0", strokeWidth: 2.25 }),
159
+ Icon && /* @__PURE__ */ jsx(
160
+ Icon,
161
+ {
162
+ "aria-hidden": true,
163
+ className: "size-3.5 shrink-0",
164
+ strokeWidth: 2.25
165
+ }
166
+ ),
102
167
  title,
103
168
  /* @__PURE__ */ jsx(
104
169
  ChevronDown,
@@ -114,7 +179,14 @@ function FacetGroup(_a) {
114
179
  }
115
180
  )
116
181
  ) : /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5", children: [
117
- Icon && /* @__PURE__ */ jsx(Icon, { "aria-hidden": true, className: "size-3.5 shrink-0", strokeWidth: 2.25 }),
182
+ Icon && /* @__PURE__ */ jsx(
183
+ Icon,
184
+ {
185
+ "aria-hidden": true,
186
+ className: "size-3.5 shrink-0",
187
+ strokeWidth: 2.25
188
+ }
189
+ ),
118
190
  title
119
191
  ] })
120
192
  }
@@ -164,7 +236,13 @@ function FacetGroup(_a) {
164
236
  "peer-focus-visible:ring-2 peer-focus-visible:ring-ring peer-focus-visible:ring-offset-2",
165
237
  checked ? "border-primary bg-primary" : "border-border bg-background"
166
238
  ),
167
- children: checked && (isSingle ? /* @__PURE__ */ jsx("span", { className: "size-[7px] rounded-full bg-primary-foreground" }) : /* @__PURE__ */ jsx(Check, { className: "h-[11px] w-[11px] text-primary-foreground", strokeWidth: 3 }))
239
+ children: checked && (isSingle ? /* @__PURE__ */ jsx("span", { className: "size-[7px] rounded-full bg-primary-foreground" }) : /* @__PURE__ */ jsx(
240
+ Check,
241
+ {
242
+ className: "h-[11px] w-[11px] text-primary-foreground",
243
+ strokeWidth: 3
244
+ }
245
+ ))
168
246
  }
169
247
  ),
170
248
  /* @__PURE__ */ jsx(
@@ -205,18 +283,38 @@ function FacetGroupSkeleton({
205
283
  optionCount = 4,
206
284
  showMore,
207
285
  size = "comfortable",
208
- className
286
+ className,
287
+ layout = "rows"
209
288
  }) {
289
+ if (layout === "chips")
290
+ return /* @__PURE__ */ jsxs("div", { "aria-hidden": "true", className: cn("py-3", className), children: [
291
+ /* @__PURE__ */ jsx(Skeleton, { className: "mb-4 h-4 w-24" }),
292
+ /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2", children: Array.from({ length: optionCount }, (_, index) => /* @__PURE__ */ jsx(
293
+ Skeleton,
294
+ {
295
+ className: cn("h-11 rounded-2xl", index % 2 ? "w-28" : "w-24")
296
+ },
297
+ index
298
+ )) }),
299
+ showMore && /* @__PURE__ */ jsx(Skeleton, { className: "mt-3 h-4 w-20" })
300
+ ] });
210
301
  return (
211
302
  // Matches the live group: no rule of its own, `py-3`, and the row gap keyed
212
303
  // to the same density — or the panel shifts on load by the difference.
213
304
  /* @__PURE__ */ jsxs("div", { "aria-hidden": "true", className: cn("py-3", className), children: [
214
305
  /* @__PURE__ */ jsx(Skeleton, { className: "mb-[11px] h-3 w-20" }),
215
- /* @__PURE__ */ jsx("div", { className: cn("flex flex-col", ROW_GAP[size]), children: Array.from({ length: optionCount }).map((_, index) => /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-[9px]", ROW_SIZE[size]), children: [
216
- /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-4 rounded-[5px]" }),
217
- /* @__PURE__ */ jsx(Skeleton, { className: "h-3.5 w-24" }),
218
- /* @__PURE__ */ jsx(Skeleton, { className: "ml-auto h-3 w-5" })
219
- ] }, index)) }),
306
+ /* @__PURE__ */ jsx("div", { className: cn("flex flex-col", ROW_GAP[size]), children: Array.from({ length: optionCount }).map((_, index) => /* @__PURE__ */ jsxs(
307
+ "div",
308
+ {
309
+ className: cn("flex items-center gap-[9px]", ROW_SIZE[size]),
310
+ children: [
311
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-4 rounded-[5px]" }),
312
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-3.5 w-24" }),
313
+ /* @__PURE__ */ jsx(Skeleton, { className: "ml-auto h-3 w-5" })
314
+ ]
315
+ },
316
+ index
317
+ )) }),
220
318
  showMore && /* @__PURE__ */ jsx(Skeleton, { className: "mt-[11px] h-3 w-16" })
221
319
  ] })
222
320
  );