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