@l3mpire/ui 2.6.0 → 2.7.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/USAGE.md +127 -0
- package/dist/index.d.mts +319 -1
- package/dist/index.d.ts +319 -1
- package/dist/index.js +2637 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2610 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -5
- package/src/styles/globals.css +33 -0
package/dist/index.mjs
CHANGED
|
@@ -4724,7 +4724,2584 @@ var SidePanelContent = React33.forwardRef(({ className, overlay = true, children
|
|
|
4724
4724
|
)
|
|
4725
4725
|
] }));
|
|
4726
4726
|
SidePanelContent.displayName = "SidePanelContent";
|
|
4727
|
+
|
|
4728
|
+
// src/components/ui/filter/filter-chip-segment.tsx
|
|
4729
|
+
import * as React34 from "react";
|
|
4730
|
+
import { cva as cva19 } from "class-variance-authority";
|
|
4731
|
+
import { Icon as Icon22 } from "@l3mpire/icons";
|
|
4732
|
+
import { jsx as jsx34, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
4733
|
+
var filterChipSegmentVariants = cva19(
|
|
4734
|
+
["flex items-center shrink-0 transition-colors"],
|
|
4735
|
+
{
|
|
4736
|
+
variants: {
|
|
4737
|
+
type: {
|
|
4738
|
+
property: "gap-xs px-base py-sm",
|
|
4739
|
+
operator: "gap-0 px-base py-sm",
|
|
4740
|
+
value: "gap-xs px-base py-sm",
|
|
4741
|
+
placeholder: "gap-0 px-base py-sm",
|
|
4742
|
+
button: "gap-0 p-0"
|
|
4743
|
+
},
|
|
4744
|
+
hasBorder: {
|
|
4745
|
+
true: "border-r border-filter-chip-segment-border",
|
|
4746
|
+
false: ""
|
|
4747
|
+
}
|
|
4748
|
+
},
|
|
4749
|
+
defaultVariants: {
|
|
4750
|
+
type: "property",
|
|
4751
|
+
hasBorder: false
|
|
4752
|
+
}
|
|
4753
|
+
}
|
|
4754
|
+
);
|
|
4755
|
+
var FilterChipSegment = React34.forwardRef(
|
|
4756
|
+
({
|
|
4757
|
+
className,
|
|
4758
|
+
segmentType = "property",
|
|
4759
|
+
hasBorder,
|
|
4760
|
+
icon,
|
|
4761
|
+
label,
|
|
4762
|
+
badgeCount,
|
|
4763
|
+
adornment,
|
|
4764
|
+
onKebabClick,
|
|
4765
|
+
children,
|
|
4766
|
+
...props
|
|
4767
|
+
}, ref) => {
|
|
4768
|
+
if (segmentType === "button") {
|
|
4769
|
+
return /* @__PURE__ */ jsxs30(
|
|
4770
|
+
"div",
|
|
4771
|
+
{
|
|
4772
|
+
ref,
|
|
4773
|
+
className: cn(filterChipSegmentVariants({ type: "button", hasBorder: false }), className),
|
|
4774
|
+
...props,
|
|
4775
|
+
children: [
|
|
4776
|
+
/* @__PURE__ */ jsx34(
|
|
4777
|
+
"button",
|
|
4778
|
+
{
|
|
4779
|
+
type: "button",
|
|
4780
|
+
onClick: onKebabClick,
|
|
4781
|
+
className: "flex items-center justify-center p-sm cursor-pointer hover:bg-filter-chip-segment-bg-hover active:bg-filter-chip-segment-bg-pressed transition-colors",
|
|
4782
|
+
"aria-label": "Filter actions",
|
|
4783
|
+
children: /* @__PURE__ */ jsx34("span", { className: "size-5 flex items-center justify-center text-sm leading-sm text-filter-chip-kebab-text", children: /* @__PURE__ */ jsxs30("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "currentColor", children: [
|
|
4784
|
+
/* @__PURE__ */ jsx34("circle", { cx: "10", cy: "4.5", r: "1.5" }),
|
|
4785
|
+
/* @__PURE__ */ jsx34("circle", { cx: "10", cy: "10", r: "1.5" }),
|
|
4786
|
+
/* @__PURE__ */ jsx34("circle", { cx: "10", cy: "15.5", r: "1.5" })
|
|
4787
|
+
] }) })
|
|
4788
|
+
}
|
|
4789
|
+
),
|
|
4790
|
+
children
|
|
4791
|
+
]
|
|
4792
|
+
}
|
|
4793
|
+
);
|
|
4794
|
+
}
|
|
4795
|
+
return /* @__PURE__ */ jsxs30(
|
|
4796
|
+
"div",
|
|
4797
|
+
{
|
|
4798
|
+
ref,
|
|
4799
|
+
className: cn(
|
|
4800
|
+
filterChipSegmentVariants({ type: segmentType, hasBorder }),
|
|
4801
|
+
"cursor-pointer hover:bg-filter-chip-segment-bg-hover active:bg-filter-chip-segment-bg-pressed",
|
|
4802
|
+
className
|
|
4803
|
+
),
|
|
4804
|
+
...props,
|
|
4805
|
+
children: [
|
|
4806
|
+
adornment && segmentType === "value" && /* @__PURE__ */ jsx34("div", { className: "shrink-0 size-5", children: adornment }),
|
|
4807
|
+
icon && segmentType === "property" && /* @__PURE__ */ jsx34(
|
|
4808
|
+
Icon22,
|
|
4809
|
+
{
|
|
4810
|
+
icon,
|
|
4811
|
+
size: "sm",
|
|
4812
|
+
className: "shrink-0 text-filter-chip-segment-icon"
|
|
4813
|
+
}
|
|
4814
|
+
),
|
|
4815
|
+
label && /* @__PURE__ */ jsx34(
|
|
4816
|
+
"span",
|
|
4817
|
+
{
|
|
4818
|
+
className: cn(
|
|
4819
|
+
"text-sm font-medium leading-sm whitespace-nowrap",
|
|
4820
|
+
segmentType === "placeholder" ? "text-filter-chip-segment-placeholder" : "text-filter-chip-segment-text"
|
|
4821
|
+
),
|
|
4822
|
+
children: label
|
|
4823
|
+
}
|
|
4824
|
+
),
|
|
4825
|
+
badgeCount != null && badgeCount > 0 && /* @__PURE__ */ jsx34("span", { className: "flex items-center gap-2xs p-2xs rounded-xs bg-filter-chip-badge-bg", children: /* @__PURE__ */ jsx34("span", { className: "text-[10px] font-medium leading-2xs text-filter-chip-badge-text", children: badgeCount }) }),
|
|
4826
|
+
children
|
|
4827
|
+
]
|
|
4828
|
+
}
|
|
4829
|
+
);
|
|
4830
|
+
}
|
|
4831
|
+
);
|
|
4832
|
+
FilterChipSegment.displayName = "FilterChipSegment";
|
|
4833
|
+
|
|
4834
|
+
// src/components/ui/filter/filter-chip.tsx
|
|
4835
|
+
import * as React35 from "react";
|
|
4836
|
+
import { jsx as jsx35, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
4837
|
+
var FilterChip = React35.forwardRef(
|
|
4838
|
+
({
|
|
4839
|
+
className,
|
|
4840
|
+
icon,
|
|
4841
|
+
property,
|
|
4842
|
+
operator,
|
|
4843
|
+
value,
|
|
4844
|
+
badgeCount,
|
|
4845
|
+
valueAdornment,
|
|
4846
|
+
onPropertyClick,
|
|
4847
|
+
onOperatorClick,
|
|
4848
|
+
onValueClick,
|
|
4849
|
+
onKebabClick,
|
|
4850
|
+
...props
|
|
4851
|
+
}, ref) => {
|
|
4852
|
+
const hasOperator = !!operator;
|
|
4853
|
+
const hasValue = hasOperator && value != null;
|
|
4854
|
+
return /* @__PURE__ */ jsxs31(
|
|
4855
|
+
"div",
|
|
4856
|
+
{
|
|
4857
|
+
ref,
|
|
4858
|
+
className: cn(
|
|
4859
|
+
"flex items-center overflow-clip",
|
|
4860
|
+
"bg-filter-chip-bg border border-filter-chip-border rounded-md",
|
|
4861
|
+
className
|
|
4862
|
+
),
|
|
4863
|
+
...props,
|
|
4864
|
+
children: [
|
|
4865
|
+
/* @__PURE__ */ jsx35(
|
|
4866
|
+
FilterChipSegment,
|
|
4867
|
+
{
|
|
4868
|
+
segmentType: "property",
|
|
4869
|
+
hasBorder: true,
|
|
4870
|
+
icon,
|
|
4871
|
+
label: property,
|
|
4872
|
+
onClick: onPropertyClick
|
|
4873
|
+
}
|
|
4874
|
+
),
|
|
4875
|
+
/* @__PURE__ */ jsx35(
|
|
4876
|
+
FilterChipSegment,
|
|
4877
|
+
{
|
|
4878
|
+
segmentType: hasOperator ? "operator" : "placeholder",
|
|
4879
|
+
hasBorder: true,
|
|
4880
|
+
label: hasOperator ? operator : "Select condition",
|
|
4881
|
+
onClick: onOperatorClick
|
|
4882
|
+
}
|
|
4883
|
+
),
|
|
4884
|
+
hasOperator && /* @__PURE__ */ jsx35(
|
|
4885
|
+
FilterChipSegment,
|
|
4886
|
+
{
|
|
4887
|
+
segmentType: hasValue ? "value" : "placeholder",
|
|
4888
|
+
hasBorder: true,
|
|
4889
|
+
label: hasValue ? value : "Select condition",
|
|
4890
|
+
adornment: valueAdornment,
|
|
4891
|
+
badgeCount,
|
|
4892
|
+
onClick: onValueClick
|
|
4893
|
+
}
|
|
4894
|
+
),
|
|
4895
|
+
hasOperator && /* @__PURE__ */ jsx35(
|
|
4896
|
+
FilterChipSegment,
|
|
4897
|
+
{
|
|
4898
|
+
segmentType: "button",
|
|
4899
|
+
onKebabClick
|
|
4900
|
+
}
|
|
4901
|
+
)
|
|
4902
|
+
]
|
|
4903
|
+
}
|
|
4904
|
+
);
|
|
4905
|
+
}
|
|
4906
|
+
);
|
|
4907
|
+
FilterChip.displayName = "FilterChip";
|
|
4908
|
+
|
|
4909
|
+
// src/components/ui/filter/utils.ts
|
|
4910
|
+
var OPERATORS_BY_TYPE = {
|
|
4911
|
+
text: [
|
|
4912
|
+
"contains",
|
|
4913
|
+
"does not contain",
|
|
4914
|
+
"is",
|
|
4915
|
+
"is not",
|
|
4916
|
+
"starts with",
|
|
4917
|
+
"ends with",
|
|
4918
|
+
"is empty",
|
|
4919
|
+
"is not empty"
|
|
4920
|
+
],
|
|
4921
|
+
number: ["=", "\u2260", ">", "<", "\u2265", "\u2264", "is between", "is empty", "is not empty"],
|
|
4922
|
+
date: [
|
|
4923
|
+
"is",
|
|
4924
|
+
"is before",
|
|
4925
|
+
"is after",
|
|
4926
|
+
"is on or before",
|
|
4927
|
+
"is on or after",
|
|
4928
|
+
"is between",
|
|
4929
|
+
"is relative",
|
|
4930
|
+
"is empty",
|
|
4931
|
+
"is not empty"
|
|
4932
|
+
],
|
|
4933
|
+
enum: ["is", "is not", "is any of", "is none of", "is empty", "is not empty"],
|
|
4934
|
+
tags: [
|
|
4935
|
+
"contains",
|
|
4936
|
+
"does not contain",
|
|
4937
|
+
"contains any of",
|
|
4938
|
+
"contains all of",
|
|
4939
|
+
"is empty",
|
|
4940
|
+
"is not empty"
|
|
4941
|
+
],
|
|
4942
|
+
boolean: ["is true", "is false"],
|
|
4943
|
+
relation: ["is", "is not", "is any of", "is none of", "is empty", "is not empty"]
|
|
4944
|
+
};
|
|
4945
|
+
var DEFAULT_OPERATOR_BY_TYPE = {
|
|
4946
|
+
text: "contains",
|
|
4947
|
+
number: "=",
|
|
4948
|
+
date: "is relative",
|
|
4949
|
+
enum: "is",
|
|
4950
|
+
tags: "contains",
|
|
4951
|
+
boolean: "is true",
|
|
4952
|
+
relation: "is"
|
|
4953
|
+
};
|
|
4954
|
+
function isNoValueOperator(operator) {
|
|
4955
|
+
return ["is empty", "is not empty", "is true", "is false"].includes(operator);
|
|
4956
|
+
}
|
|
4957
|
+
function getDefaultOperator(type) {
|
|
4958
|
+
return DEFAULT_OPERATOR_BY_TYPE[type];
|
|
4959
|
+
}
|
|
4960
|
+
function createFilterWithDefaults(propertyId, type) {
|
|
4961
|
+
const operator = getDefaultOperator(type);
|
|
4962
|
+
return {
|
|
4963
|
+
id: crypto.randomUUID(),
|
|
4964
|
+
propertyId,
|
|
4965
|
+
operator,
|
|
4966
|
+
value: type === "boolean" ? true : null
|
|
4967
|
+
};
|
|
4968
|
+
}
|
|
4969
|
+
function getValueInputType(type, operator) {
|
|
4970
|
+
if (isNoValueOperator(operator)) return null;
|
|
4971
|
+
if (type === "text") return "TextInput";
|
|
4972
|
+
if (type === "number")
|
|
4973
|
+
return operator === "is between" ? "NumberRange" : "NumberInput";
|
|
4974
|
+
if (type === "date") {
|
|
4975
|
+
if (operator === "is between") return "DateRange";
|
|
4976
|
+
if (operator === "is relative") return "PresetTags";
|
|
4977
|
+
return "DatePicker";
|
|
4978
|
+
}
|
|
4979
|
+
if (type === "enum")
|
|
4980
|
+
return ["is any of", "is none of"].includes(operator) ? "MultiSelect" : "SingleSelect";
|
|
4981
|
+
if (type === "tags")
|
|
4982
|
+
return ["contains any of", "contains all of"].includes(operator) ? "MultiSelect" : "SingleSelect";
|
|
4983
|
+
if (type === "relation")
|
|
4984
|
+
return ["is any of", "is none of"].includes(operator) ? "MultiRelationPicker" : "RelationPicker";
|
|
4985
|
+
return null;
|
|
4986
|
+
}
|
|
4987
|
+
|
|
4988
|
+
// src/components/ui/filter/filter-bar.tsx
|
|
4989
|
+
import * as React36 from "react";
|
|
4990
|
+
import { jsx as jsx36 } from "react/jsx-runtime";
|
|
4991
|
+
var FilterBar = React36.forwardRef(
|
|
4992
|
+
({ className, children, ...props }, ref) => /* @__PURE__ */ jsx36(
|
|
4993
|
+
"div",
|
|
4994
|
+
{
|
|
4995
|
+
ref,
|
|
4996
|
+
className: cn(
|
|
4997
|
+
"flex items-center justify-between w-full",
|
|
4998
|
+
className
|
|
4999
|
+
),
|
|
5000
|
+
role: "toolbar",
|
|
5001
|
+
"aria-label": "Filters",
|
|
5002
|
+
"aria-orientation": "horizontal",
|
|
5003
|
+
...props,
|
|
5004
|
+
children
|
|
5005
|
+
}
|
|
5006
|
+
)
|
|
5007
|
+
);
|
|
5008
|
+
FilterBar.displayName = "FilterBar";
|
|
5009
|
+
var FilterBarLeft = React36.forwardRef(
|
|
5010
|
+
({ className, children, ...props }, ref) => /* @__PURE__ */ jsx36(
|
|
5011
|
+
"div",
|
|
5012
|
+
{
|
|
5013
|
+
ref,
|
|
5014
|
+
className: cn("flex items-center gap-base flex-wrap", className),
|
|
5015
|
+
...props,
|
|
5016
|
+
children
|
|
5017
|
+
}
|
|
5018
|
+
)
|
|
5019
|
+
);
|
|
5020
|
+
FilterBarLeft.displayName = "FilterBarLeft";
|
|
5021
|
+
var FilterBarRight = React36.forwardRef(
|
|
5022
|
+
({ className, children, ...props }, ref) => /* @__PURE__ */ jsx36(
|
|
5023
|
+
"div",
|
|
5024
|
+
{
|
|
5025
|
+
ref,
|
|
5026
|
+
className: cn("flex items-center gap-base shrink-0", className),
|
|
5027
|
+
...props,
|
|
5028
|
+
children
|
|
5029
|
+
}
|
|
5030
|
+
)
|
|
5031
|
+
);
|
|
5032
|
+
FilterBarRight.displayName = "FilterBarRight";
|
|
5033
|
+
|
|
5034
|
+
// src/components/ui/filter/sort-button.tsx
|
|
5035
|
+
import * as React37 from "react";
|
|
5036
|
+
import * as PopoverPrimitive3 from "@radix-ui/react-popover";
|
|
5037
|
+
import { Icon as Icon23 } from "@l3mpire/icons";
|
|
5038
|
+
import {
|
|
5039
|
+
faArrowUpSmallBigOutline,
|
|
5040
|
+
faArrowDownBigSmallOutline
|
|
5041
|
+
} from "@l3mpire/icons";
|
|
5042
|
+
import { jsx as jsx37, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
5043
|
+
var SortButton = ({
|
|
5044
|
+
className,
|
|
5045
|
+
fields,
|
|
5046
|
+
activeField,
|
|
5047
|
+
direction,
|
|
5048
|
+
onChange,
|
|
5049
|
+
...props
|
|
5050
|
+
}) => {
|
|
5051
|
+
const [open, setOpen] = React37.useState(false);
|
|
5052
|
+
const activeFieldDef = fields.find((f) => f.id === activeField);
|
|
5053
|
+
const activeLabel = activeFieldDef?.label ?? activeField;
|
|
5054
|
+
return /* @__PURE__ */ jsxs32(PopoverPrimitive3.Root, { open, onOpenChange: setOpen, children: [
|
|
5055
|
+
/* @__PURE__ */ jsx37(PopoverPrimitive3.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs32(
|
|
5056
|
+
"button",
|
|
5057
|
+
{
|
|
5058
|
+
type: "button",
|
|
5059
|
+
className: cn(
|
|
5060
|
+
"flex items-center gap-xs px-md py-sm",
|
|
5061
|
+
"min-h-[32px] max-h-[32px] min-w-[80px]",
|
|
5062
|
+
"bg-gradient-to-t from-[var(--color-btn-outlined-neutral-bg-default)] to-[var(--color-btn-outlined-neutral-bg-gradient-to-default)]",
|
|
5063
|
+
"border border-[var(--color-btn-outlined-neutral-border-default)] rounded-md shadow-sm",
|
|
5064
|
+
"cursor-pointer transition-colors",
|
|
5065
|
+
"hover:from-[var(--color-btn-outlined-neutral-bg-hover)] hover:to-[var(--color-btn-outlined-neutral-bg-gradient-to-hover)]",
|
|
5066
|
+
className
|
|
5067
|
+
),
|
|
5068
|
+
children: [
|
|
5069
|
+
/* @__PURE__ */ jsx37(
|
|
5070
|
+
Icon23,
|
|
5071
|
+
{
|
|
5072
|
+
icon: direction === "asc" ? faArrowUpSmallBigOutline : faArrowDownBigSmallOutline,
|
|
5073
|
+
size: "sm",
|
|
5074
|
+
className: "shrink-0 text-[var(--color-foreground)]"
|
|
5075
|
+
}
|
|
5076
|
+
),
|
|
5077
|
+
/* @__PURE__ */ jsxs32("span", { className: "text-sm font-medium leading-sm whitespace-nowrap", children: [
|
|
5078
|
+
/* @__PURE__ */ jsxs32("span", { className: "text-[var(--color-muted-foreground)]", children: [
|
|
5079
|
+
"Sort by",
|
|
5080
|
+
" "
|
|
5081
|
+
] }),
|
|
5082
|
+
/* @__PURE__ */ jsx37("span", { className: "text-[var(--color-foreground)]", children: activeLabel })
|
|
5083
|
+
] })
|
|
5084
|
+
]
|
|
5085
|
+
}
|
|
5086
|
+
) }),
|
|
5087
|
+
/* @__PURE__ */ jsx37(PopoverPrimitive3.Portal, { children: /* @__PURE__ */ jsxs32(
|
|
5088
|
+
PopoverPrimitive3.Content,
|
|
5089
|
+
{
|
|
5090
|
+
sideOffset: 4,
|
|
5091
|
+
align: "start",
|
|
5092
|
+
className: cn(
|
|
5093
|
+
"z-50 flex flex-col gap-xs overflow-clip p-xs",
|
|
5094
|
+
"bg-[var(--color-dropdown-bg)] border border-[var(--color-dropdown-border)] rounded-md shadow-lg",
|
|
5095
|
+
"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
|
|
5096
|
+
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
|
|
5097
|
+
"data-[side=bottom]:slide-in-from-top-2",
|
|
5098
|
+
"min-w-[180px]"
|
|
5099
|
+
),
|
|
5100
|
+
children: [
|
|
5101
|
+
/* @__PURE__ */ jsx37("div", { className: "flex flex-col", children: fields.map((field) => /* @__PURE__ */ jsxs32(
|
|
5102
|
+
"button",
|
|
5103
|
+
{
|
|
5104
|
+
type: "button",
|
|
5105
|
+
onClick: () => {
|
|
5106
|
+
onChange?.(field.id, direction);
|
|
5107
|
+
setOpen(false);
|
|
5108
|
+
},
|
|
5109
|
+
className: cn(
|
|
5110
|
+
"flex items-center gap-base p-base rounded-base cursor-pointer transition-colors",
|
|
5111
|
+
"hover:bg-[var(--color-dropdown-item-hover)]",
|
|
5112
|
+
field.id === activeField ? "bg-[var(--color-dropdown-item-hover)]" : ""
|
|
5113
|
+
),
|
|
5114
|
+
children: [
|
|
5115
|
+
/* @__PURE__ */ jsx37(
|
|
5116
|
+
Icon23,
|
|
5117
|
+
{
|
|
5118
|
+
icon: field.icon,
|
|
5119
|
+
size: "sm",
|
|
5120
|
+
className: cn(
|
|
5121
|
+
"shrink-0",
|
|
5122
|
+
field.id === activeField ? "text-[var(--color-foreground)]" : "text-[var(--color-dropdown-item-icon)]"
|
|
5123
|
+
)
|
|
5124
|
+
}
|
|
5125
|
+
),
|
|
5126
|
+
/* @__PURE__ */ jsx37(
|
|
5127
|
+
"span",
|
|
5128
|
+
{
|
|
5129
|
+
className: cn(
|
|
5130
|
+
"flex-1 text-sm font-regular leading-sm text-left truncate",
|
|
5131
|
+
field.id === activeField ? "text-[var(--color-foreground)]" : "text-[var(--color-dropdown-item-icon)]"
|
|
5132
|
+
),
|
|
5133
|
+
children: field.label
|
|
5134
|
+
}
|
|
5135
|
+
)
|
|
5136
|
+
]
|
|
5137
|
+
},
|
|
5138
|
+
field.id
|
|
5139
|
+
)) }),
|
|
5140
|
+
/* @__PURE__ */ jsx37("div", { className: "h-px bg-[var(--color-border)]" }),
|
|
5141
|
+
/* @__PURE__ */ jsxs32("div", { className: "flex flex-col", children: [
|
|
5142
|
+
/* @__PURE__ */ jsxs32(
|
|
5143
|
+
"button",
|
|
5144
|
+
{
|
|
5145
|
+
type: "button",
|
|
5146
|
+
onClick: () => {
|
|
5147
|
+
onChange?.(activeField, "asc");
|
|
5148
|
+
setOpen(false);
|
|
5149
|
+
},
|
|
5150
|
+
className: cn(
|
|
5151
|
+
"flex items-center gap-base p-base rounded-base cursor-pointer transition-colors",
|
|
5152
|
+
"hover:bg-[var(--color-dropdown-item-hover)]",
|
|
5153
|
+
direction === "asc" ? "bg-[var(--color-dropdown-item-hover)]" : ""
|
|
5154
|
+
),
|
|
5155
|
+
children: [
|
|
5156
|
+
/* @__PURE__ */ jsx37(
|
|
5157
|
+
Icon23,
|
|
5158
|
+
{
|
|
5159
|
+
icon: faArrowUpSmallBigOutline,
|
|
5160
|
+
size: "sm",
|
|
5161
|
+
className: cn(
|
|
5162
|
+
"shrink-0",
|
|
5163
|
+
direction === "asc" ? "text-[var(--color-foreground)]" : "text-[var(--color-dropdown-item-icon)]"
|
|
5164
|
+
)
|
|
5165
|
+
}
|
|
5166
|
+
),
|
|
5167
|
+
/* @__PURE__ */ jsx37(
|
|
5168
|
+
"span",
|
|
5169
|
+
{
|
|
5170
|
+
className: cn(
|
|
5171
|
+
"flex-1 text-sm font-regular leading-sm text-left",
|
|
5172
|
+
direction === "asc" ? "text-[var(--color-foreground)]" : "text-[var(--color-dropdown-item-icon)]"
|
|
5173
|
+
),
|
|
5174
|
+
children: "Ascending"
|
|
5175
|
+
}
|
|
5176
|
+
)
|
|
5177
|
+
]
|
|
5178
|
+
}
|
|
5179
|
+
),
|
|
5180
|
+
/* @__PURE__ */ jsxs32(
|
|
5181
|
+
"button",
|
|
5182
|
+
{
|
|
5183
|
+
type: "button",
|
|
5184
|
+
onClick: () => {
|
|
5185
|
+
onChange?.(activeField, "desc");
|
|
5186
|
+
setOpen(false);
|
|
5187
|
+
},
|
|
5188
|
+
className: cn(
|
|
5189
|
+
"flex items-center gap-base p-base rounded-base cursor-pointer transition-colors",
|
|
5190
|
+
"hover:bg-[var(--color-dropdown-item-hover)]",
|
|
5191
|
+
direction === "desc" ? "bg-[var(--color-dropdown-item-hover)]" : ""
|
|
5192
|
+
),
|
|
5193
|
+
children: [
|
|
5194
|
+
/* @__PURE__ */ jsx37(
|
|
5195
|
+
Icon23,
|
|
5196
|
+
{
|
|
5197
|
+
icon: faArrowDownBigSmallOutline,
|
|
5198
|
+
size: "sm",
|
|
5199
|
+
className: cn(
|
|
5200
|
+
"shrink-0",
|
|
5201
|
+
direction === "desc" ? "text-[var(--color-foreground)]" : "text-[var(--color-dropdown-item-icon)]"
|
|
5202
|
+
)
|
|
5203
|
+
}
|
|
5204
|
+
),
|
|
5205
|
+
/* @__PURE__ */ jsx37(
|
|
5206
|
+
"span",
|
|
5207
|
+
{
|
|
5208
|
+
className: cn(
|
|
5209
|
+
"flex-1 text-sm font-regular leading-sm text-left",
|
|
5210
|
+
direction === "desc" ? "text-[var(--color-foreground)]" : "text-[var(--color-dropdown-item-icon)]"
|
|
5211
|
+
),
|
|
5212
|
+
children: "Descending"
|
|
5213
|
+
}
|
|
5214
|
+
)
|
|
5215
|
+
]
|
|
5216
|
+
}
|
|
5217
|
+
)
|
|
5218
|
+
] })
|
|
5219
|
+
]
|
|
5220
|
+
}
|
|
5221
|
+
) })
|
|
5222
|
+
] });
|
|
5223
|
+
};
|
|
5224
|
+
SortButton.displayName = "SortButton";
|
|
5225
|
+
|
|
5226
|
+
// src/components/ui/filter/filter-bar-button.tsx
|
|
5227
|
+
import * as React38 from "react";
|
|
5228
|
+
import { Icon as Icon24, faSlidersOutline } from "@l3mpire/icons";
|
|
5229
|
+
import { jsx as jsx38, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
5230
|
+
var FilterBarButton = React38.forwardRef(({ className, count, children, ...props }, ref) => /* @__PURE__ */ jsxs33(
|
|
5231
|
+
"button",
|
|
5232
|
+
{
|
|
5233
|
+
ref,
|
|
5234
|
+
type: "button",
|
|
5235
|
+
className: cn(
|
|
5236
|
+
"flex items-center gap-sm px-base py-sm",
|
|
5237
|
+
"min-h-[32px] max-h-[32px] min-w-[80px]",
|
|
5238
|
+
"bg-gradient-to-t from-[var(--color-btn-outlined-neutral-bg-default)] to-[var(--color-btn-outlined-neutral-bg-gradient-to-default)]",
|
|
5239
|
+
"border border-[var(--color-btn-outlined-neutral-border-default)] rounded-md shadow-sm",
|
|
5240
|
+
"cursor-pointer transition-colors",
|
|
5241
|
+
"hover:from-[var(--color-btn-outlined-neutral-bg-hover)] hover:to-[var(--color-btn-outlined-neutral-bg-gradient-to-hover)]",
|
|
5242
|
+
className
|
|
5243
|
+
),
|
|
5244
|
+
...props,
|
|
5245
|
+
children: [
|
|
5246
|
+
/* @__PURE__ */ jsx38(
|
|
5247
|
+
Icon24,
|
|
5248
|
+
{
|
|
5249
|
+
icon: faSlidersOutline,
|
|
5250
|
+
size: "sm",
|
|
5251
|
+
className: "shrink-0 text-[var(--color-foreground)]"
|
|
5252
|
+
}
|
|
5253
|
+
),
|
|
5254
|
+
/* @__PURE__ */ jsx38("span", { className: "text-sm font-medium leading-sm whitespace-nowrap text-[var(--color-foreground)]", children: children ?? "Filters" }),
|
|
5255
|
+
count != null && count > 0 && /* @__PURE__ */ jsx38("span", { className: "flex items-center p-2xs rounded-xs bg-filter-chip-badge-bg", children: /* @__PURE__ */ jsx38("span", { className: "text-[10px] font-medium leading-2xs text-filter-chip-badge-text", children: count }) })
|
|
5256
|
+
]
|
|
5257
|
+
}
|
|
5258
|
+
));
|
|
5259
|
+
FilterBarButton.displayName = "FilterBarButton";
|
|
5260
|
+
|
|
5261
|
+
// src/components/ui/filter/save-view-button.tsx
|
|
5262
|
+
import * as React39 from "react";
|
|
5263
|
+
import { Icon as Icon25, faChevronDownOutline } from "@l3mpire/icons";
|
|
5264
|
+
import { jsx as jsx39, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
5265
|
+
var SaveViewButton = React39.forwardRef(
|
|
5266
|
+
({ className, label = "Save view", onSave, onDropdown, ...props }, ref) => {
|
|
5267
|
+
const sharedStyle = [
|
|
5268
|
+
"flex items-center justify-center",
|
|
5269
|
+
"min-h-[32px] max-h-[32px]",
|
|
5270
|
+
"bg-gradient-to-t from-[var(--color-btn-solid-brand-bg-default)] from-[10%] to-[var(--color-btn-solid-brand-bg-gradient-to-default)]",
|
|
5271
|
+
"border border-[var(--color-btn-solid-brand-border-default)]",
|
|
5272
|
+
"shadow-sm cursor-pointer transition-colors",
|
|
5273
|
+
"hover:from-[var(--color-btn-solid-brand-bg-hover)] hover:to-[var(--color-btn-solid-brand-bg-gradient-to-hover)]"
|
|
5274
|
+
];
|
|
5275
|
+
return /* @__PURE__ */ jsxs34(
|
|
5276
|
+
"div",
|
|
5277
|
+
{
|
|
5278
|
+
ref,
|
|
5279
|
+
className: cn("flex items-center", className),
|
|
5280
|
+
...props,
|
|
5281
|
+
children: [
|
|
5282
|
+
/* @__PURE__ */ jsxs34(
|
|
5283
|
+
"button",
|
|
5284
|
+
{
|
|
5285
|
+
type: "button",
|
|
5286
|
+
onClick: onSave,
|
|
5287
|
+
className: cn(
|
|
5288
|
+
sharedStyle,
|
|
5289
|
+
"gap-sm px-base py-sm min-w-[80px]",
|
|
5290
|
+
"rounded-l-md -mr-px"
|
|
5291
|
+
),
|
|
5292
|
+
children: [
|
|
5293
|
+
/* @__PURE__ */ jsx39("span", { className: "text-sm font-medium leading-sm whitespace-nowrap text-[var(--color-btn-solid-brand-text-default)]", children: label }),
|
|
5294
|
+
/* @__PURE__ */ jsx39("span", { className: "absolute inset-0 rounded-l-[11px] border border-[var(--color-btn-solid-brand-inner-border-default)] shadow-sm pointer-events-none" })
|
|
5295
|
+
]
|
|
5296
|
+
}
|
|
5297
|
+
),
|
|
5298
|
+
/* @__PURE__ */ jsxs34(
|
|
5299
|
+
"button",
|
|
5300
|
+
{
|
|
5301
|
+
type: "button",
|
|
5302
|
+
onClick: onDropdown,
|
|
5303
|
+
className: cn(
|
|
5304
|
+
sharedStyle,
|
|
5305
|
+
"p-sm",
|
|
5306
|
+
"rounded-r-md -ml-px"
|
|
5307
|
+
),
|
|
5308
|
+
children: [
|
|
5309
|
+
/* @__PURE__ */ jsx39(
|
|
5310
|
+
Icon25,
|
|
5311
|
+
{
|
|
5312
|
+
icon: faChevronDownOutline,
|
|
5313
|
+
size: "sm",
|
|
5314
|
+
className: "text-[var(--color-btn-solid-brand-text-default)]"
|
|
5315
|
+
}
|
|
5316
|
+
),
|
|
5317
|
+
/* @__PURE__ */ jsx39("span", { className: "absolute inset-0 rounded-r-[11px] border border-[var(--color-btn-solid-brand-inner-border-default)] shadow-sm pointer-events-none" })
|
|
5318
|
+
]
|
|
5319
|
+
}
|
|
5320
|
+
)
|
|
5321
|
+
]
|
|
5322
|
+
}
|
|
5323
|
+
);
|
|
5324
|
+
}
|
|
5325
|
+
);
|
|
5326
|
+
SaveViewButton.displayName = "SaveViewButton";
|
|
5327
|
+
|
|
5328
|
+
// src/components/ui/filter/operator-selector.tsx
|
|
5329
|
+
import * as PopoverPrimitive4 from "@radix-ui/react-popover";
|
|
5330
|
+
import { jsx as jsx40, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
5331
|
+
var OperatorSelector = ({
|
|
5332
|
+
dataType,
|
|
5333
|
+
activeOperator,
|
|
5334
|
+
onSelect,
|
|
5335
|
+
open,
|
|
5336
|
+
onOpenChange,
|
|
5337
|
+
children
|
|
5338
|
+
}) => {
|
|
5339
|
+
const operators = OPERATORS_BY_TYPE[dataType];
|
|
5340
|
+
return /* @__PURE__ */ jsxs35(PopoverPrimitive4.Root, { open, onOpenChange, children: [
|
|
5341
|
+
/* @__PURE__ */ jsx40(PopoverPrimitive4.Trigger, { asChild: true, children }),
|
|
5342
|
+
/* @__PURE__ */ jsx40(PopoverPrimitive4.Portal, { children: /* @__PURE__ */ jsx40(
|
|
5343
|
+
PopoverPrimitive4.Content,
|
|
5344
|
+
{
|
|
5345
|
+
sideOffset: 4,
|
|
5346
|
+
align: "start",
|
|
5347
|
+
className: cn(
|
|
5348
|
+
"z-50 flex flex-col p-xs overflow-clip",
|
|
5349
|
+
"bg-[var(--color-dropdown-bg)] border border-[var(--color-dropdown-border)] rounded-md shadow-lg",
|
|
5350
|
+
"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
|
|
5351
|
+
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
|
|
5352
|
+
"data-[side=bottom]:slide-in-from-top-2",
|
|
5353
|
+
"min-w-[180px]"
|
|
5354
|
+
),
|
|
5355
|
+
children: operators.map((op) => /* @__PURE__ */ jsxs35(
|
|
5356
|
+
"button",
|
|
5357
|
+
{
|
|
5358
|
+
type: "button",
|
|
5359
|
+
onClick: () => onSelect(op),
|
|
5360
|
+
className: cn(
|
|
5361
|
+
"flex items-center gap-base p-base rounded-base cursor-pointer transition-colors text-left",
|
|
5362
|
+
"hover:bg-[var(--color-dropdown-item-hover)]",
|
|
5363
|
+
op === activeOperator && "bg-[var(--color-dropdown-item-hover)]"
|
|
5364
|
+
),
|
|
5365
|
+
children: [
|
|
5366
|
+
/* @__PURE__ */ jsx40(
|
|
5367
|
+
"span",
|
|
5368
|
+
{
|
|
5369
|
+
className: cn(
|
|
5370
|
+
"text-sm font-regular leading-sm",
|
|
5371
|
+
op === activeOperator ? "text-[var(--color-foreground)] font-medium" : "text-[var(--color-dropdown-item-text)]"
|
|
5372
|
+
),
|
|
5373
|
+
children: op
|
|
5374
|
+
}
|
|
5375
|
+
),
|
|
5376
|
+
isNoValueOperator(op) && /* @__PURE__ */ jsx40("span", { className: "ml-auto text-xs text-[var(--color-muted-foreground)]", children: "instant" })
|
|
5377
|
+
]
|
|
5378
|
+
},
|
|
5379
|
+
op
|
|
5380
|
+
))
|
|
5381
|
+
}
|
|
5382
|
+
) })
|
|
5383
|
+
] });
|
|
5384
|
+
};
|
|
5385
|
+
OperatorSelector.displayName = "OperatorSelector";
|
|
5386
|
+
var OperatorList = ({
|
|
5387
|
+
dataType,
|
|
5388
|
+
activeOperator,
|
|
5389
|
+
onSelect
|
|
5390
|
+
}) => {
|
|
5391
|
+
const operators = OPERATORS_BY_TYPE[dataType];
|
|
5392
|
+
return /* @__PURE__ */ jsx40("div", { className: "flex flex-col", children: operators.map((op) => /* @__PURE__ */ jsx40(
|
|
5393
|
+
"button",
|
|
5394
|
+
{
|
|
5395
|
+
type: "button",
|
|
5396
|
+
onClick: () => onSelect(op),
|
|
5397
|
+
className: cn(
|
|
5398
|
+
"flex items-center gap-base p-base rounded-base cursor-pointer transition-colors text-left",
|
|
5399
|
+
"hover:bg-[var(--color-dropdown-item-hover)]",
|
|
5400
|
+
op === activeOperator && "bg-[var(--color-dropdown-item-hover)]"
|
|
5401
|
+
),
|
|
5402
|
+
children: /* @__PURE__ */ jsx40(
|
|
5403
|
+
"span",
|
|
5404
|
+
{
|
|
5405
|
+
className: cn(
|
|
5406
|
+
"text-sm font-regular leading-sm",
|
|
5407
|
+
op === activeOperator ? "text-[var(--color-foreground)] font-medium" : "text-[var(--color-dropdown-item-text)]"
|
|
5408
|
+
),
|
|
5409
|
+
children: op
|
|
5410
|
+
}
|
|
5411
|
+
)
|
|
5412
|
+
},
|
|
5413
|
+
op
|
|
5414
|
+
)) });
|
|
5415
|
+
};
|
|
5416
|
+
OperatorList.displayName = "OperatorList";
|
|
5417
|
+
|
|
5418
|
+
// src/components/ui/filter/value-input.tsx
|
|
5419
|
+
import { jsx as jsx41, jsxs as jsxs36 } from "react/jsx-runtime";
|
|
5420
|
+
var RELATIVE_DATE_PRESETS = [
|
|
5421
|
+
{ group: "Past", options: ["Today", "Yesterday", "Last 7 days", "Last 14 days", "Last 30 days", "Last 90 days"] },
|
|
5422
|
+
{ group: "Current", options: ["This week", "This month", "This quarter", "This year"] },
|
|
5423
|
+
{ group: "Future", options: ["Tomorrow", "Next 7 days", "Next 14 days", "Next 30 days", "Next week", "Next month", "Next quarter"] }
|
|
5424
|
+
];
|
|
5425
|
+
var ValueInput = ({
|
|
5426
|
+
dataType,
|
|
5427
|
+
operator,
|
|
5428
|
+
value,
|
|
5429
|
+
onChange,
|
|
5430
|
+
onSubmit,
|
|
5431
|
+
options = [],
|
|
5432
|
+
className
|
|
5433
|
+
}) => {
|
|
5434
|
+
const inputType = getValueInputType(dataType, operator);
|
|
5435
|
+
if (!inputType) return null;
|
|
5436
|
+
const handleKeyDown = (e) => {
|
|
5437
|
+
if (e.key === "Enter") onSubmit?.();
|
|
5438
|
+
};
|
|
5439
|
+
switch (inputType) {
|
|
5440
|
+
case "TextInput":
|
|
5441
|
+
return /* @__PURE__ */ jsxs36("div", { className: cn("flex flex-col gap-base p-base", className), children: [
|
|
5442
|
+
/* @__PURE__ */ jsx41(
|
|
5443
|
+
"input",
|
|
5444
|
+
{
|
|
5445
|
+
type: "text",
|
|
5446
|
+
value: value ?? "",
|
|
5447
|
+
onChange: (e) => onChange(e.target.value),
|
|
5448
|
+
onKeyDown: handleKeyDown,
|
|
5449
|
+
placeholder: "Enter value...",
|
|
5450
|
+
autoFocus: true,
|
|
5451
|
+
className: cn(
|
|
5452
|
+
"w-full px-base py-sm rounded-base border border-[var(--color-input)]",
|
|
5453
|
+
"bg-[var(--color-background)] text-sm font-regular leading-sm text-[var(--color-foreground)]",
|
|
5454
|
+
"placeholder:text-[var(--color-muted-foreground)]",
|
|
5455
|
+
"focus:outline-none focus:ring-2 focus:ring-[var(--color-ring)] focus:ring-offset-0"
|
|
5456
|
+
)
|
|
5457
|
+
}
|
|
5458
|
+
),
|
|
5459
|
+
/* @__PURE__ */ jsx41(
|
|
5460
|
+
"button",
|
|
5461
|
+
{
|
|
5462
|
+
type: "button",
|
|
5463
|
+
onClick: onSubmit,
|
|
5464
|
+
className: "self-end px-md py-sm text-sm font-medium leading-sm text-[var(--color-primary-foreground)] bg-[var(--color-primary)] rounded-base cursor-pointer hover:opacity-90 transition-opacity",
|
|
5465
|
+
children: "Apply"
|
|
5466
|
+
}
|
|
5467
|
+
)
|
|
5468
|
+
] });
|
|
5469
|
+
case "NumberInput":
|
|
5470
|
+
return /* @__PURE__ */ jsxs36("div", { className: cn("flex flex-col gap-base p-base", className), children: [
|
|
5471
|
+
/* @__PURE__ */ jsx41(
|
|
5472
|
+
"input",
|
|
5473
|
+
{
|
|
5474
|
+
type: "number",
|
|
5475
|
+
value: value ?? "",
|
|
5476
|
+
onChange: (e) => onChange(e.target.value ? Number(e.target.value) : null),
|
|
5477
|
+
onKeyDown: handleKeyDown,
|
|
5478
|
+
placeholder: "Enter number...",
|
|
5479
|
+
autoFocus: true,
|
|
5480
|
+
className: cn(
|
|
5481
|
+
"w-full px-base py-sm rounded-base border border-[var(--color-input)]",
|
|
5482
|
+
"bg-[var(--color-background)] text-sm font-regular leading-sm text-[var(--color-foreground)]",
|
|
5483
|
+
"placeholder:text-[var(--color-muted-foreground)]",
|
|
5484
|
+
"focus:outline-none focus:ring-2 focus:ring-[var(--color-ring)] focus:ring-offset-0"
|
|
5485
|
+
)
|
|
5486
|
+
}
|
|
5487
|
+
),
|
|
5488
|
+
/* @__PURE__ */ jsx41(
|
|
5489
|
+
"button",
|
|
5490
|
+
{
|
|
5491
|
+
type: "button",
|
|
5492
|
+
onClick: onSubmit,
|
|
5493
|
+
className: "self-end px-md py-sm text-sm font-medium leading-sm text-[var(--color-primary-foreground)] bg-[var(--color-primary)] rounded-base cursor-pointer hover:opacity-90 transition-opacity",
|
|
5494
|
+
children: "Apply"
|
|
5495
|
+
}
|
|
5496
|
+
)
|
|
5497
|
+
] });
|
|
5498
|
+
case "NumberRange": {
|
|
5499
|
+
const rangeVal = value ?? [0, 0];
|
|
5500
|
+
return /* @__PURE__ */ jsxs36("div", { className: cn("flex flex-col gap-base p-base", className), children: [
|
|
5501
|
+
/* @__PURE__ */ jsxs36("div", { className: "flex items-center gap-base", children: [
|
|
5502
|
+
/* @__PURE__ */ jsx41(
|
|
5503
|
+
"input",
|
|
5504
|
+
{
|
|
5505
|
+
type: "number",
|
|
5506
|
+
value: rangeVal[0] ?? "",
|
|
5507
|
+
onChange: (e) => onChange([Number(e.target.value), rangeVal[1]]),
|
|
5508
|
+
placeholder: "Min",
|
|
5509
|
+
autoFocus: true,
|
|
5510
|
+
className: cn(
|
|
5511
|
+
"flex-1 px-base py-sm rounded-base border border-[var(--color-input)]",
|
|
5512
|
+
"bg-[var(--color-background)] text-sm font-regular leading-sm text-[var(--color-foreground)]",
|
|
5513
|
+
"focus:outline-none focus:ring-2 focus:ring-[var(--color-ring)]"
|
|
5514
|
+
)
|
|
5515
|
+
}
|
|
5516
|
+
),
|
|
5517
|
+
/* @__PURE__ */ jsx41("span", { className: "text-sm text-[var(--color-muted-foreground)]", children: "and" }),
|
|
5518
|
+
/* @__PURE__ */ jsx41(
|
|
5519
|
+
"input",
|
|
5520
|
+
{
|
|
5521
|
+
type: "number",
|
|
5522
|
+
value: rangeVal[1] ?? "",
|
|
5523
|
+
onChange: (e) => onChange([rangeVal[0], Number(e.target.value)]),
|
|
5524
|
+
placeholder: "Max",
|
|
5525
|
+
className: cn(
|
|
5526
|
+
"flex-1 px-base py-sm rounded-base border border-[var(--color-input)]",
|
|
5527
|
+
"bg-[var(--color-background)] text-sm font-regular leading-sm text-[var(--color-foreground)]",
|
|
5528
|
+
"focus:outline-none focus:ring-2 focus:ring-[var(--color-ring)]"
|
|
5529
|
+
)
|
|
5530
|
+
}
|
|
5531
|
+
)
|
|
5532
|
+
] }),
|
|
5533
|
+
/* @__PURE__ */ jsx41(
|
|
5534
|
+
"button",
|
|
5535
|
+
{
|
|
5536
|
+
type: "button",
|
|
5537
|
+
onClick: onSubmit,
|
|
5538
|
+
className: "self-end px-md py-sm text-sm font-medium leading-sm text-[var(--color-primary-foreground)] bg-[var(--color-primary)] rounded-base cursor-pointer hover:opacity-90 transition-opacity",
|
|
5539
|
+
children: "Apply"
|
|
5540
|
+
}
|
|
5541
|
+
)
|
|
5542
|
+
] });
|
|
5543
|
+
}
|
|
5544
|
+
case "PresetTags":
|
|
5545
|
+
return /* @__PURE__ */ jsx41("div", { className: cn("flex flex-col gap-base p-base max-w-[280px]", className), children: RELATIVE_DATE_PRESETS.map((group) => /* @__PURE__ */ jsxs36("div", { className: "flex flex-col gap-xs", children: [
|
|
5546
|
+
/* @__PURE__ */ jsx41("span", { className: "text-xs font-medium leading-xs text-[var(--color-muted-foreground)] uppercase px-xs", children: group.group }),
|
|
5547
|
+
/* @__PURE__ */ jsx41("div", { className: "flex flex-wrap gap-xs", children: group.options.map((preset) => /* @__PURE__ */ jsx41(
|
|
5548
|
+
"button",
|
|
5549
|
+
{
|
|
5550
|
+
type: "button",
|
|
5551
|
+
onClick: () => {
|
|
5552
|
+
onChange(preset);
|
|
5553
|
+
onSubmit?.();
|
|
5554
|
+
},
|
|
5555
|
+
className: cn(
|
|
5556
|
+
"px-base py-2xs rounded-base border cursor-pointer transition-colors text-sm font-regular leading-sm",
|
|
5557
|
+
value === preset ? "border-[var(--color-ring)] bg-[var(--color-primary)] text-[var(--color-primary-foreground)]" : "border-[var(--color-input)] bg-[var(--color-background)] text-[var(--color-foreground)] hover:bg-[var(--color-accent)]"
|
|
5558
|
+
),
|
|
5559
|
+
children: preset
|
|
5560
|
+
},
|
|
5561
|
+
preset
|
|
5562
|
+
)) })
|
|
5563
|
+
] }, group.group)) });
|
|
5564
|
+
case "SingleSelect":
|
|
5565
|
+
return /* @__PURE__ */ jsx41("div", { className: cn("flex flex-col gap-xs p-base max-h-[250px] overflow-y-auto", className), children: options.map((opt) => /* @__PURE__ */ jsx41(
|
|
5566
|
+
"button",
|
|
5567
|
+
{
|
|
5568
|
+
type: "button",
|
|
5569
|
+
onClick: () => {
|
|
5570
|
+
onChange(opt);
|
|
5571
|
+
onSubmit?.();
|
|
5572
|
+
},
|
|
5573
|
+
className: cn(
|
|
5574
|
+
"flex items-center gap-base p-base rounded-base cursor-pointer transition-colors text-left",
|
|
5575
|
+
"hover:bg-[var(--color-dropdown-item-hover)]",
|
|
5576
|
+
value === opt && "bg-[var(--color-dropdown-item-hover)]"
|
|
5577
|
+
),
|
|
5578
|
+
children: /* @__PURE__ */ jsx41("span", { className: "text-sm font-regular leading-sm text-[var(--color-foreground)]", children: opt })
|
|
5579
|
+
},
|
|
5580
|
+
opt
|
|
5581
|
+
)) });
|
|
5582
|
+
case "MultiSelect": {
|
|
5583
|
+
const selected = Array.isArray(value) ? value : [];
|
|
5584
|
+
return /* @__PURE__ */ jsxs36("div", { className: cn("flex flex-col gap-xs p-base", className), children: [
|
|
5585
|
+
/* @__PURE__ */ jsx41("div", { className: "flex flex-col max-h-[200px] overflow-y-auto", children: options.map((opt) => {
|
|
5586
|
+
const isSelected = selected.includes(opt);
|
|
5587
|
+
return /* @__PURE__ */ jsxs36(
|
|
5588
|
+
"button",
|
|
5589
|
+
{
|
|
5590
|
+
type: "button",
|
|
5591
|
+
onClick: () => {
|
|
5592
|
+
const next = isSelected ? selected.filter((s) => s !== opt) : [...selected, opt];
|
|
5593
|
+
onChange(next);
|
|
5594
|
+
},
|
|
5595
|
+
className: cn(
|
|
5596
|
+
"flex items-center gap-base p-base rounded-base cursor-pointer transition-colors text-left",
|
|
5597
|
+
"hover:bg-[var(--color-dropdown-item-hover)]"
|
|
5598
|
+
),
|
|
5599
|
+
children: [
|
|
5600
|
+
/* @__PURE__ */ jsx41(
|
|
5601
|
+
"span",
|
|
5602
|
+
{
|
|
5603
|
+
className: cn(
|
|
5604
|
+
"flex items-center justify-center size-4 rounded-xs border transition-colors",
|
|
5605
|
+
isSelected ? "bg-[var(--color-primary)] border-[var(--color-primary)]" : "border-[var(--color-input)] bg-[var(--color-background)]"
|
|
5606
|
+
),
|
|
5607
|
+
children: isSelected && /* @__PURE__ */ jsx41("svg", { width: "10", height: "10", viewBox: "0 0 10 10", fill: "none", children: /* @__PURE__ */ jsx41("path", { d: "M2 5L4 7L8 3", stroke: "white", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) })
|
|
5608
|
+
}
|
|
5609
|
+
),
|
|
5610
|
+
/* @__PURE__ */ jsx41("span", { className: "text-sm font-regular leading-sm text-[var(--color-foreground)]", children: opt })
|
|
5611
|
+
]
|
|
5612
|
+
},
|
|
5613
|
+
opt
|
|
5614
|
+
);
|
|
5615
|
+
}) }),
|
|
5616
|
+
/* @__PURE__ */ jsx41(
|
|
5617
|
+
"button",
|
|
5618
|
+
{
|
|
5619
|
+
type: "button",
|
|
5620
|
+
onClick: onSubmit,
|
|
5621
|
+
className: "self-end px-md py-sm text-sm font-medium leading-sm text-[var(--color-primary-foreground)] bg-[var(--color-primary)] rounded-base cursor-pointer hover:opacity-90 transition-opacity",
|
|
5622
|
+
children: "Apply"
|
|
5623
|
+
}
|
|
5624
|
+
)
|
|
5625
|
+
] });
|
|
5626
|
+
}
|
|
5627
|
+
// DatePicker, DateRange, RelationPicker, MultiRelationPicker
|
|
5628
|
+
// Stub as text inputs for now — will wire to actual DatePicker/relation components
|
|
5629
|
+
case "DatePicker":
|
|
5630
|
+
return /* @__PURE__ */ jsxs36("div", { className: cn("flex flex-col gap-base p-base", className), children: [
|
|
5631
|
+
/* @__PURE__ */ jsx41(
|
|
5632
|
+
"input",
|
|
5633
|
+
{
|
|
5634
|
+
type: "date",
|
|
5635
|
+
value: value instanceof Date ? value.toISOString().split("T")[0] : value ?? "",
|
|
5636
|
+
onChange: (e) => onChange(e.target.value ? new Date(e.target.value) : null),
|
|
5637
|
+
autoFocus: true,
|
|
5638
|
+
className: cn(
|
|
5639
|
+
"w-full px-base py-sm rounded-base border border-[var(--color-input)]",
|
|
5640
|
+
"bg-[var(--color-background)] text-sm font-regular leading-sm text-[var(--color-foreground)]",
|
|
5641
|
+
"focus:outline-none focus:ring-2 focus:ring-[var(--color-ring)]"
|
|
5642
|
+
)
|
|
5643
|
+
}
|
|
5644
|
+
),
|
|
5645
|
+
/* @__PURE__ */ jsx41(
|
|
5646
|
+
"button",
|
|
5647
|
+
{
|
|
5648
|
+
type: "button",
|
|
5649
|
+
onClick: onSubmit,
|
|
5650
|
+
className: "self-end px-md py-sm text-sm font-medium leading-sm text-[var(--color-primary-foreground)] bg-[var(--color-primary)] rounded-base cursor-pointer hover:opacity-90 transition-opacity",
|
|
5651
|
+
children: "Apply"
|
|
5652
|
+
}
|
|
5653
|
+
)
|
|
5654
|
+
] });
|
|
5655
|
+
case "DateRange":
|
|
5656
|
+
return /* @__PURE__ */ jsxs36("div", { className: cn("flex flex-col gap-base p-base", className), children: [
|
|
5657
|
+
/* @__PURE__ */ jsxs36("div", { className: "flex items-center gap-base", children: [
|
|
5658
|
+
/* @__PURE__ */ jsx41(
|
|
5659
|
+
"input",
|
|
5660
|
+
{
|
|
5661
|
+
type: "date",
|
|
5662
|
+
autoFocus: true,
|
|
5663
|
+
className: cn(
|
|
5664
|
+
"flex-1 px-base py-sm rounded-base border border-[var(--color-input)]",
|
|
5665
|
+
"bg-[var(--color-background)] text-sm font-regular leading-sm text-[var(--color-foreground)]",
|
|
5666
|
+
"focus:outline-none focus:ring-2 focus:ring-[var(--color-ring)]"
|
|
5667
|
+
)
|
|
5668
|
+
}
|
|
5669
|
+
),
|
|
5670
|
+
/* @__PURE__ */ jsx41("span", { className: "text-sm text-[var(--color-muted-foreground)]", children: "to" }),
|
|
5671
|
+
/* @__PURE__ */ jsx41(
|
|
5672
|
+
"input",
|
|
5673
|
+
{
|
|
5674
|
+
type: "date",
|
|
5675
|
+
className: cn(
|
|
5676
|
+
"flex-1 px-base py-sm rounded-base border border-[var(--color-input)]",
|
|
5677
|
+
"bg-[var(--color-background)] text-sm font-regular leading-sm text-[var(--color-foreground)]",
|
|
5678
|
+
"focus:outline-none focus:ring-2 focus:ring-[var(--color-ring)]"
|
|
5679
|
+
)
|
|
5680
|
+
}
|
|
5681
|
+
)
|
|
5682
|
+
] }),
|
|
5683
|
+
/* @__PURE__ */ jsx41(
|
|
5684
|
+
"button",
|
|
5685
|
+
{
|
|
5686
|
+
type: "button",
|
|
5687
|
+
onClick: onSubmit,
|
|
5688
|
+
className: "self-end px-md py-sm text-sm font-medium leading-sm text-[var(--color-primary-foreground)] bg-[var(--color-primary)] rounded-base cursor-pointer hover:opacity-90 transition-opacity",
|
|
5689
|
+
children: "Apply"
|
|
5690
|
+
}
|
|
5691
|
+
)
|
|
5692
|
+
] });
|
|
5693
|
+
case "RelationPicker":
|
|
5694
|
+
case "MultiRelationPicker":
|
|
5695
|
+
return /* @__PURE__ */ jsxs36("div", { className: cn("flex flex-col gap-base p-base", className), children: [
|
|
5696
|
+
/* @__PURE__ */ jsx41(
|
|
5697
|
+
"input",
|
|
5698
|
+
{
|
|
5699
|
+
type: "text",
|
|
5700
|
+
value: value ?? "",
|
|
5701
|
+
onChange: (e) => onChange(e.target.value),
|
|
5702
|
+
onKeyDown: handleKeyDown,
|
|
5703
|
+
placeholder: "Search...",
|
|
5704
|
+
autoFocus: true,
|
|
5705
|
+
className: cn(
|
|
5706
|
+
"w-full px-base py-sm rounded-base border border-[var(--color-input)]",
|
|
5707
|
+
"bg-[var(--color-background)] text-sm font-regular leading-sm text-[var(--color-foreground)]",
|
|
5708
|
+
"placeholder:text-[var(--color-muted-foreground)]",
|
|
5709
|
+
"focus:outline-none focus:ring-2 focus:ring-[var(--color-ring)]"
|
|
5710
|
+
)
|
|
5711
|
+
}
|
|
5712
|
+
),
|
|
5713
|
+
/* @__PURE__ */ jsx41(
|
|
5714
|
+
"button",
|
|
5715
|
+
{
|
|
5716
|
+
type: "button",
|
|
5717
|
+
onClick: onSubmit,
|
|
5718
|
+
className: "self-end px-md py-sm text-sm font-medium leading-sm text-[var(--color-primary-foreground)] bg-[var(--color-primary)] rounded-base cursor-pointer hover:opacity-90 transition-opacity",
|
|
5719
|
+
children: "Apply"
|
|
5720
|
+
}
|
|
5721
|
+
)
|
|
5722
|
+
] });
|
|
5723
|
+
default:
|
|
5724
|
+
return null;
|
|
5725
|
+
}
|
|
5726
|
+
};
|
|
5727
|
+
ValueInput.displayName = "ValueInput";
|
|
5728
|
+
|
|
5729
|
+
// src/components/ui/filter/property-selector.tsx
|
|
5730
|
+
import * as React40 from "react";
|
|
5731
|
+
import * as PopoverPrimitive5 from "@radix-ui/react-popover";
|
|
5732
|
+
import { Icon as Icon26, faChevronLeftOutline as faChevronLeftOutline2, faChevronRightOutline as faChevronRightOutline2, faMagnifyingGlassOutline } from "@l3mpire/icons";
|
|
5733
|
+
import { jsx as jsx42, jsxs as jsxs37 } from "react/jsx-runtime";
|
|
5734
|
+
var PropertySelector = ({
|
|
5735
|
+
properties,
|
|
5736
|
+
onSelect,
|
|
5737
|
+
open,
|
|
5738
|
+
onOpenChange,
|
|
5739
|
+
children
|
|
5740
|
+
}) => {
|
|
5741
|
+
const [activeGroup, setActiveGroup] = React40.useState(null);
|
|
5742
|
+
const [search, setSearch] = React40.useState("");
|
|
5743
|
+
React40.useEffect(() => {
|
|
5744
|
+
if (!open) {
|
|
5745
|
+
setActiveGroup(null);
|
|
5746
|
+
setSearch("");
|
|
5747
|
+
}
|
|
5748
|
+
}, [open]);
|
|
5749
|
+
const groups = React40.useMemo(() => {
|
|
5750
|
+
const map = /* @__PURE__ */ new Map();
|
|
5751
|
+
for (const prop of properties) {
|
|
5752
|
+
const existing = map.get(prop.group);
|
|
5753
|
+
if (existing) {
|
|
5754
|
+
existing.count++;
|
|
5755
|
+
} else {
|
|
5756
|
+
map.set(prop.group, {
|
|
5757
|
+
group: prop.group,
|
|
5758
|
+
groupLabel: prop.groupLabel,
|
|
5759
|
+
groupIcon: prop.icon,
|
|
5760
|
+
count: 1
|
|
5761
|
+
});
|
|
5762
|
+
}
|
|
5763
|
+
}
|
|
5764
|
+
return Array.from(map.values());
|
|
5765
|
+
}, [properties]);
|
|
5766
|
+
const filteredProperties = React40.useMemo(() => {
|
|
5767
|
+
if (!activeGroup) return [];
|
|
5768
|
+
const groupProps = properties.filter((p) => p.group === activeGroup);
|
|
5769
|
+
if (!search) return groupProps;
|
|
5770
|
+
const lower = search.toLowerCase();
|
|
5771
|
+
return groupProps.filter((p) => p.label.toLowerCase().includes(lower));
|
|
5772
|
+
}, [properties, activeGroup, search]);
|
|
5773
|
+
const activeGroupInfo = groups.find((g) => g.group === activeGroup);
|
|
5774
|
+
return /* @__PURE__ */ jsxs37(PopoverPrimitive5.Root, { open, onOpenChange, children: [
|
|
5775
|
+
/* @__PURE__ */ jsx42(PopoverPrimitive5.Trigger, { asChild: true, children }),
|
|
5776
|
+
/* @__PURE__ */ jsx42(PopoverPrimitive5.Portal, { children: /* @__PURE__ */ jsx42(
|
|
5777
|
+
PopoverPrimitive5.Content,
|
|
5778
|
+
{
|
|
5779
|
+
sideOffset: 4,
|
|
5780
|
+
align: "start",
|
|
5781
|
+
className: cn(
|
|
5782
|
+
"z-50 flex flex-col gap-xs overflow-clip p-xs",
|
|
5783
|
+
"bg-[var(--color-dropdown-bg)] border border-[var(--color-dropdown-border)] rounded-md shadow-lg",
|
|
5784
|
+
"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
|
|
5785
|
+
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
|
|
5786
|
+
"data-[side=bottom]:slide-in-from-top-2",
|
|
5787
|
+
"min-w-[230px]"
|
|
5788
|
+
),
|
|
5789
|
+
children: activeGroup === null ? (
|
|
5790
|
+
/* ── Level 1: Categories ─────────────────────────────────── */
|
|
5791
|
+
/* @__PURE__ */ jsx42("div", { className: "flex flex-col", children: groups.map((g) => /* @__PURE__ */ jsxs37(
|
|
5792
|
+
"button",
|
|
5793
|
+
{
|
|
5794
|
+
type: "button",
|
|
5795
|
+
onClick: () => setActiveGroup(g.group),
|
|
5796
|
+
className: "flex items-center gap-base p-base rounded-base cursor-pointer transition-colors hover:bg-[var(--color-dropdown-item-hover)]",
|
|
5797
|
+
children: [
|
|
5798
|
+
/* @__PURE__ */ jsx42(
|
|
5799
|
+
Icon26,
|
|
5800
|
+
{
|
|
5801
|
+
icon: g.groupIcon,
|
|
5802
|
+
size: "sm",
|
|
5803
|
+
className: "shrink-0 text-[var(--color-dropdown-item-icon)]"
|
|
5804
|
+
}
|
|
5805
|
+
),
|
|
5806
|
+
/* @__PURE__ */ jsx42("span", { className: "flex-1 text-sm font-regular leading-sm text-[var(--color-dropdown-item-text)] text-left truncate", children: g.groupLabel }),
|
|
5807
|
+
/* @__PURE__ */ jsx42("span", { className: "text-xs font-medium leading-xs text-[var(--color-muted-foreground)]", children: g.count }),
|
|
5808
|
+
/* @__PURE__ */ jsx42(
|
|
5809
|
+
Icon26,
|
|
5810
|
+
{
|
|
5811
|
+
icon: faChevronRightOutline2,
|
|
5812
|
+
size: "xs",
|
|
5813
|
+
className: "shrink-0 text-[var(--color-dropdown-item-icon)]"
|
|
5814
|
+
}
|
|
5815
|
+
)
|
|
5816
|
+
]
|
|
5817
|
+
},
|
|
5818
|
+
g.group
|
|
5819
|
+
)) })
|
|
5820
|
+
) : (
|
|
5821
|
+
/* ── Level 2: Properties ─────────────────────────────────── */
|
|
5822
|
+
/* @__PURE__ */ jsxs37("div", { className: "flex flex-col gap-xs", children: [
|
|
5823
|
+
/* @__PURE__ */ jsxs37(
|
|
5824
|
+
"button",
|
|
5825
|
+
{
|
|
5826
|
+
type: "button",
|
|
5827
|
+
onClick: () => {
|
|
5828
|
+
setActiveGroup(null);
|
|
5829
|
+
setSearch("");
|
|
5830
|
+
},
|
|
5831
|
+
className: "flex items-center gap-base p-base rounded-base cursor-pointer transition-colors hover:bg-[var(--color-dropdown-item-hover)]",
|
|
5832
|
+
children: [
|
|
5833
|
+
/* @__PURE__ */ jsx42(
|
|
5834
|
+
Icon26,
|
|
5835
|
+
{
|
|
5836
|
+
icon: faChevronLeftOutline2,
|
|
5837
|
+
size: "sm",
|
|
5838
|
+
className: "shrink-0 text-[var(--color-dropdown-item-icon)]"
|
|
5839
|
+
}
|
|
5840
|
+
),
|
|
5841
|
+
/* @__PURE__ */ jsx42("span", { className: "flex-1 text-xs font-medium leading-xs text-[var(--color-muted-foreground)] text-left truncate", children: activeGroupInfo?.groupLabel })
|
|
5842
|
+
]
|
|
5843
|
+
}
|
|
5844
|
+
),
|
|
5845
|
+
/* @__PURE__ */ jsxs37("div", { className: "flex items-center gap-base px-md py-base border border-[var(--color-input)] rounded-md", children: [
|
|
5846
|
+
/* @__PURE__ */ jsx42(
|
|
5847
|
+
Icon26,
|
|
5848
|
+
{
|
|
5849
|
+
icon: faMagnifyingGlassOutline,
|
|
5850
|
+
size: "sm",
|
|
5851
|
+
className: "shrink-0 text-[var(--color-muted-foreground)]"
|
|
5852
|
+
}
|
|
5853
|
+
),
|
|
5854
|
+
/* @__PURE__ */ jsx42(
|
|
5855
|
+
"input",
|
|
5856
|
+
{
|
|
5857
|
+
type: "text",
|
|
5858
|
+
value: search,
|
|
5859
|
+
onChange: (e) => setSearch(e.target.value),
|
|
5860
|
+
placeholder: "Search...",
|
|
5861
|
+
autoFocus: true,
|
|
5862
|
+
className: "flex-1 text-sm font-regular leading-sm text-[var(--color-foreground)] bg-transparent outline-none placeholder:text-[var(--color-muted-foreground)]"
|
|
5863
|
+
}
|
|
5864
|
+
)
|
|
5865
|
+
] }),
|
|
5866
|
+
/* @__PURE__ */ jsxs37("div", { className: "flex flex-col max-h-[300px] overflow-y-auto", children: [
|
|
5867
|
+
filteredProperties.map((prop) => /* @__PURE__ */ jsxs37(
|
|
5868
|
+
"button",
|
|
5869
|
+
{
|
|
5870
|
+
type: "button",
|
|
5871
|
+
onClick: () => {
|
|
5872
|
+
onSelect(prop);
|
|
5873
|
+
onOpenChange?.(false);
|
|
5874
|
+
},
|
|
5875
|
+
className: "flex items-center gap-base p-base rounded-base cursor-pointer transition-colors hover:bg-[var(--color-dropdown-item-hover)]",
|
|
5876
|
+
children: [
|
|
5877
|
+
/* @__PURE__ */ jsx42(
|
|
5878
|
+
Icon26,
|
|
5879
|
+
{
|
|
5880
|
+
icon: prop.icon,
|
|
5881
|
+
size: "sm",
|
|
5882
|
+
className: "shrink-0 text-[var(--color-dropdown-item-icon)]"
|
|
5883
|
+
}
|
|
5884
|
+
),
|
|
5885
|
+
/* @__PURE__ */ jsx42("span", { className: "flex-1 text-sm font-regular leading-sm text-[var(--color-dropdown-item-text)] text-left truncate", children: prop.label })
|
|
5886
|
+
]
|
|
5887
|
+
},
|
|
5888
|
+
prop.id
|
|
5889
|
+
)),
|
|
5890
|
+
filteredProperties.length === 0 && /* @__PURE__ */ jsx42("span", { className: "p-base text-sm text-[var(--color-muted-foreground)]", children: "No results" })
|
|
5891
|
+
] })
|
|
5892
|
+
] })
|
|
5893
|
+
)
|
|
5894
|
+
}
|
|
5895
|
+
) })
|
|
5896
|
+
] });
|
|
5897
|
+
};
|
|
5898
|
+
PropertySelector.displayName = "PropertySelector";
|
|
5899
|
+
|
|
5900
|
+
// src/components/ui/filter/kebab-menu.tsx
|
|
5901
|
+
import * as PopoverPrimitive6 from "@radix-ui/react-popover";
|
|
5902
|
+
import { Icon as Icon27, faArrowRightOutline, faTrashOutline } from "@l3mpire/icons";
|
|
5903
|
+
import { jsx as jsx43, jsxs as jsxs38 } from "react/jsx-runtime";
|
|
5904
|
+
var KebabMenu = ({
|
|
5905
|
+
onConvertToAdvanced,
|
|
5906
|
+
onDelete,
|
|
5907
|
+
open,
|
|
5908
|
+
onOpenChange,
|
|
5909
|
+
children
|
|
5910
|
+
}) => /* @__PURE__ */ jsxs38(PopoverPrimitive6.Root, { open, onOpenChange, children: [
|
|
5911
|
+
/* @__PURE__ */ jsx43(PopoverPrimitive6.Trigger, { asChild: true, children }),
|
|
5912
|
+
/* @__PURE__ */ jsx43(PopoverPrimitive6.Portal, { children: /* @__PURE__ */ jsxs38(
|
|
5913
|
+
PopoverPrimitive6.Content,
|
|
5914
|
+
{
|
|
5915
|
+
sideOffset: 4,
|
|
5916
|
+
align: "end",
|
|
5917
|
+
className: cn(
|
|
5918
|
+
"z-50 flex flex-col p-xs overflow-clip",
|
|
5919
|
+
"bg-[var(--color-dropdown-bg)] border border-[var(--color-dropdown-border)] rounded-md shadow-lg",
|
|
5920
|
+
"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
|
|
5921
|
+
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
|
|
5922
|
+
"data-[side=bottom]:slide-in-from-top-2",
|
|
5923
|
+
"min-w-[210px]"
|
|
5924
|
+
),
|
|
5925
|
+
children: [
|
|
5926
|
+
onConvertToAdvanced && /* @__PURE__ */ jsxs38(
|
|
5927
|
+
"button",
|
|
5928
|
+
{
|
|
5929
|
+
type: "button",
|
|
5930
|
+
onClick: () => {
|
|
5931
|
+
onConvertToAdvanced();
|
|
5932
|
+
onOpenChange?.(false);
|
|
5933
|
+
},
|
|
5934
|
+
className: "flex items-center gap-base p-base rounded-base cursor-pointer transition-colors hover:bg-[var(--color-dropdown-item-hover)]",
|
|
5935
|
+
children: [
|
|
5936
|
+
/* @__PURE__ */ jsx43(
|
|
5937
|
+
Icon27,
|
|
5938
|
+
{
|
|
5939
|
+
icon: faArrowRightOutline,
|
|
5940
|
+
size: "sm",
|
|
5941
|
+
className: "shrink-0 text-[var(--color-dropdown-item-icon)]"
|
|
5942
|
+
}
|
|
5943
|
+
),
|
|
5944
|
+
/* @__PURE__ */ jsx43("span", { className: "text-sm font-regular leading-sm text-[var(--color-dropdown-item-text)]", children: "Convert to advanced" })
|
|
5945
|
+
]
|
|
5946
|
+
}
|
|
5947
|
+
),
|
|
5948
|
+
onConvertToAdvanced && onDelete && /* @__PURE__ */ jsx43("div", { className: "h-px mx-base my-xs bg-[var(--color-border)]" }),
|
|
5949
|
+
onDelete && /* @__PURE__ */ jsxs38(
|
|
5950
|
+
"button",
|
|
5951
|
+
{
|
|
5952
|
+
type: "button",
|
|
5953
|
+
onClick: () => {
|
|
5954
|
+
onDelete();
|
|
5955
|
+
onOpenChange?.(false);
|
|
5956
|
+
},
|
|
5957
|
+
className: "flex items-center gap-base p-base rounded-base cursor-pointer transition-colors hover:bg-[var(--color-dropdown-item-hover)]",
|
|
5958
|
+
children: [
|
|
5959
|
+
/* @__PURE__ */ jsx43(
|
|
5960
|
+
Icon27,
|
|
5961
|
+
{
|
|
5962
|
+
icon: faTrashOutline,
|
|
5963
|
+
size: "sm",
|
|
5964
|
+
className: "shrink-0 text-[var(--color-destructive)]"
|
|
5965
|
+
}
|
|
5966
|
+
),
|
|
5967
|
+
/* @__PURE__ */ jsx43("span", { className: "text-sm font-regular leading-sm text-[var(--color-destructive)]", children: "Delete filter" })
|
|
5968
|
+
]
|
|
5969
|
+
}
|
|
5970
|
+
)
|
|
5971
|
+
]
|
|
5972
|
+
}
|
|
5973
|
+
) })
|
|
5974
|
+
] });
|
|
5975
|
+
KebabMenu.displayName = "KebabMenu";
|
|
5976
|
+
|
|
5977
|
+
// src/components/ui/filter/filter-editor.tsx
|
|
5978
|
+
import * as React41 from "react";
|
|
5979
|
+
import * as PopoverPrimitive7 from "@radix-ui/react-popover";
|
|
5980
|
+
import { Icon as Icon28 } from "@l3mpire/icons";
|
|
5981
|
+
import { jsx as jsx44, jsxs as jsxs39 } from "react/jsx-runtime";
|
|
5982
|
+
var FilterEditor = ({
|
|
5983
|
+
propertyDef,
|
|
5984
|
+
condition,
|
|
5985
|
+
mode,
|
|
5986
|
+
onUpdate,
|
|
5987
|
+
onClose,
|
|
5988
|
+
open,
|
|
5989
|
+
onOpenChange,
|
|
5990
|
+
children
|
|
5991
|
+
}) => {
|
|
5992
|
+
const [view, setView] = React41.useState(
|
|
5993
|
+
mode === "add" ? "value" : "operator"
|
|
5994
|
+
);
|
|
5995
|
+
const [localOperator, setLocalOperator] = React41.useState(
|
|
5996
|
+
condition.operator
|
|
5997
|
+
);
|
|
5998
|
+
const [localValue, setLocalValue] = React41.useState(
|
|
5999
|
+
condition.value
|
|
6000
|
+
);
|
|
6001
|
+
React41.useEffect(() => {
|
|
6002
|
+
if (open) {
|
|
6003
|
+
setView(mode === "add" ? "value" : "operator");
|
|
6004
|
+
setLocalOperator(condition.operator);
|
|
6005
|
+
setLocalValue(condition.value);
|
|
6006
|
+
}
|
|
6007
|
+
}, [open, mode, condition.operator, condition.value]);
|
|
6008
|
+
const handleOperatorSelect = (op) => {
|
|
6009
|
+
setLocalOperator(op);
|
|
6010
|
+
if (isNoValueOperator(op)) {
|
|
6011
|
+
onUpdate({ ...condition, operator: op, value: null });
|
|
6012
|
+
onOpenChange?.(false);
|
|
6013
|
+
onClose();
|
|
6014
|
+
} else {
|
|
6015
|
+
if (op !== localOperator) {
|
|
6016
|
+
setLocalValue(null);
|
|
6017
|
+
}
|
|
6018
|
+
setView("value");
|
|
6019
|
+
}
|
|
6020
|
+
};
|
|
6021
|
+
const handleSubmit = () => {
|
|
6022
|
+
onUpdate({ ...condition, operator: localOperator, value: localValue });
|
|
6023
|
+
onOpenChange?.(false);
|
|
6024
|
+
onClose();
|
|
6025
|
+
};
|
|
6026
|
+
return /* @__PURE__ */ jsxs39(PopoverPrimitive7.Root, { open, onOpenChange, children: [
|
|
6027
|
+
/* @__PURE__ */ jsx44(PopoverPrimitive7.Trigger, { asChild: true, children }),
|
|
6028
|
+
/* @__PURE__ */ jsx44(PopoverPrimitive7.Portal, { children: /* @__PURE__ */ jsxs39(
|
|
6029
|
+
PopoverPrimitive7.Content,
|
|
6030
|
+
{
|
|
6031
|
+
sideOffset: 4,
|
|
6032
|
+
align: "start",
|
|
6033
|
+
className: cn(
|
|
6034
|
+
"z-50 flex flex-col overflow-clip",
|
|
6035
|
+
"bg-[var(--color-dropdown-bg)] border border-[var(--color-dropdown-border)] rounded-md shadow-lg",
|
|
6036
|
+
"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
|
|
6037
|
+
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
|
|
6038
|
+
"data-[side=bottom]:slide-in-from-top-2",
|
|
6039
|
+
"min-w-[240px]"
|
|
6040
|
+
),
|
|
6041
|
+
children: [
|
|
6042
|
+
/* @__PURE__ */ jsxs39("div", { className: "flex items-center gap-base px-base pt-base pb-xs border-b border-[var(--color-border)]", children: [
|
|
6043
|
+
/* @__PURE__ */ jsx44(
|
|
6044
|
+
Icon28,
|
|
6045
|
+
{
|
|
6046
|
+
icon: propertyDef.icon,
|
|
6047
|
+
size: "sm",
|
|
6048
|
+
className: "shrink-0 text-[var(--color-dropdown-item-icon)]"
|
|
6049
|
+
}
|
|
6050
|
+
),
|
|
6051
|
+
/* @__PURE__ */ jsx44("span", { className: "text-sm font-medium leading-sm text-[var(--color-foreground)]", children: propertyDef.label }),
|
|
6052
|
+
localOperator && view === "value" && /* @__PURE__ */ jsxs39(
|
|
6053
|
+
"button",
|
|
6054
|
+
{
|
|
6055
|
+
type: "button",
|
|
6056
|
+
onClick: () => setView("operator"),
|
|
6057
|
+
className: "ml-auto text-xs font-regular text-[var(--color-muted-foreground)] hover:text-[var(--color-foreground)] cursor-pointer transition-colors",
|
|
6058
|
+
children: [
|
|
6059
|
+
localOperator,
|
|
6060
|
+
" \u25BE"
|
|
6061
|
+
]
|
|
6062
|
+
}
|
|
6063
|
+
)
|
|
6064
|
+
] }),
|
|
6065
|
+
view === "operator" ? /* @__PURE__ */ jsx44("div", { className: "p-xs", children: /* @__PURE__ */ jsx44(
|
|
6066
|
+
OperatorList,
|
|
6067
|
+
{
|
|
6068
|
+
dataType: propertyDef.type,
|
|
6069
|
+
activeOperator: localOperator,
|
|
6070
|
+
onSelect: handleOperatorSelect
|
|
6071
|
+
}
|
|
6072
|
+
) }) : localOperator && /* @__PURE__ */ jsx44(
|
|
6073
|
+
ValueInput,
|
|
6074
|
+
{
|
|
6075
|
+
dataType: propertyDef.type,
|
|
6076
|
+
operator: localOperator,
|
|
6077
|
+
value: localValue,
|
|
6078
|
+
onChange: setLocalValue,
|
|
6079
|
+
onSubmit: handleSubmit,
|
|
6080
|
+
options: propertyDef.options
|
|
6081
|
+
}
|
|
6082
|
+
)
|
|
6083
|
+
]
|
|
6084
|
+
}
|
|
6085
|
+
) })
|
|
6086
|
+
] });
|
|
6087
|
+
};
|
|
6088
|
+
FilterEditor.displayName = "FilterEditor";
|
|
6089
|
+
|
|
6090
|
+
// src/components/ui/filter/interactive-filter-chip.tsx
|
|
6091
|
+
import * as React42 from "react";
|
|
6092
|
+
import * as PopoverPrimitive8 from "@radix-ui/react-popover";
|
|
6093
|
+
import { jsx as jsx45, jsxs as jsxs40 } from "react/jsx-runtime";
|
|
6094
|
+
function formatFilterValue(value) {
|
|
6095
|
+
if (value == null) return void 0;
|
|
6096
|
+
if (typeof value === "boolean") return value ? "Yes" : "No";
|
|
6097
|
+
if (value instanceof Date) {
|
|
6098
|
+
return value.toLocaleDateString("en-US", {
|
|
6099
|
+
month: "short",
|
|
6100
|
+
day: "numeric",
|
|
6101
|
+
year: "numeric"
|
|
6102
|
+
});
|
|
6103
|
+
}
|
|
6104
|
+
if (Array.isArray(value)) {
|
|
6105
|
+
if (value.length === 0) return void 0;
|
|
6106
|
+
if (value.length === 2 && typeof value[0] === "number") {
|
|
6107
|
+
return `${value[0]} \u2013 ${value[1]}`;
|
|
6108
|
+
}
|
|
6109
|
+
return value[0];
|
|
6110
|
+
}
|
|
6111
|
+
return String(value);
|
|
6112
|
+
}
|
|
6113
|
+
function getBadgeCount(value) {
|
|
6114
|
+
if (Array.isArray(value) && value.length > 1 && typeof value[0] === "string") {
|
|
6115
|
+
return value.length;
|
|
6116
|
+
}
|
|
6117
|
+
return void 0;
|
|
6118
|
+
}
|
|
6119
|
+
var SegmentPopover = ({
|
|
6120
|
+
open,
|
|
6121
|
+
onOpenChange,
|
|
6122
|
+
trigger,
|
|
6123
|
+
children,
|
|
6124
|
+
align = "start",
|
|
6125
|
+
minWidth = "240px"
|
|
6126
|
+
}) => /* @__PURE__ */ jsxs40(PopoverPrimitive8.Root, { open, onOpenChange, children: [
|
|
6127
|
+
/* @__PURE__ */ jsx45(PopoverPrimitive8.Trigger, { asChild: true, children: trigger }),
|
|
6128
|
+
/* @__PURE__ */ jsx45(PopoverPrimitive8.Portal, { children: /* @__PURE__ */ jsx45(
|
|
6129
|
+
PopoverPrimitive8.Content,
|
|
6130
|
+
{
|
|
6131
|
+
sideOffset: 4,
|
|
6132
|
+
align,
|
|
6133
|
+
className: cn(
|
|
6134
|
+
"z-50 flex flex-col overflow-clip",
|
|
6135
|
+
"bg-[var(--color-dropdown-bg)] border border-[var(--color-dropdown-border)] rounded-md shadow-lg",
|
|
6136
|
+
"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
|
|
6137
|
+
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
|
|
6138
|
+
"data-[side=bottom]:slide-in-from-top-2"
|
|
6139
|
+
),
|
|
6140
|
+
style: { minWidth },
|
|
6141
|
+
children
|
|
6142
|
+
}
|
|
6143
|
+
) })
|
|
6144
|
+
] });
|
|
6145
|
+
var InteractiveFilterChip = ({
|
|
6146
|
+
propertyDef,
|
|
6147
|
+
condition,
|
|
6148
|
+
properties,
|
|
6149
|
+
mode = "edit",
|
|
6150
|
+
autoOpen = false,
|
|
6151
|
+
onUpdate,
|
|
6152
|
+
onPropertyChange,
|
|
6153
|
+
onDelete,
|
|
6154
|
+
onConvertToAdvanced,
|
|
6155
|
+
className
|
|
6156
|
+
}) => {
|
|
6157
|
+
const [operatorOpen, setOperatorOpen] = React42.useState(false);
|
|
6158
|
+
const [valueOpen, setValueOpen] = React42.useState(false);
|
|
6159
|
+
const [propertyOpen, setPropertyOpen] = React42.useState(false);
|
|
6160
|
+
const [kebabOpen, setKebabOpen] = React42.useState(false);
|
|
6161
|
+
React42.useEffect(() => {
|
|
6162
|
+
if (autoOpen && condition.operator && !isNoValueOperator(condition.operator)) {
|
|
6163
|
+
const t = setTimeout(() => setValueOpen(true), 50);
|
|
6164
|
+
return () => clearTimeout(t);
|
|
6165
|
+
}
|
|
6166
|
+
}, []);
|
|
6167
|
+
const handleOperatorSelect = (op) => {
|
|
6168
|
+
if (isNoValueOperator(op)) {
|
|
6169
|
+
onUpdate({ ...condition, operator: op, value: null });
|
|
6170
|
+
setOperatorOpen(false);
|
|
6171
|
+
} else {
|
|
6172
|
+
const resetValue = op !== condition.operator ? null : condition.value;
|
|
6173
|
+
onUpdate({ ...condition, operator: op, value: resetValue });
|
|
6174
|
+
setOperatorOpen(false);
|
|
6175
|
+
if (resetValue == null) {
|
|
6176
|
+
setTimeout(() => setValueOpen(true), 100);
|
|
6177
|
+
}
|
|
6178
|
+
}
|
|
6179
|
+
};
|
|
6180
|
+
const handleValueChange = (val) => {
|
|
6181
|
+
onUpdate({ ...condition, value: val });
|
|
6182
|
+
};
|
|
6183
|
+
const handleValueSubmit = () => {
|
|
6184
|
+
setValueOpen(false);
|
|
6185
|
+
};
|
|
6186
|
+
const hasOperator = !!condition.operator;
|
|
6187
|
+
const displayValue = formatFilterValue(condition.value);
|
|
6188
|
+
const hasValue = hasOperator && displayValue != null;
|
|
6189
|
+
const badgeCount = getBadgeCount(condition.value);
|
|
6190
|
+
return /* @__PURE__ */ jsxs40(
|
|
6191
|
+
"div",
|
|
6192
|
+
{
|
|
6193
|
+
className: cn(
|
|
6194
|
+
"inline-flex items-center overflow-clip",
|
|
6195
|
+
"bg-filter-chip-bg border border-filter-chip-border rounded-md",
|
|
6196
|
+
className
|
|
6197
|
+
),
|
|
6198
|
+
children: [
|
|
6199
|
+
properties ? /* @__PURE__ */ jsx45(
|
|
6200
|
+
PropertySelector,
|
|
6201
|
+
{
|
|
6202
|
+
properties,
|
|
6203
|
+
onSelect: (prop) => {
|
|
6204
|
+
onPropertyChange?.(prop);
|
|
6205
|
+
setPropertyOpen(false);
|
|
6206
|
+
},
|
|
6207
|
+
open: propertyOpen,
|
|
6208
|
+
onOpenChange: setPropertyOpen,
|
|
6209
|
+
children: /* @__PURE__ */ jsx45("div", { children: /* @__PURE__ */ jsx45(
|
|
6210
|
+
FilterChipSegment,
|
|
6211
|
+
{
|
|
6212
|
+
segmentType: "property",
|
|
6213
|
+
hasBorder: true,
|
|
6214
|
+
icon: propertyDef.icon,
|
|
6215
|
+
label: propertyDef.label,
|
|
6216
|
+
onClick: () => setPropertyOpen(true)
|
|
6217
|
+
}
|
|
6218
|
+
) })
|
|
6219
|
+
}
|
|
6220
|
+
) : /* @__PURE__ */ jsx45(
|
|
6221
|
+
FilterChipSegment,
|
|
6222
|
+
{
|
|
6223
|
+
segmentType: "property",
|
|
6224
|
+
hasBorder: true,
|
|
6225
|
+
icon: propertyDef.icon,
|
|
6226
|
+
label: propertyDef.label
|
|
6227
|
+
}
|
|
6228
|
+
),
|
|
6229
|
+
/* @__PURE__ */ jsx45(
|
|
6230
|
+
SegmentPopover,
|
|
6231
|
+
{
|
|
6232
|
+
open: operatorOpen,
|
|
6233
|
+
onOpenChange: setOperatorOpen,
|
|
6234
|
+
minWidth: "180px",
|
|
6235
|
+
trigger: /* @__PURE__ */ jsx45("div", { children: /* @__PURE__ */ jsx45(
|
|
6236
|
+
FilterChipSegment,
|
|
6237
|
+
{
|
|
6238
|
+
segmentType: hasOperator ? "operator" : "placeholder",
|
|
6239
|
+
hasBorder: true,
|
|
6240
|
+
label: hasOperator ? condition.operator : "Select condition",
|
|
6241
|
+
onClick: () => setOperatorOpen(true)
|
|
6242
|
+
}
|
|
6243
|
+
) }),
|
|
6244
|
+
children: /* @__PURE__ */ jsx45("div", { className: "p-xs", children: /* @__PURE__ */ jsx45(
|
|
6245
|
+
OperatorList,
|
|
6246
|
+
{
|
|
6247
|
+
dataType: propertyDef.type,
|
|
6248
|
+
activeOperator: condition.operator,
|
|
6249
|
+
onSelect: handleOperatorSelect
|
|
6250
|
+
}
|
|
6251
|
+
) })
|
|
6252
|
+
}
|
|
6253
|
+
),
|
|
6254
|
+
hasOperator && condition.operator && !isNoValueOperator(condition.operator) && /* @__PURE__ */ jsx45(
|
|
6255
|
+
SegmentPopover,
|
|
6256
|
+
{
|
|
6257
|
+
open: valueOpen,
|
|
6258
|
+
onOpenChange: setValueOpen,
|
|
6259
|
+
minWidth: "240px",
|
|
6260
|
+
trigger: /* @__PURE__ */ jsx45("div", { children: /* @__PURE__ */ jsx45(
|
|
6261
|
+
FilterChipSegment,
|
|
6262
|
+
{
|
|
6263
|
+
segmentType: hasValue ? "value" : "placeholder",
|
|
6264
|
+
hasBorder: true,
|
|
6265
|
+
label: hasValue ? displayValue : "Enter value",
|
|
6266
|
+
badgeCount,
|
|
6267
|
+
onClick: () => setValueOpen(true)
|
|
6268
|
+
}
|
|
6269
|
+
) }),
|
|
6270
|
+
children: /* @__PURE__ */ jsx45(
|
|
6271
|
+
ValueInput,
|
|
6272
|
+
{
|
|
6273
|
+
dataType: propertyDef.type,
|
|
6274
|
+
operator: condition.operator,
|
|
6275
|
+
value: condition.value,
|
|
6276
|
+
onChange: handleValueChange,
|
|
6277
|
+
onSubmit: handleValueSubmit,
|
|
6278
|
+
options: propertyDef.options
|
|
6279
|
+
}
|
|
6280
|
+
)
|
|
6281
|
+
}
|
|
6282
|
+
),
|
|
6283
|
+
hasOperator && condition.operator && isNoValueOperator(condition.operator) && /* @__PURE__ */ jsx45(
|
|
6284
|
+
FilterChipSegment,
|
|
6285
|
+
{
|
|
6286
|
+
segmentType: "value",
|
|
6287
|
+
hasBorder: true,
|
|
6288
|
+
label: condition.operator
|
|
6289
|
+
}
|
|
6290
|
+
),
|
|
6291
|
+
hasOperator && /* @__PURE__ */ jsx45(
|
|
6292
|
+
KebabMenu,
|
|
6293
|
+
{
|
|
6294
|
+
open: kebabOpen,
|
|
6295
|
+
onOpenChange: setKebabOpen,
|
|
6296
|
+
onConvertToAdvanced,
|
|
6297
|
+
onDelete,
|
|
6298
|
+
children: /* @__PURE__ */ jsx45("div", { children: /* @__PURE__ */ jsx45(
|
|
6299
|
+
FilterChipSegment,
|
|
6300
|
+
{
|
|
6301
|
+
segmentType: "button",
|
|
6302
|
+
onKebabClick: (e) => {
|
|
6303
|
+
e.stopPropagation();
|
|
6304
|
+
setKebabOpen(true);
|
|
6305
|
+
}
|
|
6306
|
+
}
|
|
6307
|
+
) })
|
|
6308
|
+
}
|
|
6309
|
+
)
|
|
6310
|
+
]
|
|
6311
|
+
}
|
|
6312
|
+
);
|
|
6313
|
+
};
|
|
6314
|
+
InteractiveFilterChip.displayName = "InteractiveFilterChip";
|
|
6315
|
+
|
|
6316
|
+
// src/components/ui/filter/filter-system.tsx
|
|
6317
|
+
import * as React46 from "react";
|
|
6318
|
+
|
|
6319
|
+
// src/components/ui/filter/advanced-chip.tsx
|
|
6320
|
+
import * as React43 from "react";
|
|
6321
|
+
import { Icon as Icon29, faXmarkOutline as faXmarkOutline2 } from "@l3mpire/icons";
|
|
6322
|
+
import { Fragment as Fragment4, jsx as jsx46, jsxs as jsxs41 } from "react/jsx-runtime";
|
|
6323
|
+
var AdvancedChip = React43.forwardRef(
|
|
6324
|
+
({ className, count, onClear, onClick, ...props }, ref) => /* @__PURE__ */ jsxs41(
|
|
6325
|
+
"div",
|
|
6326
|
+
{
|
|
6327
|
+
className: cn(
|
|
6328
|
+
"inline-flex items-center overflow-clip",
|
|
6329
|
+
"bg-[var(--color-primary)]/5 border border-[var(--color-primary)]/30 rounded-md",
|
|
6330
|
+
className
|
|
6331
|
+
),
|
|
6332
|
+
children: [
|
|
6333
|
+
/* @__PURE__ */ jsxs41(
|
|
6334
|
+
"button",
|
|
6335
|
+
{
|
|
6336
|
+
ref,
|
|
6337
|
+
type: "button",
|
|
6338
|
+
onClick,
|
|
6339
|
+
className: "flex items-center gap-sm px-base py-sm cursor-pointer transition-colors hover:bg-[var(--color-primary)]/10",
|
|
6340
|
+
...props,
|
|
6341
|
+
children: [
|
|
6342
|
+
/* @__PURE__ */ jsx46("span", { className: "text-sm font-medium leading-sm whitespace-nowrap text-[var(--color-primary)]", children: "Advanced filter" }),
|
|
6343
|
+
/* @__PURE__ */ jsx46("span", { className: "flex items-center p-2xs rounded-xs bg-filter-chip-badge-bg", children: /* @__PURE__ */ jsx46("span", { className: "text-[10px] font-medium leading-2xs text-filter-chip-badge-text", children: count }) })
|
|
6344
|
+
]
|
|
6345
|
+
}
|
|
6346
|
+
),
|
|
6347
|
+
onClear && /* @__PURE__ */ jsxs41(Fragment4, { children: [
|
|
6348
|
+
/* @__PURE__ */ jsx46("span", { className: "w-px h-4 bg-[var(--color-primary)]/20" }),
|
|
6349
|
+
/* @__PURE__ */ jsx46(
|
|
6350
|
+
"button",
|
|
6351
|
+
{
|
|
6352
|
+
type: "button",
|
|
6353
|
+
onClick: (e) => {
|
|
6354
|
+
e.stopPropagation();
|
|
6355
|
+
onClear();
|
|
6356
|
+
},
|
|
6357
|
+
className: "flex items-center justify-center p-sm cursor-pointer transition-colors hover:bg-[var(--color-primary)]/10",
|
|
6358
|
+
"aria-label": "Clear all advanced filters",
|
|
6359
|
+
children: /* @__PURE__ */ jsx46(Icon29, { icon: faXmarkOutline2, size: "xs", className: "text-[var(--color-primary)]" })
|
|
6360
|
+
}
|
|
6361
|
+
)
|
|
6362
|
+
] })
|
|
6363
|
+
]
|
|
6364
|
+
}
|
|
6365
|
+
)
|
|
6366
|
+
);
|
|
6367
|
+
AdvancedChip.displayName = "AdvancedChip";
|
|
6368
|
+
|
|
6369
|
+
// src/components/ui/filter/advanced-popover.tsx
|
|
6370
|
+
import * as React45 from "react";
|
|
6371
|
+
import * as PopoverPrimitive10 from "@radix-ui/react-popover";
|
|
6372
|
+
|
|
6373
|
+
// src/components/ui/filter/advanced-row.tsx
|
|
6374
|
+
import * as React44 from "react";
|
|
6375
|
+
import * as PopoverPrimitive9 from "@radix-ui/react-popover";
|
|
6376
|
+
import { Icon as Icon30, faEllipsisVerticalOutline, faRefreshOutline } from "@l3mpire/icons";
|
|
6377
|
+
import { jsx as jsx47, jsxs as jsxs42 } from "react/jsx-runtime";
|
|
6378
|
+
var AdvancedRow = ({
|
|
6379
|
+
connector,
|
|
6380
|
+
propertyDef,
|
|
6381
|
+
condition,
|
|
6382
|
+
properties,
|
|
6383
|
+
onUpdate,
|
|
6384
|
+
onPropertyChange,
|
|
6385
|
+
onDelete
|
|
6386
|
+
}) => {
|
|
6387
|
+
const [operatorOpen, setOperatorOpen] = React44.useState(false);
|
|
6388
|
+
const [valueOpen, setValueOpen] = React44.useState(false);
|
|
6389
|
+
const [propertyOpen, setPropertyOpen] = React44.useState(false);
|
|
6390
|
+
const handleOperatorSelect = (op) => {
|
|
6391
|
+
if (isNoValueOperator(op)) {
|
|
6392
|
+
onUpdate({ ...condition, operator: op, value: null });
|
|
6393
|
+
} else {
|
|
6394
|
+
const resetValue = op !== condition.operator ? null : condition.value;
|
|
6395
|
+
onUpdate({ ...condition, operator: op, value: resetValue });
|
|
6396
|
+
}
|
|
6397
|
+
setOperatorOpen(false);
|
|
6398
|
+
};
|
|
6399
|
+
const handleValueChange = (val) => {
|
|
6400
|
+
onUpdate({ ...condition, value: val });
|
|
6401
|
+
};
|
|
6402
|
+
const displayValue = condition.value == null ? "" : typeof condition.value === "string" ? condition.value : String(condition.value);
|
|
6403
|
+
const groupedProps = React44.useMemo(() => {
|
|
6404
|
+
const map = /* @__PURE__ */ new Map();
|
|
6405
|
+
for (const p of properties) {
|
|
6406
|
+
const arr = map.get(p.group) ?? [];
|
|
6407
|
+
arr.push(p);
|
|
6408
|
+
map.set(p.group, arr);
|
|
6409
|
+
}
|
|
6410
|
+
return map;
|
|
6411
|
+
}, [properties]);
|
|
6412
|
+
return /* @__PURE__ */ jsxs42("div", { className: "group flex items-center gap-base py-xs", children: [
|
|
6413
|
+
/* @__PURE__ */ jsx47(
|
|
6414
|
+
"span",
|
|
6415
|
+
{
|
|
6416
|
+
className: cn(
|
|
6417
|
+
"shrink-0 w-[52px] text-xs font-medium leading-xs text-right",
|
|
6418
|
+
connector === "Where" ? "text-[var(--color-muted-foreground)]" : "text-[var(--color-muted-foreground)]"
|
|
6419
|
+
),
|
|
6420
|
+
children: /* @__PURE__ */ jsxs42("span", { className: "flex items-center justify-end gap-2xs", children: [
|
|
6421
|
+
connector,
|
|
6422
|
+
connector === "And" && /* @__PURE__ */ jsx47(Icon30, { icon: faRefreshOutline, size: "xs", className: "text-[var(--color-muted-foreground)]" })
|
|
6423
|
+
] })
|
|
6424
|
+
}
|
|
6425
|
+
),
|
|
6426
|
+
/* @__PURE__ */ jsxs42(PopoverPrimitive9.Root, { open: propertyOpen, onOpenChange: setPropertyOpen, children: [
|
|
6427
|
+
/* @__PURE__ */ jsx47(PopoverPrimitive9.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs42(
|
|
6428
|
+
"button",
|
|
6429
|
+
{
|
|
6430
|
+
type: "button",
|
|
6431
|
+
className: "flex items-center gap-xs px-base py-sm rounded-base border border-[var(--color-input)] bg-[var(--color-background)] cursor-pointer hover:bg-[var(--color-accent)] transition-colors",
|
|
6432
|
+
children: [
|
|
6433
|
+
/* @__PURE__ */ jsx47(Icon30, { icon: propertyDef.icon, size: "xs", className: "text-[var(--color-muted-foreground)]" }),
|
|
6434
|
+
/* @__PURE__ */ jsxs42("span", { className: "text-sm font-regular leading-sm text-[var(--color-foreground)] whitespace-nowrap", children: [
|
|
6435
|
+
propertyDef.groupLabel,
|
|
6436
|
+
" \u203A ",
|
|
6437
|
+
propertyDef.label
|
|
6438
|
+
] }),
|
|
6439
|
+
/* @__PURE__ */ jsx47("svg", { width: "10", height: "10", viewBox: "0 0 10 10", fill: "currentColor", className: "text-[var(--color-muted-foreground)]", children: /* @__PURE__ */ jsx47("path", { d: "M2.5 4L5 6.5L7.5 4", stroke: "currentColor", strokeWidth: "1.2", fill: "none", strokeLinecap: "round" }) })
|
|
6440
|
+
]
|
|
6441
|
+
}
|
|
6442
|
+
) }),
|
|
6443
|
+
/* @__PURE__ */ jsx47(PopoverPrimitive9.Portal, { children: /* @__PURE__ */ jsx47(
|
|
6444
|
+
PopoverPrimitive9.Content,
|
|
6445
|
+
{
|
|
6446
|
+
sideOffset: 4,
|
|
6447
|
+
align: "start",
|
|
6448
|
+
className: cn(
|
|
6449
|
+
"z-50 flex flex-col p-xs overflow-clip max-h-[300px] overflow-y-auto",
|
|
6450
|
+
"bg-[var(--color-dropdown-bg)] border border-[var(--color-dropdown-border)] rounded-md shadow-lg",
|
|
6451
|
+
"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
|
|
6452
|
+
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0",
|
|
6453
|
+
"min-w-[200px]"
|
|
6454
|
+
),
|
|
6455
|
+
children: Array.from(groupedProps.entries()).map(([group, props]) => /* @__PURE__ */ jsx47("div", { className: "flex flex-col", children: props.map((p) => /* @__PURE__ */ jsxs42(
|
|
6456
|
+
"button",
|
|
6457
|
+
{
|
|
6458
|
+
type: "button",
|
|
6459
|
+
onClick: () => {
|
|
6460
|
+
onPropertyChange(p);
|
|
6461
|
+
setPropertyOpen(false);
|
|
6462
|
+
},
|
|
6463
|
+
className: cn(
|
|
6464
|
+
"flex items-center gap-base p-base rounded-base cursor-pointer transition-colors text-left",
|
|
6465
|
+
"hover:bg-[var(--color-dropdown-item-hover)]",
|
|
6466
|
+
p.id === condition.propertyId && "bg-[var(--color-dropdown-item-hover)]"
|
|
6467
|
+
),
|
|
6468
|
+
children: [
|
|
6469
|
+
/* @__PURE__ */ jsx47(Icon30, { icon: p.icon, size: "sm", className: "shrink-0 text-[var(--color-dropdown-item-icon)]" }),
|
|
6470
|
+
/* @__PURE__ */ jsx47("span", { className: "text-sm font-regular leading-sm text-[var(--color-dropdown-item-text)] truncate", children: p.label })
|
|
6471
|
+
]
|
|
6472
|
+
},
|
|
6473
|
+
p.id
|
|
6474
|
+
)) }, group))
|
|
6475
|
+
}
|
|
6476
|
+
) })
|
|
6477
|
+
] }),
|
|
6478
|
+
/* @__PURE__ */ jsxs42(PopoverPrimitive9.Root, { open: operatorOpen, onOpenChange: setOperatorOpen, children: [
|
|
6479
|
+
/* @__PURE__ */ jsx47(PopoverPrimitive9.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs42(
|
|
6480
|
+
"button",
|
|
6481
|
+
{
|
|
6482
|
+
type: "button",
|
|
6483
|
+
className: "flex items-center gap-xs px-base py-sm rounded-base border border-[var(--color-input)] bg-[var(--color-background)] cursor-pointer hover:bg-[var(--color-accent)] transition-colors",
|
|
6484
|
+
children: [
|
|
6485
|
+
/* @__PURE__ */ jsx47("span", { className: "text-sm font-regular leading-sm text-[var(--color-foreground)] whitespace-nowrap", children: condition.operator ?? "select" }),
|
|
6486
|
+
/* @__PURE__ */ jsx47("svg", { width: "10", height: "10", viewBox: "0 0 10 10", fill: "currentColor", className: "text-[var(--color-muted-foreground)]", children: /* @__PURE__ */ jsx47("path", { d: "M2.5 4L5 6.5L7.5 4", stroke: "currentColor", strokeWidth: "1.2", fill: "none", strokeLinecap: "round" }) })
|
|
6487
|
+
]
|
|
6488
|
+
}
|
|
6489
|
+
) }),
|
|
6490
|
+
/* @__PURE__ */ jsx47(PopoverPrimitive9.Portal, { children: /* @__PURE__ */ jsx47(
|
|
6491
|
+
PopoverPrimitive9.Content,
|
|
6492
|
+
{
|
|
6493
|
+
sideOffset: 4,
|
|
6494
|
+
align: "start",
|
|
6495
|
+
className: cn(
|
|
6496
|
+
"z-50 flex flex-col p-xs overflow-clip",
|
|
6497
|
+
"bg-[var(--color-dropdown-bg)] border border-[var(--color-dropdown-border)] rounded-md shadow-lg",
|
|
6498
|
+
"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
|
|
6499
|
+
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0",
|
|
6500
|
+
"min-w-[160px]"
|
|
6501
|
+
),
|
|
6502
|
+
children: /* @__PURE__ */ jsx47(
|
|
6503
|
+
OperatorList,
|
|
6504
|
+
{
|
|
6505
|
+
dataType: propertyDef.type,
|
|
6506
|
+
activeOperator: condition.operator,
|
|
6507
|
+
onSelect: handleOperatorSelect
|
|
6508
|
+
}
|
|
6509
|
+
)
|
|
6510
|
+
}
|
|
6511
|
+
) })
|
|
6512
|
+
] }),
|
|
6513
|
+
condition.operator && !isNoValueOperator(condition.operator) && /* @__PURE__ */ jsx47(
|
|
6514
|
+
"input",
|
|
6515
|
+
{
|
|
6516
|
+
type: "text",
|
|
6517
|
+
value: displayValue,
|
|
6518
|
+
onChange: (e) => handleValueChange(e.target.value),
|
|
6519
|
+
placeholder: "Enter value...",
|
|
6520
|
+
className: cn(
|
|
6521
|
+
"flex-1 min-w-[100px] px-base py-sm rounded-base border border-[var(--color-input)]",
|
|
6522
|
+
"bg-[var(--color-background)] text-sm font-regular leading-sm text-[var(--color-foreground)]",
|
|
6523
|
+
"placeholder:text-[var(--color-muted-foreground)]",
|
|
6524
|
+
"focus:outline-none focus:ring-2 focus:ring-[var(--color-ring)] focus:ring-offset-0"
|
|
6525
|
+
)
|
|
6526
|
+
}
|
|
6527
|
+
),
|
|
6528
|
+
/* @__PURE__ */ jsx47(
|
|
6529
|
+
"button",
|
|
6530
|
+
{
|
|
6531
|
+
type: "button",
|
|
6532
|
+
onClick: onDelete,
|
|
6533
|
+
className: "shrink-0 flex items-center justify-center p-sm rounded-base opacity-0 group-hover:opacity-100 cursor-pointer transition-opacity hover:bg-[var(--color-accent)]",
|
|
6534
|
+
"aria-label": "Remove filter",
|
|
6535
|
+
children: /* @__PURE__ */ jsx47(Icon30, { icon: faEllipsisVerticalOutline, size: "sm", className: "text-[var(--color-muted-foreground)]" })
|
|
6536
|
+
}
|
|
6537
|
+
)
|
|
6538
|
+
] });
|
|
6539
|
+
};
|
|
6540
|
+
AdvancedRow.displayName = "AdvancedRow";
|
|
6541
|
+
|
|
6542
|
+
// src/components/ui/filter/advanced-popover.tsx
|
|
6543
|
+
import { jsx as jsx48, jsxs as jsxs43 } from "react/jsx-runtime";
|
|
6544
|
+
var AdvancedPopover = ({
|
|
6545
|
+
filters,
|
|
6546
|
+
properties,
|
|
6547
|
+
onFiltersChange,
|
|
6548
|
+
open,
|
|
6549
|
+
onOpenChange,
|
|
6550
|
+
children
|
|
6551
|
+
}) => {
|
|
6552
|
+
const [addSelectorOpen, setAddSelectorOpen] = React45.useState(false);
|
|
6553
|
+
const getPropertyDef = (propertyId) => properties.find((p) => p.id === propertyId);
|
|
6554
|
+
const handleUpdateFilter = (updated) => {
|
|
6555
|
+
onFiltersChange(filters.map((f) => f.id === updated.id ? updated : f));
|
|
6556
|
+
};
|
|
6557
|
+
const handleDeleteFilter = (id) => {
|
|
6558
|
+
onFiltersChange(filters.filter((f) => f.id !== id));
|
|
6559
|
+
};
|
|
6560
|
+
const handlePropertyChange = (filterId, newProp) => {
|
|
6561
|
+
const newCondition = createFilterWithDefaults(newProp.id, newProp.type);
|
|
6562
|
+
onFiltersChange(
|
|
6563
|
+
filters.map((f) => f.id === filterId ? { ...newCondition, id: filterId } : f)
|
|
6564
|
+
);
|
|
6565
|
+
};
|
|
6566
|
+
const handleAddFilter = (property) => {
|
|
6567
|
+
const newFilter = createFilterWithDefaults(property.id, property.type);
|
|
6568
|
+
onFiltersChange([...filters, newFilter]);
|
|
6569
|
+
setAddSelectorOpen(false);
|
|
6570
|
+
};
|
|
6571
|
+
const handleClearAll = () => {
|
|
6572
|
+
onFiltersChange([]);
|
|
6573
|
+
onOpenChange?.(false);
|
|
6574
|
+
};
|
|
6575
|
+
return /* @__PURE__ */ jsxs43(PopoverPrimitive10.Root, { open, onOpenChange, children: [
|
|
6576
|
+
/* @__PURE__ */ jsx48(PopoverPrimitive10.Trigger, { asChild: true, children }),
|
|
6577
|
+
/* @__PURE__ */ jsx48(PopoverPrimitive10.Portal, { children: /* @__PURE__ */ jsxs43(
|
|
6578
|
+
PopoverPrimitive10.Content,
|
|
6579
|
+
{
|
|
6580
|
+
sideOffset: 4,
|
|
6581
|
+
align: "start",
|
|
6582
|
+
className: cn(
|
|
6583
|
+
"z-50 flex flex-col overflow-clip",
|
|
6584
|
+
"bg-[var(--color-dropdown-bg)] border border-[var(--color-dropdown-border)] rounded-md shadow-lg",
|
|
6585
|
+
"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
|
|
6586
|
+
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
|
|
6587
|
+
"data-[side=bottom]:slide-in-from-top-2",
|
|
6588
|
+
"min-w-[520px] max-w-[90vw]"
|
|
6589
|
+
),
|
|
6590
|
+
children: [
|
|
6591
|
+
/* @__PURE__ */ jsxs43("div", { className: "flex flex-col px-base pt-base", children: [
|
|
6592
|
+
filters.map((filter, i) => {
|
|
6593
|
+
const propDef = getPropertyDef(filter.propertyId);
|
|
6594
|
+
if (!propDef) return null;
|
|
6595
|
+
return /* @__PURE__ */ jsx48(
|
|
6596
|
+
AdvancedRow,
|
|
6597
|
+
{
|
|
6598
|
+
connector: i === 0 ? "Where" : "And",
|
|
6599
|
+
propertyDef: propDef,
|
|
6600
|
+
condition: filter,
|
|
6601
|
+
properties,
|
|
6602
|
+
onUpdate: handleUpdateFilter,
|
|
6603
|
+
onPropertyChange: (p) => handlePropertyChange(filter.id, p),
|
|
6604
|
+
onDelete: () => handleDeleteFilter(filter.id)
|
|
6605
|
+
},
|
|
6606
|
+
filter.id
|
|
6607
|
+
);
|
|
6608
|
+
}),
|
|
6609
|
+
filters.length === 0 && /* @__PURE__ */ jsx48("p", { className: "py-base text-sm text-[var(--color-muted-foreground)]", children: "No advanced filters yet." })
|
|
6610
|
+
] }),
|
|
6611
|
+
/* @__PURE__ */ jsxs43("div", { className: "flex items-center justify-between px-base py-base border-t border-[var(--color-border)]", children: [
|
|
6612
|
+
/* @__PURE__ */ jsx48(
|
|
6613
|
+
PropertySelector,
|
|
6614
|
+
{
|
|
6615
|
+
properties,
|
|
6616
|
+
onSelect: handleAddFilter,
|
|
6617
|
+
open: addSelectorOpen,
|
|
6618
|
+
onOpenChange: setAddSelectorOpen,
|
|
6619
|
+
children: /* @__PURE__ */ jsx48(
|
|
6620
|
+
"button",
|
|
6621
|
+
{
|
|
6622
|
+
type: "button",
|
|
6623
|
+
className: "text-sm font-regular leading-sm text-[var(--color-muted-foreground)] hover:text-[var(--color-foreground)] cursor-pointer transition-colors",
|
|
6624
|
+
children: "+ Add filter"
|
|
6625
|
+
}
|
|
6626
|
+
)
|
|
6627
|
+
}
|
|
6628
|
+
),
|
|
6629
|
+
/* @__PURE__ */ jsx48(
|
|
6630
|
+
"button",
|
|
6631
|
+
{
|
|
6632
|
+
type: "button",
|
|
6633
|
+
onClick: handleClearAll,
|
|
6634
|
+
className: "text-sm font-regular leading-sm text-[var(--color-muted-foreground)] hover:text-[var(--color-foreground)] cursor-pointer transition-colors",
|
|
6635
|
+
children: "Clear all filters"
|
|
6636
|
+
}
|
|
6637
|
+
)
|
|
6638
|
+
] })
|
|
6639
|
+
]
|
|
6640
|
+
}
|
|
6641
|
+
) })
|
|
6642
|
+
] });
|
|
6643
|
+
};
|
|
6644
|
+
AdvancedPopover.displayName = "AdvancedPopover";
|
|
6645
|
+
|
|
6646
|
+
// src/components/ui/filter/filter-system.tsx
|
|
6647
|
+
import { jsx as jsx49, jsxs as jsxs44 } from "react/jsx-runtime";
|
|
6648
|
+
var FilterSystem = ({
|
|
6649
|
+
properties,
|
|
6650
|
+
filterState,
|
|
6651
|
+
onFilterStateChange,
|
|
6652
|
+
sortFields,
|
|
6653
|
+
children,
|
|
6654
|
+
actions,
|
|
6655
|
+
className
|
|
6656
|
+
}) => {
|
|
6657
|
+
const [propertySelectorOpen, setPropertySelectorOpen] = React46.useState(false);
|
|
6658
|
+
const [advancedOpen, setAdvancedOpen] = React46.useState(false);
|
|
6659
|
+
const [pendingFilterId, setPendingFilterId] = React46.useState(null);
|
|
6660
|
+
const handleAddFilter = (property) => {
|
|
6661
|
+
const newFilter = createFilterWithDefaults(property.id, property.type);
|
|
6662
|
+
if (newFilter.operator && isNoValueOperator(newFilter.operator)) {
|
|
6663
|
+
onFilterStateChange({
|
|
6664
|
+
...filterState,
|
|
6665
|
+
basicFilters: [...filterState.basicFilters, newFilter]
|
|
6666
|
+
});
|
|
6667
|
+
return;
|
|
6668
|
+
}
|
|
6669
|
+
setPendingFilterId(newFilter.id);
|
|
6670
|
+
onFilterStateChange({
|
|
6671
|
+
...filterState,
|
|
6672
|
+
basicFilters: [...filterState.basicFilters, newFilter]
|
|
6673
|
+
});
|
|
6674
|
+
};
|
|
6675
|
+
const handleUpdateFilter = (updated) => {
|
|
6676
|
+
onFilterStateChange({
|
|
6677
|
+
...filterState,
|
|
6678
|
+
basicFilters: filterState.basicFilters.map(
|
|
6679
|
+
(f) => f.id === updated.id ? updated : f
|
|
6680
|
+
)
|
|
6681
|
+
});
|
|
6682
|
+
if (pendingFilterId === updated.id) {
|
|
6683
|
+
setPendingFilterId(null);
|
|
6684
|
+
}
|
|
6685
|
+
};
|
|
6686
|
+
const handleDeleteFilter = (id) => {
|
|
6687
|
+
onFilterStateChange({
|
|
6688
|
+
...filterState,
|
|
6689
|
+
basicFilters: filterState.basicFilters.filter((f) => f.id !== id)
|
|
6690
|
+
});
|
|
6691
|
+
};
|
|
6692
|
+
const handlePropertyChange = (filterId, newProp) => {
|
|
6693
|
+
const newCondition = createFilterWithDefaults(newProp.id, newProp.type);
|
|
6694
|
+
onFilterStateChange({
|
|
6695
|
+
...filterState,
|
|
6696
|
+
basicFilters: filterState.basicFilters.map(
|
|
6697
|
+
(f) => f.id === filterId ? { ...newCondition, id: filterId } : f
|
|
6698
|
+
)
|
|
6699
|
+
});
|
|
6700
|
+
if (newCondition.operator && !isNoValueOperator(newCondition.operator)) {
|
|
6701
|
+
setPendingFilterId(filterId);
|
|
6702
|
+
}
|
|
6703
|
+
};
|
|
6704
|
+
const handleConvertToAdvanced = (id) => {
|
|
6705
|
+
const filter = filterState.basicFilters.find((f) => f.id === id);
|
|
6706
|
+
if (!filter) return;
|
|
6707
|
+
onFilterStateChange({
|
|
6708
|
+
...filterState,
|
|
6709
|
+
basicFilters: filterState.basicFilters.filter((f) => f.id !== id),
|
|
6710
|
+
advancedFilters: [...filterState.advancedFilters, filter]
|
|
6711
|
+
});
|
|
6712
|
+
};
|
|
6713
|
+
const handleAdvancedFiltersChange = (filters) => {
|
|
6714
|
+
onFilterStateChange({
|
|
6715
|
+
...filterState,
|
|
6716
|
+
advancedFilters: filters
|
|
6717
|
+
});
|
|
6718
|
+
};
|
|
6719
|
+
const handleClearAdvanced = () => {
|
|
6720
|
+
onFilterStateChange({
|
|
6721
|
+
...filterState,
|
|
6722
|
+
advancedFilters: []
|
|
6723
|
+
});
|
|
6724
|
+
};
|
|
6725
|
+
const handleSortChange = (field, direction) => {
|
|
6726
|
+
onFilterStateChange({
|
|
6727
|
+
...filterState,
|
|
6728
|
+
sort: { field, direction }
|
|
6729
|
+
});
|
|
6730
|
+
};
|
|
6731
|
+
const getPropertyDef = (propertyId) => properties.find((p) => p.id === propertyId);
|
|
6732
|
+
const hasAdvanced = filterState.advancedFilters.length > 0;
|
|
6733
|
+
return /* @__PURE__ */ jsxs44(FilterBar, { className, children: [
|
|
6734
|
+
/* @__PURE__ */ jsxs44(FilterBarLeft, { children: [
|
|
6735
|
+
children,
|
|
6736
|
+
sortFields && filterState.sort && /* @__PURE__ */ jsx49(
|
|
6737
|
+
SortButton,
|
|
6738
|
+
{
|
|
6739
|
+
fields: sortFields,
|
|
6740
|
+
activeField: filterState.sort.field,
|
|
6741
|
+
direction: filterState.sort.direction,
|
|
6742
|
+
onChange: handleSortChange
|
|
6743
|
+
}
|
|
6744
|
+
),
|
|
6745
|
+
hasAdvanced && /* @__PURE__ */ jsx49(
|
|
6746
|
+
AdvancedPopover,
|
|
6747
|
+
{
|
|
6748
|
+
filters: filterState.advancedFilters,
|
|
6749
|
+
properties,
|
|
6750
|
+
onFiltersChange: handleAdvancedFiltersChange,
|
|
6751
|
+
open: advancedOpen,
|
|
6752
|
+
onOpenChange: setAdvancedOpen,
|
|
6753
|
+
children: /* @__PURE__ */ jsx49(
|
|
6754
|
+
AdvancedChip,
|
|
6755
|
+
{
|
|
6756
|
+
count: filterState.advancedFilters.length,
|
|
6757
|
+
onClick: () => setAdvancedOpen(true),
|
|
6758
|
+
onClear: handleClearAdvanced
|
|
6759
|
+
}
|
|
6760
|
+
)
|
|
6761
|
+
}
|
|
6762
|
+
),
|
|
6763
|
+
filterState.basicFilters.map((filter) => {
|
|
6764
|
+
const propDef = getPropertyDef(filter.propertyId);
|
|
6765
|
+
if (!propDef) return null;
|
|
6766
|
+
return /* @__PURE__ */ jsx49(
|
|
6767
|
+
InteractiveFilterChip,
|
|
6768
|
+
{
|
|
6769
|
+
propertyDef: propDef,
|
|
6770
|
+
condition: filter,
|
|
6771
|
+
properties,
|
|
6772
|
+
mode: pendingFilterId === filter.id ? "add" : "edit",
|
|
6773
|
+
autoOpen: pendingFilterId === filter.id,
|
|
6774
|
+
onUpdate: handleUpdateFilter,
|
|
6775
|
+
onPropertyChange: (newProp) => handlePropertyChange(filter.id, newProp),
|
|
6776
|
+
onDelete: () => handleDeleteFilter(filter.id),
|
|
6777
|
+
onConvertToAdvanced: () => handleConvertToAdvanced(filter.id)
|
|
6778
|
+
},
|
|
6779
|
+
filter.id
|
|
6780
|
+
);
|
|
6781
|
+
}),
|
|
6782
|
+
/* @__PURE__ */ jsx49(
|
|
6783
|
+
PropertySelector,
|
|
6784
|
+
{
|
|
6785
|
+
properties,
|
|
6786
|
+
onSelect: handleAddFilter,
|
|
6787
|
+
open: propertySelectorOpen,
|
|
6788
|
+
onOpenChange: setPropertySelectorOpen,
|
|
6789
|
+
children: /* @__PURE__ */ jsx49(
|
|
6790
|
+
FilterBarButton,
|
|
6791
|
+
{
|
|
6792
|
+
count: filterState.basicFilters.length + filterState.advancedFilters.length || void 0
|
|
6793
|
+
}
|
|
6794
|
+
)
|
|
6795
|
+
}
|
|
6796
|
+
)
|
|
6797
|
+
] }),
|
|
6798
|
+
actions && /* @__PURE__ */ jsx49(FilterBarRight, { children: actions })
|
|
6799
|
+
] });
|
|
6800
|
+
};
|
|
6801
|
+
FilterSystem.displayName = "FilterSystem";
|
|
6802
|
+
|
|
6803
|
+
// src/components/ui/date-picker.tsx
|
|
6804
|
+
import * as React47 from "react";
|
|
6805
|
+
import * as PopoverPrimitive11 from "@radix-ui/react-popover";
|
|
6806
|
+
import {
|
|
6807
|
+
Icon as Icon31,
|
|
6808
|
+
faChevronLeftOutline as faChevronLeftOutline3,
|
|
6809
|
+
faChevronRightOutline as faChevronRightOutline3,
|
|
6810
|
+
faArrowRightOutline as faArrowRightOutline2,
|
|
6811
|
+
faCalendarOutline
|
|
6812
|
+
} from "@l3mpire/icons";
|
|
6813
|
+
import { jsx as jsx50, jsxs as jsxs45 } from "react/jsx-runtime";
|
|
6814
|
+
function getDaysInMonth(year, month) {
|
|
6815
|
+
return new Date(year, month + 1, 0).getDate();
|
|
6816
|
+
}
|
|
6817
|
+
function getWeekdayIndex(date) {
|
|
6818
|
+
return (date.getDay() + 6) % 7;
|
|
6819
|
+
}
|
|
6820
|
+
function isSameDay(a, b) {
|
|
6821
|
+
return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
|
|
6822
|
+
}
|
|
6823
|
+
function isInRange(date, from, to) {
|
|
6824
|
+
const t = date.getTime();
|
|
6825
|
+
return t >= from.getTime() && t <= to.getTime();
|
|
6826
|
+
}
|
|
6827
|
+
function startOfDay(d) {
|
|
6828
|
+
return new Date(d.getFullYear(), d.getMonth(), d.getDate());
|
|
6829
|
+
}
|
|
6830
|
+
var WEEKDAYS = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
|
|
6831
|
+
var MONTH_NAMES = [
|
|
6832
|
+
"January",
|
|
6833
|
+
"February",
|
|
6834
|
+
"March",
|
|
6835
|
+
"April",
|
|
6836
|
+
"May",
|
|
6837
|
+
"June",
|
|
6838
|
+
"July",
|
|
6839
|
+
"August",
|
|
6840
|
+
"September",
|
|
6841
|
+
"October",
|
|
6842
|
+
"November",
|
|
6843
|
+
"December"
|
|
6844
|
+
];
|
|
6845
|
+
var DatePickerContext = React47.createContext(
|
|
6846
|
+
null
|
|
6847
|
+
);
|
|
6848
|
+
function useDatePickerContext() {
|
|
6849
|
+
const ctx = React47.useContext(DatePickerContext);
|
|
6850
|
+
if (!ctx)
|
|
6851
|
+
throw new Error("DatePicker compound components must be used within <DatePicker>");
|
|
6852
|
+
return ctx;
|
|
6853
|
+
}
|
|
6854
|
+
var DatePicker = React47.forwardRef(
|
|
6855
|
+
({
|
|
6856
|
+
className,
|
|
6857
|
+
mode = "single",
|
|
6858
|
+
value,
|
|
6859
|
+
onValueChange,
|
|
6860
|
+
defaultMonth,
|
|
6861
|
+
defaultYear,
|
|
6862
|
+
children,
|
|
6863
|
+
...props
|
|
6864
|
+
}, ref) => {
|
|
6865
|
+
const today = React47.useMemo(() => startOfDay(/* @__PURE__ */ new Date()), []);
|
|
6866
|
+
const initialDate = React47.useMemo(() => {
|
|
6867
|
+
if (value) {
|
|
6868
|
+
if (value instanceof Date) return value;
|
|
6869
|
+
return value.from;
|
|
6870
|
+
}
|
|
6871
|
+
return today;
|
|
6872
|
+
}, []);
|
|
6873
|
+
const [month, setMonth] = React47.useState(
|
|
6874
|
+
defaultMonth ?? initialDate.getMonth()
|
|
6875
|
+
);
|
|
6876
|
+
const [year, setYear] = React47.useState(
|
|
6877
|
+
defaultYear ?? initialDate.getFullYear()
|
|
6878
|
+
);
|
|
6879
|
+
const [hoveredDate, setHoveredDate] = React47.useState();
|
|
6880
|
+
const goToPrevMonth = React47.useCallback(() => {
|
|
6881
|
+
setMonth((m) => {
|
|
6882
|
+
if (m === 0) {
|
|
6883
|
+
setYear((y) => y - 1);
|
|
6884
|
+
return 11;
|
|
6885
|
+
}
|
|
6886
|
+
return m - 1;
|
|
6887
|
+
});
|
|
6888
|
+
}, []);
|
|
6889
|
+
const goToNextMonth = React47.useCallback(() => {
|
|
6890
|
+
setMonth((m) => {
|
|
6891
|
+
if (m === 11) {
|
|
6892
|
+
setYear((y) => y + 1);
|
|
6893
|
+
return 0;
|
|
6894
|
+
}
|
|
6895
|
+
return m + 1;
|
|
6896
|
+
});
|
|
6897
|
+
}, []);
|
|
6898
|
+
const onSelect = React47.useCallback(
|
|
6899
|
+
(date) => {
|
|
6900
|
+
if (mode === "single") {
|
|
6901
|
+
onValueChange?.(date);
|
|
6902
|
+
return;
|
|
6903
|
+
}
|
|
6904
|
+
if (!value || value instanceof Date) {
|
|
6905
|
+
onValueChange?.({ from: date });
|
|
6906
|
+
return;
|
|
6907
|
+
}
|
|
6908
|
+
const range = value;
|
|
6909
|
+
if (range.to || date.getTime() < range.from.getTime()) {
|
|
6910
|
+
onValueChange?.({ from: date });
|
|
6911
|
+
} else {
|
|
6912
|
+
onValueChange?.({ from: range.from, to: date });
|
|
6913
|
+
}
|
|
6914
|
+
},
|
|
6915
|
+
[mode, value, onValueChange]
|
|
6916
|
+
);
|
|
6917
|
+
const ctxValue = React47.useMemo(
|
|
6918
|
+
() => ({
|
|
6919
|
+
mode,
|
|
6920
|
+
selected: value,
|
|
6921
|
+
onSelect,
|
|
6922
|
+
month,
|
|
6923
|
+
year,
|
|
6924
|
+
setMonth,
|
|
6925
|
+
setYear,
|
|
6926
|
+
goToPrevMonth,
|
|
6927
|
+
goToNextMonth,
|
|
6928
|
+
today,
|
|
6929
|
+
hoveredDate,
|
|
6930
|
+
setHoveredDate
|
|
6931
|
+
}),
|
|
6932
|
+
[
|
|
6933
|
+
mode,
|
|
6934
|
+
value,
|
|
6935
|
+
onSelect,
|
|
6936
|
+
month,
|
|
6937
|
+
year,
|
|
6938
|
+
goToPrevMonth,
|
|
6939
|
+
goToNextMonth,
|
|
6940
|
+
today,
|
|
6941
|
+
hoveredDate
|
|
6942
|
+
]
|
|
6943
|
+
);
|
|
6944
|
+
return /* @__PURE__ */ jsx50(DatePickerContext.Provider, { value: ctxValue, children: /* @__PURE__ */ jsx50(
|
|
6945
|
+
"div",
|
|
6946
|
+
{
|
|
6947
|
+
ref,
|
|
6948
|
+
className: cn(
|
|
6949
|
+
"flex flex-col overflow-clip",
|
|
6950
|
+
"bg-datepicker-bg border border-datepicker-border rounded-md shadow-lg",
|
|
6951
|
+
className
|
|
6952
|
+
),
|
|
6953
|
+
...props,
|
|
6954
|
+
children
|
|
6955
|
+
}
|
|
6956
|
+
) });
|
|
6957
|
+
}
|
|
6958
|
+
);
|
|
6959
|
+
DatePicker.displayName = "DatePicker";
|
|
6960
|
+
function defaultFormatDate(date) {
|
|
6961
|
+
return date.toLocaleDateString("en-US", {
|
|
6962
|
+
month: "short",
|
|
6963
|
+
day: "numeric",
|
|
6964
|
+
year: "numeric"
|
|
6965
|
+
});
|
|
6966
|
+
}
|
|
6967
|
+
var DatePickerSelects = React47.forwardRef(({ className, formatDate = defaultFormatDate, ...props }, ref) => {
|
|
6968
|
+
const { selected } = useDatePickerContext();
|
|
6969
|
+
const fromDate = selected instanceof Date ? selected : selected?.from;
|
|
6970
|
+
const toDate = selected instanceof Date ? void 0 : selected?.to;
|
|
6971
|
+
return /* @__PURE__ */ jsx50(
|
|
6972
|
+
"div",
|
|
6973
|
+
{
|
|
6974
|
+
ref,
|
|
6975
|
+
className: cn("flex flex-col items-start pt-lg px-lg", className),
|
|
6976
|
+
...props,
|
|
6977
|
+
children: /* @__PURE__ */ jsxs45("div", { className: "flex items-center gap-base w-full", children: [
|
|
6978
|
+
/* @__PURE__ */ jsxs45("div", { className: "flex-1 flex items-center gap-base min-w-0 px-base py-sm bg-gradient-to-t from-[var(--color-select-bg-default)] to-[var(--color-select-bg-gradient-to)] border border-[var(--color-select-border-default)] rounded-base shadow-sm", children: [
|
|
6979
|
+
/* @__PURE__ */ jsx50("span", { className: "flex-1 text-sm font-regular leading-sm text-datepicker-header-text truncate", children: fromDate ? formatDate(fromDate) : "Start date" }),
|
|
6980
|
+
/* @__PURE__ */ jsx50(Icon31, { icon: faCalendarOutline, size: "sm", className: "shrink-0 text-datepicker-header-text" })
|
|
6981
|
+
] }),
|
|
6982
|
+
/* @__PURE__ */ jsx50(
|
|
6983
|
+
Icon31,
|
|
6984
|
+
{
|
|
6985
|
+
icon: faArrowRightOutline2,
|
|
6986
|
+
size: "sm",
|
|
6987
|
+
className: "shrink-0 text-datepicker-header-weekday"
|
|
6988
|
+
}
|
|
6989
|
+
),
|
|
6990
|
+
/* @__PURE__ */ jsxs45("div", { className: "flex-1 flex items-center gap-base min-w-0 px-base py-sm bg-gradient-to-t from-[var(--color-select-bg-default)] to-[var(--color-select-bg-gradient-to)] border border-[var(--color-select-border-default)] rounded-base shadow-sm", children: [
|
|
6991
|
+
/* @__PURE__ */ jsx50("span", { className: "flex-1 text-sm font-regular leading-sm text-datepicker-header-text truncate", children: toDate ? formatDate(toDate) : "End date" }),
|
|
6992
|
+
/* @__PURE__ */ jsx50(Icon31, { icon: faCalendarOutline, size: "sm", className: "shrink-0 text-datepicker-header-text" })
|
|
6993
|
+
] })
|
|
6994
|
+
] })
|
|
6995
|
+
}
|
|
6996
|
+
);
|
|
6997
|
+
});
|
|
6998
|
+
DatePickerSelects.displayName = "DatePickerSelects";
|
|
6999
|
+
var DatePickerDay = ({ date, isOutside }) => {
|
|
7000
|
+
const { mode, selected, onSelect, today, hoveredDate, setHoveredDate } = useDatePickerContext();
|
|
7001
|
+
const isToday = isSameDay(date, today);
|
|
7002
|
+
const isSelected = selected instanceof Date ? isSameDay(date, selected) : selected?.from ? isSameDay(date, selected.from) || (selected.to ? isSameDay(date, selected.to) : false) : false;
|
|
7003
|
+
const isRangeStart = mode === "range" && selected && !(selected instanceof Date) && selected.from && isSameDay(date, selected.from);
|
|
7004
|
+
const isRangeEnd = mode === "range" && selected && !(selected instanceof Date) && selected.to && isSameDay(date, selected.to);
|
|
7005
|
+
const inRange = mode === "range" && selected && !(selected instanceof Date) && selected.from && selected.to && !isSelected && isInRange(date, selected.from, selected.to);
|
|
7006
|
+
const inPreviewRange = mode === "range" && selected && !(selected instanceof Date) && selected.from && !selected.to && hoveredDate && !isSelected && hoveredDate.getTime() > selected.from.getTime() && isInRange(date, selected.from, hoveredDate);
|
|
7007
|
+
const isInRangeOrPreview = inRange || inPreviewRange;
|
|
7008
|
+
return /* @__PURE__ */ jsxs45(
|
|
7009
|
+
"button",
|
|
7010
|
+
{
|
|
7011
|
+
type: "button",
|
|
7012
|
+
onClick: () => !isOutside && onSelect(date),
|
|
7013
|
+
onMouseEnter: () => mode === "range" && setHoveredDate(date),
|
|
7014
|
+
onMouseLeave: () => mode === "range" && setHoveredDate(void 0),
|
|
7015
|
+
disabled: isOutside,
|
|
7016
|
+
className: cn(
|
|
7017
|
+
"relative flex flex-col items-center justify-center w-9 rounded-full p-2 cursor-pointer transition-colors",
|
|
7018
|
+
"text-sm font-medium leading-sm text-center",
|
|
7019
|
+
// Default
|
|
7020
|
+
!isOutside && !isSelected && !isInRangeOrPreview && "text-datepicker-day-text-default hover:bg-datepicker-day-bg-hover",
|
|
7021
|
+
// Outside month (disabled)
|
|
7022
|
+
isOutside && "text-datepicker-day-text-disabled cursor-default",
|
|
7023
|
+
// Selected
|
|
7024
|
+
isSelected && "bg-datepicker-day-bg-selected text-datepicker-day-text-selected",
|
|
7025
|
+
// In range
|
|
7026
|
+
isInRangeOrPreview && "bg-datepicker-day-bg-range text-datepicker-day-text-range",
|
|
7027
|
+
// Range start/end get full rounded; in-range items could be less rounded
|
|
7028
|
+
(isRangeStart || isRangeEnd) && "rounded-full"
|
|
7029
|
+
),
|
|
7030
|
+
children: [
|
|
7031
|
+
date.getDate(),
|
|
7032
|
+
isToday && !isOutside && /* @__PURE__ */ jsx50("span", { className: "absolute bottom-0.5 left-1/2 -translate-x-1/2 size-1.5 rounded-full bg-datepicker-day-today" })
|
|
7033
|
+
]
|
|
7034
|
+
}
|
|
7035
|
+
);
|
|
7036
|
+
};
|
|
7037
|
+
var DatePickerCalendar = React47.forwardRef(({ className, header, ...props }, ref) => {
|
|
7038
|
+
const { month, year, goToPrevMonth, goToNextMonth } = useDatePickerContext();
|
|
7039
|
+
const weeks = React47.useMemo(() => {
|
|
7040
|
+
const firstDay = new Date(year, month, 1);
|
|
7041
|
+
const startOffset = getWeekdayIndex(firstDay);
|
|
7042
|
+
const daysInMonth = getDaysInMonth(year, month);
|
|
7043
|
+
const daysInPrevMonth = getDaysInMonth(
|
|
7044
|
+
month === 0 ? year - 1 : year,
|
|
7045
|
+
month === 0 ? 11 : month - 1
|
|
7046
|
+
);
|
|
7047
|
+
const days = [];
|
|
7048
|
+
for (let i = startOffset - 1; i >= 0; i--) {
|
|
7049
|
+
const d = daysInPrevMonth - i;
|
|
7050
|
+
days.push({
|
|
7051
|
+
date: new Date(
|
|
7052
|
+
month === 0 ? year - 1 : year,
|
|
7053
|
+
month === 0 ? 11 : month - 1,
|
|
7054
|
+
d
|
|
7055
|
+
),
|
|
7056
|
+
isOutside: true
|
|
7057
|
+
});
|
|
7058
|
+
}
|
|
7059
|
+
for (let d = 1; d <= daysInMonth; d++) {
|
|
7060
|
+
days.push({ date: new Date(year, month, d), isOutside: false });
|
|
7061
|
+
}
|
|
7062
|
+
const remaining = 42 - days.length;
|
|
7063
|
+
for (let d = 1; d <= remaining; d++) {
|
|
7064
|
+
days.push({
|
|
7065
|
+
date: new Date(
|
|
7066
|
+
month === 11 ? year + 1 : year,
|
|
7067
|
+
month === 11 ? 0 : month + 1,
|
|
7068
|
+
d
|
|
7069
|
+
),
|
|
7070
|
+
isOutside: true
|
|
7071
|
+
});
|
|
7072
|
+
}
|
|
7073
|
+
const result = [];
|
|
7074
|
+
for (let i = 0; i < days.length; i += 7) {
|
|
7075
|
+
result.push(days.slice(i, i + 7));
|
|
7076
|
+
}
|
|
7077
|
+
return result;
|
|
7078
|
+
}, [month, year]);
|
|
7079
|
+
return /* @__PURE__ */ jsxs45(
|
|
7080
|
+
"div",
|
|
7081
|
+
{
|
|
7082
|
+
ref,
|
|
7083
|
+
className: cn("flex flex-col", className),
|
|
7084
|
+
...props,
|
|
7085
|
+
children: [
|
|
7086
|
+
header,
|
|
7087
|
+
/* @__PURE__ */ jsxs45("div", { className: "flex flex-col gap-lg p-lg", children: [
|
|
7088
|
+
/* @__PURE__ */ jsxs45("div", { className: "flex items-center justify-between", children: [
|
|
7089
|
+
/* @__PURE__ */ jsxs45("span", { className: "text-base font-medium leading-base text-datepicker-header-text", children: [
|
|
7090
|
+
MONTH_NAMES[month],
|
|
7091
|
+
" ",
|
|
7092
|
+
year
|
|
7093
|
+
] }),
|
|
7094
|
+
/* @__PURE__ */ jsxs45("div", { className: "flex items-center gap-xs", children: [
|
|
7095
|
+
/* @__PURE__ */ jsx50(
|
|
7096
|
+
"button",
|
|
7097
|
+
{
|
|
7098
|
+
type: "button",
|
|
7099
|
+
onClick: goToPrevMonth,
|
|
7100
|
+
className: "flex items-center justify-center p-xs rounded-base hover:bg-datepicker-day-bg-hover transition-colors cursor-pointer",
|
|
7101
|
+
"aria-label": "Previous month",
|
|
7102
|
+
children: /* @__PURE__ */ jsx50(Icon31, { icon: faChevronLeftOutline3, size: "xs", className: "text-datepicker-header-nav" })
|
|
7103
|
+
}
|
|
7104
|
+
),
|
|
7105
|
+
/* @__PURE__ */ jsx50(
|
|
7106
|
+
"button",
|
|
7107
|
+
{
|
|
7108
|
+
type: "button",
|
|
7109
|
+
onClick: goToNextMonth,
|
|
7110
|
+
className: "flex items-center justify-center p-xs rounded-base hover:bg-datepicker-day-bg-hover transition-colors cursor-pointer",
|
|
7111
|
+
"aria-label": "Next month",
|
|
7112
|
+
children: /* @__PURE__ */ jsx50(Icon31, { icon: faChevronRightOutline3, size: "xs", className: "text-datepicker-header-nav" })
|
|
7113
|
+
}
|
|
7114
|
+
)
|
|
7115
|
+
] })
|
|
7116
|
+
] }),
|
|
7117
|
+
/* @__PURE__ */ jsxs45("div", { className: "flex flex-col", children: [
|
|
7118
|
+
/* @__PURE__ */ jsx50("div", { className: "grid grid-cols-7 gap-base py-sm", children: WEEKDAYS.map((day) => /* @__PURE__ */ jsx50(
|
|
7119
|
+
"span",
|
|
7120
|
+
{
|
|
7121
|
+
className: "w-9 text-center text-xs font-regular leading-xs text-datepicker-header-weekday",
|
|
7122
|
+
children: day
|
|
7123
|
+
},
|
|
7124
|
+
day
|
|
7125
|
+
)) }),
|
|
7126
|
+
/* @__PURE__ */ jsx50("div", { className: "flex flex-col", children: weeks.map((week, wi) => /* @__PURE__ */ jsx50("div", { className: "grid grid-cols-7 gap-base", children: week.map((day, di) => /* @__PURE__ */ jsx50(
|
|
7127
|
+
DatePickerDay,
|
|
7128
|
+
{
|
|
7129
|
+
date: day.date,
|
|
7130
|
+
isOutside: day.isOutside
|
|
7131
|
+
},
|
|
7132
|
+
di
|
|
7133
|
+
)) }, wi)) })
|
|
7134
|
+
] })
|
|
7135
|
+
] })
|
|
7136
|
+
]
|
|
7137
|
+
}
|
|
7138
|
+
);
|
|
7139
|
+
});
|
|
7140
|
+
DatePickerCalendar.displayName = "DatePickerCalendar";
|
|
7141
|
+
var DatePickerSuggestions = React47.forwardRef(
|
|
7142
|
+
({ className, suggestions, formatDate = defaultFormatDate, ...props }, ref) => {
|
|
7143
|
+
const { onSelect, mode } = useDatePickerContext();
|
|
7144
|
+
const onValueChange = React47.useContext(DatePickerContext) ? void 0 : void 0;
|
|
7145
|
+
const ctx = useDatePickerContext();
|
|
7146
|
+
const handleClick = (suggestion) => {
|
|
7147
|
+
const val = suggestion.getValue();
|
|
7148
|
+
if (val instanceof Date) {
|
|
7149
|
+
ctx.onSelect(val);
|
|
7150
|
+
} else {
|
|
7151
|
+
ctx.onSelect(val.from);
|
|
7152
|
+
if (val.to) {
|
|
7153
|
+
setTimeout(() => ctx.onSelect(val.to), 0);
|
|
7154
|
+
}
|
|
7155
|
+
}
|
|
7156
|
+
};
|
|
7157
|
+
const formatSuggestionDate = (suggestion) => {
|
|
7158
|
+
const val = suggestion.getValue();
|
|
7159
|
+
if (val instanceof Date) {
|
|
7160
|
+
return formatDate(val);
|
|
7161
|
+
}
|
|
7162
|
+
const from = formatDate(val.from);
|
|
7163
|
+
const to = val.to ? formatDate(val.to) : "";
|
|
7164
|
+
return to ? `${from} - ${to}` : from;
|
|
7165
|
+
};
|
|
7166
|
+
return /* @__PURE__ */ jsxs45(
|
|
7167
|
+
"div",
|
|
7168
|
+
{
|
|
7169
|
+
ref,
|
|
7170
|
+
className: cn(
|
|
7171
|
+
"flex flex-col border-l border-datepicker-border self-stretch shrink-0",
|
|
7172
|
+
className
|
|
7173
|
+
),
|
|
7174
|
+
...props,
|
|
7175
|
+
children: [
|
|
7176
|
+
/* @__PURE__ */ jsx50("div", { className: "pt-lg px-base", children: /* @__PURE__ */ jsx50("div", { className: "flex items-center p-base rounded-base", children: /* @__PURE__ */ jsx50("span", { className: "flex-1 text-xs font-medium leading-xs text-datepicker-suggestion-heading uppercase truncate", children: "Suggestions" }) }) }),
|
|
7177
|
+
/* @__PURE__ */ jsx50("div", { className: "flex flex-1 flex-col p-base min-w-[222px]", children: suggestions.map((suggestion, i) => /* @__PURE__ */ jsxs45(
|
|
7178
|
+
"button",
|
|
7179
|
+
{
|
|
7180
|
+
type: "button",
|
|
7181
|
+
onClick: () => handleClick(suggestion),
|
|
7182
|
+
className: "flex items-center gap-sm p-base rounded-base hover:bg-datepicker-suggestion-hover transition-colors cursor-pointer text-left",
|
|
7183
|
+
children: [
|
|
7184
|
+
/* @__PURE__ */ jsx50("span", { className: "text-sm font-regular leading-sm text-datepicker-suggestion-text truncate shrink-0", children: suggestion.label }),
|
|
7185
|
+
/* @__PURE__ */ jsx50("span", { className: "text-xs font-regular leading-xs text-datepicker-suggestion-date truncate", children: formatSuggestionDate(suggestion) })
|
|
7186
|
+
]
|
|
7187
|
+
},
|
|
7188
|
+
i
|
|
7189
|
+
)) })
|
|
7190
|
+
]
|
|
7191
|
+
}
|
|
7192
|
+
);
|
|
7193
|
+
}
|
|
7194
|
+
);
|
|
7195
|
+
DatePickerSuggestions.displayName = "DatePickerSuggestions";
|
|
7196
|
+
var DatePickerFooter = React47.forwardRef(
|
|
7197
|
+
({ className, children, ...props }, ref) => /* @__PURE__ */ jsx50(
|
|
7198
|
+
"div",
|
|
7199
|
+
{
|
|
7200
|
+
ref,
|
|
7201
|
+
className: cn(
|
|
7202
|
+
"flex items-center justify-between p-lg",
|
|
7203
|
+
"border-t border-datepicker-footer-border",
|
|
7204
|
+
"bg-datepicker-bg",
|
|
7205
|
+
className
|
|
7206
|
+
),
|
|
7207
|
+
...props,
|
|
7208
|
+
children
|
|
7209
|
+
}
|
|
7210
|
+
)
|
|
7211
|
+
);
|
|
7212
|
+
DatePickerFooter.displayName = "DatePickerFooter";
|
|
7213
|
+
var DatePickerPanel = React47.forwardRef(
|
|
7214
|
+
({ className, children, ...props }, ref) => /* @__PURE__ */ jsx50(
|
|
7215
|
+
"div",
|
|
7216
|
+
{
|
|
7217
|
+
ref,
|
|
7218
|
+
className: cn("flex items-start", className),
|
|
7219
|
+
...props,
|
|
7220
|
+
children
|
|
7221
|
+
}
|
|
7222
|
+
)
|
|
7223
|
+
);
|
|
7224
|
+
DatePickerPanel.displayName = "DatePickerPanel";
|
|
7225
|
+
var DatePickerRoot = PopoverPrimitive11.Root;
|
|
7226
|
+
var DatePickerTrigger = PopoverPrimitive11.Trigger;
|
|
7227
|
+
var DatePickerPopover = React47.forwardRef(({ className, sideOffset = 4, align = "start", children, ...props }, ref) => /* @__PURE__ */ jsx50(PopoverPrimitive11.Portal, { children: /* @__PURE__ */ jsx50(
|
|
7228
|
+
PopoverPrimitive11.Content,
|
|
7229
|
+
{
|
|
7230
|
+
ref,
|
|
7231
|
+
sideOffset,
|
|
7232
|
+
align,
|
|
7233
|
+
className: cn(
|
|
7234
|
+
"z-50",
|
|
7235
|
+
"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
|
|
7236
|
+
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
|
|
7237
|
+
"data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2",
|
|
7238
|
+
className
|
|
7239
|
+
),
|
|
7240
|
+
...props,
|
|
7241
|
+
children
|
|
7242
|
+
}
|
|
7243
|
+
) }));
|
|
7244
|
+
DatePickerPopover.displayName = "DatePickerPopover";
|
|
7245
|
+
function getDefaultSuggestions(referenceDate) {
|
|
7246
|
+
const now = referenceDate ?? /* @__PURE__ */ new Date();
|
|
7247
|
+
const today = startOfDay(now);
|
|
7248
|
+
const dayOfWeek = getWeekdayIndex(today);
|
|
7249
|
+
const startOfThisWeek = new Date(today);
|
|
7250
|
+
startOfThisWeek.setDate(today.getDate() - dayOfWeek);
|
|
7251
|
+
const endOfThisWeek = new Date(startOfThisWeek);
|
|
7252
|
+
endOfThisWeek.setDate(startOfThisWeek.getDate() + 6);
|
|
7253
|
+
const startOfThisMonth = new Date(today.getFullYear(), today.getMonth(), 1);
|
|
7254
|
+
const endOfThisMonth = new Date(
|
|
7255
|
+
today.getFullYear(),
|
|
7256
|
+
today.getMonth() + 1,
|
|
7257
|
+
0
|
|
7258
|
+
);
|
|
7259
|
+
const startOfThisYear = new Date(today.getFullYear(), 0, 1);
|
|
7260
|
+
const endOfThisYear = new Date(today.getFullYear(), 11, 31);
|
|
7261
|
+
const startOfLastWeek = new Date(startOfThisWeek);
|
|
7262
|
+
startOfLastWeek.setDate(startOfThisWeek.getDate() - 7);
|
|
7263
|
+
const endOfLastWeek = new Date(startOfThisWeek);
|
|
7264
|
+
endOfLastWeek.setDate(startOfThisWeek.getDate() - 1);
|
|
7265
|
+
const startOfLastMonth = new Date(
|
|
7266
|
+
today.getFullYear(),
|
|
7267
|
+
today.getMonth() - 1,
|
|
7268
|
+
1
|
|
7269
|
+
);
|
|
7270
|
+
const endOfLastMonth = new Date(today.getFullYear(), today.getMonth(), 0);
|
|
7271
|
+
const startOfLastYear = new Date(today.getFullYear() - 1, 0, 1);
|
|
7272
|
+
const endOfLastYear = new Date(today.getFullYear() - 1, 11, 31);
|
|
7273
|
+
return [
|
|
7274
|
+
{ label: "Today", getValue: () => today },
|
|
7275
|
+
{
|
|
7276
|
+
label: "This week",
|
|
7277
|
+
getValue: () => ({ from: startOfThisWeek, to: endOfThisWeek })
|
|
7278
|
+
},
|
|
7279
|
+
{
|
|
7280
|
+
label: "This month",
|
|
7281
|
+
getValue: () => ({ from: startOfThisMonth, to: endOfThisMonth })
|
|
7282
|
+
},
|
|
7283
|
+
{
|
|
7284
|
+
label: "This year",
|
|
7285
|
+
getValue: () => ({ from: startOfThisYear, to: endOfThisYear })
|
|
7286
|
+
},
|
|
7287
|
+
{
|
|
7288
|
+
label: "Last week",
|
|
7289
|
+
getValue: () => ({ from: startOfLastWeek, to: endOfLastWeek })
|
|
7290
|
+
},
|
|
7291
|
+
{
|
|
7292
|
+
label: "Last month",
|
|
7293
|
+
getValue: () => ({ from: startOfLastMonth, to: endOfLastMonth })
|
|
7294
|
+
},
|
|
7295
|
+
{
|
|
7296
|
+
label: "Last year",
|
|
7297
|
+
getValue: () => ({ from: startOfLastYear, to: endOfLastYear })
|
|
7298
|
+
}
|
|
7299
|
+
];
|
|
7300
|
+
}
|
|
4727
7301
|
export {
|
|
7302
|
+
AdvancedChip,
|
|
7303
|
+
AdvancedPopover,
|
|
7304
|
+
AdvancedRow,
|
|
4728
7305
|
Avatar,
|
|
4729
7306
|
AvatarCell,
|
|
4730
7307
|
Badge,
|
|
@@ -4734,9 +7311,19 @@ export {
|
|
|
4734
7311
|
ButtonCell,
|
|
4735
7312
|
Checkbox,
|
|
4736
7313
|
ChipInput,
|
|
7314
|
+
DEFAULT_OPERATOR_BY_TYPE,
|
|
4737
7315
|
DataTable,
|
|
4738
7316
|
DataTablePagination,
|
|
4739
7317
|
DateCell,
|
|
7318
|
+
DatePicker,
|
|
7319
|
+
DatePickerCalendar,
|
|
7320
|
+
DatePickerFooter,
|
|
7321
|
+
DatePickerPanel,
|
|
7322
|
+
DatePickerPopover,
|
|
7323
|
+
DatePickerRoot,
|
|
7324
|
+
DatePickerSelects,
|
|
7325
|
+
DatePickerSuggestions,
|
|
7326
|
+
DatePickerTrigger,
|
|
4740
7327
|
Dialog,
|
|
4741
7328
|
DropdownMenu,
|
|
4742
7329
|
DropdownMenuClear,
|
|
@@ -4750,8 +7337,18 @@ export {
|
|
|
4750
7337
|
EditableCell,
|
|
4751
7338
|
EmailCell,
|
|
4752
7339
|
EmptyState,
|
|
7340
|
+
FilterBar,
|
|
7341
|
+
FilterBarButton,
|
|
7342
|
+
FilterBarLeft,
|
|
7343
|
+
FilterBarRight,
|
|
7344
|
+
FilterChip,
|
|
7345
|
+
FilterChipSegment,
|
|
7346
|
+
FilterEditor,
|
|
7347
|
+
FilterSystem,
|
|
4753
7348
|
InfoMessage,
|
|
4754
7349
|
InputLabel,
|
|
7350
|
+
InteractiveFilterChip,
|
|
7351
|
+
KebabMenu,
|
|
4755
7352
|
Link,
|
|
4756
7353
|
LinkCell,
|
|
4757
7354
|
Modal,
|
|
@@ -4766,8 +7363,13 @@ export {
|
|
|
4766
7363
|
ModalTrigger,
|
|
4767
7364
|
NumberCell,
|
|
4768
7365
|
NumberInput,
|
|
7366
|
+
OPERATORS_BY_TYPE,
|
|
7367
|
+
OperatorList,
|
|
7368
|
+
OperatorSelector,
|
|
4769
7369
|
ProductLogo,
|
|
7370
|
+
PropertySelector,
|
|
4770
7371
|
RowActions,
|
|
7372
|
+
SaveViewButton,
|
|
4771
7373
|
SearchBar,
|
|
4772
7374
|
Select,
|
|
4773
7375
|
SidePanel,
|
|
@@ -4780,6 +7382,7 @@ export {
|
|
|
4780
7382
|
SidebarHeadingItem,
|
|
4781
7383
|
SidebarItem,
|
|
4782
7384
|
SidebarSection,
|
|
7385
|
+
SortButton,
|
|
4783
7386
|
StatusCell,
|
|
4784
7387
|
Switch,
|
|
4785
7388
|
TabContent,
|
|
@@ -4809,14 +7412,21 @@ export {
|
|
|
4809
7412
|
UserMenu,
|
|
4810
7413
|
UserMenuInfoRow,
|
|
4811
7414
|
UserMenuSection,
|
|
7415
|
+
ValueInput,
|
|
4812
7416
|
avatarVariants,
|
|
4813
7417
|
badgeVariants,
|
|
4814
7418
|
buttonVariants,
|
|
4815
7419
|
chipInputVariants,
|
|
4816
7420
|
cn,
|
|
7421
|
+
createFilterWithDefaults,
|
|
4817
7422
|
emptyStateVariants,
|
|
7423
|
+
filterChipSegmentVariants,
|
|
4818
7424
|
flexRender,
|
|
7425
|
+
getDefaultOperator,
|
|
7426
|
+
getDefaultSuggestions,
|
|
7427
|
+
getValueInputType,
|
|
4819
7428
|
infoMessageVariants,
|
|
7429
|
+
isNoValueOperator,
|
|
4820
7430
|
linkVariants,
|
|
4821
7431
|
modalVariants,
|
|
4822
7432
|
productLogoVariants,
|