@sustaina/shared-ui 1.70.7 → 1.71.0

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
@@ -5543,6 +5543,78 @@ var DatePicker2 = (props) => {
5543
5543
  // src/components/advanceSearch/components/constants/index.ts
5544
5544
  var fallbackShortDateFormat = "DD/MM/YYYY";
5545
5545
  var UUIDregex = /^[0-9a-f]{8}-?[0-9a-f]{4}-?4[0-9a-f]{3}-?[89ab][0-9a-f]{3}-?[0-9a-f]{12}$/i;
5546
+ var RANGE_START_ERROR = "Start value must be before end value.";
5547
+ var RANGE_END_ERROR = "End value must be after start value.";
5548
+ var RANGE_VALIDATED_TYPES = ["date", "datetime", "datemonth"];
5549
+ var sanitizeInput = (val, fieldType) => {
5550
+ if (!val) return val;
5551
+ if (Array.isArray(val)) {
5552
+ return val.map((v) => sanitizeInput(v, fieldType));
5553
+ }
5554
+ if (val.includes("\n") || val.includes("\r") || /[\u2028\u2029]/u.test(val))
5555
+ return "__INVALID_NEWLINE__";
5556
+ if (/\\\\/.test(val)) return "__INVALID_ESCAPE__";
5557
+ if (/\\(n|t|r|b|f|u[0-9a-fA-F]{4})/.test(val)) return "__INVALID_ESCAPE__";
5558
+ if (/\p{Cf}/u.test(val)) return "__INVALID_UNICODE_WHITESPACE__";
5559
+ if (/[\u00A0\u1680\u180E\u202F\u205F\u3000]/u.test(val)) return "__INVALID_UNICODE_WHITESPACE__";
5560
+ if (fieldType === "text") return val;
5561
+ const trimmed = val.trim();
5562
+ if (/^\{.*\}$/s.test(trimmed) || /^\[.*\]$/s.test(trimmed)) return "__INVALID_JSON_LITERAL__";
5563
+ if (/\\\{/.test(val) || /\\\}/.test(val)) return "__INVALID_JSON_ESCAPE__";
5564
+ if (/[%*~^]/.test(trimmed)) return "__INVALID_WILDCARD__";
5565
+ if (/[%><={}\\[\]"']/u.test(trimmed)) return "__INVALID_CHAR__";
5566
+ if (/\p{Cc}/u.test(val)) return "__INVALID_CONTROL_CHAR__";
5567
+ return val;
5568
+ };
5569
+ var numericTypes = ["number"];
5570
+ var dateTypes = ["date", "datemonth"];
5571
+ var validateByFieldType = (value, fieldType) => {
5572
+ if (!value) return { valid: true };
5573
+ if (Array.isArray(value)) {
5574
+ return { valid: true };
5575
+ }
5576
+ if (numericTypes.includes(fieldType)) {
5577
+ if (!/^-?\d+(\.\d+)?$/.test(value)) {
5578
+ return { valid: false, message: "Please enter a valid number." };
5579
+ }
5580
+ }
5581
+ if (fieldType === "uuid") {
5582
+ if (!UUIDregex.test(value)) {
5583
+ return { valid: false, message: "Please enter a valid UUID." };
5584
+ }
5585
+ }
5586
+ if (dateTypes.includes(fieldType)) {
5587
+ const normalized = fieldType === "datemonth" ? `${value}-01` : value;
5588
+ const parsed = dateFns.parseISO(normalized);
5589
+ if (!dateFns.isValid(parsed)) {
5590
+ return { valid: false, message: "Invalid date format." };
5591
+ }
5592
+ }
5593
+ return { valid: true };
5594
+ };
5595
+ var parseRangeValue = (raw, fieldType) => {
5596
+ if (!raw) return void 0;
5597
+ const normalized = fieldType === "datemonth" ? `${raw}-01` : raw;
5598
+ const parsed = dateFns.parseISO(normalized);
5599
+ return dateFns.isValid(parsed) ? parsed : void 0;
5600
+ };
5601
+ var validateDateRange = (which, row, formValues) => {
5602
+ if (row.operator !== "between" || !RANGE_VALIDATED_TYPES.includes(row.fieldType)) return true;
5603
+ const start = formValues[`value_${row.id}`];
5604
+ const end = formValues[`value2_${row.id}`];
5605
+ if (typeof start !== "string" || typeof end !== "string" || !start || !end) return true;
5606
+ const d1 = parseRangeValue(start, row.fieldType);
5607
+ const d2 = parseRangeValue(end, row.fieldType);
5608
+ if (d1 && d2 && dateFns.isAfter(d1, d2)) {
5609
+ return which === "value" ? RANGE_START_ERROR : RANGE_END_ERROR;
5610
+ }
5611
+ return true;
5612
+ };
5613
+ var buildValueRules = (which, row) => ({
5614
+ required: "This field is required.",
5615
+ validate: (_value, formValues) => validateDateRange(which, row, formValues),
5616
+ deps: [which === "value" ? `value2_${row.id}` : `value_${row.id}`]
5617
+ });
5546
5618
  var ConditionDateInput = ({
5547
5619
  row,
5548
5620
  control,
@@ -5566,8 +5638,9 @@ var ConditionDateInput = ({
5566
5638
  {
5567
5639
  control,
5568
5640
  name: fieldName,
5569
- rules: { required: "This field is required." },
5641
+ rules: buildValueRules(which, row),
5570
5642
  render: ({ field, fieldState }) => {
5643
+ const { value: fieldValue, ...fieldRest } = field;
5571
5644
  const handleValueChange = (next) => {
5572
5645
  field.onChange(next ?? void 0);
5573
5646
  if (!next) {
@@ -5578,8 +5651,8 @@ var ConditionDateInput = ({
5578
5651
  /* @__PURE__ */ jsxRuntime.jsx(FormControl, { children: /* @__PURE__ */ jsxRuntime.jsx(
5579
5652
  DatePicker2,
5580
5653
  {
5581
- ...field,
5582
- value: field.value || void 0,
5654
+ ...fieldRest,
5655
+ value: fieldValue || void 0,
5583
5656
  onValueChange: handleValueChange,
5584
5657
  placeholder: dateFormat,
5585
5658
  ariaLabel: buildAriaLabel(options?.isEnd),
@@ -6088,9 +6161,10 @@ var ConditionMonthInput = ({ row, control, onClear }) => {
6088
6161
  {
6089
6162
  control,
6090
6163
  name: fieldName,
6091
- rules: { required: "This field is required." },
6164
+ rules: buildValueRules(which, row),
6092
6165
  render: ({ field, fieldState }) => {
6093
- const value = field.value || void 0;
6166
+ const { value: fieldValue, ...fieldRest } = field;
6167
+ const value = fieldValue || void 0;
6094
6168
  const handleValueChange = (next) => {
6095
6169
  field.onChange(next ?? void 0);
6096
6170
  if (!next) {
@@ -6101,7 +6175,7 @@ var ConditionMonthInput = ({ row, control, onClear }) => {
6101
6175
  /* @__PURE__ */ jsxRuntime.jsx(FormControl, { children: /* @__PURE__ */ jsxRuntime.jsx(
6102
6176
  MonthPicker2,
6103
6177
  {
6104
- ...field,
6178
+ ...fieldRest,
6105
6179
  value,
6106
6180
  onValueChange: handleValueChange,
6107
6181
  placeholder,
@@ -8648,51 +8722,6 @@ function transformFilterKeys(obj, fieldMap = FILTER_FIELD_MAP) {
8648
8722
  }
8649
8723
  return obj;
8650
8724
  }
8651
- var sanitizeInput = (val) => {
8652
- if (!val) return val;
8653
- if (Array.isArray(val)) {
8654
- return val.map((v) => sanitizeInput(v));
8655
- }
8656
- if (val.includes("\n") || val.includes("\r") || /[\u2028\u2029]/u.test(val))
8657
- return "__INVALID_NEWLINE__";
8658
- if (/\\\\/.test(val)) return "__INVALID_ESCAPE__";
8659
- if (/\\(n|t|r|b|f|u[0-9a-fA-F]{4})/.test(val)) return "__INVALID_ESCAPE__";
8660
- if (/\p{Cf}/u.test(val)) return "__INVALID_UNICODE_WHITESPACE__";
8661
- if (/[\u00A0\u1680\u180E\u202F\u205F\u3000]/u.test(val)) return "__INVALID_UNICODE_WHITESPACE__";
8662
- const trimmed = val.trim();
8663
- if (/^\{.*\}$/s.test(trimmed) || /^\[.*\]$/s.test(trimmed)) return "__INVALID_JSON_LITERAL__";
8664
- if (/\\\{/.test(val) || /\\\}/.test(val)) return "__INVALID_JSON_ESCAPE__";
8665
- if (/[%*~^]/.test(trimmed)) return "__INVALID_WILDCARD__";
8666
- if (/[%><={}\\[\]"']/u.test(trimmed)) return "__INVALID_CHAR__";
8667
- if (/\p{Cc}/u.test(val)) return "__INVALID_CONTROL_CHAR__";
8668
- return val;
8669
- };
8670
- var numericTypes = ["number"];
8671
- var dateTypes = ["date", "datemonth"];
8672
- var validateByFieldType = (value, fieldType) => {
8673
- if (!value) return { valid: true };
8674
- if (Array.isArray(value)) {
8675
- return { valid: true };
8676
- }
8677
- if (numericTypes.includes(fieldType)) {
8678
- if (!/^-?\d+(\.\d+)?$/.test(value)) {
8679
- return { valid: false, message: "Please enter a valid number." };
8680
- }
8681
- }
8682
- if (fieldType === "uuid") {
8683
- if (!UUIDregex.test(value)) {
8684
- return { valid: false, message: "Please enter a valid UUID." };
8685
- }
8686
- }
8687
- if (dateTypes.includes(fieldType)) {
8688
- const normalized = fieldType === "datemonth" ? `${value}-01` : value;
8689
- const parsed = dateFns.parseISO(normalized);
8690
- if (!dateFns.isValid(parsed)) {
8691
- return { valid: false, message: "Invalid date format." };
8692
- }
8693
- }
8694
- return { valid: true };
8695
- };
8696
8725
  var AdvanceSearch = ({
8697
8726
  fields,
8698
8727
  portalId,
@@ -8745,13 +8774,6 @@ var AdvanceSearch = ({
8745
8774
  },
8746
8775
  [resetField, clearErrors]
8747
8776
  );
8748
- const parseRangeValue = React.useCallback((raw, fieldType) => {
8749
- if (!raw) return void 0;
8750
- if (Array.isArray(raw)) return void 0;
8751
- const normalized = fieldType === "datemonth" ? `${raw}-01` : raw;
8752
- const parsed = dateFns.parseISO(normalized);
8753
- return dateFns.isValid(parsed) ? parsed : void 0;
8754
- }, []);
8755
8777
  const onSubmit = React.useCallback(() => {
8756
8778
  const operatorValidation = {};
8757
8779
  rows.forEach((r) => {
@@ -8768,7 +8790,7 @@ var AdvanceSearch = ({
8768
8790
  const endField = `value2_${r.id}`;
8769
8791
  let v1 = currentValues[startField];
8770
8792
  let v2 = currentValues[endField];
8771
- const s1 = sanitizeInput(v1);
8793
+ const s1 = sanitizeInput(v1, r.fieldType);
8772
8794
  if (Array.isArray(s1) && s1.some((v) => v?.startsWith("__INVALID")) || typeof s1 === "string" && s1?.startsWith("__INVALID")) {
8773
8795
  hasError = true;
8774
8796
  setError(startField, { type: "validate", message: "Invalid input." });
@@ -8782,7 +8804,7 @@ var AdvanceSearch = ({
8782
8804
  return null;
8783
8805
  }
8784
8806
  if (r.operator === "between") {
8785
- const s2 = sanitizeInput(v2);
8807
+ const s2 = sanitizeInput(v2, r.fieldType);
8786
8808
  if (Array.isArray(s2) && s2.some((v) => v?.startsWith("__INVALID")) || typeof s2 === "string" && s2?.startsWith("__INVALID")) {
8787
8809
  hasError = true;
8788
8810
  setError(endField, { type: "validate", message: "Invalid input." });
@@ -8795,16 +8817,6 @@ var AdvanceSearch = ({
8795
8817
  setError(endField, { type: "validate", message: valid2.message });
8796
8818
  return null;
8797
8819
  }
8798
- if (v1 && v2 && ["date", "datemonth"].includes(r.fieldType)) {
8799
- const d1 = parseRangeValue(v1, r.fieldType);
8800
- const d2 = parseRangeValue(v2, r.fieldType);
8801
- if (d1 && d2 && dateFns.isAfter(d1, d2)) {
8802
- hasError = true;
8803
- setError(startField, { type: "validate", message: "Start value must be before end value." });
8804
- setError(endField, { type: "validate", message: "End value must be after start value." });
8805
- return null;
8806
- }
8807
- }
8808
8820
  return { ...r, value: v1, value2: v2 };
8809
8821
  }
8810
8822
  return { ...r, value: v1 };
@@ -8834,7 +8846,6 @@ var AdvanceSearch = ({
8834
8846
  rows,
8835
8847
  operatorsForField,
8836
8848
  getValues,
8837
- parseRangeValue,
8838
8849
  setError,
8839
8850
  setOperatorErrors,
8840
8851
  filterFieldMap,
@@ -13874,8 +13885,8 @@ var GridSettingsModal = ({
13874
13885
  }
13875
13886
  }, [isOpen, currentColumns, form]);
13876
13887
  const addColumn = async () => {
13877
- const isValid7 = await trigger("columns");
13878
- if (isValid7) {
13888
+ const isValid6 = await trigger("columns");
13889
+ if (isValid6) {
13879
13890
  append({ id: "" });
13880
13891
  requestAnimationFrame(() => {
13881
13892
  const container = scrollRef.current;