@clyrex-digital/clyrex-controls-dev 0.8.1-dev.20260923102653 → 0.8.1-dev.20260923125229

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clyrex-digital/clyrex-controls-dev",
3
- "version": "0.8.1-dev.20260923102653",
3
+ "version": "0.8.1-dev.20260923125229",
4
4
  "description": "Reusable React components",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -1,294 +0,0 @@
1
- "use client";
2
-
3
- "use client";
4
- import {
5
- InputControl_default
6
- } from "./chunk-XDTWUEVR.mjs";
7
- import {
8
- Button_default
9
- } from "./chunk-LSKD5U3S.mjs";
10
- import {
11
- InputControlType_default
12
- } from "./chunk-F4DNLPFN.mjs";
13
- import "./chunk-IMNQO57B.mjs";
14
-
15
- // src/components/pageRenderingEngine/nodes/DataBindingControls.tsx
16
- import { useCallback, useEffect, useRef, useState } from "react";
17
- import { useRouter } from "next/navigation";
18
- import { jsx, jsxs } from "react/jsx-runtime";
19
- var humanize = (value) => value.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[_-]+/g, " ").trim();
20
- var escapeODataString = (value) => value.replace(/'/g, "''");
21
- var parseFacetSelections = (filter) => {
22
- const selections = /* @__PURE__ */ new Map();
23
- const groupedExpression = /\(\s*([^()]+?)\s+eq\s+'((?:''|[^'])*)'\s*\)/gi;
24
- for (const match of filter.matchAll(groupedExpression)) {
25
- selections.set(match[1].trim(), match[2].replace(/''/g, "'"));
26
- }
27
- if (selections.size === 0) {
28
- const ungroupedExpression = /(?:^|\s+and\s+)\s*([^()]+?)\s+eq\s+'((?:''|[^'])*)'\s*(?=\s+and\s+|$)/gi;
29
- for (const match of filter.matchAll(ungroupedExpression)) {
30
- selections.set(
31
- match[1].trim(),
32
- match[2].replace(/''/g, "'")
33
- );
34
- }
35
- }
36
- return selections;
37
- };
38
- var buildFacetFilter = (selections) => Array.from(selections.entries()).map(([field, value]) => `${field} eq '${escapeODataString(value)}'`).join(" and ");
39
- var parseODataSearch = (value) => {
40
- if (!value) return "";
41
- const trimmedValue = value.trim();
42
- if (trimmedValue.startsWith("'") && trimmedValue.endsWith("'")) {
43
- return trimmedValue.slice(1, -1).replace(/''/g, "'");
44
- }
45
- return trimmedValue;
46
- };
47
- var SearchIcon = ({ className = "" }) => /* @__PURE__ */ jsxs(
48
- "svg",
49
- {
50
- "aria-hidden": "true",
51
- className,
52
- fill: "none",
53
- viewBox: "0 0 24 24",
54
- stroke: "currentColor",
55
- strokeWidth: "2",
56
- children: [
57
- /* @__PURE__ */ jsx("circle", { cx: "11", cy: "11", r: "7" }),
58
- /* @__PURE__ */ jsx("path", { strokeLinecap: "round", d: "m20 20-4-4" })
59
- ]
60
- }
61
- );
62
- var normalizeSortOption = (option) => {
63
- const direction = option.direction.trim();
64
- return {
65
- label: option.title || humanize(option.name),
66
- value: [option.name, direction].filter(Boolean).join(" ")
67
- };
68
- };
69
- var DUMMY_FACETS = {
70
- CategoryTitle: [
71
- { value: "Career Readiness", count: 2 },
72
- { value: "Student Learning", count: 2 }
73
- ],
74
- Author: [
75
- { value: "John Smith", count: 2 },
76
- { value: "Sarah Jones", count: 1 },
77
- { value: "Emily Brown", count: 1 }
78
- ]
79
- };
80
- var DUMMY_SORT_OPTIONS = [
81
- { name: "createdDate", title: "Newest First", direction: "desc" },
82
- { name: "createdDate", title: "Oldest First", direction: "asc" },
83
- { name: "title", title: "Title A-Z", direction: "asc" },
84
- { name: "title", title: "Title Z-A", direction: "desc" }
85
- ];
86
- var DataBindingControls = ({
87
- path,
88
- query,
89
- facets,
90
- sortOptions,
91
- showFacets,
92
- showSortOptions,
93
- showSearchBar,
94
- mode = "toolbar"
95
- }) => {
96
- const router = useRouter();
97
- const apiFacetGroups = Object.entries(facets ?? {}).filter(
98
- ([, values]) => Array.isArray(values) && values.length > 0
99
- );
100
- const facetGroups = apiFacetGroups.length > 0 ? apiFacetGroups : Object.entries(DUMMY_FACETS);
101
- const apiSortOptions = (sortOptions ?? []).filter(
102
- (option) => option?.name && option?.direction
103
- );
104
- const resolvedSortOptions = apiSortOptions.length > 0 ? apiSortOptions : DUMMY_SORT_OPTIONS;
105
- const normalizedSortOptions = resolvedSortOptions.map(normalizeSortOption).filter((option) => option.value);
106
- const currentFilter = query?.["$filter"] ?? query?.filter ?? "";
107
- const selectedFacetValues = parseFacetSelections(currentFilter);
108
- const currentSort = query?.["$orderby"] ?? query?.orderBy ?? "";
109
- const currentSearch = parseODataSearch(query?.["$search"]);
110
- const [searchText, setSearchText] = useState(currentSearch);
111
- const lastNavigationUrl = useRef(null);
112
- useEffect(() => {
113
- setSearchText(currentSearch);
114
- }, [currentSearch]);
115
- const getQueryUrl = useCallback(
116
- (updates) => {
117
- const params = new URLSearchParams(query ?? {});
118
- Object.entries(updates).forEach(([key, value]) => {
119
- if (value) {
120
- params.set(key, value);
121
- } else {
122
- params.delete(key);
123
- }
124
- });
125
- params.delete("$skip");
126
- params.delete("skip");
127
- const queryString = Array.from(params.entries()).map(([key, value]) => `${key}=${value}`).join("&");
128
- return queryString ? `${path}?${queryString}` : path;
129
- },
130
- [path, query]
131
- );
132
- const getFacetUrl = (field, value) => {
133
- const updatedSelections = new Map(selectedFacetValues);
134
- if (value) {
135
- updatedSelections.set(field, value);
136
- } else {
137
- updatedSelections.delete(field);
138
- }
139
- const updatedFilter = buildFacetFilter(updatedSelections);
140
- return getQueryUrl({
141
- $filter: updatedFilter || void 0,
142
- filter: void 0
143
- });
144
- };
145
- const navigateWithoutReload = useCallback(
146
- (url) => {
147
- if (lastNavigationUrl.current === url) {
148
- return;
149
- }
150
- if (typeof window !== "undefined") {
151
- const targetUrl = new URL(url, window.location.origin);
152
- if (targetUrl.pathname === window.location.pathname && targetUrl.search === window.location.search) {
153
- return;
154
- }
155
- }
156
- lastNavigationUrl.current = url;
157
- router.push(url, { scroll: false });
158
- },
159
- [router]
160
- );
161
- const handleSearch = useCallback(async () => {
162
- const trimmedSearchText = searchText.trim();
163
- if (trimmedSearchText === currentSearch.trim()) {
164
- return { isSuccessful: true };
165
- }
166
- navigateWithoutReload(
167
- getQueryUrl({
168
- "$search": trimmedSearchText || void 0
169
- })
170
- );
171
- return { isSuccessful: true };
172
- }, [currentSearch, getQueryUrl, navigateWithoutReload, searchText]);
173
- const hasFacetControls = showFacets && facetGroups.length > 0;
174
- const hasSortControls = showSortOptions && normalizedSortOptions.length > 0;
175
- const shouldShowToolbar = mode === "toolbar" && (showSearchBar || hasSortControls);
176
- const shouldShowFacets = mode === "facets" && hasFacetControls;
177
- if (!shouldShowToolbar && !shouldShowFacets) {
178
- return null;
179
- }
180
- const renderFacetLinks = (field, values, stacked = false) => /* @__PURE__ */ jsxs("div", { className: stacked ? "flex flex-col gap-1" : "flex flex-wrap gap-2", children: [
181
- /* @__PURE__ */ jsx(
182
- "button",
183
- {
184
- type: "button",
185
- onClick: () => navigateWithoutReload(getFacetUrl(field)),
186
- "aria-pressed": !selectedFacetValues.has(field),
187
- className: `px-3 py-2 text-left text-sm ${stacked ? "w-full" : "border"} ${selectedFacetValues.has(field) ? "" : "bg-primary-base font-semibold"}`,
188
- children: "All"
189
- }
190
- ),
191
- values.map((facet) => {
192
- const isSelected = selectedFacetValues.get(field) === facet.value;
193
- return /* @__PURE__ */ jsxs(
194
- "button",
195
- {
196
- type: "button",
197
- onClick: () => navigateWithoutReload(getFacetUrl(field, facet.value)),
198
- "aria-pressed": isSelected,
199
- className: `px-3 py-2 text-left text-sm ${stacked ? "w-full" : "border"} ${isSelected ? "bg-primary-base font-semibold" : ""}`,
200
- children: [
201
- facet.value,
202
- " (",
203
- facet.count,
204
- ")"
205
- ]
206
- },
207
- `${field}-${facet.value}`
208
- );
209
- })
210
- ] });
211
- return /* @__PURE__ */ jsxs("div", { className: mode === "toolbar" ? "my-6" : "flex flex-col gap-2", children: [
212
- shouldShowToolbar && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
213
- showSearchBar && /* @__PURE__ */ jsxs(
214
- "form",
215
- {
216
- role: "search",
217
- className: "flex w-full flex-col gap-3 rounded-2xl border border-info bg-info-soft p-3 sm:flex-row sm:items-center md:min-w-0 md:flex-1",
218
- onSubmit: (event) => {
219
- event.preventDefault();
220
- void handleSearch();
221
- },
222
- children: [
223
- /* @__PURE__ */ jsxs("div", { className: "relative bg-default rounded-xl min-w-0 flex-1", children: [
224
- /* @__PURE__ */ jsx(SearchIcon, { className: "pointer-events-none absolute left-4 top-1/2 z-10 h-5 w-5 -translate-y-1/2" }),
225
- /* @__PURE__ */ jsx(
226
- InputControl_default,
227
- {
228
- name: "searchText",
229
- controlType: InputControlType_default.lineTextInput,
230
- value: searchText,
231
- callback: (updatedValues) => setSearchText(updatedValues.value),
232
- attributes: {
233
- placeholder: "Search discussions, topics, or keywords..."
234
- },
235
- inputClasses: "!mt-0 !rounded-xl !py-3 !pl-11 !pr-4 !shadow-sm"
236
- }
237
- )
238
- ] }),
239
- /* @__PURE__ */ jsxs(
240
- Button_default,
241
- {
242
- ButtonType: "Primary" /* Solid */,
243
- onClick: handleSearch,
244
- className: "!rounded-xl !px-6 !py-3 sm:self-stretch",
245
- children: [
246
- /* @__PURE__ */ jsx(SearchIcon, { className: "h-5 w-5" }),
247
- /* @__PURE__ */ jsx("span", { children: "Search" })
248
- ]
249
- }
250
- )
251
- ]
252
- }
253
- ),
254
- hasSortControls && /* @__PURE__ */ jsxs("div", { className: "flex w-full items-center gap-3 rounded-2xl border border-info bg-info-soft p-3 text-sm md:ml-auto md:w-auto md:min-w-72 md:self-stretch", children: [
255
- /* @__PURE__ */ jsx(
256
- "label",
257
- {
258
- htmlFor: "sortOptions",
259
- className: "shrink-0 whitespace-nowrap font-medium",
260
- children: "Sort by"
261
- }
262
- ),
263
- /* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1 rounded-xl bg-default md:min-w-48", children: /* @__PURE__ */ jsx(
264
- InputControl_default,
265
- {
266
- name: "sortOptions",
267
- controlType: InputControlType_default.select,
268
- value: currentSort,
269
- dataset: normalizedSortOptions,
270
- dataKeyFieldName: "value",
271
- dataTextFieldName: "label",
272
- callback: (updatedValues) => navigateWithoutReload(
273
- getQueryUrl({
274
- $orderby: updatedValues.value || void 0,
275
- orderBy: void 0
276
- })
277
- ),
278
- attributes: { placeholder: "Default" },
279
- inputClasses: "!mt-0 !rounded-xl !border-info !bg-default !px-4 !py-3 !text-body !shadow-sm focus:!border-primary focus:!ring-primary-base"
280
- }
281
- ) })
282
- ] })
283
- ] }),
284
- shouldShowFacets && facetGroups.length === 1 && /* @__PURE__ */ jsx("nav", { "aria-label": `${humanize(facetGroups[0][0])} filters`, children: renderFacetLinks(facetGroups[0][0], facetGroups[0][1]) }),
285
- shouldShowFacets && facetGroups.length > 1 && /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children: facetGroups.map(([field, values]) => /* @__PURE__ */ jsxs("details", { className: "border-b", open: true, children: [
286
- /* @__PURE__ */ jsx("summary", { className: "cursor-pointer font-semibold", children: humanize(field) }),
287
- /* @__PURE__ */ jsx("div", { className: "p-2", children: renderFacetLinks(field, values, true) })
288
- ] }, field)) })
289
- ] });
290
- };
291
- var DataBindingControls_default = DataBindingControls;
292
- export {
293
- DataBindingControls_default as default
294
- };
@@ -1,298 +0,0 @@
1
- "use client";
2
- import {
3
- InputControlType_default
4
- } from "./chunk-HRDHAIZF.mjs";
5
- import {
6
- Button_default
7
- } from "./chunk-4WMSS6CE.mjs";
8
- import "./chunk-56HSDML5.mjs";
9
-
10
- // src/components/pageRenderingEngine/nodes/DataBindingControls.tsx
11
- import { useCallback, useEffect, useRef, useState } from "react";
12
- import { useRouter } from "next/navigation";
13
-
14
- // src/components/controls/edit/InputControl.tsx
15
- import dynamic from "next/dynamic";
16
- var InputControl = dynamic(() => import("./InputControlClient-NHXG4QBU.mjs"), {
17
- ssr: false
18
- });
19
- var InputControl_default = InputControl;
20
-
21
- // src/components/pageRenderingEngine/nodes/DataBindingControls.tsx
22
- import { jsx, jsxs } from "react/jsx-runtime";
23
- var humanize = (value) => value.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[_-]+/g, " ").trim();
24
- var escapeODataString = (value) => value.replace(/'/g, "''");
25
- var parseFacetSelections = (filter) => {
26
- const selections = /* @__PURE__ */ new Map();
27
- const groupedExpression = /\(\s*([^()]+?)\s+eq\s+'((?:''|[^'])*)'\s*\)/gi;
28
- for (const match of filter.matchAll(groupedExpression)) {
29
- selections.set(match[1].trim(), match[2].replace(/''/g, "'"));
30
- }
31
- if (selections.size === 0) {
32
- const ungroupedExpression = /(?:^|\s+and\s+)\s*([^()]+?)\s+eq\s+'((?:''|[^'])*)'\s*(?=\s+and\s+|$)/gi;
33
- for (const match of filter.matchAll(ungroupedExpression)) {
34
- selections.set(
35
- match[1].trim(),
36
- match[2].replace(/''/g, "'")
37
- );
38
- }
39
- }
40
- return selections;
41
- };
42
- var buildFacetFilter = (selections) => Array.from(selections.entries()).map(([field, value]) => `${field} eq '${escapeODataString(value)}'`).join(" and ");
43
- var parseODataSearch = (value) => {
44
- if (!value) return "";
45
- const trimmedValue = value.trim();
46
- if (trimmedValue.startsWith("'") && trimmedValue.endsWith("'")) {
47
- return trimmedValue.slice(1, -1).replace(/''/g, "'");
48
- }
49
- return trimmedValue;
50
- };
51
- var SearchIcon = ({ className = "" }) => /* @__PURE__ */ jsxs(
52
- "svg",
53
- {
54
- "aria-hidden": "true",
55
- className,
56
- fill: "none",
57
- viewBox: "0 0 24 24",
58
- stroke: "currentColor",
59
- strokeWidth: "2",
60
- children: [
61
- /* @__PURE__ */ jsx("circle", { cx: "11", cy: "11", r: "7" }),
62
- /* @__PURE__ */ jsx("path", { strokeLinecap: "round", d: "m20 20-4-4" })
63
- ]
64
- }
65
- );
66
- var normalizeSortOption = (option) => {
67
- const direction = option.direction.trim();
68
- return {
69
- label: option.title || humanize(option.name),
70
- value: [option.name, direction].filter(Boolean).join(" ")
71
- };
72
- };
73
- var DUMMY_FACETS = {
74
- CategoryTitle: [
75
- { value: "Career Readiness", count: 2 },
76
- { value: "Student Learning", count: 2 }
77
- ],
78
- Author: [
79
- { value: "John Smith", count: 2 },
80
- { value: "Sarah Jones", count: 1 },
81
- { value: "Emily Brown", count: 1 }
82
- ]
83
- };
84
- var DUMMY_SORT_OPTIONS = [
85
- { name: "createdDate", title: "Newest First", direction: "desc" },
86
- { name: "createdDate", title: "Oldest First", direction: "asc" },
87
- { name: "title", title: "Title A-Z", direction: "asc" },
88
- { name: "title", title: "Title Z-A", direction: "desc" }
89
- ];
90
- var DataBindingControls = ({
91
- path,
92
- query,
93
- facets,
94
- sortOptions,
95
- showFacets,
96
- showSortOptions,
97
- showSearchBar,
98
- mode = "toolbar"
99
- }) => {
100
- const router = useRouter();
101
- const apiFacetGroups = Object.entries(facets ?? {}).filter(
102
- ([, values]) => Array.isArray(values) && values.length > 0
103
- );
104
- const facetGroups = apiFacetGroups.length > 0 ? apiFacetGroups : Object.entries(DUMMY_FACETS);
105
- const apiSortOptions = (sortOptions ?? []).filter(
106
- (option) => option?.name && option?.direction
107
- );
108
- const resolvedSortOptions = apiSortOptions.length > 0 ? apiSortOptions : DUMMY_SORT_OPTIONS;
109
- const normalizedSortOptions = resolvedSortOptions.map(normalizeSortOption).filter((option) => option.value);
110
- const currentFilter = query?.["$filter"] ?? query?.filter ?? "";
111
- const selectedFacetValues = parseFacetSelections(currentFilter);
112
- const currentSort = query?.["$orderby"] ?? query?.orderBy ?? "";
113
- const currentSearch = parseODataSearch(query?.["$search"]);
114
- const [searchText, setSearchText] = useState(currentSearch);
115
- const lastNavigationUrl = useRef(null);
116
- useEffect(() => {
117
- setSearchText(currentSearch);
118
- }, [currentSearch]);
119
- const getQueryUrl = useCallback(
120
- (updates) => {
121
- const params = new URLSearchParams(query ?? {});
122
- Object.entries(updates).forEach(([key, value]) => {
123
- if (value) {
124
- params.set(key, value);
125
- } else {
126
- params.delete(key);
127
- }
128
- });
129
- params.delete("$skip");
130
- params.delete("skip");
131
- const queryString = Array.from(params.entries()).map(([key, value]) => `${key}=${value}`).join("&");
132
- return queryString ? `${path}?${queryString}` : path;
133
- },
134
- [path, query]
135
- );
136
- const getFacetUrl = (field, value) => {
137
- const updatedSelections = new Map(selectedFacetValues);
138
- if (value) {
139
- updatedSelections.set(field, value);
140
- } else {
141
- updatedSelections.delete(field);
142
- }
143
- const updatedFilter = buildFacetFilter(updatedSelections);
144
- return getQueryUrl({
145
- $filter: updatedFilter || void 0,
146
- filter: void 0
147
- });
148
- };
149
- const navigateWithoutReload = useCallback(
150
- (url) => {
151
- if (lastNavigationUrl.current === url) {
152
- return;
153
- }
154
- if (typeof window !== "undefined") {
155
- const targetUrl = new URL(url, window.location.origin);
156
- if (targetUrl.pathname === window.location.pathname && targetUrl.search === window.location.search) {
157
- return;
158
- }
159
- }
160
- lastNavigationUrl.current = url;
161
- router.push(url, { scroll: false });
162
- },
163
- [router]
164
- );
165
- const handleSearch = useCallback(async () => {
166
- const trimmedSearchText = searchText.trim();
167
- if (trimmedSearchText === currentSearch.trim()) {
168
- return { isSuccessful: true };
169
- }
170
- navigateWithoutReload(
171
- getQueryUrl({
172
- "$search": trimmedSearchText || void 0
173
- })
174
- );
175
- return { isSuccessful: true };
176
- }, [currentSearch, getQueryUrl, navigateWithoutReload, searchText]);
177
- const hasFacetControls = showFacets && facetGroups.length > 0;
178
- const hasSortControls = showSortOptions && normalizedSortOptions.length > 0;
179
- const shouldShowToolbar = mode === "toolbar" && (showSearchBar || hasSortControls);
180
- const shouldShowFacets = mode === "facets" && hasFacetControls;
181
- if (!shouldShowToolbar && !shouldShowFacets) {
182
- return null;
183
- }
184
- const renderFacetLinks = (field, values, stacked = false) => /* @__PURE__ */ jsxs("div", { className: stacked ? "flex flex-col gap-1" : "flex flex-wrap gap-2", children: [
185
- /* @__PURE__ */ jsx(
186
- "button",
187
- {
188
- type: "button",
189
- onClick: () => navigateWithoutReload(getFacetUrl(field)),
190
- "aria-pressed": !selectedFacetValues.has(field),
191
- className: `px-3 py-2 text-left text-sm ${stacked ? "w-full" : "border"} ${selectedFacetValues.has(field) ? "" : "bg-primary-base font-semibold"}`,
192
- children: "All"
193
- }
194
- ),
195
- values.map((facet) => {
196
- const isSelected = selectedFacetValues.get(field) === facet.value;
197
- return /* @__PURE__ */ jsxs(
198
- "button",
199
- {
200
- type: "button",
201
- onClick: () => navigateWithoutReload(getFacetUrl(field, facet.value)),
202
- "aria-pressed": isSelected,
203
- className: `px-3 py-2 text-left text-sm ${stacked ? "w-full" : "border"} ${isSelected ? "bg-primary-base font-semibold" : ""}`,
204
- children: [
205
- facet.value,
206
- " (",
207
- facet.count,
208
- ")"
209
- ]
210
- },
211
- `${field}-${facet.value}`
212
- );
213
- })
214
- ] });
215
- return /* @__PURE__ */ jsxs("div", { className: mode === "toolbar" ? "my-6" : "flex flex-col gap-2", children: [
216
- shouldShowToolbar && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
217
- showSearchBar && /* @__PURE__ */ jsxs(
218
- "form",
219
- {
220
- role: "search",
221
- className: "flex w-full flex-col gap-3 rounded-2xl border border-info bg-info-soft p-3 sm:flex-row sm:items-center md:min-w-0 md:flex-1",
222
- onSubmit: (event) => {
223
- event.preventDefault();
224
- void handleSearch();
225
- },
226
- children: [
227
- /* @__PURE__ */ jsxs("div", { className: "relative bg-default rounded-xl min-w-0 flex-1", children: [
228
- /* @__PURE__ */ jsx(SearchIcon, { className: "pointer-events-none absolute left-4 top-1/2 z-10 h-5 w-5 -translate-y-1/2" }),
229
- /* @__PURE__ */ jsx(
230
- InputControl_default,
231
- {
232
- name: "searchText",
233
- controlType: InputControlType_default.lineTextInput,
234
- value: searchText,
235
- callback: (updatedValues) => setSearchText(updatedValues.value),
236
- attributes: {
237
- placeholder: "Search discussions, topics, or keywords..."
238
- },
239
- inputClasses: "!mt-0 !rounded-xl !py-3 !pl-11 !pr-4 !shadow-sm"
240
- }
241
- )
242
- ] }),
243
- /* @__PURE__ */ jsxs(
244
- Button_default,
245
- {
246
- ButtonType: "Primary" /* Solid */,
247
- onClick: handleSearch,
248
- className: "!rounded-xl !px-6 !py-3 sm:self-stretch",
249
- children: [
250
- /* @__PURE__ */ jsx(SearchIcon, { className: "h-5 w-5" }),
251
- /* @__PURE__ */ jsx("span", { children: "Search" })
252
- ]
253
- }
254
- )
255
- ]
256
- }
257
- ),
258
- hasSortControls && /* @__PURE__ */ jsxs("div", { className: "flex w-full items-center gap-3 rounded-2xl border border-info bg-info-soft p-3 text-sm md:ml-auto md:w-auto md:min-w-72 md:self-stretch", children: [
259
- /* @__PURE__ */ jsx(
260
- "label",
261
- {
262
- htmlFor: "sortOptions",
263
- className: "shrink-0 whitespace-nowrap font-medium",
264
- children: "Sort by"
265
- }
266
- ),
267
- /* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1 rounded-xl bg-default md:min-w-48", children: /* @__PURE__ */ jsx(
268
- InputControl_default,
269
- {
270
- name: "sortOptions",
271
- controlType: InputControlType_default.select,
272
- value: currentSort,
273
- dataset: normalizedSortOptions,
274
- dataKeyFieldName: "value",
275
- dataTextFieldName: "label",
276
- callback: (updatedValues) => navigateWithoutReload(
277
- getQueryUrl({
278
- $orderby: updatedValues.value || void 0,
279
- orderBy: void 0
280
- })
281
- ),
282
- attributes: { placeholder: "Default" },
283
- inputClasses: "!mt-0 !rounded-xl !border-info !bg-default !px-4 !py-3 !text-body !shadow-sm focus:!border-primary focus:!ring-primary-base"
284
- }
285
- ) })
286
- ] })
287
- ] }),
288
- shouldShowFacets && facetGroups.length === 1 && /* @__PURE__ */ jsx("nav", { "aria-label": `${humanize(facetGroups[0][0])} filters`, children: renderFacetLinks(facetGroups[0][0], facetGroups[0][1]) }),
289
- shouldShowFacets && facetGroups.length > 1 && /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children: facetGroups.map(([field, values]) => /* @__PURE__ */ jsxs("details", { className: "border-b", open: true, children: [
290
- /* @__PURE__ */ jsx("summary", { className: "cursor-pointer font-semibold", children: humanize(field) }),
291
- /* @__PURE__ */ jsx("div", { className: "p-2", children: renderFacetLinks(field, values, true) })
292
- ] }, field)) })
293
- ] });
294
- };
295
- var DataBindingControls_default = DataBindingControls;
296
- export {
297
- DataBindingControls_default as default
298
- };