@clyrex-digital/clyrex-controls-dev 0.8.1-dev.20260924103055 → 0.8.1-dev.20260924115534

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -5686,7 +5686,7 @@ var DataBindingControls_exports = {};
5686
5686
  __export(DataBindingControls_exports, {
5687
5687
  default: () => DataBindingControls_default
5688
5688
  });
5689
- var import_react59, import_navigation, import_jsx_runtime86, ACTIVE_QUERY_CONTROLS_EVENT, humanize, escapeODataString, parseFacetSelections, buildFacetFilter, parseODataSearch, SearchIcon, ResetIcon, normalizeSortOption, DataBindingControls, DataBindingControls_default;
5689
+ var import_react59, import_navigation, import_jsx_runtime86, humanize, escapeODataString, parseFacetSelections, buildFacetFilter, parseODataSearch, SearchIcon, ResetIcon, FilterSlidersIcon, ChevronDownIcon, CheckIcon, CloseIcon, normalizeSortOption, DataBindingControls, DataBindingControls_default;
5690
5690
  var init_DataBindingControls = __esm({
5691
5691
  "src/components/pageRenderingEngine/nodes/DataBindingControls.tsx"() {
5692
5692
  "use strict";
@@ -5698,22 +5698,15 @@ var init_DataBindingControls = __esm({
5698
5698
  init_InputControlType();
5699
5699
  init_StyleTypes();
5700
5700
  import_jsx_runtime86 = require("react/jsx-runtime");
5701
- ACTIVE_QUERY_CONTROLS_EVENT = "data-binding-active-query-controls";
5702
5701
  humanize = (value) => value.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[_-]+/g, " ").trim();
5703
5702
  escapeODataString = (value) => value.replace(/'/g, "''");
5704
5703
  parseFacetSelections = (filter) => {
5705
5704
  const selections = /* @__PURE__ */ new Map();
5706
- const groupedExpression = /\(\s*([^()]+?)\s+eq\s+'((?:''|[^'])*)'\s*\)/gi;
5707
- for (const match of filter.matchAll(groupedExpression)) {
5708
- selections.set(match[1].trim(), match[2].replace(/''/g, "'"));
5709
- }
5710
- if (selections.size === 0) {
5711
- const ungroupedExpression = /(?:^|\s+and\s+)\s*([^()]+?)\s+eq\s+'((?:''|[^'])*)'\s*(?=\s+and\s+|$)/gi;
5712
- for (const match of filter.matchAll(ungroupedExpression)) {
5713
- selections.set(
5714
- match[1].trim(),
5715
- match[2].replace(/''/g, "'")
5716
- );
5705
+ if (!filter || !filter.trim()) return selections;
5706
+ const expression = /(?:^|[\s()]+(?:and[\s()]+)?)([\w./-]+)\s+eq\s+'((?:''|[^'])*)'/gi;
5707
+ for (const match of filter.matchAll(expression)) {
5708
+ if (match[1] && match[2] !== void 0) {
5709
+ selections.set(match[1].trim(), match[2].replace(/''/g, "'"));
5717
5710
  }
5718
5711
  }
5719
5712
  return selections;
@@ -5764,6 +5757,59 @@ var init_DataBindingControls = __esm({
5764
5757
  ]
5765
5758
  }
5766
5759
  );
