@l3mpire/ui 2.12.0 → 2.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/USAGE.md +38 -1
- package/dist/index.d.mts +45 -9
- package/dist/index.d.ts +45 -9
- package/dist/index.js +2769 -2095
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2254 -1573
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -5
package/dist/index.mjs
CHANGED
|
@@ -5016,7 +5016,6 @@ var OPERATORS_BY_TYPE = {
|
|
|
5016
5016
|
"is on or before",
|
|
5017
5017
|
"is on or after",
|
|
5018
5018
|
"is between",
|
|
5019
|
-
"is relative",
|
|
5020
5019
|
"is empty",
|
|
5021
5020
|
"is not empty"
|
|
5022
5021
|
],
|
|
@@ -5035,7 +5034,7 @@ var OPERATORS_BY_TYPE = {
|
|
|
5035
5034
|
var DEFAULT_OPERATOR_BY_TYPE = {
|
|
5036
5035
|
text: "contains",
|
|
5037
5036
|
number: "=",
|
|
5038
|
-
date: "is
|
|
5037
|
+
date: "is between",
|
|
5039
5038
|
enum: "is",
|
|
5040
5039
|
tags: "contains",
|
|
5041
5040
|
boolean: "is true",
|
|
@@ -5063,7 +5062,6 @@ function getValueInputType(type, operator) {
|
|
|
5063
5062
|
return operator === "is between" ? "NumberRange" : "NumberInput";
|
|
5064
5063
|
if (type === "date") {
|
|
5065
5064
|
if (operator === "is between") return "DateRange";
|
|
5066
|
-
if (operator === "is relative") return "PresetTags";
|
|
5067
5065
|
return "DatePicker";
|
|
5068
5066
|
}
|
|
5069
5067
|
if (type === "enum")
|
|
@@ -5074,6 +5072,130 @@ function getValueInputType(type, operator) {
|
|
|
5074
5072
|
return ["is any of", "is none of"].includes(operator) ? "MultiRelationPicker" : "RelationPicker";
|
|
5075
5073
|
return null;
|
|
5076
5074
|
}
|
|
5075
|
+
function formatFilterValue(value) {
|
|
5076
|
+
if (value == null) return void 0;
|
|
5077
|
+
if (typeof value === "boolean") return value ? "Yes" : "No";
|
|
5078
|
+
if (value instanceof Date) {
|
|
5079
|
+
return value.toLocaleDateString("en-US", {
|
|
5080
|
+
month: "short",
|
|
5081
|
+
day: "numeric",
|
|
5082
|
+
year: "numeric"
|
|
5083
|
+
});
|
|
5084
|
+
}
|
|
5085
|
+
if (Array.isArray(value)) {
|
|
5086
|
+
if (value.length === 0) return void 0;
|
|
5087
|
+
if (value.length === 2 && typeof value[0] === "number") {
|
|
5088
|
+
return `${value[0]} \u2013 ${value[1]}`;
|
|
5089
|
+
}
|
|
5090
|
+
if (value.length === 2 && value[0] instanceof Date) {
|
|
5091
|
+
const fmt = (d) => d.toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" });
|
|
5092
|
+
return `${fmt(value[0])} \u2013 ${value[1] instanceof Date ? fmt(value[1]) : "\u2026"}`;
|
|
5093
|
+
}
|
|
5094
|
+
return String(value[0]);
|
|
5095
|
+
}
|
|
5096
|
+
return String(value);
|
|
5097
|
+
}
|
|
5098
|
+
function getBadgeCount(value) {
|
|
5099
|
+
if (Array.isArray(value) && value.length > 1 && typeof value[0] === "string") {
|
|
5100
|
+
return value.length;
|
|
5101
|
+
}
|
|
5102
|
+
return void 0;
|
|
5103
|
+
}
|
|
5104
|
+
function isFilterGroup(node) {
|
|
5105
|
+
return node.type === "group";
|
|
5106
|
+
}
|
|
5107
|
+
function createEmptyGroup() {
|
|
5108
|
+
return {
|
|
5109
|
+
id: crypto.randomUUID(),
|
|
5110
|
+
type: "group",
|
|
5111
|
+
children: []
|
|
5112
|
+
};
|
|
5113
|
+
}
|
|
5114
|
+
function duplicateNode(node) {
|
|
5115
|
+
if (isFilterGroup(node)) {
|
|
5116
|
+
return {
|
|
5117
|
+
...node,
|
|
5118
|
+
id: crypto.randomUUID(),
|
|
5119
|
+
children: node.children.map(duplicateNode)
|
|
5120
|
+
};
|
|
5121
|
+
}
|
|
5122
|
+
return { ...node, id: crypto.randomUUID() };
|
|
5123
|
+
}
|
|
5124
|
+
function wrapInGroup(condition) {
|
|
5125
|
+
return {
|
|
5126
|
+
id: crypto.randomUUID(),
|
|
5127
|
+
type: "group",
|
|
5128
|
+
logicOperator: condition.logicOperator,
|
|
5129
|
+
children: [{ ...condition, logicOperator: void 0 }]
|
|
5130
|
+
};
|
|
5131
|
+
}
|
|
5132
|
+
function unwrapGroup(group) {
|
|
5133
|
+
const first = group.children.find((c) => !isFilterGroup(c));
|
|
5134
|
+
if (!first) return null;
|
|
5135
|
+
return { ...first, logicOperator: group.logicOperator };
|
|
5136
|
+
}
|
|
5137
|
+
function updateNodeInTree(nodes, id, updater) {
|
|
5138
|
+
return nodes.map((node) => {
|
|
5139
|
+
if (node.id === id) return updater(node);
|
|
5140
|
+
if (isFilterGroup(node)) {
|
|
5141
|
+
const updated = updateNodeInTree(node.children, id, updater);
|
|
5142
|
+
if (updated !== node.children) return { ...node, children: updated };
|
|
5143
|
+
}
|
|
5144
|
+
return node;
|
|
5145
|
+
});
|
|
5146
|
+
}
|
|
5147
|
+
function removeNodeFromTree(nodes, id) {
|
|
5148
|
+
const result = [];
|
|
5149
|
+
for (const node of nodes) {
|
|
5150
|
+
if (node.id === id) continue;
|
|
5151
|
+
if (isFilterGroup(node)) {
|
|
5152
|
+
const updated = removeNodeFromTree(node.children, id);
|
|
5153
|
+
result.push(updated !== node.children ? { ...node, children: updated } : node);
|
|
5154
|
+
} else {
|
|
5155
|
+
result.push(node);
|
|
5156
|
+
}
|
|
5157
|
+
}
|
|
5158
|
+
return result;
|
|
5159
|
+
}
|
|
5160
|
+
function insertAfterInTree(nodes, afterId, newNode) {
|
|
5161
|
+
const result = [];
|
|
5162
|
+
let inserted = false;
|
|
5163
|
+
for (const node of nodes) {
|
|
5164
|
+
result.push(node);
|
|
5165
|
+
if (node.id === afterId) {
|
|
5166
|
+
result.push(newNode);
|
|
5167
|
+
inserted = true;
|
|
5168
|
+
} else if (!inserted && isFilterGroup(node)) {
|
|
5169
|
+
const updated = insertAfterInTree(node.children, afterId, newNode);
|
|
5170
|
+
if (updated.length !== node.children.length) {
|
|
5171
|
+
result[result.length - 1] = { ...node, children: updated };
|
|
5172
|
+
inserted = true;
|
|
5173
|
+
}
|
|
5174
|
+
}
|
|
5175
|
+
}
|
|
5176
|
+
return result;
|
|
5177
|
+
}
|
|
5178
|
+
function replaceNodeInTree(nodes, id, replacement) {
|
|
5179
|
+
return nodes.map((node) => {
|
|
5180
|
+
if (node.id === id) return replacement;
|
|
5181
|
+
if (isFilterGroup(node)) {
|
|
5182
|
+
const updated = replaceNodeInTree(node.children, id, replacement);
|
|
5183
|
+
if (updated !== node.children) return { ...node, children: updated };
|
|
5184
|
+
}
|
|
5185
|
+
return node;
|
|
5186
|
+
});
|
|
5187
|
+
}
|
|
5188
|
+
function countConditions(nodes) {
|
|
5189
|
+
let count = 0;
|
|
5190
|
+
for (const node of nodes) {
|
|
5191
|
+
if (isFilterGroup(node)) {
|
|
5192
|
+
count += countConditions(node.children);
|
|
5193
|
+
} else {
|
|
5194
|
+
count++;
|
|
5195
|
+
}
|
|
5196
|
+
}
|
|
5197
|
+
return count;
|
|
5198
|
+
}
|
|
5077
5199
|
|
|
5078
5200
|
// src/components/ui/filter/filter-bar.tsx
|
|
5079
5201
|
import * as React37 from "react";
|
|
@@ -5617,304 +5739,924 @@ var NumberRangeValueInput = ({
|
|
|
5617
5739
|
NumberRangeValueInput.displayName = "NumberRangeValueInput";
|
|
5618
5740
|
|
|
5619
5741
|
// src/components/ui/filter/value-inputs/date-value-input.tsx
|
|
5620
|
-
import
|
|
5621
|
-
var RELATIVE_DATE_PRESETS = [
|
|
5622
|
-
{ group: "Past", options: ["Today", "Yesterday", "Last 7 days", "Last 14 days", "Last 30 days", "Last 90 days"] },
|
|
5623
|
-
{ group: "Current", options: ["This week", "This month", "This quarter", "This year"] },
|
|
5624
|
-
{ group: "Future", options: ["Tomorrow", "Next 7 days", "Next 14 days", "Next 30 days", "Next week", "Next month", "Next quarter"] }
|
|
5625
|
-
];
|
|
5626
|
-
var DatePickerValueInput = ({
|
|
5627
|
-
value,
|
|
5628
|
-
onChange,
|
|
5629
|
-
onSubmit,
|
|
5630
|
-
className
|
|
5631
|
-
}) => /* @__PURE__ */ jsxs39("div", { className: cn("flex flex-col gap-base p-base", className), children: [
|
|
5632
|
-
/* @__PURE__ */ jsx44(
|
|
5633
|
-
"input",
|
|
5634
|
-
{
|
|
5635
|
-
type: "date",
|
|
5636
|
-
value: value instanceof Date ? value.toISOString().split("T")[0] : value ?? "",
|
|
5637
|
-
onChange: (e) => onChange(e.target.value ? new Date(e.target.value) : null),
|
|
5638
|
-
autoFocus: true,
|
|
5639
|
-
className: inputClasses
|
|
5640
|
-
}
|
|
5641
|
-
),
|
|
5642
|
-
/* @__PURE__ */ jsx44("button", { type: "button", onClick: onSubmit, className: applyBtnClasses, children: "Apply" })
|
|
5643
|
-
] });
|
|
5644
|
-
DatePickerValueInput.displayName = "DatePickerValueInput";
|
|
5645
|
-
function toDateString(d) {
|
|
5646
|
-
if (!d) return "";
|
|
5647
|
-
if (d instanceof Date) return d.toISOString().split("T")[0];
|
|
5648
|
-
return String(d);
|
|
5649
|
-
}
|
|
5650
|
-
var DateRangeValueInput = ({
|
|
5651
|
-
value,
|
|
5652
|
-
onChange,
|
|
5653
|
-
onSubmit,
|
|
5654
|
-
className
|
|
5655
|
-
}) => {
|
|
5656
|
-
const rangeVal = Array.isArray(value) ? value : [null, null];
|
|
5657
|
-
return /* @__PURE__ */ jsxs39("div", { className: cn("flex flex-col gap-base p-base", className), children: [
|
|
5658
|
-
/* @__PURE__ */ jsxs39("div", { className: "flex items-center gap-base", children: [
|
|
5659
|
-
/* @__PURE__ */ jsx44(
|
|
5660
|
-
"input",
|
|
5661
|
-
{
|
|
5662
|
-
type: "date",
|
|
5663
|
-
value: toDateString(rangeVal[0]),
|
|
5664
|
-
onChange: (e) => {
|
|
5665
|
-
const from = e.target.value ? new Date(e.target.value) : null;
|
|
5666
|
-
onChange([from, rangeVal[1]]);
|
|
5667
|
-
},
|
|
5668
|
-
autoFocus: true,
|
|
5669
|
-
className: halfInputClasses
|
|
5670
|
-
}
|
|
5671
|
-
),
|
|
5672
|
-
/* @__PURE__ */ jsx44("span", { className: "text-sm text-[var(--color-muted-foreground)]", children: "to" }),
|
|
5673
|
-
/* @__PURE__ */ jsx44(
|
|
5674
|
-
"input",
|
|
5675
|
-
{
|
|
5676
|
-
type: "date",
|
|
5677
|
-
value: toDateString(rangeVal[1]),
|
|
5678
|
-
onChange: (e) => {
|
|
5679
|
-
const to = e.target.value ? new Date(e.target.value) : null;
|
|
5680
|
-
onChange([rangeVal[0], to]);
|
|
5681
|
-
},
|
|
5682
|
-
className: halfInputClasses
|
|
5683
|
-
}
|
|
5684
|
-
)
|
|
5685
|
-
] }),
|
|
5686
|
-
/* @__PURE__ */ jsx44("button", { type: "button", onClick: onSubmit, className: applyBtnClasses, children: "Apply" })
|
|
5687
|
-
] });
|
|
5688
|
-
};
|
|
5689
|
-
DateRangeValueInput.displayName = "DateRangeValueInput";
|
|
5690
|
-
var PresetTagsValueInput = ({
|
|
5691
|
-
value,
|
|
5692
|
-
onChange,
|
|
5693
|
-
onSubmit,
|
|
5694
|
-
className
|
|
5695
|
-
}) => /* @__PURE__ */ jsx44("div", { className: cn("flex flex-col gap-base p-base max-w-[280px]", className), children: RELATIVE_DATE_PRESETS.map((group) => /* @__PURE__ */ jsxs39("div", { className: "flex flex-col gap-xs", children: [
|
|
5696
|
-
/* @__PURE__ */ jsx44("span", { className: "text-xs font-semibold leading-xs text-[var(--color-muted-foreground)] uppercase px-xs", children: group.group }),
|
|
5697
|
-
/* @__PURE__ */ jsx44("div", { className: "flex flex-wrap gap-xs", children: group.options.map((preset) => /* @__PURE__ */ jsx44(
|
|
5698
|
-
"button",
|
|
5699
|
-
{
|
|
5700
|
-
type: "button",
|
|
5701
|
-
onClick: () => {
|
|
5702
|
-
onChange(preset);
|
|
5703
|
-
onSubmit?.();
|
|
5704
|
-
},
|
|
5705
|
-
className: cn(
|
|
5706
|
-
"px-base py-2xs rounded-base border cursor-pointer transition-colors text-sm font-regular leading-sm",
|
|
5707
|
-
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)]"
|
|
5708
|
-
),
|
|
5709
|
-
children: preset
|
|
5710
|
-
},
|
|
5711
|
-
preset
|
|
5712
|
-
)) })
|
|
5713
|
-
] }, group.group)) });
|
|
5714
|
-
PresetTagsValueInput.displayName = "PresetTagsValueInput";
|
|
5715
|
-
|
|
5716
|
-
// src/components/ui/filter/value-inputs/select-value-input.tsx
|
|
5717
|
-
import { jsx as jsx45, jsxs as jsxs40 } from "react/jsx-runtime";
|
|
5718
|
-
var SingleSelectValueInput = ({
|
|
5719
|
-
value,
|
|
5720
|
-
onChange,
|
|
5721
|
-
onSubmit,
|
|
5722
|
-
options,
|
|
5723
|
-
className
|
|
5724
|
-
}) => /* @__PURE__ */ jsx45("div", { className: cn("flex flex-col gap-xs p-base max-h-[250px] overflow-y-auto", className), children: options.map((opt) => /* @__PURE__ */ jsx45(
|
|
5725
|
-
"button",
|
|
5726
|
-
{
|
|
5727
|
-
type: "button",
|
|
5728
|
-
onClick: () => {
|
|
5729
|
-
onChange(opt);
|
|
5730
|
-
onSubmit?.();
|
|
5731
|
-
},
|
|
5732
|
-
className: cn(
|
|
5733
|
-
"flex items-center gap-base p-base rounded-base cursor-pointer transition-colors text-left",
|
|
5734
|
-
"hover:bg-[var(--color-dropdown-item-hover)]",
|
|
5735
|
-
value === opt && "bg-[var(--color-dropdown-item-hover)]"
|
|
5736
|
-
),
|
|
5737
|
-
children: /* @__PURE__ */ jsx45("span", { className: "text-sm font-regular leading-sm text-[var(--color-foreground)]", children: opt })
|
|
5738
|
-
},
|
|
5739
|
-
opt
|
|
5740
|
-
)) });
|
|
5741
|
-
SingleSelectValueInput.displayName = "SingleSelectValueInput";
|
|
5742
|
-
var MultiSelectValueInput = ({
|
|
5743
|
-
value,
|
|
5744
|
-
onChange,
|
|
5745
|
-
onSubmit,
|
|
5746
|
-
options,
|
|
5747
|
-
className
|
|
5748
|
-
}) => {
|
|
5749
|
-
const selected = Array.isArray(value) ? value : [];
|
|
5750
|
-
return /* @__PURE__ */ jsxs40("div", { className: cn("flex flex-col gap-xs p-base", className), children: [
|
|
5751
|
-
/* @__PURE__ */ jsx45("div", { className: "flex flex-col max-h-[200px] overflow-y-auto", children: options.map((opt) => {
|
|
5752
|
-
const isSelected = selected.includes(opt);
|
|
5753
|
-
return /* @__PURE__ */ jsxs40(
|
|
5754
|
-
"button",
|
|
5755
|
-
{
|
|
5756
|
-
type: "button",
|
|
5757
|
-
onClick: () => {
|
|
5758
|
-
const next = isSelected ? selected.filter((s) => s !== opt) : [...selected, opt];
|
|
5759
|
-
onChange(next);
|
|
5760
|
-
},
|
|
5761
|
-
className: cn(
|
|
5762
|
-
"flex items-center gap-base p-base rounded-base cursor-pointer transition-colors text-left",
|
|
5763
|
-
"hover:bg-[var(--color-dropdown-item-hover)]"
|
|
5764
|
-
),
|
|
5765
|
-
children: [
|
|
5766
|
-
/* @__PURE__ */ jsx45(
|
|
5767
|
-
"span",
|
|
5768
|
-
{
|
|
5769
|
-
className: cn(
|
|
5770
|
-
"flex items-center justify-center size-4 rounded-xs border transition-colors",
|
|
5771
|
-
isSelected ? "bg-[var(--color-primary)] border-[var(--color-primary)]" : "border-[var(--color-input)] bg-[var(--color-background)]"
|
|
5772
|
-
),
|
|
5773
|
-
children: isSelected && /* @__PURE__ */ jsx45("svg", { width: "10", height: "10", viewBox: "0 0 10 10", fill: "none", children: /* @__PURE__ */ jsx45("path", { d: "M2 5L4 7L8 3", stroke: "white", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) })
|
|
5774
|
-
}
|
|
5775
|
-
),
|
|
5776
|
-
/* @__PURE__ */ jsx45("span", { className: "text-sm font-regular leading-sm text-[var(--color-foreground)]", children: opt })
|
|
5777
|
-
]
|
|
5778
|
-
},
|
|
5779
|
-
opt
|
|
5780
|
-
);
|
|
5781
|
-
}) }),
|
|
5782
|
-
/* @__PURE__ */ jsx45("button", { type: "button", onClick: onSubmit, className: applyBtnClasses, children: "Apply" })
|
|
5783
|
-
] });
|
|
5784
|
-
};
|
|
5785
|
-
MultiSelectValueInput.displayName = "MultiSelectValueInput";
|
|
5786
|
-
|
|
5787
|
-
// src/components/ui/filter/value-inputs/relation-value-input.tsx
|
|
5788
|
-
import { jsx as jsx46, jsxs as jsxs41 } from "react/jsx-runtime";
|
|
5789
|
-
var RelationValueInput = ({
|
|
5790
|
-
value,
|
|
5791
|
-
onChange,
|
|
5792
|
-
onSubmit,
|
|
5793
|
-
className
|
|
5794
|
-
}) => {
|
|
5795
|
-
const handleKeyDown = (e) => {
|
|
5796
|
-
if (e.key === "Enter") onSubmit?.();
|
|
5797
|
-
};
|
|
5798
|
-
return /* @__PURE__ */ jsxs41("div", { className: cn("flex flex-col gap-base p-base", className), children: [
|
|
5799
|
-
/* @__PURE__ */ jsx46(
|
|
5800
|
-
"input",
|
|
5801
|
-
{
|
|
5802
|
-
type: "text",
|
|
5803
|
-
value: value ?? "",
|
|
5804
|
-
onChange: (e) => onChange(e.target.value),
|
|
5805
|
-
onKeyDown: handleKeyDown,
|
|
5806
|
-
placeholder: "Search...",
|
|
5807
|
-
autoFocus: true,
|
|
5808
|
-
className: inputClasses
|
|
5809
|
-
}
|
|
5810
|
-
),
|
|
5811
|
-
/* @__PURE__ */ jsx46("button", { type: "button", onClick: onSubmit, className: applyBtnClasses, children: "Apply" })
|
|
5812
|
-
] });
|
|
5813
|
-
};
|
|
5814
|
-
RelationValueInput.displayName = "RelationValueInput";
|
|
5815
|
-
|
|
5816
|
-
// src/components/ui/filter/value-input.tsx
|
|
5817
|
-
import { jsx as jsx47 } from "react/jsx-runtime";
|
|
5818
|
-
var ValueInput = ({
|
|
5819
|
-
dataType,
|
|
5820
|
-
operator,
|
|
5821
|
-
value,
|
|
5822
|
-
onChange,
|
|
5823
|
-
onSubmit,
|
|
5824
|
-
options = [],
|
|
5825
|
-
className
|
|
5826
|
-
}) => {
|
|
5827
|
-
const inputType = getValueInputType(dataType, operator);
|
|
5828
|
-
if (!inputType) return null;
|
|
5829
|
-
switch (inputType) {
|
|
5830
|
-
case "TextInput":
|
|
5831
|
-
return /* @__PURE__ */ jsx47(TextValueInput, { value, onChange, onSubmit, className });
|
|
5832
|
-
case "NumberInput":
|
|
5833
|
-
return /* @__PURE__ */ jsx47(NumberValueInput, { value, onChange, onSubmit, className });
|
|
5834
|
-
case "NumberRange":
|
|
5835
|
-
return /* @__PURE__ */ jsx47(NumberRangeValueInput, { value, onChange, onSubmit, className });
|
|
5836
|
-
case "PresetTags":
|
|
5837
|
-
return /* @__PURE__ */ jsx47(PresetTagsValueInput, { value, onChange, onSubmit, className });
|
|
5838
|
-
case "SingleSelect":
|
|
5839
|
-
return /* @__PURE__ */ jsx47(SingleSelectValueInput, { value, onChange, onSubmit, options, className });
|
|
5840
|
-
case "MultiSelect":
|
|
5841
|
-
return /* @__PURE__ */ jsx47(MultiSelectValueInput, { value, onChange, onSubmit, options, className });
|
|
5842
|
-
case "DatePicker":
|
|
5843
|
-
return /* @__PURE__ */ jsx47(DatePickerValueInput, { value, onChange, onSubmit, className });
|
|
5844
|
-
case "DateRange":
|
|
5845
|
-
return /* @__PURE__ */ jsx47(DateRangeValueInput, { value, onChange, onSubmit, className });
|
|
5846
|
-
case "RelationPicker":
|
|
5847
|
-
case "MultiRelationPicker":
|
|
5848
|
-
return /* @__PURE__ */ jsx47(RelationValueInput, { value, onChange, onSubmit, className });
|
|
5849
|
-
default:
|
|
5850
|
-
return null;
|
|
5851
|
-
}
|
|
5852
|
-
};
|
|
5853
|
-
ValueInput.displayName = "ValueInput";
|
|
5742
|
+
import * as React42 from "react";
|
|
5854
5743
|
|
|
5855
|
-
// src/components/ui/
|
|
5744
|
+
// src/components/ui/date-picker.tsx
|
|
5856
5745
|
import * as React41 from "react";
|
|
5857
5746
|
import * as PopoverPrimitive5 from "@radix-ui/react-popover";
|
|
5858
5747
|
import {
|
|
5859
5748
|
Icon as Icon26,
|
|
5860
5749
|
faChevronLeftOutline as faChevronLeftOutline2,
|
|
5861
5750
|
faChevronRightOutline as faChevronRightOutline2,
|
|
5862
|
-
|
|
5863
|
-
|
|
5751
|
+
faArrowRightOutline,
|
|
5752
|
+
faCalendarOutline
|
|
5864
5753
|
} from "@l3mpire/icons";
|
|
5865
|
-
import {
|
|
5866
|
-
|
|
5867
|
-
|
|
5868
|
-
|
|
5869
|
-
|
|
5870
|
-
|
|
5871
|
-
|
|
5872
|
-
|
|
5873
|
-
|
|
5874
|
-
|
|
5875
|
-
|
|
5876
|
-
|
|
5877
|
-
|
|
5878
|
-
|
|
5879
|
-
|
|
5880
|
-
|
|
5881
|
-
|
|
5882
|
-
|
|
5883
|
-
|
|
5884
|
-
|
|
5885
|
-
|
|
5886
|
-
|
|
5887
|
-
|
|
5888
|
-
|
|
5889
|
-
|
|
5890
|
-
|
|
5891
|
-
|
|
5892
|
-
|
|
5893
|
-
|
|
5894
|
-
|
|
5895
|
-
|
|
5896
|
-
|
|
5897
|
-
|
|
5898
|
-
|
|
5899
|
-
|
|
5900
|
-
|
|
5901
|
-
|
|
5902
|
-
|
|
5903
|
-
|
|
5904
|
-
|
|
5905
|
-
|
|
5906
|
-
|
|
5907
|
-
|
|
5908
|
-
|
|
5909
|
-
|
|
5910
|
-
|
|
5911
|
-
|
|
5754
|
+
import { jsx as jsx44, jsxs as jsxs39 } from "react/jsx-runtime";
|
|
5755
|
+
function getDaysInMonth(year, month) {
|
|
5756
|
+
return new Date(year, month + 1, 0).getDate();
|
|
5757
|
+
}
|
|
5758
|
+
function getWeekdayIndex(date) {
|
|
5759
|
+
return (date.getDay() + 6) % 7;
|
|
5760
|
+
}
|
|
5761
|
+
function isSameDay(a, b) {
|
|
5762
|
+
return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
|
|
5763
|
+
}
|
|
5764
|
+
function isInRange(date, from, to) {
|
|
5765
|
+
const t = date.getTime();
|
|
5766
|
+
return t >= from.getTime() && t <= to.getTime();
|
|
5767
|
+
}
|
|
5768
|
+
function startOfDay(d) {
|
|
5769
|
+
return new Date(d.getFullYear(), d.getMonth(), d.getDate());
|
|
5770
|
+
}
|
|
5771
|
+
var WEEKDAYS = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
|
|
5772
|
+
var MONTH_NAMES = [
|
|
5773
|
+
"January",
|
|
5774
|
+
"February",
|
|
5775
|
+
"March",
|
|
5776
|
+
"April",
|
|
5777
|
+
"May",
|
|
5778
|
+
"June",
|
|
5779
|
+
"July",
|
|
5780
|
+
"August",
|
|
5781
|
+
"September",
|
|
5782
|
+
"October",
|
|
5783
|
+
"November",
|
|
5784
|
+
"December"
|
|
5785
|
+
];
|
|
5786
|
+
var DatePickerContext = React41.createContext(
|
|
5787
|
+
null
|
|
5788
|
+
);
|
|
5789
|
+
function useDatePickerContext() {
|
|
5790
|
+
const ctx = React41.useContext(DatePickerContext);
|
|
5791
|
+
if (!ctx)
|
|
5792
|
+
throw new Error("DatePicker compound components must be used within <DatePicker>");
|
|
5793
|
+
return ctx;
|
|
5794
|
+
}
|
|
5795
|
+
var DatePicker = React41.forwardRef(
|
|
5796
|
+
({
|
|
5797
|
+
className,
|
|
5798
|
+
mode = "single",
|
|
5799
|
+
value,
|
|
5800
|
+
onValueChange,
|
|
5801
|
+
defaultMonth,
|
|
5802
|
+
defaultYear,
|
|
5803
|
+
children,
|
|
5804
|
+
...props
|
|
5805
|
+
}, ref) => {
|
|
5806
|
+
const today = React41.useMemo(() => startOfDay(/* @__PURE__ */ new Date()), []);
|
|
5807
|
+
const initialDate = React41.useMemo(() => {
|
|
5808
|
+
if (value) {
|
|
5809
|
+
if (value instanceof Date) return value;
|
|
5810
|
+
return value.from;
|
|
5811
|
+
}
|
|
5812
|
+
return today;
|
|
5813
|
+
}, []);
|
|
5814
|
+
const [month, setMonth] = React41.useState(
|
|
5815
|
+
defaultMonth ?? initialDate.getMonth()
|
|
5816
|
+
);
|
|
5817
|
+
const [year, setYear] = React41.useState(
|
|
5818
|
+
defaultYear ?? initialDate.getFullYear()
|
|
5819
|
+
);
|
|
5820
|
+
const [hoveredDate, setHoveredDate] = React41.useState();
|
|
5821
|
+
const goToPrevMonth = React41.useCallback(() => {
|
|
5822
|
+
setMonth((m) => {
|
|
5823
|
+
if (m === 0) {
|
|
5824
|
+
setYear((y) => y - 1);
|
|
5825
|
+
return 11;
|
|
5826
|
+
}
|
|
5827
|
+
return m - 1;
|
|
5828
|
+
});
|
|
5829
|
+
}, []);
|
|
5830
|
+
const goToNextMonth = React41.useCallback(() => {
|
|
5831
|
+
setMonth((m) => {
|
|
5832
|
+
if (m === 11) {
|
|
5833
|
+
setYear((y) => y + 1);
|
|
5834
|
+
return 0;
|
|
5835
|
+
}
|
|
5836
|
+
return m + 1;
|
|
5837
|
+
});
|
|
5838
|
+
}, []);
|
|
5839
|
+
const onSelect = React41.useCallback(
|
|
5840
|
+
(date) => {
|
|
5841
|
+
if (mode === "single") {
|
|
5842
|
+
onValueChange?.(date);
|
|
5843
|
+
return;
|
|
5844
|
+
}
|
|
5845
|
+
if (!value || value instanceof Date) {
|
|
5846
|
+
onValueChange?.({ from: date });
|
|
5847
|
+
return;
|
|
5848
|
+
}
|
|
5849
|
+
const range = value;
|
|
5850
|
+
if (range.to || date.getTime() < range.from.getTime()) {
|
|
5851
|
+
onValueChange?.({ from: date });
|
|
5852
|
+
} else {
|
|
5853
|
+
onValueChange?.({ from: range.from, to: date });
|
|
5854
|
+
}
|
|
5855
|
+
},
|
|
5856
|
+
[mode, value, onValueChange]
|
|
5857
|
+
);
|
|
5858
|
+
const ctxValue = React41.useMemo(
|
|
5859
|
+
() => ({
|
|
5860
|
+
mode,
|
|
5861
|
+
selected: value,
|
|
5862
|
+
onSelect,
|
|
5863
|
+
month,
|
|
5864
|
+
year,
|
|
5865
|
+
setMonth,
|
|
5866
|
+
setYear,
|
|
5867
|
+
goToPrevMonth,
|
|
5868
|
+
goToNextMonth,
|
|
5869
|
+
today,
|
|
5870
|
+
hoveredDate,
|
|
5871
|
+
setHoveredDate
|
|
5872
|
+
}),
|
|
5873
|
+
[
|
|
5874
|
+
mode,
|
|
5875
|
+
value,
|
|
5876
|
+
onSelect,
|
|
5877
|
+
month,
|
|
5878
|
+
year,
|
|
5879
|
+
goToPrevMonth,
|
|
5880
|
+
goToNextMonth,
|
|
5881
|
+
today,
|
|
5882
|
+
hoveredDate
|
|
5883
|
+
]
|
|
5884
|
+
);
|
|
5885
|
+
return /* @__PURE__ */ jsx44(DatePickerContext.Provider, { value: ctxValue, children: /* @__PURE__ */ jsx44(
|
|
5886
|
+
"div",
|
|
5887
|
+
{
|
|
5888
|
+
ref,
|
|
5889
|
+
className: cn(
|
|
5890
|
+
"flex flex-col overflow-clip",
|
|
5891
|
+
"bg-datepicker-bg border border-datepicker-border rounded-md shadow-lg",
|
|
5892
|
+
className
|
|
5893
|
+
),
|
|
5894
|
+
...props,
|
|
5895
|
+
children
|
|
5896
|
+
}
|
|
5897
|
+
) });
|
|
5898
|
+
}
|
|
5899
|
+
);
|
|
5900
|
+
DatePicker.displayName = "DatePicker";
|
|
5901
|
+
function defaultFormatDate(date) {
|
|
5902
|
+
return date.toLocaleDateString("en-US", {
|
|
5903
|
+
month: "short",
|
|
5904
|
+
day: "numeric",
|
|
5905
|
+
year: "numeric"
|
|
5906
|
+
});
|
|
5907
|
+
}
|
|
5908
|
+
var DatePickerSelects = React41.forwardRef(({ className, formatDate = defaultFormatDate, ...props }, ref) => {
|
|
5909
|
+
const { selected } = useDatePickerContext();
|
|
5910
|
+
const fromDate = selected instanceof Date ? selected : selected?.from;
|
|
5911
|
+
const toDate = selected instanceof Date ? void 0 : selected?.to;
|
|
5912
|
+
return /* @__PURE__ */ jsx44(
|
|
5913
|
+
"div",
|
|
5914
|
+
{
|
|
5915
|
+
ref,
|
|
5916
|
+
className: cn("flex flex-col items-start pt-lg px-lg", className),
|
|
5917
|
+
...props,
|
|
5918
|
+
children: /* @__PURE__ */ jsxs39("div", { className: "flex items-center gap-base w-full", children: [
|
|
5919
|
+
/* @__PURE__ */ jsxs39("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: [
|
|
5920
|
+
/* @__PURE__ */ jsx44("span", { className: "flex-1 text-sm font-regular leading-sm text-datepicker-header-text truncate", children: fromDate ? formatDate(fromDate) : "Start date" }),
|
|
5921
|
+
/* @__PURE__ */ jsx44(Icon26, { icon: faCalendarOutline, size: "sm", className: "shrink-0 text-datepicker-header-text" })
|
|
5922
|
+
] }),
|
|
5923
|
+
/* @__PURE__ */ jsx44(
|
|
5924
|
+
Icon26,
|
|
5925
|
+
{
|
|
5926
|
+
icon: faArrowRightOutline,
|
|
5927
|
+
size: "sm",
|
|
5928
|
+
className: "shrink-0 text-datepicker-header-weekday"
|
|
5929
|
+
}
|
|
5930
|
+
),
|
|
5931
|
+
/* @__PURE__ */ jsxs39("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: [
|
|
5932
|
+
/* @__PURE__ */ jsx44("span", { className: "flex-1 text-sm font-regular leading-sm text-datepicker-header-text truncate", children: toDate ? formatDate(toDate) : "End date" }),
|
|
5933
|
+
/* @__PURE__ */ jsx44(Icon26, { icon: faCalendarOutline, size: "sm", className: "shrink-0 text-datepicker-header-text" })
|
|
5934
|
+
] })
|
|
5935
|
+
] })
|
|
5936
|
+
}
|
|
5937
|
+
);
|
|
5938
|
+
});
|
|
5939
|
+
DatePickerSelects.displayName = "DatePickerSelects";
|
|
5940
|
+
var DatePickerDay = ({ date, isOutside }) => {
|
|
5941
|
+
const { mode, selected, onSelect, today, hoveredDate, setHoveredDate } = useDatePickerContext();
|
|
5942
|
+
const isToday = isSameDay(date, today);
|
|
5943
|
+
const isSelected = selected instanceof Date ? isSameDay(date, selected) : selected?.from ? isSameDay(date, selected.from) || (selected.to ? isSameDay(date, selected.to) : false) : false;
|
|
5944
|
+
const isRangeStart = mode === "range" && selected && !(selected instanceof Date) && selected.from && isSameDay(date, selected.from);
|
|
5945
|
+
const isRangeEnd = mode === "range" && selected && !(selected instanceof Date) && selected.to && isSameDay(date, selected.to);
|
|
5946
|
+
const inRange = mode === "range" && selected && !(selected instanceof Date) && selected.from && selected.to && !isSelected && isInRange(date, selected.from, selected.to);
|
|
5947
|
+
const inPreviewRange = mode === "range" && selected && !(selected instanceof Date) && selected.from && !selected.to && hoveredDate && !isSelected && hoveredDate.getTime() > selected.from.getTime() && isInRange(date, selected.from, hoveredDate);
|
|
5948
|
+
const isInRangeOrPreview = inRange || inPreviewRange;
|
|
5949
|
+
return /* @__PURE__ */ jsxs39(
|
|
5950
|
+
"button",
|
|
5951
|
+
{
|
|
5952
|
+
type: "button",
|
|
5953
|
+
onClick: () => !isOutside && onSelect(date),
|
|
5954
|
+
onMouseEnter: () => mode === "range" && setHoveredDate(date),
|
|
5955
|
+
onMouseLeave: () => mode === "range" && setHoveredDate(void 0),
|
|
5956
|
+
disabled: isOutside,
|
|
5957
|
+
className: cn(
|
|
5958
|
+
"relative flex flex-col items-center justify-center w-9 rounded-full p-2 cursor-pointer transition-colors",
|
|
5959
|
+
"text-sm font-semibold leading-sm text-center",
|
|
5960
|
+
// Default
|
|
5961
|
+
!isOutside && !isSelected && !isInRangeOrPreview && "text-datepicker-day-text-default hover:bg-datepicker-day-bg-hover",
|
|
5962
|
+
// Outside month (disabled)
|
|
5963
|
+
isOutside && "text-datepicker-day-text-disabled cursor-default",
|
|
5964
|
+
// Selected
|
|
5965
|
+
isSelected && "bg-datepicker-day-bg-selected text-datepicker-day-text-selected",
|
|
5966
|
+
// In range
|
|
5967
|
+
isInRangeOrPreview && "bg-datepicker-day-bg-range text-datepicker-day-text-range",
|
|
5968
|
+
// Range start/end get full rounded; in-range items could be less rounded
|
|
5969
|
+
(isRangeStart || isRangeEnd) && "rounded-full"
|
|
5970
|
+
),
|
|
5971
|
+
children: [
|
|
5972
|
+
date.getDate(),
|
|
5973
|
+
isToday && !isOutside && /* @__PURE__ */ jsx44("span", { className: "absolute bottom-0.5 left-1/2 -translate-x-1/2 size-1.5 rounded-full bg-datepicker-day-today" })
|
|
5974
|
+
]
|
|
5975
|
+
}
|
|
5976
|
+
);
|
|
5977
|
+
};
|
|
5978
|
+
var DatePickerCalendar = React41.forwardRef(({ className, header, ...props }, ref) => {
|
|
5979
|
+
const { month, year, goToPrevMonth, goToNextMonth } = useDatePickerContext();
|
|
5980
|
+
const weeks = React41.useMemo(() => {
|
|
5981
|
+
const firstDay = new Date(year, month, 1);
|
|
5982
|
+
const startOffset = getWeekdayIndex(firstDay);
|
|
5983
|
+
const daysInMonth = getDaysInMonth(year, month);
|
|
5984
|
+
const daysInPrevMonth = getDaysInMonth(
|
|
5985
|
+
month === 0 ? year - 1 : year,
|
|
5986
|
+
month === 0 ? 11 : month - 1
|
|
5987
|
+
);
|
|
5988
|
+
const days = [];
|
|
5989
|
+
for (let i = startOffset - 1; i >= 0; i--) {
|
|
5990
|
+
const d = daysInPrevMonth - i;
|
|
5991
|
+
days.push({
|
|
5992
|
+
date: new Date(
|
|
5993
|
+
month === 0 ? year - 1 : year,
|
|
5994
|
+
month === 0 ? 11 : month - 1,
|
|
5995
|
+
d
|
|
5996
|
+
),
|
|
5997
|
+
isOutside: true
|
|
5998
|
+
});
|
|
5999
|
+
}
|
|
6000
|
+
for (let d = 1; d <= daysInMonth; d++) {
|
|
6001
|
+
days.push({ date: new Date(year, month, d), isOutside: false });
|
|
6002
|
+
}
|
|
6003
|
+
const remaining = 42 - days.length;
|
|
6004
|
+
for (let d = 1; d <= remaining; d++) {
|
|
6005
|
+
days.push({
|
|
6006
|
+
date: new Date(
|
|
6007
|
+
month === 11 ? year + 1 : year,
|
|
6008
|
+
month === 11 ? 0 : month + 1,
|
|
6009
|
+
d
|
|
6010
|
+
),
|
|
6011
|
+
isOutside: true
|
|
6012
|
+
});
|
|
6013
|
+
}
|
|
6014
|
+
const result = [];
|
|
6015
|
+
for (let i = 0; i < days.length; i += 7) {
|
|
6016
|
+
result.push(days.slice(i, i + 7));
|
|
6017
|
+
}
|
|
6018
|
+
return result;
|
|
6019
|
+
}, [month, year]);
|
|
6020
|
+
return /* @__PURE__ */ jsxs39(
|
|
6021
|
+
"div",
|
|
6022
|
+
{
|
|
6023
|
+
ref,
|
|
6024
|
+
className: cn("flex flex-col", className),
|
|
6025
|
+
...props,
|
|
6026
|
+
children: [
|
|
6027
|
+
header,
|
|
6028
|
+
/* @__PURE__ */ jsxs39("div", { className: "flex flex-col gap-lg p-lg", children: [
|
|
6029
|
+
/* @__PURE__ */ jsxs39("div", { className: "flex items-center justify-between", children: [
|
|
6030
|
+
/* @__PURE__ */ jsxs39("span", { className: "text-base font-semibold leading-base text-datepicker-header-text", children: [
|
|
6031
|
+
MONTH_NAMES[month],
|
|
6032
|
+
" ",
|
|
6033
|
+
year
|
|
6034
|
+
] }),
|
|
6035
|
+
/* @__PURE__ */ jsxs39("div", { className: "flex items-center gap-xs", children: [
|
|
6036
|
+
/* @__PURE__ */ jsx44(
|
|
6037
|
+
"button",
|
|
6038
|
+
{
|
|
6039
|
+
type: "button",
|
|
6040
|
+
onClick: goToPrevMonth,
|
|
6041
|
+
className: "flex items-center justify-center p-xs rounded-base hover:bg-datepicker-day-bg-hover transition-colors cursor-pointer",
|
|
6042
|
+
"aria-label": "Previous month",
|
|
6043
|
+
children: /* @__PURE__ */ jsx44(Icon26, { icon: faChevronLeftOutline2, size: "xs", className: "text-datepicker-header-nav" })
|
|
6044
|
+
}
|
|
6045
|
+
),
|
|
6046
|
+
/* @__PURE__ */ jsx44(
|
|
6047
|
+
"button",
|
|
6048
|
+
{
|
|
6049
|
+
type: "button",
|
|
6050
|
+
onClick: goToNextMonth,
|
|
6051
|
+
className: "flex items-center justify-center p-xs rounded-base hover:bg-datepicker-day-bg-hover transition-colors cursor-pointer",
|
|
6052
|
+
"aria-label": "Next month",
|
|
6053
|
+
children: /* @__PURE__ */ jsx44(Icon26, { icon: faChevronRightOutline2, size: "xs", className: "text-datepicker-header-nav" })
|
|
6054
|
+
}
|
|
6055
|
+
)
|
|
6056
|
+
] })
|
|
6057
|
+
] }),
|
|
6058
|
+
/* @__PURE__ */ jsxs39("div", { className: "flex flex-col", children: [
|
|
6059
|
+
/* @__PURE__ */ jsx44("div", { className: "grid grid-cols-7 gap-base py-sm", children: WEEKDAYS.map((day) => /* @__PURE__ */ jsx44(
|
|
6060
|
+
"span",
|
|
6061
|
+
{
|
|
6062
|
+
className: "w-9 text-center text-xs font-regular leading-xs text-datepicker-header-weekday",
|
|
6063
|
+
children: day
|
|
6064
|
+
},
|
|
6065
|
+
day
|
|
6066
|
+
)) }),
|
|
6067
|
+
/* @__PURE__ */ jsx44("div", { className: "flex flex-col", children: weeks.map((week, wi) => /* @__PURE__ */ jsx44("div", { className: "grid grid-cols-7 gap-base", children: week.map((day, di) => /* @__PURE__ */ jsx44(
|
|
6068
|
+
DatePickerDay,
|
|
6069
|
+
{
|
|
6070
|
+
date: day.date,
|
|
6071
|
+
isOutside: day.isOutside
|
|
6072
|
+
},
|
|
6073
|
+
di
|
|
6074
|
+
)) }, wi)) })
|
|
6075
|
+
] })
|
|
6076
|
+
] })
|
|
6077
|
+
]
|
|
6078
|
+
}
|
|
6079
|
+
);
|
|
6080
|
+
});
|
|
6081
|
+
DatePickerCalendar.displayName = "DatePickerCalendar";
|
|
6082
|
+
var DatePickerSuggestions = React41.forwardRef(
|
|
6083
|
+
({ className, suggestions, formatDate = defaultFormatDate, ...props }, ref) => {
|
|
6084
|
+
const { onSelect, mode } = useDatePickerContext();
|
|
6085
|
+
const onValueChange = React41.useContext(DatePickerContext) ? void 0 : void 0;
|
|
6086
|
+
const ctx = useDatePickerContext();
|
|
6087
|
+
const handleClick = (suggestion) => {
|
|
6088
|
+
const val = suggestion.getValue();
|
|
6089
|
+
if (val instanceof Date) {
|
|
6090
|
+
ctx.onSelect(val);
|
|
6091
|
+
} else {
|
|
6092
|
+
ctx.onSelect(val.from);
|
|
6093
|
+
if (val.to) {
|
|
6094
|
+
setTimeout(() => ctx.onSelect(val.to), 0);
|
|
6095
|
+
}
|
|
6096
|
+
}
|
|
6097
|
+
};
|
|
6098
|
+
const formatSuggestionDate = (suggestion) => {
|
|
6099
|
+
const val = suggestion.getValue();
|
|
6100
|
+
if (val instanceof Date) {
|
|
6101
|
+
return formatDate(val);
|
|
6102
|
+
}
|
|
6103
|
+
const from = formatDate(val.from);
|
|
6104
|
+
const to = val.to ? formatDate(val.to) : "";
|
|
6105
|
+
return to ? `${from} - ${to}` : from;
|
|
6106
|
+
};
|
|
6107
|
+
return /* @__PURE__ */ jsxs39(
|
|
6108
|
+
"div",
|
|
6109
|
+
{
|
|
6110
|
+
ref,
|
|
6111
|
+
className: cn(
|
|
6112
|
+
"flex flex-col border-l border-datepicker-border self-stretch shrink-0",
|
|
6113
|
+
className
|
|
6114
|
+
),
|
|
6115
|
+
...props,
|
|
6116
|
+
children: [
|
|
6117
|
+
/* @__PURE__ */ jsx44("div", { className: "pt-lg px-base", children: /* @__PURE__ */ jsx44("div", { className: "flex items-center p-base rounded-base", children: /* @__PURE__ */ jsx44("span", { className: "flex-1 text-xs font-semibold leading-xs text-datepicker-suggestion-heading uppercase truncate", children: "Suggestions" }) }) }),
|
|
6118
|
+
/* @__PURE__ */ jsx44("div", { className: "flex flex-1 flex-col p-base min-w-[222px]", children: suggestions.map((suggestion, i) => /* @__PURE__ */ jsxs39(
|
|
6119
|
+
"button",
|
|
6120
|
+
{
|
|
6121
|
+
type: "button",
|
|
6122
|
+
onClick: () => handleClick(suggestion),
|
|
6123
|
+
className: "flex items-center gap-sm p-base rounded-base hover:bg-datepicker-suggestion-hover transition-colors cursor-pointer text-left",
|
|
6124
|
+
children: [
|
|
6125
|
+
/* @__PURE__ */ jsx44("span", { className: "text-sm font-regular leading-sm text-datepicker-suggestion-text truncate shrink-0", children: suggestion.label }),
|
|
6126
|
+
/* @__PURE__ */ jsx44("span", { className: "text-xs font-regular leading-xs text-datepicker-suggestion-date truncate", children: formatSuggestionDate(suggestion) })
|
|
6127
|
+
]
|
|
6128
|
+
},
|
|
6129
|
+
i
|
|
6130
|
+
)) })
|
|
6131
|
+
]
|
|
6132
|
+
}
|
|
6133
|
+
);
|
|
6134
|
+
}
|
|
6135
|
+
);
|
|
6136
|
+
DatePickerSuggestions.displayName = "DatePickerSuggestions";
|
|
6137
|
+
var DatePickerFooter = React41.forwardRef(
|
|
6138
|
+
({ className, children, ...props }, ref) => /* @__PURE__ */ jsx44(
|
|
6139
|
+
"div",
|
|
6140
|
+
{
|
|
6141
|
+
ref,
|
|
6142
|
+
className: cn(
|
|
6143
|
+
"flex items-center justify-between p-lg",
|
|
6144
|
+
"border-t border-datepicker-footer-border",
|
|
6145
|
+
"bg-datepicker-bg",
|
|
6146
|
+
className
|
|
6147
|
+
),
|
|
6148
|
+
...props,
|
|
6149
|
+
children
|
|
6150
|
+
}
|
|
6151
|
+
)
|
|
6152
|
+
);
|
|
6153
|
+
DatePickerFooter.displayName = "DatePickerFooter";
|
|
6154
|
+
var DatePickerPanel = React41.forwardRef(
|
|
6155
|
+
({ className, children, ...props }, ref) => /* @__PURE__ */ jsx44(
|
|
6156
|
+
"div",
|
|
6157
|
+
{
|
|
6158
|
+
ref,
|
|
6159
|
+
className: cn("flex items-start", className),
|
|
6160
|
+
...props,
|
|
6161
|
+
children
|
|
6162
|
+
}
|
|
6163
|
+
)
|
|
6164
|
+
);
|
|
6165
|
+
DatePickerPanel.displayName = "DatePickerPanel";
|
|
6166
|
+
var DatePickerRoot = PopoverPrimitive5.Root;
|
|
6167
|
+
var DatePickerTrigger = PopoverPrimitive5.Trigger;
|
|
6168
|
+
var DatePickerPopover = React41.forwardRef(({ className, sideOffset = 4, align = "start", children, ...props }, ref) => /* @__PURE__ */ jsx44(PopoverPrimitive5.Portal, { children: /* @__PURE__ */ jsx44(
|
|
6169
|
+
PopoverPrimitive5.Content,
|
|
6170
|
+
{
|
|
6171
|
+
ref,
|
|
6172
|
+
sideOffset,
|
|
6173
|
+
align,
|
|
6174
|
+
className: cn(
|
|
6175
|
+
"z-50",
|
|
6176
|
+
"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
|
|
6177
|
+
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
|
|
6178
|
+
"data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2",
|
|
6179
|
+
className
|
|
6180
|
+
),
|
|
6181
|
+
...props,
|
|
6182
|
+
children
|
|
6183
|
+
}
|
|
6184
|
+
) }));
|
|
6185
|
+
DatePickerPopover.displayName = "DatePickerPopover";
|
|
6186
|
+
function getDefaultSuggestions(referenceDate) {
|
|
6187
|
+
const now = referenceDate ?? /* @__PURE__ */ new Date();
|
|
6188
|
+
const today = startOfDay(now);
|
|
6189
|
+
const dayOfWeek = getWeekdayIndex(today);
|
|
6190
|
+
const startOfThisWeek = new Date(today);
|
|
6191
|
+
startOfThisWeek.setDate(today.getDate() - dayOfWeek);
|
|
6192
|
+
const endOfThisWeek = new Date(startOfThisWeek);
|
|
6193
|
+
endOfThisWeek.setDate(startOfThisWeek.getDate() + 6);
|
|
6194
|
+
const startOfThisMonth = new Date(today.getFullYear(), today.getMonth(), 1);
|
|
6195
|
+
const endOfThisMonth = new Date(
|
|
6196
|
+
today.getFullYear(),
|
|
6197
|
+
today.getMonth() + 1,
|
|
6198
|
+
0
|
|
6199
|
+
);
|
|
6200
|
+
const startOfThisYear = new Date(today.getFullYear(), 0, 1);
|
|
6201
|
+
const endOfThisYear = new Date(today.getFullYear(), 11, 31);
|
|
6202
|
+
const startOfLastWeek = new Date(startOfThisWeek);
|
|
6203
|
+
startOfLastWeek.setDate(startOfThisWeek.getDate() - 7);
|
|
6204
|
+
const endOfLastWeek = new Date(startOfThisWeek);
|
|
6205
|
+
endOfLastWeek.setDate(startOfThisWeek.getDate() - 1);
|
|
6206
|
+
const startOfLastMonth = new Date(
|
|
6207
|
+
today.getFullYear(),
|
|
6208
|
+
today.getMonth() - 1,
|
|
6209
|
+
1
|
|
6210
|
+
);
|
|
6211
|
+
const endOfLastMonth = new Date(today.getFullYear(), today.getMonth(), 0);
|
|
6212
|
+
const startOfLastYear = new Date(today.getFullYear() - 1, 0, 1);
|
|
6213
|
+
const endOfLastYear = new Date(today.getFullYear() - 1, 11, 31);
|
|
6214
|
+
return [
|
|
6215
|
+
{ label: "Today", getValue: () => today },
|
|
6216
|
+
{
|
|
6217
|
+
label: "This week",
|
|
6218
|
+
getValue: () => ({ from: startOfThisWeek, to: endOfThisWeek })
|
|
6219
|
+
},
|
|
6220
|
+
{
|
|
6221
|
+
label: "This month",
|
|
6222
|
+
getValue: () => ({ from: startOfThisMonth, to: endOfThisMonth })
|
|
6223
|
+
},
|
|
6224
|
+
{
|
|
6225
|
+
label: "This year",
|
|
6226
|
+
getValue: () => ({ from: startOfThisYear, to: endOfThisYear })
|
|
6227
|
+
},
|
|
6228
|
+
{
|
|
6229
|
+
label: "Last week",
|
|
6230
|
+
getValue: () => ({ from: startOfLastWeek, to: endOfLastWeek })
|
|
6231
|
+
},
|
|
6232
|
+
{
|
|
6233
|
+
label: "Last month",
|
|
6234
|
+
getValue: () => ({ from: startOfLastMonth, to: endOfLastMonth })
|
|
6235
|
+
},
|
|
6236
|
+
{
|
|
6237
|
+
label: "Last year",
|
|
6238
|
+
getValue: () => ({ from: startOfLastYear, to: endOfLastYear })
|
|
6239
|
+
}
|
|
6240
|
+
];
|
|
6241
|
+
}
|
|
6242
|
+
|
|
6243
|
+
// src/components/ui/filter/value-inputs/date-value-input.tsx
|
|
6244
|
+
import { jsx as jsx45, jsxs as jsxs40 } from "react/jsx-runtime";
|
|
6245
|
+
var RELATIVE_DATE_PRESETS = [
|
|
6246
|
+
{ group: "Past", options: ["Today", "Yesterday", "Last 7 days", "Last 14 days", "Last 30 days", "Last 90 days"] },
|
|
6247
|
+
{ group: "Current", options: ["This week", "This month", "This quarter", "This year"] },
|
|
6248
|
+
{ group: "Future", options: ["Tomorrow", "Next 7 days", "Next 14 days", "Next 30 days", "Next week", "Next month", "Next quarter"] }
|
|
6249
|
+
];
|
|
6250
|
+
var DateCalendarValueInput = ({
|
|
6251
|
+
operator,
|
|
6252
|
+
value,
|
|
6253
|
+
onChange,
|
|
6254
|
+
onSubmit,
|
|
6255
|
+
className
|
|
6256
|
+
}) => {
|
|
6257
|
+
const isRange = operator === "is between";
|
|
6258
|
+
const pickerValue = React42.useMemo(() => {
|
|
6259
|
+
if (isRange) {
|
|
6260
|
+
if (Array.isArray(value) && value.length === 2) {
|
|
6261
|
+
const [from, to] = value;
|
|
6262
|
+
return { from, to };
|
|
6263
|
+
}
|
|
6264
|
+
return void 0;
|
|
6265
|
+
}
|
|
6266
|
+
return value instanceof Date ? value : void 0;
|
|
6267
|
+
}, [value, isRange]);
|
|
6268
|
+
const handleValueChange = (v) => {
|
|
6269
|
+
if (v instanceof Date) {
|
|
6270
|
+
onChange(v);
|
|
6271
|
+
if (!isRange) onSubmit?.();
|
|
6272
|
+
} else {
|
|
6273
|
+
const range = v;
|
|
6274
|
+
if (range.from && range.to) {
|
|
6275
|
+
onChange([range.from, range.to]);
|
|
6276
|
+
} else if (range.from) {
|
|
6277
|
+
onChange([range.from, range.from]);
|
|
6278
|
+
}
|
|
6279
|
+
}
|
|
6280
|
+
};
|
|
6281
|
+
const suggestions = React42.useMemo(() => getDefaultSuggestions(), []);
|
|
6282
|
+
return /* @__PURE__ */ jsx45("div", { className: cn("flex flex-col", className), children: /* @__PURE__ */ jsxs40(
|
|
6283
|
+
DatePicker,
|
|
6284
|
+
{
|
|
6285
|
+
mode: isRange ? "range" : "single",
|
|
6286
|
+
value: pickerValue,
|
|
6287
|
+
onValueChange: handleValueChange,
|
|
6288
|
+
children: [
|
|
6289
|
+
isRange && /* @__PURE__ */ jsx45(DatePickerSelects, {}),
|
|
6290
|
+
isRange ? /* @__PURE__ */ jsxs40(DatePickerPanel, { children: [
|
|
6291
|
+
/* @__PURE__ */ jsx45(DatePickerCalendar, {}),
|
|
6292
|
+
/* @__PURE__ */ jsx45(DatePickerSuggestions, { suggestions })
|
|
6293
|
+
] }) : /* @__PURE__ */ jsx45(DatePickerCalendar, {}),
|
|
6294
|
+
isRange && /* @__PURE__ */ jsxs40(DatePickerFooter, { children: [
|
|
6295
|
+
/* @__PURE__ */ jsx45("div", {}),
|
|
6296
|
+
/* @__PURE__ */ jsx45("button", { type: "button", onClick: onSubmit, className: applyBtnClasses, children: "Apply" })
|
|
6297
|
+
] })
|
|
6298
|
+
]
|
|
6299
|
+
}
|
|
6300
|
+
) });
|
|
6301
|
+
};
|
|
6302
|
+
DateCalendarValueInput.displayName = "DateCalendarValueInput";
|
|
6303
|
+
var PresetTagsValueInput = ({
|
|
6304
|
+
value,
|
|
6305
|
+
onChange,
|
|
6306
|
+
onSubmit,
|
|
6307
|
+
className
|
|
6308
|
+
}) => /* @__PURE__ */ jsx45("div", { className: cn("flex flex-col gap-base p-base max-w-[280px]", className), children: RELATIVE_DATE_PRESETS.map((group) => /* @__PURE__ */ jsxs40("div", { className: "flex flex-col gap-xs", children: [
|
|
6309
|
+
/* @__PURE__ */ jsx45("span", { className: "text-xs font-semibold leading-xs text-[var(--color-muted-foreground)] uppercase px-xs", children: group.group }),
|
|
6310
|
+
/* @__PURE__ */ jsx45("div", { className: "flex flex-wrap gap-xs", children: group.options.map((preset) => /* @__PURE__ */ jsx45(
|
|
6311
|
+
"button",
|
|
6312
|
+
{
|
|
6313
|
+
type: "button",
|
|
6314
|
+
onClick: () => {
|
|
6315
|
+
onChange(preset);
|
|
6316
|
+
onSubmit?.();
|
|
6317
|
+
},
|
|
6318
|
+
className: cn(
|
|
6319
|
+
"px-base py-2xs rounded-base border cursor-pointer transition-colors text-sm font-regular leading-sm",
|
|
6320
|
+
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)]"
|
|
6321
|
+
),
|
|
6322
|
+
children: preset
|
|
6323
|
+
},
|
|
6324
|
+
preset
|
|
6325
|
+
)) })
|
|
6326
|
+
] }, group.group)) });
|
|
6327
|
+
PresetTagsValueInput.displayName = "PresetTagsValueInput";
|
|
6328
|
+
|
|
6329
|
+
// src/components/ui/filter/value-inputs/select-value-input.tsx
|
|
6330
|
+
import { Icon as Icon27 } from "@l3mpire/icons";
|
|
6331
|
+
import { jsx as jsx46, jsxs as jsxs41 } from "react/jsx-runtime";
|
|
6332
|
+
var DynamicOptionRow = ({
|
|
6333
|
+
option,
|
|
6334
|
+
selected,
|
|
6335
|
+
multi,
|
|
6336
|
+
onClick
|
|
6337
|
+
}) => /* @__PURE__ */ jsxs41(
|
|
6338
|
+
"button",
|
|
6339
|
+
{
|
|
6340
|
+
type: "button",
|
|
6341
|
+
onClick,
|
|
6342
|
+
className: cn(
|
|
6343
|
+
"flex items-start gap-base p-base rounded-base cursor-pointer transition-colors text-left",
|
|
6344
|
+
"hover:bg-[var(--color-dropdown-item-hover)]",
|
|
6345
|
+
selected && "bg-[var(--color-dropdown-item-hover)]"
|
|
6346
|
+
),
|
|
6347
|
+
children: [
|
|
6348
|
+
multi && /* @__PURE__ */ jsx46(
|
|
6349
|
+
"span",
|
|
6350
|
+
{
|
|
6351
|
+
className: cn(
|
|
6352
|
+
"mt-[2px] flex items-center justify-center size-4 rounded-xs border transition-colors shrink-0",
|
|
6353
|
+
selected ? "bg-[var(--color-primary)] border-[var(--color-primary)]" : "border-[var(--color-input)] bg-[var(--color-background)]"
|
|
6354
|
+
),
|
|
6355
|
+
children: selected && /* @__PURE__ */ jsx46("svg", { width: "10", height: "10", viewBox: "0 0 10 10", fill: "none", children: /* @__PURE__ */ jsx46(
|
|
6356
|
+
"path",
|
|
6357
|
+
{
|
|
6358
|
+
d: "M2 5L4 7L8 3",
|
|
6359
|
+
stroke: "white",
|
|
6360
|
+
strokeWidth: "1.5",
|
|
6361
|
+
strokeLinecap: "round",
|
|
6362
|
+
strokeLinejoin: "round"
|
|
6363
|
+
}
|
|
6364
|
+
) })
|
|
6365
|
+
}
|
|
6366
|
+
),
|
|
6367
|
+
option.icon && /* @__PURE__ */ jsx46(
|
|
6368
|
+
Icon27,
|
|
6369
|
+
{
|
|
6370
|
+
icon: option.icon,
|
|
6371
|
+
size: "sm",
|
|
6372
|
+
className: "shrink-0 mt-[1px] text-[var(--color-interactive-text-primary-dark-default,var(--color-primary))]"
|
|
6373
|
+
}
|
|
6374
|
+
),
|
|
6375
|
+
/* @__PURE__ */ jsxs41("span", { className: "flex-1 flex flex-col gap-2xs min-w-0", children: [
|
|
6376
|
+
/* @__PURE__ */ jsx46("span", { className: "text-sm font-regular leading-sm text-[var(--color-foreground)] truncate", children: option.label }),
|
|
6377
|
+
option.description && /* @__PURE__ */ jsx46("span", { className: "text-xs font-regular leading-xs text-[var(--color-muted-foreground)]", children: option.description })
|
|
6378
|
+
] })
|
|
6379
|
+
]
|
|
6380
|
+
}
|
|
6381
|
+
);
|
|
6382
|
+
var DynamicOptionsDivider = () => /* @__PURE__ */ jsx46("div", { className: "h-px bg-[var(--color-dropdown-border)] mx-xs my-xs" });
|
|
6383
|
+
var SingleSelectValueInput = ({
|
|
6384
|
+
value,
|
|
6385
|
+
onChange,
|
|
6386
|
+
onSubmit,
|
|
6387
|
+
options,
|
|
6388
|
+
dynamicOptions,
|
|
6389
|
+
className
|
|
6390
|
+
}) => {
|
|
6391
|
+
const pick = (v) => {
|
|
6392
|
+
onChange(v);
|
|
6393
|
+
onSubmit?.();
|
|
6394
|
+
};
|
|
6395
|
+
return /* @__PURE__ */ jsxs41(
|
|
6396
|
+
"div",
|
|
6397
|
+
{
|
|
6398
|
+
className: cn(
|
|
6399
|
+
"flex flex-col gap-xs p-base max-h-[280px] overflow-y-auto",
|
|
6400
|
+
className
|
|
6401
|
+
),
|
|
6402
|
+
children: [
|
|
6403
|
+
dynamicOptions?.map((opt) => /* @__PURE__ */ jsx46(
|
|
6404
|
+
DynamicOptionRow,
|
|
6405
|
+
{
|
|
6406
|
+
option: opt,
|
|
6407
|
+
selected: value === opt.value,
|
|
6408
|
+
multi: false,
|
|
6409
|
+
onClick: () => pick(opt.value)
|
|
6410
|
+
},
|
|
6411
|
+
opt.value
|
|
6412
|
+
)),
|
|
6413
|
+
dynamicOptions && dynamicOptions.length > 0 && options.length > 0 && /* @__PURE__ */ jsx46(DynamicOptionsDivider, {}),
|
|
6414
|
+
options.map((opt) => /* @__PURE__ */ jsx46(
|
|
6415
|
+
"button",
|
|
6416
|
+
{
|
|
6417
|
+
type: "button",
|
|
6418
|
+
onClick: () => pick(opt),
|
|
6419
|
+
className: cn(
|
|
6420
|
+
"flex items-center gap-base p-base rounded-base cursor-pointer transition-colors text-left",
|
|
6421
|
+
"hover:bg-[var(--color-dropdown-item-hover)]",
|
|
6422
|
+
value === opt && "bg-[var(--color-dropdown-item-hover)]"
|
|
6423
|
+
),
|
|
6424
|
+
children: /* @__PURE__ */ jsx46("span", { className: "text-sm font-regular leading-sm text-[var(--color-foreground)]", children: opt })
|
|
6425
|
+
},
|
|
6426
|
+
opt
|
|
6427
|
+
))
|
|
6428
|
+
]
|
|
6429
|
+
}
|
|
6430
|
+
);
|
|
6431
|
+
};
|
|
6432
|
+
SingleSelectValueInput.displayName = "SingleSelectValueInput";
|
|
6433
|
+
var MultiSelectValueInput = ({
|
|
6434
|
+
value,
|
|
6435
|
+
onChange,
|
|
6436
|
+
onSubmit,
|
|
6437
|
+
options,
|
|
6438
|
+
dynamicOptions,
|
|
6439
|
+
className
|
|
6440
|
+
}) => {
|
|
6441
|
+
const selected = Array.isArray(value) ? value : [];
|
|
6442
|
+
const toggle = (v) => {
|
|
6443
|
+
const next = selected.includes(v) ? selected.filter((s) => s !== v) : [...selected, v];
|
|
6444
|
+
onChange(next);
|
|
6445
|
+
};
|
|
6446
|
+
return /* @__PURE__ */ jsxs41("div", { className: cn("flex flex-col gap-xs p-base", className), children: [
|
|
6447
|
+
/* @__PURE__ */ jsxs41("div", { className: "flex flex-col max-h-[240px] overflow-y-auto", children: [
|
|
6448
|
+
dynamicOptions?.map((opt) => /* @__PURE__ */ jsx46(
|
|
6449
|
+
DynamicOptionRow,
|
|
6450
|
+
{
|
|
6451
|
+
option: opt,
|
|
6452
|
+
selected: selected.includes(opt.value),
|
|
6453
|
+
multi: true,
|
|
6454
|
+
onClick: () => toggle(opt.value)
|
|
6455
|
+
},
|
|
6456
|
+
opt.value
|
|
6457
|
+
)),
|
|
6458
|
+
dynamicOptions && dynamicOptions.length > 0 && options.length > 0 && /* @__PURE__ */ jsx46(DynamicOptionsDivider, {}),
|
|
6459
|
+
options.map((opt) => {
|
|
6460
|
+
const isSelected = selected.includes(opt);
|
|
6461
|
+
return /* @__PURE__ */ jsxs41(
|
|
6462
|
+
"button",
|
|
6463
|
+
{
|
|
6464
|
+
type: "button",
|
|
6465
|
+
onClick: () => toggle(opt),
|
|
6466
|
+
className: cn(
|
|
6467
|
+
"flex items-center gap-base p-base rounded-base cursor-pointer transition-colors text-left",
|
|
6468
|
+
"hover:bg-[var(--color-dropdown-item-hover)]"
|
|
6469
|
+
),
|
|
6470
|
+
children: [
|
|
6471
|
+
/* @__PURE__ */ jsx46(
|
|
6472
|
+
"span",
|
|
6473
|
+
{
|
|
6474
|
+
className: cn(
|
|
6475
|
+
"flex items-center justify-center size-4 rounded-xs border transition-colors",
|
|
6476
|
+
isSelected ? "bg-[var(--color-primary)] border-[var(--color-primary)]" : "border-[var(--color-input)] bg-[var(--color-background)]"
|
|
6477
|
+
),
|
|
6478
|
+
children: isSelected && /* @__PURE__ */ jsx46("svg", { width: "10", height: "10", viewBox: "0 0 10 10", fill: "none", children: /* @__PURE__ */ jsx46(
|
|
6479
|
+
"path",
|
|
6480
|
+
{
|
|
6481
|
+
d: "M2 5L4 7L8 3",
|
|
6482
|
+
stroke: "white",
|
|
6483
|
+
strokeWidth: "1.5",
|
|
6484
|
+
strokeLinecap: "round",
|
|
6485
|
+
strokeLinejoin: "round"
|
|
6486
|
+
}
|
|
6487
|
+
) })
|
|
6488
|
+
}
|
|
6489
|
+
),
|
|
6490
|
+
/* @__PURE__ */ jsx46("span", { className: "text-sm font-regular leading-sm text-[var(--color-foreground)]", children: opt })
|
|
6491
|
+
]
|
|
6492
|
+
},
|
|
6493
|
+
opt
|
|
6494
|
+
);
|
|
6495
|
+
})
|
|
6496
|
+
] }),
|
|
6497
|
+
/* @__PURE__ */ jsx46("button", { type: "button", onClick: onSubmit, className: applyBtnClasses, children: "Apply" })
|
|
6498
|
+
] });
|
|
6499
|
+
};
|
|
6500
|
+
MultiSelectValueInput.displayName = "MultiSelectValueInput";
|
|
6501
|
+
|
|
6502
|
+
// src/components/ui/filter/value-inputs/relation-value-input.tsx
|
|
6503
|
+
import { jsx as jsx47, jsxs as jsxs42 } from "react/jsx-runtime";
|
|
6504
|
+
var RelationValueInput = ({
|
|
6505
|
+
value,
|
|
6506
|
+
onChange,
|
|
6507
|
+
onSubmit,
|
|
6508
|
+
className
|
|
6509
|
+
}) => {
|
|
6510
|
+
const handleKeyDown = (e) => {
|
|
6511
|
+
if (e.key === "Enter") onSubmit?.();
|
|
6512
|
+
};
|
|
6513
|
+
return /* @__PURE__ */ jsxs42("div", { className: cn("flex flex-col gap-base p-base", className), children: [
|
|
6514
|
+
/* @__PURE__ */ jsx47(
|
|
6515
|
+
"input",
|
|
6516
|
+
{
|
|
6517
|
+
type: "text",
|
|
6518
|
+
value: value ?? "",
|
|
6519
|
+
onChange: (e) => onChange(e.target.value),
|
|
6520
|
+
onKeyDown: handleKeyDown,
|
|
6521
|
+
placeholder: "Search...",
|
|
6522
|
+
autoFocus: true,
|
|
6523
|
+
className: inputClasses
|
|
6524
|
+
}
|
|
6525
|
+
),
|
|
6526
|
+
/* @__PURE__ */ jsx47("button", { type: "button", onClick: onSubmit, className: applyBtnClasses, children: "Apply" })
|
|
6527
|
+
] });
|
|
6528
|
+
};
|
|
6529
|
+
RelationValueInput.displayName = "RelationValueInput";
|
|
6530
|
+
|
|
6531
|
+
// src/components/ui/filter/value-input.tsx
|
|
6532
|
+
import { jsx as jsx48 } from "react/jsx-runtime";
|
|
6533
|
+
var ValueInput = ({
|
|
6534
|
+
dataType,
|
|
6535
|
+
operator,
|
|
6536
|
+
value,
|
|
6537
|
+
onChange,
|
|
6538
|
+
onSubmit,
|
|
6539
|
+
options = [],
|
|
6540
|
+
dynamicOptions,
|
|
6541
|
+
className
|
|
6542
|
+
}) => {
|
|
6543
|
+
const inputType = getValueInputType(dataType, operator);
|
|
6544
|
+
if (!inputType) return null;
|
|
6545
|
+
switch (inputType) {
|
|
6546
|
+
case "TextInput":
|
|
6547
|
+
return /* @__PURE__ */ jsx48(TextValueInput, { value, onChange, onSubmit, className });
|
|
6548
|
+
case "NumberInput":
|
|
6549
|
+
return /* @__PURE__ */ jsx48(NumberValueInput, { value, onChange, onSubmit, className });
|
|
6550
|
+
case "NumberRange":
|
|
6551
|
+
return /* @__PURE__ */ jsx48(NumberRangeValueInput, { value, onChange, onSubmit, className });
|
|
6552
|
+
case "SingleSelect":
|
|
6553
|
+
return /* @__PURE__ */ jsx48(
|
|
6554
|
+
SingleSelectValueInput,
|
|
6555
|
+
{
|
|
6556
|
+
value,
|
|
6557
|
+
onChange,
|
|
6558
|
+
onSubmit,
|
|
6559
|
+
options,
|
|
6560
|
+
dynamicOptions,
|
|
6561
|
+
className
|
|
6562
|
+
}
|
|
6563
|
+
);
|
|
6564
|
+
case "MultiSelect":
|
|
6565
|
+
return /* @__PURE__ */ jsx48(
|
|
6566
|
+
MultiSelectValueInput,
|
|
6567
|
+
{
|
|
6568
|
+
value,
|
|
6569
|
+
onChange,
|
|
6570
|
+
onSubmit,
|
|
6571
|
+
options,
|
|
6572
|
+
dynamicOptions,
|
|
6573
|
+
className
|
|
6574
|
+
}
|
|
6575
|
+
);
|
|
6576
|
+
case "DatePicker":
|
|
6577
|
+
case "DateRange":
|
|
6578
|
+
return /* @__PURE__ */ jsx48(
|
|
6579
|
+
DateCalendarValueInput,
|
|
6580
|
+
{
|
|
6581
|
+
operator,
|
|
6582
|
+
value,
|
|
6583
|
+
onChange,
|
|
6584
|
+
onSubmit,
|
|
6585
|
+
className
|
|
6586
|
+
}
|
|
6587
|
+
);
|
|
6588
|
+
case "RelationPicker":
|
|
6589
|
+
case "MultiRelationPicker":
|
|
6590
|
+
return /* @__PURE__ */ jsx48(RelationValueInput, { value, onChange, onSubmit, className });
|
|
6591
|
+
default:
|
|
6592
|
+
return null;
|
|
6593
|
+
}
|
|
6594
|
+
};
|
|
6595
|
+
ValueInput.displayName = "ValueInput";
|
|
6596
|
+
|
|
6597
|
+
// src/components/ui/filter/property-selector.tsx
|
|
6598
|
+
import * as React43 from "react";
|
|
6599
|
+
import * as PopoverPrimitive6 from "@radix-ui/react-popover";
|
|
6600
|
+
import {
|
|
6601
|
+
Icon as Icon28,
|
|
6602
|
+
faChevronLeftOutline as faChevronLeftOutline3,
|
|
6603
|
+
faChevronRightOutline as faChevronRightOutline3,
|
|
6604
|
+
faMagnifyingGlassOutline,
|
|
6605
|
+
faFilterOutline as faFilterOutline2
|
|
6606
|
+
} from "@l3mpire/icons";
|
|
6607
|
+
import { Fragment as Fragment4, jsx as jsx49, jsxs as jsxs43 } from "react/jsx-runtime";
|
|
6608
|
+
var AdvancedFilterFooter = ({ onClick, count }) => /* @__PURE__ */ jsxs43(Fragment4, { children: [
|
|
6609
|
+
/* @__PURE__ */ jsx49("div", { className: "h-px bg-[var(--color-dropdown-border)] mx-xs" }),
|
|
6610
|
+
/* @__PURE__ */ jsxs43(
|
|
6611
|
+
"button",
|
|
6612
|
+
{
|
|
6613
|
+
type: "button",
|
|
6614
|
+
onPointerDown: (e) => e.preventDefault(),
|
|
6615
|
+
onClick,
|
|
6616
|
+
className: "flex items-center gap-base p-base rounded-base cursor-pointer transition-colors hover:bg-[var(--color-dropdown-item-hover)]",
|
|
6617
|
+
children: [
|
|
6618
|
+
/* @__PURE__ */ jsx49(
|
|
6619
|
+
Icon28,
|
|
6620
|
+
{
|
|
6621
|
+
icon: faFilterOutline2,
|
|
6622
|
+
size: "sm",
|
|
6623
|
+
className: "shrink-0 text-[var(--color-dropdown-item-icon)]"
|
|
6624
|
+
}
|
|
6625
|
+
),
|
|
6626
|
+
/* @__PURE__ */ jsx49("span", { className: "flex-1 text-sm font-regular leading-sm text-[var(--color-dropdown-item-text)] text-left truncate", children: "Advanced filter" }),
|
|
6627
|
+
count > 0 && /* @__PURE__ */ jsxs43("span", { className: "text-xs font-regular leading-xs text-[var(--color-muted-foreground)]", children: [
|
|
6628
|
+
count,
|
|
6629
|
+
" ",
|
|
6630
|
+
count === 1 ? "rule" : "rules"
|
|
6631
|
+
] })
|
|
6632
|
+
]
|
|
6633
|
+
}
|
|
6634
|
+
)
|
|
6635
|
+
] });
|
|
6636
|
+
var PropertySelector = ({
|
|
6637
|
+
properties,
|
|
6638
|
+
onSelect,
|
|
6639
|
+
open,
|
|
6640
|
+
onOpenChange,
|
|
6641
|
+
children,
|
|
6642
|
+
onAdvancedFilter,
|
|
6643
|
+
advancedFilterCount = 0
|
|
6644
|
+
}) => {
|
|
6645
|
+
const handleAdvancedClick = (e) => {
|
|
6646
|
+
e.stopPropagation();
|
|
6647
|
+
e.preventDefault();
|
|
6648
|
+
onAdvancedFilter?.();
|
|
6649
|
+
};
|
|
6650
|
+
const showAdvancedFooter = !!onAdvancedFilter;
|
|
6651
|
+
const [activeGroup, setActiveGroup] = React43.useState(null);
|
|
6652
|
+
const [search, setSearch] = React43.useState("");
|
|
6653
|
+
React43.useEffect(() => {
|
|
5912
6654
|
if (!open) {
|
|
5913
6655
|
setActiveGroup(null);
|
|
5914
6656
|
setSearch("");
|
|
5915
6657
|
}
|
|
5916
6658
|
}, [open]);
|
|
5917
|
-
const groups =
|
|
6659
|
+
const groups = React43.useMemo(() => {
|
|
5918
6660
|
const map = /* @__PURE__ */ new Map();
|
|
5919
6661
|
for (const prop of properties) {
|
|
5920
6662
|
const existing = map.get(prop.group);
|
|
@@ -5931,12 +6673,12 @@ var PropertySelector = ({
|
|
|
5931
6673
|
}
|
|
5932
6674
|
return Array.from(map.values());
|
|
5933
6675
|
}, [properties]);
|
|
5934
|
-
const globalSearchResults =
|
|
6676
|
+
const globalSearchResults = React43.useMemo(() => {
|
|
5935
6677
|
if (!search || activeGroup) return [];
|
|
5936
6678
|
const lower = search.toLowerCase();
|
|
5937
6679
|
return properties.filter((p) => p.label.toLowerCase().includes(lower));
|
|
5938
6680
|
}, [properties, search, activeGroup]);
|
|
5939
|
-
const filteredGroups =
|
|
6681
|
+
const filteredGroups = React43.useMemo(() => {
|
|
5940
6682
|
if (!search || activeGroup) return groups;
|
|
5941
6683
|
const lower = search.toLowerCase();
|
|
5942
6684
|
return groups.filter(
|
|
@@ -5945,7 +6687,7 @@ var PropertySelector = ({
|
|
|
5945
6687
|
)
|
|
5946
6688
|
);
|
|
5947
6689
|
}, [groups, properties, search, activeGroup]);
|
|
5948
|
-
const filteredProperties =
|
|
6690
|
+
const filteredProperties = React43.useMemo(() => {
|
|
5949
6691
|
if (!activeGroup) return [];
|
|
5950
6692
|
const groupProps = properties.filter((p) => p.group === activeGroup);
|
|
5951
6693
|
if (!search) return groupProps;
|
|
@@ -5954,10 +6696,10 @@ var PropertySelector = ({
|
|
|
5954
6696
|
}, [properties, activeGroup, search]);
|
|
5955
6697
|
const activeGroupInfo = groups.find((g) => g.group === activeGroup);
|
|
5956
6698
|
const showGlobalResults = search.length > 0 && !activeGroup && globalSearchResults.length > 0;
|
|
5957
|
-
return /* @__PURE__ */
|
|
5958
|
-
/* @__PURE__ */
|
|
5959
|
-
/* @__PURE__ */
|
|
5960
|
-
|
|
6699
|
+
return /* @__PURE__ */ jsxs43(PopoverPrimitive6.Root, { open, onOpenChange, children: [
|
|
6700
|
+
/* @__PURE__ */ jsx49(PopoverPrimitive6.Trigger, { asChild: true, children }),
|
|
6701
|
+
/* @__PURE__ */ jsx49(PopoverPrimitive6.Portal, { children: /* @__PURE__ */ jsxs43(
|
|
6702
|
+
PopoverPrimitive6.Content,
|
|
5961
6703
|
{
|
|
5962
6704
|
sideOffset: 4,
|
|
5963
6705
|
align: "start",
|
|
@@ -5973,17 +6715,17 @@ var PropertySelector = ({
|
|
|
5973
6715
|
children: [
|
|
5974
6716
|
activeGroup === null ? (
|
|
5975
6717
|
/* ── Level 1: Search + Categories ───────────────────────── */
|
|
5976
|
-
/* @__PURE__ */
|
|
5977
|
-
/* @__PURE__ */
|
|
5978
|
-
/* @__PURE__ */
|
|
5979
|
-
|
|
6718
|
+
/* @__PURE__ */ jsxs43("div", { className: "flex flex-col gap-xs", children: [
|
|
6719
|
+
/* @__PURE__ */ jsxs43("div", { className: "flex items-center gap-base px-md py-base border border-[var(--color-input)] rounded-md", children: [
|
|
6720
|
+
/* @__PURE__ */ jsx49(
|
|
6721
|
+
Icon28,
|
|
5980
6722
|
{
|
|
5981
6723
|
icon: faMagnifyingGlassOutline,
|
|
5982
6724
|
size: "sm",
|
|
5983
6725
|
className: "shrink-0 text-[var(--color-muted-foreground)]"
|
|
5984
6726
|
}
|
|
5985
6727
|
),
|
|
5986
|
-
/* @__PURE__ */
|
|
6728
|
+
/* @__PURE__ */ jsx49(
|
|
5987
6729
|
"input",
|
|
5988
6730
|
{
|
|
5989
6731
|
type: "text",
|
|
@@ -5997,7 +6739,7 @@ var PropertySelector = ({
|
|
|
5997
6739
|
] }),
|
|
5998
6740
|
showGlobalResults ? (
|
|
5999
6741
|
/* ── Global search results (flat property list) ─────── */
|
|
6000
|
-
/* @__PURE__ */
|
|
6742
|
+
/* @__PURE__ */ jsx49("div", { className: "flex flex-col max-h-[300px] overflow-y-auto", children: globalSearchResults.map((prop) => /* @__PURE__ */ jsxs43(
|
|
6001
6743
|
"button",
|
|
6002
6744
|
{
|
|
6003
6745
|
type: "button",
|
|
@@ -6007,24 +6749,24 @@ var PropertySelector = ({
|
|
|
6007
6749
|
},
|
|
6008
6750
|
className: "flex items-center gap-base p-base rounded-base cursor-pointer transition-colors hover:bg-[var(--color-dropdown-item-hover)]",
|
|
6009
6751
|
children: [
|
|
6010
|
-
/* @__PURE__ */
|
|
6011
|
-
|
|
6752
|
+
/* @__PURE__ */ jsx49(
|
|
6753
|
+
Icon28,
|
|
6012
6754
|
{
|
|
6013
6755
|
icon: prop.icon,
|
|
6014
6756
|
size: "sm",
|
|
6015
6757
|
className: "shrink-0 text-[var(--color-dropdown-item-icon)]"
|
|
6016
6758
|
}
|
|
6017
6759
|
),
|
|
6018
|
-
/* @__PURE__ */
|
|
6019
|
-
/* @__PURE__ */
|
|
6760
|
+
/* @__PURE__ */ jsx49("span", { className: "flex-1 text-sm font-regular leading-sm text-[var(--color-dropdown-item-text)] text-left truncate", children: prop.label }),
|
|
6761
|
+
/* @__PURE__ */ jsx49("span", { className: "text-xs font-regular leading-xs text-[var(--color-muted-foreground)]", children: prop.groupLabel })
|
|
6020
6762
|
]
|
|
6021
6763
|
},
|
|
6022
6764
|
prop.id
|
|
6023
6765
|
)) })
|
|
6024
6766
|
) : (
|
|
6025
6767
|
/* ── Group list ─────────────────────────────────────── */
|
|
6026
|
-
/* @__PURE__ */
|
|
6027
|
-
filteredGroups.map((g) => /* @__PURE__ */
|
|
6768
|
+
/* @__PURE__ */ jsxs43("div", { className: "flex flex-col", children: [
|
|
6769
|
+
filteredGroups.map((g) => /* @__PURE__ */ jsxs43(
|
|
6028
6770
|
"button",
|
|
6029
6771
|
{
|
|
6030
6772
|
type: "button",
|
|
@@ -6034,20 +6776,20 @@ var PropertySelector = ({
|
|
|
6034
6776
|
},
|
|
6035
6777
|
className: "flex items-center gap-base p-base rounded-base cursor-pointer transition-colors hover:bg-[var(--color-dropdown-item-hover)]",
|
|
6036
6778
|
children: [
|
|
6037
|
-
/* @__PURE__ */
|
|
6038
|
-
|
|
6779
|
+
/* @__PURE__ */ jsx49(
|
|
6780
|
+
Icon28,
|
|
6039
6781
|
{
|
|
6040
6782
|
icon: g.groupIcon,
|
|
6041
6783
|
size: "sm",
|
|
6042
6784
|
className: "shrink-0 text-[var(--color-dropdown-item-icon)]"
|
|
6043
6785
|
}
|
|
6044
6786
|
),
|
|
6045
|
-
/* @__PURE__ */
|
|
6046
|
-
/* @__PURE__ */
|
|
6047
|
-
/* @__PURE__ */
|
|
6048
|
-
|
|
6787
|
+
/* @__PURE__ */ jsx49("span", { className: "flex-1 text-sm font-regular leading-sm text-[var(--color-dropdown-item-text)] text-left truncate", children: g.groupLabel }),
|
|
6788
|
+
/* @__PURE__ */ jsx49("span", { className: "text-xs font-semibold leading-xs text-[var(--color-muted-foreground)]", children: g.count }),
|
|
6789
|
+
/* @__PURE__ */ jsx49(
|
|
6790
|
+
Icon28,
|
|
6049
6791
|
{
|
|
6050
|
-
icon:
|
|
6792
|
+
icon: faChevronRightOutline3,
|
|
6051
6793
|
size: "xs",
|
|
6052
6794
|
className: "shrink-0 text-[var(--color-dropdown-item-icon)]"
|
|
6053
6795
|
}
|
|
@@ -6056,14 +6798,14 @@ var PropertySelector = ({
|
|
|
6056
6798
|
},
|
|
6057
6799
|
g.group
|
|
6058
6800
|
)),
|
|
6059
|
-
filteredGroups.length === 0 && /* @__PURE__ */
|
|
6801
|
+
filteredGroups.length === 0 && /* @__PURE__ */ jsx49("span", { className: "p-base text-sm text-[var(--color-muted-foreground)]", children: "No results" })
|
|
6060
6802
|
] })
|
|
6061
6803
|
)
|
|
6062
6804
|
] })
|
|
6063
6805
|
) : (
|
|
6064
6806
|
/* ── Level 2: Properties ─────────────────────────────────── */
|
|
6065
|
-
/* @__PURE__ */
|
|
6066
|
-
/* @__PURE__ */
|
|
6807
|
+
/* @__PURE__ */ jsxs43("div", { className: "flex flex-col gap-xs", children: [
|
|
6808
|
+
/* @__PURE__ */ jsxs43(
|
|
6067
6809
|
"button",
|
|
6068
6810
|
{
|
|
6069
6811
|
type: "button",
|
|
@@ -6073,28 +6815,28 @@ var PropertySelector = ({
|
|
|
6073
6815
|
},
|
|
6074
6816
|
className: "flex items-center gap-base p-base rounded-base cursor-pointer transition-colors hover:bg-[var(--color-dropdown-item-hover)]",
|
|
6075
6817
|
children: [
|
|
6076
|
-
/* @__PURE__ */
|
|
6077
|
-
|
|
6818
|
+
/* @__PURE__ */ jsx49(
|
|
6819
|
+
Icon28,
|
|
6078
6820
|
{
|
|
6079
|
-
icon:
|
|
6821
|
+
icon: faChevronLeftOutline3,
|
|
6080
6822
|
size: "sm",
|
|
6081
6823
|
className: "shrink-0 text-[var(--color-dropdown-item-icon)]"
|
|
6082
6824
|
}
|
|
6083
6825
|
),
|
|
6084
|
-
/* @__PURE__ */
|
|
6826
|
+
/* @__PURE__ */ jsx49("span", { className: "flex-1 text-xs font-semibold leading-xs text-[var(--color-muted-foreground)] text-left truncate", children: activeGroupInfo?.groupLabel })
|
|
6085
6827
|
]
|
|
6086
6828
|
}
|
|
6087
6829
|
),
|
|
6088
|
-
/* @__PURE__ */
|
|
6089
|
-
/* @__PURE__ */
|
|
6090
|
-
|
|
6830
|
+
/* @__PURE__ */ jsxs43("div", { className: "flex items-center gap-base px-md py-base border border-[var(--color-input)] rounded-md", children: [
|
|
6831
|
+
/* @__PURE__ */ jsx49(
|
|
6832
|
+
Icon28,
|
|
6091
6833
|
{
|
|
6092
6834
|
icon: faMagnifyingGlassOutline,
|
|
6093
6835
|
size: "sm",
|
|
6094
6836
|
className: "shrink-0 text-[var(--color-muted-foreground)]"
|
|
6095
6837
|
}
|
|
6096
6838
|
),
|
|
6097
|
-
/* @__PURE__ */
|
|
6839
|
+
/* @__PURE__ */ jsx49(
|
|
6098
6840
|
"input",
|
|
6099
6841
|
{
|
|
6100
6842
|
type: "text",
|
|
@@ -6106,8 +6848,8 @@ var PropertySelector = ({
|
|
|
6106
6848
|
}
|
|
6107
6849
|
)
|
|
6108
6850
|
] }),
|
|
6109
|
-
/* @__PURE__ */
|
|
6110
|
-
filteredProperties.map((prop) => /* @__PURE__ */
|
|
6851
|
+
/* @__PURE__ */ jsxs43("div", { className: "flex flex-col max-h-[300px] overflow-y-auto", children: [
|
|
6852
|
+
filteredProperties.map((prop) => /* @__PURE__ */ jsxs43(
|
|
6111
6853
|
"button",
|
|
6112
6854
|
{
|
|
6113
6855
|
type: "button",
|
|
@@ -6117,24 +6859,24 @@ var PropertySelector = ({
|
|
|
6117
6859
|
},
|
|
6118
6860
|
className: "flex items-center gap-base p-base rounded-base cursor-pointer transition-colors hover:bg-[var(--color-dropdown-item-hover)]",
|
|
6119
6861
|
children: [
|
|
6120
|
-
/* @__PURE__ */
|
|
6121
|
-
|
|
6862
|
+
/* @__PURE__ */ jsx49(
|
|
6863
|
+
Icon28,
|
|
6122
6864
|
{
|
|
6123
6865
|
icon: prop.icon,
|
|
6124
6866
|
size: "sm",
|
|
6125
6867
|
className: "shrink-0 text-[var(--color-dropdown-item-icon)]"
|
|
6126
6868
|
}
|
|
6127
6869
|
),
|
|
6128
|
-
/* @__PURE__ */
|
|
6870
|
+
/* @__PURE__ */ jsx49("span", { className: "flex-1 text-sm font-regular leading-sm text-[var(--color-dropdown-item-text)] text-left truncate", children: prop.label })
|
|
6129
6871
|
]
|
|
6130
6872
|
},
|
|
6131
6873
|
prop.id
|
|
6132
6874
|
)),
|
|
6133
|
-
filteredProperties.length === 0 && /* @__PURE__ */
|
|
6875
|
+
filteredProperties.length === 0 && /* @__PURE__ */ jsx49("span", { className: "p-base text-sm text-[var(--color-muted-foreground)]", children: "No results" })
|
|
6134
6876
|
] })
|
|
6135
6877
|
] })
|
|
6136
6878
|
),
|
|
6137
|
-
showAdvancedFooter && /* @__PURE__ */
|
|
6879
|
+
showAdvancedFooter && /* @__PURE__ */ jsx49(
|
|
6138
6880
|
AdvancedFilterFooter,
|
|
6139
6881
|
{
|
|
6140
6882
|
onClick: handleAdvancedClick,
|
|
@@ -6149,19 +6891,19 @@ var PropertySelector = ({
|
|
|
6149
6891
|
PropertySelector.displayName = "PropertySelector";
|
|
6150
6892
|
|
|
6151
6893
|
// src/components/ui/filter/kebab-menu.tsx
|
|
6152
|
-
import * as
|
|
6153
|
-
import { Icon as
|
|
6154
|
-
import { jsx as
|
|
6894
|
+
import * as PopoverPrimitive7 from "@radix-ui/react-popover";
|
|
6895
|
+
import { Icon as Icon29, faArrowRightOutline as faArrowRightOutline2, faTrashOutline } from "@l3mpire/icons";
|
|
6896
|
+
import { jsx as jsx50, jsxs as jsxs44 } from "react/jsx-runtime";
|
|
6155
6897
|
var KebabMenu = ({
|
|
6156
6898
|
onConvertToAdvanced,
|
|
6157
6899
|
onDelete,
|
|
6158
6900
|
open,
|
|
6159
6901
|
onOpenChange,
|
|
6160
6902
|
children
|
|
6161
|
-
}) => /* @__PURE__ */
|
|
6162
|
-
/* @__PURE__ */
|
|
6163
|
-
/* @__PURE__ */
|
|
6164
|
-
|
|
6903
|
+
}) => /* @__PURE__ */ jsxs44(PopoverPrimitive7.Root, { open, onOpenChange, children: [
|
|
6904
|
+
/* @__PURE__ */ jsx50(PopoverPrimitive7.Trigger, { asChild: true, children }),
|
|
6905
|
+
/* @__PURE__ */ jsx50(PopoverPrimitive7.Portal, { children: /* @__PURE__ */ jsxs44(
|
|
6906
|
+
PopoverPrimitive7.Content,
|
|
6165
6907
|
{
|
|
6166
6908
|
sideOffset: 4,
|
|
6167
6909
|
align: "end",
|
|
@@ -6174,7 +6916,7 @@ var KebabMenu = ({
|
|
|
6174
6916
|
"min-w-[210px]"
|
|
6175
6917
|
),
|
|
6176
6918
|
children: [
|
|
6177
|
-
onConvertToAdvanced && /* @__PURE__ */
|
|
6919
|
+
onConvertToAdvanced && /* @__PURE__ */ jsxs44(
|
|
6178
6920
|
"button",
|
|
6179
6921
|
{
|
|
6180
6922
|
type: "button",
|
|
@@ -6184,20 +6926,20 @@ var KebabMenu = ({
|
|
|
6184
6926
|
},
|
|
6185
6927
|
className: "flex items-center gap-base p-base rounded-base cursor-pointer transition-colors hover:bg-[var(--color-dropdown-item-hover)]",
|
|
6186
6928
|
children: [
|
|
6187
|
-
/* @__PURE__ */
|
|
6188
|
-
|
|
6929
|
+
/* @__PURE__ */ jsx50(
|
|
6930
|
+
Icon29,
|
|
6189
6931
|
{
|
|
6190
|
-
icon:
|
|
6932
|
+
icon: faArrowRightOutline2,
|
|
6191
6933
|
size: "sm",
|
|
6192
6934
|
className: "shrink-0 text-[var(--color-dropdown-item-icon)]"
|
|
6193
6935
|
}
|
|
6194
6936
|
),
|
|
6195
|
-
/* @__PURE__ */
|
|
6937
|
+
/* @__PURE__ */ jsx50("span", { className: "text-sm font-regular leading-sm text-[var(--color-dropdown-item-text)]", children: "Convert to advanced" })
|
|
6196
6938
|
]
|
|
6197
6939
|
}
|
|
6198
6940
|
),
|
|
6199
|
-
onConvertToAdvanced && onDelete && /* @__PURE__ */
|
|
6200
|
-
onDelete && /* @__PURE__ */
|
|
6941
|
+
onConvertToAdvanced && onDelete && /* @__PURE__ */ jsx50("div", { className: "h-px mx-base my-xs bg-[var(--color-border)]" }),
|
|
6942
|
+
onDelete && /* @__PURE__ */ jsxs44(
|
|
6201
6943
|
"button",
|
|
6202
6944
|
{
|
|
6203
6945
|
type: "button",
|
|
@@ -6207,15 +6949,15 @@ var KebabMenu = ({
|
|
|
6207
6949
|
},
|
|
6208
6950
|
className: "flex items-center gap-base p-base rounded-base cursor-pointer transition-colors hover:bg-[var(--color-dropdown-item-hover)]",
|
|
6209
6951
|
children: [
|
|
6210
|
-
/* @__PURE__ */
|
|
6211
|
-
|
|
6952
|
+
/* @__PURE__ */ jsx50(
|
|
6953
|
+
Icon29,
|
|
6212
6954
|
{
|
|
6213
6955
|
icon: faTrashOutline,
|
|
6214
6956
|
size: "sm",
|
|
6215
6957
|
className: "shrink-0 text-[var(--color-destructive)]"
|
|
6216
6958
|
}
|
|
6217
6959
|
),
|
|
6218
|
-
/* @__PURE__ */
|
|
6960
|
+
/* @__PURE__ */ jsx50("span", { className: "text-sm font-regular leading-sm text-[var(--color-destructive)]", children: "Delete filter" })
|
|
6219
6961
|
]
|
|
6220
6962
|
}
|
|
6221
6963
|
)
|
|
@@ -6226,10 +6968,10 @@ var KebabMenu = ({
|
|
|
6226
6968
|
KebabMenu.displayName = "KebabMenu";
|
|
6227
6969
|
|
|
6228
6970
|
// src/components/ui/filter/filter-editor.tsx
|
|
6229
|
-
import * as
|
|
6230
|
-
import * as
|
|
6231
|
-
import { Icon as
|
|
6232
|
-
import { jsx as
|
|
6971
|
+
import * as React44 from "react";
|
|
6972
|
+
import * as PopoverPrimitive8 from "@radix-ui/react-popover";
|
|
6973
|
+
import { Icon as Icon30 } from "@l3mpire/icons";
|
|
6974
|
+
import { jsx as jsx51, jsxs as jsxs45 } from "react/jsx-runtime";
|
|
6233
6975
|
var FilterEditor = ({
|
|
6234
6976
|
propertyDef,
|
|
6235
6977
|
condition,
|
|
@@ -6240,16 +6982,16 @@ var FilterEditor = ({
|
|
|
6240
6982
|
onOpenChange,
|
|
6241
6983
|
children
|
|
6242
6984
|
}) => {
|
|
6243
|
-
const [view, setView] =
|
|
6985
|
+
const [view, setView] = React44.useState(
|
|
6244
6986
|
mode === "add" ? "value" : "operator"
|
|
6245
6987
|
);
|
|
6246
|
-
const [localOperator, setLocalOperator] =
|
|
6988
|
+
const [localOperator, setLocalOperator] = React44.useState(
|
|
6247
6989
|
condition.operator
|
|
6248
6990
|
);
|
|
6249
|
-
const [localValue, setLocalValue] =
|
|
6991
|
+
const [localValue, setLocalValue] = React44.useState(
|
|
6250
6992
|
condition.value
|
|
6251
6993
|
);
|
|
6252
|
-
|
|
6994
|
+
React44.useEffect(() => {
|
|
6253
6995
|
if (open) {
|
|
6254
6996
|
setView(mode === "add" ? "value" : "operator");
|
|
6255
6997
|
setLocalOperator(condition.operator);
|
|
@@ -6274,10 +7016,10 @@ var FilterEditor = ({
|
|
|
6274
7016
|
onOpenChange?.(false);
|
|
6275
7017
|
onClose();
|
|
6276
7018
|
};
|
|
6277
|
-
return /* @__PURE__ */
|
|
6278
|
-
/* @__PURE__ */
|
|
6279
|
-
/* @__PURE__ */
|
|
6280
|
-
|
|
7019
|
+
return /* @__PURE__ */ jsxs45(PopoverPrimitive8.Root, { open, onOpenChange, children: [
|
|
7020
|
+
/* @__PURE__ */ jsx51(PopoverPrimitive8.Trigger, { asChild: true, children }),
|
|
7021
|
+
/* @__PURE__ */ jsx51(PopoverPrimitive8.Portal, { children: /* @__PURE__ */ jsxs45(
|
|
7022
|
+
PopoverPrimitive8.Content,
|
|
6281
7023
|
{
|
|
6282
7024
|
sideOffset: 4,
|
|
6283
7025
|
align: "start",
|
|
@@ -6290,17 +7032,17 @@ var FilterEditor = ({
|
|
|
6290
7032
|
"min-w-[240px]"
|
|
6291
7033
|
),
|
|
6292
7034
|
children: [
|
|
6293
|
-
/* @__PURE__ */
|
|
6294
|
-
/* @__PURE__ */
|
|
6295
|
-
|
|
7035
|
+
/* @__PURE__ */ jsxs45("div", { className: "flex items-center gap-base px-base pt-base pb-xs border-b border-[var(--color-border)]", children: [
|
|
7036
|
+
/* @__PURE__ */ jsx51(
|
|
7037
|
+
Icon30,
|
|
6296
7038
|
{
|
|
6297
7039
|
icon: propertyDef.icon,
|
|
6298
7040
|
size: "sm",
|
|
6299
7041
|
className: "shrink-0 text-[var(--color-dropdown-item-icon)]"
|
|
6300
7042
|
}
|
|
6301
7043
|
),
|
|
6302
|
-
/* @__PURE__ */
|
|
6303
|
-
localOperator && view === "value" && /* @__PURE__ */
|
|
7044
|
+
/* @__PURE__ */ jsx51("span", { className: "text-sm font-semibold leading-sm text-[var(--color-foreground)]", children: propertyDef.label }),
|
|
7045
|
+
localOperator && view === "value" && /* @__PURE__ */ jsxs45(
|
|
6304
7046
|
"button",
|
|
6305
7047
|
{
|
|
6306
7048
|
type: "button",
|
|
@@ -6313,14 +7055,14 @@ var FilterEditor = ({
|
|
|
6313
7055
|
}
|
|
6314
7056
|
)
|
|
6315
7057
|
] }),
|
|
6316
|
-
view === "operator" ? /* @__PURE__ */
|
|
7058
|
+
view === "operator" ? /* @__PURE__ */ jsx51("div", { className: "p-xs", children: /* @__PURE__ */ jsx51(
|
|
6317
7059
|
OperatorList,
|
|
6318
7060
|
{
|
|
6319
7061
|
dataType: propertyDef.type,
|
|
6320
7062
|
activeOperator: localOperator,
|
|
6321
7063
|
onSelect: handleOperatorSelect
|
|
6322
7064
|
}
|
|
6323
|
-
) }) : localOperator && /* @__PURE__ */
|
|
7065
|
+
) }) : localOperator && /* @__PURE__ */ jsx51(
|
|
6324
7066
|
ValueInput,
|
|
6325
7067
|
{
|
|
6326
7068
|
dataType: propertyDef.type,
|
|
@@ -6328,7 +7070,8 @@ var FilterEditor = ({
|
|
|
6328
7070
|
value: localValue,
|
|
6329
7071
|
onChange: setLocalValue,
|
|
6330
7072
|
onSubmit: handleSubmit,
|
|
6331
|
-
options: propertyDef.options
|
|
7073
|
+
options: propertyDef.options,
|
|
7074
|
+
dynamicOptions: propertyDef.dynamicOptions
|
|
6332
7075
|
}
|
|
6333
7076
|
)
|
|
6334
7077
|
]
|
|
@@ -6339,34 +7082,9 @@ var FilterEditor = ({
|
|
|
6339
7082
|
FilterEditor.displayName = "FilterEditor";
|
|
6340
7083
|
|
|
6341
7084
|
// src/components/ui/filter/interactive-filter-chip.tsx
|
|
6342
|
-
import * as
|
|
6343
|
-
import * as
|
|
6344
|
-
import { jsx as
|
|
6345
|
-
function formatFilterValue(value) {
|
|
6346
|
-
if (value == null) return void 0;
|
|
6347
|
-
if (typeof value === "boolean") return value ? "Yes" : "No";
|
|
6348
|
-
if (value instanceof Date) {
|
|
6349
|
-
return value.toLocaleDateString("en-US", {
|
|
6350
|
-
month: "short",
|
|
6351
|
-
day: "numeric",
|
|
6352
|
-
year: "numeric"
|
|
6353
|
-
});
|
|
6354
|
-
}
|
|
6355
|
-
if (Array.isArray(value)) {
|
|
6356
|
-
if (value.length === 0) return void 0;
|
|
6357
|
-
if (value.length === 2 && typeof value[0] === "number") {
|
|
6358
|
-
return `${value[0]} \u2013 ${value[1]}`;
|
|
6359
|
-
}
|
|
6360
|
-
return value[0];
|
|
6361
|
-
}
|
|
6362
|
-
return String(value);
|
|
6363
|
-
}
|
|
6364
|
-
function getBadgeCount(value) {
|
|
6365
|
-
if (Array.isArray(value) && value.length > 1 && typeof value[0] === "string") {
|
|
6366
|
-
return value.length;
|
|
6367
|
-
}
|
|
6368
|
-
return void 0;
|
|
6369
|
-
}
|
|
7085
|
+
import * as React45 from "react";
|
|
7086
|
+
import * as PopoverPrimitive9 from "@radix-ui/react-popover";
|
|
7087
|
+
import { jsx as jsx52, jsxs as jsxs46 } from "react/jsx-runtime";
|
|
6370
7088
|
var SegmentPopover = ({
|
|
6371
7089
|
open,
|
|
6372
7090
|
onOpenChange,
|
|
@@ -6374,10 +7092,10 @@ var SegmentPopover = ({
|
|
|
6374
7092
|
children,
|
|
6375
7093
|
align = "start",
|
|
6376
7094
|
minWidth = "240px"
|
|
6377
|
-
}) => /* @__PURE__ */
|
|
6378
|
-
/* @__PURE__ */
|
|
6379
|
-
/* @__PURE__ */
|
|
6380
|
-
|
|
7095
|
+
}) => /* @__PURE__ */ jsxs46(PopoverPrimitive9.Root, { open, onOpenChange, children: [
|
|
7096
|
+
/* @__PURE__ */ jsx52(PopoverPrimitive9.Trigger, { asChild: true, children: trigger }),
|
|
7097
|
+
/* @__PURE__ */ jsx52(PopoverPrimitive9.Portal, { children: /* @__PURE__ */ jsx52(
|
|
7098
|
+
PopoverPrimitive9.Content,
|
|
6381
7099
|
{
|
|
6382
7100
|
sideOffset: 4,
|
|
6383
7101
|
align,
|
|
@@ -6405,19 +7123,19 @@ var InteractiveFilterChip = ({
|
|
|
6405
7123
|
onConvertToAdvanced,
|
|
6406
7124
|
className
|
|
6407
7125
|
}) => {
|
|
6408
|
-
const [operatorOpen, setOperatorOpen] =
|
|
6409
|
-
const [valueOpen, setValueOpen] =
|
|
6410
|
-
const [propertyOpen, setPropertyOpen] =
|
|
6411
|
-
const [kebabOpen, setKebabOpen] =
|
|
6412
|
-
const [pendingValueOpen, setPendingValueOpen] =
|
|
6413
|
-
const autoOpenHandled =
|
|
6414
|
-
|
|
7126
|
+
const [operatorOpen, setOperatorOpen] = React45.useState(false);
|
|
7127
|
+
const [valueOpen, setValueOpen] = React45.useState(false);
|
|
7128
|
+
const [propertyOpen, setPropertyOpen] = React45.useState(false);
|
|
7129
|
+
const [kebabOpen, setKebabOpen] = React45.useState(false);
|
|
7130
|
+
const [pendingValueOpen, setPendingValueOpen] = React45.useState(false);
|
|
7131
|
+
const autoOpenHandled = React45.useRef(false);
|
|
7132
|
+
React45.useEffect(() => {
|
|
6415
7133
|
if (autoOpen && !autoOpenHandled.current && condition.operator && !isNoValueOperator(condition.operator)) {
|
|
6416
7134
|
autoOpenHandled.current = true;
|
|
6417
7135
|
setValueOpen(true);
|
|
6418
7136
|
}
|
|
6419
7137
|
}, [autoOpen, condition.operator]);
|
|
6420
|
-
|
|
7138
|
+
React45.useEffect(() => {
|
|
6421
7139
|
if (!operatorOpen && pendingValueOpen) {
|
|
6422
7140
|
setPendingValueOpen(false);
|
|
6423
7141
|
setValueOpen(true);
|
|
@@ -6446,7 +7164,7 @@ var InteractiveFilterChip = ({
|
|
|
6446
7164
|
const displayValue = formatFilterValue(condition.value);
|
|
6447
7165
|
const hasValue = hasOperator && displayValue != null;
|
|
6448
7166
|
const badgeCount = getBadgeCount(condition.value);
|
|
6449
|
-
return /* @__PURE__ */
|
|
7167
|
+
return /* @__PURE__ */ jsxs46(
|
|
6450
7168
|
"div",
|
|
6451
7169
|
{
|
|
6452
7170
|
className: cn(
|
|
@@ -6455,7 +7173,7 @@ var InteractiveFilterChip = ({
|
|
|
6455
7173
|
className
|
|
6456
7174
|
),
|
|
6457
7175
|
children: [
|
|
6458
|
-
properties ? /* @__PURE__ */
|
|
7176
|
+
properties ? /* @__PURE__ */ jsx52(
|
|
6459
7177
|
PropertySelector,
|
|
6460
7178
|
{
|
|
6461
7179
|
properties,
|
|
@@ -6465,7 +7183,7 @@ var InteractiveFilterChip = ({
|
|
|
6465
7183
|
},
|
|
6466
7184
|
open: propertyOpen,
|
|
6467
7185
|
onOpenChange: setPropertyOpen,
|
|
6468
|
-
children: /* @__PURE__ */
|
|
7186
|
+
children: /* @__PURE__ */ jsx52("div", { children: /* @__PURE__ */ jsx52(
|
|
6469
7187
|
FilterChipSegment,
|
|
6470
7188
|
{
|
|
6471
7189
|
segmentType: "property",
|
|
@@ -6476,7 +7194,7 @@ var InteractiveFilterChip = ({
|
|
|
6476
7194
|
}
|
|
6477
7195
|
) })
|
|
6478
7196
|
}
|
|
6479
|
-
) : /* @__PURE__ */
|
|
7197
|
+
) : /* @__PURE__ */ jsx52(
|
|
6480
7198
|
FilterChipSegment,
|
|
6481
7199
|
{
|
|
6482
7200
|
segmentType: "property",
|
|
@@ -6485,13 +7203,13 @@ var InteractiveFilterChip = ({
|
|
|
6485
7203
|
label: propertyDef.label
|
|
6486
7204
|
}
|
|
6487
7205
|
),
|
|
6488
|
-
/* @__PURE__ */
|
|
7206
|
+
/* @__PURE__ */ jsx52(
|
|
6489
7207
|
SegmentPopover,
|
|
6490
7208
|
{
|
|
6491
7209
|
open: operatorOpen,
|
|
6492
7210
|
onOpenChange: setOperatorOpen,
|
|
6493
7211
|
minWidth: "180px",
|
|
6494
|
-
trigger: /* @__PURE__ */
|
|
7212
|
+
trigger: /* @__PURE__ */ jsx52("div", { children: /* @__PURE__ */ jsx52(
|
|
6495
7213
|
FilterChipSegment,
|
|
6496
7214
|
{
|
|
6497
7215
|
segmentType: hasOperator ? "operator" : "placeholder",
|
|
@@ -6500,7 +7218,7 @@ var InteractiveFilterChip = ({
|
|
|
6500
7218
|
onClick: () => setOperatorOpen(true)
|
|
6501
7219
|
}
|
|
6502
7220
|
) }),
|
|
6503
|
-
children: /* @__PURE__ */
|
|
7221
|
+
children: /* @__PURE__ */ jsx52("div", { className: "p-xs", children: /* @__PURE__ */ jsx52(
|
|
6504
7222
|
OperatorList,
|
|
6505
7223
|
{
|
|
6506
7224
|
dataType: propertyDef.type,
|
|
@@ -6510,36 +7228,41 @@ var InteractiveFilterChip = ({
|
|
|
6510
7228
|
) })
|
|
6511
7229
|
}
|
|
6512
7230
|
),
|
|
6513
|
-
hasOperator && condition.operator && !isNoValueOperator(condition.operator) &&
|
|
6514
|
-
|
|
6515
|
-
|
|
6516
|
-
|
|
6517
|
-
|
|
6518
|
-
|
|
6519
|
-
|
|
6520
|
-
|
|
6521
|
-
|
|
6522
|
-
|
|
6523
|
-
|
|
6524
|
-
|
|
6525
|
-
|
|
6526
|
-
|
|
6527
|
-
|
|
6528
|
-
|
|
6529
|
-
|
|
6530
|
-
|
|
6531
|
-
|
|
6532
|
-
|
|
6533
|
-
|
|
6534
|
-
|
|
6535
|
-
|
|
6536
|
-
|
|
6537
|
-
|
|
6538
|
-
|
|
6539
|
-
|
|
6540
|
-
|
|
6541
|
-
|
|
6542
|
-
|
|
7231
|
+
hasOperator && condition.operator && !isNoValueOperator(condition.operator) && (() => {
|
|
7232
|
+
const inputType = getValueInputType(propertyDef.type, condition.operator);
|
|
7233
|
+
const dateWide = inputType === "DatePicker" || inputType === "DateRange";
|
|
7234
|
+
return /* @__PURE__ */ jsx52(
|
|
7235
|
+
SegmentPopover,
|
|
7236
|
+
{
|
|
7237
|
+
open: valueOpen,
|
|
7238
|
+
onOpenChange: setValueOpen,
|
|
7239
|
+
minWidth: dateWide ? "auto" : "240px",
|
|
7240
|
+
trigger: /* @__PURE__ */ jsx52("div", { children: /* @__PURE__ */ jsx52(
|
|
7241
|
+
FilterChipSegment,
|
|
7242
|
+
{
|
|
7243
|
+
segmentType: hasValue ? "value" : "placeholder",
|
|
7244
|
+
hasBorder: true,
|
|
7245
|
+
label: hasValue ? displayValue : "Enter value",
|
|
7246
|
+
badgeCount,
|
|
7247
|
+
onClick: () => setValueOpen(true)
|
|
7248
|
+
}
|
|
7249
|
+
) }),
|
|
7250
|
+
children: /* @__PURE__ */ jsx52(
|
|
7251
|
+
ValueInput,
|
|
7252
|
+
{
|
|
7253
|
+
dataType: propertyDef.type,
|
|
7254
|
+
operator: condition.operator,
|
|
7255
|
+
value: condition.value,
|
|
7256
|
+
onChange: handleValueChange,
|
|
7257
|
+
onSubmit: handleValueSubmit,
|
|
7258
|
+
options: propertyDef.options,
|
|
7259
|
+
dynamicOptions: propertyDef.dynamicOptions
|
|
7260
|
+
}
|
|
7261
|
+
)
|
|
7262
|
+
}
|
|
7263
|
+
);
|
|
7264
|
+
})(),
|
|
7265
|
+
hasOperator && condition.operator && isNoValueOperator(condition.operator) && /* @__PURE__ */ jsx52(
|
|
6543
7266
|
FilterChipSegment,
|
|
6544
7267
|
{
|
|
6545
7268
|
segmentType: "value",
|
|
@@ -6547,14 +7270,14 @@ var InteractiveFilterChip = ({
|
|
|
6547
7270
|
label: condition.operator
|
|
6548
7271
|
}
|
|
6549
7272
|
),
|
|
6550
|
-
hasOperator && /* @__PURE__ */
|
|
7273
|
+
hasOperator && /* @__PURE__ */ jsx52(
|
|
6551
7274
|
KebabMenu,
|
|
6552
7275
|
{
|
|
6553
7276
|
open: kebabOpen,
|
|
6554
7277
|
onOpenChange: setKebabOpen,
|
|
6555
7278
|
onConvertToAdvanced,
|
|
6556
7279
|
onDelete,
|
|
6557
|
-
children: /* @__PURE__ */
|
|
7280
|
+
children: /* @__PURE__ */ jsx52("div", { children: /* @__PURE__ */ jsx52(
|
|
6558
7281
|
FilterChipSegment,
|
|
6559
7282
|
{
|
|
6560
7283
|
segmentType: "button",
|
|
@@ -6573,13 +7296,13 @@ var InteractiveFilterChip = ({
|
|
|
6573
7296
|
InteractiveFilterChip.displayName = "InteractiveFilterChip";
|
|
6574
7297
|
|
|
6575
7298
|
// src/components/ui/filter/filter-system.tsx
|
|
6576
|
-
import * as
|
|
6577
|
-
import { Icon as
|
|
7299
|
+
import * as React53 from "react";
|
|
7300
|
+
import { Icon as Icon37, faXmarkOutline as faXmarkOutline5, faPlusOutline as faPlusOutline5 } from "@l3mpire/icons";
|
|
6578
7301
|
|
|
6579
7302
|
// src/components/ui/filter/advanced-chip.tsx
|
|
6580
|
-
import * as
|
|
6581
|
-
import { Icon as
|
|
6582
|
-
import { jsx as
|
|
7303
|
+
import * as React46 from "react";
|
|
7304
|
+
import { Icon as Icon31, faXmarkOutline as faXmarkOutline2 } from "@l3mpire/icons";
|
|
7305
|
+
import { jsx as jsx53, jsxs as jsxs47 } from "react/jsx-runtime";
|
|
6583
7306
|
var btnBase = [
|
|
6584
7307
|
"flex items-center justify-center",
|
|
6585
7308
|
"min-h-[32px] max-h-[32px]",
|
|
@@ -6588,9 +7311,9 @@ var btnBase = [
|
|
|
6588
7311
|
"cursor-pointer transition-colors",
|
|
6589
7312
|
"hover:from-[var(--color-btn-outlined-neutral-bg-hover)] hover:to-[var(--color-btn-outlined-neutral-bg-gradient-to-hover)]"
|
|
6590
7313
|
];
|
|
6591
|
-
var AdvancedChip =
|
|
6592
|
-
({ className, count, onClear, onClick, ...props }, ref) => /* @__PURE__ */
|
|
6593
|
-
/* @__PURE__ */
|
|
7314
|
+
var AdvancedChip = React46.forwardRef(
|
|
7315
|
+
({ className, count, onClear, onClick, ...props }, ref) => /* @__PURE__ */ jsxs47("div", { className: cn("inline-flex items-center", className), children: [
|
|
7316
|
+
/* @__PURE__ */ jsxs47(
|
|
6594
7317
|
"button",
|
|
6595
7318
|
{
|
|
6596
7319
|
ref,
|
|
@@ -6603,12 +7326,12 @@ var AdvancedChip = React44.forwardRef(
|
|
|
6603
7326
|
),
|
|
6604
7327
|
...props,
|
|
6605
7328
|
children: [
|
|
6606
|
-
/* @__PURE__ */
|
|
6607
|
-
count > 0 && /* @__PURE__ */
|
|
7329
|
+
/* @__PURE__ */ jsx53("span", { className: "text-sm font-semibold leading-sm whitespace-nowrap text-[var(--color-foreground)]", children: "Advanced filters" }),
|
|
7330
|
+
count > 0 && /* @__PURE__ */ jsx53("span", { className: "flex items-center p-2xs rounded-xs bg-filter-chip-badge-bg", children: /* @__PURE__ */ jsx53("span", { className: "text-[10px] font-semibold leading-2xs text-filter-chip-badge-text", children: count }) })
|
|
6608
7331
|
]
|
|
6609
7332
|
}
|
|
6610
7333
|
),
|
|
6611
|
-
onClear && /* @__PURE__ */
|
|
7334
|
+
onClear && /* @__PURE__ */ jsx53(
|
|
6612
7335
|
"button",
|
|
6613
7336
|
{
|
|
6614
7337
|
type: "button",
|
|
@@ -6622,7 +7345,7 @@ var AdvancedChip = React44.forwardRef(
|
|
|
6622
7345
|
"rounded-r-md -ml-px"
|
|
6623
7346
|
),
|
|
6624
7347
|
"aria-label": "Clear all advanced filters",
|
|
6625
|
-
children: /* @__PURE__ */
|
|
7348
|
+
children: /* @__PURE__ */ jsx53(Icon31, { icon: faXmarkOutline2, size: "sm", className: "text-[var(--color-foreground)]" })
|
|
6626
7349
|
}
|
|
6627
7350
|
)
|
|
6628
7351
|
] })
|
|
@@ -6630,15 +7353,128 @@ var AdvancedChip = React44.forwardRef(
|
|
|
6630
7353
|
AdvancedChip.displayName = "AdvancedChip";
|
|
6631
7354
|
|
|
6632
7355
|
// src/components/ui/filter/advanced-popover.tsx
|
|
6633
|
-
import * as
|
|
7356
|
+
import * as React50 from "react";
|
|
7357
|
+
import * as PopoverPrimitive12 from "@radix-ui/react-popover";
|
|
7358
|
+
import { Icon as Icon35, faPlusOutline as faPlusOutline3, faChevronDownOutline as faChevronDownOutline3, faXmarkOutline as faXmarkOutline3 } from "@l3mpire/icons";
|
|
7359
|
+
|
|
7360
|
+
// src/components/ui/filter/advanced-row.tsx
|
|
7361
|
+
import * as React48 from "react";
|
|
7362
|
+
import * as PopoverPrimitive11 from "@radix-ui/react-popover";
|
|
7363
|
+
import { Icon as Icon33, faRefreshOutline, faChevronDownOutline as faChevronDownOutline2 } from "@l3mpire/icons";
|
|
7364
|
+
|
|
7365
|
+
// src/components/ui/filter/filter-node-actions.tsx
|
|
7366
|
+
import * as React47 from "react";
|
|
6634
7367
|
import * as PopoverPrimitive10 from "@radix-ui/react-popover";
|
|
6635
|
-
import {
|
|
7368
|
+
import {
|
|
7369
|
+
Icon as Icon32,
|
|
7370
|
+
faEllipsisOutline,
|
|
7371
|
+
faCopyOutline,
|
|
7372
|
+
faTrashOutline as faTrashOutline2,
|
|
7373
|
+
faFolderOutline,
|
|
7374
|
+
faFilterOutline as faFilterOutline3
|
|
7375
|
+
} from "@l3mpire/icons";
|
|
7376
|
+
import { jsx as jsx54, jsxs as jsxs48 } from "react/jsx-runtime";
|
|
7377
|
+
var FilterNodeActions = ({
|
|
7378
|
+
nodeType,
|
|
7379
|
+
onDuplicate,
|
|
7380
|
+
onConvert,
|
|
7381
|
+
onDelete
|
|
7382
|
+
}) => {
|
|
7383
|
+
const [open, setOpen] = React47.useState(false);
|
|
7384
|
+
const items = [
|
|
7385
|
+
{
|
|
7386
|
+
label: "Duplicate",
|
|
7387
|
+
icon: faCopyOutline,
|
|
7388
|
+
action: onDuplicate
|
|
7389
|
+
},
|
|
7390
|
+
{
|
|
7391
|
+
label: nodeType === "condition" ? "Turn into group" : "Turn into filter",
|
|
7392
|
+
icon: nodeType === "condition" ? faFolderOutline : faFilterOutline3,
|
|
7393
|
+
action: onConvert
|
|
7394
|
+
},
|
|
7395
|
+
{
|
|
7396
|
+
label: "Delete",
|
|
7397
|
+
icon: faTrashOutline2,
|
|
7398
|
+
action: onDelete,
|
|
7399
|
+
destructive: true
|
|
7400
|
+
}
|
|
7401
|
+
];
|
|
7402
|
+
return /* @__PURE__ */ jsxs48(PopoverPrimitive10.Root, { open, onOpenChange: setOpen, children: [
|
|
7403
|
+
/* @__PURE__ */ jsx54(PopoverPrimitive10.Trigger, { asChild: true, children: /* @__PURE__ */ jsx54(
|
|
7404
|
+
"button",
|
|
7405
|
+
{
|
|
7406
|
+
type: "button",
|
|
7407
|
+
className: "shrink-0 flex items-center justify-center p-sm rounded-md cursor-pointer transition-colors hover:bg-[var(--color-accent)]",
|
|
7408
|
+
"aria-label": "More actions",
|
|
7409
|
+
children: /* @__PURE__ */ jsx54(
|
|
7410
|
+
Icon32,
|
|
7411
|
+
{
|
|
7412
|
+
icon: faEllipsisOutline,
|
|
7413
|
+
size: "sm",
|
|
7414
|
+
className: "text-[var(--color-foreground)]"
|
|
7415
|
+
}
|
|
7416
|
+
)
|
|
7417
|
+
}
|
|
7418
|
+
) }),
|
|
7419
|
+
/* @__PURE__ */ jsx54(PopoverPrimitive10.Portal, { children: /* @__PURE__ */ jsx54(
|
|
7420
|
+
PopoverPrimitive10.Content,
|
|
7421
|
+
{
|
|
7422
|
+
sideOffset: 4,
|
|
7423
|
+
align: "end",
|
|
7424
|
+
className: cn(
|
|
7425
|
+
"z-50 flex flex-col p-xs overflow-clip",
|
|
7426
|
+
"bg-[var(--color-dropdown-bg)] border border-[var(--color-dropdown-border)] rounded-md shadow-lg",
|
|
7427
|
+
"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
|
|
7428
|
+
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
|
|
7429
|
+
"min-w-[180px]"
|
|
7430
|
+
),
|
|
7431
|
+
children: items.map((item) => /* @__PURE__ */ jsxs48(
|
|
7432
|
+
"button",
|
|
7433
|
+
{
|
|
7434
|
+
type: "button",
|
|
7435
|
+
onClick: () => {
|
|
7436
|
+
item.action();
|
|
7437
|
+
setOpen(false);
|
|
7438
|
+
},
|
|
7439
|
+
className: cn(
|
|
7440
|
+
"flex items-center gap-base p-base rounded-base cursor-pointer transition-colors text-left",
|
|
7441
|
+
"hover:bg-[var(--color-dropdown-item-hover)]",
|
|
7442
|
+
item.destructive && "text-[var(--color-destructive,#ef4444)]"
|
|
7443
|
+
),
|
|
7444
|
+
children: [
|
|
7445
|
+
/* @__PURE__ */ jsx54(
|
|
7446
|
+
Icon32,
|
|
7447
|
+
{
|
|
7448
|
+
icon: item.icon,
|
|
7449
|
+
size: "sm",
|
|
7450
|
+
className: cn(
|
|
7451
|
+
"shrink-0",
|
|
7452
|
+
item.destructive ? "text-[var(--color-destructive,#ef4444)]" : "text-[var(--color-dropdown-item-icon)]"
|
|
7453
|
+
)
|
|
7454
|
+
}
|
|
7455
|
+
),
|
|
7456
|
+
/* @__PURE__ */ jsx54(
|
|
7457
|
+
"span",
|
|
7458
|
+
{
|
|
7459
|
+
className: cn(
|
|
7460
|
+
"text-sm font-regular leading-sm",
|
|
7461
|
+
item.destructive ? "text-[var(--color-destructive,#ef4444)]" : "text-[var(--color-dropdown-item-text)]"
|
|
7462
|
+
),
|
|
7463
|
+
children: item.label
|
|
7464
|
+
}
|
|
7465
|
+
)
|
|
7466
|
+
]
|
|
7467
|
+
},
|
|
7468
|
+
item.label
|
|
7469
|
+
))
|
|
7470
|
+
}
|
|
7471
|
+
) })
|
|
7472
|
+
] });
|
|
7473
|
+
};
|
|
7474
|
+
FilterNodeActions.displayName = "FilterNodeActions";
|
|
6636
7475
|
|
|
6637
7476
|
// src/components/ui/filter/advanced-row.tsx
|
|
6638
|
-
import
|
|
6639
|
-
import * as PopoverPrimitive9 from "@radix-ui/react-popover";
|
|
6640
|
-
import { Icon as Icon30, faXmarkOutline as faXmarkOutline3, faRefreshOutline, faChevronDownOutline as faChevronDownOutline2 } from "@l3mpire/icons";
|
|
6641
|
-
import { jsx as jsx53, jsxs as jsxs47 } from "react/jsx-runtime";
|
|
7477
|
+
import { jsx as jsx55, jsxs as jsxs49 } from "react/jsx-runtime";
|
|
6642
7478
|
var selectBtnStyle = [
|
|
6643
7479
|
"flex items-center gap-base",
|
|
6644
7480
|
"px-base py-sm",
|
|
@@ -6655,10 +7491,13 @@ var AdvancedRow = ({
|
|
|
6655
7491
|
properties,
|
|
6656
7492
|
onUpdate,
|
|
6657
7493
|
onPropertyChange,
|
|
6658
|
-
onDelete
|
|
7494
|
+
onDelete,
|
|
7495
|
+
onDuplicate,
|
|
7496
|
+
onTurnIntoGroup
|
|
6659
7497
|
}) => {
|
|
6660
|
-
const [operatorOpen, setOperatorOpen] =
|
|
6661
|
-
const [propertyOpen, setPropertyOpen] =
|
|
7498
|
+
const [operatorOpen, setOperatorOpen] = React48.useState(false);
|
|
7499
|
+
const [propertyOpen, setPropertyOpen] = React48.useState(false);
|
|
7500
|
+
const [valueOpen, setValueOpen] = React48.useState(false);
|
|
6662
7501
|
const handleOperatorSelect = (op) => {
|
|
6663
7502
|
if (isNoValueOperator(op)) {
|
|
6664
7503
|
onUpdate({ ...condition, operator: op, value: null });
|
|
@@ -6671,16 +7510,18 @@ var AdvancedRow = ({
|
|
|
6671
7510
|
const handleValueChange = (val) => {
|
|
6672
7511
|
onUpdate({ ...condition, value: val });
|
|
6673
7512
|
};
|
|
6674
|
-
const displayValue =
|
|
6675
|
-
|
|
6676
|
-
|
|
7513
|
+
const displayValue = formatFilterValue(condition.value);
|
|
7514
|
+
const badgeCount = getBadgeCount(condition.value);
|
|
7515
|
+
const hasValue = displayValue != null;
|
|
7516
|
+
return /* @__PURE__ */ jsxs49("div", { className: "flex items-center gap-base w-full min-w-0", children: [
|
|
7517
|
+
connector === "Where" ? /* @__PURE__ */ jsx55("div", { className: "shrink-0 w-[64px] flex items-center justify-end", children: /* @__PURE__ */ jsx55("span", { className: "text-xs font-semibold leading-xs text-[var(--color-muted-foreground)]", children: "Where" }) }) : /* @__PURE__ */ jsxs49(
|
|
6677
7518
|
"button",
|
|
6678
7519
|
{
|
|
6679
7520
|
type: "button",
|
|
6680
7521
|
onClick: onConnectorToggle,
|
|
6681
7522
|
className: cn(
|
|
6682
7523
|
"shrink-0 flex items-center justify-center gap-xs",
|
|
6683
|
-
"min-w-[64px] min-h-[
|
|
7524
|
+
"min-w-[64px] min-h-[32px] max-h-[32px] px-base py-sm",
|
|
6684
7525
|
"bg-gradient-to-t from-[var(--color-btn-outlined-neutral-bg-default)] from-[10%] to-[var(--color-btn-outlined-neutral-bg-gradient-to-default)]",
|
|
6685
7526
|
"border border-[var(--color-btn-outlined-neutral-border-default)] rounded-base shadow-sm",
|
|
6686
7527
|
"cursor-pointer transition-colors text-xs font-semibold leading-xs text-[var(--color-foreground)]",
|
|
@@ -6688,22 +7529,18 @@ var AdvancedRow = ({
|
|
|
6688
7529
|
),
|
|
6689
7530
|
children: [
|
|
6690
7531
|
connector,
|
|
6691
|
-
/* @__PURE__ */
|
|
7532
|
+
/* @__PURE__ */ jsx55(Icon33, { icon: faRefreshOutline, size: "xs", className: "text-[var(--color-foreground)]" })
|
|
6692
7533
|
]
|
|
6693
7534
|
}
|
|
6694
7535
|
),
|
|
6695
|
-
/* @__PURE__ */
|
|
6696
|
-
/* @__PURE__ */
|
|
6697
|
-
/* @__PURE__ */
|
|
6698
|
-
/* @__PURE__ */
|
|
6699
|
-
|
|
6700
|
-
" > ",
|
|
6701
|
-
propertyDef.label
|
|
6702
|
-
] }),
|
|
6703
|
-
/* @__PURE__ */ jsx53(Icon30, { icon: faChevronDownOutline2, size: "xs", className: "shrink-0 text-[var(--color-foreground)]" })
|
|
7536
|
+
/* @__PURE__ */ jsxs49(PopoverPrimitive11.Root, { open: propertyOpen, onOpenChange: setPropertyOpen, children: [
|
|
7537
|
+
/* @__PURE__ */ jsx55(PopoverPrimitive11.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs49("button", { type: "button", className: cn(selectBtnStyle, "min-w-0"), children: [
|
|
7538
|
+
/* @__PURE__ */ jsx55(Icon33, { icon: propertyDef.icon, size: "sm", className: "shrink-0 text-[var(--color-muted-foreground)]" }),
|
|
7539
|
+
/* @__PURE__ */ jsx55("span", { className: "text-sm font-regular leading-sm text-[var(--color-foreground)] whitespace-nowrap truncate", children: propertyDef.label }),
|
|
7540
|
+
/* @__PURE__ */ jsx55(Icon33, { icon: faChevronDownOutline2, size: "xs", className: "shrink-0 text-[var(--color-foreground)]" })
|
|
6704
7541
|
] }) }),
|
|
6705
|
-
/* @__PURE__ */
|
|
6706
|
-
|
|
7542
|
+
/* @__PURE__ */ jsx55(PopoverPrimitive11.Portal, { children: /* @__PURE__ */ jsx55(
|
|
7543
|
+
PopoverPrimitive11.Content,
|
|
6707
7544
|
{
|
|
6708
7545
|
sideOffset: 4,
|
|
6709
7546
|
align: "start",
|
|
@@ -6714,7 +7551,7 @@ var AdvancedRow = ({
|
|
|
6714
7551
|
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0",
|
|
6715
7552
|
"min-w-[200px]"
|
|
6716
7553
|
),
|
|
6717
|
-
children: properties.map((p) => /* @__PURE__ */
|
|
7554
|
+
children: properties.map((p) => /* @__PURE__ */ jsxs49(
|
|
6718
7555
|
"button",
|
|
6719
7556
|
{
|
|
6720
7557
|
type: "button",
|
|
@@ -6728,8 +7565,8 @@ var AdvancedRow = ({
|
|
|
6728
7565
|
p.id === condition.propertyId && "bg-[var(--color-dropdown-item-hover)]"
|
|
6729
7566
|
),
|
|
6730
7567
|
children: [
|
|
6731
|
-
/* @__PURE__ */
|
|
6732
|
-
/* @__PURE__ */
|
|
7568
|
+
/* @__PURE__ */ jsx55(Icon33, { icon: p.icon, size: "sm", className: "shrink-0 text-[var(--color-dropdown-item-icon)]" }),
|
|
7569
|
+
/* @__PURE__ */ jsx55("span", { className: "text-sm font-regular leading-sm text-[var(--color-dropdown-item-text)] truncate", children: p.label })
|
|
6733
7570
|
]
|
|
6734
7571
|
},
|
|
6735
7572
|
p.id
|
|
@@ -6737,1177 +7574,1021 @@ var AdvancedRow = ({
|
|
|
6737
7574
|
}
|
|
6738
7575
|
) })
|
|
6739
7576
|
] }),
|
|
6740
|
-
/* @__PURE__ */
|
|
6741
|
-
/* @__PURE__ */
|
|
6742
|
-
/* @__PURE__ */
|
|
6743
|
-
/* @__PURE__ */
|
|
7577
|
+
/* @__PURE__ */ jsxs49(PopoverPrimitive11.Root, { open: operatorOpen, onOpenChange: setOperatorOpen, children: [
|
|
7578
|
+
/* @__PURE__ */ jsx55(PopoverPrimitive11.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs49("button", { type: "button", className: cn(selectBtnStyle, "min-w-0"), children: [
|
|
7579
|
+
/* @__PURE__ */ jsx55("span", { className: "text-sm font-regular leading-sm text-[var(--color-foreground)] whitespace-nowrap truncate text-left", children: condition.operator ?? "Select" }),
|
|
7580
|
+
/* @__PURE__ */ jsx55(Icon33, { icon: faChevronDownOutline2, size: "xs", className: "shrink-0 text-[var(--color-foreground)]" })
|
|
6744
7581
|
] }) }),
|
|
6745
|
-
/* @__PURE__ */
|
|
6746
|
-
|
|
7582
|
+
/* @__PURE__ */ jsx55(PopoverPrimitive11.Portal, { children: /* @__PURE__ */ jsx55(
|
|
7583
|
+
PopoverPrimitive11.Content,
|
|
6747
7584
|
{
|
|
6748
7585
|
sideOffset: 4,
|
|
6749
7586
|
align: "start",
|
|
6750
7587
|
className: cn(
|
|
6751
7588
|
"z-50 flex flex-col p-xs overflow-clip",
|
|
6752
7589
|
"bg-[var(--color-dropdown-bg)] border border-[var(--color-dropdown-border)] rounded-md shadow-lg",
|
|
6753
|
-
"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
|
|
6754
|
-
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0",
|
|
6755
|
-
"min-w-[160px]"
|
|
6756
|
-
),
|
|
6757
|
-
children: /* @__PURE__ */
|
|
6758
|
-
OperatorList,
|
|
6759
|
-
{
|
|
6760
|
-
dataType: propertyDef.type,
|
|
6761
|
-
activeOperator: condition.operator,
|
|
6762
|
-
onSelect: handleOperatorSelect
|
|
6763
|
-
}
|
|
6764
|
-
)
|
|
6765
|
-
}
|
|
6766
|
-
) })
|
|
6767
|
-
] }),
|
|
6768
|
-
condition.operator && !isNoValueOperator(condition.operator) &&
|
|
6769
|
-
|
|
6770
|
-
|
|
6771
|
-
|
|
6772
|
-
|
|
6773
|
-
|
|
6774
|
-
|
|
6775
|
-
|
|
6776
|
-
|
|
6777
|
-
|
|
6778
|
-
|
|
6779
|
-
|
|
6780
|
-
"focus:outline-none focus:ring-2 focus:ring-[var(--color-ring)] focus:ring-offset-0"
|
|
6781
|
-
)
|
|
6782
|
-
}
|
|
6783
|
-
),
|
|
6784
|
-
/* @__PURE__ */ jsx53(
|
|
6785
|
-
"button",
|
|
6786
|
-
{
|
|
6787
|
-
type: "button",
|
|
6788
|
-
onClick: onDelete,
|
|
6789
|
-
className: "ml-auto shrink-0 flex items-center justify-center p-sm rounded-md cursor-pointer transition-colors hover:bg-[var(--color-accent)]",
|
|
6790
|
-
"aria-label": "Remove filter",
|
|
6791
|
-
children: /* @__PURE__ */ jsx53(Icon30, { icon: faXmarkOutline3, size: "sm", className: "text-[var(--color-foreground)]" })
|
|
6792
|
-
}
|
|
6793
|
-
)
|
|
6794
|
-
] });
|
|
6795
|
-
};
|
|
6796
|
-
AdvancedRow.displayName = "AdvancedRow";
|
|
6797
|
-
|
|
6798
|
-
// src/components/ui/filter/advanced-popover.tsx
|
|
6799
|
-
import { jsx as jsx54, jsxs as jsxs48 } from "react/jsx-runtime";
|
|
6800
|
-
var outlinedBtn = [
|
|
6801
|
-
"flex items-center gap-sm px-base py-sm",
|
|
6802
|
-
"min-h-[32px] max-h-[32px] min-w-[80px]",
|
|
6803
|
-
"bg-gradient-to-t from-[var(--color-btn-outlined-neutral-bg-default)] from-[10%] to-[var(--color-btn-outlined-neutral-bg-gradient-to-default)]",
|
|
6804
|
-
"border border-[var(--color-btn-outlined-neutral-border-default)] rounded-md shadow-sm",
|
|
6805
|
-
"cursor-pointer transition-colors text-sm font-semibold leading-sm text-[var(--color-foreground)]",
|
|
6806
|
-
"hover:from-[var(--color-btn-outlined-neutral-bg-hover)] hover:to-[var(--color-btn-outlined-neutral-bg-gradient-to-hover)]"
|
|
6807
|
-
];
|
|
6808
|
-
var AdvancedPopover = ({
|
|
6809
|
-
filters,
|
|
6810
|
-
properties,
|
|
6811
|
-
onFiltersChange,
|
|
6812
|
-
open,
|
|
6813
|
-
onOpenChange,
|
|
6814
|
-
children
|
|
6815
|
-
}) => {
|
|
6816
|
-
const [addSelectorOpen, setAddSelectorOpen] = React46.useState(false);
|
|
6817
|
-
const [draftPickerOpen, setDraftPickerOpen] = React46.useState(false);
|
|
6818
|
-
const getPropertyDef = (propertyId) => properties.find((p) => p.id === propertyId);
|
|
6819
|
-
const handleUpdateFilter = (updated) => {
|
|
6820
|
-
onFiltersChange(filters.map((f) => f.id === updated.id ? updated : f));
|
|
6821
|
-
};
|
|
6822
|
-
const handleDeleteFilter = (id) => {
|
|
6823
|
-
onFiltersChange(filters.filter((f) => f.id !== id));
|
|
6824
|
-
};
|
|
6825
|
-
const handlePropertyChange = (filterId, newProp) => {
|
|
6826
|
-
const newCondition = createFilterWithDefaults(newProp.id, newProp.type);
|
|
6827
|
-
onFiltersChange(
|
|
6828
|
-
filters.map((f) => f.id === filterId ? { ...newCondition, id: filterId } : f)
|
|
6829
|
-
);
|
|
6830
|
-
};
|
|
6831
|
-
const handleAddFilter = (property) => {
|
|
6832
|
-
const newFilter = createFilterWithDefaults(property.id, property.type);
|
|
6833
|
-
onFiltersChange([...filters, newFilter]);
|
|
6834
|
-
setAddSelectorOpen(false);
|
|
6835
|
-
};
|
|
6836
|
-
const handleClearAll = () => {
|
|
6837
|
-
onFiltersChange([]);
|
|
6838
|
-
onOpenChange?.(false);
|
|
6839
|
-
};
|
|
6840
|
-
const toggleLogicOp = (filterId) => {
|
|
6841
|
-
onFiltersChange(
|
|
6842
|
-
filters.map(
|
|
6843
|
-
(f) => f.id === filterId ? { ...f, logicOperator: (f.logicOperator ?? "and") === "and" ? "or" : "and" } : f
|
|
6844
|
-
)
|
|
6845
|
-
);
|
|
6846
|
-
};
|
|
6847
|
-
return /* @__PURE__ */ jsxs48(PopoverPrimitive10.Root, { open, onOpenChange, children: [
|
|
6848
|
-
/* @__PURE__ */ jsx54(PopoverPrimitive10.Trigger, { asChild: true, children }),
|
|
6849
|
-
/* @__PURE__ */ jsx54(PopoverPrimitive10.Portal, { children: /* @__PURE__ */ jsxs48(
|
|
6850
|
-
PopoverPrimitive10.Content,
|
|
6851
|
-
{
|
|
6852
|
-
sideOffset: 4,
|
|
6853
|
-
align: "start",
|
|
6854
|
-
collisionPadding: 16,
|
|
6855
|
-
onOpenAutoFocus: (e) => e.preventDefault(),
|
|
6856
|
-
className: cn(
|
|
6857
|
-
"z-50 flex flex-col",
|
|
6858
|
-
"bg-[var(--color-background)] rounded-md shadow-lg",
|
|
6859
|
-
"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
|
|
6860
|
-
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
|
|
6861
|
-
"data-[side=bottom]:slide-in-from-top-2",
|
|
6862
|
-
"w-[min(520px,calc(100vw-32px))]"
|
|
6863
|
-
),
|
|
6864
|
-
children: [
|
|
6865
|
-
/* @__PURE__ */ jsxs48("div", { className: "flex flex-col gap-base p-base", children: [
|
|
6866
|
-
filters.map((filter, i) => {
|
|
6867
|
-
const propDef = getPropertyDef(filter.propertyId);
|
|
6868
|
-
if (!propDef) return null;
|
|
6869
|
-
return /* @__PURE__ */ jsx54(
|
|
6870
|
-
AdvancedRow,
|
|
6871
|
-
{
|
|
6872
|
-
connector: i === 0 ? "Where" : (filter.logicOperator ?? "and") === "and" ? "And" : "Or",
|
|
6873
|
-
onConnectorToggle: i > 0 ? () => toggleLogicOp(filter.id) : void 0,
|
|
6874
|
-
propertyDef: propDef,
|
|
6875
|
-
condition: filter,
|
|
6876
|
-
properties,
|
|
6877
|
-
onUpdate: handleUpdateFilter,
|
|
6878
|
-
onPropertyChange: (p) => handlePropertyChange(filter.id, p),
|
|
6879
|
-
onDelete: () => handleDeleteFilter(filter.id)
|
|
6880
|
-
},
|
|
6881
|
-
filter.id
|
|
6882
|
-
);
|
|
6883
|
-
}),
|
|
6884
|
-
filters.length === 0 && /* ── Draft row: inline "Select property" placeholder ──── */
|
|
6885
|
-
/* @__PURE__ */ jsxs48("div", { className: "flex items-center gap-base w-full min-w-0", children: [
|
|
6886
|
-
/* @__PURE__ */ jsx54("div", { className: "shrink-0 w-[64px] flex items-center justify-end", children: /* @__PURE__ */ jsx54("span", { className: "text-xs font-semibold leading-xs text-[var(--color-muted-foreground)]", children: "Where" }) }),
|
|
6887
|
-
/* @__PURE__ */ jsx54(
|
|
6888
|
-
PropertySelector,
|
|
7590
|
+
"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
|
|
7591
|
+
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0",
|
|
7592
|
+
"min-w-[160px]"
|
|
7593
|
+
),
|
|
7594
|
+
children: /* @__PURE__ */ jsx55(
|
|
7595
|
+
OperatorList,
|
|
7596
|
+
{
|
|
7597
|
+
dataType: propertyDef.type,
|
|
7598
|
+
activeOperator: condition.operator,
|
|
7599
|
+
onSelect: handleOperatorSelect
|
|
7600
|
+
}
|
|
7601
|
+
)
|
|
7602
|
+
}
|
|
7603
|
+
) })
|
|
7604
|
+
] }),
|
|
7605
|
+
condition.operator && !isNoValueOperator(condition.operator) && (() => {
|
|
7606
|
+
const inputType = getValueInputType(propertyDef.type, condition.operator);
|
|
7607
|
+
const dateWide = inputType === "DatePicker" || inputType === "DateRange";
|
|
7608
|
+
return /* @__PURE__ */ jsxs49(PopoverPrimitive11.Root, { open: valueOpen, onOpenChange: setValueOpen, children: [
|
|
7609
|
+
/* @__PURE__ */ jsx55(PopoverPrimitive11.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs49(
|
|
7610
|
+
"button",
|
|
7611
|
+
{
|
|
7612
|
+
type: "button",
|
|
7613
|
+
className: cn(selectBtnStyle, "flex-1 min-w-[80px] justify-between"),
|
|
7614
|
+
children: [
|
|
7615
|
+
/* @__PURE__ */ jsx55(
|
|
7616
|
+
"span",
|
|
6889
7617
|
{
|
|
6890
|
-
|
|
6891
|
-
|
|
6892
|
-
|
|
6893
|
-
|
|
6894
|
-
children:
|
|
6895
|
-
"button",
|
|
6896
|
-
{
|
|
6897
|
-
type: "button",
|
|
6898
|
-
className: cn(
|
|
6899
|
-
"flex items-center gap-base px-base py-sm min-w-0",
|
|
6900
|
-
"bg-gradient-to-t from-[var(--color-btn-outlined-neutral-bg-default)] to-[var(--color-btn-outlined-neutral-bg-gradient-to-default)]",
|
|
6901
|
-
"border border-[var(--color-btn-outlined-neutral-border-default)] rounded-md shadow-sm",
|
|
6902
|
-
"cursor-pointer transition-colors",
|
|
6903
|
-
"hover:from-[var(--color-btn-outlined-neutral-bg-hover)] hover:to-[var(--color-btn-outlined-neutral-bg-gradient-to-hover)]"
|
|
6904
|
-
),
|
|
6905
|
-
children: [
|
|
6906
|
-
/* @__PURE__ */ jsx54("span", { className: "text-sm font-regular leading-sm text-[var(--color-muted-foreground)] whitespace-nowrap", children: "Select property" }),
|
|
6907
|
-
/* @__PURE__ */ jsx54(
|
|
6908
|
-
Icon31,
|
|
6909
|
-
{
|
|
6910
|
-
icon: faChevronDownOutline3,
|
|
6911
|
-
size: "xs",
|
|
6912
|
-
className: "shrink-0 text-[var(--color-foreground)]"
|
|
6913
|
-
}
|
|
6914
|
-
)
|
|
6915
|
-
]
|
|
6916
|
-
}
|
|
6917
|
-
)
|
|
7618
|
+
className: cn(
|
|
7619
|
+
"text-sm font-regular leading-sm whitespace-nowrap truncate text-left",
|
|
7620
|
+
hasValue ? "text-[var(--color-foreground)]" : "text-[var(--color-muted-foreground)]"
|
|
7621
|
+
),
|
|
7622
|
+
children: hasValue ? displayValue : "Enter a value"
|
|
6918
7623
|
}
|
|
6919
|
-
)
|
|
6920
|
-
|
|
6921
|
-
|
|
6922
|
-
|
|
6923
|
-
|
|
6924
|
-
|
|
6925
|
-
|
|
6926
|
-
|
|
6927
|
-
|
|
6928
|
-
|
|
6929
|
-
|
|
6930
|
-
|
|
6931
|
-
|
|
6932
|
-
|
|
6933
|
-
|
|
6934
|
-
|
|
7624
|
+
),
|
|
7625
|
+
/* @__PURE__ */ jsxs49("span", { className: "flex items-center gap-xs shrink-0", children: [
|
|
7626
|
+
badgeCount != null && /* @__PURE__ */ jsxs49("span", { className: "text-xs font-semibold leading-xs text-[var(--color-muted-foreground)]", children: [
|
|
7627
|
+
"+",
|
|
7628
|
+
badgeCount - 1
|
|
7629
|
+
] }),
|
|
7630
|
+
/* @__PURE__ */ jsx55(
|
|
7631
|
+
Icon33,
|
|
7632
|
+
{
|
|
7633
|
+
icon: faChevronDownOutline2,
|
|
7634
|
+
size: "xs",
|
|
7635
|
+
className: "text-[var(--color-foreground)]"
|
|
7636
|
+
}
|
|
7637
|
+
)
|
|
7638
|
+
] })
|
|
7639
|
+
]
|
|
7640
|
+
}
|
|
7641
|
+
) }),
|
|
7642
|
+
/* @__PURE__ */ jsx55(PopoverPrimitive11.Portal, { children: /* @__PURE__ */ jsx55(
|
|
7643
|
+
PopoverPrimitive11.Content,
|
|
7644
|
+
{
|
|
7645
|
+
sideOffset: 4,
|
|
7646
|
+
align: "start",
|
|
7647
|
+
className: cn(
|
|
7648
|
+
"z-50 flex flex-col overflow-clip",
|
|
7649
|
+
"bg-[var(--color-dropdown-bg)] border border-[var(--color-dropdown-border)] rounded-md shadow-lg",
|
|
7650
|
+
"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
|
|
7651
|
+
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0"
|
|
6935
7652
|
),
|
|
6936
|
-
|
|
6937
|
-
|
|
7653
|
+
style: { minWidth: dateWide ? "auto" : "240px" },
|
|
7654
|
+
children: /* @__PURE__ */ jsx55(
|
|
7655
|
+
ValueInput,
|
|
6938
7656
|
{
|
|
6939
|
-
|
|
6940
|
-
|
|
6941
|
-
|
|
6942
|
-
|
|
7657
|
+
dataType: propertyDef.type,
|
|
7658
|
+
operator: condition.operator,
|
|
7659
|
+
value: condition.value,
|
|
7660
|
+
onChange: handleValueChange,
|
|
7661
|
+
onSubmit: () => setValueOpen(false),
|
|
7662
|
+
options: propertyDef.options,
|
|
7663
|
+
dynamicOptions: propertyDef.dynamicOptions
|
|
6943
7664
|
}
|
|
6944
7665
|
)
|
|
6945
|
-
|
|
6946
|
-
|
|
7666
|
+
}
|
|
7667
|
+
) })
|
|
7668
|
+
] });
|
|
7669
|
+
})(),
|
|
7670
|
+
/* @__PURE__ */ jsx55(
|
|
7671
|
+
FilterNodeActions,
|
|
7672
|
+
{
|
|
7673
|
+
nodeType: "condition",
|
|
7674
|
+
onDuplicate: onDuplicate ?? (() => {
|
|
7675
|
+
}),
|
|
7676
|
+
onConvert: onTurnIntoGroup ?? (() => {
|
|
7677
|
+
}),
|
|
7678
|
+
onDelete
|
|
6947
7679
|
}
|
|
6948
|
-
)
|
|
7680
|
+
)
|
|
6949
7681
|
] });
|
|
6950
7682
|
};
|
|
6951
|
-
|
|
7683
|
+
AdvancedRow.displayName = "AdvancedRow";
|
|
6952
7684
|
|
|
6953
|
-
// src/components/ui/filter/
|
|
6954
|
-
import * as
|
|
6955
|
-
import
|
|
6956
|
-
import {
|
|
6957
|
-
|
|
6958
|
-
|
|
6959
|
-
|
|
6960
|
-
|
|
7685
|
+
// src/components/ui/filter/advanced-group.tsx
|
|
7686
|
+
import * as React49 from "react";
|
|
7687
|
+
import { Icon as Icon34, faRefreshOutline as faRefreshOutline2, faPlusOutline as faPlusOutline2 } from "@l3mpire/icons";
|
|
7688
|
+
import { jsx as jsx56, jsxs as jsxs50 } from "react/jsx-runtime";
|
|
7689
|
+
var AdvancedGroup = ({
|
|
7690
|
+
connector,
|
|
7691
|
+
onConnectorToggle,
|
|
7692
|
+
onDuplicate,
|
|
7693
|
+
onTurnIntoFilter,
|
|
7694
|
+
onDelete,
|
|
7695
|
+
onAddFilter,
|
|
6961
7696
|
properties,
|
|
6962
|
-
|
|
6963
|
-
onClearAll,
|
|
6964
|
-
children,
|
|
6965
|
-
className,
|
|
6966
|
-
open: openProp,
|
|
6967
|
-
onOpenChange
|
|
7697
|
+
children
|
|
6968
7698
|
}) => {
|
|
6969
|
-
const [
|
|
6970
|
-
|
|
6971
|
-
|
|
6972
|
-
const setOpen = (v) => {
|
|
6973
|
-
if (!isControlled) setUncontrolledOpen(v);
|
|
6974
|
-
onOpenChange?.(v);
|
|
6975
|
-
};
|
|
6976
|
-
const [addSelectorOpen, setAddSelectorOpen] = React47.useState(false);
|
|
6977
|
-
const [draftPickerOpen, setDraftPickerOpen] = React47.useState(false);
|
|
6978
|
-
const getPropertyDef = (propertyId) => properties.find((p) => p.id === propertyId);
|
|
6979
|
-
const handleUpdateFilter = (updated) => {
|
|
6980
|
-
onFiltersChange(filters.map((f) => f.id === updated.id ? updated : f));
|
|
6981
|
-
};
|
|
6982
|
-
const handleDeleteFilter = (id) => {
|
|
6983
|
-
const next = filters.filter((f) => f.id !== id);
|
|
6984
|
-
onFiltersChange(next);
|
|
6985
|
-
if (next.length === 0) setOpen(false);
|
|
6986
|
-
};
|
|
6987
|
-
const handlePropertyChange = (filterId, newProp) => {
|
|
6988
|
-
const newCondition = createFilterWithDefaults(newProp.id, newProp.type);
|
|
6989
|
-
onFiltersChange(
|
|
6990
|
-
filters.map((f) => f.id === filterId ? { ...newCondition, id: filterId } : f)
|
|
6991
|
-
);
|
|
6992
|
-
};
|
|
6993
|
-
const handleAddFilter = (property) => {
|
|
6994
|
-
const newFilter = createFilterWithDefaults(property.id, property.type);
|
|
6995
|
-
onFiltersChange([...filters, newFilter]);
|
|
6996
|
-
setAddSelectorOpen(false);
|
|
6997
|
-
};
|
|
6998
|
-
const toggleLogicOp = (filterId) => {
|
|
6999
|
-
onFiltersChange(
|
|
7000
|
-
filters.map(
|
|
7001
|
-
(f) => f.id === filterId ? { ...f, logicOperator: (f.logicOperator ?? "and") === "and" ? "or" : "and" } : f
|
|
7002
|
-
)
|
|
7003
|
-
);
|
|
7004
|
-
};
|
|
7005
|
-
return /* @__PURE__ */ jsxs49(PopoverPrimitive11.Root, { open, onOpenChange: setOpen, children: [
|
|
7006
|
-
/* @__PURE__ */ jsx55(PopoverPrimitive11.Trigger, { asChild: true, children: children ?? /* @__PURE__ */ jsxs49(
|
|
7699
|
+
const [addOpen, setAddOpen] = React49.useState(false);
|
|
7700
|
+
return /* @__PURE__ */ jsxs50("div", { className: "flex items-start gap-base w-full min-w-0", children: [
|
|
7701
|
+
connector === "Where" ? /* @__PURE__ */ jsx56("div", { className: "shrink-0 w-[64px] flex items-center justify-end pt-base", children: /* @__PURE__ */ jsx56("span", { className: "text-xs font-semibold leading-xs text-[var(--color-muted-foreground)]", children: "Where" }) }) : /* @__PURE__ */ jsx56("div", { className: "shrink-0 w-[64px] flex items-center justify-end pt-base", children: /* @__PURE__ */ jsxs50(
|
|
7007
7702
|
"button",
|
|
7008
7703
|
{
|
|
7009
7704
|
type: "button",
|
|
7705
|
+
onClick: onConnectorToggle,
|
|
7010
7706
|
className: cn(
|
|
7011
|
-
"
|
|
7012
|
-
"min-h-[32px] max-h-[32px]",
|
|
7707
|
+
"flex items-center justify-center gap-xs",
|
|
7708
|
+
"min-w-[64px] min-h-[32px] max-h-[32px] px-base py-sm",
|
|
7013
7709
|
"bg-gradient-to-t from-[var(--color-btn-outlined-neutral-bg-default)] from-[10%] to-[var(--color-btn-outlined-neutral-bg-gradient-to-default)]",
|
|
7014
|
-
"border border-[var(--color-btn-outlined-neutral-border-default)] rounded-
|
|
7015
|
-
"cursor-pointer transition-colors",
|
|
7016
|
-
"hover:from-[var(--color-btn-outlined-neutral-bg-hover)] hover:to-[var(--color-btn-outlined-neutral-bg-gradient-to-hover)]"
|
|
7017
|
-
className
|
|
7710
|
+
"border border-[var(--color-btn-outlined-neutral-border-default)] rounded-base shadow-sm",
|
|
7711
|
+
"cursor-pointer transition-colors text-xs font-semibold leading-xs text-[var(--color-foreground)]",
|
|
7712
|
+
"hover:from-[var(--color-btn-outlined-neutral-bg-hover)] hover:to-[var(--color-btn-outlined-neutral-bg-gradient-to-hover)]"
|
|
7018
7713
|
),
|
|
7019
7714
|
children: [
|
|
7020
|
-
|
|
7021
|
-
|
|
7022
|
-
{
|
|
7023
|
-
icon: faSlidersOutline2,
|
|
7024
|
-
size: "sm",
|
|
7025
|
-
className: "shrink-0 text-[var(--color-foreground)]"
|
|
7026
|
-
}
|
|
7027
|
-
),
|
|
7028
|
-
/* @__PURE__ */ jsx55("span", { className: "text-sm font-semibold leading-sm whitespace-nowrap text-[var(--color-foreground)]", children: "Filters" }),
|
|
7029
|
-
count > 0 && /* @__PURE__ */ jsx55("span", { className: "flex items-center p-2xs rounded-xs bg-filter-chip-badge-bg", children: /* @__PURE__ */ jsx55("span", { className: "text-[10px] font-semibold leading-2xs text-filter-chip-badge-text", children: count }) })
|
|
7715
|
+
connector,
|
|
7716
|
+
/* @__PURE__ */ jsx56(Icon34, { icon: faRefreshOutline2, size: "xs", className: "text-[var(--color-foreground)]" })
|
|
7030
7717
|
]
|
|
7031
7718
|
}
|
|
7032
7719
|
) }),
|
|
7033
|
-
/* @__PURE__ */
|
|
7034
|
-
|
|
7720
|
+
/* @__PURE__ */ jsxs50("div", { className: "flex-1 min-w-0 flex flex-col gap-base p-base border border-[var(--color-border)] rounded-md bg-[var(--color-secondary,var(--color-accent))]", children: [
|
|
7721
|
+
children,
|
|
7722
|
+
onAddFilter && properties && /* @__PURE__ */ jsx56(
|
|
7723
|
+
PropertySelector,
|
|
7724
|
+
{
|
|
7725
|
+
properties,
|
|
7726
|
+
onSelect: (prop) => {
|
|
7727
|
+
onAddFilter(prop);
|
|
7728
|
+
setAddOpen(false);
|
|
7729
|
+
},
|
|
7730
|
+
open: addOpen,
|
|
7731
|
+
onOpenChange: setAddOpen,
|
|
7732
|
+
children: /* @__PURE__ */ jsxs50(
|
|
7733
|
+
"button",
|
|
7734
|
+
{
|
|
7735
|
+
type: "button",
|
|
7736
|
+
className: "flex items-center gap-sm px-base py-sm text-sm font-semibold leading-sm text-[var(--color-muted-foreground)] cursor-pointer transition-colors rounded-md hover:bg-[var(--color-accent)] hover:text-[var(--color-foreground)] w-fit",
|
|
7737
|
+
children: [
|
|
7738
|
+
/* @__PURE__ */ jsx56(Icon34, { icon: faPlusOutline2, size: "sm" }),
|
|
7739
|
+
"Add filter"
|
|
7740
|
+
]
|
|
7741
|
+
}
|
|
7742
|
+
)
|
|
7743
|
+
}
|
|
7744
|
+
)
|
|
7745
|
+
] }),
|
|
7746
|
+
/* @__PURE__ */ jsx56("div", { className: "shrink-0 pt-base", children: /* @__PURE__ */ jsx56(
|
|
7747
|
+
FilterNodeActions,
|
|
7035
7748
|
{
|
|
7036
|
-
|
|
7037
|
-
|
|
7038
|
-
|
|
7039
|
-
|
|
7040
|
-
className: cn(
|
|
7041
|
-
"z-50 flex flex-col overflow-clip",
|
|
7042
|
-
"bg-[var(--color-dropdown-bg)] border border-[var(--color-dropdown-border)] rounded-md shadow-lg",
|
|
7043
|
-
"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
|
|
7044
|
-
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
|
|
7045
|
-
"data-[side=bottom]:slide-in-from-top-2",
|
|
7046
|
-
"w-[min(520px,calc(100vw-32px))]"
|
|
7047
|
-
),
|
|
7048
|
-
children: [
|
|
7049
|
-
/* @__PURE__ */ jsxs49("div", { className: "flex flex-col gap-base p-base", children: [
|
|
7050
|
-
filters.map((filter, i) => {
|
|
7051
|
-
const propDef = getPropertyDef(filter.propertyId);
|
|
7052
|
-
if (!propDef) return null;
|
|
7053
|
-
return /* @__PURE__ */ jsx55(
|
|
7054
|
-
AdvancedRow,
|
|
7055
|
-
{
|
|
7056
|
-
connector: i === 0 ? "Where" : (filter.logicOperator ?? "and") === "and" ? "And" : "Or",
|
|
7057
|
-
onConnectorToggle: i > 0 ? () => toggleLogicOp(filter.id) : void 0,
|
|
7058
|
-
propertyDef: propDef,
|
|
7059
|
-
condition: filter,
|
|
7060
|
-
properties,
|
|
7061
|
-
onUpdate: handleUpdateFilter,
|
|
7062
|
-
onPropertyChange: (p) => handlePropertyChange(filter.id, p),
|
|
7063
|
-
onDelete: () => handleDeleteFilter(filter.id)
|
|
7064
|
-
},
|
|
7065
|
-
filter.id
|
|
7066
|
-
);
|
|
7067
|
-
}),
|
|
7068
|
-
filters.length === 0 && /* ── Draft row: inline "Select property" placeholder ──── */
|
|
7069
|
-
/* @__PURE__ */ jsxs49("div", { className: "flex items-center gap-base w-full min-w-0", children: [
|
|
7070
|
-
/* @__PURE__ */ jsx55("div", { className: "shrink-0 w-[64px] flex items-center justify-end", children: /* @__PURE__ */ jsx55("span", { className: "text-xs font-semibold leading-xs text-[var(--color-muted-foreground)]", children: "Where" }) }),
|
|
7071
|
-
/* @__PURE__ */ jsx55(
|
|
7072
|
-
PropertySelector,
|
|
7073
|
-
{
|
|
7074
|
-
properties,
|
|
7075
|
-
onSelect: handleAddFilter,
|
|
7076
|
-
open: draftPickerOpen,
|
|
7077
|
-
onOpenChange: setDraftPickerOpen,
|
|
7078
|
-
children: /* @__PURE__ */ jsxs49(
|
|
7079
|
-
"button",
|
|
7080
|
-
{
|
|
7081
|
-
type: "button",
|
|
7082
|
-
className: cn(
|
|
7083
|
-
"flex items-center gap-base px-base py-sm min-w-0",
|
|
7084
|
-
"bg-gradient-to-t from-[var(--color-btn-outlined-neutral-bg-default)] to-[var(--color-btn-outlined-neutral-bg-gradient-to-default)]",
|
|
7085
|
-
"border border-[var(--color-btn-outlined-neutral-border-default)] rounded-md shadow-sm",
|
|
7086
|
-
"cursor-pointer transition-colors",
|
|
7087
|
-
"hover:from-[var(--color-btn-outlined-neutral-bg-hover)] hover:to-[var(--color-btn-outlined-neutral-bg-gradient-to-hover)]"
|
|
7088
|
-
),
|
|
7089
|
-
children: [
|
|
7090
|
-
/* @__PURE__ */ jsx55("span", { className: "text-sm font-regular leading-sm text-[var(--color-muted-foreground)] whitespace-nowrap", children: "Select property" }),
|
|
7091
|
-
/* @__PURE__ */ jsx55(
|
|
7092
|
-
Icon32,
|
|
7093
|
-
{
|
|
7094
|
-
icon: faChevronDownOutline4,
|
|
7095
|
-
size: "xs",
|
|
7096
|
-
className: "shrink-0 text-[var(--color-foreground)]"
|
|
7097
|
-
}
|
|
7098
|
-
)
|
|
7099
|
-
]
|
|
7100
|
-
}
|
|
7101
|
-
)
|
|
7102
|
-
}
|
|
7103
|
-
)
|
|
7104
|
-
] })
|
|
7105
|
-
] }),
|
|
7106
|
-
/* @__PURE__ */ jsxs49("div", { className: "flex items-center justify-between p-base border-t border-[var(--color-border)]", children: [
|
|
7107
|
-
/* @__PURE__ */ jsx55(
|
|
7108
|
-
PropertySelector,
|
|
7109
|
-
{
|
|
7110
|
-
properties,
|
|
7111
|
-
onSelect: handleAddFilter,
|
|
7112
|
-
open: addSelectorOpen,
|
|
7113
|
-
onOpenChange: setAddSelectorOpen,
|
|
7114
|
-
children: /* @__PURE__ */ jsxs49(
|
|
7115
|
-
"button",
|
|
7116
|
-
{
|
|
7117
|
-
type: "button",
|
|
7118
|
-
className: cn(
|
|
7119
|
-
"flex items-center gap-sm px-base py-sm",
|
|
7120
|
-
"min-h-[32px] max-h-[32px] min-w-[80px]",
|
|
7121
|
-
"bg-gradient-to-t from-[var(--color-btn-outlined-neutral-bg-default)] from-[10%] to-[var(--color-btn-outlined-neutral-bg-gradient-to-default)]",
|
|
7122
|
-
"border border-[var(--color-btn-outlined-neutral-border-default)] rounded-md shadow-sm",
|
|
7123
|
-
"cursor-pointer transition-colors text-sm font-semibold leading-sm text-[var(--color-foreground)]",
|
|
7124
|
-
"hover:from-[var(--color-btn-outlined-neutral-bg-hover)] hover:to-[var(--color-btn-outlined-neutral-bg-gradient-to-hover)]"
|
|
7125
|
-
),
|
|
7126
|
-
children: [
|
|
7127
|
-
/* @__PURE__ */ jsx55(Icon32, { icon: faPlusOutline3, size: "sm", className: "text-[var(--color-foreground)]" }),
|
|
7128
|
-
"Add filter"
|
|
7129
|
-
]
|
|
7130
|
-
}
|
|
7131
|
-
)
|
|
7132
|
-
}
|
|
7133
|
-
),
|
|
7134
|
-
filters.length > 0 && /* @__PURE__ */ jsx55(
|
|
7135
|
-
"button",
|
|
7136
|
-
{
|
|
7137
|
-
type: "button",
|
|
7138
|
-
onClick: () => {
|
|
7139
|
-
onClearAll();
|
|
7140
|
-
setOpen(false);
|
|
7141
|
-
},
|
|
7142
|
-
className: "text-sm font-semibold leading-sm text-[var(--color-foreground)] cursor-pointer transition-colors hover:opacity-70 px-base py-sm",
|
|
7143
|
-
children: "Clear all filters"
|
|
7144
|
-
}
|
|
7145
|
-
)
|
|
7146
|
-
] })
|
|
7147
|
-
]
|
|
7749
|
+
nodeType: "group",
|
|
7750
|
+
onDuplicate,
|
|
7751
|
+
onConvert: onTurnIntoFilter,
|
|
7752
|
+
onDelete
|
|
7148
7753
|
}
|
|
7149
7754
|
) })
|
|
7150
7755
|
] });
|
|
7151
7756
|
};
|
|
7152
|
-
|
|
7153
|
-
|
|
7154
|
-
// src/components/ui/filter/use-filter-bar-mode.ts
|
|
7155
|
-
import * as React48 from "react";
|
|
7156
|
-
var DEFAULT_BREAKPOINT = 600;
|
|
7157
|
-
function useFilterBarMode(ref, override, breakpoint = DEFAULT_BREAKPOINT) {
|
|
7158
|
-
const [mode, setMode] = React48.useState("default");
|
|
7159
|
-
React48.useEffect(() => {
|
|
7160
|
-
if (override) return;
|
|
7161
|
-
const el = ref.current;
|
|
7162
|
-
if (!el) return;
|
|
7163
|
-
const observer = new ResizeObserver((entries) => {
|
|
7164
|
-
const width = entries[0]?.contentRect.width ?? 0;
|
|
7165
|
-
setMode(width > breakpoint ? "default" : "minimal");
|
|
7166
|
-
});
|
|
7167
|
-
observer.observe(el);
|
|
7168
|
-
return () => observer.disconnect();
|
|
7169
|
-
}, [ref, override, breakpoint]);
|
|
7170
|
-
return override ?? mode;
|
|
7171
|
-
}
|
|
7757
|
+
AdvancedGroup.displayName = "AdvancedGroup";
|
|
7172
7758
|
|
|
7173
|
-
// src/components/ui/filter/
|
|
7174
|
-
import {
|
|
7175
|
-
var
|
|
7176
|
-
|
|
7177
|
-
|
|
7178
|
-
|
|
7179
|
-
|
|
7180
|
-
|
|
7181
|
-
|
|
7182
|
-
|
|
7183
|
-
|
|
7184
|
-
|
|
7185
|
-
|
|
7186
|
-
|
|
7187
|
-
|
|
7188
|
-
|
|
7189
|
-
const [
|
|
7190
|
-
const [
|
|
7191
|
-
const [
|
|
7192
|
-
const
|
|
7193
|
-
const
|
|
7194
|
-
|
|
7195
|
-
|
|
7196
|
-
|
|
7197
|
-
onFilterStateChange({
|
|
7198
|
-
...filterState,
|
|
7199
|
-
basicFilters: [...filterState.basicFilters, newFilter]
|
|
7200
|
-
});
|
|
7201
|
-
return;
|
|
7202
|
-
}
|
|
7203
|
-
setPendingFilterId(newFilter.id);
|
|
7204
|
-
onFilterStateChange({
|
|
7205
|
-
...filterState,
|
|
7206
|
-
basicFilters: [...filterState.basicFilters, newFilter]
|
|
7207
|
-
});
|
|
7759
|
+
// src/components/ui/filter/advanced-popover.tsx
|
|
7760
|
+
import { jsx as jsx57, jsxs as jsxs51 } from "react/jsx-runtime";
|
|
7761
|
+
var ghostBtn = [
|
|
7762
|
+
"flex items-center gap-sm px-base py-sm",
|
|
7763
|
+
"min-h-[32px]",
|
|
7764
|
+
"cursor-pointer transition-colors text-sm font-semibold leading-sm",
|
|
7765
|
+
"rounded-md hover:bg-[var(--color-accent)]"
|
|
7766
|
+
];
|
|
7767
|
+
var AdvancedPopover = ({
|
|
7768
|
+
filters,
|
|
7769
|
+
properties,
|
|
7770
|
+
onFiltersChange,
|
|
7771
|
+
open,
|
|
7772
|
+
onOpenChange,
|
|
7773
|
+
children
|
|
7774
|
+
}) => {
|
|
7775
|
+
const [addSelectorOpen, setAddSelectorOpen] = React50.useState(false);
|
|
7776
|
+
const [draftPickerOpen, setDraftPickerOpen] = React50.useState(false);
|
|
7777
|
+
const [groupSelectorOpen, setGroupSelectorOpen] = React50.useState(false);
|
|
7778
|
+
const getPropertyDef = (propertyId) => properties.find((p) => p.id === propertyId);
|
|
7779
|
+
const handleAddFilter = (property) => {
|
|
7780
|
+
const newFilter = createFilterWithDefaults(property.id, property.type);
|
|
7781
|
+
onFiltersChange([...filters, newFilter]);
|
|
7782
|
+
setAddSelectorOpen(false);
|
|
7208
7783
|
};
|
|
7209
|
-
const
|
|
7210
|
-
|
|
7211
|
-
|
|
7212
|
-
|
|
7213
|
-
(f) => f.id === updated.id ? updated : f
|
|
7214
|
-
)
|
|
7215
|
-
});
|
|
7216
|
-
if (pendingFilterId === updated.id) {
|
|
7217
|
-
setPendingFilterId(null);
|
|
7218
|
-
}
|
|
7784
|
+
const handleAddGroup = () => {
|
|
7785
|
+
const group = createEmptyGroup();
|
|
7786
|
+
onFiltersChange([...filters, group]);
|
|
7787
|
+
setGroupSelectorOpen(false);
|
|
7219
7788
|
};
|
|
7220
|
-
const
|
|
7221
|
-
|
|
7222
|
-
|
|
7223
|
-
basicFilters: filterState.basicFilters.filter((f) => f.id !== id)
|
|
7224
|
-
});
|
|
7789
|
+
const handleClearAll = () => {
|
|
7790
|
+
onFiltersChange([]);
|
|
7791
|
+
onOpenChange?.(false);
|
|
7225
7792
|
};
|
|
7226
|
-
const
|
|
7227
|
-
|
|
7228
|
-
onFilterStateChange({
|
|
7229
|
-
...filterState,
|
|
7230
|
-
basicFilters: filterState.basicFilters.map(
|
|
7231
|
-
(f) => f.id === filterId ? { ...newCondition, id: filterId } : f
|
|
7232
|
-
)
|
|
7233
|
-
});
|
|
7234
|
-
if (newCondition.operator && !isNoValueOperator(newCondition.operator)) {
|
|
7235
|
-
setPendingFilterId(filterId);
|
|
7236
|
-
}
|
|
7793
|
+
const handleUpdateNode = (id, updated) => {
|
|
7794
|
+
onFiltersChange(updateNodeInTree(filters, id, () => updated));
|
|
7237
7795
|
};
|
|
7238
|
-
const
|
|
7239
|
-
|
|
7240
|
-
if (!filter) return;
|
|
7241
|
-
onFilterStateChange({
|
|
7242
|
-
...filterState,
|
|
7243
|
-
basicFilters: filterState.basicFilters.filter((f) => f.id !== id),
|
|
7244
|
-
advancedFilters: [...filterState.advancedFilters, filter]
|
|
7245
|
-
});
|
|
7796
|
+
const handleDeleteNode = (id) => {
|
|
7797
|
+
onFiltersChange(removeNodeFromTree(filters, id));
|
|
7246
7798
|
};
|
|
7247
|
-
const
|
|
7248
|
-
|
|
7799
|
+
const handleDuplicateNode = (id) => {
|
|
7800
|
+
const find = (nodes) => {
|
|
7801
|
+
for (const n of nodes) {
|
|
7802
|
+
if (n.id === id) return n;
|
|
7803
|
+
if (isFilterGroup(n)) {
|
|
7804
|
+
const found = find(n.children);
|
|
7805
|
+
if (found) return found;
|
|
7806
|
+
}
|
|
7807
|
+
}
|
|
7808
|
+
};
|
|
7809
|
+
const node = find(filters);
|
|
7810
|
+
if (!node) return;
|
|
7811
|
+
const clone = duplicateNode(node);
|
|
7812
|
+
clone.logicOperator = node.logicOperator ?? "and";
|
|
7813
|
+
onFiltersChange(insertAfterInTree(filters, id, clone));
|
|
7249
7814
|
};
|
|
7250
|
-
const
|
|
7251
|
-
|
|
7815
|
+
const handleWrapInGroup = (id) => {
|
|
7816
|
+
const find = (nodes) => {
|
|
7817
|
+
for (const n of nodes) {
|
|
7818
|
+
if (n.id === id && !isFilterGroup(n)) return n;
|
|
7819
|
+
if (isFilterGroup(n)) {
|
|
7820
|
+
const found = find(n.children);
|
|
7821
|
+
if (found) return found;
|
|
7822
|
+
}
|
|
7823
|
+
}
|
|
7824
|
+
};
|
|
7825
|
+
const condition = find(filters);
|
|
7826
|
+
if (!condition) return;
|
|
7827
|
+
const group = wrapInGroup(condition);
|
|
7828
|
+
onFiltersChange(replaceNodeInTree(filters, id, group));
|
|
7252
7829
|
};
|
|
7253
|
-
const
|
|
7254
|
-
|
|
7255
|
-
|
|
7256
|
-
|
|
7257
|
-
|
|
7258
|
-
|
|
7830
|
+
const handleUnwrapGroup = (id) => {
|
|
7831
|
+
const find = (nodes) => {
|
|
7832
|
+
for (const n of nodes) {
|
|
7833
|
+
if (n.id === id && isFilterGroup(n)) return n;
|
|
7834
|
+
if (isFilterGroup(n)) {
|
|
7835
|
+
const found = find(n.children);
|
|
7836
|
+
if (found) return found;
|
|
7837
|
+
}
|
|
7838
|
+
}
|
|
7839
|
+
};
|
|
7840
|
+
const group = find(filters);
|
|
7841
|
+
if (!group) return;
|
|
7842
|
+
const replacement = unwrapGroup(group);
|
|
7843
|
+
if (replacement) {
|
|
7844
|
+
onFiltersChange(replaceNodeInTree(filters, id, replacement));
|
|
7845
|
+
} else {
|
|
7846
|
+
onFiltersChange(removeNodeFromTree(filters, id));
|
|
7847
|
+
}
|
|
7259
7848
|
};
|
|
7260
|
-
const
|
|
7261
|
-
|
|
7849
|
+
const toggleLogicOp = (id) => {
|
|
7850
|
+
onFiltersChange(
|
|
7851
|
+
updateNodeInTree(filters, id, (n) => ({
|
|
7852
|
+
...n,
|
|
7853
|
+
logicOperator: (n.logicOperator ?? "and") === "and" ? "or" : "and"
|
|
7854
|
+
}))
|
|
7855
|
+
);
|
|
7262
7856
|
};
|
|
7263
|
-
const
|
|
7264
|
-
|
|
7265
|
-
|
|
7266
|
-
|
|
7267
|
-
|
|
7268
|
-
|
|
7269
|
-
|
|
7270
|
-
|
|
7271
|
-
} else {
|
|
7272
|
-
setAdvancedOpen(true);
|
|
7273
|
-
}
|
|
7274
|
-
});
|
|
7857
|
+
const handleGroupChildrenChange = (groupId, children2) => {
|
|
7858
|
+
onFiltersChange(
|
|
7859
|
+
updateNodeInTree(
|
|
7860
|
+
filters,
|
|
7861
|
+
groupId,
|
|
7862
|
+
(n) => isFilterGroup(n) ? { ...n, children: children2 } : n
|
|
7863
|
+
)
|
|
7864
|
+
);
|
|
7275
7865
|
};
|
|
7276
|
-
const
|
|
7277
|
-
|
|
7278
|
-
|
|
7279
|
-
|
|
7280
|
-
|
|
7281
|
-
children,
|
|
7282
|
-
sortFields && filterState.sort && /* @__PURE__ */ jsx56(
|
|
7283
|
-
SortButton,
|
|
7866
|
+
const renderNode = (node, index) => {
|
|
7867
|
+
const connector = index === 0 ? "Where" : (node.logicOperator ?? "and") === "and" ? "And" : "Or";
|
|
7868
|
+
if (isFilterGroup(node)) {
|
|
7869
|
+
return /* @__PURE__ */ jsx57(
|
|
7870
|
+
AdvancedGroup,
|
|
7284
7871
|
{
|
|
7285
|
-
|
|
7286
|
-
|
|
7287
|
-
|
|
7288
|
-
|
|
7289
|
-
|
|
7290
|
-
|
|
7291
|
-
|
|
7292
|
-
|
|
7293
|
-
|
|
7294
|
-
|
|
7295
|
-
|
|
7296
|
-
|
|
7297
|
-
|
|
7298
|
-
|
|
7299
|
-
SummaryChip,
|
|
7872
|
+
connector,
|
|
7873
|
+
onConnectorToggle: index > 0 ? () => toggleLogicOp(node.id) : void 0,
|
|
7874
|
+
onDuplicate: () => handleDuplicateNode(node.id),
|
|
7875
|
+
onTurnIntoFilter: () => handleUnwrapGroup(node.id),
|
|
7876
|
+
onDelete: () => handleDeleteNode(node.id),
|
|
7877
|
+
properties,
|
|
7878
|
+
onAddFilter: (prop) => {
|
|
7879
|
+
const newFilter = createFilterWithDefaults(prop.id, prop.type);
|
|
7880
|
+
handleGroupChildrenChange(node.id, [...node.children, newFilter]);
|
|
7881
|
+
},
|
|
7882
|
+
children: node.children.length === 0 ? (
|
|
7883
|
+
/* Draft row in empty group */
|
|
7884
|
+
/* @__PURE__ */ jsx57(
|
|
7885
|
+
DraftRow,
|
|
7300
7886
|
{
|
|
7301
|
-
count: totalCount,
|
|
7302
|
-
filters: allFilters,
|
|
7303
7887
|
properties,
|
|
7304
|
-
|
|
7305
|
-
|
|
7306
|
-
|
|
7307
|
-
|
|
7308
|
-
advancedFilters: []
|
|
7309
|
-
});
|
|
7310
|
-
},
|
|
7311
|
-
onClearAll: handleClearAll,
|
|
7312
|
-
open: summaryOpen,
|
|
7313
|
-
onOpenChange: setSummaryOpen
|
|
7888
|
+
onSelect: (prop) => {
|
|
7889
|
+
const newFilter = createFilterWithDefaults(prop.id, prop.type);
|
|
7890
|
+
handleGroupChildrenChange(node.id, [newFilter]);
|
|
7891
|
+
}
|
|
7314
7892
|
}
|
|
7315
7893
|
)
|
|
7316
|
-
|
|
7894
|
+
) : node.children.map((child, i) => renderNode(child, i))
|
|
7895
|
+
},
|
|
7896
|
+
node.id
|
|
7897
|
+
);
|
|
7898
|
+
}
|
|
7899
|
+
const propDef = getPropertyDef(node.propertyId);
|
|
7900
|
+
if (!propDef) return null;
|
|
7901
|
+
return /* @__PURE__ */ jsx57(
|
|
7902
|
+
AdvancedRow,
|
|
7903
|
+
{
|
|
7904
|
+
connector,
|
|
7905
|
+
onConnectorToggle: index > 0 ? () => toggleLogicOp(node.id) : void 0,
|
|
7906
|
+
propertyDef: propDef,
|
|
7907
|
+
condition: node,
|
|
7908
|
+
properties,
|
|
7909
|
+
onUpdate: (updated) => handleUpdateNode(node.id, updated),
|
|
7910
|
+
onPropertyChange: (p) => {
|
|
7911
|
+
const newCondition = createFilterWithDefaults(p.id, p.type);
|
|
7912
|
+
handleUpdateNode(node.id, { ...newCondition, id: node.id });
|
|
7913
|
+
},
|
|
7914
|
+
onDelete: () => handleDeleteNode(node.id),
|
|
7915
|
+
onDuplicate: () => handleDuplicateNode(node.id),
|
|
7916
|
+
onTurnIntoGroup: () => handleWrapInGroup(node.id)
|
|
7917
|
+
},
|
|
7918
|
+
node.id
|
|
7919
|
+
);
|
|
7920
|
+
};
|
|
7921
|
+
return /* @__PURE__ */ jsxs51(PopoverPrimitive12.Root, { open, onOpenChange, children: [
|
|
7922
|
+
/* @__PURE__ */ jsx57(PopoverPrimitive12.Trigger, { asChild: true, children }),
|
|
7923
|
+
/* @__PURE__ */ jsx57(PopoverPrimitive12.Portal, { children: /* @__PURE__ */ jsxs51(
|
|
7924
|
+
PopoverPrimitive12.Content,
|
|
7925
|
+
{
|
|
7926
|
+
sideOffset: 4,
|
|
7927
|
+
align: "start",
|
|
7928
|
+
collisionPadding: 16,
|
|
7929
|
+
onOpenAutoFocus: (e) => e.preventDefault(),
|
|
7930
|
+
className: cn(
|
|
7931
|
+
"z-50 flex flex-col",
|
|
7932
|
+
"bg-[var(--color-background)] rounded-md shadow-lg",
|
|
7933
|
+
"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
|
|
7934
|
+
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
|
|
7935
|
+
"data-[side=bottom]:slide-in-from-top-2",
|
|
7936
|
+
"w-[min(640px,calc(100vw-32px))]"
|
|
7317
7937
|
),
|
|
7318
|
-
|
|
7319
|
-
|
|
7320
|
-
|
|
7321
|
-
properties,
|
|
7322
|
-
onSelect: handleAddFilter,
|
|
7323
|
-
open: propertySelectorOpen,
|
|
7324
|
-
onOpenChange: setPropertySelectorOpen,
|
|
7325
|
-
onAdvancedFilter: handleOpenAdvanced,
|
|
7326
|
-
advancedFilterCount,
|
|
7327
|
-
children: /* @__PURE__ */ jsx56(FilterBarButton, { iconOnly: true })
|
|
7328
|
-
}
|
|
7329
|
-
)
|
|
7330
|
-
] }) : (
|
|
7331
|
-
/* ── DEFAULT MODE ────────────────────────────────────── */
|
|
7332
|
-
/* @__PURE__ */ jsxs50(Fragment5, { children: [
|
|
7333
|
-
/* @__PURE__ */ jsx56(
|
|
7334
|
-
AdvancedPopover,
|
|
7938
|
+
children: [
|
|
7939
|
+
/* @__PURE__ */ jsx57("div", { className: "flex flex-col gap-base p-base", children: filters.length > 0 ? filters.map((node, i) => renderNode(node, i)) : /* @__PURE__ */ jsx57(
|
|
7940
|
+
DraftRow,
|
|
7335
7941
|
{
|
|
7336
|
-
filters: filterState.advancedFilters,
|
|
7337
7942
|
properties,
|
|
7338
|
-
|
|
7339
|
-
open:
|
|
7340
|
-
onOpenChange:
|
|
7341
|
-
|
|
7342
|
-
|
|
7943
|
+
onSelect: handleAddFilter,
|
|
7944
|
+
open: draftPickerOpen,
|
|
7945
|
+
onOpenChange: setDraftPickerOpen
|
|
7946
|
+
}
|
|
7947
|
+
) }),
|
|
7948
|
+
/* @__PURE__ */ jsxs51("div", { className: "flex items-center justify-between p-base border-t border-[var(--color-border)]", children: [
|
|
7949
|
+
/* @__PURE__ */ jsxs51("div", { className: "flex items-center gap-sm", children: [
|
|
7950
|
+
/* @__PURE__ */ jsx57(
|
|
7951
|
+
PropertySelector,
|
|
7343
7952
|
{
|
|
7344
|
-
|
|
7345
|
-
|
|
7346
|
-
|
|
7347
|
-
|
|
7348
|
-
|
|
7349
|
-
|
|
7350
|
-
|
|
7351
|
-
|
|
7352
|
-
}
|
|
7353
|
-
)
|
|
7953
|
+
properties,
|
|
7954
|
+
onSelect: handleAddFilter,
|
|
7955
|
+
open: addSelectorOpen,
|
|
7956
|
+
onOpenChange: setAddSelectorOpen,
|
|
7957
|
+
children: /* @__PURE__ */ jsxs51("button", { type: "button", className: cn(ghostBtn, "text-[var(--color-foreground)]"), children: [
|
|
7958
|
+
/* @__PURE__ */ jsx57(Icon35, { icon: faPlusOutline3, size: "sm", className: "text-[var(--color-foreground)]" }),
|
|
7959
|
+
"Add filter"
|
|
7960
|
+
] })
|
|
7354
7961
|
}
|
|
7355
|
-
)
|
|
7356
|
-
|
|
7357
|
-
),
|
|
7358
|
-
filterState.basicFilters.map((filter) => {
|
|
7359
|
-
const propDef = getPropertyDef(filter.propertyId);
|
|
7360
|
-
if (!propDef) return null;
|
|
7361
|
-
return /* @__PURE__ */ jsx56(
|
|
7362
|
-
InteractiveFilterChip,
|
|
7363
|
-
{
|
|
7364
|
-
propertyDef: propDef,
|
|
7365
|
-
condition: filter,
|
|
7366
|
-
properties,
|
|
7367
|
-
mode: pendingFilterId === filter.id ? "add" : "edit",
|
|
7368
|
-
autoOpen: pendingFilterId === filter.id,
|
|
7369
|
-
onUpdate: handleUpdateFilter,
|
|
7370
|
-
onPropertyChange: (newProp) => handlePropertyChange(filter.id, newProp),
|
|
7371
|
-
onDelete: () => handleDeleteFilter(filter.id),
|
|
7372
|
-
onConvertToAdvanced: () => handleConvertToAdvanced(filter.id)
|
|
7373
|
-
},
|
|
7374
|
-
filter.id
|
|
7375
|
-
);
|
|
7376
|
-
}),
|
|
7377
|
-
/* @__PURE__ */ jsx56(
|
|
7378
|
-
PropertySelector,
|
|
7379
|
-
{
|
|
7380
|
-
properties,
|
|
7381
|
-
onSelect: handleAddFilter,
|
|
7382
|
-
open: propertySelectorOpen,
|
|
7383
|
-
onOpenChange: setPropertySelectorOpen,
|
|
7384
|
-
onAdvancedFilter: handleOpenAdvanced,
|
|
7385
|
-
advancedFilterCount,
|
|
7386
|
-
children: totalCount > 0 ? /* @__PURE__ */ jsx56(
|
|
7962
|
+
),
|
|
7963
|
+
/* @__PURE__ */ jsxs51(
|
|
7387
7964
|
"button",
|
|
7388
7965
|
{
|
|
7389
7966
|
type: "button",
|
|
7390
|
-
|
|
7391
|
-
|
|
7967
|
+
onClick: handleAddGroup,
|
|
7968
|
+
className: cn(ghostBtn, "text-[var(--color-foreground)]"),
|
|
7969
|
+
children: [
|
|
7970
|
+
/* @__PURE__ */ jsx57(Icon35, { icon: faPlusOutline3, size: "sm", className: "text-[var(--color-foreground)]" }),
|
|
7971
|
+
"Add filters group"
|
|
7972
|
+
]
|
|
7392
7973
|
}
|
|
7393
|
-
)
|
|
7394
|
-
}
|
|
7395
|
-
|
|
7396
|
-
|
|
7397
|
-
|
|
7398
|
-
|
|
7399
|
-
|
|
7400
|
-
|
|
7401
|
-
|
|
7402
|
-
|
|
7403
|
-
|
|
7404
|
-
|
|
7405
|
-
|
|
7406
|
-
|
|
7407
|
-
|
|
7408
|
-
|
|
7974
|
+
)
|
|
7975
|
+
] }),
|
|
7976
|
+
filters.length > 0 && /* @__PURE__ */ jsxs51(
|
|
7977
|
+
"button",
|
|
7978
|
+
{
|
|
7979
|
+
type: "button",
|
|
7980
|
+
onClick: handleClearAll,
|
|
7981
|
+
className: cn(ghostBtn, "text-[var(--color-destructive,#ef4444)]"),
|
|
7982
|
+
children: [
|
|
7983
|
+
/* @__PURE__ */ jsx57(Icon35, { icon: faXmarkOutline3, size: "sm", className: "text-[var(--color-destructive,#ef4444)]" }),
|
|
7984
|
+
"Clear filters"
|
|
7985
|
+
]
|
|
7986
|
+
}
|
|
7987
|
+
)
|
|
7988
|
+
] })
|
|
7989
|
+
]
|
|
7990
|
+
}
|
|
7991
|
+
) })
|
|
7992
|
+
] });
|
|
7993
|
+
};
|
|
7994
|
+
AdvancedPopover.displayName = "AdvancedPopover";
|
|
7995
|
+
var DraftRow = ({
|
|
7996
|
+
properties,
|
|
7997
|
+
onSelect,
|
|
7998
|
+
open: openProp,
|
|
7999
|
+
onOpenChange
|
|
8000
|
+
}) => {
|
|
8001
|
+
const [internalOpen, setInternalOpen] = React50.useState(false);
|
|
8002
|
+
const isControlled = openProp !== void 0;
|
|
8003
|
+
const open = isControlled ? openProp : internalOpen;
|
|
8004
|
+
const setOpen = (v) => {
|
|
8005
|
+
if (!isControlled) setInternalOpen(v);
|
|
8006
|
+
onOpenChange?.(v);
|
|
8007
|
+
};
|
|
8008
|
+
return /* @__PURE__ */ jsxs51("div", { className: "flex items-center gap-base w-full min-w-0", children: [
|
|
8009
|
+
/* @__PURE__ */ jsx57("div", { className: "shrink-0 w-[64px] flex items-center justify-end", children: /* @__PURE__ */ jsx57("span", { className: "text-xs font-semibold leading-xs text-[var(--color-muted-foreground)]", children: "Where" }) }),
|
|
8010
|
+
/* @__PURE__ */ jsx57(
|
|
8011
|
+
PropertySelector,
|
|
8012
|
+
{
|
|
8013
|
+
properties,
|
|
8014
|
+
onSelect: (prop) => {
|
|
8015
|
+
onSelect(prop);
|
|
8016
|
+
setOpen(false);
|
|
8017
|
+
},
|
|
8018
|
+
open,
|
|
8019
|
+
onOpenChange: setOpen,
|
|
8020
|
+
children: /* @__PURE__ */ jsxs51(
|
|
8021
|
+
"button",
|
|
8022
|
+
{
|
|
8023
|
+
type: "button",
|
|
8024
|
+
className: cn(
|
|
8025
|
+
"flex items-center gap-base px-base py-sm min-w-0",
|
|
8026
|
+
"bg-gradient-to-t from-[var(--color-btn-outlined-neutral-bg-default)] to-[var(--color-btn-outlined-neutral-bg-gradient-to-default)]",
|
|
8027
|
+
"border border-[var(--color-btn-outlined-neutral-border-default)] rounded-md shadow-sm",
|
|
8028
|
+
"cursor-pointer transition-colors",
|
|
8029
|
+
"hover:from-[var(--color-btn-outlined-neutral-bg-hover)] hover:to-[var(--color-btn-outlined-neutral-bg-gradient-to-hover)]"
|
|
8030
|
+
),
|
|
8031
|
+
children: [
|
|
8032
|
+
/* @__PURE__ */ jsx57("span", { className: "text-sm font-regular leading-sm text-[var(--color-muted-foreground)] whitespace-nowrap", children: "Select property" }),
|
|
8033
|
+
/* @__PURE__ */ jsx57(
|
|
8034
|
+
Icon35,
|
|
8035
|
+
{
|
|
8036
|
+
icon: faChevronDownOutline3,
|
|
8037
|
+
size: "xs",
|
|
8038
|
+
className: "shrink-0 text-[var(--color-foreground)]"
|
|
8039
|
+
}
|
|
8040
|
+
)
|
|
8041
|
+
]
|
|
8042
|
+
}
|
|
8043
|
+
)
|
|
8044
|
+
}
|
|
8045
|
+
)
|
|
7409
8046
|
] });
|
|
7410
8047
|
};
|
|
7411
|
-
FilterSystem.displayName = "FilterSystem";
|
|
7412
8048
|
|
|
7413
|
-
// src/components/ui/
|
|
7414
|
-
import * as
|
|
7415
|
-
import * as
|
|
7416
|
-
import {
|
|
7417
|
-
|
|
7418
|
-
|
|
7419
|
-
|
|
7420
|
-
|
|
7421
|
-
|
|
7422
|
-
|
|
7423
|
-
import { jsx as jsx57, jsxs as jsxs51 } from "react/jsx-runtime";
|
|
7424
|
-
function getDaysInMonth(year, month) {
|
|
7425
|
-
return new Date(year, month + 1, 0).getDate();
|
|
7426
|
-
}
|
|
7427
|
-
function getWeekdayIndex(date) {
|
|
7428
|
-
return (date.getDay() + 6) % 7;
|
|
7429
|
-
}
|
|
7430
|
-
function isSameDay(a, b) {
|
|
7431
|
-
return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
|
|
7432
|
-
}
|
|
7433
|
-
function isInRange(date, from, to) {
|
|
7434
|
-
const t = date.getTime();
|
|
7435
|
-
return t >= from.getTime() && t <= to.getTime();
|
|
7436
|
-
}
|
|
7437
|
-
function startOfDay(d) {
|
|
7438
|
-
return new Date(d.getFullYear(), d.getMonth(), d.getDate());
|
|
7439
|
-
}
|
|
7440
|
-
var WEEKDAYS = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
|
|
7441
|
-
var MONTH_NAMES = [
|
|
7442
|
-
"January",
|
|
7443
|
-
"February",
|
|
7444
|
-
"March",
|
|
7445
|
-
"April",
|
|
7446
|
-
"May",
|
|
7447
|
-
"June",
|
|
7448
|
-
"July",
|
|
7449
|
-
"August",
|
|
7450
|
-
"September",
|
|
7451
|
-
"October",
|
|
7452
|
-
"November",
|
|
7453
|
-
"December"
|
|
8049
|
+
// src/components/ui/filter/summary-chip.tsx
|
|
8050
|
+
import * as React51 from "react";
|
|
8051
|
+
import * as PopoverPrimitive13 from "@radix-ui/react-popover";
|
|
8052
|
+
import { Icon as Icon36, faSlidersOutline as faSlidersOutline2, faPlusOutline as faPlusOutline4, faChevronDownOutline as faChevronDownOutline4, faXmarkOutline as faXmarkOutline4 } from "@l3mpire/icons";
|
|
8053
|
+
import { jsx as jsx58, jsxs as jsxs52 } from "react/jsx-runtime";
|
|
8054
|
+
var ghostBtn2 = [
|
|
8055
|
+
"flex items-center gap-sm px-base py-sm",
|
|
8056
|
+
"min-h-[32px]",
|
|
8057
|
+
"cursor-pointer transition-colors text-sm font-semibold leading-sm",
|
|
8058
|
+
"rounded-md hover:bg-[var(--color-accent)]"
|
|
7454
8059
|
];
|
|
7455
|
-
var
|
|
7456
|
-
|
|
7457
|
-
|
|
7458
|
-
|
|
7459
|
-
|
|
7460
|
-
|
|
7461
|
-
|
|
7462
|
-
|
|
7463
|
-
|
|
7464
|
-
|
|
7465
|
-
|
|
7466
|
-
|
|
7467
|
-
|
|
7468
|
-
|
|
7469
|
-
|
|
7470
|
-
|
|
7471
|
-
|
|
7472
|
-
|
|
7473
|
-
|
|
7474
|
-
|
|
7475
|
-
|
|
7476
|
-
|
|
7477
|
-
|
|
7478
|
-
|
|
7479
|
-
|
|
7480
|
-
|
|
7481
|
-
|
|
7482
|
-
|
|
7483
|
-
|
|
7484
|
-
|
|
7485
|
-
);
|
|
7486
|
-
|
|
7487
|
-
|
|
7488
|
-
);
|
|
7489
|
-
|
|
7490
|
-
|
|
7491
|
-
|
|
7492
|
-
|
|
7493
|
-
|
|
7494
|
-
|
|
7495
|
-
|
|
7496
|
-
|
|
7497
|
-
|
|
7498
|
-
|
|
7499
|
-
const goToNextMonth = React50.useCallback(() => {
|
|
7500
|
-
setMonth((m) => {
|
|
7501
|
-
if (m === 11) {
|
|
7502
|
-
setYear((y) => y + 1);
|
|
7503
|
-
return 0;
|
|
7504
|
-
}
|
|
7505
|
-
return m + 1;
|
|
7506
|
-
});
|
|
7507
|
-
}, []);
|
|
7508
|
-
const onSelect = React50.useCallback(
|
|
7509
|
-
(date) => {
|
|
7510
|
-
if (mode === "single") {
|
|
7511
|
-
onValueChange?.(date);
|
|
7512
|
-
return;
|
|
8060
|
+
var SummaryChip = ({
|
|
8061
|
+
count,
|
|
8062
|
+
filters,
|
|
8063
|
+
properties,
|
|
8064
|
+
onFiltersChange,
|
|
8065
|
+
onClearAll,
|
|
8066
|
+
children,
|
|
8067
|
+
className,
|
|
8068
|
+
open: openProp,
|
|
8069
|
+
onOpenChange
|
|
8070
|
+
}) => {
|
|
8071
|
+
const [uncontrolledOpen, setUncontrolledOpen] = React51.useState(false);
|
|
8072
|
+
const isControlled = openProp !== void 0;
|
|
8073
|
+
const open = isControlled ? openProp : uncontrolledOpen;
|
|
8074
|
+
const setOpen = (v) => {
|
|
8075
|
+
if (!isControlled) setUncontrolledOpen(v);
|
|
8076
|
+
onOpenChange?.(v);
|
|
8077
|
+
};
|
|
8078
|
+
const [addSelectorOpen, setAddSelectorOpen] = React51.useState(false);
|
|
8079
|
+
const [draftPickerOpen, setDraftPickerOpen] = React51.useState(false);
|
|
8080
|
+
const getPropertyDef = (propertyId) => properties.find((p) => p.id === propertyId);
|
|
8081
|
+
const handleAddFilter = (property) => {
|
|
8082
|
+
const newFilter = createFilterWithDefaults(property.id, property.type);
|
|
8083
|
+
onFiltersChange([...filters, newFilter]);
|
|
8084
|
+
setAddSelectorOpen(false);
|
|
8085
|
+
};
|
|
8086
|
+
const handleAddGroup = () => {
|
|
8087
|
+
onFiltersChange([...filters, createEmptyGroup()]);
|
|
8088
|
+
};
|
|
8089
|
+
const handleUpdateNode = (id, updated) => {
|
|
8090
|
+
onFiltersChange(updateNodeInTree(filters, id, () => updated));
|
|
8091
|
+
};
|
|
8092
|
+
const handleDeleteNode = (id) => {
|
|
8093
|
+
const next = removeNodeFromTree(filters, id);
|
|
8094
|
+
onFiltersChange(next);
|
|
8095
|
+
if (next.length === 0) setOpen(false);
|
|
8096
|
+
};
|
|
8097
|
+
const handleDuplicateNode = (id) => {
|
|
8098
|
+
const find = (nodes) => {
|
|
8099
|
+
for (const n of nodes) {
|
|
8100
|
+
if (n.id === id) return n;
|
|
8101
|
+
if (isFilterGroup(n)) {
|
|
8102
|
+
const f = find(n.children);
|
|
8103
|
+
if (f) return f;
|
|
7513
8104
|
}
|
|
7514
|
-
|
|
7515
|
-
|
|
7516
|
-
|
|
8105
|
+
}
|
|
8106
|
+
};
|
|
8107
|
+
const node = find(filters);
|
|
8108
|
+
if (!node) return;
|
|
8109
|
+
const clone = duplicateNode(node);
|
|
8110
|
+
clone.logicOperator = node.logicOperator ?? "and";
|
|
8111
|
+
onFiltersChange(insertAfterInTree(filters, id, clone));
|
|
8112
|
+
};
|
|
8113
|
+
const handleWrapInGroup = (id) => {
|
|
8114
|
+
const find = (nodes) => {
|
|
8115
|
+
for (const n of nodes) {
|
|
8116
|
+
if (n.id === id && !isFilterGroup(n)) return n;
|
|
8117
|
+
if (isFilterGroup(n)) {
|
|
8118
|
+
const f = find(n.children);
|
|
8119
|
+
if (f) return f;
|
|
7517
8120
|
}
|
|
7518
|
-
|
|
7519
|
-
|
|
7520
|
-
|
|
7521
|
-
|
|
7522
|
-
|
|
8121
|
+
}
|
|
8122
|
+
};
|
|
8123
|
+
const condition = find(filters);
|
|
8124
|
+
if (!condition) return;
|
|
8125
|
+
onFiltersChange(replaceNodeInTree(filters, id, wrapInGroup(condition)));
|
|
8126
|
+
};
|
|
8127
|
+
const handleUnwrapGroup = (id) => {
|
|
8128
|
+
const find = (nodes) => {
|
|
8129
|
+
for (const n of nodes) {
|
|
8130
|
+
if (n.id === id && isFilterGroup(n)) return n;
|
|
8131
|
+
if (isFilterGroup(n)) {
|
|
8132
|
+
const f = find(n.children);
|
|
8133
|
+
if (f) return f;
|
|
7523
8134
|
}
|
|
7524
|
-
}
|
|
7525
|
-
|
|
8135
|
+
}
|
|
8136
|
+
};
|
|
8137
|
+
const group = find(filters);
|
|
8138
|
+
if (!group) return;
|
|
8139
|
+
const replacement = unwrapGroup(group);
|
|
8140
|
+
if (replacement) {
|
|
8141
|
+
onFiltersChange(replaceNodeInTree(filters, id, replacement));
|
|
8142
|
+
} else {
|
|
8143
|
+
onFiltersChange(removeNodeFromTree(filters, id));
|
|
8144
|
+
}
|
|
8145
|
+
};
|
|
8146
|
+
const toggleLogicOp = (id) => {
|
|
8147
|
+
onFiltersChange(
|
|
8148
|
+
updateNodeInTree(filters, id, (n) => ({
|
|
8149
|
+
...n,
|
|
8150
|
+
logicOperator: (n.logicOperator ?? "and") === "and" ? "or" : "and"
|
|
8151
|
+
}))
|
|
7526
8152
|
);
|
|
7527
|
-
|
|
7528
|
-
|
|
7529
|
-
|
|
7530
|
-
|
|
7531
|
-
|
|
7532
|
-
|
|
7533
|
-
|
|
7534
|
-
|
|
7535
|
-
setYear,
|
|
7536
|
-
goToPrevMonth,
|
|
7537
|
-
goToNextMonth,
|
|
7538
|
-
today,
|
|
7539
|
-
hoveredDate,
|
|
7540
|
-
setHoveredDate
|
|
7541
|
-
}),
|
|
7542
|
-
[
|
|
7543
|
-
mode,
|
|
7544
|
-
value,
|
|
7545
|
-
onSelect,
|
|
7546
|
-
month,
|
|
7547
|
-
year,
|
|
7548
|
-
goToPrevMonth,
|
|
7549
|
-
goToNextMonth,
|
|
7550
|
-
today,
|
|
7551
|
-
hoveredDate
|
|
7552
|
-
]
|
|
8153
|
+
};
|
|
8154
|
+
const handleGroupChildrenChange = (groupId, newChildren) => {
|
|
8155
|
+
onFiltersChange(
|
|
8156
|
+
updateNodeInTree(
|
|
8157
|
+
filters,
|
|
8158
|
+
groupId,
|
|
8159
|
+
(n) => isFilterGroup(n) ? { ...n, children: newChildren } : n
|
|
8160
|
+
)
|
|
7553
8161
|
);
|
|
7554
|
-
|
|
7555
|
-
|
|
8162
|
+
};
|
|
8163
|
+
const renderNode = (node, index) => {
|
|
8164
|
+
const connector = index === 0 ? "Where" : (node.logicOperator ?? "and") === "and" ? "And" : "Or";
|
|
8165
|
+
if (isFilterGroup(node)) {
|
|
8166
|
+
return /* @__PURE__ */ jsx58(
|
|
8167
|
+
AdvancedGroup,
|
|
8168
|
+
{
|
|
8169
|
+
connector,
|
|
8170
|
+
onConnectorToggle: index > 0 ? () => toggleLogicOp(node.id) : void 0,
|
|
8171
|
+
onDuplicate: () => handleDuplicateNode(node.id),
|
|
8172
|
+
onTurnIntoFilter: () => handleUnwrapGroup(node.id),
|
|
8173
|
+
onDelete: () => handleDeleteNode(node.id),
|
|
8174
|
+
properties,
|
|
8175
|
+
onAddFilter: (prop) => {
|
|
8176
|
+
const newFilter = createFilterWithDefaults(prop.id, prop.type);
|
|
8177
|
+
handleGroupChildrenChange(node.id, [...node.children, newFilter]);
|
|
8178
|
+
},
|
|
8179
|
+
children: node.children.length === 0 ? /* @__PURE__ */ jsx58(
|
|
8180
|
+
DraftRow2,
|
|
8181
|
+
{
|
|
8182
|
+
properties,
|
|
8183
|
+
onSelect: (prop) => {
|
|
8184
|
+
const newFilter = createFilterWithDefaults(prop.id, prop.type);
|
|
8185
|
+
handleGroupChildrenChange(node.id, [newFilter]);
|
|
8186
|
+
}
|
|
8187
|
+
}
|
|
8188
|
+
) : node.children.map((child, i) => renderNode(child, i))
|
|
8189
|
+
},
|
|
8190
|
+
node.id
|
|
8191
|
+
);
|
|
8192
|
+
}
|
|
8193
|
+
const propDef = getPropertyDef(node.propertyId);
|
|
8194
|
+
if (!propDef) return null;
|
|
8195
|
+
return /* @__PURE__ */ jsx58(
|
|
8196
|
+
AdvancedRow,
|
|
7556
8197
|
{
|
|
7557
|
-
|
|
8198
|
+
connector,
|
|
8199
|
+
onConnectorToggle: index > 0 ? () => toggleLogicOp(node.id) : void 0,
|
|
8200
|
+
propertyDef: propDef,
|
|
8201
|
+
condition: node,
|
|
8202
|
+
properties,
|
|
8203
|
+
onUpdate: (updated) => handleUpdateNode(node.id, updated),
|
|
8204
|
+
onPropertyChange: (p) => {
|
|
8205
|
+
const newCondition = createFilterWithDefaults(p.id, p.type);
|
|
8206
|
+
handleUpdateNode(node.id, { ...newCondition, id: node.id });
|
|
8207
|
+
},
|
|
8208
|
+
onDelete: () => handleDeleteNode(node.id),
|
|
8209
|
+
onDuplicate: () => handleDuplicateNode(node.id),
|
|
8210
|
+
onTurnIntoGroup: () => handleWrapInGroup(node.id)
|
|
8211
|
+
},
|
|
8212
|
+
node.id
|
|
8213
|
+
);
|
|
8214
|
+
};
|
|
8215
|
+
return /* @__PURE__ */ jsxs52(PopoverPrimitive13.Root, { open, onOpenChange: setOpen, children: [
|
|
8216
|
+
/* @__PURE__ */ jsx58(PopoverPrimitive13.Trigger, { asChild: true, children: children ?? /* @__PURE__ */ jsxs52(
|
|
8217
|
+
"button",
|
|
8218
|
+
{
|
|
8219
|
+
type: "button",
|
|
7558
8220
|
className: cn(
|
|
7559
|
-
"flex
|
|
7560
|
-
"
|
|
8221
|
+
"inline-flex items-center gap-sm px-base py-sm",
|
|
8222
|
+
"min-h-[32px] max-h-[32px]",
|
|
8223
|
+
"bg-gradient-to-t from-[var(--color-btn-outlined-neutral-bg-default)] from-[10%] to-[var(--color-btn-outlined-neutral-bg-gradient-to-default)]",
|
|
8224
|
+
"border border-[var(--color-btn-outlined-neutral-border-default)] rounded-md shadow-sm",
|
|
8225
|
+
"cursor-pointer transition-colors",
|
|
8226
|
+
"hover:from-[var(--color-btn-outlined-neutral-bg-hover)] hover:to-[var(--color-btn-outlined-neutral-bg-gradient-to-hover)]",
|
|
7561
8227
|
className
|
|
7562
8228
|
),
|
|
7563
|
-
|
|
7564
|
-
|
|
8229
|
+
children: [
|
|
8230
|
+
/* @__PURE__ */ jsx58(Icon36, { icon: faSlidersOutline2, size: "sm", className: "shrink-0 text-[var(--color-foreground)]" }),
|
|
8231
|
+
/* @__PURE__ */ jsx58("span", { className: "text-sm font-semibold leading-sm whitespace-nowrap text-[var(--color-foreground)]", children: "Filters" }),
|
|
8232
|
+
count > 0 && /* @__PURE__ */ jsx58("span", { className: "flex items-center p-2xs rounded-xs bg-filter-chip-badge-bg", children: /* @__PURE__ */ jsx58("span", { className: "text-[10px] font-semibold leading-2xs text-filter-chip-badge-text", children: count }) })
|
|
8233
|
+
]
|
|
8234
|
+
}
|
|
8235
|
+
) }),
|
|
8236
|
+
/* @__PURE__ */ jsx58(PopoverPrimitive13.Portal, { children: /* @__PURE__ */ jsxs52(
|
|
8237
|
+
PopoverPrimitive13.Content,
|
|
8238
|
+
{
|
|
8239
|
+
sideOffset: 4,
|
|
8240
|
+
align: "start",
|
|
8241
|
+
collisionPadding: 16,
|
|
8242
|
+
onOpenAutoFocus: (e) => e.preventDefault(),
|
|
8243
|
+
className: cn(
|
|
8244
|
+
"z-50 flex flex-col overflow-clip",
|
|
8245
|
+
"bg-[var(--color-dropdown-bg)] border border-[var(--color-dropdown-border)] rounded-md shadow-lg",
|
|
8246
|
+
"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
|
|
8247
|
+
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
|
|
8248
|
+
"data-[side=bottom]:slide-in-from-top-2",
|
|
8249
|
+
"w-[min(640px,calc(100vw-32px))]"
|
|
8250
|
+
),
|
|
8251
|
+
children: [
|
|
8252
|
+
/* @__PURE__ */ jsx58("div", { className: "flex flex-col gap-base p-base", children: filters.length > 0 ? filters.map((node, i) => renderNode(node, i)) : /* @__PURE__ */ jsx58(
|
|
8253
|
+
DraftRow2,
|
|
8254
|
+
{
|
|
8255
|
+
properties,
|
|
8256
|
+
onSelect: handleAddFilter,
|
|
8257
|
+
open: draftPickerOpen,
|
|
8258
|
+
onOpenChange: setDraftPickerOpen
|
|
8259
|
+
}
|
|
8260
|
+
) }),
|
|
8261
|
+
/* @__PURE__ */ jsxs52("div", { className: "flex items-center justify-between p-base border-t border-[var(--color-border)]", children: [
|
|
8262
|
+
/* @__PURE__ */ jsxs52("div", { className: "flex items-center gap-sm", children: [
|
|
8263
|
+
/* @__PURE__ */ jsx58(
|
|
8264
|
+
PropertySelector,
|
|
8265
|
+
{
|
|
8266
|
+
properties,
|
|
8267
|
+
onSelect: handleAddFilter,
|
|
8268
|
+
open: addSelectorOpen,
|
|
8269
|
+
onOpenChange: setAddSelectorOpen,
|
|
8270
|
+
children: /* @__PURE__ */ jsxs52("button", { type: "button", className: cn(ghostBtn2, "text-[var(--color-foreground)]"), children: [
|
|
8271
|
+
/* @__PURE__ */ jsx58(Icon36, { icon: faPlusOutline4, size: "sm", className: "text-[var(--color-foreground)]" }),
|
|
8272
|
+
"Add filter"
|
|
8273
|
+
] })
|
|
8274
|
+
}
|
|
8275
|
+
),
|
|
8276
|
+
/* @__PURE__ */ jsxs52("button", { type: "button", onClick: handleAddGroup, className: cn(ghostBtn2, "text-[var(--color-foreground)]"), children: [
|
|
8277
|
+
/* @__PURE__ */ jsx58(Icon36, { icon: faPlusOutline4, size: "sm", className: "text-[var(--color-foreground)]" }),
|
|
8278
|
+
"Add filters group"
|
|
8279
|
+
] })
|
|
8280
|
+
] }),
|
|
8281
|
+
filters.length > 0 && /* @__PURE__ */ jsxs52(
|
|
8282
|
+
"button",
|
|
8283
|
+
{
|
|
8284
|
+
type: "button",
|
|
8285
|
+
onClick: () => {
|
|
8286
|
+
onClearAll();
|
|
8287
|
+
setOpen(false);
|
|
8288
|
+
},
|
|
8289
|
+
className: cn(ghostBtn2, "text-[var(--color-destructive,#ef4444)]"),
|
|
8290
|
+
children: [
|
|
8291
|
+
/* @__PURE__ */ jsx58(Icon36, { icon: faXmarkOutline4, size: "sm", className: "text-[var(--color-destructive,#ef4444)]" }),
|
|
8292
|
+
"Clear filters"
|
|
8293
|
+
]
|
|
8294
|
+
}
|
|
8295
|
+
)
|
|
8296
|
+
] })
|
|
8297
|
+
]
|
|
8298
|
+
}
|
|
8299
|
+
) })
|
|
8300
|
+
] });
|
|
8301
|
+
};
|
|
8302
|
+
SummaryChip.displayName = "SummaryChip";
|
|
8303
|
+
var DraftRow2 = ({ properties, onSelect, open: openProp, onOpenChange }) => {
|
|
8304
|
+
const [internalOpen, setInternalOpen] = React51.useState(false);
|
|
8305
|
+
const isCtrl = openProp !== void 0;
|
|
8306
|
+
const open = isCtrl ? openProp : internalOpen;
|
|
8307
|
+
const setOpen = (v) => {
|
|
8308
|
+
if (!isCtrl) setInternalOpen(v);
|
|
8309
|
+
onOpenChange?.(v);
|
|
8310
|
+
};
|
|
8311
|
+
return /* @__PURE__ */ jsxs52("div", { className: "flex items-center gap-base w-full min-w-0", children: [
|
|
8312
|
+
/* @__PURE__ */ jsx58("div", { className: "shrink-0 w-[64px] flex items-center justify-end", children: /* @__PURE__ */ jsx58("span", { className: "text-xs font-semibold leading-xs text-[var(--color-muted-foreground)]", children: "Where" }) }),
|
|
8313
|
+
/* @__PURE__ */ jsx58(PropertySelector, { properties, onSelect: (p) => {
|
|
8314
|
+
onSelect(p);
|
|
8315
|
+
setOpen(false);
|
|
8316
|
+
}, open, onOpenChange: setOpen, children: /* @__PURE__ */ jsxs52(
|
|
8317
|
+
"button",
|
|
8318
|
+
{
|
|
8319
|
+
type: "button",
|
|
8320
|
+
className: cn(
|
|
8321
|
+
"flex items-center gap-base px-base py-sm min-w-0",
|
|
8322
|
+
"bg-gradient-to-t from-[var(--color-btn-outlined-neutral-bg-default)] to-[var(--color-btn-outlined-neutral-bg-gradient-to-default)]",
|
|
8323
|
+
"border border-[var(--color-btn-outlined-neutral-border-default)] rounded-md shadow-sm cursor-pointer transition-colors",
|
|
8324
|
+
"hover:from-[var(--color-btn-outlined-neutral-bg-hover)] hover:to-[var(--color-btn-outlined-neutral-bg-gradient-to-hover)]"
|
|
8325
|
+
),
|
|
8326
|
+
children: [
|
|
8327
|
+
/* @__PURE__ */ jsx58("span", { className: "text-sm font-regular leading-sm text-[var(--color-muted-foreground)] whitespace-nowrap", children: "Select property" }),
|
|
8328
|
+
/* @__PURE__ */ jsx58(Icon36, { icon: faChevronDownOutline4, size: "xs", className: "shrink-0 text-[var(--color-foreground)]" })
|
|
8329
|
+
]
|
|
7565
8330
|
}
|
|
7566
|
-
) })
|
|
7567
|
-
}
|
|
7568
|
-
);
|
|
7569
|
-
DatePicker.displayName = "DatePicker";
|
|
7570
|
-
function defaultFormatDate(date) {
|
|
7571
|
-
return date.toLocaleDateString("en-US", {
|
|
7572
|
-
month: "short",
|
|
7573
|
-
day: "numeric",
|
|
7574
|
-
year: "numeric"
|
|
7575
|
-
});
|
|
7576
|
-
}
|
|
7577
|
-
var DatePickerSelects = React50.forwardRef(({ className, formatDate = defaultFormatDate, ...props }, ref) => {
|
|
7578
|
-
const { selected } = useDatePickerContext();
|
|
7579
|
-
const fromDate = selected instanceof Date ? selected : selected?.from;
|
|
7580
|
-
const toDate = selected instanceof Date ? void 0 : selected?.to;
|
|
7581
|
-
return /* @__PURE__ */ jsx57(
|
|
7582
|
-
"div",
|
|
7583
|
-
{
|
|
7584
|
-
ref,
|
|
7585
|
-
className: cn("flex flex-col items-start pt-lg px-lg", className),
|
|
7586
|
-
...props,
|
|
7587
|
-
children: /* @__PURE__ */ jsxs51("div", { className: "flex items-center gap-base w-full", children: [
|
|
7588
|
-
/* @__PURE__ */ jsxs51("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: [
|
|
7589
|
-
/* @__PURE__ */ jsx57("span", { className: "flex-1 text-sm font-regular leading-sm text-datepicker-header-text truncate", children: fromDate ? formatDate(fromDate) : "Start date" }),
|
|
7590
|
-
/* @__PURE__ */ jsx57(Icon34, { icon: faCalendarOutline, size: "sm", className: "shrink-0 text-datepicker-header-text" })
|
|
7591
|
-
] }),
|
|
7592
|
-
/* @__PURE__ */ jsx57(
|
|
7593
|
-
Icon34,
|
|
7594
|
-
{
|
|
7595
|
-
icon: faArrowRightOutline2,
|
|
7596
|
-
size: "sm",
|
|
7597
|
-
className: "shrink-0 text-datepicker-header-weekday"
|
|
7598
|
-
}
|
|
7599
|
-
),
|
|
7600
|
-
/* @__PURE__ */ jsxs51("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: [
|
|
7601
|
-
/* @__PURE__ */ jsx57("span", { className: "flex-1 text-sm font-regular leading-sm text-datepicker-header-text truncate", children: toDate ? formatDate(toDate) : "End date" }),
|
|
7602
|
-
/* @__PURE__ */ jsx57(Icon34, { icon: faCalendarOutline, size: "sm", className: "shrink-0 text-datepicker-header-text" })
|
|
7603
|
-
] })
|
|
7604
|
-
] })
|
|
7605
|
-
}
|
|
7606
|
-
);
|
|
7607
|
-
});
|
|
7608
|
-
DatePickerSelects.displayName = "DatePickerSelects";
|
|
7609
|
-
var DatePickerDay = ({ date, isOutside }) => {
|
|
7610
|
-
const { mode, selected, onSelect, today, hoveredDate, setHoveredDate } = useDatePickerContext();
|
|
7611
|
-
const isToday = isSameDay(date, today);
|
|
7612
|
-
const isSelected = selected instanceof Date ? isSameDay(date, selected) : selected?.from ? isSameDay(date, selected.from) || (selected.to ? isSameDay(date, selected.to) : false) : false;
|
|
7613
|
-
const isRangeStart = mode === "range" && selected && !(selected instanceof Date) && selected.from && isSameDay(date, selected.from);
|
|
7614
|
-
const isRangeEnd = mode === "range" && selected && !(selected instanceof Date) && selected.to && isSameDay(date, selected.to);
|
|
7615
|
-
const inRange = mode === "range" && selected && !(selected instanceof Date) && selected.from && selected.to && !isSelected && isInRange(date, selected.from, selected.to);
|
|
7616
|
-
const inPreviewRange = mode === "range" && selected && !(selected instanceof Date) && selected.from && !selected.to && hoveredDate && !isSelected && hoveredDate.getTime() > selected.from.getTime() && isInRange(date, selected.from, hoveredDate);
|
|
7617
|
-
const isInRangeOrPreview = inRange || inPreviewRange;
|
|
7618
|
-
return /* @__PURE__ */ jsxs51(
|
|
7619
|
-
"button",
|
|
7620
|
-
{
|
|
7621
|
-
type: "button",
|
|
7622
|
-
onClick: () => !isOutside && onSelect(date),
|
|
7623
|
-
onMouseEnter: () => mode === "range" && setHoveredDate(date),
|
|
7624
|
-
onMouseLeave: () => mode === "range" && setHoveredDate(void 0),
|
|
7625
|
-
disabled: isOutside,
|
|
7626
|
-
className: cn(
|
|
7627
|
-
"relative flex flex-col items-center justify-center w-9 rounded-full p-2 cursor-pointer transition-colors",
|
|
7628
|
-
"text-sm font-semibold leading-sm text-center",
|
|
7629
|
-
// Default
|
|
7630
|
-
!isOutside && !isSelected && !isInRangeOrPreview && "text-datepicker-day-text-default hover:bg-datepicker-day-bg-hover",
|
|
7631
|
-
// Outside month (disabled)
|
|
7632
|
-
isOutside && "text-datepicker-day-text-disabled cursor-default",
|
|
7633
|
-
// Selected
|
|
7634
|
-
isSelected && "bg-datepicker-day-bg-selected text-datepicker-day-text-selected",
|
|
7635
|
-
// In range
|
|
7636
|
-
isInRangeOrPreview && "bg-datepicker-day-bg-range text-datepicker-day-text-range",
|
|
7637
|
-
// Range start/end get full rounded; in-range items could be less rounded
|
|
7638
|
-
(isRangeStart || isRangeEnd) && "rounded-full"
|
|
7639
|
-
),
|
|
7640
|
-
children: [
|
|
7641
|
-
date.getDate(),
|
|
7642
|
-
isToday && !isOutside && /* @__PURE__ */ jsx57("span", { className: "absolute bottom-0.5 left-1/2 -translate-x-1/2 size-1.5 rounded-full bg-datepicker-day-today" })
|
|
7643
|
-
]
|
|
7644
|
-
}
|
|
7645
|
-
);
|
|
8331
|
+
) })
|
|
8332
|
+
] });
|
|
7646
8333
|
};
|
|
7647
|
-
|
|
7648
|
-
|
|
7649
|
-
|
|
7650
|
-
|
|
7651
|
-
|
|
7652
|
-
|
|
7653
|
-
|
|
7654
|
-
|
|
7655
|
-
|
|
7656
|
-
);
|
|
7657
|
-
const
|
|
7658
|
-
|
|
7659
|
-
|
|
7660
|
-
|
|
7661
|
-
|
|
7662
|
-
|
|
7663
|
-
|
|
7664
|
-
|
|
7665
|
-
|
|
7666
|
-
|
|
8334
|
+
|
|
8335
|
+
// src/components/ui/filter/use-filter-bar-mode.ts
|
|
8336
|
+
import * as React52 from "react";
|
|
8337
|
+
var DEFAULT_BREAKPOINT = 600;
|
|
8338
|
+
function useFilterBarMode(ref, override, breakpoint = DEFAULT_BREAKPOINT) {
|
|
8339
|
+
const [mode, setMode] = React52.useState("default");
|
|
8340
|
+
React52.useEffect(() => {
|
|
8341
|
+
if (override) return;
|
|
8342
|
+
const el = ref.current;
|
|
8343
|
+
if (!el) return;
|
|
8344
|
+
const observer = new ResizeObserver((entries) => {
|
|
8345
|
+
const width = entries[0]?.contentRect.width ?? 0;
|
|
8346
|
+
setMode(width > breakpoint ? "default" : "minimal");
|
|
8347
|
+
});
|
|
8348
|
+
observer.observe(el);
|
|
8349
|
+
return () => observer.disconnect();
|
|
8350
|
+
}, [ref, override, breakpoint]);
|
|
8351
|
+
return override ?? mode;
|
|
8352
|
+
}
|
|
8353
|
+
|
|
8354
|
+
// src/components/ui/filter/filter-system.tsx
|
|
8355
|
+
import { Fragment as Fragment5, jsx as jsx59, jsxs as jsxs53 } from "react/jsx-runtime";
|
|
8356
|
+
var FilterSystem = ({
|
|
8357
|
+
properties,
|
|
8358
|
+
filterState,
|
|
8359
|
+
onFilterStateChange,
|
|
8360
|
+
sortFields,
|
|
8361
|
+
mode: modeOverride,
|
|
8362
|
+
breakpoint,
|
|
8363
|
+
children,
|
|
8364
|
+
actions,
|
|
8365
|
+
className
|
|
8366
|
+
}) => {
|
|
8367
|
+
const containerRef = React53.useRef(null);
|
|
8368
|
+
const mode = useFilterBarMode(containerRef, modeOverride, breakpoint);
|
|
8369
|
+
const [propertySelectorOpen, setPropertySelectorOpen] = React53.useState(false);
|
|
8370
|
+
const [advancedOpen, setAdvancedOpen] = React53.useState(false);
|
|
8371
|
+
const [summaryOpen, setSummaryOpen] = React53.useState(false);
|
|
8372
|
+
const [pendingFilterId, setPendingFilterId] = React53.useState(null);
|
|
8373
|
+
const totalCount = filterState.basicFilters.length + countConditions(filterState.advancedFilters);
|
|
8374
|
+
const handleAddFilter = (property) => {
|
|
8375
|
+
const newFilter = createFilterWithDefaults(property.id, property.type);
|
|
8376
|
+
if (newFilter.operator && isNoValueOperator(newFilter.operator)) {
|
|
8377
|
+
onFilterStateChange({
|
|
8378
|
+
...filterState,
|
|
8379
|
+
basicFilters: [...filterState.basicFilters, newFilter]
|
|
7667
8380
|
});
|
|
8381
|
+
return;
|
|
7668
8382
|
}
|
|
7669
|
-
|
|
7670
|
-
|
|
7671
|
-
|
|
7672
|
-
|
|
7673
|
-
|
|
7674
|
-
|
|
7675
|
-
|
|
7676
|
-
|
|
7677
|
-
|
|
7678
|
-
|
|
7679
|
-
)
|
|
7680
|
-
|
|
7681
|
-
|
|
8383
|
+
setPendingFilterId(newFilter.id);
|
|
8384
|
+
onFilterStateChange({
|
|
8385
|
+
...filterState,
|
|
8386
|
+
basicFilters: [...filterState.basicFilters, newFilter]
|
|
8387
|
+
});
|
|
8388
|
+
};
|
|
8389
|
+
const handleUpdateFilter = (updated) => {
|
|
8390
|
+
onFilterStateChange({
|
|
8391
|
+
...filterState,
|
|
8392
|
+
basicFilters: filterState.basicFilters.map(
|
|
8393
|
+
(f) => f.id === updated.id ? updated : f
|
|
8394
|
+
)
|
|
8395
|
+
});
|
|
8396
|
+
if (pendingFilterId === updated.id) {
|
|
8397
|
+
setPendingFilterId(null);
|
|
7682
8398
|
}
|
|
7683
|
-
|
|
7684
|
-
|
|
7685
|
-
|
|
8399
|
+
};
|
|
8400
|
+
const handleDeleteFilter = (id) => {
|
|
8401
|
+
onFilterStateChange({
|
|
8402
|
+
...filterState,
|
|
8403
|
+
basicFilters: filterState.basicFilters.filter((f) => f.id !== id)
|
|
8404
|
+
});
|
|
8405
|
+
};
|
|
8406
|
+
const handlePropertyChange = (filterId, newProp) => {
|
|
8407
|
+
const newCondition = createFilterWithDefaults(newProp.id, newProp.type);
|
|
8408
|
+
onFilterStateChange({
|
|
8409
|
+
...filterState,
|
|
8410
|
+
basicFilters: filterState.basicFilters.map(
|
|
8411
|
+
(f) => f.id === filterId ? { ...newCondition, id: filterId } : f
|
|
8412
|
+
)
|
|
8413
|
+
});
|
|
8414
|
+
if (newCondition.operator && !isNoValueOperator(newCondition.operator)) {
|
|
8415
|
+
setPendingFilterId(filterId);
|
|
7686
8416
|
}
|
|
7687
|
-
|
|
7688
|
-
|
|
7689
|
-
|
|
7690
|
-
|
|
7691
|
-
{
|
|
7692
|
-
|
|
7693
|
-
|
|
7694
|
-
...
|
|
7695
|
-
|
|
7696
|
-
|
|
7697
|
-
|
|
7698
|
-
|
|
7699
|
-
|
|
7700
|
-
|
|
7701
|
-
|
|
7702
|
-
|
|
7703
|
-
|
|
7704
|
-
|
|
7705
|
-
|
|
7706
|
-
|
|
8417
|
+
};
|
|
8418
|
+
const handleConvertToAdvanced = (id) => {
|
|
8419
|
+
const filter = filterState.basicFilters.find((f) => f.id === id);
|
|
8420
|
+
if (!filter) return;
|
|
8421
|
+
onFilterStateChange({
|
|
8422
|
+
...filterState,
|
|
8423
|
+
basicFilters: filterState.basicFilters.filter((f) => f.id !== id),
|
|
8424
|
+
advancedFilters: [...filterState.advancedFilters, filter]
|
|
8425
|
+
});
|
|
8426
|
+
};
|
|
8427
|
+
const handleAdvancedFiltersChange = (filters) => {
|
|
8428
|
+
onFilterStateChange({ ...filterState, advancedFilters: filters });
|
|
8429
|
+
};
|
|
8430
|
+
const handleClearAdvanced = () => {
|
|
8431
|
+
onFilterStateChange({ ...filterState, advancedFilters: [] });
|
|
8432
|
+
};
|
|
8433
|
+
const handleClearAll = () => {
|
|
8434
|
+
onFilterStateChange({
|
|
8435
|
+
...filterState,
|
|
8436
|
+
basicFilters: [],
|
|
8437
|
+
advancedFilters: []
|
|
8438
|
+
});
|
|
8439
|
+
};
|
|
8440
|
+
const handleSortChange = (field, direction) => {
|
|
8441
|
+
onFilterStateChange({ ...filterState, sort: { field, direction } });
|
|
8442
|
+
};
|
|
8443
|
+
const getPropertyDef = (propertyId) => properties.find((p) => p.id === propertyId);
|
|
8444
|
+
const hasAdvanced = filterState.advancedFilters.length > 0;
|
|
8445
|
+
const isMinimal = mode === "minimal";
|
|
8446
|
+
const handleOpenAdvanced = () => {
|
|
8447
|
+
setPropertySelectorOpen(false);
|
|
8448
|
+
requestAnimationFrame(() => {
|
|
8449
|
+
if (isMinimal) {
|
|
8450
|
+
setSummaryOpen(true);
|
|
8451
|
+
} else {
|
|
8452
|
+
setAdvancedOpen(true);
|
|
8453
|
+
}
|
|
8454
|
+
});
|
|
8455
|
+
};
|
|
8456
|
+
const advancedFilterCount = filterState.advancedFilters.length;
|
|
8457
|
+
const showAdvancedChip = hasAdvanced || advancedOpen;
|
|
8458
|
+
const showSummaryChip = totalCount > 0 || summaryOpen;
|
|
8459
|
+
return /* @__PURE__ */ jsxs53(FilterBar, { ref: containerRef, className, children: [
|
|
8460
|
+
/* @__PURE__ */ jsxs53(FilterBarLeft, { className: "flex-nowrap flex-1 min-w-0 overflow-x-auto scrollbar-none outline-none [&>*]:shrink-0", children: [
|
|
8461
|
+
children,
|
|
8462
|
+
sortFields && filterState.sort && /* @__PURE__ */ jsx59(
|
|
8463
|
+
SortButton,
|
|
8464
|
+
{
|
|
8465
|
+
fields: sortFields,
|
|
8466
|
+
activeField: filterState.sort.field,
|
|
8467
|
+
direction: filterState.sort.direction,
|
|
8468
|
+
onChange: handleSortChange,
|
|
8469
|
+
iconOnly: isMinimal
|
|
8470
|
+
}
|
|
8471
|
+
),
|
|
8472
|
+
isMinimal ? /* @__PURE__ */ jsxs53(Fragment5, { children: [
|
|
8473
|
+
/* @__PURE__ */ jsx59(
|
|
8474
|
+
"div",
|
|
8475
|
+
{
|
|
8476
|
+
className: showSummaryChip ? "inline-flex" : "inline-flex w-0 overflow-hidden opacity-0 pointer-events-none",
|
|
8477
|
+
"aria-hidden": !showSummaryChip || void 0,
|
|
8478
|
+
children: /* @__PURE__ */ jsx59(
|
|
8479
|
+
SummaryChip,
|
|
8480
|
+
{
|
|
8481
|
+
count: totalCount,
|
|
8482
|
+
filters: [...filterState.basicFilters, ...filterState.advancedFilters],
|
|
8483
|
+
properties,
|
|
8484
|
+
onFiltersChange: (nodes) => {
|
|
8485
|
+
onFilterStateChange({
|
|
8486
|
+
...filterState,
|
|
8487
|
+
basicFilters: [],
|
|
8488
|
+
advancedFilters: nodes
|
|
8489
|
+
});
|
|
8490
|
+
},
|
|
8491
|
+
onClearAll: handleClearAll,
|
|
8492
|
+
open: summaryOpen,
|
|
8493
|
+
onOpenChange: setSummaryOpen
|
|
8494
|
+
}
|
|
8495
|
+
)
|
|
8496
|
+
}
|
|
8497
|
+
),
|
|
8498
|
+
!showSummaryChip && /* @__PURE__ */ jsx59(
|
|
8499
|
+
PropertySelector,
|
|
8500
|
+
{
|
|
8501
|
+
properties,
|
|
8502
|
+
onSelect: handleAddFilter,
|
|
8503
|
+
open: propertySelectorOpen,
|
|
8504
|
+
onOpenChange: setPropertySelectorOpen,
|
|
8505
|
+
onAdvancedFilter: handleOpenAdvanced,
|
|
8506
|
+
advancedFilterCount,
|
|
8507
|
+
children: /* @__PURE__ */ jsx59(FilterBarButton, { iconOnly: true })
|
|
8508
|
+
}
|
|
8509
|
+
)
|
|
8510
|
+
] }) : (
|
|
8511
|
+
/* ── DEFAULT MODE ────────────────────────────────────── */
|
|
8512
|
+
/* @__PURE__ */ jsxs53(Fragment5, { children: [
|
|
8513
|
+
/* @__PURE__ */ jsx59(
|
|
8514
|
+
AdvancedPopover,
|
|
8515
|
+
{
|
|
8516
|
+
filters: filterState.advancedFilters,
|
|
8517
|
+
properties,
|
|
8518
|
+
onFiltersChange: handleAdvancedFiltersChange,
|
|
8519
|
+
open: advancedOpen,
|
|
8520
|
+
onOpenChange: setAdvancedOpen,
|
|
8521
|
+
children: /* @__PURE__ */ jsx59(
|
|
8522
|
+
"div",
|
|
7707
8523
|
{
|
|
7708
|
-
|
|
7709
|
-
|
|
7710
|
-
|
|
7711
|
-
|
|
7712
|
-
|
|
8524
|
+
className: showAdvancedChip ? "inline-flex" : "inline-flex w-0 overflow-hidden opacity-0 pointer-events-none",
|
|
8525
|
+
"aria-hidden": !showAdvancedChip || void 0,
|
|
8526
|
+
children: /* @__PURE__ */ jsx59(
|
|
8527
|
+
AdvancedChip,
|
|
8528
|
+
{
|
|
8529
|
+
count: filterState.advancedFilters.length,
|
|
8530
|
+
onClick: () => setAdvancedOpen(true),
|
|
8531
|
+
onClear: handleClearAdvanced
|
|
8532
|
+
}
|
|
8533
|
+
)
|
|
7713
8534
|
}
|
|
7714
|
-
)
|
|
7715
|
-
|
|
8535
|
+
)
|
|
8536
|
+
}
|
|
8537
|
+
),
|
|
8538
|
+
filterState.basicFilters.map((filter) => {
|
|
8539
|
+
const propDef = getPropertyDef(filter.propertyId);
|
|
8540
|
+
if (!propDef) return null;
|
|
8541
|
+
return /* @__PURE__ */ jsx59(
|
|
8542
|
+
InteractiveFilterChip,
|
|
8543
|
+
{
|
|
8544
|
+
propertyDef: propDef,
|
|
8545
|
+
condition: filter,
|
|
8546
|
+
properties,
|
|
8547
|
+
mode: pendingFilterId === filter.id ? "add" : "edit",
|
|
8548
|
+
autoOpen: pendingFilterId === filter.id,
|
|
8549
|
+
onUpdate: handleUpdateFilter,
|
|
8550
|
+
onPropertyChange: (newProp) => handlePropertyChange(filter.id, newProp),
|
|
8551
|
+
onDelete: () => handleDeleteFilter(filter.id),
|
|
8552
|
+
onConvertToAdvanced: () => handleConvertToAdvanced(filter.id)
|
|
8553
|
+
},
|
|
8554
|
+
filter.id
|
|
8555
|
+
);
|
|
8556
|
+
}),
|
|
8557
|
+
/* @__PURE__ */ jsx59(
|
|
8558
|
+
PropertySelector,
|
|
8559
|
+
{
|
|
8560
|
+
properties,
|
|
8561
|
+
onSelect: handleAddFilter,
|
|
8562
|
+
open: propertySelectorOpen,
|
|
8563
|
+
onOpenChange: setPropertySelectorOpen,
|
|
8564
|
+
onAdvancedFilter: handleOpenAdvanced,
|
|
8565
|
+
advancedFilterCount,
|
|
8566
|
+
children: totalCount > 0 ? /* @__PURE__ */ jsx59(
|
|
7716
8567
|
"button",
|
|
7717
8568
|
{
|
|
7718
8569
|
type: "button",
|
|
7719
|
-
|
|
7720
|
-
|
|
7721
|
-
"aria-label": "Next month",
|
|
7722
|
-
children: /* @__PURE__ */ jsx57(Icon34, { icon: faChevronRightOutline3, size: "xs", className: "text-datepicker-header-nav" })
|
|
8570
|
+
className: "shrink-0 inline-flex items-center justify-center size-8 rounded-md border border-[var(--color-btn-outlined-neutral-border-default)] bg-gradient-to-t from-[var(--color-btn-outlined-neutral-bg-default)] from-[10%] to-[var(--color-btn-outlined-neutral-bg-gradient-to-default)] shadow-sm cursor-pointer transition-colors hover:from-[var(--color-btn-outlined-neutral-bg-hover)] hover:to-[var(--color-btn-outlined-neutral-bg-gradient-to-hover)]",
|
|
8571
|
+
children: /* @__PURE__ */ jsx59(Icon37, { icon: faPlusOutline5, size: "sm", className: "text-[var(--color-foreground)]" })
|
|
7723
8572
|
}
|
|
7724
|
-
)
|
|
7725
|
-
|
|
7726
|
-
|
|
7727
|
-
/* @__PURE__ */ jsxs51("div", { className: "flex flex-col", children: [
|
|
7728
|
-
/* @__PURE__ */ jsx57("div", { className: "grid grid-cols-7 gap-base py-sm", children: WEEKDAYS.map((day) => /* @__PURE__ */ jsx57(
|
|
7729
|
-
"span",
|
|
7730
|
-
{
|
|
7731
|
-
className: "w-9 text-center text-xs font-regular leading-xs text-datepicker-header-weekday",
|
|
7732
|
-
children: day
|
|
7733
|
-
},
|
|
7734
|
-
day
|
|
7735
|
-
)) }),
|
|
7736
|
-
/* @__PURE__ */ jsx57("div", { className: "flex flex-col", children: weeks.map((week, wi) => /* @__PURE__ */ jsx57("div", { className: "grid grid-cols-7 gap-base", children: week.map((day, di) => /* @__PURE__ */ jsx57(
|
|
7737
|
-
DatePickerDay,
|
|
7738
|
-
{
|
|
7739
|
-
date: day.date,
|
|
7740
|
-
isOutside: day.isOutside
|
|
7741
|
-
},
|
|
7742
|
-
di
|
|
7743
|
-
)) }, wi)) })
|
|
7744
|
-
] })
|
|
8573
|
+
) : /* @__PURE__ */ jsx59(FilterBarButton, {})
|
|
8574
|
+
}
|
|
8575
|
+
)
|
|
7745
8576
|
] })
|
|
7746
|
-
]
|
|
7747
|
-
}
|
|
7748
|
-
);
|
|
7749
|
-
});
|
|
7750
|
-
DatePickerCalendar.displayName = "DatePickerCalendar";
|
|
7751
|
-
var DatePickerSuggestions = React50.forwardRef(
|
|
7752
|
-
({ className, suggestions, formatDate = defaultFormatDate, ...props }, ref) => {
|
|
7753
|
-
const { onSelect, mode } = useDatePickerContext();
|
|
7754
|
-
const onValueChange = React50.useContext(DatePickerContext) ? void 0 : void 0;
|
|
7755
|
-
const ctx = useDatePickerContext();
|
|
7756
|
-
const handleClick = (suggestion) => {
|
|
7757
|
-
const val = suggestion.getValue();
|
|
7758
|
-
if (val instanceof Date) {
|
|
7759
|
-
ctx.onSelect(val);
|
|
7760
|
-
} else {
|
|
7761
|
-
ctx.onSelect(val.from);
|
|
7762
|
-
if (val.to) {
|
|
7763
|
-
setTimeout(() => ctx.onSelect(val.to), 0);
|
|
7764
|
-
}
|
|
7765
|
-
}
|
|
7766
|
-
};
|
|
7767
|
-
const formatSuggestionDate = (suggestion) => {
|
|
7768
|
-
const val = suggestion.getValue();
|
|
7769
|
-
if (val instanceof Date) {
|
|
7770
|
-
return formatDate(val);
|
|
7771
|
-
}
|
|
7772
|
-
const from = formatDate(val.from);
|
|
7773
|
-
const to = val.to ? formatDate(val.to) : "";
|
|
7774
|
-
return to ? `${from} - ${to}` : from;
|
|
7775
|
-
};
|
|
7776
|
-
return /* @__PURE__ */ jsxs51(
|
|
7777
|
-
"div",
|
|
7778
|
-
{
|
|
7779
|
-
ref,
|
|
7780
|
-
className: cn(
|
|
7781
|
-
"flex flex-col border-l border-datepicker-border self-stretch shrink-0",
|
|
7782
|
-
className
|
|
7783
|
-
),
|
|
7784
|
-
...props,
|
|
7785
|
-
children: [
|
|
7786
|
-
/* @__PURE__ */ jsx57("div", { className: "pt-lg px-base", children: /* @__PURE__ */ jsx57("div", { className: "flex items-center p-base rounded-base", children: /* @__PURE__ */ jsx57("span", { className: "flex-1 text-xs font-semibold leading-xs text-datepicker-suggestion-heading uppercase truncate", children: "Suggestions" }) }) }),
|
|
7787
|
-
/* @__PURE__ */ jsx57("div", { className: "flex flex-1 flex-col p-base min-w-[222px]", children: suggestions.map((suggestion, i) => /* @__PURE__ */ jsxs51(
|
|
7788
|
-
"button",
|
|
7789
|
-
{
|
|
7790
|
-
type: "button",
|
|
7791
|
-
onClick: () => handleClick(suggestion),
|
|
7792
|
-
className: "flex items-center gap-sm p-base rounded-base hover:bg-datepicker-suggestion-hover transition-colors cursor-pointer text-left",
|
|
7793
|
-
children: [
|
|
7794
|
-
/* @__PURE__ */ jsx57("span", { className: "text-sm font-regular leading-sm text-datepicker-suggestion-text truncate shrink-0", children: suggestion.label }),
|
|
7795
|
-
/* @__PURE__ */ jsx57("span", { className: "text-xs font-regular leading-xs text-datepicker-suggestion-date truncate", children: formatSuggestionDate(suggestion) })
|
|
7796
|
-
]
|
|
7797
|
-
},
|
|
7798
|
-
i
|
|
7799
|
-
)) })
|
|
7800
|
-
]
|
|
7801
|
-
}
|
|
7802
|
-
);
|
|
7803
|
-
}
|
|
7804
|
-
);
|
|
7805
|
-
DatePickerSuggestions.displayName = "DatePickerSuggestions";
|
|
7806
|
-
var DatePickerFooter = React50.forwardRef(
|
|
7807
|
-
({ className, children, ...props }, ref) => /* @__PURE__ */ jsx57(
|
|
7808
|
-
"div",
|
|
7809
|
-
{
|
|
7810
|
-
ref,
|
|
7811
|
-
className: cn(
|
|
7812
|
-
"flex items-center justify-between p-lg",
|
|
7813
|
-
"border-t border-datepicker-footer-border",
|
|
7814
|
-
"bg-datepicker-bg",
|
|
7815
|
-
className
|
|
7816
8577
|
),
|
|
7817
|
-
|
|
7818
|
-
|
|
7819
|
-
|
|
7820
|
-
|
|
7821
|
-
|
|
7822
|
-
|
|
7823
|
-
var
|
|
7824
|
-
|
|
7825
|
-
|
|
7826
|
-
|
|
7827
|
-
|
|
7828
|
-
|
|
7829
|
-
|
|
7830
|
-
|
|
7831
|
-
}
|
|
7832
|
-
)
|
|
7833
|
-
);
|
|
7834
|
-
DatePickerPanel.displayName = "DatePickerPanel";
|
|
7835
|
-
var DatePickerRoot = PopoverPrimitive12.Root;
|
|
7836
|
-
var DatePickerTrigger = PopoverPrimitive12.Trigger;
|
|
7837
|
-
var DatePickerPopover = React50.forwardRef(({ className, sideOffset = 4, align = "start", children, ...props }, ref) => /* @__PURE__ */ jsx57(PopoverPrimitive12.Portal, { children: /* @__PURE__ */ jsx57(
|
|
7838
|
-
PopoverPrimitive12.Content,
|
|
7839
|
-
{
|
|
7840
|
-
ref,
|
|
7841
|
-
sideOffset,
|
|
7842
|
-
align,
|
|
7843
|
-
className: cn(
|
|
7844
|
-
"z-50",
|
|
7845
|
-
"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
|
|
7846
|
-
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
|
|
7847
|
-
"data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2",
|
|
7848
|
-
className
|
|
7849
|
-
),
|
|
7850
|
-
...props,
|
|
7851
|
-
children
|
|
7852
|
-
}
|
|
7853
|
-
) }));
|
|
7854
|
-
DatePickerPopover.displayName = "DatePickerPopover";
|
|
7855
|
-
function getDefaultSuggestions(referenceDate) {
|
|
7856
|
-
const now = referenceDate ?? /* @__PURE__ */ new Date();
|
|
7857
|
-
const today = startOfDay(now);
|
|
7858
|
-
const dayOfWeek = getWeekdayIndex(today);
|
|
7859
|
-
const startOfThisWeek = new Date(today);
|
|
7860
|
-
startOfThisWeek.setDate(today.getDate() - dayOfWeek);
|
|
7861
|
-
const endOfThisWeek = new Date(startOfThisWeek);
|
|
7862
|
-
endOfThisWeek.setDate(startOfThisWeek.getDate() + 6);
|
|
7863
|
-
const startOfThisMonth = new Date(today.getFullYear(), today.getMonth(), 1);
|
|
7864
|
-
const endOfThisMonth = new Date(
|
|
7865
|
-
today.getFullYear(),
|
|
7866
|
-
today.getMonth() + 1,
|
|
7867
|
-
0
|
|
7868
|
-
);
|
|
7869
|
-
const startOfThisYear = new Date(today.getFullYear(), 0, 1);
|
|
7870
|
-
const endOfThisYear = new Date(today.getFullYear(), 11, 31);
|
|
7871
|
-
const startOfLastWeek = new Date(startOfThisWeek);
|
|
7872
|
-
startOfLastWeek.setDate(startOfThisWeek.getDate() - 7);
|
|
7873
|
-
const endOfLastWeek = new Date(startOfThisWeek);
|
|
7874
|
-
endOfLastWeek.setDate(startOfThisWeek.getDate() - 1);
|
|
7875
|
-
const startOfLastMonth = new Date(
|
|
7876
|
-
today.getFullYear(),
|
|
7877
|
-
today.getMonth() - 1,
|
|
7878
|
-
1
|
|
7879
|
-
);
|
|
7880
|
-
const endOfLastMonth = new Date(today.getFullYear(), today.getMonth(), 0);
|
|
7881
|
-
const startOfLastYear = new Date(today.getFullYear() - 1, 0, 1);
|
|
7882
|
-
const endOfLastYear = new Date(today.getFullYear() - 1, 11, 31);
|
|
7883
|
-
return [
|
|
7884
|
-
{ label: "Today", getValue: () => today },
|
|
7885
|
-
{
|
|
7886
|
-
label: "This week",
|
|
7887
|
-
getValue: () => ({ from: startOfThisWeek, to: endOfThisWeek })
|
|
7888
|
-
},
|
|
7889
|
-
{
|
|
7890
|
-
label: "This month",
|
|
7891
|
-
getValue: () => ({ from: startOfThisMonth, to: endOfThisMonth })
|
|
7892
|
-
},
|
|
7893
|
-
{
|
|
7894
|
-
label: "This year",
|
|
7895
|
-
getValue: () => ({ from: startOfThisYear, to: endOfThisYear })
|
|
7896
|
-
},
|
|
7897
|
-
{
|
|
7898
|
-
label: "Last week",
|
|
7899
|
-
getValue: () => ({ from: startOfLastWeek, to: endOfLastWeek })
|
|
7900
|
-
},
|
|
7901
|
-
{
|
|
7902
|
-
label: "Last month",
|
|
7903
|
-
getValue: () => ({ from: startOfLastMonth, to: endOfLastMonth })
|
|
7904
|
-
},
|
|
7905
|
-
{
|
|
7906
|
-
label: "Last year",
|
|
7907
|
-
getValue: () => ({ from: startOfLastYear, to: endOfLastYear })
|
|
7908
|
-
}
|
|
7909
|
-
];
|
|
7910
|
-
}
|
|
8578
|
+
totalCount > 0 && /* @__PURE__ */ jsx59(
|
|
8579
|
+
"button",
|
|
8580
|
+
{
|
|
8581
|
+
type: "button",
|
|
8582
|
+
onClick: handleClearAll,
|
|
8583
|
+
className: "shrink-0 flex items-center gap-sm px-base py-sm min-h-[32px] max-h-[32px] rounded-md cursor-pointer transition-colors hover:bg-[var(--color-accent)]",
|
|
8584
|
+
children: isMinimal ? /* @__PURE__ */ jsx59(Icon37, { icon: faXmarkOutline5, size: "sm", className: "text-[var(--color-foreground)]" }) : /* @__PURE__ */ jsx59("span", { className: "text-sm font-semibold leading-sm text-[var(--color-foreground)]", children: "Clear" })
|
|
8585
|
+
}
|
|
8586
|
+
)
|
|
8587
|
+
] }),
|
|
8588
|
+
actions && /* @__PURE__ */ jsx59(FilterBarRight, { className: "shrink-0 -ml-2xl pl-2xl relative z-10 bg-[linear-gradient(to_right,transparent_0px,var(--filter-bar-bg,var(--color-background,#fff))_24px)]", children: actions })
|
|
8589
|
+
] });
|
|
8590
|
+
};
|
|
8591
|
+
FilterSystem.displayName = "FilterSystem";
|
|
7911
8592
|
export {
|
|
7912
8593
|
AdvancedChip,
|
|
7913
8594
|
AdvancedPopover,
|