@visns-studio/visns-components 5.7.12 → 5.7.14

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/package.json CHANGED
@@ -82,7 +82,7 @@
82
82
  "react-dom": "^17.0.0 || ^18.0.0"
83
83
  },
84
84
  "name": "@visns-studio/visns-components",
85
- "version": "5.7.12",
85
+ "version": "5.7.14",
86
86
  "description": "Various packages to assist in the development of our Custom Applications.",
87
87
  "main": "src/index.js",
88
88
  "files": [
@@ -515,66 +515,27 @@ const DataGrid = forwardRef(
515
515
  (typeof param.selected === 'object' &&
516
516
  Object.keys(param.selected).length > 0)
517
517
  ) {
518
- // Show confirmation dialog for selection
519
- const selectedCount =
520
- param.selected === true ? param.data.length : 1;
521
- const itemText = selectedCount === 1 ? 'item' : 'items';
522
-
523
- confirmDialog({
524
- title: 'Selection Confirmation',
525
- message: `You have selected ${selectedCount} ${itemText}. Do you want to proceed with this selection?`,
526
- data:
527
- param.selected === true
528
- ? param.data
529
- : param.selected, // Pass the selected data
530
- buttons: [
531
- {
532
- label: 'Yes',
533
- onClick: () => {
534
- // Process the selection as before
535
- if (param.selected === true) {
536
- const s = {};
537
- param.data.forEach((obj) => {
538
- s[obj.id] = obj;
539
- });
540
- setSelected(s);
541
- } else if (
542
- typeof param.selected === 'object'
543
- ) {
544
- const selectedKey = Object.keys(
545
- param.selected
546
- )[0];
547
- const isSelectedAlready =
548
- selected.hasOwnProperty(
549
- selectedKey
550
- );
551
-
552
- if (isSelectedAlready) {
553
- setSelected({});
554
- } else {
555
- setSelected((prevSelected) => ({
556
- ...prevSelected,
557
- [selectedKey]:
558
- param.selected[selectedKey],
559
- }));
560
- }
561
- }
562
-
563
- // Show a success message
564
- toast.success(
565
- `Selection of ${selectedCount} ${itemText} confirmed`
566
- );
567
- },
568
- },
569
- {
570
- label: 'No',
571
- onClick: () => {
572
- // Clear selection if user cancels
573
- setSelected({});
574
- },
575
- },
576
- ],
577
- });
518
+ // Process the selection directly without confirmation
519
+ if (param.selected === true) {
520
+ const s = {};
521
+ param.data.forEach((obj) => {
522
+ s[obj.id] = obj;
523
+ });
524
+ setSelected(s);
525
+ } else if (typeof param.selected === 'object') {
526
+ const selectedKey = Object.keys(param.selected)[0];
527
+ const isSelectedAlready =
528
+ selected.hasOwnProperty(selectedKey);
529
+
530
+ if (isSelectedAlready) {
531
+ setSelected({});
532
+ } else {
533
+ setSelected((prevSelected) => ({
534
+ ...prevSelected,
535
+ [selectedKey]: param.selected[selectedKey],
536
+ }));
537
+ }
538
+ }
578
539
  } else {
579
540
  // Handle deselection directly without confirmation
580
541
  setSelected(param.selected);
@@ -32,6 +32,21 @@ const CustomOption = (props) => {
32
32
  );
33
33
  };
34
34
 
35
+ // Custom MultiValue component to display description for selected values
36
+ const CustomMultiValue = (props) => {
37
+ const { children, data, ...rest } = props;
38
+ return (
39
+ <components.MultiValue {...rest}>
40
+ <div className={styles.multiValue}>
41
+ <div className={styles.multiValueLabel}>{children}</div>
42
+ {data.description && (
43
+ <div className={styles.multiValueDescription}>{data.description}</div>
44
+ )}
45
+ </div>
46
+ </components.MultiValue>
47
+ );
48
+ };
49
+
35
50
  function MultiSelect({
36
51
  className,
37
52
  inputValue = [], // Default to an empty array
@@ -91,14 +106,36 @@ function MultiSelect({
91
106
  JSON.stringify(prevInputValueRef.current) !==
92
107
  JSON.stringify(inputValue)
93
108
  ) {
109
+ // Find matching options to get descriptions if not present in inputValue
110
+ const findMatchingOption = (item) => {
111
+ if (item.description) return item;
112
+
113
+ // Try to find a matching option with description
114
+ const matchingOption = selectOptions.find(opt =>
115
+ opt.id === item.id || opt.value === item.id
116
+ );
117
+
118
+ if (matchingOption && matchingOption.description) {
119
+ return {
120
+ ...item,
121
+ description: matchingOption.description
122
+ };
123
+ }
124
+
125
+ return item;
126
+ };
127
+
94
128
  const _values = Array.isArray(inputValue)
95
- ? inputValue.map((a) => ({
96
- value: a.id,
97
- label: a.label || a.name || a.description || 'Unknown',
98
- // Make sure description is preserved
99
- description: a.description || null,
100
- ...a,
101
- }))
129
+ ? inputValue.map((a) => {
130
+ const enrichedItem = findMatchingOption(a);
131
+ return {
132
+ value: enrichedItem.id,
133
+ label: enrichedItem.label || enrichedItem.name || enrichedItem.description || 'Unknown',
134
+ // Make sure description is preserved
135
+ description: enrichedItem.description || null,
136
+ ...enrichedItem,
137
+ };
138
+ })
102
139
  : inputValue && typeof inputValue === 'object'
103
140
  ? [
104
141
  {
@@ -114,10 +151,11 @@ function MultiSelect({
114
151
  },
115
152
  ]
116
153
  : [];
154
+
117
155
  setSelectValue(_values);
118
156
  prevInputValueRef.current = inputValue;
119
157
  }
120
- }, [inputValue]);
158
+ }, [inputValue, selectOptions]);
121
159
 
122
160
  const handleCreate = async (inputValue) => {
123
161
  if (creatableConfig.url && creatableConfig.method) {
@@ -171,7 +209,8 @@ function MultiSelect({
171
209
  filterOption={createFilter({ ignoreAccents: false })}
172
210
  components={{
173
211
  SelectList,
174
- Option: CustomOption
212
+ Option: CustomOption,
213
+ MultiValue: CustomMultiValue
175
214
  }}
176
215
  options={selectOptions}
177
216
  menuPortalTarget={document.body}
@@ -259,6 +298,24 @@ function MultiSelect({
259
298
  multiValue: (base) => ({
260
299
  ...base,
261
300
  margin: '2px',
301
+ padding: '2px 4px',
302
+ minHeight: '30px',
303
+ display: 'flex',
304
+ flexDirection: 'column',
305
+ alignItems: 'flex-start',
306
+ }),
307
+ multiValueLabel: (base) => ({
308
+ ...base,
309
+ padding: '0',
310
+ display: 'flex',
311
+ flexDirection: 'column',
312
+ width: '100%',
313
+ }),
314
+ multiValueRemove: (base) => ({
315
+ ...base,
316
+ padding: '0 4px',
317
+ alignSelf: 'flex-start',
318
+ marginTop: '2px',
262
319
  }),
263
320
  }}
264
321
  value={selectValue}
@@ -30,6 +30,28 @@
30
30
  margin-top: 2px;
31
31
  }
32
32
 
33
+ .multiValue {
34
+ display: flex;
35
+ flex-direction: column;
36
+ gap: 1px;
37
+ }
38
+
39
+ .multiValueLabel {
40
+ font-size: 13px;
41
+ font-weight: 500;
42
+ }
43
+
44
+ .multiValueDescription {
45
+ font-size: 11px;
46
+ color: rgba(0, 0, 0, 0.7); /* Darker color for better contrast */
47
+ font-weight: 400;
48
+ line-height: 1.1;
49
+ background-color: rgba(255, 255, 255, 0.7); /* Semi-transparent white background */
50
+ padding: 1px 3px;
51
+ border-radius: 2px;
52
+ margin-top: 1px;
53
+ }
54
+
33
55
  /* Global styles for react-select to ensure it works in modals */
34
56
  :global {
35
57
  .visns-select__menu-portal {
@@ -84,6 +106,24 @@
84
106
  /* Multi-value styles */
85
107
  .visns-select__multi-value {
86
108
  margin: 2px !important;
109
+ padding: 2px 4px !important;
110
+ min-height: 30px !important;
111
+ display: flex !important;
112
+ flex-direction: column !important;
113
+ align-items: flex-start !important;
114
+ }
115
+
116
+ .visns-select__multi-value__label {
117
+ padding: 0 !important;
118
+ display: flex !important;
119
+ flex-direction: column !important;
120
+ width: 100% !important;
121
+ }
122
+
123
+ .visns-select__multi-value__remove {
124
+ padding: 0 4px !important;
125
+ align-self: flex-start !important;
126
+ margin-top: 2px !important;
87
127
  }
88
128
 
89
129
  /* Fix for modals */