@flanksource/clicky-ui 0.2.20 → 0.3.1
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/Combobox.cjs +5 -2
- package/dist/components/Combobox.cjs.map +1 -1
- package/dist/components/Combobox.d.ts.map +1 -1
- package/dist/components/Combobox.js +5 -2
- package/dist/components/Combobox.js.map +1 -1
- package/dist/components/FilterBar.cjs +280 -253
- package/dist/components/FilterBar.cjs.map +1 -1
- package/dist/components/FilterBar.d.ts.map +1 -1
- package/dist/components/FilterBar.js +280 -253
- package/dist/components/FilterBar.js.map +1 -1
- package/dist/components/JsonSchemaForm.cjs +3 -1
- package/dist/components/JsonSchemaForm.cjs.map +1 -1
- package/dist/components/JsonSchemaForm.d.ts.map +1 -1
- package/dist/components/JsonSchemaForm.js +4 -2
- package/dist/components/JsonSchemaForm.js.map +1 -1
- package/dist/components/MultiSelect.cjs +29 -32
- package/dist/components/MultiSelect.cjs.map +1 -1
- package/dist/components/MultiSelect.d.ts.map +1 -1
- package/dist/components/MultiSelect.js +30 -33
- package/dist/components/MultiSelect.js.map +1 -1
- package/dist/components/TimeRange.cjs +29 -37
- package/dist/components/TimeRange.cjs.map +1 -1
- package/dist/components/TimeRange.d.ts.map +1 -1
- package/dist/components/TimeRange.js +30 -38
- package/dist/components/TimeRange.js.map +1 -1
- package/dist/components/TreePickerField.cjs +6 -3
- package/dist/components/TreePickerField.cjs.map +1 -1
- package/dist/components/TreePickerField.d.ts.map +1 -1
- package/dist/components/TreePickerField.js +6 -3
- package/dist/components/TreePickerField.js.map +1 -1
- package/dist/components/icon-menu-picker.cjs +9 -3
- package/dist/components/icon-menu-picker.cjs.map +1 -1
- package/dist/components/icon-menu-picker.d.ts.map +1 -1
- package/dist/components/icon-menu-picker.js +9 -3
- package/dist/components/icon-menu-picker.js.map +1 -1
- package/dist/components/json-schema-form-fields.cjs +80 -2
- package/dist/components/json-schema-form-fields.cjs.map +1 -1
- package/dist/components/json-schema-form-fields.d.ts +15 -0
- package/dist/components/json-schema-form-fields.d.ts.map +1 -1
- package/dist/components/json-schema-form-fields.js +81 -3
- package/dist/components/json-schema-form-fields.js.map +1 -1
- package/dist/components/json-schema-form-refs.cjs +60 -0
- package/dist/components/json-schema-form-refs.cjs.map +1 -0
- package/dist/components/json-schema-form-refs.d.ts +3 -0
- package/dist/components/json-schema-form-refs.d.ts.map +1 -0
- package/dist/components/json-schema-form-refs.js +60 -0
- package/dist/components/json-schema-form-refs.js.map +1 -0
- package/dist/components/json-schema-form-render.cjs +14 -2
- package/dist/components/json-schema-form-render.cjs.map +1 -1
- package/dist/components/json-schema-form-render.d.ts.map +1 -1
- package/dist/components/json-schema-form-render.js +15 -3
- package/dist/components/json-schema-form-render.js.map +1 -1
- package/dist/components/json-schema-form-resolve.cjs +5 -0
- package/dist/components/json-schema-form-resolve.cjs.map +1 -1
- package/dist/components/json-schema-form-resolve.d.ts.map +1 -1
- package/dist/components/json-schema-form-resolve.js +5 -0
- package/dist/components/json-schema-form-resolve.js.map +1 -1
- package/dist/components/json-schema-form-template-menu.cjs +83 -0
- package/dist/components/json-schema-form-template-menu.cjs.map +1 -0
- package/dist/components/json-schema-form-template-menu.d.ts +15 -0
- package/dist/components/json-schema-form-template-menu.d.ts.map +1 -0
- package/dist/components/json-schema-form-template-menu.js +83 -0
- package/dist/components/json-schema-form-template-menu.js.map +1 -0
- package/dist/components/json-schema-form-template.cjs +18 -0
- package/dist/components/json-schema-form-template.cjs.map +1 -0
- package/dist/components/json-schema-form-template.d.ts +13 -0
- package/dist/components/json-schema-form-template.d.ts.map +1 -0
- package/dist/components/json-schema-form-template.js +18 -0
- package/dist/components/json-schema-form-template.js.map +1 -0
- package/dist/components/json-schema-form-types.d.ts +5 -1
- package/dist/components/json-schema-form-types.d.ts.map +1 -1
- package/dist/components.cjs +4 -0
- package/dist/components.cjs.map +1 -1
- package/dist/components.d.ts +3 -0
- package/dist/components.d.ts.map +1 -1
- package/dist/components.js +4 -0
- package/dist/components.js.map +1 -1
- package/dist/data/Clicky.cjs +6 -9
- package/dist/data/Clicky.cjs.map +1 -1
- package/dist/data/Clicky.d.ts.map +1 -1
- package/dist/data/Clicky.js +6 -9
- package/dist/data/Clicky.js.map +1 -1
- package/dist/data/DataTable.cjs +23 -17
- package/dist/data/DataTable.cjs.map +1 -1
- package/dist/data/DataTable.d.ts +7 -1
- package/dist/data/DataTable.d.ts.map +1 -1
- package/dist/data/DataTable.js +24 -18
- package/dist/data/DataTable.js.map +1 -1
- package/dist/data/Gauge.cjs +37 -4
- package/dist/data/Gauge.cjs.map +1 -1
- package/dist/data/Gauge.d.ts +6 -1
- package/dist/data/Gauge.d.ts.map +1 -1
- package/dist/data/Gauge.js +37 -4
- package/dist/data/Gauge.js.map +1 -1
- package/dist/data/TimeseriesCoreBars.cjs +127 -29
- package/dist/data/TimeseriesCoreBars.cjs.map +1 -1
- package/dist/data/TimeseriesCoreBars.d.ts +11 -1
- package/dist/data/TimeseriesCoreBars.d.ts.map +1 -1
- package/dist/data/TimeseriesCoreBars.js +128 -30
- package/dist/data/TimeseriesCoreBars.js.map +1 -1
- package/dist/data/TimeseriesGauge.cjs +105 -47
- package/dist/data/TimeseriesGauge.cjs.map +1 -1
- package/dist/data/TimeseriesGauge.d.ts +6 -1
- package/dist/data/TimeseriesGauge.d.ts.map +1 -1
- package/dist/data/TimeseriesGauge.js +105 -47
- package/dist/data/TimeseriesGauge.js.map +1 -1
- package/dist/data/WorkloadCard.cjs +371 -0
- package/dist/data/WorkloadCard.cjs.map +1 -0
- package/dist/data/WorkloadCard.d.ts +24 -0
- package/dist/data/WorkloadCard.d.ts.map +1 -0
- package/dist/data/WorkloadCard.js +371 -0
- package/dist/data/WorkloadCard.js.map +1 -0
- package/dist/data/WorkloadCard.model.cjs +51 -0
- package/dist/data/WorkloadCard.model.cjs.map +1 -0
- package/dist/data/WorkloadCard.model.d.ts +53 -0
- package/dist/data/WorkloadCard.model.d.ts.map +1 -0
- package/dist/data/WorkloadCard.model.js +51 -0
- package/dist/data/WorkloadCard.model.js.map +1 -0
- package/dist/data/ai/ChatFab.cjs +3 -1
- package/dist/data/ai/ChatFab.cjs.map +1 -1
- package/dist/data/ai/ChatFab.d.ts.map +1 -1
- package/dist/data/ai/ChatFab.js +3 -1
- package/dist/data/ai/ChatFab.js.map +1 -1
- package/dist/data/ai/ChatWindow.cjs +25 -7
- package/dist/data/ai/ChatWindow.cjs.map +1 -1
- package/dist/data/ai/ChatWindow.d.ts +11 -3
- package/dist/data/ai/ChatWindow.d.ts.map +1 -1
- package/dist/data/ai/ChatWindow.js +26 -8
- package/dist/data/ai/ChatWindow.js.map +1 -1
- package/dist/data/ai/chat-window-context.cjs +2 -1
- package/dist/data/ai/chat-window-context.cjs.map +1 -1
- package/dist/data/ai/chat-window-context.d.ts +1 -1
- package/dist/data/ai/chat-window-context.d.ts.map +1 -1
- package/dist/data/ai/chat-window-context.js +2 -1
- package/dist/data/ai/chat-window-context.js.map +1 -1
- package/dist/data/ai/context.cjs.map +1 -1
- package/dist/data/ai/context.d.ts +3 -0
- package/dist/data/ai/context.d.ts.map +1 -1
- package/dist/data/ai/context.js.map +1 -1
- package/dist/data/chat/Chat.cjs +13 -2
- package/dist/data/chat/Chat.cjs.map +1 -1
- package/dist/data/chat/Chat.d.ts +4 -2
- package/dist/data/chat/Chat.d.ts.map +1 -1
- package/dist/data/chat/Chat.js +14 -3
- package/dist/data/chat/Chat.js.map +1 -1
- package/dist/data/chat/Conversation.cjs +47 -2
- package/dist/data/chat/Conversation.cjs.map +1 -1
- package/dist/data/chat/Conversation.d.ts +8 -2
- package/dist/data/chat/Conversation.d.ts.map +1 -1
- package/dist/data/chat/Conversation.js +47 -2
- package/dist/data/chat/Conversation.js.map +1 -1
- package/dist/data/chat/Message.cjs +13 -4
- package/dist/data/chat/Message.cjs.map +1 -1
- package/dist/data/chat/Message.d.ts +4 -2
- package/dist/data/chat/Message.d.ts.map +1 -1
- package/dist/data/chat/Message.js +13 -4
- package/dist/data/chat/Message.js.map +1 -1
- package/dist/data/chat/ToolCall.cjs +9 -4
- package/dist/data/chat/ToolCall.cjs.map +1 -1
- package/dist/data/chat/ToolCall.d.ts +3 -2
- package/dist/data/chat/ToolCall.d.ts.map +1 -1
- package/dist/data/chat/ToolCall.js +9 -4
- package/dist/data/chat/ToolCall.js.map +1 -1
- package/dist/data/chat/index.d.ts +1 -1
- package/dist/data/chat/index.d.ts.map +1 -1
- package/dist/data/chat/types.cjs.map +1 -1
- package/dist/data/chat/types.d.ts +7 -0
- package/dist/data/chat/types.d.ts.map +1 -1
- package/dist/data/chat/types.js.map +1 -1
- package/dist/data/version-info.cjs +3 -3
- package/dist/data/version-info.js +3 -3
- package/dist/data.cjs +7 -0
- package/dist/data.cjs.map +1 -1
- package/dist/data.d.ts +5 -3
- package/dist/data.d.ts.map +1 -1
- package/dist/data.js +8 -1
- package/dist/data.js.map +1 -1
- package/dist/hooks/use-sort.cjs +19 -10
- package/dist/hooks/use-sort.cjs.map +1 -1
- package/dist/hooks/use-sort.d.ts +3 -0
- package/dist/hooks/use-sort.d.ts.map +1 -1
- package/dist/hooks/use-sort.js +19 -10
- package/dist/hooks/use-sort.js.map +1 -1
- package/dist/index.cjs +11 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -1
- package/dist/layout/AppShell.cjs +6 -10
- package/dist/layout/AppShell.cjs.map +1 -1
- package/dist/layout/AppShell.d.ts +2 -0
- package/dist/layout/AppShell.d.ts.map +1 -1
- package/dist/layout/AppShell.js +6 -10
- package/dist/layout/AppShell.js.map +1 -1
- package/dist/overlay/DropdownMenu.cjs +50 -38
- package/dist/overlay/DropdownMenu.cjs.map +1 -1
- package/dist/overlay/DropdownMenu.d.ts +5 -1
- package/dist/overlay/DropdownMenu.d.ts.map +1 -1
- package/dist/overlay/DropdownMenu.js +50 -38
- package/dist/overlay/DropdownMenu.js.map +1 -1
- package/dist/overlay/HoverCard.cjs +7 -2
- package/dist/overlay/HoverCard.cjs.map +1 -1
- package/dist/overlay/HoverCard.d.ts.map +1 -1
- package/dist/overlay/HoverCard.js +7 -2
- package/dist/overlay/HoverCard.js.map +1 -1
- package/dist/overlay/Modal.cjs +20 -17
- package/dist/overlay/Modal.cjs.map +1 -1
- package/dist/overlay/Modal.d.ts.map +1 -1
- package/dist/overlay/Modal.js +21 -18
- package/dist/overlay/Modal.js.map +1 -1
- package/dist/overlay/Toast.cjs +9 -1
- package/dist/overlay/Toast.cjs.map +1 -1
- package/dist/overlay/Toast.d.ts.map +1 -1
- package/dist/overlay/Toast.js +9 -1
- package/dist/overlay/Toast.js.map +1 -1
- package/dist/overlay/modalStack.cjs +53 -1
- package/dist/overlay/modalStack.cjs.map +1 -1
- package/dist/overlay/modalStack.d.ts +12 -0
- package/dist/overlay/modalStack.d.ts.map +1 -1
- package/dist/overlay/modalStack.js +54 -2
- package/dist/overlay/modalStack.js.map +1 -1
- package/dist/overlay/zIndex.cjs +20 -0
- package/dist/overlay/zIndex.cjs.map +1 -0
- package/dist/overlay/zIndex.d.ts +39 -0
- package/dist/overlay/zIndex.d.ts.map +1 -0
- package/dist/overlay/zIndex.js +20 -0
- package/dist/overlay/zIndex.js.map +1 -0
- package/dist/rpc/AcceptPicker.cjs +28 -26
- package/dist/rpc/AcceptPicker.cjs.map +1 -1
- package/dist/rpc/AcceptPicker.d.ts.map +1 -1
- package/dist/rpc/AcceptPicker.js +29 -27
- package/dist/rpc/AcceptPicker.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { useMemo, useRef, useState, useLayoutEffect, useCallback, useEffect, createContext, useContext, isValidElement, cloneElement } from "react";
|
|
3
|
+
import { useMergeRefs, FloatingPortal, FloatingFocusManager, useFloating, autoUpdate, offset, flip, shift, useInteractions, useClick, useDismiss, useRole } from "@floating-ui/react";
|
|
3
4
|
import { FilterPill } from "../data/FilterPill.js";
|
|
4
5
|
import { isFilterBarFilterActive, clearFilterBarFilter } from "./filter-bar-utils.js";
|
|
5
6
|
import { Icon, LabelIcon } from "../data/Icon.js";
|
|
6
7
|
import { formatDateTimeRelative } from "../data/cells/timestamp-format.js";
|
|
7
8
|
import { cn } from "../lib/utils.js";
|
|
9
|
+
import { useFloatingZIndex, useEscapeLayer } from "../overlay/modalStack.js";
|
|
8
10
|
import { Button } from "./button.js";
|
|
9
11
|
import { Combobox } from "./Combobox.js";
|
|
10
12
|
import { DateTimePicker } from "./DateTimePicker.js";
|
|
@@ -260,7 +262,6 @@ function OverflowFiltersMenu({
|
|
|
260
262
|
activeHidden,
|
|
261
263
|
onApply
|
|
262
264
|
}) {
|
|
263
|
-
const rootRef = useRef(null);
|
|
264
265
|
const [open, setOpen] = useState(false);
|
|
265
266
|
const [stagedValues, setStagedValues] = useState({});
|
|
266
267
|
const hasHidden = filters.length > 0;
|
|
@@ -268,15 +269,19 @@ function OverflowFiltersMenu({
|
|
|
268
269
|
() => filters.map((filter) => filter.key).join("\0"),
|
|
269
270
|
[filters]
|
|
270
271
|
);
|
|
271
|
-
const
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
272
|
+
const { refs, floatingStyles, context, floatingZ, getReferenceProps, getFloatingProps } = useAnchoredPopup(
|
|
273
|
+
open,
|
|
274
|
+
(next) => {
|
|
275
|
+
setStagedValues(createFilterValueMap(filters));
|
|
276
|
+
setOpen(next);
|
|
277
|
+
},
|
|
278
|
+
"bottom-end"
|
|
279
|
+
);
|
|
275
280
|
const closeOverflowMenu = useCallback(() => {
|
|
276
281
|
setStagedValues(createFilterValueMap(filters));
|
|
277
282
|
setOpen(false);
|
|
278
283
|
}, [filters]);
|
|
279
|
-
|
|
284
|
+
const setTriggerRef = useMergeRefs([refs.setReference, triggerRef]);
|
|
280
285
|
useEffect(() => {
|
|
281
286
|
if (!hasHidden) closeOverflowMenu();
|
|
282
287
|
}, [closeOverflowMenu, hasHidden]);
|
|
@@ -297,47 +302,39 @@ function OverflowFiltersMenu({
|
|
|
297
302
|
return /* @__PURE__ */ jsxs(
|
|
298
303
|
"div",
|
|
299
304
|
{
|
|
300
|
-
|
|
301
|
-
className: cn("relative shrink-0", !hasHidden && "invisible pointer-events-none"),
|
|
305
|
+
className: cn("inline-flex shrink-0", !hasHidden && "invisible pointer-events-none"),
|
|
302
306
|
"aria-hidden": !hasHidden || void 0,
|
|
303
307
|
children: [
|
|
304
308
|
/* @__PURE__ */ jsxs(
|
|
305
309
|
Button,
|
|
306
310
|
{
|
|
307
|
-
ref:
|
|
311
|
+
ref: setTriggerRef,
|
|
308
312
|
type: "button",
|
|
309
313
|
variant: "outline",
|
|
310
314
|
size: "sm",
|
|
311
315
|
"aria-label": "More filters",
|
|
312
|
-
"aria-haspopup": "dialog",
|
|
313
|
-
"aria-expanded": hasHidden ? open : false,
|
|
314
316
|
tabIndex: hasHidden ? 0 : -1,
|
|
315
317
|
title: hasHidden ? "More filters" : void 0,
|
|
316
|
-
onClick: () => {
|
|
317
|
-
if (!hasHidden) return;
|
|
318
|
-
if (open) {
|
|
319
|
-
closeOverflowMenu();
|
|
320
|
-
} else {
|
|
321
|
-
openOverflowMenu();
|
|
322
|
-
}
|
|
323
|
-
},
|
|
324
318
|
className: cn(
|
|
325
319
|
"h-8 min-w-0 gap-1.5 px-2 text-xs font-normal",
|
|
326
320
|
activeHidden > 0 && "border-primary/40 text-primary"
|
|
327
321
|
),
|
|
322
|
+
...getReferenceProps(),
|
|
328
323
|
children: [
|
|
329
324
|
/* @__PURE__ */ jsx(Icon, { icon: UiFilter, className: "text-[14px]" }),
|
|
330
325
|
activeHidden > 0 && /* @__PURE__ */ jsx("span", { className: "rounded-full bg-muted px-1.5 text-[10px] font-medium text-muted-foreground", children: activeHidden })
|
|
331
326
|
]
|
|
332
327
|
}
|
|
333
328
|
),
|
|
334
|
-
hasHidden && open && /* @__PURE__ */ jsxs(
|
|
329
|
+
hasHidden && open && /* @__PURE__ */ jsx(FloatingPortal, { children: /* @__PURE__ */ jsx(FloatingFocusManager, { context, modal: false, children: /* @__PURE__ */ jsxs(
|
|
335
330
|
"div",
|
|
336
331
|
{
|
|
332
|
+
ref: refs.setFloating,
|
|
337
333
|
role: "dialog",
|
|
338
334
|
"aria-label": "Overflow filters",
|
|
339
|
-
|
|
340
|
-
|
|
335
|
+
style: { ...floatingStyles, zIndex: floatingZ },
|
|
336
|
+
className: "flex max-h-[min(34rem,calc(100vh-2rem))] w-[min(34rem,calc(100vw-2rem))] flex-col overflow-hidden rounded-md border border-border bg-popover p-2 text-popover-foreground shadow-lg shadow-black/10",
|
|
337
|
+
...getFloatingProps(),
|
|
341
338
|
children: [
|
|
342
339
|
/* @__PURE__ */ jsxs("div", { className: "mb-2 flex items-center justify-between gap-2 px-1", children: [
|
|
343
340
|
/* @__PURE__ */ jsx("div", { className: "text-[10px] font-medium uppercase tracking-wide text-muted-foreground", children: "Filters" }),
|
|
@@ -365,7 +362,7 @@ function OverflowFiltersMenu({
|
|
|
365
362
|
)
|
|
366
363
|
] })
|
|
367
364
|
] }),
|
|
368
|
-
/* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1 divide-y divide-border/70 overflow-y-auto rounded-md border border-border/70
|
|
365
|
+
/* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1 divide-y divide-border/70 overflow-y-auto rounded-md border border-border/70", children: stagedFilters.map((filter) => {
|
|
369
366
|
const active = isFilterBarFilterActive(filter);
|
|
370
367
|
return /* @__PURE__ */ jsxs(
|
|
371
368
|
"div",
|
|
@@ -440,7 +437,7 @@ function OverflowFiltersMenu({
|
|
|
440
437
|
] })
|
|
441
438
|
]
|
|
442
439
|
}
|
|
443
|
-
)
|
|
440
|
+
) }) })
|
|
444
441
|
]
|
|
445
442
|
}
|
|
446
443
|
);
|
|
@@ -852,10 +849,8 @@ function LookupMultiFilterField({
|
|
|
852
849
|
);
|
|
853
850
|
}
|
|
854
851
|
function NumberFilterField({ filter, grow }) {
|
|
855
|
-
const rootRef = useRef(null);
|
|
856
|
-
const triggerRef = useRef(null);
|
|
857
852
|
const [open, setOpen] = useState(false);
|
|
858
|
-
|
|
853
|
+
const popup = useAnchoredPopup(open, setOpen);
|
|
859
854
|
const bounds = resolveNumberFilterBounds(filter);
|
|
860
855
|
const [draft, setDraft] = useDebouncedNumberDraft(filter.value, filter.onChange);
|
|
861
856
|
const sliderMin = clampNumber(parseFilterNumber(draft.min) ?? bounds.min, bounds.min, bounds.max);
|
|
@@ -866,10 +861,9 @@ function NumberFilterField({ filter, grow }) {
|
|
|
866
861
|
return /* @__PURE__ */ jsxs(
|
|
867
862
|
"div",
|
|
868
863
|
{
|
|
869
|
-
ref: rootRef,
|
|
870
864
|
title: filter.description,
|
|
871
865
|
className: cn(
|
|
872
|
-
"
|
|
866
|
+
"inline-flex min-w-0",
|
|
873
867
|
grow ? "min-w-[8rem] max-w-[12rem] flex-1" : "shrink-0",
|
|
874
868
|
filter.disabled && "opacity-60",
|
|
875
869
|
filter.className
|
|
@@ -878,20 +872,18 @@ function NumberFilterField({ filter, grow }) {
|
|
|
878
872
|
/* @__PURE__ */ jsxs(
|
|
879
873
|
Button,
|
|
880
874
|
{
|
|
881
|
-
ref:
|
|
875
|
+
ref: popup.refs.setReference,
|
|
882
876
|
type: "button",
|
|
883
877
|
variant: "outline",
|
|
884
878
|
size: "sm",
|
|
885
879
|
"aria-label": `${filter.label} filter`,
|
|
886
|
-
"aria-haspopup": "dialog",
|
|
887
|
-
"aria-expanded": open,
|
|
888
880
|
disabled: filter.disabled,
|
|
889
|
-
onClick: () => setOpen((current) => !current),
|
|
890
881
|
className: cn(
|
|
891
882
|
"min-w-0 gap-2 font-normal",
|
|
892
883
|
grow ? "w-full max-w-[12rem] justify-between" : "w-auto max-w-[9.5rem] px-2.5",
|
|
893
884
|
summary === filter.label && "text-muted-foreground"
|
|
894
885
|
),
|
|
886
|
+
...popup.getReferenceProps(),
|
|
895
887
|
children: [
|
|
896
888
|
/* @__PURE__ */ jsx(LabelIcon, { icon: filter.icon, className: "text-[14px] text-muted-foreground" }),
|
|
897
889
|
/* @__PURE__ */ jsx("span", { className: "truncate", children: summary }),
|
|
@@ -899,88 +891,99 @@ function NumberFilterField({ filter, grow }) {
|
|
|
899
891
|
]
|
|
900
892
|
}
|
|
901
893
|
),
|
|
902
|
-
open && /* @__PURE__ */
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
},
|
|
914
|
-
disabled: !String(draft.min ?? "").trim() && !String(draft.max ?? "").trim(),
|
|
915
|
-
children: "Clear all"
|
|
916
|
-
}
|
|
917
|
-
)
|
|
918
|
-
] }),
|
|
919
|
-
/* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
920
|
-
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
921
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-[11px] text-muted-foreground", children: [
|
|
922
|
-
/* @__PURE__ */ jsx("span", { children: formatNumberValue(bounds.min, filter) }),
|
|
923
|
-
/* @__PURE__ */ jsx("span", { children: formatNumberValue(bounds.max, filter) })
|
|
924
|
-
] }),
|
|
925
|
-
/* @__PURE__ */ jsx("div", { className: "relative h-6", children: /* @__PURE__ */ jsx(
|
|
926
|
-
RangeSlider,
|
|
927
|
-
{
|
|
928
|
-
min: bounds.min,
|
|
929
|
-
max: bounds.max,
|
|
930
|
-
step: bounds.step,
|
|
931
|
-
value: [activeMin, activeMax],
|
|
932
|
-
ariaLabelMin: `${filter.label} minimum slider`,
|
|
933
|
-
ariaLabelMax: `${filter.label} maximum slider`,
|
|
934
|
-
onChange: ([nextMin, nextMax]) => setDraft(numberFilterValueFromSlider([nextMin, nextMax], bounds))
|
|
935
|
-
}
|
|
936
|
-
) })
|
|
937
|
-
] }),
|
|
938
|
-
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
|
|
939
|
-
/* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
940
|
-
/* @__PURE__ */ jsx("label", { className: "text-[10px] text-muted-foreground", children: "Min" }),
|
|
894
|
+
open && /* @__PURE__ */ jsx(FloatingPortal, { children: /* @__PURE__ */ jsx(FloatingFocusManager, { context: popup.context, modal: false, children: /* @__PURE__ */ jsxs(
|
|
895
|
+
"div",
|
|
896
|
+
{
|
|
897
|
+
ref: popup.refs.setFloating,
|
|
898
|
+
role: "dialog",
|
|
899
|
+
"aria-label": filter.label,
|
|
900
|
+
style: { ...popup.floatingStyles, zIndex: popup.floatingZ },
|
|
901
|
+
className: "min-w-[18rem] max-w-[22rem] rounded-md border border-border bg-popover p-3 text-popover-foreground shadow-lg shadow-black/5",
|
|
902
|
+
...popup.getFloatingProps(),
|
|
903
|
+
children: [
|
|
904
|
+
/* @__PURE__ */ jsxs("div", { className: "mb-3 flex items-center justify-between gap-2", children: [
|
|
905
|
+
/* @__PURE__ */ jsx("div", { className: "text-[10px] font-medium uppercase tracking-wide text-muted-foreground", children: filter.label }),
|
|
941
906
|
/* @__PURE__ */ jsx(
|
|
942
|
-
"
|
|
907
|
+
"button",
|
|
943
908
|
{
|
|
944
|
-
type: "
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
normalizeNumberFilterValue(
|
|
953
|
-
{ min: event.target.value, max: draft.max ?? "" },
|
|
954
|
-
"min-input"
|
|
955
|
-
)
|
|
956
|
-
)
|
|
909
|
+
type: "button",
|
|
910
|
+
className: "text-[10px] text-primary disabled:text-muted-foreground",
|
|
911
|
+
onClick: () => {
|
|
912
|
+
setDraft({});
|
|
913
|
+
filter.onChange({});
|
|
914
|
+
},
|
|
915
|
+
disabled: !String(draft.min ?? "").trim() && !String(draft.max ?? "").trim(),
|
|
916
|
+
children: "Clear all"
|
|
957
917
|
}
|
|
958
918
|
)
|
|
959
919
|
] }),
|
|
960
|
-
/* @__PURE__ */ jsxs("div", { className: "space-y-
|
|
961
|
-
/* @__PURE__ */
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
920
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
921
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
922
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-[11px] text-muted-foreground", children: [
|
|
923
|
+
/* @__PURE__ */ jsx("span", { children: formatNumberValue(bounds.min, filter) }),
|
|
924
|
+
/* @__PURE__ */ jsx("span", { children: formatNumberValue(bounds.max, filter) })
|
|
925
|
+
] }),
|
|
926
|
+
/* @__PURE__ */ jsx("div", { className: "relative h-6", children: /* @__PURE__ */ jsx(
|
|
927
|
+
RangeSlider,
|
|
928
|
+
{
|
|
929
|
+
min: bounds.min,
|
|
930
|
+
max: bounds.max,
|
|
931
|
+
step: bounds.step,
|
|
932
|
+
value: [activeMin, activeMax],
|
|
933
|
+
ariaLabelMin: `${filter.label} minimum slider`,
|
|
934
|
+
ariaLabelMax: `${filter.label} maximum slider`,
|
|
935
|
+
onChange: ([nextMin, nextMax]) => setDraft(numberFilterValueFromSlider([nextMin, nextMax], bounds))
|
|
936
|
+
}
|
|
937
|
+
) })
|
|
938
|
+
] }),
|
|
939
|
+
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
|
|
940
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
941
|
+
/* @__PURE__ */ jsx("label", { className: "text-[10px] text-muted-foreground", children: "Min" }),
|
|
942
|
+
/* @__PURE__ */ jsx(
|
|
943
|
+
"input",
|
|
944
|
+
{
|
|
945
|
+
type: "number",
|
|
946
|
+
inputMode: "decimal",
|
|
947
|
+
step: bounds.step,
|
|
948
|
+
"aria-label": `${filter.label} minimum`,
|
|
949
|
+
className: "h-8 w-full rounded-md border border-input bg-background px-2 text-xs outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
950
|
+
...filter.minPlaceholder !== void 0 ? { placeholder: filter.minPlaceholder } : {},
|
|
951
|
+
value: draft.min ?? "",
|
|
952
|
+
onChange: (event) => setDraft(
|
|
953
|
+
normalizeNumberFilterValue(
|
|
954
|
+
{ min: event.target.value, max: draft.max ?? "" },
|
|
955
|
+
"min-input"
|
|
956
|
+
)
|
|
957
|
+
)
|
|
958
|
+
}
|
|
977
959
|
)
|
|
978
|
-
}
|
|
979
|
-
|
|
960
|
+
] }),
|
|
961
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
962
|
+
/* @__PURE__ */ jsx("label", { className: "text-[10px] text-muted-foreground", children: "Max" }),
|
|
963
|
+
/* @__PURE__ */ jsx(
|
|
964
|
+
"input",
|
|
965
|
+
{
|
|
966
|
+
type: "number",
|
|
967
|
+
inputMode: "decimal",
|
|
968
|
+
step: bounds.step,
|
|
969
|
+
"aria-label": `${filter.label} maximum`,
|
|
970
|
+
className: "h-8 w-full rounded-md border border-input bg-background px-2 text-xs outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
971
|
+
...filter.maxPlaceholder !== void 0 ? { placeholder: filter.maxPlaceholder } : {},
|
|
972
|
+
value: draft.max ?? "",
|
|
973
|
+
onChange: (event) => setDraft(
|
|
974
|
+
normalizeNumberFilterValue(
|
|
975
|
+
{ min: draft.min ?? "", max: event.target.value },
|
|
976
|
+
"max-input"
|
|
977
|
+
)
|
|
978
|
+
)
|
|
979
|
+
}
|
|
980
|
+
)
|
|
981
|
+
] })
|
|
982
|
+
] })
|
|
980
983
|
] })
|
|
981
|
-
]
|
|
982
|
-
|
|
983
|
-
|
|
984
|
+
]
|
|
985
|
+
}
|
|
986
|
+
) }) })
|
|
984
987
|
]
|
|
985
988
|
}
|
|
986
989
|
);
|
|
@@ -1089,14 +1092,16 @@ function NumberFilterPanel({
|
|
|
1089
1092
|
}
|
|
1090
1093
|
);
|
|
1091
1094
|
}
|
|
1095
|
+
const MULTI_FILTER_OPTION_ROW_HEIGHT = 30;
|
|
1096
|
+
const MULTI_FILTER_OPTION_LIST_HEIGHT = 288;
|
|
1097
|
+
const MULTI_FILTER_OPTION_OVERSCAN = 6;
|
|
1092
1098
|
function MultiFilterField({ filter, grow }) {
|
|
1093
|
-
const rootRef = useRef(null);
|
|
1094
|
-
const triggerRef = useRef(null);
|
|
1095
1099
|
const [open, setOpen] = useState(false);
|
|
1096
1100
|
const [optionQuery, setOptionQuery] = useState("");
|
|
1101
|
+
const [optionScrollTop, setOptionScrollTop] = useState(0);
|
|
1097
1102
|
const [searchOptions, setSearchOptions] = useState([]);
|
|
1098
1103
|
const [draft, setDraft] = useDebouncedMultiDraft(filter.value, filter.onChange);
|
|
1099
|
-
|
|
1104
|
+
const popup = useAnchoredPopup(open, setOpen);
|
|
1100
1105
|
const onSearch = filter.onSearch;
|
|
1101
1106
|
useEffect(() => {
|
|
1102
1107
|
if (!onSearch) return;
|
|
@@ -1139,6 +1144,25 @@ function MultiFilterField({ filter, grow }) {
|
|
|
1139
1144
|
(option) => multiSelectOptionText(option).toLowerCase().includes(lowered)
|
|
1140
1145
|
);
|
|
1141
1146
|
}, [baseOptions, searchOptions, optionQuery, onSearch, draft]);
|
|
1147
|
+
useEffect(() => {
|
|
1148
|
+
setOptionScrollTop(0);
|
|
1149
|
+
}, [optionQuery]);
|
|
1150
|
+
const optionWindow = useMemo(() => {
|
|
1151
|
+
const visibleRows = Math.ceil(MULTI_FILTER_OPTION_LIST_HEIGHT / MULTI_FILTER_OPTION_ROW_HEIGHT);
|
|
1152
|
+
const start = Math.max(
|
|
1153
|
+
0,
|
|
1154
|
+
Math.floor(optionScrollTop / MULTI_FILTER_OPTION_ROW_HEIGHT) - MULTI_FILTER_OPTION_OVERSCAN
|
|
1155
|
+
);
|
|
1156
|
+
const end = Math.min(
|
|
1157
|
+
visibleOptions.length,
|
|
1158
|
+
start + visibleRows + MULTI_FILTER_OPTION_OVERSCAN * 2
|
|
1159
|
+
);
|
|
1160
|
+
return {
|
|
1161
|
+
options: visibleOptions.slice(start, end),
|
|
1162
|
+
totalHeight: visibleOptions.length * MULTI_FILTER_OPTION_ROW_HEIGHT,
|
|
1163
|
+
top: start * MULTI_FILTER_OPTION_ROW_HEIGHT
|
|
1164
|
+
};
|
|
1165
|
+
}, [optionScrollTop, visibleOptions]);
|
|
1142
1166
|
const trimmedQuery = optionQuery.trim();
|
|
1143
1167
|
const canAddCustom = allowCustomValue && trimmedQuery !== "" && !visibleOptions.some((o) => o.value === trimmedQuery);
|
|
1144
1168
|
const addCustom = () => {
|
|
@@ -1149,10 +1173,9 @@ function MultiFilterField({ filter, grow }) {
|
|
|
1149
1173
|
return /* @__PURE__ */ jsxs(
|
|
1150
1174
|
"div",
|
|
1151
1175
|
{
|
|
1152
|
-
ref: rootRef,
|
|
1153
1176
|
title: filter.description,
|
|
1154
1177
|
className: cn(
|
|
1155
|
-
"
|
|
1178
|
+
"inline-flex min-w-0",
|
|
1156
1179
|
grow ? "min-w-[8rem] max-w-[12rem] flex-1" : "shrink-0",
|
|
1157
1180
|
filter.disabled && "opacity-60",
|
|
1158
1181
|
filter.className
|
|
@@ -1161,20 +1184,18 @@ function MultiFilterField({ filter, grow }) {
|
|
|
1161
1184
|
/* @__PURE__ */ jsxs(
|
|
1162
1185
|
Button,
|
|
1163
1186
|
{
|
|
1164
|
-
ref:
|
|
1187
|
+
ref: popup.refs.setReference,
|
|
1165
1188
|
type: "button",
|
|
1166
1189
|
variant: "outline",
|
|
1167
1190
|
size: "sm",
|
|
1168
1191
|
"aria-label": `${filter.label} filter`,
|
|
1169
|
-
"aria-haspopup": "dialog",
|
|
1170
|
-
"aria-expanded": open,
|
|
1171
1192
|
disabled: filter.disabled,
|
|
1172
|
-
onClick: () => setOpen((current) => !current),
|
|
1173
1193
|
className: cn(
|
|
1174
1194
|
"min-w-0 gap-2 font-normal",
|
|
1175
1195
|
grow ? "w-full max-w-[12rem] justify-between" : "w-auto max-w-[8.5rem] px-2.5",
|
|
1176
1196
|
summary === filter.label && "text-muted-foreground"
|
|
1177
1197
|
),
|
|
1198
|
+
...popup.getReferenceProps(),
|
|
1178
1199
|
children: [
|
|
1179
1200
|
/* @__PURE__ */ jsx(LabelIcon, { icon: filter.icon, className: "text-[14px] text-muted-foreground" }),
|
|
1180
1201
|
/* @__PURE__ */ jsx("span", { className: "truncate", children: summary }),
|
|
@@ -1182,97 +1203,118 @@ function MultiFilterField({ filter, grow }) {
|
|
|
1182
1203
|
]
|
|
1183
1204
|
}
|
|
1184
1205
|
),
|
|
1185
|
-
open && /* @__PURE__ */
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1206
|
+
open && /* @__PURE__ */ jsx(FloatingPortal, { children: /* @__PURE__ */ jsx(FloatingFocusManager, { context: popup.context, modal: false, children: /* @__PURE__ */ jsxs(
|
|
1207
|
+
"div",
|
|
1208
|
+
{
|
|
1209
|
+
ref: popup.refs.setFloating,
|
|
1210
|
+
role: "dialog",
|
|
1211
|
+
"aria-label": filter.label,
|
|
1212
|
+
style: { ...popup.floatingStyles, zIndex: popup.floatingZ },
|
|
1213
|
+
className: "min-w-[18rem] max-w-[22rem] rounded-md border border-border bg-popover p-2 text-popover-foreground shadow-lg shadow-black/5",
|
|
1214
|
+
...popup.getFloatingProps(),
|
|
1215
|
+
children: [
|
|
1216
|
+
/* @__PURE__ */ jsxs("div", { className: "mb-2 flex items-center justify-between gap-2", children: [
|
|
1217
|
+
/* @__PURE__ */ jsx("div", { className: "text-[10px] font-medium uppercase tracking-wide text-muted-foreground", children: filter.label }),
|
|
1218
|
+
/* @__PURE__ */ jsx(
|
|
1219
|
+
"button",
|
|
1220
|
+
{
|
|
1221
|
+
type: "button",
|
|
1222
|
+
className: "text-[10px] text-primary disabled:text-muted-foreground",
|
|
1223
|
+
onClick: () => setDraft({}),
|
|
1224
|
+
disabled: Object.keys(draft).length === 0,
|
|
1225
|
+
children: "Clear all"
|
|
1226
|
+
}
|
|
1227
|
+
)
|
|
1228
|
+
] }),
|
|
1229
|
+
showOptionFilter && /* @__PURE__ */ jsxs("div", { className: "mb-2 flex items-center gap-2 rounded-md border border-input bg-background px-2", children: [
|
|
1230
|
+
/* @__PURE__ */ jsx(Icon, { icon: UiSearch, className: "shrink-0 text-muted-foreground" }),
|
|
1231
|
+
/* @__PURE__ */ jsx(
|
|
1232
|
+
"input",
|
|
1233
|
+
{
|
|
1234
|
+
type: "search",
|
|
1235
|
+
"aria-label": `Filter ${filter.label} options`,
|
|
1236
|
+
className: "h-8 min-w-0 flex-1 bg-transparent text-sm outline-none placeholder:text-muted-foreground",
|
|
1237
|
+
placeholder: `Filter ${filter.label.toLowerCase()}`,
|
|
1238
|
+
value: optionQuery,
|
|
1239
|
+
onChange: (event) => setOptionQuery(event.target.value)
|
|
1240
|
+
}
|
|
1241
|
+
)
|
|
1242
|
+
] }),
|
|
1243
|
+
/* @__PURE__ */ jsxs(
|
|
1218
1244
|
"div",
|
|
1219
1245
|
{
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1246
|
+
className: "max-h-72 overflow-auto",
|
|
1247
|
+
onScroll: (event) => setOptionScrollTop(event.currentTarget.scrollTop),
|
|
1248
|
+
children: [
|
|
1249
|
+
/* @__PURE__ */ jsx("div", { className: "relative", style: { height: optionWindow.totalHeight }, children: /* @__PURE__ */ jsx("div", { style: { transform: `translateY(${optionWindow.top}px)` }, children: optionWindow.options.map((option) => {
|
|
1250
|
+
const mode = draft[option.value] ?? "neutral";
|
|
1251
|
+
const title = option.title ?? multiSelectOptionText(option);
|
|
1252
|
+
return /* @__PURE__ */ jsx(
|
|
1253
|
+
"div",
|
|
1254
|
+
{
|
|
1255
|
+
role: "button",
|
|
1256
|
+
tabIndex: 0,
|
|
1257
|
+
"data-filter-option": option.value,
|
|
1258
|
+
className: "box-border flex items-center rounded-md px-1.5 py-0.5 hover:bg-accent/50 focus-visible:bg-accent/50 focus-visible:outline-none",
|
|
1259
|
+
style: { height: MULTI_FILTER_OPTION_ROW_HEIGHT },
|
|
1260
|
+
onClick: () => setDraft(updateMultiFilterValue(draft, option.value, nextFilterMode(mode))),
|
|
1261
|
+
onKeyDown: (event) => {
|
|
1262
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
1263
|
+
event.preventDefault();
|
|
1264
|
+
setDraft(
|
|
1265
|
+
updateMultiFilterValue(draft, option.value, nextFilterMode(mode))
|
|
1266
|
+
);
|
|
1267
|
+
}
|
|
1268
|
+
},
|
|
1269
|
+
children: /* @__PURE__ */ jsx(
|
|
1270
|
+
FilterPill,
|
|
1271
|
+
{
|
|
1272
|
+
className: "w-full justify-between",
|
|
1273
|
+
label: option.label,
|
|
1274
|
+
mode,
|
|
1275
|
+
title,
|
|
1276
|
+
togglePosition: "right",
|
|
1277
|
+
onModeChange: (next) => setDraft(updateMultiFilterValue(draft, option.value, next))
|
|
1278
|
+
}
|
|
1279
|
+
)
|
|
1280
|
+
},
|
|
1281
|
+
option.value
|
|
1282
|
+
);
|
|
1283
|
+
}) }) }),
|
|
1284
|
+
canAddCustom && /* @__PURE__ */ jsxs(
|
|
1285
|
+
"div",
|
|
1286
|
+
{
|
|
1287
|
+
role: "button",
|
|
1288
|
+
tabIndex: 0,
|
|
1289
|
+
"data-filter-add-custom": trimmedQuery,
|
|
1290
|
+
className: "rounded-md px-2 py-1 text-sm text-primary hover:bg-accent/50 focus-visible:bg-accent/50 focus-visible:outline-none",
|
|
1291
|
+
onClick: addCustom,
|
|
1292
|
+
onKeyDown: (event) => {
|
|
1293
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
1294
|
+
event.preventDefault();
|
|
1295
|
+
addCustom();
|
|
1296
|
+
}
|
|
1297
|
+
},
|
|
1298
|
+
children: [
|
|
1299
|
+
"Add “",
|
|
1300
|
+
trimmedQuery,
|
|
1301
|
+
"”"
|
|
1302
|
+
]
|
|
1303
|
+
}
|
|
1304
|
+
),
|
|
1305
|
+
visibleOptions.length === 0 && !canAddCustom && /* @__PURE__ */ jsx("div", { className: "px-2 py-3 text-sm text-muted-foreground", children: "No options found" })
|
|
1306
|
+
]
|
|
1307
|
+
}
|
|
1308
|
+
),
|
|
1309
|
+
moreCount > 0 && !optionQuery.trim() && /* @__PURE__ */ jsxs("div", { className: "mt-2 px-1.5 text-[11px] text-muted-foreground", children: [
|
|
1310
|
+
"… and ",
|
|
1311
|
+
moreCount.toLocaleString(),
|
|
1312
|
+
" more",
|
|
1313
|
+
onSearch ? " — type to search all" : ""
|
|
1314
|
+
] })
|
|
1315
|
+
]
|
|
1316
|
+
}
|
|
1317
|
+
) }) })
|
|
1276
1318
|
]
|
|
1277
1319
|
}
|
|
1278
1320
|
);
|
|
@@ -1559,14 +1601,12 @@ function NestedMultiFilterField({
|
|
|
1559
1601
|
filter,
|
|
1560
1602
|
grow
|
|
1561
1603
|
}) {
|
|
1562
|
-
const rootRef = useRef(null);
|
|
1563
|
-
const triggerRef = useRef(null);
|
|
1564
1604
|
const [open, setOpen] = useState(false);
|
|
1565
1605
|
const [activeGroup, setActiveGroup] = useState(null);
|
|
1566
1606
|
const [draft, setDraft] = useDebouncedMultiDraft(filter.value, filter.onChange);
|
|
1567
|
-
|
|
1568
|
-
setOpen(
|
|
1569
|
-
setActiveGroup(null);
|
|
1607
|
+
const popup = useAnchoredPopup(open, (next) => {
|
|
1608
|
+
setOpen(next);
|
|
1609
|
+
if (!next) setActiveGroup(null);
|
|
1570
1610
|
});
|
|
1571
1611
|
const summary = summarizeMultiFilter(filter.label, draft);
|
|
1572
1612
|
const groups = filter.groups;
|
|
@@ -1606,10 +1646,9 @@ function NestedMultiFilterField({
|
|
|
1606
1646
|
return /* @__PURE__ */ jsxs(
|
|
1607
1647
|
"div",
|
|
1608
1648
|
{
|
|
1609
|
-
ref: rootRef,
|
|
1610
1649
|
title: filter.description,
|
|
1611
1650
|
className: cn(
|
|
1612
|
-
"
|
|
1651
|
+
"inline-flex min-w-0",
|
|
1613
1652
|
grow ? "min-w-[8rem] max-w-[12rem] flex-1" : "shrink-0",
|
|
1614
1653
|
filter.disabled && "opacity-60",
|
|
1615
1654
|
filter.className
|
|
@@ -1618,41 +1657,33 @@ function NestedMultiFilterField({
|
|
|
1618
1657
|
/* @__PURE__ */ jsxs(
|
|
1619
1658
|
Button,
|
|
1620
1659
|
{
|
|
1621
|
-
ref:
|
|
1660
|
+
ref: popup.refs.setReference,
|
|
1622
1661
|
type: "button",
|
|
1623
1662
|
variant: "outline",
|
|
1624
1663
|
size: "sm",
|
|
1625
1664
|
"aria-label": `${filter.label} filter`,
|
|
1626
|
-
"aria-haspopup": "dialog",
|
|
1627
|
-
"aria-expanded": open,
|
|
1628
1665
|
disabled: filter.disabled,
|
|
1629
|
-
onClick: () => {
|
|
1630
|
-
setOpen((current) => !current);
|
|
1631
|
-
if (open) setActiveGroup(null);
|
|
1632
|
-
},
|
|
1633
1666
|
className: cn(
|
|
1634
1667
|
"min-w-0 gap-2 font-normal",
|
|
1635
1668
|
grow ? "w-full max-w-[12rem] justify-between" : "w-auto max-w-[8.5rem] px-2.5",
|
|
1636
1669
|
summary === filter.label && "text-muted-foreground"
|
|
1637
1670
|
),
|
|
1671
|
+
...popup.getReferenceProps(),
|
|
1638
1672
|
children: [
|
|
1639
1673
|
/* @__PURE__ */ jsx("span", { className: "truncate", children: summary }),
|
|
1640
1674
|
/* @__PURE__ */ jsx(Icon, { icon: open ? UiChevronUp : UiChevronDown, className: "text-muted-foreground" })
|
|
1641
1675
|
]
|
|
1642
1676
|
}
|
|
1643
1677
|
),
|
|
1644
|
-
open && /* @__PURE__ */ jsxs(
|
|
1678
|
+
open && /* @__PURE__ */ jsx(FloatingPortal, { children: /* @__PURE__ */ jsx(FloatingFocusManager, { context: popup.context, modal: false, children: /* @__PURE__ */ jsxs(
|
|
1645
1679
|
"div",
|
|
1646
1680
|
{
|
|
1681
|
+
ref: popup.refs.setFloating,
|
|
1647
1682
|
role: "dialog",
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
setActiveGroup(null);
|
|
1653
|
-
}
|
|
1654
|
-
},
|
|
1655
|
-
className: "absolute left-0 top-[calc(100%+0.375rem)] z-50 flex",
|
|
1683
|
+
"aria-label": filter.label,
|
|
1684
|
+
style: { ...popup.floatingStyles, zIndex: popup.floatingZ },
|
|
1685
|
+
className: "flex",
|
|
1686
|
+
...popup.getFloatingProps(),
|
|
1656
1687
|
children: [
|
|
1657
1688
|
/* @__PURE__ */ jsxs("div", { className: "min-w-[14rem] max-w-[16rem] rounded-md border border-border bg-popover p-2 text-popover-foreground shadow-lg shadow-black/5", children: [
|
|
1658
1689
|
/* @__PURE__ */ jsxs("div", { className: "mb-2 flex items-center justify-between gap-2", children: [
|
|
@@ -1771,7 +1802,7 @@ function NestedMultiFilterField({
|
|
|
1771
1802
|
)
|
|
1772
1803
|
]
|
|
1773
1804
|
}
|
|
1774
|
-
)
|
|
1805
|
+
) }) })
|
|
1775
1806
|
]
|
|
1776
1807
|
}
|
|
1777
1808
|
);
|
|
@@ -1851,29 +1882,25 @@ function RangeControlButton({
|
|
|
1851
1882
|
}
|
|
1852
1883
|
);
|
|
1853
1884
|
}
|
|
1854
|
-
function
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
document.removeEventListener("mousedown", onPointerDown);
|
|
1874
|
-
document.removeEventListener("keydown", onKeyDown);
|
|
1875
|
-
};
|
|
1876
|
-
}, [onClose, open, rootRef, triggerRef]);
|
|
1885
|
+
function useAnchoredPopup(open, onOpenChange, placement = "bottom-start") {
|
|
1886
|
+
const floatingZ = useFloatingZIndex();
|
|
1887
|
+
const { refs, floatingStyles, context } = useFloating({
|
|
1888
|
+
open,
|
|
1889
|
+
onOpenChange,
|
|
1890
|
+
placement,
|
|
1891
|
+
whileElementsMounted: autoUpdate,
|
|
1892
|
+
middleware: [offset(6), flip({ padding: 8 }), shift({ padding: 8 })]
|
|
1893
|
+
});
|
|
1894
|
+
const { getReferenceProps, getFloatingProps } = useInteractions([
|
|
1895
|
+
useClick(context),
|
|
1896
|
+
useDismiss(context, { escapeKey: false }),
|
|
1897
|
+
useRole(context, { role: "dialog" })
|
|
1898
|
+
]);
|
|
1899
|
+
useEscapeLayer(open, () => {
|
|
1900
|
+
onOpenChange(false);
|
|
1901
|
+
if (refs.domReference.current instanceof HTMLElement) refs.domReference.current.focus();
|
|
1902
|
+
});
|
|
1903
|
+
return { refs, floatingStyles, context, floatingZ, getReferenceProps, getFloatingProps };
|
|
1877
1904
|
}
|
|
1878
1905
|
function useMediaQuery(query) {
|
|
1879
1906
|
const [matches, setMatches] = useState(() => {
|