@clyrex-digital/clyrex-controls-dev 0.8.1-dev.20260910063325 → 0.8.1-dev.20260916063140

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.
@@ -3,10 +3,14 @@
3
3
  "use client";
4
4
  import {
5
5
  InputControl_default
6
- } from "./chunk-PIMVBXWS.mjs";
6
+ } from "./chunk-6GVLDYCQ.mjs";
7
+ import {
8
+ Button_default
9
+ } from "./chunk-LSKD5U3S.mjs";
7
10
  import {
8
11
  InputControlType_default
9
12
  } from "./chunk-DTWPZPSX.mjs";
13
+ import "./chunk-IMNQO57B.mjs";
10
14
 
11
15
  // src/components/pageRenderingEngine/nodes/DataBindingControls.tsx
12
16
  import { useCallback, useEffect, useRef, useState } from "react";
@@ -40,6 +44,21 @@ var parseODataSearch = (value) => {
40
44
  }
41
45
  return trimmedValue;
42
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
+ );
43
62
  var normalizeSortOption = (option) => {
44
63
  const direction = option.direction.trim();
45
64
  return {
@@ -139,19 +158,17 @@ var DataBindingControls = ({
139
158
  },
140
159
  [router]
141
160
  );
142
- useEffect(() => {
161
+ const handleSearch = useCallback(async () => {
143
162
  const trimmedSearchText = searchText.trim();
144
163
  if (trimmedSearchText === currentSearch.trim()) {
145
- return;
164
+ return { isSuccessful: true };
146
165
  }
147
- const timeout = window.setTimeout(() => {
148
- navigateWithoutReload(
149
- getQueryUrl({
150
- "$search": trimmedSearchText || void 0
151
- })
152
- );
153
- }, 500);
154
- return () => window.clearTimeout(timeout);
166
+ navigateWithoutReload(
167
+ getQueryUrl({
168
+ "$search": trimmedSearchText || void 0
169
+ })
170
+ );
171
+ return { isSuccessful: true };
155
172
  }, [currentSearch, getQueryUrl, navigateWithoutReload, searchText]);
156
173
  const hasFacetControls = showFacets && facetGroups.length > 0;
157
174
  const hasSortControls = showSortOptions && normalizedSortOptions.length > 0;
@@ -193,20 +210,57 @@ var DataBindingControls = ({
193
210
  ] });
194
211
  return /* @__PURE__ */ jsxs("div", { className: mode === "toolbar" ? "my-6" : "flex flex-col gap-2", children: [
195
212
  shouldShowToolbar && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
196
- showSearchBar && /* @__PURE__ */ jsx("div", { className: "w-full max-w-xl", children: /* @__PURE__ */ jsx(
197
- InputControl_default,
213
+ showSearchBar && /* @__PURE__ */ jsxs(
214
+ "form",
198
215
  {
199
- name: "searchText",
200
- controlType: InputControlType_default.lineTextInput,
201
- value: searchText,
202
- callback: (updatedValues) => setSearchText(updatedValues.value),
203
- attributes: { placeholder: "Search" },
204
- inputClasses: "!mt-0"
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
+ ]
205
252
  }
206
- ) }),
207
- hasSortControls && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-sm", children: [
208
- /* @__PURE__ */ jsx("span", { className: "font-medium", children: "Sort by" }),
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: [
209
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(
210
264
  InputControl_default,
211
265
  {
212
266
  name: "sortOptions",
@@ -222,9 +276,9 @@ var DataBindingControls = ({
222
276
  })
223
277
  ),
224
278
  attributes: { placeholder: "Default" },
225
- inputClasses: "!mt-0 min-w-44"
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"
226
280
  }
227
- )
281
+ ) })
228
282
  ] })
229
283
  ] }),
230
284
  shouldShowFacets && facetGroups.length === 1 && /* @__PURE__ */ jsx("nav", { "aria-label": `${humanize(facetGroups[0][0])} filters`, children: renderFacetLinks(facetGroups[0][0], facetGroups[0][1]) }),
@@ -2,6 +2,10 @@
2
2
  import {
3
3
  InputControlType_default
4
4
  } from "./chunk-IEY342PD.mjs";
5
+ import {
6
+ Button_default
7
+ } from "./chunk-4WMSS6CE.mjs";
8
+ import "./chunk-56HSDML5.mjs";
5
9
 
6
10
  // src/components/pageRenderingEngine/nodes/DataBindingControls.tsx
7
11
  import { useCallback, useEffect, useRef, useState } from "react";
@@ -9,7 +13,7 @@ import { useRouter } from "next/navigation";
9
13
 
10
14
  // src/components/controls/edit/InputControl.tsx
11
15
  import dynamic from "next/dynamic";