5760
+ FilterSlidersIcon = ({ className = "" }) => /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)(
5761
+ "svg",
5762
+ {
5763
+ "aria-hidden": "true",
5764
+ className,
5765
+ fill: "none",
5766
+ viewBox: "0 0 24 24",
5767
+ stroke: "currentColor",
5768
+ strokeWidth: "2",
5769
+ children: [
5770
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M3 4h18M3 12h18M3 20h18" }),
5771
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("circle", { cx: "8", cy: "4", r: "2", fill: "currentColor" }),
5772
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("circle", { cx: "16", cy: "12", r: "2", fill: "currentColor" }),
5773
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("circle", { cx: "10", cy: "20", r: "2", fill: "currentColor" })
5774
+ ]
5775
+ }
5776
+ );
5777
+ ChevronDownIcon = ({ className = "" }) => /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(
5778
+ "svg",
5779
+ {
5780
+ "aria-hidden": "true",
5781
+ className,
5782
+ fill: "none",
5783
+ viewBox: "0 0 24 24",
5784
+ stroke: "currentColor",
5785
+ strokeWidth: "2",
5786
+ children: /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "m19 9-7 7-7-7" })
5787
+ }
5788
+ );
5789
+ CheckIcon = ({ className = "" }) => /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(
5790
+ "svg",
5791
+ {
5792
+ "aria-hidden": "true",
5793
+ className,
5794
+ fill: "none",
5795
+ viewBox: "0 0 24 24",
5796
+ stroke: "currentColor",
5797
+ strokeWidth: "2.5",
5798
+ children: /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M5 13l4 4L19 7" })
5799
+ }
5800
+ );
5801
+ CloseIcon = ({ className = "" }) => /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(
5802
+ "svg",
5803
+ {
5804
+ "aria-hidden": "true",
5805
+ className,
5806
+ fill: "none",
5807
+ viewBox: "0 0 24 24",
5808
+ stroke: "currentColor",
5809
+ strokeWidth: "2",
5810
+ children: /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" })
5811
+ }
5812
+ );
5767
5813
  normalizeSortOption = (option) => {
5768
5814
  const direction = option.direction.trim();
5769
5815
  return {
@@ -5782,59 +5828,46 @@ var init_DataBindingControls = __esm({
5782
5828
  mode = "toolbar"
5783
5829
  }) => {
5784
5830
  const router = (0, import_navigation.useRouter)();
5785
- const facetGroups = Object.entries(facets ?? {}).filter(
5786
- ([, values]) => Array.isArray(values) && values.length > 0
5831
+ const searchParams = (0, import_navigation.useSearchParams)();
5832
+ const [collapsedCategories, setCollapsedCategories] = (0, import_react59.useState)({});
5833
+ const toggleCategory = (field) => {
5834
+ setCollapsedCategories((prev) => ({
5835
+ ...prev,
5836
+ [field]: !prev[field]
5837
+ }));
5838
+ };
5839
+ const searchParamsFilter = searchParams?.get("$filter") ?? searchParams?.get("filter");
5840
+ const searchParamsSort = searchParams?.get("$orderby") ?? searchParams?.get("orderBy");
5841
+ const searchParamsSearch = searchParams?.get("$search");
5842
+ const currentFilter = searchParamsFilter !== void 0 && searchParamsFilter !== null ? searchParamsFilter : query?.["$filter"] ?? query?.filter ?? "";
5843
+ const currentSort = searchParamsSort !== void 0 && searchParamsSort !== null ? searchParamsSort : query?.["$orderby"] ?? query?.orderBy ?? "";
5844
+ const currentSearch = parseODataSearch(
5845
+ searchParamsSearch !== void 0 && searchParamsSearch !== null ? searchParamsSearch : query?.["$search"]
5787
5846
  );
5788
- const normalizedSortOptions = (sortOptions ?? []).filter((option) => option?.name && option?.direction).map(normalizeSortOption).filter((option) => option.value);
5789
- const queryFilter = query?.["$filter"] ?? query?.filter ?? "";
5790
- const querySort = query?.["$orderby"] ?? query?.orderBy ?? "";
5791
- const [currentFilter, setCurrentFilter] = (0, import_react59.useState)(queryFilter);
5792
- const [currentSort, setCurrentSort] = (0, import_react59.useState)(querySort);
5793
- const selectedFacetValues = parseFacetSelections(currentFilter);
5794
- const currentSearch = parseODataSearch(query?.["$search"]);
5795
5847
  const [searchText, setSearchText] = (0, import_react59.useState)(currentSearch);
5796
- const lastNavigationUrl = (0, import_react59.useRef)(null);
5797
5848
  (0, import_react59.useEffect)(() => {
5798
5849
  setSearchText(currentSearch);
5799
5850
  }, [currentSearch]);
5800
- (0, import_react59.useEffect)(() => {
5801
- setCurrentFilter(queryFilter);
5802
- }, [queryFilter]);
5803
- (0, import_react59.useEffect)(() => {
5804
- setCurrentSort(querySort);
5805
- }, [querySort]);
5806
- (0, import_react59.useEffect)(() => {
5807
- const syncActiveQueryControls2 = (event) => {
5808
- const { filter, sort } = event.detail;
5809
- if (filter !== void 0) {
5810
- setCurrentFilter(filter);
5811
- }
5812
- if (sort !== void 0) {
5813
- setCurrentSort(sort);
5814
- }
5815
- };
5816
- window.addEventListener(
5817
- ACTIVE_QUERY_CONTROLS_EVENT,
5818
- syncActiveQueryControls2
5819
- );
5820
- return () => window.removeEventListener(
5821
- ACTIVE_QUERY_CONTROLS_EVENT,
5822
- syncActiveQueryControls2
5823
- );
5824
- }, []);
5825
- const syncActiveQueryControls = (0, import_react59.useCallback)(
5826
- (updates) => {
5827
- window.dispatchEvent(
5828
- new CustomEvent(ACTIVE_QUERY_CONTROLS_EVENT, {
5829
- detail: updates
5830
- })
5831
- );
5832
- },
5833
- []
5851
+ const selectedFacetValues = (0, import_react59.useMemo)(
5852
+ () => parseFacetSelections(currentFilter),
5853
+ [currentFilter]
5834
5854
  );
5855
+ const activeFacets = (0, import_react59.useMemo)(() => {
5856
+ if (!facets) return [];
5857
+ return Object.entries(facets).map(([field, values]) => {
5858
+ if (!Array.isArray(values)) return null;
5859
+ const filteredValues = values.filter(
5860
+ (item) => item.count > 0 || selectedFacetValues.get(field) === item.value
5861
+ );
5862
+ if (filteredValues.length === 0) return null;
5863
+ return [field, filteredValues];
5864
+ }).filter((group) => group !== null);
5865
+ }, [facets, selectedFacetValues]);
5866
+ const normalizedSortOptions = (sortOptions ?? []).filter((option) => option?.name && option?.direction).map(normalizeSortOption).filter((option) => option.value);
5835
5867
  const getQueryUrl = (0, import_react59.useCallback)(
5836
5868
  (updates) => {
5837
- const params = new URLSearchParams(query ?? {});
5869
+ const initialParams = searchParams ? searchParams.toString() : "";
5870
+ const params = new URLSearchParams(initialParams || query || {});
5838
5871
  Object.entries(updates).forEach(([key, value]) => {
5839
5872
  if (value) {
5840
5873
  params.set(key, value);
@@ -5849,38 +5882,48 @@ var init_DataBindingControls = __esm({
5849
5882
  ).join("&");
5850
5883
  return queryString ? `${path}?${queryString}` : path;
5851
5884
  },
5852
- [path, query]
5885
+ [path, query, searchParams]
5853
5886
  );
5854
- const getFacetUrl = (field, value) => {
5855
- const updatedSelections = new Map(selectedFacetValues);
5856
- if (value) {
5857
- updatedSelections.set(field, value);
5858
- } else {
5859
- updatedSelections.delete(field);
5860
- }
5861
- const updatedFilter = buildFacetFilter(updatedSelections);
5862
- syncActiveQueryControls({ filter: updatedFilter });
5863
- return getQueryUrl({
5864
- $filter: updatedFilter || void 0,
5865
- filter: void 0
5866
- });
5867
- };
5868
5887
  const navigateWithoutReload = (0, import_react59.useCallback)(
5869
5888
  (url) => {
5870
- if (lastNavigationUrl.current === url) {
5871
- return;
5872
- }
5873
5889
  if (typeof window !== "undefined") {
5874
5890
  const targetUrl = new URL(url, window.location.origin);
5875
5891
  if (targetUrl.pathname === window.location.pathname && targetUrl.search === window.location.search) {
5876
5892
  return;
5877
5893
  }
5878
5894
  }
5879
- lastNavigationUrl.current = url;
5880
5895
  router.push(url, { scroll: false });
5881
5896
  },
5882
5897
  [router]
5883
5898
  );
5899
+ const getFacetUrl = (field, value) => {
5900
+ const updatedSelections = new Map(selectedFacetValues);
5901
+ if (value) {
5902
+ if (updatedSelections.get(field) === value) {
5903
+ updatedSelections.delete(field);
5904
+ } else {
5905
+ updatedSelections.set(field, value);
5906
+ }
5907
+ } else {
5908
+ updatedSelections.delete(field);
5909
+ }
5910
+ const updatedFilter = buildFacetFilter(updatedSelections);
5911
+ return getQueryUrl({
5912
+ $filter: updatedFilter || void 0,
5913
+ filter: void 0
5914
+ });
5915
+ };
5916
+ const clearFacetField = (field) => {
5917
+ const updatedSelections = new Map(selectedFacetValues);
5918
+ updatedSelections.delete(field);
5919
+ const updatedFilter = buildFacetFilter(updatedSelections);
5920
+ navigateWithoutReload(
5921
+ getQueryUrl({
5922
+ $filter: updatedFilter || void 0,
5923
+ filter: void 0
5924
+ })
5925
+ );
5926
+ };
5884
5927
  const handleSearch = (0, import_react59.useCallback)(async () => {
5885
5928
  const trimmedSearchText = searchText.trim();
5886
5929
  if (trimmedSearchText === currentSearch.trim()) {
@@ -5894,7 +5937,6 @@ var init_DataBindingControls = __esm({
5894
5937
  return { isSuccessful: true };
5895
5938
  }, [currentSearch, getQueryUrl, navigateWithoutReload, searchText]);
5896
5939
  const handleClearAll = (0, import_react59.useCallback)(async () => {
5897
- syncActiveQueryControls({ filter: "", sort: "" });
5898
5940
  navigateWithoutReload(
5899
5941
  getQueryUrl({
5900
5942
  $filter: void 0,
@@ -5904,66 +5946,76 @@ var init_DataBindingControls = __esm({
5904
5946
  })
5905
5947
  );
5906
5948
  return { isSuccessful: true };
5907
- }, [getQueryUrl, navigateWithoutReload, syncActiveQueryControls]);
5908
- const hasFacetControls = showFacets && facetGroups.length > 0;
5949
+ }, [getQueryUrl, navigateWithoutReload]);
5950
+ const hasFacetControls = showFacets && activeFacets.length > 0;
5909
5951
  const hasSortControls = showSortOptions && normalizedSortOptions.length > 0;
5910
5952
  const hasActiveFiltersOrSort = Boolean(
5911
5953
  currentFilter.trim() || currentSort.trim()
5912
5954
  );
5955
+ const selectedFacetCount = selectedFacetValues.size;
5913
5956
  const shouldShowToolbarClearAll = hasActiveFiltersOrSort && !hasFacetControls;
5914
5957
  const shouldShowToolbar = mode === "toolbar" && (showSearchBar || hasSortControls || shouldShowToolbarClearAll);
5915
5958
  const shouldShowFacets = mode === "facets" && hasFacetControls;
5916
5959
  if (!shouldShowToolbar && !shouldShowFacets) {
5917
5960
  return null;
5918
5961
  }
5919
- const renderFacetLinks = (field, values, stacked = false) => /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: stacked ? "flex flex-col gap-0.5" : "flex flex-wrap gap-1.5", children: [
5920
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(
5962
+ const renderFacetItems = (field, values) => /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("div", { className: "flex flex-col gap-1 pt-1 pb-1", children: values.map((facet) => {
5963
+ const isSelected = selectedFacetValues.get(field) === facet.value;
5964
+ return /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)(
5921
5965
  "button",
5922
5966
  {
5923
5967
  type: "button",
5924
- onClick: () => navigateWithoutReload(getFacetUrl(field)),
5925
- "aria-pressed": !selectedFacetValues.has(field),
5926
- className: `cursor-pointer px-3 py-1.5 text-left text-sm transition-all duration-150 ease-out hover:shadow-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary ${stacked ? "w-full" : "border"} ${selectedFacetValues.has(field) ? "hover:bg-info-soft" : "bg-primary-base font-semibold hover:brightness-95"}`,
5927
- children: "All"
5928
- }
5929
- ),
5930
- values.map((facet) => {
5931
- const isSelected = selectedFacetValues.get(field) === facet.value;
5932
- return /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)(
5933
- "button",
5934
- {
5935
- type: "button",
5936
- onClick: () => navigateWithoutReload(getFacetUrl(field, facet.value)),
5937
- "aria-pressed": isSelected,
5938
- className: `cursor-pointer px-3 py-1.5 text-left text-sm transition-all duration-150 ease-out hover:shadow-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary ${stacked ? "w-full" : "border"} ${isSelected ? "bg-primary-base font-semibold hover:brightness-95" : "hover:bg-info-soft"}`,
5939
- children: [
5940
- facet.value,
5941
- " (",
5942
- facet.count,
5943
- ")"
5944
- ]
5945
- },
5946
- `${field}-${facet.value}`
5947
- );
5948
- })
5949
- ] });
5968
+ onClick: () => navigateWithoutReload(getFacetUrl(field, facet.value)),
5969
+ "aria-pressed": isSelected,
5970
+ 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 " : "hover:bg-neutral-weak border border-transparent"}`,
5971
+ children: [
5972
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "flex min-w-0 items-center gap-2.5", children: [
5973
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(
5974
+ "span",
5975
+ {
5976
+ 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"}`,
5977
+ children: isSelected && /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(CheckIcon, { className: "h-3 w-3" })
5978
+ }
5979
+ ),
5980
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "leading-snug break-words", children: facet.value })
5981
+ ] }),
5982
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(
5983
+ "span",
5984
+ {
5985
+ 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"}`,
5986
+ children: facet.count
5987
+ }
5988
+ )
5989
+ ]
5990
+ },
5991
+ `${field}-${facet.value}`
5992
+ );
5993
+ }) });
5950
5994
  return /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)(
5951
5995
  "div",
5952
5996
  {
5953
- className: mode === "toolbar" ? "my-6" : "flex flex-col gap-2 border bg-default rounded-[5px] p-3",
5997
+ className: mode === "toolbar" ? "my-6" : "flex flex-col rounded-md border bg-default p-3.5 shadow-sm",
5954
5998
  children: [
5955
5999
  shouldShowToolbar && /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
5956
- showSearchBar && /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)(
6000
+ showSearchBar && // <form
6001
+ // role="search"
6002
+ // className="flex w-full flex-col gap-3 rounded-md border border-info bg-info-soft p-3 sm:flex-row sm:items-center md:min-w-0 md:flex-1"
6003
+ // onSubmit={(event) => {
6004
+ // event.preventDefault();
6005
+ // void handleSearch();
6006
+ // }}
6007
+ // >
6008
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)(
5957
6009
  "form",
5958
6010
  {
5959
6011
  role: "search",
5960
- className: "flex w-full flex-col gap-3 rounded-xl border border-info bg-info-soft p-3 sm:flex-row sm:items-center md:min-w-0 md:flex-1",
6012
+ className: "flex w-full flex-col gap-3 rounded-md sm:flex-row sm:items-center md:min-w-0 md:flex-1",
5961
6013
  onSubmit: (event) => {
5962
6014
  event.preventDefault();
5963
6015
  void handleSearch();
5964
6016
  },
5965
6017
  children: [
5966
- /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "relative bg-default rounded-xl min-w-0 flex-1", children: [
6018
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "relative bg-default rounded-md min-w-0 flex-1", children: [
5967
6019
  /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(SearchIcon, { className: "pointer-events-none absolute left-4 top-1/2 z-10 h-5 w-5 -translate-y-1/2" }),
5968
6020
  /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(
5969
6021
  InputControl_default,
@@ -5975,7 +6027,7 @@ var init_DataBindingControls = __esm({
5975
6027
  attributes: {
5976
6028
  placeholder: "Search discussions, topics, or keywords..."
5977
6029
  },
5978
- inputClasses: "!mt-0 !rounded-xl !py-3 !pl-11 !pr-4 !shadow-sm"
6030
+ inputClasses: "!mt-0 !rounded-md !py-3 !pl-11 !pr-4 !shadow-sm"
5979
6031
  }
5980
6032
  )
5981
6033
  ] }),
@@ -5984,7 +6036,7 @@ var init_DataBindingControls = __esm({
5984
6036
  {
5985
6037
  ButtonType: "Primary" /* Solid */,
5986
6038
  onClick: handleSearch,
5987
- className: "!rounded-xl !px-6 !py-3 sm:self-stretch",
6039
+ className: "!rounded-md !px-6 !py-3 sm:self-stretch",
5988
6040
  children: [
5989
6041
  /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(SearchIcon, { className: "h-5 w-5" }),
5990
6042
  /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { children: "Search" })
@@ -5994,7 +6046,7 @@ var init_DataBindingControls = __esm({
5994
6046
  ]
5995
6047
  }
5996
6048
  ),
5997
- hasSortControls && /* @__PURE__ */ (0, import_jsx_runtime86.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: [
6049
+ hasSortControls && /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "flex w-full items-center gap-3 rounded-md border border-info bg-info-soft p-3 text-sm md:ml-auto md:w-auto md:min-w-72 md:self-stretch", children: [
5998
6050
  /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(
5999
6051
  "label",
6000
6052
  {
@@ -6003,7 +6055,7 @@ var init_DataBindingControls = __esm({
6003
6055
  children: "Sort by"
6004
6056
  }
6005
6057
  ),
6006
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("div", { className: "min-w-0 flex-1 rounded-xl bg-default md:min-w-48", children: /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(
6058
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("div", { className: "min-w-0 flex-1 rounded-md bg-default md:min-w-48", children: /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(
6007
6059
  InputControl_default,
6008
6060
  {
6009
6061
  name: "sortOptions",
@@ -6014,7 +6066,6 @@ var init_DataBindingControls = __esm({
6014
6066
  dataTextFieldName: "label",
6015
6067
  callback: (updatedValues) => {
6016
6068
  const updatedSort = updatedValues.value || "";
6017
- syncActiveQueryControls({ sort: updatedSort });
6018
6069
  navigateWithoutReload(
6019
6070
  getQueryUrl({
6020
6071
  $orderby: updatedSort || void 0,
@@ -6023,32 +6074,81 @@ var init_DataBindingControls = __esm({
6023
6074
  );
6024
6075
  },
6025
6076
  attributes: { placeholder: "Default" },
6026
- inputClasses: "!mt-0 !rounded-xl !border-info !bg-default !px-4 !py-3 !text-body !shadow-sm focus:!border-primary focus:!ring-primary-base"
6077
+ inputClasses: "!mt-0 !rounded-md !border-info !bg-default !px-4 !py-3 !shadow-sm focus:!border-primary focus:!ring-primary-base"
6027
6078
  }
6028
6079
  ) })
6029
6080
  ] })
6030
6081
  ] }),
6031
- shouldShowFacets && /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "flex items-center justify-between gap-2 border-b pb-2", children: [
6032
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("h2", { className: "text-lg font-semibold", children: "Filters" }),
6033
- hasActiveFiltersOrSort && /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)(
6082
+ shouldShowFacets && /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "flex flex-col gap-3", children: [
6083
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "flex items-center justify-between border-b pb-3", children: [
6084
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "flex items-center gap-2", children: [
6085
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(FilterSlidersIcon, { className: "h-4 w-4" }),
6086
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("h2", { className: "text-base font-semibold tracking-tight", children: "Filters" }),
6087
+ selectedFacetCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "flex h-5 items-center justify-center rounded-full bg-primary-base px-2 text-xs font-semibold", children: selectedFacetCount })
6088
+ ] }),
6089
+ hasActiveFiltersOrSort && /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)(
6090
+ "button",
6091
+ {
6092
+ type: "button",
6093
+ onClick: () => void handleClearAll(),
6094
+ 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",
6095
+ "aria-label": "Clear all filters and sorting",
6096
+ children: [
6097
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(ResetIcon, { className: "h-3.5 w-3.5 transition-transform duration-200 group-hover:-rotate-45" }),
6098
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { children: "Clear all" })
6099
+ ]
6100
+ }
6101
+ )
6102
+ ] }),
6103
+ selectedFacetCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("div", { className: "flex flex-wrap gap-1.5 pb-2.5 border-b ", children: Array.from(selectedFacetValues.entries()).map(([field, value]) => /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)(
6034
6104
  "button",
6035
6105
  {
6036
6106
  type: "button",
6037
- onClick: () => void handleClearAll(),
6038
- className: "group inline-flex cursor-pointer items-center gap-1.5 rounded-md px-2 py-1 text-xs font-medium text-primary transition-colors duration-150 hover:bg-info-soft hover:text-primary-800 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary",
6039
- "aria-label": "Clear all filters and sorting",
6107
+ onClick: () => clearFacetField(field),
6108
+ className: "group inline-flex max-w-full cursor-pointer items-center gap-1.5 rounded-md border bg-neutral-weak px-2.5 py-1 text-xs transition-colors hover:bg-neutral-soft",
6109
+ title: `Remove filter: ${value}`,
6040
6110
  children: [
6041
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(ResetIcon, { className: "h-3.5 w-3.5 transition-transform duration-200 group-hover:-rotate-45" }),
6042
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { children: "Clear all" })
6111
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "font-medium truncate max-w-[150px]", children: value }),
6112
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(CloseIcon, { className: "h-3.5 w-3.5 shrink-0 opacity-60 group-hover:opacity-100" })
6043
6113
  ]
6044
- }
6045
- )
6046
- ] }),
6047
- shouldShowFacets && facetGroups.length === 1 && /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("nav", { "aria-label": `${humanize(facetGroups[0][0])} filters`, children: renderFacetLinks(facetGroups[0][0], facetGroups[0][1]) }),
6048
- shouldShowFacets && facetGroups.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("div", { className: "flex flex-col", children: facetGroups.map(([field, values]) => /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("details", { className: "border-b py-1 last:border-b-0", open: true, children: [
6049
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("summary", { className: "cursor-pointer rounded-md px-2 py-1.5 font-semibold transition-colors duration-150 hover:bg-info-soft focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary", children: humanize(field) }),
6050
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("div", { className: "px-1 pb-1 pt-0.5", children: renderFacetLinks(field, values, true) })
6051
- ] }, field)) })
6114
+ },
6115
+ `chip-${field}`
6116
+ )) }),
6117
+ activeFacets.length === 1 && /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("nav", { "aria-label": `${humanize(activeFacets[0][0])} filters`, children: /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "py-1", children: [
6118
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("div", { className: "px-1 pb-2 font-medium text-sm", children: humanize(activeFacets[0][0]) }),
6119
+ renderFacetItems(activeFacets[0][0], activeFacets[0][1])
6120
+ ] }) }),
6121
+ activeFacets.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("div", { className: "flex flex-col divide-y divide-neutral-soft", children: activeFacets.map(([field, values]) => {
6122
+ const isOpen = !collapsedCategories[field];
6123
+ return /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)(
6124
+ "div",
6125
+ {
6126
+ className: "py-2 first:pt-0 last:pb-0",
6127
+ children: [
6128
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)(
6129
+ "button",
6130
+ {
6131
+ type: "button",
6132
+ onClick: () => toggleCategory(field),
6133
+ 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",
6134
+ children: [
6135
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { children: humanize(field) }),
6136
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(
6137
+ ChevronDownIcon,
6138
+ {
6139
+ className: `h-4 w-4 transition-transform duration-200 ease-out ${isOpen ? "rotate-180" : ""}`
6140
+ }
6141
+ )
6142
+ ]
6143
+ }
6144
+ ),
6145
+ isOpen && /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("div", { className: "pt-1", children: renderFacetItems(field, values) })
6146
+ ]
6147
+ },
6148
+ field
6149
+ );
6150
+ }) })
6151
+ ] })
6052
6152
  ]
