@axinom/mosaic-ui 0.65.0-rc.9 → 0.65.1
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/components/Explorer/BulkEdit/useBulkEdit.d.ts +2 -1
- package/dist/components/Explorer/BulkEdit/useBulkEdit.d.ts.map +1 -1
- package/dist/components/Explorer/Explorer.d.ts.map +1 -1
- package/dist/components/List/ListRow/Renderers/TagsRenderer/TagsRenderer.d.ts.map +1 -1
- package/dist/index.es.js +1 -1
- package/dist/index.es.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/components/Explorer/BulkEdit/useBulkEdit.tsx +9 -3
- package/src/components/Explorer/Explorer.tsx +1 -0
- package/src/components/Explorer/QuickEdit/useQuickEdit.tsx +1 -1
- package/src/components/List/ListRow/Renderers/TagsRenderer/TagsRenderer.tsx +53 -42
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@axinom/mosaic-ui",
|
|
3
|
-
"version": "0.65.
|
|
3
|
+
"version": "0.65.1",
|
|
4
4
|
"description": "UI components for building Axinom Mosaic applications",
|
|
5
5
|
"author": "Axinom",
|
|
6
6
|
"license": "PROPRIETARY",
|
|
@@ -112,5 +112,5 @@
|
|
|
112
112
|
"publishConfig": {
|
|
113
113
|
"access": "public"
|
|
114
114
|
},
|
|
115
|
-
"gitHead": "
|
|
115
|
+
"gitHead": "8143211a7104b40ea8f0a41951511b337525c893"
|
|
116
116
|
}
|
|
@@ -19,6 +19,7 @@ import { BulkEditFormFieldsConfigConverter } from './FormFieldsConfigConverter';
|
|
|
19
19
|
export interface useBulkEditProps<T extends Data> {
|
|
20
20
|
bulkEditRegistration?: BulkEditRegistration<T>;
|
|
21
21
|
getBulkActionSelection: () => ItemSelection<T>;
|
|
22
|
+
collapseFilters: () => void;
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
export interface useBulkEditReturnType<T extends Data> {
|
|
@@ -32,6 +33,7 @@ export interface useBulkEditReturnType<T extends Data> {
|
|
|
32
33
|
export const useBulkEdit = <T extends Data>({
|
|
33
34
|
bulkEditRegistration,
|
|
34
35
|
getBulkActionSelection,
|
|
36
|
+
collapseFilters,
|
|
35
37
|
}: useBulkEditProps<T>): useBulkEditReturnType<T> => {
|
|
36
38
|
const [isBulkEditMode, setIsBulkEditMode] = useState<boolean>(false);
|
|
37
39
|
const [noItemsSelected, setNoItemsSelected] = useState<boolean>(false);
|
|
@@ -75,11 +77,15 @@ export const useBulkEdit = <T extends Data>({
|
|
|
75
77
|
? {
|
|
76
78
|
label: bulkEditRegistration.label ?? 'Edit',
|
|
77
79
|
icon: bulkEditRegistration.icon ?? IconName.BulkEdit,
|
|
78
|
-
|
|
79
|
-
|
|
80
|
+
onClick: () => {
|
|
81
|
+
setIsBulkEditMode((prev) => !prev);
|
|
82
|
+
if (!isBulkEditMode) {
|
|
83
|
+
collapseFilters();
|
|
84
|
+
}
|
|
85
|
+
},
|
|
80
86
|
}
|
|
81
87
|
: undefined,
|
|
82
|
-
[bulkEditRegistration],
|
|
88
|
+
[bulkEditRegistration, collapseFilters, isBulkEditMode],
|
|
83
89
|
);
|
|
84
90
|
|
|
85
91
|
const handleSave = useCallback(
|
|
@@ -126,8 +126,8 @@ export const useQuickEdit = <T extends Data>({
|
|
|
126
126
|
}
|
|
127
127
|
setIsQuickEditMode(isOpen);
|
|
128
128
|
setCurrentRegistration(isOpen ? registrations[0] : undefined);
|
|
129
|
-
collapseFilters();
|
|
130
129
|
if (isOpen) {
|
|
130
|
+
collapseFilters();
|
|
131
131
|
listRef.current?.selectIndex(0);
|
|
132
132
|
}
|
|
133
133
|
}
|
|
@@ -3,18 +3,18 @@ import classes from './TagsRenderer.scss';
|
|
|
3
3
|
|
|
4
4
|
export const TagsRenderer = (val: unknown): JSX.Element => {
|
|
5
5
|
const containerRef = useRef<HTMLDivElement>(null);
|
|
6
|
-
const
|
|
7
|
-
const [
|
|
8
|
-
const [hiddenItems, setHiddenItems] = useState<string[]>([]);
|
|
6
|
+
const resizeTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
7
|
+
const [visibleCount, setVisibleCount] = useState<number>(0);
|
|
9
8
|
|
|
10
9
|
useEffect(() => {
|
|
11
10
|
if (!Array.isArray(val) || !containerRef.current || val.length === 0) {
|
|
11
|
+
setVisibleCount(0);
|
|
12
12
|
return;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
const calculateVisibleItems = (): void => {
|
|
16
16
|
const container = containerRef.current;
|
|
17
|
-
if (!container
|
|
17
|
+
if (!container) {
|
|
18
18
|
return;
|
|
19
19
|
}
|
|
20
20
|
|
|
@@ -22,17 +22,30 @@ export const TagsRenderer = (val: unknown): JSX.Element => {
|
|
|
22
22
|
const gap = 5; // Gap between items from SCSS
|
|
23
23
|
const overflowIndicatorWidth = 60; // Approximate width for "... +X"
|
|
24
24
|
|
|
25
|
-
// Measure actual tag widths using
|
|
25
|
+
// Measure actual tag widths using hidden temporary elements in the actual container
|
|
26
26
|
const tagWidths: number[] = [];
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
27
|
+
const tempElements: HTMLDivElement[] = [];
|
|
28
|
+
|
|
29
|
+
try {
|
|
30
|
+
(val as string[]).forEach((item) => {
|
|
31
|
+
const tempTag = document.createElement('div');
|
|
32
|
+
tempTag.className = classes.tag;
|
|
33
|
+
tempTag.textContent = item;
|
|
34
|
+
tempTag.style.position = 'absolute';
|
|
35
|
+
tempTag.style.visibility = 'hidden';
|
|
36
|
+
tempTag.style.pointerEvents = 'none';
|
|
37
|
+
container.appendChild(tempTag);
|
|
38
|
+
tempElements.push(tempTag);
|
|
39
|
+
tagWidths.push(tempTag.offsetWidth);
|
|
40
|
+
});
|
|
41
|
+
} finally {
|
|
42
|
+
// Clean up temporary elements
|
|
43
|
+
tempElements.forEach((el) => container.removeChild(el));
|
|
44
|
+
}
|
|
32
45
|
|
|
33
46
|
// Calculate how many items can fit
|
|
34
47
|
let totalWidth = 0;
|
|
35
|
-
let
|
|
48
|
+
let newVisibleCount = 0;
|
|
36
49
|
|
|
37
50
|
for (let i = 0; i < val.length; i++) {
|
|
38
51
|
const itemWidth = tagWidths[i] + (i > 0 ? gap : 0);
|
|
@@ -44,17 +57,17 @@ export const TagsRenderer = (val: unknown): JSX.Element => {
|
|
|
44
57
|
|
|
45
58
|
if (requiredWidth <= containerWidth) {
|
|
46
59
|
totalWidth += itemWidth;
|
|
47
|
-
|
|
60
|
+
newVisibleCount++;
|
|
48
61
|
} else {
|
|
49
62
|
break;
|
|
50
63
|
}
|
|
51
64
|
}
|
|
52
65
|
|
|
53
66
|
// If we can't fit all items, reserve space for overflow indicator
|
|
54
|
-
if (
|
|
67
|
+
if (newVisibleCount < val.length && newVisibleCount > 0) {
|
|
55
68
|
// Re-calculate with overflow indicator space reserved
|
|
56
69
|
totalWidth = 0;
|
|
57
|
-
|
|
70
|
+
newVisibleCount = 0;
|
|
58
71
|
|
|
59
72
|
for (let i = 0; i < val.length; i++) {
|
|
60
73
|
const itemWidth = tagWidths[i] + (i > 0 ? gap : 0);
|
|
@@ -63,27 +76,37 @@ export const TagsRenderer = (val: unknown): JSX.Element => {
|
|
|
63
76
|
|
|
64
77
|
if (requiredWidth <= containerWidth && i < val.length - 1) {
|
|
65
78
|
totalWidth += itemWidth;
|
|
66
|
-
|
|
79
|
+
newVisibleCount++;
|
|
67
80
|
} else {
|
|
68
81
|
break;
|
|
69
82
|
}
|
|
70
83
|
}
|
|
71
84
|
}
|
|
72
85
|
|
|
73
|
-
|
|
74
|
-
|
|
86
|
+
// Update state with the new visible count
|
|
87
|
+
setVisibleCount(newVisibleCount);
|
|
75
88
|
};
|
|
76
89
|
|
|
77
|
-
// Initial calculation
|
|
78
|
-
|
|
79
|
-
calculateVisibleItems();
|
|
80
|
-
}, 0);
|
|
90
|
+
// Initial calculation
|
|
91
|
+
calculateVisibleItems();
|
|
81
92
|
|
|
82
|
-
|
|
93
|
+
// Debounced resize handler
|
|
94
|
+
const debouncedCalculate = (): void => {
|
|
95
|
+
if (resizeTimeoutRef.current) {
|
|
96
|
+
clearTimeout(resizeTimeoutRef.current);
|
|
97
|
+
}
|
|
98
|
+
resizeTimeoutRef.current = setTimeout(() => {
|
|
99
|
+
calculateVisibleItems();
|
|
100
|
+
}, 100);
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
const resizeObserver = new ResizeObserver(debouncedCalculate);
|
|
83
104
|
resizeObserver.observe(containerRef.current);
|
|
84
105
|
|
|
85
106
|
return () => {
|
|
86
|
-
|
|
107
|
+
if (resizeTimeoutRef.current) {
|
|
108
|
+
clearTimeout(resizeTimeoutRef.current);
|
|
109
|
+
}
|
|
87
110
|
resizeObserver.disconnect();
|
|
88
111
|
};
|
|
89
112
|
}, [val]);
|
|
@@ -93,6 +116,8 @@ export const TagsRenderer = (val: unknown): JSX.Element => {
|
|
|
93
116
|
}
|
|
94
117
|
|
|
95
118
|
const stringArray = val as string[];
|
|
119
|
+
const visibleItems = stringArray.slice(0, visibleCount);
|
|
120
|
+
const hiddenItems = stringArray.slice(visibleCount);
|
|
96
121
|
|
|
97
122
|
// Create tooltip text for hidden items
|
|
98
123
|
const tooltipText = hiddenItems.length > 0 ? hiddenItems.join(', ') : '';
|
|
@@ -104,25 +129,11 @@ export const TagsRenderer = (val: unknown): JSX.Element => {
|
|
|
104
129
|
data-testid="tags-container"
|
|
105
130
|
title={stringArray.join(', ')}
|
|
106
131
|
>
|
|
107
|
-
{
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
key={`${item}-${index}`}
|
|
113
|
-
ref={(el) => {
|
|
114
|
-
tagRefs.current[index] = el;
|
|
115
|
-
}}
|
|
116
|
-
className={classes.tag}
|
|
117
|
-
style={{
|
|
118
|
-
visibility: isVisible ? 'visible' : 'hidden',
|
|
119
|
-
position: isVisible ? 'static' : 'absolute',
|
|
120
|
-
}}
|
|
121
|
-
>
|
|
122
|
-
{item}
|
|
123
|
-
</div>
|
|
124
|
-
);
|
|
125
|
-
})}
|
|
132
|
+
{visibleItems.map((item, index) => (
|
|
133
|
+
<div key={`${item}-${index}`} className={classes.tag}>
|
|
134
|
+
{item}
|
|
135
|
+
</div>
|
|
136
|
+
))}
|
|
126
137
|
{hiddenItems.length > 0 && (
|
|
127
138
|
<div className={classes.overflowIndicator} title={tooltipText}>
|
|
128
139
|
{`+${hiddenItems.length}`}
|