@axinom/mosaic-ui 0.65.0-rc.6 → 0.65.0-rc.8
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/Filters/Filter/Filter.d.ts +10 -0
- package/dist/components/Filters/Filter/Filter.d.ts.map +1 -1
- package/dist/components/Filters/Filters.model.d.ts +9 -1
- package/dist/components/Filters/Filters.model.d.ts.map +1 -1
- package/dist/components/Filters/SelectionTypes/SearcheableOptionsFilter/helpers.d.ts +4 -0
- package/dist/components/Filters/SelectionTypes/SearcheableOptionsFilter/helpers.d.ts.map +1 -0
- package/dist/components/List/ListRow/Renderers/TagsRenderer/TagsRenderer.d.ts.map +1 -1
- package/dist/components/Loaders/ImageLoader/ImageLoader.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/Filters/Filter/Filter.tsx +17 -1
- package/src/components/Filters/Filters.model.ts +9 -1
- package/src/components/Filters/SelectionTypes/SearcheableOptionsFilter/helpers.ts +24 -0
- package/src/components/List/ListRow/Renderers/TagsRenderer/TagsRenderer.spec.tsx +4 -5
- package/src/components/List/ListRow/Renderers/TagsRenderer/TagsRenderer.tsx +2 -8
- package/src/components/Loaders/ImageLoader/ImageLoader.tsx +4 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@axinom/mosaic-ui",
|
|
3
|
-
"version": "0.65.0-rc.
|
|
3
|
+
"version": "0.65.0-rc.8",
|
|
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": "96eea7bc8bd6e1b5167340c8e7c842462403987d"
|
|
116
116
|
}
|
|
@@ -18,18 +18,29 @@ import { MultiOptionsFilter } from '../SelectionTypes/MultiOptionFilter/MultiOpt
|
|
|
18
18
|
import { NumericTextFilter } from '../SelectionTypes/NumericTextFilter/NumericTextFilter';
|
|
19
19
|
import { OptionsFilter } from '../SelectionTypes/OptionsFilter/OptionsFilter';
|
|
20
20
|
import { SearcheableOptionsFilter } from '../SelectionTypes/SearcheableOptionsFilter/SearcheableOptionsFilter';
|
|
21
|
+
import { renderSearcheableOptionsFilterValue } from '../SelectionTypes/SearcheableOptionsFilter/helpers';
|
|
21
22
|
import classes from './Filter.scss';
|
|
22
23
|
|
|
23
24
|
export interface FilterProps<T extends Data> {
|
|
25
|
+
/** Focus on the element when the filter is opened. (default: true) */
|
|
24
26
|
selectOnFocus?: boolean;
|
|
27
|
+
/** Filter options */
|
|
25
28
|
options: FilterType<T>;
|
|
29
|
+
/** Current value of the filter */
|
|
26
30
|
value?: FilterValue;
|
|
31
|
+
/** Index of the filter in the list of filters */
|
|
27
32
|
index?: number;
|
|
33
|
+
/** Wether or not the filter is active. */
|
|
28
34
|
isActive: boolean;
|
|
35
|
+
/** Additional classNames to add to the filter container */
|
|
29
36
|
className?: string;
|
|
37
|
+
/** Custom renderer for the selected value */
|
|
30
38
|
selectedValueRenderer?: (value: FilterValue) => string;
|
|
39
|
+
/** Callback triggered when a new filter value is selected */
|
|
31
40
|
onFilterChange: (prop: keyof T, value: FilterValue, index: number) => void;
|
|
41
|
+
/** Callback triggered for custom validations of the filter */
|
|
32
42
|
onValidate?: (currentValue: FilterValue) => string | null | undefined;
|
|
43
|
+
/** Callback triggered when the filter is clicked */
|
|
33
44
|
onFilterClicked: () => void;
|
|
34
45
|
}
|
|
35
46
|
|
|
@@ -101,7 +112,12 @@ export const Filter = <T extends Data>({
|
|
|
101
112
|
return selectedVal.join(', ');
|
|
102
113
|
}
|
|
103
114
|
case FilterTypes.SearcheableOptions:
|
|
104
|
-
return
|
|
115
|
+
return renderSearcheableOptionsFilterValue(
|
|
116
|
+
value,
|
|
117
|
+
stringValue,
|
|
118
|
+
setStringValue,
|
|
119
|
+
options,
|
|
120
|
+
);
|
|
105
121
|
default:
|
|
106
122
|
return stringValue ?? String(value);
|
|
107
123
|
}
|
|
@@ -12,10 +12,15 @@ export enum FilterTypes {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
export interface FilterConfig<T extends Data> {
|
|
15
|
+
/** Label displayed for the filter */
|
|
15
16
|
label: string;
|
|
17
|
+
/** Property of the data the filter applies to */
|
|
16
18
|
property: keyof T;
|
|
19
|
+
/** Type of the filter */
|
|
17
20
|
type: FilterTypes;
|
|
21
|
+
/** Custom renderer for the selected value */
|
|
18
22
|
selectedValueRenderer?: SelectedValueRenderer;
|
|
23
|
+
/** Callback triggered when the filter is validated */
|
|
19
24
|
onValidate?: FilterValidatorFunction<T>;
|
|
20
25
|
}
|
|
21
26
|
|
|
@@ -45,8 +50,11 @@ export interface MultipleOptions<T extends Data> extends FilterConfig<T> {
|
|
|
45
50
|
export interface SearcheableOptionsFilter<T extends Data>
|
|
46
51
|
extends FilterConfig<T> {
|
|
47
52
|
type: FilterTypes.SearcheableOptions;
|
|
48
|
-
|
|
53
|
+
/** Callback triggered when the search input changes. This is also used to resolve the selected option from the value. */
|
|
54
|
+
optionsProvider: (searchText: string, value?: unknown) => Option[];
|
|
55
|
+
/** Placeholder for the search input */
|
|
49
56
|
searchInputPlaceholder?: string;
|
|
57
|
+
/** Maximum number of items to display */
|
|
50
58
|
maxItems?: number;
|
|
51
59
|
}
|
|
52
60
|
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Data } from '../../../../types';
|
|
2
|
+
import { FilterValue, SearcheableOptionsFilter } from '../../Filters.model';
|
|
3
|
+
|
|
4
|
+
export function renderSearcheableOptionsFilterValue<T extends Data>(
|
|
5
|
+
value: FilterValue,
|
|
6
|
+
stringValue: string | undefined,
|
|
7
|
+
setStringValue: (val: string) => void,
|
|
8
|
+
options: SearcheableOptionsFilter<T>,
|
|
9
|
+
): string {
|
|
10
|
+
if (stringValue !== undefined) {
|
|
11
|
+
return stringValue;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const selectedVal = options
|
|
15
|
+
.optionsProvider('', value)
|
|
16
|
+
.find((option) => option.value === value)?.label;
|
|
17
|
+
|
|
18
|
+
if (selectedVal !== undefined) {
|
|
19
|
+
setStringValue(selectedVal);
|
|
20
|
+
return selectedVal;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return String(value);
|
|
24
|
+
}
|
|
@@ -128,11 +128,10 @@ describe('TagsRenderer', () => {
|
|
|
128
128
|
});
|
|
129
129
|
|
|
130
130
|
it('handles empty array', () => {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
expect(container).toBeInTheDocument();
|
|
131
|
+
const { container } = render(
|
|
132
|
+
<RendererWrapper {...defaultProps} value={[]} />,
|
|
133
|
+
);
|
|
134
|
+
expect(container.firstChild).toBeNull();
|
|
136
135
|
});
|
|
137
136
|
|
|
138
137
|
it('cleans up ResizeObserver on unmount', () => {
|
|
@@ -8,13 +8,7 @@ export const TagsRenderer = (val: unknown): JSX.Element => {
|
|
|
8
8
|
const [hiddenItems, setHiddenItems] = useState<string[]>([]);
|
|
9
9
|
|
|
10
10
|
useEffect(() => {
|
|
11
|
-
if (!Array.isArray(val) || !containerRef.current) {
|
|
12
|
-
return;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
if (val.length === 0) {
|
|
16
|
-
setVisibleItems([]);
|
|
17
|
-
setHiddenItems([]);
|
|
11
|
+
if (!Array.isArray(val) || !containerRef.current || val.length === 0) {
|
|
18
12
|
return;
|
|
19
13
|
}
|
|
20
14
|
|
|
@@ -94,7 +88,7 @@ export const TagsRenderer = (val: unknown): JSX.Element => {
|
|
|
94
88
|
};
|
|
95
89
|
}, [val]);
|
|
96
90
|
|
|
97
|
-
if (!Array.isArray(val)) {
|
|
91
|
+
if (!Array.isArray(val) || val.length === 0) {
|
|
98
92
|
return <></>;
|
|
99
93
|
}
|
|
100
94
|
|
|
@@ -87,8 +87,11 @@ export const ImageLoader: React.FC<ImageLoaderProps> = ({
|
|
|
87
87
|
useEffect(() => {
|
|
88
88
|
if (imgSrc === undefined) {
|
|
89
89
|
setState(ImageLoaderState.Failed);
|
|
90
|
+
} else if (state !== ImageLoaderState.Loading) {
|
|
91
|
+
setState(ImageLoaderState.Loading);
|
|
90
92
|
}
|
|
91
|
-
|
|
93
|
+
// else: already loading, don't reset
|
|
94
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
92
95
|
}, [imgSrc]);
|
|
93
96
|
|
|
94
97
|
// Fallback if the image source fails to load in time
|