6053
6153
  }
6054
6154
  );
@@ -9420,7 +9520,7 @@ var DivContainer = async (props) => {
9420
9520
  renderedContainer,
9421
9521
  paginationControl
9422
9522
  ] }),
9423
- dataBindingProperties?.showFacets && /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("aside", { className: " lg:sticky lg:top-[90px] lg:self-start", children: /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(
9523
+ dataBindingProperties?.showFacets && /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("aside", { children: /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(
9424
9524
  DataBindingControls2,
9425
9525
  {
9426
9526
  mode: "facets",
package/dist/index.mjs CHANGED
@@ -2420,7 +2420,7 @@ var GoogleMapNode_default = GoogleMapNode;
2420
2420
  // src/components/pageRenderingEngine/nodes/DivContainer.tsx
2421
2421
  import { jsx as jsx37, jsxs as jsxs15 } from "react/jsx-runtime";
2422
2422
  var Pagination = dynamic13(() => import("./Pagination-STOHS3LO.mjs"), { ssr: true });
2423
- var DataBindingControls = dynamic13(() => import("./DataBindingControls-SLNZLI3I.mjs"), {
2423
+ var DataBindingControls = dynamic13(() => import("./DataBindingControls-5H5K5GVR.mjs"), {
2424
2424
  ssr: true
2425
2425
  });
2426
2426
  var Slider = dynamic13(() => import("./Slider-42T6THEQ.mjs"), {
@@ -2961,7 +2961,7 @@ var DivContainer = async (props) => {
2961
2961
  renderedContainer,
2962
2962
  paginationControl
2963
2963
  ] }),
2964
- dataBindingProperties?.showFacets && /* @__PURE__ */ jsx37("aside", { className: " lg:sticky lg:top-[90px] lg:self-start", children: /* @__PURE__ */ jsx37(
2964
+ dataBindingProperties?.showFacets && /* @__PURE__ */ jsx37("aside", { children: /* @__PURE__ */ jsx37(
2965
2965
  DataBindingControls,
2966
2966
  {
2967
2967
  mode: "facets",