12
- var InputControl = dynamic(() => import("./InputControlClient-3GUBYGP2.mjs"), {
16
+ var InputControl = dynamic(() => import("./InputControlClient-BZPWT7KE.mjs"), {
13
17
  ssr: false
14
18
  });
15
19
  var InputControl_default = InputControl;
@@ -44,6 +48,21 @@ var parseODataSearch = (value) => {
44
48
  }
45
49
  return trimmedValue;
46
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
+ );
47
66
  var normalizeSortOption = (option) => {
48
67
  const direction = option.direction.trim();
49
68
  return {
@@ -143,19 +162,17 @@ var DataBindingControls = ({
143
162
  },
144
163
  [router]
145
164
  );
146
- useEffect(() => {
165
+ const handleSearch = useCallback(async () => {
147
166
  const trimmedSearchText = searchText.trim();
148
167
  if (trimmedSearchText === currentSearch.trim()) {
149
- return;
168
+ return { isSuccessful: true };
150
169
  }
151
- const timeout = window.setTimeout(() => {
152
- navigateWithoutReload(
153
- getQueryUrl({
154
- "$search": trimmedSearchText || void 0
155
- })
156
- );
157
- }, 500);
158
- return () => window.clearTimeout(timeout);
170
+ navigateWithoutReload(
171
+ getQueryUrl({
172
+ "$search": trimmedSearchText || void 0
173
+ })
174
+ );
175
+ return { isSuccessful: true };
159
176
  }, [currentSearch, getQueryUrl, navigateWithoutReload, searchText]);
160
177
  const hasFacetControls = showFacets && facetGroups.length > 0;
161
178
  const hasSortControls = showSortOptions && normalizedSortOptions.length > 0;
@@ -197,20 +214,57 @@ var DataBindingControls = ({
197
214
  ] });
198
215
  return /* @__PURE__ */ jsxs("div", { className: mode === "toolbar" ? "my-6" : "flex flex-col gap-2", children: [
199
216
  shouldShowToolbar && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
200
- showSearchBar && /* @__PURE__ */ jsx("div", { className: "w-full max-w-xl", children: /* @__PURE__ */ jsx(
201
- InputControl_default,
217
+ showSearchBar && /* @__PURE__ */ jsxs(
218
+ "form",
202
219
  {
203
- name: "searchText",
204
- controlType: InputControlType_default.lineTextInput,
205
- value: searchText,
206
- callback: (updatedValues) => setSearchText(updatedValues.value),
207
- attributes: { placeholder: "Search" },
208
- inputClasses: "!mt-0"
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
+ ]
209
256
  }
210
- ) }),
211
- hasSortControls && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-sm", children: [
212
- /* @__PURE__ */ jsx("span", { className: "font-medium", children: "Sort by" }),
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: [
213
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(
214
268
  InputControl_default,
215
269
  {
216
270
  name: "sortOptions",
@@ -226,9 +280,9 @@ var DataBindingControls = ({
226
280
  })
227
281
  ),
228
282
  attributes: { placeholder: "Default" },
229
- inputClasses: "!mt-0 min-w-44"
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"
230
284
  }
231
- )
285
+ ) })
232
286
  ] })
233
287
  ] }),
234
288
  shouldShowFacets && facetGroups.length === 1 && /* @__PURE__ */ jsx("nav", { "aria-label": `${humanize(facetGroups[0][0])} filters`, children: renderFacetLinks(facetGroups[0][0], facetGroups[0][1]) }),
@@ -11,7 +11,7 @@ import {
11
11
  import {
12
12
  Button_default,
13
13
  ClientButton_default
14
- } from "./chunk-RHVNJMS4.mjs";
14
+ } from "./chunk-4WMSS6CE.mjs";
15
15
  import "./chunk-56HSDML5.mjs";
