@sustaina/shared-ui 1.13.0 → 1.13.2

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.d.mts CHANGED
@@ -38,7 +38,7 @@ interface FieldSchemaBase<T extends FieldType> {
38
38
  type: T;
39
39
  label?: string;
40
40
  multiTableSearch?: boolean;
41
- jsonPath?: string[];
41
+ lookupFieldName?: string;
42
42
  }
43
43
  interface DropdownFieldSchema extends FieldSchemaBase<"dropdown"> {
44
44
  options: Option[];
@@ -58,7 +58,15 @@ interface LookupFieldSchema extends FieldSchemaBase<"lookup"> {
58
58
  loadingMessage?: string;
59
59
  }
60
60
  type UUIDFieldSchema = FieldSchemaBase<"uuid">;
61
- type JSONFieldSchema = FieldSchemaBase<"json">;
61
+ interface JSONFieldSchema extends FieldSchemaBase<"json"> {
62
+ jsonPath?: string[];
63
+ maxTags?: number;
64
+ fetchSuggestions?: (query: string) => Promise<Option[]>;
65
+ suggestionDebounce?: number;
66
+ placeholder?: string;
67
+ noOptionsMessage?: string;
68
+ loadingMessage?: string;
69
+ }
62
70
  type FieldSchema = DropdownFieldSchema | TextFieldSchema | NumberFieldSchema | DateFieldSchema | DateTimeFieldSchema | DateMonthFieldSchema | CheckboxFieldSchema | LookupFieldSchema | UUIDFieldSchema | JSONFieldSchema;
63
71
  type OperatorValue = "contains" | "equals" | "beginsWith" | "endsWith" | "notEquals" | "notBeginsWith" | "notEndsWith" | "notContains" | "gt" | "gte" | "lt" | "lte" | "on" | "after" | "before" | "between" | "is" | "isNot" | "containsAny" | "containsOnly" | "containsAll";
64
72
  type RowState = {
@@ -66,10 +74,11 @@ type RowState = {
66
74
  fieldName: string;
67
75
  fieldType: FieldType;
68
76
  operator: Exclude<OperatorValue, "between">;
69
- value: string;
77
+ value: string | any[];
70
78
  value2?: undefined;
71
79
  multiTableSearch?: boolean;
72
80
  jsonPath?: string[];
81
+ lookupFieldName?: string;
73
82
  } | {
74
83
  id: string;
75
84
  fieldName: string;
@@ -79,6 +88,7 @@ type RowState = {
79
88
  value2: string;
80
89
  multiTableSearch?: boolean;
81
90
  jsonPath?: string[];
91
+ lookupFieldName?: string;
82
92
  };
83
93
  interface Params {
84
94
  AND: Record<string, unknown>[];
package/dist/index.d.ts CHANGED
@@ -38,7 +38,7 @@ interface FieldSchemaBase<T extends FieldType> {
38
38
  type: T;
39
39
  label?: string;
40
40
  multiTableSearch?: boolean;
41
- jsonPath?: string[];
41
+ lookupFieldName?: string;
42
42
  }
43
43
  interface DropdownFieldSchema extends FieldSchemaBase<"dropdown"> {
44
44
  options: Option[];
@@ -58,7 +58,15 @@ interface LookupFieldSchema extends FieldSchemaBase<"lookup"> {
58
58
  loadingMessage?: string;
59
59
  }
60
60
  type UUIDFieldSchema = FieldSchemaBase<"uuid">;
61
- type JSONFieldSchema = FieldSchemaBase<"json">;
61
+ interface JSONFieldSchema extends FieldSchemaBase<"json"> {
62
+ jsonPath?: string[];
63
+ maxTags?: number;
64
+ fetchSuggestions?: (query: string) => Promise<Option[]>;
65
+ suggestionDebounce?: number;
66
+ placeholder?: string;
67
+ noOptionsMessage?: string;
68
+ loadingMessage?: string;
69
+ }
62
70
  type FieldSchema = DropdownFieldSchema | TextFieldSchema | NumberFieldSchema | DateFieldSchema | DateTimeFieldSchema | DateMonthFieldSchema | CheckboxFieldSchema | LookupFieldSchema | UUIDFieldSchema | JSONFieldSchema;
63
71
  type OperatorValue = "contains" | "equals" | "beginsWith" | "endsWith" | "notEquals" | "notBeginsWith" | "notEndsWith" | "notContains" | "gt" | "gte" | "lt" | "lte" | "on" | "after" | "before" | "between" | "is" | "isNot" | "containsAny" | "containsOnly" | "containsAll";
64
72
  type RowState = {
@@ -66,10 +74,11 @@ type RowState = {
66
74
  fieldName: string;
67
75
  fieldType: FieldType;
68
76
  operator: Exclude<OperatorValue, "between">;
69
- value: string;
77
+ value: string | any[];
70
78
  value2?: undefined;
71
79
  multiTableSearch?: boolean;
72
80
  jsonPath?: string[];
81
+ lookupFieldName?: string;
73
82
  } | {
74
83
  id: string;
75
84
  fieldName: string;
@@ -79,6 +88,7 @@ type RowState = {
79
88
  value2: string;
80
89
  multiTableSearch?: boolean;
81
90
  jsonPath?: string[];
91
+ lookupFieldName?: string;
82
92
  };
83
93
  interface Params {
84
94
  AND: Record<string, unknown>[];
package/dist/index.js CHANGED
@@ -641,7 +641,7 @@ var OPERATOR_MAP = {
641
641
  dropdown: ["is", "isNot"],
642
642
  lookup: ["containsAny", "containsOnly", "containsAll", "notContains"],
643
643
  uuid: ["equals", "notEquals", "gt", "gte", "lt", "lte"],
644
- json: ["contains", "equals", "beginsWith", "endsWith"]
644
+ json: ["equals", "notEquals", "containsAny"]
645
645
  };
646
646
 
647
647
  // src/components/advanceSearch/hooks/useAdvanceSearch.ts
@@ -666,7 +666,19 @@ function makeNewRow(field) {
666
666
  value: "",
667
667
  value2: "",
668
668
  multiTableSearch: field.multiTableSearch,
669
- jsonPath: field.jsonPath
669
+ lookupFieldName: field.lookupFieldName
670
+ };
671
+ }
672
+ if (field.type === "json") {
673
+ return {
674
+ id: crypto.randomUUID(),
675
+ fieldName: field.name,
676
+ fieldType: field.type,
677
+ operator: op,
678
+ value: "",
679
+ multiTableSearch: field.multiTableSearch,
680
+ jsonPath: field.jsonPath,
681
+ lookupFieldName: field.lookupFieldName
670
682
  };
671
683
  }
672
684
  return {
@@ -676,7 +688,7 @@ function makeNewRow(field) {
676
688
  operator: op,
677
689
  value: "",
678
690
  multiTableSearch: field.multiTableSearch,
679
- jsonPath: field.jsonPath
691
+ lookupFieldName: field.lookupFieldName
680
692
  };
681
693
  }
682
694
  function useAdvanceSearch({ fields, limitRows }) {
@@ -718,7 +730,8 @@ function useAdvanceSearch({ fields, limitRows }) {
718
730
  value: "",
719
731
  value2: "",
720
732
  multiTableSearch: r.multiTableSearch,
721
- jsonPath: r.jsonPath
733
+ jsonPath: r.jsonPath,
734
+ lookupFieldName: r.lookupFieldName
722
735
  } : {
723
736
  id: r.id,
724
737
  fieldName: r.fieldName,
@@ -726,7 +739,8 @@ function useAdvanceSearch({ fields, limitRows }) {
726
739
  operator: nextOp,
727
740
  value: "",
728
741
  multiTableSearch: r.multiTableSearch,
729
- jsonPath: r.jsonPath
742
+ jsonPath: r.jsonPath,
743
+ lookupFieldName: r.lookupFieldName
730
744
  };
731
745
  })
732
746
  );
@@ -759,6 +773,7 @@ function useAdvanceSearch({ fields, limitRows }) {
759
773
  fieldName: r.fieldName,
760
774
  fieldType: r.fieldType,
761
775
  multiTableSearch: r.multiTableSearch,
776
+ lookupFieldName: r.lookupFieldName,
762
777
  jsonPath: r.jsonPath,
763
778
  operator,
764
779
  value: "",
@@ -770,6 +785,7 @@ function useAdvanceSearch({ fields, limitRows }) {
770
785
  fieldName: r.fieldName,
771
786
  fieldType: r.fieldType,
772
787
  multiTableSearch: r.multiTableSearch,
788
+ lookupFieldName: r.lookupFieldName,
773
789
  jsonPath: r.jsonPath,
774
790
  operator,
775
791
  value: ""
@@ -2475,6 +2491,7 @@ var LookupSelect = ({
2475
2491
  dropdownPortalId
2476
2492
  }) => {
2477
2493
  const [inputValue, setInputValue] = React4.useState("");
2494
+ const inputRef = React4.useRef(null);
2478
2495
  const [suggestions, setSuggestions] = React4.useState([]);
2479
2496
  const [optionLabels, setOptionLabels] = React4.useState({});
2480
2497
  const [loading, setLoading] = React4.useState(false);
@@ -2553,6 +2570,10 @@ var LookupSelect = ({
2553
2570
  (option) => {
2554
2571
  upsertOptionLabels([option]);
2555
2572
  addTag(option.value);
2573
+ inputRef.current?.focus();
2574
+ setTimeout(() => {
2575
+ inputRef.current?.scrollIntoView({ behavior: "smooth" });
2576
+ }, 100);
2556
2577
  },
2557
2578
  [addTag, upsertOptionLabels]
2558
2579
  );
@@ -2694,9 +2715,10 @@ var LookupSelect = ({
2694
2715
  `${tag}-${i}`
2695
2716
  );
2696
2717
  }),
2697
- /* @__PURE__ */ jsxRuntime.jsx(
2718
+ !limitReached && /* @__PURE__ */ jsxRuntime.jsx(
2698
2719
  "input",
2699
2720
  {
2721
+ ref: inputRef,
2700
2722
  type: "text",
2701
2723
  value: inputValue,
2702
2724
  onChange: (e) => setInputValue(e.target.value),
@@ -2712,7 +2734,7 @@ var LookupSelect = ({
2712
2734
  }
2713
2735
  )
2714
2736
  ] }),
2715
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-end absolute inset-y-1 right-2 items-center gap-2 pointer-events-auto", children: value.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex h-7 w-7 items-center justify-center text-inherit", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "h-4 w-4" }) }) : /* @__PURE__ */ jsxRuntime.jsx(
2737
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-end items-center gap-2 pointer-events-auto h-fit", children: value.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex h-7 w-7 items-center justify-center text-inherit", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "h-4 w-4" }) }) : /* @__PURE__ */ jsxRuntime.jsx(
2716
2738
  ClearButton,
2717
2739
  {
2718
2740
  onClick: handleClear,
@@ -2725,7 +2747,7 @@ var LookupSelect = ({
2725
2747
  ),
2726
2748
  renderDropdown(),
2727
2749
  fetchError && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-xs text-red-600", children: fetchError }),
2728
- limitReached && !fetchError && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "mt-1 text-xs text-inherit", children: [
2750
+ limitReached && !fetchError && maxTags !== 1 && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "mt-1 text-xs text-inherit", children: [
2729
2751
  "Maximum ",
2730
2752
  maxTags,
2731
2753
  " tags reached."
@@ -2775,6 +2797,58 @@ var ConditionLookupInput = ({
2775
2797
  }
2776
2798
  }
2777
2799
  );
2800
+ var ConditionJSONInput = ({
2801
+ row,
2802
+ control,
2803
+ onClear,
2804
+ fieldSchema,
2805
+ dropdownPortalId
2806
+ }) => /* @__PURE__ */ jsxRuntime.jsx(
2807
+ FormField,
2808
+ {
2809
+ control,
2810
+ name: `value_${row.id}`,
2811
+ rules: { required: "This field is required." },
2812
+ render: ({ field, fieldState }) => {
2813
+ const value = Array.isArray(field.value) ? field.value : [];
2814
+ const handleChange = (tags) => {
2815
+ field.onChange(tags);
2816
+ };
2817
+ const handleClear = () => {
2818
+ field.onChange([]);
2819
+ onClear("value");
2820
+ };
2821
+ return /* @__PURE__ */ jsxRuntime.jsxs(FormItem, { className: "relative w-full overflow-x-hidden", children: [
2822
+ /* @__PURE__ */ jsxRuntime.jsx(FormControl, { children: fieldSchema?.fetchSuggestions ? /* @__PURE__ */ jsxRuntime.jsx(
2823
+ LookupSelect,
2824
+ {
2825
+ value,
2826
+ onChange: handleChange,
2827
+ onClear: handleClear,
2828
+ error: Boolean(fieldState.error),
2829
+ placeholder: fieldSchema?.placeholder,
2830
+ maxTags: row.operator === "containsAny" ? fieldSchema?.maxTags : 1,
2831
+ fetchSuggestions: fieldSchema?.fetchSuggestions,
2832
+ suggestionDebounce: fieldSchema?.suggestionDebounce,
2833
+ noOptionsMessage: fieldSchema?.noOptionsMessage,
2834
+ loadingMessage: fieldSchema?.loadingMessage,
2835
+ dropdownPortalId
2836
+ }
2837
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
2838
+ Input,
2839
+ {
2840
+ ...field,
2841
+ value: field.value ?? "",
2842
+ autoComplete: "off",
2843
+ inputMode: "text",
2844
+ className: "w-full h-9 rounded-md bg-white pr-8 text-sm text-gray-700 shadow-none focus-visible:ring-0 focus-visible:ring-offset-0"
2845
+ }
2846
+ ) }),
2847
+ /* @__PURE__ */ jsxRuntime.jsx(FormMessage, { className: "absolute left-0 top-full mt-1 text-xs text-red-600" })
2848
+ ] });
2849
+ }
2850
+ }
2851
+ );
2778
2852
  var ConditionValue = ({ row, fields, onClearValue, dropdownPortalId }) => {
2779
2853
  const { control } = reactHookForm.useFormContext();
2780
2854
  const fieldSchema = fields.find((f) => f.name === row.fieldName);
@@ -2810,6 +2884,18 @@ var ConditionValue = ({ row, fields, onClearValue, dropdownPortalId }) => {
2810
2884
  dropdownPortalId
2811
2885
  }
2812
2886
  );
2887
+ case "json": {
2888
+ return /* @__PURE__ */ jsxRuntime.jsx(
2889
+ ConditionJSONInput,
2890
+ {
2891
+ row,
2892
+ control,
2893
+ onClear: onClearValue,
2894
+ fieldSchema,
2895
+ dropdownPortalId
2896
+ }
2897
+ );
2898
+ }
2813
2899
  default:
2814
2900
  return /* @__PURE__ */ jsxRuntime.jsx(ConditionTextInput, { row, control, onClear: onClearValue });
2815
2901
  }
@@ -3025,23 +3111,20 @@ var DropdownBuilder = class {
3025
3111
  // src/components/advanceSearch/builder/json.ts
3026
3112
  var JSONBuilder = class {
3027
3113
  build(row) {
3114
+ const isArray = Array.isArray(row.value);
3028
3115
  switch (row.operator) {
3029
- case "contains":
3030
- return { [row.fieldName]: { path: row.jsonPath, string_contains: row.value } };
3031
3116
  case "equals":
3032
- return { [row.fieldName]: { path: row.jsonPath, equals: row.value } };
3033
- case "beginsWith":
3034
- return { [row.fieldName]: { path: row.jsonPath, string_starts_with: row.value } };
3035
- case "endsWith":
3036
- return { [row.fieldName]: { path: row.jsonPath, string_ends_with: row.value } };
3037
- case "notContains":
3038
- return { [row.fieldName]: { path: row.jsonPath, not: { string_contains: row.value } } };
3117
+ return { [row.fieldName]: { path: row.jsonPath, equals: isArray ? row.value[0] : row.value } };
3039
3118
  case "notEquals":
3040
- return { [row.fieldName]: { path: row.jsonPath, not: { equals: row.value } } };
3041
- case "notBeginsWith":
3042
- return { [row.fieldName]: { path: row.jsonPath, not: { string_starts_with: row.value } } };
3043
- case "notEndsWith":
3044
- return { [row.fieldName]: { path: row.jsonPath, not: { string_ends_with: row.value } } };
3119
+ return {
3120
+ NOT: { [row.fieldName]: { path: row.jsonPath, equals: isArray ? row.value[0] : row.value } }
3121
+ };
3122
+ case "containsAny":
3123
+ if (!isArray)
3124
+ return { [row.fieldName]: { path: row.jsonPath, equals: isArray ? row.value[0] : row.value } };
3125
+ return {
3126
+ OR: row.value.map((v) => ({ [row.fieldName]: { path: row.jsonPath, equals: v } }))
3127
+ };
3045
3128
  default:
3046
3129
  return {};
3047
3130
  }
@@ -3051,40 +3134,29 @@ var JSONBuilder = class {
3051
3134
  // src/components/advanceSearch/builder/lookup.ts
3052
3135
  var LookupBuilder = class {
3053
3136
  build(row) {
3137
+ if (!Array.isArray(row.value)) {
3138
+ return {};
3139
+ }
3140
+ const lookupField = row.lookupFieldName ?? "id";
3054
3141
  switch (row.operator) {
3055
3142
  case "containsAny":
3056
3143
  return {
3057
- [row.fieldName]: helper(
3058
- { hasSome: String(row.value).split(",") },
3059
- { multiTableSearch: row.multiTableSearch }
3060
- )
3144
+ OR: row.value.map((v) => ({ [row.fieldName]: { some: { [lookupField]: v } } }))
3061
3145
  };
3062
- case "containsAll":
3146
+ case "containsOnly":
3063
3147
  return {
3064
- [row.fieldName]: helper(
3065
- { hasEvery: String(row.value).split(",") },
3066
- { multiTableSearch: row.multiTableSearch }
3067
- )
3148
+ AND: row.value.map((v) => ({ [row.fieldName]: { some: { [lookupField]: v } } }))
3068
3149
  };
3069
- case "containsOnly":
3150
+ case "containsAll": {
3151
+ const includes = row.value.map((v) => ({ [row.fieldName]: { some: { [lookupField]: v } } }));
3152
+ const excludes = { [row.fieldName]: { none: { [lookupField]: { notIn: row.value } } } };
3070
3153
  return {
3071
- [row.fieldName]: helper(
3072
- { equals: String(row.value).split(",") },
3073
- {
3074
- multiTableSearch: row.multiTableSearch,
3075
- insensitive: true
3076
- }
3077
- )
3154
+ AND: [...includes, excludes]
3078
3155
  };
3156
+ }
3079
3157
  case "notContains":
3080
3158
  return {
3081
- [row.fieldName]: helper(
3082
- { not: { contains: row.value } },
3083
- {
3084
- multiTableSearch: row.multiTableSearch,
3085
- insensitive: true
3086
- }
3087
- )
3159
+ NOT: { OR: row.value.map((v) => ({ [row.fieldName]: { some: { [lookupField]: v } } })) }
3088
3160
  };
3089
3161
  default:
3090
3162
  return {};
@@ -5755,9 +5827,9 @@ var InfoIcon = (props) => {
5755
5827
  {
5756
5828
  d: "M10.0013 18.3327C14.6037 18.3327 18.3346 14.6017 18.3346 9.99935C18.3346 5.39698 14.6037 1.66602 10.0013 1.66602C5.39893 1.66602 1.66797 5.39698 1.66797 9.99935C1.66797 14.6017 5.39893 18.3327 10.0013 18.3327Z",
5757
5829
  stroke: "white",
5758
- "stroke-width": "1.5",
5759
- "stroke-linecap": "round",
5760
- "stroke-linejoin": "round"
5830
+ strokeWidth: "1.5",
5831
+ strokeLinecap: "round",
5832
+ strokeLinejoin: "round"
5761
5833
  }
5762
5834
  ),
5763
5835
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -5765,9 +5837,9 @@ var InfoIcon = (props) => {
5765
5837
  {
5766
5838
  d: "M10 13.3333V10",
5767
5839
  stroke: "white",
5768
- "stroke-width": "1.5",
5769
- "stroke-linecap": "round",
5770
- "stroke-linejoin": "round"
5840
+ strokeWidth: "1.5",
5841
+ strokeLinecap: "round",
5842
+ strokeLinejoin: "round"
5771
5843
  }
5772
5844
  ),
5773
5845
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -5775,9 +5847,9 @@ var InfoIcon = (props) => {
5775
5847
  {
5776
5848
  d: "M10 6.66602H10.0083",
5777
5849
  stroke: "white",
5778
- "stroke-width": "1.5",
5779
- "stroke-linecap": "round",
5780
- "stroke-linejoin": "round"
5850
+ strokeWidth: "1.5",
5851
+ strokeLinecap: "round",
5852
+ strokeLinejoin: "round"
5781
5853
  }
5782
5854
  )
5783
5855
  ]