@l3mpire/ui 2.6.0 → 2.7.2

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