@clyrex-digital/clyrex-controls-dev 0.8.1-dev.20260925110206 → 0.8.1-dev.20260926063530
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/DataBindingControls-VSLL4WV2.mjs +882 -0
- package/dist/DataBindingControls-Z2AHWFYX.mjs +880 -0
- package/dist/{InputControlClient-A3V5YRWH.mjs → InputControlClient-K6GXQEJD.mjs} +4 -6
- package/dist/{LinkNodeButton-WXAW3ZD6.mjs → LinkNodeButton-U6AJUMFA.mjs} +1 -1
- package/dist/{Pagination-STOHS3LO.mjs → Pagination-6R4XZLF6.mjs} +3 -5
- package/dist/{Pagination-V53JCR6P.mjs → Pagination-RMAXCIL7.mjs} +71 -27
- package/dist/{chunk-4WMSS6CE.mjs → chunk-3IMICDQR.mjs} +0 -1
- package/dist/{chunk-N57RANHY.mjs → chunk-LDS5ZLVG.mjs} +1 -1
- package/dist/{chunk-GCG4OYDJ.mjs → chunk-N3EYMPAJ.mjs} +31 -0
- package/dist/{chunk-I3ND2ZRE.mjs → chunk-Q4AFJYT5.mjs} +32 -2
- package/dist/{chunk-K6GGVJCI.mjs → chunk-RSUG2VPX.mjs} +1 -1
- package/dist/index.js +494 -116
- package/dist/index.mjs +30 -28
- package/dist/server.js +691 -2317
- package/dist/server.mjs +6 -9
- package/package.json +1 -1
- package/dist/DataBindingControls-25UC5W3R.mjs +0 -502
- package/dist/DataBindingControls-6IS5F3QX.mjs +0 -498
- package/dist/InputControlClient-NHXG4QBU.mjs +0 -1836
- package/dist/chunk-2R26M6CK.mjs +0 -30
- package/dist/chunk-6PW2RLUJ.mjs +0 -52
- package/dist/chunk-F4DNLPFN.mjs +0 -36
- package/dist/chunk-HRDHAIZF.mjs +0 -33
- package/dist/chunk-XDTWUEVR.mjs +0 -13
|
@@ -0,0 +1,882 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
"use client";
|
|
4
|
+
import {
|
|
5
|
+
Button_default
|
|
6
|
+
} from "./chunk-LSKD5U3S.mjs";
|
|
7
|
+
import "./chunk-IMNQO57B.mjs";
|
|
8
|
+
|
|
9
|
+
// src/components/pageRenderingEngine/nodes/DataBindingControls.tsx
|
|
10
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
11
|
+
import { useRouter, useSearchParams } from "next/navigation";
|
|
12
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
13
|
+
var humanize = (value) => value.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[_-]+/g, " ").trim();
|
|
14
|
+
var escapeODataString = (value) => value.replace(/'/g, "''");
|
|
15
|
+
var parseFacetSelections = (filter) => {
|
|
16
|
+
const selections = /* @__PURE__ */ new Map();
|
|
17
|
+
if (!filter || !filter.trim()) return selections;
|
|
18
|
+
const expression = /(?:^|[\s()]+(?:and[\s()]+)?)([\w./-]+)\s+eq\s+'((?:''|[^'])*)'/gi;
|
|
19
|
+
for (const match of filter.matchAll(expression)) {
|
|
20
|
+
if (match[1] && match[2] !== void 0) {
|
|
21
|
+
selections.set(match[1].trim(), match[2].replace(/''/g, "'"));
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return selections;
|
|
25
|
+
};
|
|
26
|
+
var buildFacetFilter = (selections) => Array.from(selections.entries()).map(([field, value]) => `${field} eq '${escapeODataString(value)}'`).join(" and ");
|
|
27
|
+
var parseODataSearch = (value) => {
|
|
28
|
+
if (!value) return "";
|
|
29
|
+
const trimmedValue = value.trim();
|
|
30
|
+
if (trimmedValue.startsWith("'") && trimmedValue.endsWith("'")) {
|
|
31
|
+
return trimmedValue.slice(1, -1).replace(/''/g, "'");
|
|
32
|
+
}
|
|
33
|
+
return trimmedValue;
|
|
34
|
+
};
|
|
35
|
+
var SearchIcon = ({ className = "" }) => /* @__PURE__ */ jsxs(
|
|
36
|
+
"svg",
|
|
37
|
+
{
|
|
38
|
+
"aria-hidden": "true",
|
|
39
|
+
className,
|
|
40
|
+
fill: "none",
|
|
41
|
+
viewBox: "0 0 24 24",
|
|
42
|
+
stroke: "currentColor",
|
|
43
|
+
strokeWidth: "2",
|
|
44
|
+
children: [
|
|
45
|
+
/* @__PURE__ */ jsx("circle", { cx: "11", cy: "11", r: "7" }),
|
|
46
|
+
/* @__PURE__ */ jsx("path", { strokeLinecap: "round", d: "m20 20-4-4" })
|
|
47
|
+
]
|
|
48
|
+
}
|
|
49
|
+
);
|
|
50
|
+
var ResetIcon = ({ className = "" }) => /* @__PURE__ */ jsxs(
|
|
51
|
+
"svg",
|
|
52
|
+
{
|
|
53
|
+
"aria-hidden": "true",
|
|
54
|
+
className,
|
|
55
|
+
fill: "none",
|
|
56
|
+
viewBox: "0 0 24 24",
|
|
57
|
+
stroke: "currentColor",
|
|
58
|
+
strokeWidth: "2",
|
|
59
|
+
children: [
|
|
60
|
+
/* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M4 4v6h6" }),
|
|
61
|
+
/* @__PURE__ */ jsx(
|
|
62
|
+
"path",
|
|
63
|
+
{
|
|
64
|
+
strokeLinecap: "round",
|
|
65
|
+
strokeLinejoin: "round",
|
|
66
|
+
d: "M5.5 15a8 8 0 1 0 .6-7.8L4 10"
|
|
67
|
+
}
|
|
68
|
+
)
|
|
69
|
+
]
|
|
70
|
+
}
|
|
71
|
+
);
|
|
72
|
+
var FilterSlidersIcon = ({ className = "" }) => /* @__PURE__ */ jsxs(
|
|
73
|
+
"svg",
|
|
74
|
+
{
|
|
75
|
+
"aria-hidden": "true",
|
|
76
|
+
className,
|
|
77
|
+
fill: "none",
|
|
78
|
+
viewBox: "0 0 24 24",
|
|
79
|
+
stroke: "currentColor",
|
|
80
|
+
strokeWidth: "2",
|
|
81
|
+
children: [
|
|
82
|
+
/* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M3 4h18M3 12h18M3 20h18" }),
|
|
83
|
+
/* @__PURE__ */ jsx("circle", { cx: "8", cy: "4", r: "2", fill: "currentColor" }),
|
|
84
|
+
/* @__PURE__ */ jsx("circle", { cx: "16", cy: "12", r: "2", fill: "currentColor" }),
|
|
85
|
+
/* @__PURE__ */ jsx("circle", { cx: "10", cy: "20", r: "2", fill: "currentColor" })
|
|
86
|
+
]
|
|
87
|
+
}
|
|
88
|
+
);
|
|
89
|
+
var ChevronDownIcon = ({ className = "" }) => /* @__PURE__ */ jsx(
|
|
90
|
+
"svg",
|
|
91
|
+
{
|
|
92
|
+
"aria-hidden": "true",
|
|
93
|
+
className,
|
|
94
|
+
fill: "none",
|
|
95
|
+
viewBox: "0 0 24 24",
|
|
96
|
+
stroke: "currentColor",
|
|
97
|
+
strokeWidth: "2",
|
|
98
|
+
children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "m19 9-7 7-7-7" })
|
|
99
|
+
}
|
|
100
|
+
);
|
|
101
|
+
var CheckIcon = ({ className = "" }) => /* @__PURE__ */ jsx(
|
|
102
|
+
"svg",
|
|
103
|
+
{
|
|
104
|
+
"aria-hidden": "true",
|
|
105
|
+
className,
|
|
106
|
+
fill: "none",
|
|
107
|
+
viewBox: "0 0 24 24",
|
|
108
|
+
stroke: "currentColor",
|
|
109
|
+
strokeWidth: "2.5",
|
|
110
|
+
children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M5 13l4 4L19 7" })
|
|
111
|
+
}
|
|
112
|
+
);
|
|
113
|
+
var CloseIcon = ({ className = "" }) => /* @__PURE__ */ jsx(
|
|
114
|
+
"svg",
|
|
115
|
+
{
|
|
116
|
+
"aria-hidden": "true",
|
|
117
|
+
className,
|
|
118
|
+
fill: "none",
|
|
119
|
+
viewBox: "0 0 24 24",
|
|
120
|
+
stroke: "currentColor",
|
|
121
|
+
strokeWidth: "2",
|
|
122
|
+
children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" })
|
|
123
|
+
}
|
|
124
|
+
);
|
|
125
|
+
var MapPinIcon = ({ className = "" }) => /* @__PURE__ */ jsxs(
|
|
126
|
+
"svg",
|
|
127
|
+
{
|
|
128
|
+
"aria-hidden": "true",
|
|
129
|
+
className,
|
|
130
|
+
fill: "none",
|
|
131
|
+
viewBox: "0 0 24 24",
|
|
132
|
+
stroke: "currentColor",
|
|
133
|
+
strokeWidth: "2",
|
|
134
|
+
children: [
|
|
135
|
+
/* @__PURE__ */ jsx(
|
|
136
|
+
"path",
|
|
137
|
+
{
|
|
138
|
+
strokeLinecap: "round",
|
|
139
|
+
strokeLinejoin: "round",
|
|
140
|
+
d: "M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z"
|
|
141
|
+
}
|
|
142
|
+
),
|
|
143
|
+
/* @__PURE__ */ jsx(
|
|
144
|
+
"path",
|
|
145
|
+
{
|
|
146
|
+
strokeLinecap: "round",
|
|
147
|
+
strokeLinejoin: "round",
|
|
148
|
+
d: "M15 11a3 3 0 11-6 0 3 3 0 016 0z"
|
|
149
|
+
}
|
|
150
|
+
)
|
|
151
|
+
]
|
|
152
|
+
}
|
|
153
|
+
);
|
|
154
|
+
var BriefcaseIcon = ({ className = "" }) => /* @__PURE__ */ jsx(
|
|
155
|
+
"svg",
|
|
156
|
+
{
|
|
157
|
+
"aria-hidden": "true",
|
|
158
|
+
className,
|
|
159
|
+
fill: "none",
|
|
160
|
+
viewBox: "0 0 24 24",
|
|
161
|
+
stroke: "currentColor",
|
|
162
|
+
strokeWidth: "2",
|
|
163
|
+
children: /* @__PURE__ */ jsx(
|
|
164
|
+
"path",
|
|
165
|
+
{
|
|
166
|
+
strokeLinecap: "round",
|
|
167
|
+
strokeLinejoin: "round",
|
|
168
|
+
d: "M21 13.255A23.931 23.931 0 0112 15c-3.183 0-6.22-.62-9-1.745M16 6V4a2 2 0 00-2-2h-4a2 2 0 00-2 2v2m4 6h.01M5 20h14a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"
|
|
169
|
+
}
|
|
170
|
+
)
|
|
171
|
+
}
|
|
172
|
+
);
|
|
173
|
+
var FileTextIcon = ({ className = "" }) => /* @__PURE__ */ jsx(
|
|
174
|
+
"svg",
|
|
175
|
+
{
|
|
176
|
+
"aria-hidden": "true",
|
|
177
|
+
className,
|
|
178
|
+
fill: "none",
|
|
179
|
+
viewBox: "0 0 24 24",
|
|
180
|
+
stroke: "currentColor",
|
|
181
|
+
strokeWidth: "2",
|
|
182
|
+
children: /* @__PURE__ */ jsx(
|
|
183
|
+
"path",
|
|
184
|
+
{
|
|
185
|
+
strokeLinecap: "round",
|
|
186
|
+
strokeLinejoin: "round",
|
|
187
|
+
d: "M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"
|
|
188
|
+
}
|
|
189
|
+
)
|
|
190
|
+
}
|
|
191
|
+
);
|
|
192
|
+
var TagIcon = ({ className = "" }) => /* @__PURE__ */ jsx(
|
|
193
|
+
"svg",
|
|
194
|
+
{
|
|
195
|
+
"aria-hidden": "true",
|
|
196
|
+
className,
|
|
197
|
+
fill: "none",
|
|
198
|
+
viewBox: "0 0 24 24",
|
|
199
|
+
stroke: "currentColor",
|
|
200
|
+
strokeWidth: "2",
|
|
201
|
+
children: /* @__PURE__ */ jsx(
|
|
202
|
+
"path",
|
|
203
|
+
{
|
|
204
|
+
strokeLinecap: "round",
|
|
205
|
+
strokeLinejoin: "round",
|
|
206
|
+
d: "M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z"
|
|
207
|
+
}
|
|
208
|
+
)
|
|
209
|
+
}
|
|
210
|
+
);
|
|
211
|
+
var getCategoryIcon = (category) => {
|
|
212
|
+
const lower = category.toLowerCase();
|
|
213
|
+
if (lower.includes("location") || lower.includes("city") || lower.includes("country") || lower.includes("state") || lower.includes("address")) {
|
|
214
|
+
return /* @__PURE__ */ jsx(MapPinIcon, { className: "h-4 w-4" });
|
|
215
|
+
}
|
|
216
|
+
if (lower.includes("type") || lower.includes("work") || lower.includes("employment") || lower.includes("experience")) {
|
|
217
|
+
return /* @__PURE__ */ jsx(BriefcaseIcon, { className: "h-4 w-4" });
|
|
218
|
+
}
|
|
219
|
+
if (lower.includes("department") || lower.includes("category") || lower.includes("role") || lower.includes("industry")) {
|
|
220
|
+
return /* @__PURE__ */ jsx(FileTextIcon, { className: "h-4 w-4" });
|
|
221
|
+
}
|
|
222
|
+
return /* @__PURE__ */ jsx(TagIcon, { className: "h-4 w-4" });
|
|
223
|
+
};
|
|
224
|
+
var normalizeSortOption = (option) => {
|
|
225
|
+
const direction = option.direction.trim();
|
|
226
|
+
const title = option.title || humanize(option.name);
|
|
227
|
+
return {
|
|
228
|
+
label: title,
|
|
229
|
+
value: [option.name, direction].filter(Boolean).join(" ")
|
|
230
|
+
};
|
|
231
|
+
};
|
|
232
|
+
var DataBindingControls = ({
|
|
233
|
+
path,
|
|
234
|
+
query,
|
|
235
|
+
facets,
|
|
236
|
+
sortOptions,
|
|
237
|
+
showFacets,
|
|
238
|
+
showSortOptions,
|
|
239
|
+
showSearchBar,
|
|
240
|
+
mode = "toolbar"
|
|
241
|
+
}) => {
|
|
242
|
+
const router = useRouter();
|
|
243
|
+
const searchParams = useSearchParams();
|
|
244
|
+
const [collapsedCategories, setCollapsedCategories] = useState({});
|
|
245
|
+
const [isSortOpen, setIsSortOpen] = useState(false);
|
|
246
|
+
const [isMobileFiltersOpen, setIsMobileFiltersOpen] = useState(false);
|
|
247
|
+
const [facetCategorySearch, setFacetCategorySearch] = useState({});
|
|
248
|
+
const desktopSortDropdownRef = useRef(null);
|
|
249
|
+
const mobileSortDropdownRef = useRef(null);
|
|
250
|
+
useEffect(() => {
|
|
251
|
+
const handleClickOutside = (event) => {
|
|
252
|
+
const target = event.target;
|
|
253
|
+
const clickedInsideDesktop = desktopSortDropdownRef.current?.contains(target);
|
|
254
|
+
const clickedInsideMobile = mobileSortDropdownRef.current?.contains(target);
|
|
255
|
+
if (!clickedInsideDesktop && !clickedInsideMobile) {
|
|
256
|
+
setIsSortOpen(false);
|
|
257
|
+
}
|
|
258
|
+
};
|
|
259
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
260
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
261
|
+
}, []);
|
|
262
|
+
const toggleCategory = (field) => {
|
|
263
|
+
setCollapsedCategories((prev) => ({
|
|
264
|
+
...prev,
|
|
265
|
+
[field]: !prev[field]
|
|
266
|
+
}));
|
|
267
|
+
};
|
|
268
|
+
const searchParamsFilter = searchParams?.get("$filter") ?? searchParams?.get("filter");
|
|
269
|
+
const searchParamsSort = searchParams?.get("$orderby") ?? searchParams?.get("orderBy");
|
|
270
|
+
const searchParamsSearch = searchParams?.get("$search");
|
|
271
|
+
const currentFilter = searchParamsFilter !== void 0 && searchParamsFilter !== null ? searchParamsFilter : query?.["$filter"] ?? query?.filter ?? "";
|
|
272
|
+
const currentSort = searchParamsSort !== void 0 && searchParamsSort !== null ? searchParamsSort : query?.["$orderby"] ?? query?.orderBy ?? "";
|
|
273
|
+
const currentSearch = parseODataSearch(
|
|
274
|
+
searchParamsSearch !== void 0 && searchParamsSearch !== null ? searchParamsSearch : query?.["$search"]
|
|
275
|
+
);
|
|
276
|
+
const [searchText, setSearchText] = useState(currentSearch);
|
|
277
|
+
useEffect(() => {
|
|
278
|
+
setSearchText(currentSearch);
|
|
279
|
+
}, [currentSearch]);
|
|
280
|
+
const selectedFacetValues = useMemo(
|
|
281
|
+
() => parseFacetSelections(currentFilter),
|
|
282
|
+
[currentFilter]
|
|
283
|
+
);
|
|
284
|
+
useEffect(() => {
|
|
285
|
+
if (isMobileFiltersOpen) {
|
|
286
|
+
document.body.style.overflow = "hidden";
|
|
287
|
+
} else {
|
|
288
|
+
document.body.style.overflow = "";
|
|
289
|
+
}
|
|
290
|
+
return () => {
|
|
291
|
+
document.body.style.overflow = "";
|
|
292
|
+
};
|
|
293
|
+
}, [isMobileFiltersOpen]);
|
|
294
|
+
const activeFacets = useMemo(() => {
|
|
295
|
+
const facetMap = /* @__PURE__ */ new Map();
|
|
296
|
+
if (facets) {
|
|
297
|
+
Object.entries(facets).forEach(([field, values]) => {
|
|
298
|
+
if (!Array.isArray(values)) return;
|
|
299
|
+
const filteredValues = values.filter(
|
|
300
|
+
(item) => item.count > 0 || selectedFacetValues.get(field) === item.value
|
|
301
|
+
);
|
|
302
|
+
if (filteredValues.length > 0) {
|
|
303
|
+
facetMap.set(field, filteredValues);
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
selectedFacetValues.forEach((val, field) => {
|
|
308
|
+
if (!facetMap.has(field)) {
|
|
309
|
+
facetMap.set(field, [{ value: val, count: 0 }]);
|
|
310
|
+
} else {
|
|
311
|
+
const existing = facetMap.get(field);
|
|
312
|
+
if (!existing.some((item) => item.value === val)) {
|
|
313
|
+
existing.push({ value: val, count: 0 });
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
});
|
|
317
|
+
return Array.from(facetMap.entries());
|
|
318
|
+
}, [facets, selectedFacetValues]);
|
|
319
|
+
const normalizedSortOptions = useMemo(
|
|
320
|
+
() => (sortOptions ?? []).filter((option) => option?.name && option?.direction).map(normalizeSortOption).filter((option) => option.value),
|
|
321
|
+
[sortOptions]
|
|
322
|
+
);
|
|
323
|
+
const selectedSortOption = useMemo(() => {
|
|
324
|
+
if (!normalizedSortOptions.length) return null;
|
|
325
|
+
const trimmedCurrentSort = currentSort.trim().toLowerCase();
|
|
326
|
+
if (!trimmedCurrentSort) return normalizedSortOptions[0];
|
|
327
|
+
return normalizedSortOptions.find(
|
|
328
|
+
(opt) => opt.value.trim().toLowerCase() === trimmedCurrentSort
|
|
329
|
+
) || normalizedSortOptions[0];
|
|
330
|
+
}, [normalizedSortOptions, currentSort]);
|
|
331
|
+
const selectedSortLabel = selectedSortOption?.label || "";
|
|
332
|
+
const getQueryUrl = useCallback(
|
|
333
|
+
(updates) => {
|
|
334
|
+
const initialParams = searchParams ? searchParams.toString() : "";
|
|
335
|
+
const params = new URLSearchParams(initialParams || query || {});
|
|
336
|
+
Object.entries(updates).forEach(([key, value]) => {
|
|
337
|
+
if (value) {
|
|
338
|
+
params.set(key, value);
|
|
339
|
+
} else {
|
|
340
|
+
params.delete(key);
|
|
341
|
+
}
|
|
342
|
+
});
|
|
343
|
+
params.delete("$skip");
|
|
344
|
+
params.delete("skip");
|
|
345
|
+
const queryString = Array.from(params.entries()).map(([key, value]) => `${key}=${encodeURIComponent(value)}`).join("&");
|
|
346
|
+
return queryString ? `${path}?${queryString}` : path;
|
|
347
|
+
},
|
|
348
|
+
[path, query, searchParams]
|
|
349
|
+
);
|
|
350
|
+
const navigateWithoutReload = useCallback(
|
|
351
|
+
(url) => {
|
|
352
|
+
if (typeof window !== "undefined") {
|
|
353
|
+
const targetUrl = new URL(url, window.location.origin);
|
|
354
|
+
if (targetUrl.pathname === window.location.pathname && decodeURIComponent(targetUrl.search) === decodeURIComponent(window.location.search)) {
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
router.push(url, { scroll: false });
|
|
359
|
+
},
|
|
360
|
+
[router]
|
|
361
|
+
);
|
|
362
|
+
const handleSelectSort = useCallback(
|
|
363
|
+
(sortValue) => {
|
|
364
|
+
setIsSortOpen(false);
|
|
365
|
+
navigateWithoutReload(
|
|
366
|
+
getQueryUrl({
|
|
367
|
+
$orderby: sortValue || void 0,
|
|
368
|
+
orderBy: void 0
|
|
369
|
+
})
|
|
370
|
+
);
|
|
371
|
+
},
|
|
372
|
+
[getQueryUrl, navigateWithoutReload]
|
|
373
|
+
);
|
|
374
|
+
const getFacetUrl = (field, value) => {
|
|
375
|
+
const updatedSelections = new Map(selectedFacetValues);
|
|
376
|
+
if (value) {
|
|
377
|
+
if (updatedSelections.get(field) === value) {
|
|
378
|
+
updatedSelections.delete(field);
|
|
379
|
+
} else {
|
|
380
|
+
updatedSelections.set(field, value);
|
|
381
|
+
}
|
|
382
|
+
} else {
|
|
383
|
+
updatedSelections.delete(field);
|
|
384
|
+
}
|
|
385
|
+
const updatedFilter = buildFacetFilter(updatedSelections);
|
|
386
|
+
return getQueryUrl({
|
|
387
|
+
$filter: updatedFilter || void 0,
|
|
388
|
+
filter: void 0
|
|
389
|
+
});
|
|
390
|
+
};
|
|
391
|
+
const clearFacetField = (field) => {
|
|
392
|
+
const updatedSelections = new Map(selectedFacetValues);
|
|
393
|
+
updatedSelections.delete(field);
|
|
394
|
+
const updatedFilter = buildFacetFilter(updatedSelections);
|
|
395
|
+
navigateWithoutReload(
|
|
396
|
+
getQueryUrl({
|
|
397
|
+
$filter: updatedFilter || void 0,
|
|
398
|
+
filter: void 0
|
|
399
|
+
})
|
|
400
|
+
);
|
|
401
|
+
};
|
|
402
|
+
const handleSearch = useCallback(async () => {
|
|
403
|
+
const trimmedSearchText = searchText.trim();
|
|
404
|
+
if (trimmedSearchText === currentSearch.trim()) {
|
|
405
|
+
return { isSuccessful: true };
|
|
406
|
+
}
|
|
407
|
+
navigateWithoutReload(
|
|
408
|
+
getQueryUrl({
|
|
409
|
+
"$search": trimmedSearchText || void 0
|
|
410
|
+
})
|
|
411
|
+
);
|
|
412
|
+
return { isSuccessful: true };
|
|
413
|
+
}, [currentSearch, getQueryUrl, navigateWithoutReload, searchText]);
|
|
414
|
+
const handleClearAll = useCallback(async () => {
|
|
415
|
+
navigateWithoutReload(
|
|
416
|
+
getQueryUrl({
|
|
417
|
+
$filter: void 0,
|
|
418
|
+
filter: void 0,
|
|
419
|
+
$orderby: void 0,
|
|
420
|
+
orderBy: void 0
|
|
421
|
+
})
|
|
422
|
+
);
|
|
423
|
+
return { isSuccessful: true };
|
|
424
|
+
}, [getQueryUrl, navigateWithoutReload]);
|
|
425
|
+
const hasFacetControls = Boolean(showFacets && (activeFacets.length > 0 || selectedFacetValues.size > 0));
|
|
426
|
+
const hasSortControls = Boolean(showSortOptions && normalizedSortOptions.length > 0);
|
|
427
|
+
const hasActiveFiltersOrSort = Boolean(
|
|
428
|
+
currentFilter.trim() || currentSort.trim()
|
|
429
|
+
);
|
|
430
|
+
const selectedFacetCount = selectedFacetValues.size;
|
|
431
|
+
const shouldShowToolbarClearAll = hasActiveFiltersOrSort && !hasFacetControls;
|
|
432
|
+
const shouldShowToolbar = mode === "toolbar" && (showSearchBar || hasSortControls || showFacets || shouldShowToolbarClearAll);
|
|
433
|
+
const shouldShowFacets = mode === "facets" && (hasFacetControls || showFacets && activeFacets.length > 0);
|
|
434
|
+
if (!shouldShowToolbar && !shouldShowFacets) {
|
|
435
|
+
return null;
|
|
436
|
+
}
|
|
437
|
+
const renderFacetItems = (field, values) => /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-1 pt-1 pb-1", children: values.map((facet) => {
|
|
438
|
+
const isSelected = selectedFacetValues.get(field) === facet.value;
|
|
439
|
+
return /* @__PURE__ */ jsxs(
|
|
440
|
+
"button",
|
|
441
|
+
{
|
|
442
|
+
type: "button",
|
|
443
|
+
onClick: () => navigateWithoutReload(getFacetUrl(field, facet.value)),
|
|
444
|
+
"aria-pressed": isSelected,
|
|
445
|
+
className: `group flex w-full cursor-pointer items-center justify-between gap-2.5 rounded-md px-2 py-1.5 text-left text-sm transition-all duration-150 ease-out focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary-base ${isSelected ? "bg-neutral-soft font-medium border border-neutral-soft" : "hover:bg-neutral-weak border border-transparent"}`,
|
|
446
|
+
children: [
|
|
447
|
+
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center gap-2.5", children: [
|
|
448
|
+
/* @__PURE__ */ jsx(
|
|
449
|
+
"span",
|
|
450
|
+
{
|
|
451
|
+
className: `flex h-4 w-4 shrink-0 items-center justify-center rounded-[3px] border transition-colors duration-150 ${isSelected ? "bg-primary-base border-primary-base" : " group-hover:border-neutral-strong bg-default border-neutral-soft"}`,
|
|
452
|
+
children: isSelected && /* @__PURE__ */ jsx(CheckIcon, { className: "h-3 w-3" })
|
|
453
|
+
}
|
|
454
|
+
),
|
|
455
|
+
/* @__PURE__ */ jsx("span", { className: "leading-snug break-words", children: facet.value })
|
|
456
|
+
] }),
|
|
457
|
+
/* @__PURE__ */ jsx(
|
|
458
|
+
"span",
|
|
459
|
+
{
|
|
460
|
+
className: `shrink-0 rounded px-1.5 py-0.5 text-xs transition-colors ml-2 ${isSelected ? "bg-neutral-weak font-semibold" : "bg-neutral-weak font-normal"}`,
|
|
461
|
+
children: facet.count
|
|
462
|
+
}
|
|
463
|
+
)
|
|
464
|
+
]
|
|
465
|
+
},
|
|
466
|
+
`${field}-${facet.value}`
|
|
467
|
+
);
|
|
468
|
+
}) });
|
|
469
|
+
return /* @__PURE__ */ jsxs(
|
|
470
|
+
"div",
|
|
471
|
+
{
|
|
472
|
+
className: mode === "toolbar" ? "my-4 sm:my-6" : "flex flex-col rounded-md border border-neutral-soft bg-default p-4 shadow-sm",
|
|
473
|
+
children: [
|
|
474
|
+
shouldShowToolbar && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
475
|
+
/* @__PURE__ */ jsxs("div", { className: "hidden lg:flex lg:items-center lg:justify-between lg:gap-4", children: [
|
|
476
|
+
showSearchBar && /* @__PURE__ */ jsxs(
|
|
477
|
+
"form",
|
|
478
|
+
{
|
|
479
|
+
role: "search",
|
|
480
|
+
className: "flex w-full items-center gap-2 md:min-w-0 md:flex-1",
|
|
481
|
+
onSubmit: (event) => {
|
|
482
|
+
event.preventDefault();
|
|
483
|
+
void handleSearch();
|
|
484
|
+
},
|
|
485
|
+
children: [
|
|
486
|
+
/* @__PURE__ */ jsxs("div", { className: "relative min-w-0 flex-1", children: [
|
|
487
|
+
/* @__PURE__ */ jsx(SearchIcon, { className: "pointer-events-none absolute left-3.5 top-1/2 z-10 h-4 w-4 -translate-y-1/2 opacity-60" }),
|
|
488
|
+
/* @__PURE__ */ jsx(
|
|
489
|
+
"input",
|
|
490
|
+
{
|
|
491
|
+
type: "text",
|
|
492
|
+
name: "searchText",
|
|
493
|
+
value: searchText,
|
|
494
|
+
onChange: (e) => setSearchText(e.target.value),
|
|
495
|
+
placeholder: "Search discussions, topics, or keywords...",
|
|
496
|
+
className: "h-10 w-full rounded-md border border-neutral-soft bg-default py-2 pl-10 pr-4 text-sm shadow-sm transition-colors focus:border-primary-base focus:outline-none focus:ring-1 focus:ring-primary-base"
|
|
497
|
+
}
|
|
498
|
+
)
|
|
499
|
+
] }),
|
|
500
|
+
/* @__PURE__ */ jsxs(
|
|
501
|
+
Button_default,
|
|
502
|
+
{
|
|
503
|
+
ButtonType: "Primary" /* Solid */,
|
|
504
|
+
onClick: handleSearch,
|
|
505
|
+
className: "!h-10 !rounded-md !px-5 !py-0 flex items-center justify-center gap-1.5 shrink-0",
|
|
506
|
+
children: [
|
|
507
|
+
/* @__PURE__ */ jsx(SearchIcon, { className: "h-4 w-4" }),
|
|
508
|
+
/* @__PURE__ */ jsx("span", { children: "Search" })
|
|
509
|
+
]
|
|
510
|
+
}
|
|
511
|
+
)
|
|
512
|
+
]
|
|
513
|
+
}
|
|
514
|
+
),
|
|
515
|
+
hasSortControls && /* @__PURE__ */ jsxs("div", { className: "relative shrink-0", ref: desktopSortDropdownRef, children: [
|
|
516
|
+
/* @__PURE__ */ jsxs(
|
|
517
|
+
"button",
|
|
518
|
+
{
|
|
519
|
+
type: "button",
|
|
520
|
+
onClick: () => setIsSortOpen((prev) => !prev),
|
|
521
|
+
"aria-expanded": isSortOpen,
|
|
522
|
+
className: "inline-flex h-10 items-center justify-between gap-2.5 rounded-md border border-neutral-soft bg-default px-3.5 text-sm font-normal shadow-sm transition-all hover:bg-neutral-weak focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-base cursor-pointer whitespace-nowrap",
|
|
523
|
+
children: [
|
|
524
|
+
/* @__PURE__ */ jsxs("span", { className: "whitespace-nowrap", children: [
|
|
525
|
+
/* @__PURE__ */ jsx("span", { className: "opacity-70", children: "Sort by: " }),
|
|
526
|
+
/* @__PURE__ */ jsx("span", { className: "font-semibold", children: selectedSortLabel })
|
|
527
|
+
] }),
|
|
528
|
+
/* @__PURE__ */ jsx(
|
|
529
|
+
ChevronDownIcon,
|
|
530
|
+
{
|
|
531
|
+
className: `h-4 w-4 shrink-0 transition-transform duration-200 ${isSortOpen ? "rotate-180" : ""}`
|
|
532
|
+
}
|
|
533
|
+
)
|
|
534
|
+
]
|
|
535
|
+
}
|
|
536
|
+
),
|
|
537
|
+
isSortOpen && /* @__PURE__ */ jsx("div", { className: "absolute right-0 z-50 mt-1.5 w-max min-w-full max-h-80 overflow-y-auto rounded-md border border-neutral-soft bg-default p-1 shadow-lg", children: normalizedSortOptions.map((option) => {
|
|
538
|
+
const isSelected = selectedSortOption?.value === option.value;
|
|
539
|
+
return /* @__PURE__ */ jsxs(
|
|
540
|
+
"button",
|
|
541
|
+
{
|
|
542
|
+
type: "button",
|
|
543
|
+
onClick: () => handleSelectSort(option.value),
|
|
544
|
+
className: `flex w-full items-center justify-between gap-4 rounded-md px-3 py-1.5 text-left text-sm transition-colors cursor-pointer whitespace-nowrap ${isSelected ? "bg-primary-base font-semibold" : "hover:bg-neutral-soft font-normal"}`,
|
|
545
|
+
children: [
|
|
546
|
+
/* @__PURE__ */ jsx("span", { className: "whitespace-nowrap", children: option.label }),
|
|
547
|
+
isSelected && /* @__PURE__ */ jsx(CheckIcon, { className: "h-4 w-4 shrink-0" })
|
|
548
|
+
]
|
|
549
|
+
},
|
|
550
|
+
option.value
|
|
551
|
+
);
|
|
552
|
+
}) })
|
|
553
|
+
] })
|
|
554
|
+
] }),
|
|
555
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2.5 lg:hidden", children: [
|
|
556
|
+
showSearchBar && /* @__PURE__ */ jsxs(
|
|
557
|
+
"form",
|
|
558
|
+
{
|
|
559
|
+
role: "search",
|
|
560
|
+
className: "relative w-full",
|
|
561
|
+
onSubmit: (event) => {
|
|
562
|
+
event.preventDefault();
|
|
563
|
+
void handleSearch();
|
|
564
|
+
},
|
|
565
|
+
children: [
|
|
566
|
+
/* @__PURE__ */ jsx(SearchIcon, { className: "pointer-events-none absolute left-3.5 top-1/2 z-10 h-4 w-4 -translate-y-1/2 opacity-50" }),
|
|
567
|
+
/* @__PURE__ */ jsx(
|
|
568
|
+
"input",
|
|
569
|
+
{
|
|
570
|
+
type: "text",
|
|
571
|
+
name: "searchTextMobile",
|
|
572
|
+
value: searchText,
|
|
573
|
+
onChange: (e) => setSearchText(e.target.value),
|
|
574
|
+
placeholder: "Search jobs, skills, or keywords...",
|
|
575
|
+
className: "h-11 w-full rounded-md border border-neutral-soft bg-default py-2.5 pl-10 pr-4 text-sm shadow-sm transition-colors focus:border-primary-base focus:outline-none focus:ring-1 focus:ring-primary-base"
|
|
576
|
+
}
|
|
577
|
+
)
|
|
578
|
+
]
|
|
579
|
+
}
|
|
580
|
+
),
|
|
581
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2.5 pt-0.5", children: [
|
|
582
|
+
showFacets && /* @__PURE__ */ jsxs(
|
|
583
|
+
"button",
|
|
584
|
+
{
|
|
585
|
+
type: "button",
|
|
586
|
+
onClick: () => setIsMobileFiltersOpen(true),
|
|
587
|
+
className: "inline-flex h-10 items-center justify-center gap-2 rounded-md border border-neutral-soft bg-default px-3.5 text-sm font-medium shadow-sm transition-all hover:bg-neutral-weak cursor-pointer active:scale-95",
|
|
588
|
+
children: [
|
|
589
|
+
/* @__PURE__ */ jsx(FilterSlidersIcon, { className: "h-4 w-4" }),
|
|
590
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
591
|
+
"Filters",
|
|
592
|
+
selectedFacetCount > 0 ? ` (${selectedFacetCount})` : ""
|
|
593
|
+
] }),
|
|
594
|
+
selectedFacetCount > 0 && /* @__PURE__ */ jsxs("span", { className: "relative flex h-2 w-2", children: [
|
|
595
|
+
/* @__PURE__ */ jsx("span", { className: "animate-ping absolute inline-flex h-full w-full rounded-full bg-primary-base opacity-75" }),
|
|
596
|
+
/* @__PURE__ */ jsx("span", { className: "relative inline-flex rounded-full h-2 w-2 bg-primary-base" })
|
|
597
|
+
] })
|
|
598
|
+
]
|
|
599
|
+
}
|
|
600
|
+
),
|
|
601
|
+
hasSortControls && /* @__PURE__ */ jsxs("div", { className: "relative shrink-0 ml-auto", ref: mobileSortDropdownRef, children: [
|
|
602
|
+
/* @__PURE__ */ jsxs(
|
|
603
|
+
"button",
|
|
604
|
+
{
|
|
605
|
+
type: "button",
|
|
606
|
+
onClick: () => setIsSortOpen((prev) => !prev),
|
|
607
|
+
"aria-expanded": isSortOpen,
|
|
608
|
+
className: "inline-flex h-10 items-center justify-between gap-2 rounded-md border border-neutral-soft bg-default px-3.5 text-sm font-medium shadow-sm transition-all hover:bg-neutral-weak cursor-pointer whitespace-nowrap",
|
|
609
|
+
children: [
|
|
610
|
+
/* @__PURE__ */ jsx("span", { className: "whitespace-nowrap font-medium", children: selectedSortLabel }),
|
|
611
|
+
/* @__PURE__ */ jsx(
|
|
612
|
+
ChevronDownIcon,
|
|
613
|
+
{
|
|
614
|
+
className: `h-4 w-4 shrink-0 transition-transform duration-200 ${isSortOpen ? "rotate-180" : ""}`
|
|
615
|
+
}
|
|
616
|
+
)
|
|
617
|
+
]
|
|
618
|
+
}
|
|
619
|
+
),
|
|
620
|
+
isSortOpen && /* @__PURE__ */ jsx("div", { className: "absolute right-0 z-50 mt-1.5 w-max min-w-[160px] max-h-80 overflow-y-auto rounded-md border border-neutral-soft bg-default p-1 shadow-xl", children: normalizedSortOptions.map((option) => {
|
|
621
|
+
const isSelected = selectedSortOption?.value === option.value;
|
|
622
|
+
return /* @__PURE__ */ jsxs(
|
|
623
|
+
"button",
|
|
624
|
+
{
|
|
625
|
+
type: "button",
|
|
626
|
+
onClick: () => handleSelectSort(option.value),
|
|
627
|
+
className: `flex w-full items-center justify-between gap-3 rounded-md px-3 py-2 text-left text-sm transition-colors cursor-pointer whitespace-nowrap ${isSelected ? "bg-primary-base font-semibold" : "hover:bg-neutral-soft font-normal"}`,
|
|
628
|
+
children: [
|
|
629
|
+
/* @__PURE__ */ jsx("span", { className: "whitespace-nowrap", children: option.label }),
|
|
630
|
+
isSelected && /* @__PURE__ */ jsx(CheckIcon, { className: "h-4 w-4 shrink-0" })
|
|
631
|
+
]
|
|
632
|
+
},
|
|
633
|
+
option.value
|
|
634
|
+
);
|
|
635
|
+
}) })
|
|
636
|
+
] })
|
|
637
|
+
] }),
|
|
638
|
+
selectedFacetCount > 0 && /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-1.5 pt-1", children: [
|
|
639
|
+
Array.from(selectedFacetValues.entries()).map(([field, value]) => /* @__PURE__ */ jsxs(
|
|
640
|
+
"button",
|
|
641
|
+
{
|
|
642
|
+
type: "button",
|
|
643
|
+
onClick: () => clearFacetField(field),
|
|
644
|
+
className: "group inline-flex max-w-full cursor-pointer items-center gap-1.5 rounded-md border border-neutral-soft bg-neutral-weak px-2.5 py-1 text-xs transition-colors hover:bg-neutral-soft",
|
|
645
|
+
title: `Remove filter: ${value}`,
|
|
646
|
+
children: [
|
|
647
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium truncate max-w-[140px]", children: value }),
|
|
648
|
+
/* @__PURE__ */ jsx(CloseIcon, { className: "h-3 w-3 shrink-0 opacity-60 group-hover:opacity-100" })
|
|
649
|
+
]
|
|
650
|
+
},
|
|
651
|
+
`mobile-chip-${field}`
|
|
652
|
+
)),
|
|
653
|
+
/* @__PURE__ */ jsx(
|
|
654
|
+
"button",
|
|
655
|
+
{
|
|
656
|
+
type: "button",
|
|
657
|
+
onClick: () => void handleClearAll(),
|
|
658
|
+
className: "inline-flex cursor-pointer items-center rounded-md px-2 py-1 text-xs font-semibold underline underline-offset-2 hover:bg-neutral-weak transition-colors ml-auto",
|
|
659
|
+
children: "Clear all"
|
|
660
|
+
}
|
|
661
|
+
)
|
|
662
|
+
] })
|
|
663
|
+
] }),
|
|
664
|
+
isMobileFiltersOpen && /* @__PURE__ */ jsxs("div", { className: "fixed inset-0 z-50 flex flex-col justify-end lg:hidden", children: [
|
|
665
|
+
/* @__PURE__ */ jsx(
|
|
666
|
+
"div",
|
|
667
|
+
{
|
|
668
|
+
className: "fixed inset-0 bg-neutral-stronger/60 backdrop-blur-xs transition-opacity duration-300",
|
|
669
|
+
onClick: () => setIsMobileFiltersOpen(false),
|
|
670
|
+
"aria-hidden": "true"
|
|
671
|
+
}
|
|
672
|
+
),
|
|
673
|
+
/* @__PURE__ */ jsxs("div", { className: "relative z-10 flex h-[85vh] max-h-[85vh] w-full flex-col rounded-t-xl border-t border-neutral-soft bg-default shadow-2xl transition-transform duration-300 animate-in slide-in-from-bottom", children: [
|
|
674
|
+
/* @__PURE__ */ jsx("div", { className: "pt-2.5 pb-1", children: /* @__PURE__ */ jsx("div", { className: "mx-auto h-1.5 w-12 rounded-full bg-neutral-soft" }) }),
|
|
675
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-5 py-3 border-b border-neutral-soft", children: [
|
|
676
|
+
/* @__PURE__ */ jsx("h2", { className: "text-lg font-bold tracking-tight", children: "Filters" }),
|
|
677
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
678
|
+
selectedFacetCount > 0 && /* @__PURE__ */ jsx(
|
|
679
|
+
"button",
|
|
680
|
+
{
|
|
681
|
+
type: "button",
|
|
682
|
+
onClick: () => void handleClearAll(),
|
|
683
|
+
className: "text-xs font-semibold cursor-pointer underline underline-offset-2 hover:opacity-80",
|
|
684
|
+
children: "Clear all"
|
|
685
|
+
}
|
|
686
|
+
),
|
|
687
|
+
/* @__PURE__ */ jsx(
|
|
688
|
+
"button",
|
|
689
|
+
{
|
|
690
|
+
type: "button",
|
|
691
|
+
onClick: () => setIsMobileFiltersOpen(false),
|
|
692
|
+
className: "p-1 rounded-full hover:bg-neutral-weak transition-colors cursor-pointer",
|
|
693
|
+
"aria-label": "Close filters",
|
|
694
|
+
children: /* @__PURE__ */ jsx(CloseIcon, { className: "h-5 w-5 opacity-70" })
|
|
695
|
+
}
|
|
696
|
+
)
|
|
697
|
+
] })
|
|
698
|
+
] }),
|
|
699
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto px-5 py-3 space-y-3 divide-y divide-neutral-soft", children: activeFacets.map(([field, values]) => {
|
|
700
|
+
const isOpen = !collapsedCategories[field];
|
|
701
|
+
const selectedValue = selectedFacetValues.get(field);
|
|
702
|
+
const categorySearch = facetCategorySearch[field]?.toLowerCase() || "";
|
|
703
|
+
const filteredValues = categorySearch ? values.filter((v) => v.value.toLowerCase().includes(categorySearch)) : values;
|
|
704
|
+
return /* @__PURE__ */ jsxs("div", { className: "pt-3 first:pt-0", children: [
|
|
705
|
+
/* @__PURE__ */ jsxs(
|
|
706
|
+
"button",
|
|
707
|
+
{
|
|
708
|
+
type: "button",
|
|
709
|
+
onClick: () => toggleCategory(field),
|
|
710
|
+
className: "flex w-full cursor-pointer items-center justify-between rounded-md py-2 text-left transition-colors",
|
|
711
|
+
children: [
|
|
712
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2.5", children: [
|
|
713
|
+
/* @__PURE__ */ jsx("span", { className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-md border border-neutral-soft bg-neutral-weak", children: getCategoryIcon(field) }),
|
|
714
|
+
/* @__PURE__ */ jsx("span", { className: "font-semibold text-sm", children: humanize(field) })
|
|
715
|
+
] }),
|
|
716
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
717
|
+
selectedValue && /* @__PURE__ */ jsx("span", { className: "flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-primary-base text-xs font-bold leading-none", children: "1" }),
|
|
718
|
+
/* @__PURE__ */ jsx(
|
|
719
|
+
ChevronDownIcon,
|
|
720
|
+
{
|
|
721
|
+
className: `h-4 w-4 transition-transform duration-200 ${isOpen ? "rotate-180" : ""}`
|
|
722
|
+
}
|
|
723
|
+
)
|
|
724
|
+
] })
|
|
725
|
+
]
|
|
726
|
+
}
|
|
727
|
+
),
|
|
728
|
+
isOpen && /* @__PURE__ */ jsxs("div", { className: "pt-2 pb-1 pl-1 pr-1 space-y-1.5", children: [
|
|
729
|
+
values.length > 5 && /* @__PURE__ */ jsxs("div", { className: "relative mb-2", children: [
|
|
730
|
+
/* @__PURE__ */ jsx(SearchIcon, { className: "pointer-events-none absolute left-3 top-1/2 h-3.5 w-3.5 -translate-y-1/2 opacity-50" }),
|
|
731
|
+
/* @__PURE__ */ jsx(
|
|
732
|
+
"input",
|
|
733
|
+
{
|
|
734
|
+
type: "text",
|
|
735
|
+
value: facetCategorySearch[field] || "",
|
|
736
|
+
onChange: (e) => setFacetCategorySearch((prev) => ({
|
|
737
|
+
...prev,
|
|
738
|
+
[field]: e.target.value
|
|
739
|
+
})),
|
|
740
|
+
placeholder: `Search ${humanize(field).toLowerCase()}...`,
|
|
741
|
+
className: "h-8.5 w-full rounded-md border border-neutral-soft bg-neutral-weak py-1 pl-8 pr-3 text-xs focus:border-primary-base focus:outline-none"
|
|
742
|
+
}
|
|
743
|
+
)
|
|
744
|
+
] }),
|
|
745
|
+
filteredValues.length === 0 ? /* @__PURE__ */ jsx("div", { className: "py-2 text-center text-xs opacity-60", children: "No matching options" }) : filteredValues.map((facet) => {
|
|
746
|
+
const isChecked = selectedValue === facet.value;
|
|
747
|
+
return /* @__PURE__ */ jsxs(
|
|
748
|
+
"button",
|
|
749
|
+
{
|
|
750
|
+
type: "button",
|
|
751
|
+
onClick: () => navigateWithoutReload(
|
|
752
|
+
getFacetUrl(field, facet.value)
|
|
753
|
+
),
|
|
754
|
+
"aria-pressed": isChecked,
|
|
755
|
+
className: `flex w-full cursor-pointer items-center justify-between gap-3 rounded-md px-2.5 py-2 text-left text-sm transition-colors ${isChecked ? "bg-neutral-soft font-medium" : "hover:bg-neutral-weak"}`,
|
|
756
|
+
children: [
|
|
757
|
+
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center gap-3", children: [
|
|
758
|
+
/* @__PURE__ */ jsx(
|
|
759
|
+
"span",
|
|
760
|
+
{
|
|
761
|
+
className: `flex h-5 w-5 shrink-0 items-center justify-center rounded-md border transition-colors ${isChecked ? "bg-primary-base border-primary-base" : "border-neutral-soft bg-default"}`,
|
|
762
|
+
children: isChecked && /* @__PURE__ */ jsx(CheckIcon, { className: "h-3.5 w-3.5" })
|
|
763
|
+
}
|
|
764
|
+
),
|
|
765
|
+
/* @__PURE__ */ jsx("span", { className: "leading-snug break-words", children: facet.value })
|
|
766
|
+
] }),
|
|
767
|
+
/* @__PURE__ */ jsx("span", { className: "shrink-0 text-xs opacity-60 ml-2", children: facet.count })
|
|
768
|
+
]
|
|
769
|
+
},
|
|
770
|
+
`drawer-${field}-${facet.value}`
|
|
771
|
+
);
|
|
772
|
+
})
|
|
773
|
+
] })
|
|
774
|
+
] }, `drawer-cat-${field}`);
|
|
775
|
+
}) }),
|
|
776
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 border-t border-neutral-soft bg-default p-4", children: [
|
|
777
|
+
/* @__PURE__ */ jsx(
|
|
778
|
+
"button",
|
|
779
|
+
{
|
|
780
|
+
type: "button",
|
|
781
|
+
onClick: () => setIsMobileFiltersOpen(false),
|
|
782
|
+
className: "flex-1 h-11 rounded-md border border-neutral-soft bg-default text-sm font-medium transition-colors hover:bg-neutral-weak cursor-pointer flex items-center justify-center",
|
|
783
|
+
children: "Close"
|
|
784
|
+
}
|
|
785
|
+
),
|
|
786
|
+
/* @__PURE__ */ jsxs(
|
|
787
|
+
"button",
|
|
788
|
+
{
|
|
789
|
+
type: "button",
|
|
790
|
+
onClick: () => setIsMobileFiltersOpen(false),
|
|
791
|
+
className: "flex-1 h-11 rounded-md bg-primary-base text-sm font-semibold shadow-md transition-all hover:opacity-90 active:scale-98 cursor-pointer flex items-center justify-center",
|
|
792
|
+
children: [
|
|
793
|
+
"Apply Filters",
|
|
794
|
+
selectedFacetCount > 0 ? ` (${selectedFacetCount})` : ""
|
|
795
|
+
]
|
|
796
|
+
}
|
|
797
|
+
)
|
|
798
|
+
] })
|
|
799
|
+
] })
|
|
800
|
+
] })
|
|
801
|
+
] }),
|
|
802
|
+
shouldShowFacets && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
803
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between border-b border-neutral-soft pb-3", children: [
|
|
804
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
805
|
+
/* @__PURE__ */ jsx(FilterSlidersIcon, { className: "h-4 w-4" }),
|
|
806
|
+
/* @__PURE__ */ jsx("h2", { className: "text-base font-semibold tracking-tight", children: "Filters" }),
|
|
807
|
+
selectedFacetCount > 0 && /* @__PURE__ */ jsx("span", { className: "flex h-5 items-center justify-center rounded-full bg-primary-base px-2 text-xs font-semibold", children: selectedFacetCount })
|
|
808
|
+
] }),
|
|
809
|
+
hasActiveFiltersOrSort && /* @__PURE__ */ jsxs(
|
|
810
|
+
"button",
|
|
811
|
+
{
|
|
812
|
+
type: "button",
|
|
813
|
+
onClick: () => void handleClearAll(),
|
|
814
|
+
className: "group inline-flex cursor-pointer items-center gap-1.5 rounded-md px-2 py-1 text-xs font-medium transition-colors duration-150 hover:bg-neutral-soft focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary-base",
|
|
815
|
+
"aria-label": "Clear all filters and sorting",
|
|
816
|
+
children: [
|
|
817
|
+
/* @__PURE__ */ jsx(ResetIcon, { className: "h-3.5 w-3.5 transition-transform duration-200 group-hover:-rotate-45" }),
|
|
818
|
+
/* @__PURE__ */ jsx("span", { children: "Clear all" })
|
|
819
|
+
]
|
|
820
|
+
}
|
|
821
|
+
)
|
|
822
|
+
] }),
|
|
823
|
+
selectedFacetCount > 0 && /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1.5 pb-2.5 border-b border-neutral-soft", children: Array.from(selectedFacetValues.entries()).map(([field, value]) => /* @__PURE__ */ jsxs(
|
|
824
|
+
"button",
|
|
825
|
+
{
|
|
826
|
+
type: "button",
|
|
827
|
+
onClick: () => clearFacetField(field),
|
|
828
|
+
className: "group inline-flex max-w-full cursor-pointer items-center gap-1.5 rounded-md border border-neutral-soft bg-neutral-weak px-2.5 py-1 text-xs transition-colors hover:bg-neutral-soft",
|
|
829
|
+
title: `Remove filter: ${value}`,
|
|
830
|
+
children: [
|
|
831
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium truncate max-w-[150px]", children: value }),
|
|
832
|
+
/* @__PURE__ */ jsx(CloseIcon, { className: "h-3.5 w-3.5 shrink-0 opacity-60 group-hover:opacity-100" })
|
|
833
|
+
]
|
|
834
|
+
},
|
|
835
|
+
`chip-${field}`
|
|
836
|
+
)) }),
|
|
837
|
+
activeFacets.length === 1 && /* @__PURE__ */ jsx("nav", { "aria-label": `${humanize(activeFacets[0][0])} filters`, children: /* @__PURE__ */ jsxs("div", { className: "py-1", children: [
|
|
838
|
+
/* @__PURE__ */ jsx("div", { className: "px-1 pb-2 font-medium text-sm", children: humanize(activeFacets[0][0]) }),
|
|
839
|
+
renderFacetItems(activeFacets[0][0], activeFacets[0][1])
|
|
840
|
+
] }) }),
|
|
841
|
+
activeFacets.length > 1 && /* @__PURE__ */ jsx("div", { className: "flex flex-col divide-y divide-neutral-soft", children: activeFacets.map(([field, values]) => {
|
|
842
|
+
const isOpen = !collapsedCategories[field];
|
|
843
|
+
return /* @__PURE__ */ jsxs(
|
|
844
|
+
"div",
|
|
845
|
+
{
|
|
846
|
+
className: "py-2 first:pt-0 last:pb-0",
|
|
847
|
+
children: [
|
|
848
|
+
/* @__PURE__ */ jsxs(
|
|
849
|
+
"button",
|
|
850
|
+
{
|
|
851
|
+
type: "button",
|
|
852
|
+
onClick: () => toggleCategory(field),
|
|
853
|
+
className: "flex w-full cursor-pointer items-center justify-between rounded-md px-1.5 py-1.5 text-sm font-semibold transition-colors duration-150 hover:bg-neutral-weak focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary-base",
|
|
854
|
+
children: [
|
|
855
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
856
|
+
/* @__PURE__ */ jsx("span", { className: "flex h-5 w-5 shrink-0 items-center justify-center rounded border border-neutral-soft bg-neutral-weak", children: getCategoryIcon(field) }),
|
|
857
|
+
/* @__PURE__ */ jsx("span", { children: humanize(field) })
|
|
858
|
+
] }),
|
|
859
|
+
/* @__PURE__ */ jsx(
|
|
860
|
+
ChevronDownIcon,
|
|
861
|
+
{
|
|
862
|
+
className: `h-4 w-4 transition-transform duration-200 ease-out ${isOpen ? "rotate-180" : ""}`
|
|
863
|
+
}
|
|
864
|
+
)
|
|
865
|
+
]
|
|
866
|
+
}
|
|
867
|
+
),
|
|
868
|
+
isOpen && /* @__PURE__ */ jsx("div", { className: "pt-1", children: renderFacetItems(field, values) })
|
|
869
|
+
]
|
|
870
|
+
},
|
|
871
|
+
field
|
|
872
|
+
);
|
|
873
|
+
}) })
|
|
874
|
+
] })
|
|
875
|
+
]
|
|
876
|
+
}
|
|
877
|
+
);
|
|
878
|
+
};
|
|
879
|
+
var DataBindingControls_default = DataBindingControls;
|
|
880
|
+
export {
|
|
881
|
+
DataBindingControls_default as default
|
|
882
|
+
};
|