16
16
  import {
17
17
  AssetUtility_default
@@ -19,18 +19,18 @@ import {
19
19
  Select_default,
20
20
  TimeInput_default
21
21
  } from "./chunk-BF4G3ZGG.mjs";
22
- import {
23
- Button_default,
24
- ClientButton_default
25
- } from "./chunk-23WJE3YB.mjs";
26
22
  import {
27
23
  Hyperlink,
28
24
  Icon_default
29
25
  } from "./chunk-GCG4OYDJ.mjs";
30
- import "./chunk-IMNQO57B.mjs";
26
+ import {
27
+ Button_default,
28
+ ClientButton_default
29
+ } from "./chunk-LSKD5U3S.mjs";
31
30
  import {
32
31
  InputControlType_default
33
32
  } from "./chunk-DTWPZPSX.mjs";
33
+ import "./chunk-IMNQO57B.mjs";
34
34
  import {
35
35
  AssetUtility_default
36
36
  } from "./chunk-UPCAOGEY.mjs";
@@ -7,7 +7,7 @@ import {
7
7
  import {
8
8
  Button_default,
9
9
  ToastService_default
10
- } from "./chunk-23WJE3YB.mjs";
10
+ } from "./chunk-LSKD5U3S.mjs";
11
11
  import "./chunk-IMNQO57B.mjs";
12
12
 
13
13
  // src/components/pageRenderingEngine/nodes/LinkNodeButton.tsx
@@ -191,13 +191,16 @@ var LinkNodeButton = (props) => {
191
191
  return node.title || "Button";
192
192
  };
193
193
  const fontSize = node.children?.[0]?.style?.match(/font-size:\s*([^;]+)/)?.[1];
194
+ const isCustomButton = Boolean(node.customButtonClass);
195
+ const buttonClass = isCustomButton ? node.customButtonClass ?? "" : ["w-full", node.customButtonClass].filter(Boolean).join(" ");
194
196
  return /* @__PURE__ */ jsx("div", { className: "link-button-wrapper", children: /* @__PURE__ */ jsx(
195
197
  Button_default,
196
198
  {
197
199
  ButtonType: linkType,
198
200
  onClick,
199
201
  disabled: isLoading || !!successMessage,
200
- className: "w-full",
202
+ className: buttonClass,
203
+ isCustomButton,
201
204
  children: successMessage ? /* @__PURE__ */ jsxs(
202
205
  "span",
203
206
  {
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  Button_default,
4
4
  ToastService_default
5
- } from "./chunk-RHVNJMS4.mjs";
5
+ } from "./chunk-4WMSS6CE.mjs";
6
6
  import {
7
7
  ServiceClient_default
8
8
  } from "./chunk-WXZMRMRS.mjs";
@@ -189,13 +189,16 @@ var LinkNodeButton = (props) => {
189
189
  return node.title || "Button";
190
190
  };
191
191
  const fontSize = node.children?.[0]?.style?.match(/font-size:\s*([^;]+)/)?.[1];
192
+ const isCustomButton = Boolean(node.customButtonClass);
193
+ const buttonClass = isCustomButton ? node.customButtonClass ?? "" : ["w-full", node.customButtonClass].filter(Boolean).join(" ");
192
194
  return /* @__PURE__ */ jsx("div", { className: "link-button-wrapper", children: /* @__PURE__ */ jsx(
193
195
  Button_default,
194
196
  {
195
197
  ButtonType: linkType,
196
198
  onClick,
197
199
  disabled: isLoading || !!successMessage,
198
- className: "w-full",
200
+ className: buttonClass,
201
+ isCustomButton,
199
202
  children: successMessage ? /* @__PURE__ */ jsxs(
200
203
  "span",
201
204
  {
@@ -192,7 +192,7 @@ var Button = (props) => {
192
192
  );
193
193
  });
194
194
  };
195
- let buttonClass = props.ButtonType ? buttonClasses.get(props.ButtonType) : buttonClasses.get("Primary" /* Solid */);
195
+ let buttonClass = props.isCustomButton ? props.ButtonType ? buttonClasses.get(props.ButtonType) ?? "" : "" : props.ButtonType ? buttonClasses.get(props.ButtonType) : buttonClasses.get("Primary" /* Solid */);
196
196
  let progressClass = props.ButtonType ? progressClasses.get(props.ButtonType) : progressClasses.get("Primary" /* Solid */);
197
197
  const isDisabled = inProgress || isActionPerformed && props.oneTimeAction;
198
198
  return /* @__PURE__ */ jsxs2(React3.Fragment, { children: [
@@ -203,7 +203,7 @@ var Button = (props) => {
203
203
  onClick: execute,
204
204
  disabled: props.disabled,
205
205
  title: isDisabled ? "The button is disabled to prevent any action" : "",
206
- className: `${buttonClass} relative inline-flex items-center justify-center gap-2 ${props.className ?? ""}`,
206
+ className: props.isCustomButton ? `${buttonClass ? buttonClass + " " : ""}${props.className ?? ""}`.trim() : `${buttonClass} relative inline-flex items-center justify-center gap-2 ${props.className ?? ""}`.trim(),
207
207
  children: [
208
208
  isActionPerformed && props.oneTimeAction && responseMessage ? responseMessage : props.children,
209
209
  inProgress && /* @__PURE__ */ jsx3(Fragment2, { children: props.hideProgressIndicator ? /* @__PURE__ */ jsx3("div", { className: "absolute bottom-0 left-0 h-0.5 bg-gray-400 rounded animate-progress" }) : /* @__PURE__ */ jsxs2(
@@ -3,7 +3,7 @@
3
3
 
4
4
  // src/components/controls/edit/InputControl.tsx
5
5
  import dynamic from "next/dynamic";
6
- var InputControl = dynamic(() => import("./InputControlClient-Y3IT2BUV.mjs"), {
6
+ var InputControl = dynamic(() => import("./InputControlClient-DZGLI4DU.mjs"), {
7
7
  ssr: false
8
8
  });
9
9
  var InputControl_default = InputControl;
@@ -194,7 +194,7 @@ var Button = (props) => {
194
194
  );
195
195
  });
196
196
  };
197
- let buttonClass = props.ButtonType ? buttonClasses.get(props.ButtonType) : buttonClasses.get("Primary" /* Solid */);
197
+ let buttonClass = props.isCustomButton ? props.ButtonType ? buttonClasses.get(props.ButtonType) ?? "" : "" : props.ButtonType ? buttonClasses.get(props.ButtonType) : buttonClasses.get("Primary" /* Solid */);
198
198
  let progressClass = props.ButtonType ? progressClasses.get(props.ButtonType) : progressClasses.get("Primary" /* Solid */);
199
199
  const isDisabled = inProgress || isActionPerformed && props.oneTimeAction;
200
200
  return /* @__PURE__ */ jsxs2(React3.Fragment, { children: [
@@ -205,7 +205,7 @@ var Button = (props) => {
205
205
  onClick: execute,
206
206
  disabled: props.disabled,
207
207
  title: isDisabled ? "The button is disabled to prevent any action" : "",
208
- className: `${buttonClass} relative inline-flex items-center justify-center gap-2 ${props.className ?? ""}`,
208
+ className: props.isCustomButton ? `${buttonClass ? buttonClass + " " : ""}${props.className ?? ""}`.trim() : `${buttonClass} relative inline-flex items-center justify-center gap-2 ${props.className ?? ""}`.trim(),
209
209
  children: [
210
210
  isActionPerformed && props.oneTimeAction && responseMessage ? responseMessage : props.children,
211
211
  inProgress && /* @__PURE__ */ jsx3(Fragment2, { children: props.hideProgressIndicator ? /* @__PURE__ */ jsx3("div", { className: "absolute bottom-0 left-0 h-0.5 bg-gray-400 rounded animate-progress" }) : /* @__PURE__ */ jsxs2(
package/dist/index.d.mts CHANGED
@@ -250,6 +250,7 @@ interface ButtonProps<T> {
250
250
  confirm?: boolean;
251
251
  confirmationMessage?: string;
252
252
  disabled?: boolean;
253
+ isCustomButton?: boolean;
253
254
  }
254
255
  declare const Button: React__default.FC<ButtonProps<any>>;
255
256
 
package/dist/index.d.ts CHANGED
@@ -250,6 +250,7 @@ interface ButtonProps<T> {
250
250
  confirm?: boolean;
251
251
  confirmationMessage?: string;
252
252
  disabled?: boolean;
253
+ isCustomButton?: boolean;
253
254
  }
254
255
  declare const Button: React__default.FC<ButtonProps<any>>;
255
256
 
package/dist/index.js CHANGED
@@ -3382,7 +3382,7 @@ var init_Button = __esm({
3382
3382
  );
3383
3383
  });
3384
3384
  };
3385
- let buttonClass = props.ButtonType ? buttonClasses.get(props.ButtonType) : buttonClasses.get("Primary" /* Solid */);
3385
+ let buttonClass = props.isCustomButton ? props.ButtonType ? buttonClasses.get(props.ButtonType) ?? "" : "" : props.ButtonType ? buttonClasses.get(props.ButtonType) : buttonClasses.get("Primary" /* Solid */);
3386
3386
  let progressClass = props.ButtonType ? progressClasses.get(props.ButtonType) : progressClasses.get("Primary" /* Solid */);
3387
3387
  const isDisabled = inProgress || isActionPerformed && props.oneTimeAction;
3388
3388
  return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(import_react37.default.Fragment, { children: [
@@ -3393,7 +3393,7 @@ var init_Button = __esm({
3393
3393
  onClick: execute,
3394
3394
  disabled: props.disabled,
3395
3395
  title: isDisabled ? "The button is disabled to prevent any action" : "",
3396
- className: `${buttonClass} relative inline-flex items-center justify-center gap-2 ${props.className ?? ""}`,
3396
+ className: props.isCustomButton ? `${buttonClass ? buttonClass + " " : ""}${props.className ?? ""}`.trim() : `${buttonClass} relative inline-flex items-center justify-center gap-2 ${props.className ?? ""}`.trim(),
3397
3397
  children: [
3398
3398
  isActionPerformed && props.oneTimeAction && responseMessage ? responseMessage : props.children,
3399
3399
  inProgress && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_jsx_runtime44.Fragment, { children: props.hideProgressIndicator ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "absolute bottom-0 left-0 h-0.5 bg-gray-400 rounded animate-progress" }) : /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
@@ -4960,13 +4960,16 @@ var init_LinkNodeButton = __esm({
4960
4960
  return node.title || "Button";
4961
4961
  };
4962
4962
  const fontSize = node.children?.[0]?.style?.match(/font-size:\s*([^;]+)/)?.[1];
4963
+ const isCustomButton = Boolean(node.customButtonClass);
4964
+ const buttonClass = isCustomButton ? node.customButtonClass ?? "" : ["w-full", node.customButtonClass].filter(Boolean).join(" ");
4963
4965
  return /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("div", { className: "link-button-wrapper", children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
4964
4966
  Button_default,
4965
4967
  {
4966
4968
  ButtonType: linkType,
4967
4969
  onClick,
4968
4970
  disabled: isLoading || !!successMessage,
4969
- className: "w-full",
4971
+ className: buttonClass,
4972
+ isCustomButton,
4970
4973
  children: successMessage ? /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(
4971
4974
  "span",
4972
4975
  {
@@ -5605,15 +5608,17 @@ var DataBindingControls_exports = {};
5605
5608
  __export(DataBindingControls_exports, {
5606
5609
  default: () => DataBindingControls_default
5607
5610
  });
5608
- var import_react59, import_navigation, import_jsx_runtime85, humanize, escapeODataString, parseFacetSelections, buildFacetFilter, parseODataSearch, normalizeSortOption, DUMMY_FACETS, DUMMY_SORT_OPTIONS, DataBindingControls, DataBindingControls_default;
5611
+ var import_react59, import_navigation, import_jsx_runtime85, humanize, escapeODataString, parseFacetSelections, buildFacetFilter, parseODataSearch, SearchIcon, normalizeSortOption, DUMMY_FACETS, DUMMY_SORT_OPTIONS, DataBindingControls, DataBindingControls_default;
5609
5612
  var init_DataBindingControls = __esm({
5610
5613
  "src/components/pageRenderingEngine/nodes/DataBindingControls.tsx"() {
5611
5614
  "use strict";
5612
5615
  "use client";
5613
5616
  import_react59 = require("react");
5614
5617
  import_navigation = require("next/navigation");
5618
+ init_Button();
5615
5619
  init_InputControl();
5616
5620
  init_InputControlType();
5621
+ init_StyleTypes();
5617
5622
  import_jsx_runtime85 = require("react/jsx-runtime");
5618
5623
  humanize = (value) => value.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[_-]+/g, " ").trim();
5619
5624
  escapeODataString = (value) => value.replace(/'/g, "''");
@@ -5643,6 +5648,21 @@ var init_DataBindingControls = __esm({
5643
5648
  }
5644
5649
  return trimmedValue;
5645
5650
  };
5651
+ SearchIcon = ({ className = "" }) => /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)(
5652
+ "svg",
5653
+ {
5654
+ "aria-hidden": "true",
5655
+ className,
5656
+ fill: "none",
5657
+ viewBox: "0 0 24 24",
5658
+ stroke: "currentColor",
5659
+ strokeWidth: "2",
5660
+ children: [
5661
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("circle", { cx: "11", cy: "11", r: "7" }),
5662
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("path", { strokeLinecap: "round", d: "m20 20-4-4" })
5663
+ ]
5664
+ }
5665
+ );
5646
5666
  normalizeSortOption = (option) => {
5647
5667
  const direction = option.direction.trim();
5648
5668
  return {
@@ -5742,19 +5762,17 @@ var init_DataBindingControls = __esm({
5742
5762
  },
5743
5763
  [router]
5744
5764
  );
5745
- (0, import_react59.useEffect)(() => {
5765
+ const handleSearch = (0, import_react59.useCallback)(async () => {
5746
5766
  const trimmedSearchText = searchText.trim();
5747
5767
  if (trimmedSearchText === currentSearch.trim()) {
5748
- return;
5768
+ return { isSuccessful: true };
5749
5769
  }
5750
- const timeout = window.setTimeout(() => {
5751
- navigateWithoutReload(
5752
- getQueryUrl({
5753
- "$search": trimmedSearchText || void 0
5754
- })
5755
- );
5756
- }, 500);
5757
- return () => window.clearTimeout(timeout);
5770
+ navigateWithoutReload(
5771
+ getQueryUrl({
5772
+ "$search": trimmedSearchText || void 0
5773
+ })
5774
+ );
5775
+ return { isSuccessful: true };
5758
5776
  }, [currentSearch, getQueryUrl, navigateWithoutReload, searchText]);
5759
5777
  const hasFacetControls = showFacets && facetGroups.length > 0;
5760
5778
  const hasSortControls = showSortOptions && normalizedSortOptions.length > 0;
@@ -5796,20 +5814,57 @@ var init_DataBindingControls = __esm({
5796
5814
  ] });
5797
5815
  return /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: mode === "toolbar" ? "my-6" : "flex flex-col gap-2", children: [
5798
5816
  shouldShowToolbar && /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
5799
- showSearchBar && /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("div", { className: "w-full max-w-xl", children: /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(
5800
- InputControl_default,
5817
+ showSearchBar && /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)(
5818
+ "form",
5801
5819
  {
5802
- name: "searchText",
5803
- controlType: InputControlType_default.lineTextInput,
5804
- value: searchText,
5805
- callback: (updatedValues) => setSearchText(updatedValues.value),
5806
- attributes: { placeholder: "Search" },
5807
- inputClasses: "!mt-0"
5820
+ role: "search",
5821
+ 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",
5822
+ onSubmit: (event) => {
5823
+ event.preventDefault();
5824
+ void handleSearch();
5825
+ },
5826
+ children: [
5827
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: "relative bg-default rounded-xl min-w-0 flex-1", children: [
5828
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(SearchIcon, { className: "pointer-events-none absolute left-4 top-1/2 z-10 h-5 w-5 -translate-y-1/2" }),
5829
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(
5830
+ InputControl_default,
5831
+ {
5832
+ name: "searchText",
5833
+ controlType: InputControlType_default.lineTextInput,
5834
+ value: searchText,
5835
+ callback: (updatedValues) => setSearchText(updatedValues.value),
5836
+ attributes: {
5837
+ placeholder: "Search discussions, topics, or keywords..."
5838
+ },
5839
+ inputClasses: "!mt-0 !rounded-xl !py-3 !pl-11 !pr-4 !shadow-sm"
5840
+ }
5841
+ )
5842
+ ] }),
5843
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)(
5844
+ Button_default,
5845
+ {
5846
+ ButtonType: "Primary" /* Solid */,
5847
+ onClick: handleSearch,
5848
+ className: "!rounded-xl !px-6 !py-3 sm:self-stretch",
5849
+ children: [
5850
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(SearchIcon, { className: "h-5 w-5" }),
5851
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { children: "Search" })
5852
+ ]
5853
+ }
5854
+ )
5855
+ ]
5808
5856
  }
5809
- ) }),
5810
- hasSortControls && /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: "flex items-center gap-2 text-sm", children: [
5811
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { className: "font-medium", children: "Sort by" }),
5857
+ ),
5858
+ hasSortControls && /* @__PURE__ */ (0, import_jsx_runtime85.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: [
5812
5859
  /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(
5860
+ "label",
5861
+ {
5862
+ htmlFor: "sortOptions",
5863
+ className: "shrink-0 whitespace-nowrap font-medium",
5864
+ children: "Sort by"
5865
+ }
5866
+ ),
5867
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("div", { className: "min-w-0 flex-1 rounded-xl bg-default md:min-w-48", children: /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(
5813
5868
  InputControl_default,
5814
5869
  {
5815
5870
  name: "sortOptions",
@@ -5825,9 +5880,9 @@ var init_DataBindingControls = __esm({
5825
5880
  })
5826
5881
  ),
5827
5882
  attributes: { placeholder: "Default" },
5828
- inputClasses: "!mt-0 min-w-44"
5883
+ inputClasses: "!mt-0 !rounded-xl !border-info !bg-default !px-4 !py-3 !text-body !shadow-sm focus:!border-primary focus:!ring-primary-base"
5829
5884
  }
5830
- )
5885
+ ) })
5831
5886
  ] })
5832
5887
  ] }),
5833
5888
  shouldShowFacets && facetGroups.length === 1 && /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("nav", { "aria-label": `${humanize(facetGroups[0][0])} filters`, children: renderFacetLinks(facetGroups[0][0], facetGroups[0][1]) }),
@@ -6951,6 +7006,7 @@ var LinkNode = (props) => {
6951
7006
  {
6952
7007
  href: linkUrl || "#",
6953
7008
  linkType,
7009
+ className: node.customButtonClass,
6954
7010
  alt: linkText || node.title || "",
6955
7011
  children: [
6956
7012
  renderChildren2(),
package/dist/index.mjs CHANGED
@@ -8,7 +8,7 @@ import {
8
8
  } from "./chunk-RG3CISAA.mjs";
9
9
  import {
10
10
  InputControl_default
11
- } from "./chunk-PIMVBXWS.mjs";
11
+ } from "./chunk-6GVLDYCQ.mjs";
12
12
  import "./chunk-JDX47MFV.mjs";
13
13
  import {
14
14
  CheckboxInput_default,
@@ -28,20 +28,20 @@ import {
28
28
  Select_default,
29
29
  TimeInput_default
30
30
  } from "./chunk-BF4G3ZGG.mjs";
31
- import {
32
- Button_default,
33
- ClientButton_default,
34
- ToastService_default
35
- } from "./chunk-23WJE3YB.mjs";
36
31
  import {
37
32
  Hyperlink,
38
33
  Icon_default
39
34
  } from "./chunk-GCG4OYDJ.mjs";
40
- import "./chunk-IMNQO57B.mjs";
35
+ import {
36
+ Button_default,
37
+ ClientButton_default,
38
+ ToastService_default
39
+ } from "./chunk-LSKD5U3S.mjs";
41
40
  import {
42
41
  Constants,
43
42
  InputControlType_default
44
43
  } from "./chunk-DTWPZPSX.mjs";
44
+ import "./chunk-IMNQO57B.mjs";
45
45
  import {
46
46
  AssetUtility_default
47
47
  } from "./chunk-UPCAOGEY.mjs";
@@ -658,7 +658,7 @@ var ImageNode_default = ImageNode;
658
658
  // src/components/pageRenderingEngine/nodes/LinkNode.tsx
659
659
  import dynamic8 from "next/dynamic";
660
660
  import { Fragment, jsx as jsx19, jsxs as jsxs7 } from "react/jsx-runtime";
661
- var LinkNodeButton = dynamic8(() => import("./LinkNodeButton-X75YEE2O.mjs"), {
661
+ var LinkNodeButton = dynamic8(() => import("./LinkNodeButton-EZFQLUKA.mjs"), {
662
662
  ssr: false
663
663
  });
664
664
  function getNestedValue2(obj, path) {
@@ -760,6 +760,7 @@ var LinkNode = (props) => {
760
760
  {
761
761
  href: linkUrl || "#",
762
762
  linkType,
763
+ className: node.customButtonClass,
763
764
  alt: linkText || node.title || "",
764
765
  children: [
765
766
  renderChildren(),
@@ -2347,8 +2348,8 @@ var GoogleMapNode_default = GoogleMapNode;
2347
2348
 
2348
2349
  // src/components/pageRenderingEngine/nodes/DivContainer.tsx
2349
2350
  import { jsx as jsx36, jsxs as jsxs14 } from "react/jsx-runtime";
2350
- var Pagination = dynamic13(() => import("./Pagination-CQKMBXXJ.mjs"), { ssr: true });
2351
- var DataBindingControls = dynamic13(() => import("./DataBindingControls-44OP5UE6.mjs"), {
2351
+ var Pagination = dynamic13(() => import("./Pagination-PGAK7KDA.mjs"), { ssr: true });
2352
+ var DataBindingControls = dynamic13(() => import("./DataBindingControls-2CSX5L5I.mjs"), {
2352
2353
  ssr: true
2353
2354
  });
2354
2355
  var Slider = dynamic13(() => import("./Slider-IVPJBPE5.mjs"), {
package/dist/server.js CHANGED
@@ -945,7 +945,7 @@ var init_Button = __esm({
945
945
  );
946
946
  });
947
947
  };
948
- let buttonClass = props.ButtonType ? buttonClasses.get(props.ButtonType) : buttonClasses.get("Primary" /* Solid */);
948
+ let buttonClass = props.isCustomButton ? props.ButtonType ? buttonClasses.get(props.ButtonType) ?? "" : "" : props.ButtonType ? buttonClasses.get(props.ButtonType) : buttonClasses.get("Primary" /* Solid */);
949
949
  let progressClass = props.ButtonType ? progressClasses.get(props.ButtonType) : progressClasses.get("Primary" /* Solid */);
950
950
  const isDisabled = inProgress || isActionPerformed && props.oneTimeAction;
951
951
  return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_react4.default.Fragment, { children: [
@@ -956,7 +956,7 @@ var init_Button = __esm({
956
956
  onClick: execute,
957
957
  disabled: props.disabled,
958
958
  title: isDisabled ? "The button is disabled to prevent any action" : "",
959
- className: `${buttonClass} relative inline-flex items-center justify-center gap-2 ${props.className ?? ""}`,
959
+ className: props.isCustomButton ? `${buttonClass ? buttonClass + " " : ""}${props.className ?? ""}`.trim() : `${buttonClass} relative inline-flex items-center justify-center gap-2 ${props.className ?? ""}`.trim(),
960
960
  children: [
961
961
  isActionPerformed && props.oneTimeAction && responseMessage ? responseMessage : props.children,
962
962
  inProgress && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_jsx_runtime9.Fragment, { children: props.hideProgressIndicator ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "absolute bottom-0 left-0 h-0.5 bg-gray-400 rounded animate-progress" }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
@@ -1422,13 +1422,16 @@ var init_LinkNodeButton = __esm({
1422
1422
  return node.title || "Button";
1423
1423
  };
1424
1424
  const fontSize = node.children?.[0]?.style?.match(/font-size:\s*([^;]+)/)?.[1];
1425
+ const isCustomButton = Boolean(node.customButtonClass);
1426
+ const buttonClass = isCustomButton ? node.customButtonClass ?? "" : ["w-full", node.customButtonClass].filter(Boolean).join(" ");
1425
1427
  return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "link-button-wrapper", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1426
1428
  Button_default,
1427
1429
  {
1428
1430
  ButtonType: linkType,
1429
1431
  onClick,
1430
1432
  disabled: isLoading || !!successMessage,
1431
- className: "w-full",
1433
+ className: buttonClass,
1434
+ isCustomButton,
1432
1435
  children: successMessage ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
1433
1436
  "span",
1434
1437
  {
@@ -5603,15 +5606,17 @@ var DataBindingControls_exports = {};
5603
5606
  __export(DataBindingControls_exports, {
5604
5607
  default: () => DataBindingControls_default
5605
5608
  });
5606
- var import_react59, import_navigation, import_jsx_runtime85, humanize, escapeODataString, parseFacetSelections, buildFacetFilter, parseODataSearch, normalizeSortOption, DUMMY_FACETS, DUMMY_SORT_OPTIONS, DataBindingControls, DataBindingControls_default;
5609
+ var import_react59, import_navigation, import_jsx_runtime85, humanize, escapeODataString, parseFacetSelections, buildFacetFilter, parseODataSearch, SearchIcon, normalizeSortOption, DUMMY_FACETS, DUMMY_SORT_OPTIONS, DataBindingControls, DataBindingControls_default;
5607
5610
  var init_DataBindingControls = __esm({
5608
5611
  "src/components/pageRenderingEngine/nodes/DataBindingControls.tsx"() {
5609
5612
  "use strict";
5610
5613
  "use client";
5611
5614
  import_react59 = require("react");
5612
5615
  import_navigation = require("next/navigation");
5616
+ init_Button();
5613
5617
  init_InputControl();
5614
5618
  init_InputControlType();
5619
+ init_StyleTypes();
5615
5620
  import_jsx_runtime85 = require("react/jsx-runtime");
5616
5621
  humanize = (value) => value.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[_-]+/g, " ").trim();
5617
5622
  escapeODataString = (value) => value.replace(/'/g, "''");
@@ -5641,6 +5646,21 @@ var init_DataBindingControls = __esm({
5641
5646
  }
5642
5647
  return trimmedValue;
5643
5648
  };
5649
+ SearchIcon = ({ className = "" }) => /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)(
5650
+ "svg",
5651
+ {
5652
+ "aria-hidden": "true",
5653
+ className,
5654
+ fill: "none",
5655
+ viewBox: "0 0 24 24",
5656
+ stroke: "currentColor",
5657
+ strokeWidth: "2",
5658
+ children: [
5659
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("circle", { cx: "11", cy: "11", r: "7" }),
5660
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("path", { strokeLinecap: "round", d: "m20 20-4-4" })
5661
+ ]
5662
+ }
5663
+ );
5644
5664
  normalizeSortOption = (option) => {
5645
5665
  const direction = option.direction.trim();
5646
5666
  return {
@@ -5740,19 +5760,17 @@ var init_DataBindingControls = __esm({
5740
5760
  },
5741
5761
  [router]
5742
5762
  );
5743
- (0, import_react59.useEffect)(() => {
5763
+ const handleSearch = (0, import_react59.useCallback)(async () => {
5744
5764
  const trimmedSearchText = searchText.trim();
5745
5765
  if (trimmedSearchText === currentSearch.trim()) {
5746
- return;
5766
+ return { isSuccessful: true };
5747
5767
  }
5748
- const timeout = window.setTimeout(() => {
5749
- navigateWithoutReload(
5750
- getQueryUrl({
5751
- "$search": trimmedSearchText || void 0
5752
- })
5753
- );
5754
- }, 500);
5755
- return () => window.clearTimeout(timeout);
5768
+ navigateWithoutReload(
5769
+ getQueryUrl({
5770
+ "$search": trimmedSearchText || void 0
5771
+ })
5772
+ );
5773
+ return { isSuccessful: true };
5756
5774
  }, [currentSearch, getQueryUrl, navigateWithoutReload, searchText]);
5757
5775
  const hasFacetControls = showFacets && facetGroups.length > 0;
5758
5776
  const hasSortControls = showSortOptions && normalizedSortOptions.length > 0;
@@ -5794,20 +5812,57 @@ var init_DataBindingControls = __esm({
5794
5812
  ] });
5795
5813
  return /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: mode === "toolbar" ? "my-6" : "flex flex-col gap-2", children: [
5796
5814
  shouldShowToolbar && /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
5797
- showSearchBar && /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("div", { className: "w-full max-w-xl", children: /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(
5798
- InputControl_default,
5815
+ showSearchBar && /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)(
5816
+ "form",
5799
5817
  {
5800
- name: "searchText",
5801
- controlType: InputControlType_default.lineTextInput,
5802
- value: searchText,
5803
- callback: (updatedValues) => setSearchText(updatedValues.value),
5804
- attributes: { placeholder: "Search" },
5805
- inputClasses: "!mt-0"
5818
+ role: "search",
5819
+ 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",
5820
+ onSubmit: (event) => {
5821
+ event.preventDefault();
5822
+ void handleSearch();
5823
+ },
5824
+ children: [
5825
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: "relative bg-default rounded-xl min-w-0 flex-1", children: [
5826
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(SearchIcon, { className: "pointer-events-none absolute left-4 top-1/2 z-10 h-5 w-5 -translate-y-1/2" }),
5827
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(
5828
+ InputControl_default,
5829
+ {
5830
+ name: "searchText",
5831
+ controlType: InputControlType_default.lineTextInput,
5832
+ value: searchText,
5833
+ callback: (updatedValues) => setSearchText(updatedValues.value),
5834
+ attributes: {
5835
+ placeholder: "Search discussions, topics, or keywords..."
5836
+ },
5837
+ inputClasses: "!mt-0 !rounded-xl !py-3 !pl-11 !pr-4 !shadow-sm"
5838
+ }
5839
+ )
5840
+ ] }),
5841
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)(
5842
+ Button_default,
5843
+ {
5844
+ ButtonType: "Primary" /* Solid */,
5845
+ onClick: handleSearch,
5846
+ className: "!rounded-xl !px-6 !py-3 sm:self-stretch",
5847
+ children: [
5848
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(SearchIcon, { className: "h-5 w-5" }),
5849
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { children: "Search" })
5850
+ ]
5851
+ }
5852
+ )
5853
+ ]
5806
5854
  }
5807
- ) }),
5808
- hasSortControls && /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: "flex items-center gap-2 text-sm", children: [
5809
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { className: "font-medium", children: "Sort by" }),
5855
+ ),
5856
+ hasSortControls && /* @__PURE__ */ (0, import_jsx_runtime85.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: [
5810
5857
  /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(
5858
+ "label",
5859
+ {
5860
+ htmlFor: "sortOptions",
5861
+ className: "shrink-0 whitespace-nowrap font-medium",
5862
+ children: "Sort by"
5863
+ }
5864
+ ),
5865
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("div", { className: "min-w-0 flex-1 rounded-xl bg-default md:min-w-48", children: /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(
5811
5866
  InputControl_default,
5812
5867
  {
5813
5868
  name: "sortOptions",
@@ -5823,9 +5878,9 @@ var init_DataBindingControls = __esm({
5823
5878
  })
5824
5879
  ),
5825
5880
  attributes: { placeholder: "Default" },
5826
- inputClasses: "!mt-0 min-w-44"
5881
+ inputClasses: "!mt-0 !rounded-xl !border-info !bg-default !px-4 !py-3 !text-body !shadow-sm focus:!border-primary focus:!ring-primary-base"
5827
5882
  }
5828
- )
5883
+ ) })
5829
5884
  ] })
5830
5885
  ] }),
5831
5886
  shouldShowFacets && facetGroups.length === 1 && /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("nav", { "aria-label": `${humanize(facetGroups[0][0])} filters`, children: renderFacetLinks(facetGroups[0][0], facetGroups[0][1]) }),
@@ -6584,6 +6639,7 @@ var LinkNode = (props) => {
6584
6639
  {
6585
6640
  href: linkUrl || "#",
6586
6641
  linkType,
6642
+ className: node.customButtonClass,
6587
6643
  alt: linkText || node.title || "",
6588
6644
  children: [
6589
6645
  renderChildren2(),
package/dist/server.mjs CHANGED
@@ -291,7 +291,7 @@ var ImageNode_default = ImageNode;
291
291
  // src/components/pageRenderingEngine/nodes/LinkNode.tsx
292
292
  import dynamic3 from "next/dynamic";
293
293
  import { Fragment, jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
294
- var LinkNodeButton = dynamic3(() => import("./LinkNodeButton-MUX27SFO.mjs"), {
294
+ var LinkNodeButton = dynamic3(() => import("./LinkNodeButton-WXAW3ZD6.mjs"), {
295
295
  ssr: false
296
296
  });
297
297
  function getNestedValue2(obj, path) {
@@ -393,6 +393,7 @@ var LinkNode = (props) => {
393
393
  {
394
394
  href: linkUrl || "#",
395
395
  linkType,
396
+ className: node.customButtonClass,
396
397
  alt: linkText || node.title || "",
397
398
  children: [
398
399
  renderChildren(),
@@ -2316,7 +2317,7 @@ var GoogleMapNode_default = GoogleMapNode;
2316
2317
  // src/components/pageRenderingEngine/nodes/DivContainer.tsx
2317
2318
  import { jsx as jsx36, jsxs as jsxs14 } from "react/jsx-runtime";
2318
2319
  var Pagination = dynamic13(() => import("./Pagination-M3VZKKXY.mjs"), { ssr: true });
2319
- var DataBindingControls = dynamic13(() => import("./DataBindingControls-6VOZSGOL.mjs"), {
2320
+ var DataBindingControls = dynamic13(() => import("./DataBindingControls-F72KPWHV.mjs"), {
2320
2321
  ssr: true
2321
2322
  });
2322
2323
  var Slider = dynamic13(() => import("./Slider-QIGKP6AE.mjs"), {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clyrex-digital/clyrex-controls-dev",
3
- "version": "0.8.1-dev.20260910063325",
3
+ "version": "0.8.1-dev.20260916063140",
4
4
  "description": "Reusable React components",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -8,10 +8,10 @@ import {
8
8
  Hyperlink,
9
9
  Icon_default
10
10
  } from "./chunk-GCG4OYDJ.mjs";
11
- import "./chunk-IMNQO57B.mjs";
12
11
  import {
13
12
  Constants
14
13
  } from "./chunk-DTWPZPSX.mjs";
14
+ import "./chunk-IMNQO57B.mjs";
15
15
 
16
16
  // src/components/Pagination.tsx
17
17
  import { useMemo } from "react";