@sustaina/shared-ui 1.6.1 → 1.6.3

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.mjs CHANGED
@@ -869,15 +869,33 @@ var DataTable = ({
869
869
  }, [centerVisibleLeafColumns, leftVisibleLeftColumns, rightVisibleLeafColumns]);
870
870
  const fetchMoreOnScrollReached = useCallback(
871
871
  (containerRefElement) => {
872
- if (!scrollFetch?.enabled) {
872
+ if (!scrollFetch?.enabled || !containerRefElement || scrollFetch?.isFetchingMore || !scrollFetch?.hasMore || !scrollFetch?.fetchMore) {
873
873
  return;
874
874
  }
875
- if (containerRefElement) {
876
- const { scrollHeight, scrollTop, clientHeight } = containerRefElement;
877
- const threshold = 1.5;
878
- if (scrollHeight - scrollTop - clientHeight < clientHeight * threshold && !scrollFetch?.isFetchingMore && scrollFetch?.hasMore && scrollFetch?.fetchMore) {
879
- scrollFetch.fetchMore();
880
- }
875
+ const { scrollHeight, scrollTop, clientHeight } = containerRefElement;
876
+ const scrollableHeight = scrollHeight - clientHeight;
877
+ const distanceToBottom = scrollHeight - clientHeight - scrollTop;
878
+ const ratioToBottom = scrollableHeight > 0 ? scrollTop / scrollableHeight : 1;
879
+ const info = {
880
+ scrollTop,
881
+ scrollHeight,
882
+ clientHeight,
883
+ scrollableHeight,
884
+ distanceToBottom,
885
+ ratioToBottom,
886
+ isTopReached: scrollTop === 0,
887
+ isBottomReached: distanceToBottom <= 0
888
+ };
889
+ let shouldTrigger = false;
890
+ if (typeof scrollFetch.scrollThreshold === "number") {
891
+ shouldTrigger = info.ratioToBottom >= scrollFetch.scrollThreshold;
892
+ } else if (typeof scrollFetch.scrollThreshold === "function") {
893
+ shouldTrigger = scrollFetch.scrollThreshold(info);
894
+ } else {
895
+ shouldTrigger = info.ratioToBottom >= 0.7;
896
+ }
897
+ if (shouldTrigger) {
898
+ scrollFetch.fetchMore();
881
899
  }
882
900
  },
883
901
  // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -1907,9 +1925,11 @@ var Navbar = ({
1907
1925
  subTitle,
1908
1926
  headImageURL = "",
1909
1927
  headImageURLClassName,
1928
+ tooltipContentClassName = "md:w-[350px] lg:w-[420px]",
1910
1929
  tooltipTitle,
1911
1930
  tooltipIcon,
1912
1931
  tooltipdescription = [],
1932
+ tooltipDescriptionWrapperClassName,
1913
1933
  mainButtonText,
1914
1934
  mainButtonClassName,
1915
1935
  mainButtonDisable = false,
@@ -1928,17 +1948,17 @@ var Navbar = ({
1928
1948
  "nav",
1929
1949
  {
1930
1950
  className: cn(
1931
- "py-5 px-8 w-full h-[5.3rem] bg-sus-primary-1 flex items-center justify-between",
1951
+ "py-3 px-8 w-full h-16 bg-sus-primary-1 flex items-center justify-between",
1932
1952
  className
1933
1953
  ),
1934
1954
  children: [
1935
1955
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2.5", children: [
1936
- headImageURL !== "" ? /* @__PURE__ */ jsx("img", { src: headImageURL, alt: "", className: cn("w-full h-full", headImageURLClassName) }) : /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
1937
- isValidElement(title) ? title : /* @__PURE__ */ jsx("h1", { className: "text-white text-4xl font-bold", children: title }),
1938
- isValidElement(subTitle) ? subTitle : /* @__PURE__ */ jsx("h1", { className: "text-white text-xl font-bold", children: subTitle })
1956
+ headImageURL !== "" ? /* @__PURE__ */ jsx("img", { src: headImageURL, alt: "", className: cn("w-full h-full", headImageURLClassName) }) : /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
1957
+ isValidElement(title) ? title : /* @__PURE__ */ jsx("h1", { className: "text-white text-xl font-bold", children: title }),
1958
+ isValidElement(subTitle) ? subTitle : /* @__PURE__ */ jsx("h1", { className: "text-white text-sm font-semibold", children: subTitle })
1939
1959
  ] }),
1940
- tooltipTitle && /* @__PURE__ */ jsxs(Tooltip2, { children: [
1941
- /* @__PURE__ */ jsx(TooltipTrigger2, { asChild: true, children: /* @__PURE__ */ jsx("button", { className: "text-white hover:opacity-80 ", children: /* @__PURE__ */ jsx(InfoIcon_default, { className: "w-4" }) }) }),
1960
+ tooltipTitle && /* @__PURE__ */ jsxs(Tooltip2, { delayDuration: 700, children: [
1961
+ /* @__PURE__ */ jsx(TooltipTrigger2, { asChild: true, children: /* @__PURE__ */ jsx("button", { className: "text-white hover:opacity-80", children: /* @__PURE__ */ jsx(InfoIcon_default, { className: "w-4" }) }) }),
1942
1962
  /* @__PURE__ */ jsxs(
1943
1963
  TooltipContent2,
1944
1964
  {
@@ -1948,11 +1968,12 @@ var Navbar = ({
1948
1968
  align: "start",
1949
1969
  avoidCollisions: false,
1950
1970
  className: cn(
1951
- "bg-background text-foreground border border-black md:w-[350px] lg:w-[420px]",
1971
+ "bg-background text-foreground border border-black",
1952
1972
  "transition-all duration-150 ease-out origin-top",
1953
1973
  "data-[state=closed]:opacity-0 data-[state=open]:opacity-100",
1954
1974
  "data-[state=closed]:scale-95 data-[state=open]:scale-100",
1955
- { "mt-5": isDesktop }
1975
+ { "mt-5": isDesktop },
1976
+ tooltipContentClassName
1956
1977
  ),
1957
1978
  children: [
1958
1979
  /* @__PURE__ */ jsxs(
@@ -1960,7 +1981,10 @@ var Navbar = ({
1960
1981
  {
1961
1982
  role: "tooltip",
1962
1983
  "aria-label": tooltipTitle,
1963
- className: cn("flex flex-col gap-4 max-w-sm text-sm text-gray-700", className),
1984
+ className: cn(
1985
+ "flex flex-col gap-4 max-w-sm text-sm text-gray-700",
1986
+ tooltipDescriptionWrapperClassName
1987
+ ),
1964
1988
  children: [
1965
1989
  tooltipTitle && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
1966
1990
  isValidElement(tooltipIcon) ? tooltipIcon : /* @__PURE__ */ jsx(Icon3, { size: 32, "aria-hidden": "true" }),
@@ -2065,6 +2089,7 @@ var ExpandCollapse_default = ExpandCollapse;
2065
2089
 
2066
2090
  // src/components/advanceSearch/operatorMap.ts
2067
2091
  var OPERATOR_MAP = {
2092
+ uuid: ["equals", "notEquals", "gt", "gte", "lt", "lte"],
2068
2093
  text: [
2069
2094
  "contains",
2070
2095
  "equals",
@@ -2094,22 +2119,30 @@ function firstOperatorFor(fields, fieldName) {
2094
2119
  const t3 = getFieldType(fields, fieldName);
2095
2120
  return OPERATOR_MAP[t3][0];
2096
2121
  }
2097
- function makeNewRow(fields) {
2098
- const first = fields[0];
2099
- const op = OPERATOR_MAP[first.type][0];
2122
+ function makeNewRow(field) {
2123
+ const op = OPERATOR_MAP[field.type][0];
2100
2124
  if (op === "between") {
2101
2125
  return {
2102
2126
  id: crypto.randomUUID(),
2103
- fieldName: first.name,
2127
+ fieldName: field.name,
2128
+ fieldType: field.type,
2104
2129
  operator: "between",
2105
2130
  value: "",
2106
- value2: ""
2131
+ value2: "",
2132
+ multiTableSearch: field.multiTableSearch
2107
2133
  };
2108
2134
  }
2109
- return { id: crypto.randomUUID(), fieldName: first.name, operator: op, value: "" };
2135
+ return {
2136
+ id: crypto.randomUUID(),
2137
+ fieldName: field.name,
2138
+ fieldType: field.type,
2139
+ operator: op,
2140
+ value: "",
2141
+ multiTableSearch: field.multiTableSearch
2142
+ };
2110
2143
  }
2111
2144
  function useAdvanceSearch({ fields, limitRows }) {
2112
- const [rows, setRows] = useState([makeNewRow(fields)]);
2145
+ const [rows, setRows] = useState([makeNewRow(fields[0])]);
2113
2146
  const updateRows = useCallback((next) => {
2114
2147
  setRows(next);
2115
2148
  }, []);
@@ -2122,7 +2155,7 @@ function useAdvanceSearch({ fields, limitRows }) {
2122
2155
  );
2123
2156
  const addRow = useCallback(() => {
2124
2157
  if (!limitRows || rows.length < limitRows) {
2125
- updateRows([...rows, makeNewRow(fields)]);
2158
+ updateRows([...rows, makeNewRow(fields[0])]);
2126
2159
  }
2127
2160
  }, [rows, fields, updateRows, limitRows]);
2128
2161
  const removeRow = useCallback(
@@ -2138,22 +2171,29 @@ function useAdvanceSearch({ fields, limitRows }) {
2138
2171
  rows.map((r2) => {
2139
2172
  if (r2.id !== id) return r2;
2140
2173
  const nextOp = firstOperatorFor(fields, r2.fieldName);
2141
- return nextOp === "between" ? { id: r2.id, fieldName: r2.fieldName, operator: "between", value: "", value2: "" } : { id: r2.id, fieldName: r2.fieldName, operator: nextOp, value: "" };
2174
+ return nextOp === "between" ? {
2175
+ id: r2.id,
2176
+ fieldName: r2.fieldName,
2177
+ fieldType: r2.fieldType,
2178
+ operator: "between",
2179
+ value: "",
2180
+ value2: ""
2181
+ } : { id: r2.id, fieldName: r2.fieldName, fieldType: r2.fieldType, operator: nextOp, value: "" };
2142
2182
  })
2143
2183
  );
2144
2184
  },
2145
2185
  [rows, fields, updateRows]
2146
2186
  );
2147
2187
  const clearAllRow = useCallback(() => {
2148
- updateRows([makeNewRow(fields)]);
2188
+ updateRows([makeNewRow(fields[0])]);
2149
2189
  }, [fields, updateRows]);
2150
2190
  const changeField = useCallback(
2151
2191
  (id, fieldName) => {
2152
- const nextOp = firstOperatorFor(fields, fieldName);
2153
2192
  updateRows(
2154
2193
  rows.map((r2) => {
2155
2194
  if (r2.id !== id) return r2;
2156
- return nextOp === "between" ? { id: r2.id, fieldName, operator: "between", value: "", value2: "" } : { id: r2.id, fieldName, operator: nextOp, value: "" };
2195
+ const newRow = makeNewRow(fields.find((f) => f.name === fieldName) || fields[0]);
2196
+ return { ...newRow, id: r2.id };
2157
2197
  })
2158
2198
  );
2159
2199
  },
@@ -2165,9 +2205,24 @@ function useAdvanceSearch({ fields, limitRows }) {
2165
2205
  rows.map((r2) => {
2166
2206
  if (r2.id !== id) return r2;
2167
2207
  if (operator === "between") {
2168
- return { id: r2.id, fieldName: r2.fieldName, operator, value: "", value2: "" };
2208
+ return {
2209
+ id: r2.id,
2210
+ fieldName: r2.fieldName,
2211
+ fieldType: r2.fieldType,
2212
+ multiTableSearch: r2.multiTableSearch,
2213
+ operator,
2214
+ value: "",
2215
+ value2: ""
2216
+ };
2169
2217
  }
2170
- return { id: r2.id, fieldName: r2.fieldName, operator, value: "" };
2218
+ return {
2219
+ id: r2.id,
2220
+ fieldName: r2.fieldName,
2221
+ fieldType: r2.fieldType,
2222
+ multiTableSearch: r2.multiTableSearch,
2223
+ operator,
2224
+ value: ""
2225
+ };
2171
2226
  })
2172
2227
  );
2173
2228
  },
@@ -2192,55 +2247,16 @@ function useAdvanceSearch({ fields, limitRows }) {
2192
2247
  })),
2193
2248
  [fields]
2194
2249
  );
2195
- const rowToFilter = (row) => {
2196
- switch (row.operator) {
2197
- case "between":
2198
- return {
2199
- [row.fieldName]: {
2200
- gte: row.value,
2201
- lte: row.value2
2202
- }
2203
- };
2204
- case "contains":
2205
- return { [row.fieldName]: { contains: row.value } };
2206
- case "beginsWith":
2207
- return { [row.fieldName]: { startsWith: row.value } };
2208
- case "endsWith":
2209
- return { [row.fieldName]: { endsWith: row.value } };
2210
- case "notEquals":
2211
- return { [row.fieldName]: { not: row.value } };
2212
- case "gt":
2213
- return { [row.fieldName]: { gt: row.value } };
2214
- case "gte":
2215
- return { [row.fieldName]: { gte: row.value } };
2216
- case "lt":
2217
- return { [row.fieldName]: { lt: row.value } };
2218
- case "lte":
2219
- return { [row.fieldName]: { lte: row.value } };
2220
- case "is":
2221
- return { [row.fieldName]: row.value };
2222
- case "isNot":
2223
- return { [row.fieldName]: { not: row.value } };
2224
- case "notContains":
2225
- return { [row.fieldName]: { not: { contains: row.value } } };
2226
- case "notBeginsWith":
2227
- return { [row.fieldName]: { not: { startsWith: row.value } } };
2228
- case "notEndsWith":
2229
- return { [row.fieldName]: { not: { endsWith: row.value } } };
2230
- case "containsAny":
2231
- return { [row.fieldName]: { hasSome: row.value.split(",") } };
2232
- case "containsAll":
2233
- return { [row.fieldName]: { hasEvery: row.value.split(",") } };
2234
- case "containsOnly":
2235
- return { [row.fieldName]: { equals: row.value.split(",") } };
2236
- default:
2237
- return { [row.fieldName]: row.value };
2238
- }
2239
- };
2240
- const buildParam = useMemo(() => {
2241
- const andConditions = rows.map((r2) => r2.value ? rowToFilter(r2) : null).filter(Boolean);
2242
- return { AND: andConditions };
2243
- }, [rows]);
2250
+ const buildFilter = useCallback(
2251
+ (prismaFilter, options) => {
2252
+ return options?.multiTableSearch ? {
2253
+ some: {
2254
+ value: { ...prismaFilter, ...options?.insensitive ? { mode: "insensitive" } : void 0 }
2255
+ }
2256
+ } : prismaFilter;
2257
+ },
2258
+ []
2259
+ );
2244
2260
  return {
2245
2261
  rows,
2246
2262
  addRow,
@@ -2252,7 +2268,7 @@ function useAdvanceSearch({ fields, limitRows }) {
2252
2268
  changeValue,
2253
2269
  operatorsForField,
2254
2270
  fieldOptions,
2255
- param: buildParam
2271
+ buildFilter
2256
2272
  };
2257
2273
  }
2258
2274
 
@@ -4778,7 +4794,10 @@ var AdvanceSearch = ({
4778
4794
  onSearch,
4779
4795
  onClear
4780
4796
  }) => {
4781
- const fieldsData = useMemo(() => fields || [], [fields]);
4797
+ const fieldsData = useMemo(() => {
4798
+ if (fields.length === 0) throw new Error("fields cannot be an empty array");
4799
+ return fields || [];
4800
+ }, [fields]);
4782
4801
  const {
4783
4802
  rows,
4784
4803
  addRow,
@@ -4788,7 +4807,8 @@ var AdvanceSearch = ({
4788
4807
  changeField,
4789
4808
  changeOperator,
4790
4809
  operatorsForField,
4791
- fieldOptions
4810
+ fieldOptions,
4811
+ buildFilter
4792
4812
  } = useAdvanceSearch({ fields: fieldsData, limitRows });
4793
4813
  const form = useForm({
4794
4814
  mode: "onSubmit",
@@ -4800,66 +4820,181 @@ var AdvanceSearch = ({
4800
4820
  const currentValues = getValues();
4801
4821
  const param = {
4802
4822
  AND: rows.map((r2) => {
4803
- const val1 = currentValues[`value_${r2.id}`];
4823
+ let val1 = currentValues[`value_${r2.id}`];
4804
4824
  const val2 = currentValues[`value2_${r2.id}`];
4805
4825
  if (r2.operator === "between") {
4806
4826
  if (!val1 || !val2) return null;
4827
+ const start = new Date(val1);
4828
+ start.setHours(0, 0, 0, 0);
4829
+ const end = new Date(val2);
4830
+ end.setHours(23, 59, 59, 59);
4807
4831
  return {
4808
4832
  [r2.fieldName]: {
4809
- gte: val1,
4810
- lte: val2
4833
+ gte: start.toISOString(),
4834
+ lt: end.toISOString()
4811
4835
  }
4812
4836
  };
4813
4837
  }
4814
4838
  if (!val1) return null;
4839
+ val1 = r2.fieldType === "number" ? Number(val1) : val1;
4815
4840
  switch (r2.operator) {
4816
4841
  case "contains":
4817
- return { [r2.fieldName]: { contains: val1 } };
4842
+ return {
4843
+ [r2.fieldName]: buildFilter(
4844
+ { contains: val1 },
4845
+ {
4846
+ multiTableSearch: r2.multiTableSearch,
4847
+ insensitive: true
4848
+ }
4849
+ )
4850
+ };
4818
4851
  case "beginsWith":
4819
- return { [r2.fieldName]: { startsWith: val1 } };
4852
+ return {
4853
+ [r2.fieldName]: buildFilter(
4854
+ { startsWith: val1 },
4855
+ {
4856
+ multiTableSearch: r2.multiTableSearch,
4857
+ insensitive: true
4858
+ }
4859
+ )
4860
+ };
4820
4861
  case "endsWith":
4821
- return { [r2.fieldName]: { endsWith: val1 } };
4862
+ return {
4863
+ [r2.fieldName]: buildFilter(
4864
+ { endsWith: val1 },
4865
+ {
4866
+ multiTableSearch: r2.multiTableSearch,
4867
+ insensitive: true
4868
+ }
4869
+ )
4870
+ };
4822
4871
  case "equals":
4823
- return { [r2.fieldName]: { equals: val1 } };
4872
+ return {
4873
+ [r2.fieldName]: buildFilter(
4874
+ { equals: val1 },
4875
+ {
4876
+ multiTableSearch: r2.multiTableSearch,
4877
+ insensitive: true
4878
+ }
4879
+ )
4880
+ };
4824
4881
  case "notEquals":
4825
- return { [r2.fieldName]: { not: val1 } };
4882
+ return {
4883
+ [r2.fieldName]: buildFilter(
4884
+ { not: val1 },
4885
+ {
4886
+ multiTableSearch: r2.multiTableSearch,
4887
+ insensitive: true
4888
+ }
4889
+ )
4890
+ };
4826
4891
  case "gt":
4827
- return { [r2.fieldName]: { gt: val1 } };
4892
+ return {
4893
+ [r2.fieldName]: buildFilter({ gt: val1 }, { multiTableSearch: r2.multiTableSearch })
4894
+ };
4828
4895
  case "gte":
4829
- return { [r2.fieldName]: { gte: val1 } };
4896
+ return {
4897
+ [r2.fieldName]: buildFilter({ gte: val1 }, { multiTableSearch: r2.multiTableSearch })
4898
+ };
4830
4899
  case "lt":
4831
- return { [r2.fieldName]: { lt: val1 } };
4900
+ return {
4901
+ [r2.fieldName]: buildFilter({ lt: val1 }, { multiTableSearch: r2.multiTableSearch })
4902
+ };
4832
4903
  case "lte":
4833
- return { [r2.fieldName]: { lte: val1 } };
4904
+ return {
4905
+ [r2.fieldName]: buildFilter({ lte: val1 }, { multiTableSearch: r2.multiTableSearch })
4906
+ };
4834
4907
  case "is":
4835
4908
  return { [r2.fieldName]: val1 };
4836
4909
  case "isNot":
4837
4910
  return { [r2.fieldName]: { not: val1 } };
4838
4911
  case "notContains":
4839
- return { [r2.fieldName]: { not: { contains: val1 } } };
4912
+ return {
4913
+ [r2.fieldName]: buildFilter(
4914
+ { not: { contains: val1 } },
4915
+ {
4916
+ multiTableSearch: r2.multiTableSearch,
4917
+ insensitive: true
4918
+ }
4919
+ )
4920
+ };
4840
4921
  case "notBeginsWith":
4841
- return { [r2.fieldName]: { not: { startsWith: val1 } } };
4922
+ return {
4923
+ [r2.fieldName]: buildFilter(
4924
+ { not: { startsWith: val1 } },
4925
+ {
4926
+ multiTableSearch: r2.multiTableSearch,
4927
+ insensitive: true
4928
+ }
4929
+ )
4930
+ };
4842
4931
  case "notEndsWith":
4843
- return { [r2.fieldName]: { not: { endsWith: val1 } } };
4932
+ return {
4933
+ [r2.fieldName]: buildFilter(
4934
+ { not: { endsWith: val1 } },
4935
+ {
4936
+ multiTableSearch: r2.multiTableSearch,
4937
+ insensitive: true
4938
+ }
4939
+ )
4940
+ };
4844
4941
  case "containsAny":
4845
- return { [r2.fieldName]: { hasSome: String(val1).split(",") } };
4942
+ return {
4943
+ [r2.fieldName]: buildFilter(
4944
+ { hasSome: String(val1).split(",") },
4945
+ { multiTableSearch: r2.multiTableSearch }
4946
+ )
4947
+ };
4846
4948
  case "containsAll":
4847
- return { [r2.fieldName]: { hasEvery: String(val1).split(",") } };
4949
+ return {
4950
+ [r2.fieldName]: buildFilter(
4951
+ { hasEvery: String(val1).split(",") },
4952
+ { multiTableSearch: r2.multiTableSearch }
4953
+ )
4954
+ };
4848
4955
  case "containsOnly":
4849
- return { [r2.fieldName]: { equals: String(val1).split(",") } };
4850
- case "on":
4851
- return { [r2.fieldName]: { on: val1 } };
4956
+ return {
4957
+ [r2.fieldName]: buildFilter(
4958
+ { equals: String(val1).split(",") },
4959
+ {
4960
+ multiTableSearch: r2.multiTableSearch,
4961
+ insensitive: true
4962
+ }
4963
+ )
4964
+ };
4965
+ case "on": {
4966
+ const start = new Date(val1);
4967
+ start.setHours(0, 0, 0, 0);
4968
+ const end = new Date(val1);
4969
+ end.setHours(23, 59, 59, 59);
4970
+ return {
4971
+ [r2.fieldName]: buildFilter(
4972
+ { gte: start.toISOString(), lt: end.toISOString() },
4973
+ { multiTableSearch: r2.multiTableSearch }
4974
+ )
4975
+ };
4976
+ }
4852
4977
  case "after":
4853
- return { [r2.fieldName]: { after: val1 } };
4978
+ return {
4979
+ [r2.fieldName]: buildFilter(
4980
+ { gte: new Date(val1).toISOString() },
4981
+ { multiTableSearch: r2.multiTableSearch }
4982
+ )
4983
+ };
4854
4984
  case "before":
4855
- return { [r2.fieldName]: { before: val1 } };
4985
+ return {
4986
+ [r2.fieldName]: buildFilter(
4987
+ { lt: new Date(val1).toISOString() },
4988
+ { multiTableSearch: r2.multiTableSearch }
4989
+ )
4990
+ };
4856
4991
  }
4857
4992
  }).filter(Boolean)
4858
4993
  };
4859
4994
  if (onSearch) {
4860
4995
  onSearch(param);
4861
4996
  }
4862
- }, [getValues, rows, onSearch]);
4997
+ }, [buildFilter, getValues, rows, onSearch]);
4863
4998
  return /* @__PURE__ */ jsx(
4864
4999
  ExpandCollapse_default,
4865
5000
  {