@l3mpire/ui 2.16.4 → 2.18.0
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/USAGE.md +4 -3
- package/dist/index.d.mts +12 -1
- package/dist/index.d.ts +12 -1
- package/dist/index.js +82 -55
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +83 -56
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/USAGE.md
CHANGED
|
@@ -963,7 +963,7 @@ import {
|
|
|
963
963
|
|
|
964
964
|
**Advanced filter shortcut:** the PropertySelector footer shows an "Advanced filter · N rule(s)" item. Clicking it closes the property selector and opens the advanced popover directly in its initial empty state — where the user picks the first property inline via a "Where | [Select property ▾]" draft row. When no advanced filters exist yet, clicking this shortcut makes the AdvancedChip appear with the popover already open; closing without adding a filter removes the chip automatically.
|
|
965
965
|
|
|
966
|
-
**Dynamic options ("Me", "Unassigned", …):** enum/tags/relation properties accept a `dynamicOptions` array. Each entry is `{ value, label, description? }` and is rendered
|
|
966
|
+
**Dynamic options ("Me", "Unassigned", …):** enum/tags/relation properties accept a `dynamicOptions` array. Each entry is `{ value, label, description?, icon? }` and is rendered at the top of the SingleSelect / MultiSelect dropdown with a divider separating it from the regular options. The `value` is a sentinel string stored on `FilterCondition.value` — the DS only renders, the consuming app resolves it at query time (e.g. `"__me__"` → `currentUser.id`). This keeps session/business logic out of the DS while still getting a consistent visual treatment.
|
|
967
967
|
|
|
968
968
|
```tsx
|
|
969
969
|
{
|
|
@@ -979,8 +979,9 @@ import {
|
|
|
979
979
|
value: "__me__",
|
|
980
980
|
label: "Me",
|
|
981
981
|
description: "This value is dynamically applied to the current user",
|
|
982
|
+
icon: faBoltOutline,
|
|
982
983
|
},
|
|
983
|
-
{ value: "__deactivated__", label: "All deactivated and removed owners" },
|
|
984
|
+
{ value: "__deactivated__", label: "All deactivated and removed owners", icon: faBoltOutline },
|
|
984
985
|
],
|
|
985
986
|
}
|
|
986
987
|
```
|
|
@@ -992,7 +993,7 @@ import {
|
|
|
992
993
|
| `createFilterWithDefaults(propertyId, type)` | Creates FilterCondition with default operator |
|
|
993
994
|
| `isNoValueOperator(op)` | True for is empty / is not empty / is true / is false |
|
|
994
995
|
| `getValueInputType(type, op)` | Returns the input component name for a type+operator combo |
|
|
995
|
-
| `formatFilterValue(value
|
|
996
|
+
| `formatFilterValue(value)` | Stringifies a `FilterValue` for display (handles Date, ranges, arrays, booleans) |
|
|
996
997
|
| `getBadgeCount(value)` | Returns `+N` count for multi-value selections, `undefined` otherwise |
|
|
997
998
|
| `createEmptyGroup()` / `isFilterGroup(node)` | Tree helpers for nested groups |
|
|
998
999
|
| `wrapInGroup(condition)` / `unwrapGroup(group)` | Convert between condition and single-child group |
|
package/dist/index.d.mts
CHANGED
|
@@ -899,6 +899,8 @@ declare const PropertySelector: React.FC<PropertySelectorProps>;
|
|
|
899
899
|
|
|
900
900
|
interface KebabMenuProps {
|
|
901
901
|
onConvertToAdvanced?: () => void;
|
|
902
|
+
/** When true, label reads "Add to advanced filters" instead of "Convert to advanced". */
|
|
903
|
+
hasAdvancedFilters?: boolean;
|
|
902
904
|
onDelete?: () => void;
|
|
903
905
|
open?: boolean;
|
|
904
906
|
onOpenChange?: (open: boolean) => void;
|
|
@@ -931,11 +933,12 @@ interface InteractiveFilterChipProps {
|
|
|
931
933
|
onPropertyChange?: (property: PropertyDefinition) => void;
|
|
932
934
|
onDelete: () => void;
|
|
933
935
|
onConvertToAdvanced?: () => void;
|
|
936
|
+
hasAdvancedFilters?: boolean;
|
|
934
937
|
className?: string;
|
|
935
938
|
}
|
|
936
939
|
declare const InteractiveFilterChip: React.FC<InteractiveFilterChipProps>;
|
|
937
940
|
|
|
938
|
-
type FilterBarMode = "default" | "minimal";
|
|
941
|
+
type FilterBarMode = "default" | "minimal" | "icon";
|
|
939
942
|
/**
|
|
940
943
|
* Observes the container width and returns the appropriate FilterBar mode.
|
|
941
944
|
* - default: > breakpoint
|
|
@@ -952,6 +955,12 @@ interface FilterSystemProps {
|
|
|
952
955
|
mode?: FilterBarMode;
|
|
953
956
|
/** Width breakpoint (px) for switching to minimal mode. Default: 600. */
|
|
954
957
|
breakpoint?: number;
|
|
958
|
+
/**
|
|
959
|
+
* Constrain popovers to stay within the container bounds. Use this when
|
|
960
|
+
* FilterSystem lives inside an iframe or a fixed-width panel where content
|
|
961
|
+
* must not overflow.
|
|
962
|
+
*/
|
|
963
|
+
bounded?: boolean;
|
|
955
964
|
children?: React.ReactNode;
|
|
956
965
|
actions?: React.ReactNode;
|
|
957
966
|
className?: string;
|
|
@@ -989,6 +998,7 @@ interface AdvancedPopoverProps {
|
|
|
989
998
|
open?: boolean;
|
|
990
999
|
onOpenChange?: (open: boolean) => void;
|
|
991
1000
|
children?: React.ReactNode;
|
|
1001
|
+
collisionBoundary?: Element | null;
|
|
992
1002
|
}
|
|
993
1003
|
declare const AdvancedPopover: React.FC<AdvancedPopoverProps>;
|
|
994
1004
|
|
|
@@ -1002,6 +1012,7 @@ interface SummaryChipProps {
|
|
|
1002
1012
|
className?: string;
|
|
1003
1013
|
open?: boolean;
|
|
1004
1014
|
onOpenChange?: (open: boolean) => void;
|
|
1015
|
+
collisionBoundary?: Element | null;
|
|
1005
1016
|
}
|
|
1006
1017
|
declare const SummaryChip: React.FC<SummaryChipProps>;
|
|
1007
1018
|
|
package/dist/index.d.ts
CHANGED
|
@@ -899,6 +899,8 @@ declare const PropertySelector: React.FC<PropertySelectorProps>;
|
|
|
899
899
|
|
|
900
900
|
interface KebabMenuProps {
|
|
901
901
|
onConvertToAdvanced?: () => void;
|
|
902
|
+
/** When true, label reads "Add to advanced filters" instead of "Convert to advanced". */
|
|
903
|
+
hasAdvancedFilters?: boolean;
|
|
902
904
|
onDelete?: () => void;
|
|
903
905
|
open?: boolean;
|
|
904
906
|
onOpenChange?: (open: boolean) => void;
|
|
@@ -931,11 +933,12 @@ interface InteractiveFilterChipProps {
|
|
|
931
933
|
onPropertyChange?: (property: PropertyDefinition) => void;
|
|
932
934
|
onDelete: () => void;
|
|
933
935
|
onConvertToAdvanced?: () => void;
|
|
936
|
+
hasAdvancedFilters?: boolean;
|
|
934
937
|
className?: string;
|
|
935
938
|
}
|
|
936
939
|
declare const InteractiveFilterChip: React.FC<InteractiveFilterChipProps>;
|
|
937
940
|
|
|
938
|
-
type FilterBarMode = "default" | "minimal";
|
|
941
|
+
type FilterBarMode = "default" | "minimal" | "icon";
|
|
939
942
|
/**
|
|
940
943
|
* Observes the container width and returns the appropriate FilterBar mode.
|
|
941
944
|
* - default: > breakpoint
|
|
@@ -952,6 +955,12 @@ interface FilterSystemProps {
|
|
|
952
955
|
mode?: FilterBarMode;
|
|
953
956
|
/** Width breakpoint (px) for switching to minimal mode. Default: 600. */
|
|
954
957
|
breakpoint?: number;
|
|
958
|
+
/**
|
|
959
|
+
* Constrain popovers to stay within the container bounds. Use this when
|
|
960
|
+
* FilterSystem lives inside an iframe or a fixed-width panel where content
|
|
961
|
+
* must not overflow.
|
|
962
|
+
*/
|
|
963
|
+
bounded?: boolean;
|
|
955
964
|
children?: React.ReactNode;
|
|
956
965
|
actions?: React.ReactNode;
|
|
957
966
|
className?: string;
|
|
@@ -989,6 +998,7 @@ interface AdvancedPopoverProps {
|
|
|
989
998
|
open?: boolean;
|
|
990
999
|
onOpenChange?: (open: boolean) => void;
|
|
991
1000
|
children?: React.ReactNode;
|
|
1001
|
+
collisionBoundary?: Element | null;
|
|
992
1002
|
}
|
|
993
1003
|
declare const AdvancedPopover: React.FC<AdvancedPopoverProps>;
|
|
994
1004
|
|
|
@@ -1002,6 +1012,7 @@ interface SummaryChipProps {
|
|
|
1002
1012
|
className?: string;
|
|
1003
1013
|
open?: boolean;
|
|
1004
1014
|
onOpenChange?: (open: boolean) => void;
|
|
1015
|
+
collisionBoundary?: Element | null;
|
|
1005
1016
|
}
|
|
1006
1017
|
declare const SummaryChip: React.FC<SummaryChipProps>;
|
|
1007
1018
|
|
package/dist/index.js
CHANGED
|
@@ -5440,6 +5440,23 @@ function updateNodeInTree(nodes, id, updater) {
|
|
|
5440
5440
|
return node;
|
|
5441
5441
|
});
|
|
5442
5442
|
}
|
|
5443
|
+
function toggleGroupLogicInTree(nodes, id) {
|
|
5444
|
+
const idx = nodes.findIndex((n) => n.id === id);
|
|
5445
|
+
if (idx >= 0) {
|
|
5446
|
+
const current = nodes[idx].logicOperator ?? "and";
|
|
5447
|
+
const next = current === "and" ? "or" : "and";
|
|
5448
|
+
return nodes.map(
|
|
5449
|
+
(n, i) => i === 0 ? n : { ...n, logicOperator: next }
|
|
5450
|
+
);
|
|
5451
|
+
}
|
|
5452
|
+
return nodes.map((node) => {
|
|
5453
|
+
if (isFilterGroup(node)) {
|
|
5454
|
+
const updated = toggleGroupLogicInTree(node.children, id);
|
|
5455
|
+
if (updated !== node.children) return { ...node, children: updated };
|
|
5456
|
+
}
|
|
5457
|
+
return node;
|
|
5458
|
+
});
|
|
5459
|
+
}
|
|
5443
5460
|
function removeNodeFromTree(nodes, id) {
|
|
5444
5461
|
const result = [];
|
|
5445
5462
|
for (const node of nodes) {
|
|
@@ -7166,6 +7183,7 @@ var import_icons30 = require("@l3mpire/icons");
|
|
|
7166
7183
|
var import_jsx_runtime51 = require("react/jsx-runtime");
|
|
7167
7184
|
var KebabMenu = ({
|
|
7168
7185
|
onConvertToAdvanced,
|
|
7186
|
+
hasAdvancedFilters = false,
|
|
7169
7187
|
onDelete,
|
|
7170
7188
|
open,
|
|
7171
7189
|
onOpenChange,
|
|
@@ -7204,7 +7222,7 @@ var KebabMenu = ({
|
|
|
7204
7222
|
className: "shrink-0 text-[var(--color-dropdown-item-icon)]"
|
|
7205
7223
|
}
|
|
7206
7224
|
),
|
|
7207
|
-
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "text-sm font-regular leading-sm text-[var(--color-dropdown-item-text)]", children: "Convert to advanced" })
|
|
7225
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "text-sm font-regular leading-sm text-[var(--color-dropdown-item-text)]", children: hasAdvancedFilters ? "Add to advanced filters" : "Convert to advanced" })
|
|
7208
7226
|
]
|
|
7209
7227
|
}
|
|
7210
7228
|
),
|
|
@@ -7391,6 +7409,7 @@ var InteractiveFilterChip = ({
|
|
|
7391
7409
|
onPropertyChange,
|
|
7392
7410
|
onDelete,
|
|
7393
7411
|
onConvertToAdvanced,
|
|
7412
|
+
hasAdvancedFilters = false,
|
|
7394
7413
|
className
|
|
7395
7414
|
}) => {
|
|
7396
7415
|
const [operatorOpen, setOperatorOpen] = React46.useState(false);
|
|
@@ -7546,6 +7565,7 @@ var InteractiveFilterChip = ({
|
|
|
7546
7565
|
open: kebabOpen,
|
|
7547
7566
|
onOpenChange: setKebabOpen,
|
|
7548
7567
|
onConvertToAdvanced,
|
|
7568
|
+
hasAdvancedFilters,
|
|
7549
7569
|
onDelete,
|
|
7550
7570
|
children: /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
7551
7571
|
FilterChipSegment,
|
|
@@ -8044,7 +8064,8 @@ var AdvancedPopover = ({
|
|
|
8044
8064
|
onFiltersChange,
|
|
8045
8065
|
open,
|
|
8046
8066
|
onOpenChange,
|
|
8047
|
-
children
|
|
8067
|
+
children,
|
|
8068
|
+
collisionBoundary
|
|
8048
8069
|
}) => {
|
|
8049
8070
|
const [addSelectorOpen, setAddSelectorOpen] = React51.useState(false);
|
|
8050
8071
|
const [draftPickerOpen, setDraftPickerOpen] = React51.useState(false);
|
|
@@ -8121,12 +8142,7 @@ var AdvancedPopover = ({
|
|
|
8121
8142
|
}
|
|
8122
8143
|
};
|
|
8123
8144
|
const toggleLogicOp = (id) => {
|
|
8124
|
-
onFiltersChange(
|
|
8125
|
-
updateNodeInTree(filters, id, (n) => ({
|
|
8126
|
-
...n,
|
|
8127
|
-
logicOperator: (n.logicOperator ?? "and") === "and" ? "or" : "and"
|
|
8128
|
-
}))
|
|
8129
|
-
);
|
|
8145
|
+
onFiltersChange(toggleGroupLogicInTree(filters, id));
|
|
8130
8146
|
};
|
|
8131
8147
|
const handleGroupChildrenChange = (groupId, children2) => {
|
|
8132
8148
|
onFiltersChange(
|
|
@@ -8197,6 +8213,7 @@ var AdvancedPopover = ({
|
|
|
8197
8213
|
sideOffset: 4,
|
|
8198
8214
|
align: "start",
|
|
8199
8215
|
collisionPadding: 16,
|
|
8216
|
+
collisionBoundary: collisionBoundary ?? void 0,
|
|
8200
8217
|
onOpenAutoFocus: (e) => e.preventDefault(),
|
|
8201
8218
|
className: cn(
|
|
8202
8219
|
"z-50 flex flex-col",
|
|
@@ -8204,7 +8221,7 @@ var AdvancedPopover = ({
|
|
|
8204
8221
|
"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
|
|
8205
8222
|
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
|
|
8206
8223
|
"data-[side=bottom]:slide-in-from-top-2",
|
|
8207
|
-
"w-[min(640px,calc(100vw-32px))] min-w-[360px]"
|
|
8224
|
+
collisionBoundary ? "w-[min(640px,var(--radix-popover-content-available-width))] min-w-0" : "w-[min(640px,calc(100vw-32px))] min-w-[360px]"
|
|
8208
8225
|
),
|
|
8209
8226
|
children: [
|
|
8210
8227
|
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "flex flex-col gap-base p-base", children: filters.length > 0 ? filters.map((node, i) => renderNode(node, i)) : /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
@@ -8337,7 +8354,8 @@ var SummaryChip = ({
|
|
|
8337
8354
|
children,
|
|
8338
8355
|
className,
|
|
8339
8356
|
open: openProp,
|
|
8340
|
-
onOpenChange
|
|
8357
|
+
onOpenChange,
|
|
8358
|
+
collisionBoundary
|
|
8341
8359
|
}) => {
|
|
8342
8360
|
const [uncontrolledOpen, setUncontrolledOpen] = React52.useState(false);
|
|
8343
8361
|
const isControlled = openProp !== void 0;
|
|
@@ -8415,12 +8433,7 @@ var SummaryChip = ({
|
|
|
8415
8433
|
}
|
|
8416
8434
|
};
|
|
8417
8435
|
const toggleLogicOp = (id) => {
|
|
8418
|
-
onFiltersChange(
|
|
8419
|
-
updateNodeInTree(filters, id, (n) => ({
|
|
8420
|
-
...n,
|
|
8421
|
-
logicOperator: (n.logicOperator ?? "and") === "and" ? "or" : "and"
|
|
8422
|
-
}))
|
|
8423
|
-
);
|
|
8436
|
+
onFiltersChange(toggleGroupLogicInTree(filters, id));
|
|
8424
8437
|
};
|
|
8425
8438
|
const handleGroupChildrenChange = (groupId, newChildren) => {
|
|
8426
8439
|
onFiltersChange(
|
|
@@ -8510,6 +8523,7 @@ var SummaryChip = ({
|
|
|
8510
8523
|
sideOffset: 4,
|
|
8511
8524
|
align: "start",
|
|
8512
8525
|
collisionPadding: 16,
|
|
8526
|
+
collisionBoundary: collisionBoundary ?? void 0,
|
|
8513
8527
|
onOpenAutoFocus: (e) => e.preventDefault(),
|
|
8514
8528
|
className: cn(
|
|
8515
8529
|
"z-50 flex flex-col overflow-clip",
|
|
@@ -8517,7 +8531,7 @@ var SummaryChip = ({
|
|
|
8517
8531
|
"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
|
|
8518
8532
|
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
|
|
8519
8533
|
"data-[side=bottom]:slide-in-from-top-2",
|
|
8520
|
-
"w-[min(640px,calc(100vw-32px))]"
|
|
8534
|
+
collisionBoundary ? "w-[min(640px,var(--radix-popover-content-available-width))]" : "w-[min(640px,calc(100vw-32px))]"
|
|
8521
8535
|
),
|
|
8522
8536
|
children: [
|
|
8523
8537
|
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "flex flex-col gap-base p-base", children: filters.length > 0 ? filters.map((node, i) => renderNode(node, i)) : /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
@@ -8631,12 +8645,14 @@ var FilterSystem = ({
|
|
|
8631
8645
|
sortFields,
|
|
8632
8646
|
mode: modeOverride,
|
|
8633
8647
|
breakpoint,
|
|
8648
|
+
bounded = false,
|
|
8634
8649
|
children,
|
|
8635
8650
|
actions,
|
|
8636
8651
|
className
|
|
8637
8652
|
}) => {
|
|
8638
8653
|
const containerRef = React54.useRef(null);
|
|
8639
8654
|
const mode = useFilterBarMode(containerRef, modeOverride, breakpoint);
|
|
8655
|
+
const collisionBoundary = bounded ? containerRef.current : void 0;
|
|
8640
8656
|
const [propertySelectorOpen, setPropertySelectorOpen] = React54.useState(false);
|
|
8641
8657
|
const [advancedOpen, setAdvancedOpen] = React54.useState(false);
|
|
8642
8658
|
const [summaryOpen, setSummaryOpen] = React54.useState(false);
|
|
@@ -8713,7 +8729,8 @@ var FilterSystem = ({
|
|
|
8713
8729
|
};
|
|
8714
8730
|
const getPropertyDef = (propertyId) => properties.find((p) => p.id === propertyId);
|
|
8715
8731
|
const hasAdvanced = filterState.advancedFilters.length > 0;
|
|
8716
|
-
const isMinimal = mode === "minimal";
|
|
8732
|
+
const isMinimal = mode === "minimal" || mode === "icon";
|
|
8733
|
+
const isIconOnly = mode === "icon";
|
|
8717
8734
|
const handleOpenAdvanced = () => {
|
|
8718
8735
|
setPropertySelectorOpen(false);
|
|
8719
8736
|
requestAnimationFrame(() => {
|
|
@@ -8726,7 +8743,6 @@ var FilterSystem = ({
|
|
|
8726
8743
|
};
|
|
8727
8744
|
const advancedFilterCount = filterState.advancedFilters.length;
|
|
8728
8745
|
const showAdvancedChip = hasAdvanced || advancedOpen;
|
|
8729
|
-
const showSummaryChip = totalCount > 0 || summaryOpen;
|
|
8730
8746
|
return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(FilterBar, { ref: containerRef, className, children: [
|
|
8731
8747
|
/* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(FilterBarLeft, { className: "flex-nowrap flex-1 min-w-0 overflow-x-auto scrollbar-none outline-none [&>*]:shrink-0", children: [
|
|
8732
8748
|
children,
|
|
@@ -8740,38 +8756,33 @@ var FilterSystem = ({
|
|
|
8740
8756
|
iconOnly: isMinimal
|
|
8741
8757
|
}
|
|
8742
8758
|
),
|
|
8743
|
-
isMinimal ? /* @__PURE__ */ (0, import_jsx_runtime60.
|
|
8744
|
-
|
|
8745
|
-
|
|
8746
|
-
|
|
8747
|
-
|
|
8748
|
-
|
|
8749
|
-
|
|
8750
|
-
|
|
8751
|
-
|
|
8752
|
-
|
|
8753
|
-
|
|
8754
|
-
|
|
8755
|
-
|
|
8756
|
-
|
|
8757
|
-
|
|
8758
|
-
|
|
8759
|
-
|
|
8760
|
-
|
|
8761
|
-
|
|
8762
|
-
|
|
8763
|
-
|
|
8764
|
-
|
|
8765
|
-
|
|
8766
|
-
|
|
8767
|
-
|
|
8768
|
-
|
|
8769
|
-
|
|
8770
|
-
advancedFilterCount,
|
|
8771
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(FilterBarButton, { iconOnly: true })
|
|
8772
|
-
}
|
|
8773
|
-
)
|
|
8774
|
-
] }) : (
|
|
8759
|
+
isMinimal ? /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(import_jsx_runtime60.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
|
|
8760
|
+
SummaryChip,
|
|
8761
|
+
{
|
|
8762
|
+
count: totalCount,
|
|
8763
|
+
filters: [...filterState.basicFilters, ...filterState.advancedFilters],
|
|
8764
|
+
properties,
|
|
8765
|
+
onFiltersChange: (nodes) => {
|
|
8766
|
+
onFilterStateChange({
|
|
8767
|
+
...filterState,
|
|
8768
|
+
basicFilters: [],
|
|
8769
|
+
advancedFilters: nodes
|
|
8770
|
+
});
|
|
8771
|
+
},
|
|
8772
|
+
onClearAll: handleClearAll,
|
|
8773
|
+
open: summaryOpen,
|
|
8774
|
+
onOpenChange: setSummaryOpen,
|
|
8775
|
+
collisionBoundary,
|
|
8776
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
|
|
8777
|
+
FilterBarButton,
|
|
8778
|
+
{
|
|
8779
|
+
iconOnly: isIconOnly,
|
|
8780
|
+
count: totalCount > 0 ? totalCount : void 0,
|
|
8781
|
+
title: buildFilterSummary(filterState.basicFilters, filterState.advancedFilters.length, properties)
|
|
8782
|
+
}
|
|
8783
|
+
)
|
|
8784
|
+
}
|
|
8785
|
+
) }) : (
|
|
8775
8786
|
/* ── DEFAULT MODE ────────────────────────────────────── */
|
|
8776
8787
|
/* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(import_jsx_runtime60.Fragment, { children: [
|
|
8777
8788
|
showAdvancedChip && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
|
|
@@ -8782,6 +8793,7 @@ var FilterSystem = ({
|
|
|
8782
8793
|
onFiltersChange: handleAdvancedFiltersChange,
|
|
8783
8794
|
open: advancedOpen,
|
|
8784
8795
|
onOpenChange: setAdvancedOpen,
|
|
8796
|
+
collisionBoundary,
|
|
8785
8797
|
children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
|
|
8786
8798
|
AdvancedChip,
|
|
8787
8799
|
{
|
|
@@ -8806,7 +8818,8 @@ var FilterSystem = ({
|
|
|
8806
8818
|
onUpdate: handleUpdateFilter,
|
|
8807
8819
|
onPropertyChange: (newProp) => handlePropertyChange(filter.id, newProp),
|
|
8808
8820
|
onDelete: () => handleDeleteFilter(filter.id),
|
|
8809
|
-
onConvertToAdvanced: () => handleConvertToAdvanced(filter.id)
|
|
8821
|
+
onConvertToAdvanced: () => handleConvertToAdvanced(filter.id),
|
|
8822
|
+
hasAdvancedFilters: hasAdvanced
|
|
8810
8823
|
},
|
|
8811
8824
|
filter.id
|
|
8812
8825
|
);
|
|
@@ -8832,13 +8845,13 @@ var FilterSystem = ({
|
|
|
8832
8845
|
)
|
|
8833
8846
|
] })
|
|
8834
8847
|
),
|
|
8835
|
-
totalCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
|
|
8848
|
+
totalCount > 0 && !isIconOnly && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
|
|
8836
8849
|
"button",
|
|
8837
8850
|
{
|
|
8838
8851
|
type: "button",
|
|
8839
8852
|
onClick: handleClearAll,
|
|
8840
|
-
className: "shrink-0 flex items-center gap-sm px-base py-sm min-h-[32px] max-h-[32px] rounded-md cursor-pointer transition-colors hover:bg-
|
|
8841
|
-
children:
|
|
8853
|
+
className: "shrink-0 flex items-center gap-sm px-base py-sm min-h-[32px] max-h-[32px] rounded-md cursor-pointer transition-colors text-btn-ghost-brand-text-default hover:bg-btn-ghost-brand-bg-hover hover:text-btn-ghost-brand-text-hover active:bg-btn-ghost-brand-bg-pressed active:text-btn-ghost-brand-text-pressed",
|
|
8854
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { className: "text-sm font-semibold leading-sm", children: "Clear" })
|
|
8842
8855
|
}
|
|
8843
8856
|
)
|
|
8844
8857
|
] }),
|
|
@@ -8846,6 +8859,20 @@ var FilterSystem = ({
|
|
|
8846
8859
|
] });
|
|
8847
8860
|
};
|
|
8848
8861
|
FilterSystem.displayName = "FilterSystem";
|
|
8862
|
+
function buildFilterSummary(filters, advancedCount, properties) {
|
|
8863
|
+
if (filters.length === 0 && advancedCount === 0) return void 0;
|
|
8864
|
+
const lines = [];
|
|
8865
|
+
for (const f of filters) {
|
|
8866
|
+
const prop = properties.find((p) => p.id === f.propertyId);
|
|
8867
|
+
if (!prop) continue;
|
|
8868
|
+
const val = formatFilterValue(f.value, prop.dynamicOptions);
|
|
8869
|
+
lines.push(val ? `${prop.label} ${f.operator} ${val}` : `${prop.label} ${f.operator ?? ""}`);
|
|
8870
|
+
}
|
|
8871
|
+
if (advancedCount > 0) {
|
|
8872
|
+
lines.push(`+ ${advancedCount} advanced filter${advancedCount > 1 ? "s" : ""}`);
|
|
8873
|
+
}
|
|
8874
|
+
return lines.join("\n");
|
|
8875
|
+
}
|
|
8849
8876
|
// Annotate the CommonJS export names for ESM import in node:
|
|
8850
8877
|
0 && (module.exports = {
|
|
8851
8878
|
AdvancedChip,
|