@axinom/mosaic-ui 0.38.0-rc.3 → 0.38.0-rc.5
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/DynamicDataList/DynamicDataList.model.d.ts +26 -6
- package/dist/components/DynamicDataList/DynamicDataList.model.d.ts.map +1 -1
- package/dist/components/DynamicDataList/DynamicListDataEntry/DynamicListDataEntry.d.ts.map +1 -1
- package/dist/components/DynamicDataList/DynamicListRow/DynamicListRow.d.ts.map +1 -1
- package/dist/components/List/List.model.d.ts +29 -1
- package/dist/components/List/List.model.d.ts.map +1 -1
- package/dist/components/List/ListHeader/ColumnLabel/ColumnLabel.d.ts +5 -4
- package/dist/components/List/ListHeader/ColumnLabel/ColumnLabel.d.ts.map +1 -1
- package/dist/components/List/ListRow/ListRow.d.ts.map +1 -1
- package/dist/index.es.js +2 -2
- package/dist/index.es.js.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/components/DynamicDataList/DynamicDataList.model.ts +33 -6
- package/src/components/DynamicDataList/DynamicDataList.stories.tsx +15 -1
- package/src/components/DynamicDataList/DynamicListDataEntry/DynamicListDataEntry.tsx +6 -3
- package/src/components/DynamicDataList/DynamicListHeader/DynamicListHeader.tsx +1 -1
- package/src/components/DynamicDataList/DynamicListRow/DynamicListRow.tsx +7 -9
- package/src/components/List/List.model.ts +34 -1
- package/src/components/List/List.stories.tsx +18 -0
- package/src/components/List/List.tsx +1 -1
- package/src/components/List/ListHeader/ColumnLabel/ColumnLabel.tsx +11 -8
- package/src/components/List/ListHeader/ListHeader.tsx +1 -1
- package/src/components/List/ListRow/ListRow.tsx +9 -8
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@axinom/mosaic-ui",
|
|
3
|
-
"version": "0.38.0-rc.
|
|
3
|
+
"version": "0.38.0-rc.5",
|
|
4
4
|
"description": "UI components for building Axinom Mosaic applications",
|
|
5
5
|
"author": "Axinom",
|
|
6
6
|
"license": "PROPRIETARY",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"build-storybook": "storybook build"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@axinom/mosaic-core": "^0.4.11-rc.
|
|
35
|
+
"@axinom/mosaic-core": "^0.4.11-rc.5",
|
|
36
36
|
"@faker-js/faker": "^7.4.0",
|
|
37
37
|
"@popperjs/core": "^2.9.2",
|
|
38
38
|
"clsx": "^1.1.0",
|
|
@@ -104,5 +104,5 @@
|
|
|
104
104
|
"publishConfig": {
|
|
105
105
|
"access": "public"
|
|
106
106
|
},
|
|
107
|
-
"gitHead": "
|
|
107
|
+
"gitHead": "8a9ad3cb8a296d5ef91e45bc07c4f0836f82dead"
|
|
108
108
|
}
|
|
@@ -1,19 +1,42 @@
|
|
|
1
1
|
import { Data } from '../../types/data';
|
|
2
2
|
import { ColumnRenderer } from '../List/List.model';
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
interface UnboundColumn<T extends Data> extends BaseColumn<T> {
|
|
5
|
+
/** The name of the property on the Data object that should be rendered in that column. */
|
|
6
|
+
propertyName?: keyof T;
|
|
7
|
+
/**
|
|
8
|
+
* A custom render function that will be called for every row(except data entry row) that should be rendered.
|
|
9
|
+
* The DynamicDataList will already try to render the data in a meaningful way, but in some advanced use cases more control is required.
|
|
10
|
+
*/
|
|
11
|
+
render: ColumnRenderer<T>;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* The identifier for the column.
|
|
15
|
+
*/
|
|
16
|
+
key: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
interface BoundColumn<T extends Data> extends BaseColumn<T> {
|
|
5
20
|
/** The name of the property on the Data object that should be rendered in that column. */
|
|
6
21
|
propertyName: keyof T;
|
|
7
|
-
|
|
8
|
-
size?: string;
|
|
9
|
-
/** Column's header label */
|
|
10
|
-
label?: string;
|
|
22
|
+
|
|
11
23
|
/**
|
|
12
24
|
* A custom render function that will be called for every row(except data entry row) that should be rendered.
|
|
13
25
|
* The DynamicDataList will already try to render the data in a meaningful way, but in some advanced use cases more control is required.
|
|
14
|
-
* @memberof Column
|
|
15
26
|
*/
|
|
16
27
|
render?: ColumnRenderer<T>;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* The identifier for the column. (Default: propertyName)
|
|
31
|
+
*/
|
|
32
|
+
key?: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface BaseColumn<T extends Data> {
|
|
36
|
+
/** The width of the column as CSS size (default: 1fr) */
|
|
37
|
+
size?: string;
|
|
38
|
+
/** Column's header label */
|
|
39
|
+
label?: string;
|
|
17
40
|
/**
|
|
18
41
|
* If set to false, will not render a tooltip for the column data (default: undefined)
|
|
19
42
|
* If a custom renderer is used that will not return a value cast-able to a string, you should consider setting this property to false and add a title attribute on the component returned by the custom renderer.
|
|
@@ -39,6 +62,10 @@ export interface DynamicListColumn<T extends Data> {
|
|
|
39
62
|
disableResizing?: boolean;
|
|
40
63
|
}
|
|
41
64
|
|
|
65
|
+
export type DynamicListColumn<T extends Data> =
|
|
66
|
+
| UnboundColumn<T>
|
|
67
|
+
| BoundColumn<T>;
|
|
68
|
+
|
|
42
69
|
export type DynamicListDataEntryRenderer = (
|
|
43
70
|
/** Value to render. */
|
|
44
71
|
currentValue: unknown,
|
|
@@ -119,7 +119,21 @@ export default meta;
|
|
|
119
119
|
export const Default: StoryObj<StoryDDLType> = {
|
|
120
120
|
args: {
|
|
121
121
|
...defaultProps,
|
|
122
|
-
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
export const UnboundColumn: StoryObj<StoryDDLType> = {
|
|
126
|
+
args: {
|
|
127
|
+
...defaultProps,
|
|
128
|
+
columns: [
|
|
129
|
+
...defaultColumns,
|
|
130
|
+
{
|
|
131
|
+
label: 'Unbound',
|
|
132
|
+
render: () => 'Unbound',
|
|
133
|
+
key: 'unbound',
|
|
134
|
+
size: '150px',
|
|
135
|
+
},
|
|
136
|
+
],
|
|
123
137
|
},
|
|
124
138
|
};
|
|
125
139
|
|
|
@@ -158,7 +158,7 @@ export const DynamicListDataEntry = <T extends Data>({
|
|
|
158
158
|
|
|
159
159
|
let transformedState: T = state;
|
|
160
160
|
for (const { onAddTransformer, propertyName } of columns) {
|
|
161
|
-
if (onAddTransformer) {
|
|
161
|
+
if (onAddTransformer && propertyName) {
|
|
162
162
|
transformedState = {
|
|
163
163
|
...transformedState,
|
|
164
164
|
[propertyName]: onAddTransformer(
|
|
@@ -217,9 +217,12 @@ export const DynamicListDataEntry = <T extends Data>({
|
|
|
217
217
|
>
|
|
218
218
|
{renderField<T>(
|
|
219
219
|
column,
|
|
220
|
-
state[column.propertyName],
|
|
220
|
+
column.propertyName && state[column.propertyName],
|
|
221
221
|
error[column.propertyName as string],
|
|
222
|
-
|
|
222
|
+
column.propertyName
|
|
223
|
+
? (value) =>
|
|
224
|
+
valueChangedHandler(column.propertyName as keyof T, value)
|
|
225
|
+
: noop,
|
|
223
226
|
disabled,
|
|
224
227
|
mode,
|
|
225
228
|
)}
|
|
@@ -97,7 +97,7 @@ export const DynamicListHeader = <T extends Data>({
|
|
|
97
97
|
)}
|
|
98
98
|
{columns.map((column, i) => (
|
|
99
99
|
<div
|
|
100
|
-
key={column.propertyName as string}
|
|
100
|
+
key={column.key ?? (column.propertyName as string)}
|
|
101
101
|
className={clsx(classes.column)}
|
|
102
102
|
ref={cols[i].ref}
|
|
103
103
|
data-test-id={`dynamic-list-header-property:${
|
|
@@ -165,11 +165,7 @@ export const DynamicListRow = <T extends Data>({
|
|
|
165
165
|
</div>
|
|
166
166
|
)}
|
|
167
167
|
{columns.map((column: DynamicListColumn<T>) => {
|
|
168
|
-
const columnData: React.ReactNode = renderData<T>(
|
|
169
|
-
column,
|
|
170
|
-
data,
|
|
171
|
-
column.propertyName,
|
|
172
|
-
);
|
|
168
|
+
const columnData: React.ReactNode = renderData<T>(column, data);
|
|
173
169
|
|
|
174
170
|
return (
|
|
175
171
|
<div
|
|
@@ -177,13 +173,13 @@ export const DynamicListRow = <T extends Data>({
|
|
|
177
173
|
[classes.editable]:
|
|
178
174
|
column.dataEntryRender !== undefined && allowEditing,
|
|
179
175
|
})}
|
|
180
|
-
key={column.propertyName as string}
|
|
176
|
+
key={column.key ?? (column.propertyName as string)}
|
|
181
177
|
>
|
|
182
178
|
<div
|
|
183
179
|
className={classes.column}
|
|
184
180
|
title={
|
|
185
181
|
column.tooltip !== false
|
|
186
|
-
? getTooltipText(
|
|
182
|
+
? getTooltipText(columnData)
|
|
187
183
|
: undefined
|
|
188
184
|
}
|
|
189
185
|
data-test-id={`dynamic-list-property:${
|
|
@@ -229,9 +225,11 @@ export const DynamicListRow = <T extends Data>({
|
|
|
229
225
|
const renderData = function <T extends Data>(
|
|
230
226
|
column: DynamicListColumn<T>,
|
|
231
227
|
data: T,
|
|
232
|
-
propertyName: keyof T,
|
|
233
228
|
): React.ReactNode {
|
|
234
|
-
|
|
229
|
+
if (!column.propertyName) {
|
|
230
|
+
return column.render!(undefined, data);
|
|
231
|
+
}
|
|
232
|
+
const value: unknown = data[column.propertyName];
|
|
235
233
|
if (column.render) {
|
|
236
234
|
return column.render(value, data);
|
|
237
235
|
}
|
|
@@ -18,9 +18,40 @@ export interface ColumnSortKeys {
|
|
|
18
18
|
descending: string;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
interface UnboundColumn<T extends Data> extends BaseColumn<T> {
|
|
22
|
+
/** The name of the property on the Data object that should be rendered in that column. */
|
|
23
|
+
propertyName?: keyof T;
|
|
24
|
+
/**
|
|
25
|
+
* A custom render function that will be called for every row that should be rendered.
|
|
26
|
+
* The List will already try to render the data in a meaningful way, but in some advanced use cases more control is required.
|
|
27
|
+
* @memberof Column
|
|
28
|
+
*/
|
|
29
|
+
render: ColumnRenderer<T>;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* The identifier for the column.
|
|
33
|
+
*/
|
|
34
|
+
key: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
interface BoundColumn<T extends Data> extends BaseColumn<T> {
|
|
22
38
|
/** The name of the property on the Data object that should be rendered in that column. */
|
|
23
39
|
propertyName: keyof T;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* A custom render function that will be called for every row that should be rendered.
|
|
43
|
+
* The List will already try to render the data in a meaningful way, but in some advanced use cases more control is required.
|
|
44
|
+
* @memberof Column
|
|
45
|
+
*/
|
|
46
|
+
render?: ColumnRenderer<T>;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* The identifier for the column. (Default: propertyName)
|
|
50
|
+
*/
|
|
51
|
+
key?: string;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
interface BaseColumn<T extends Data> {
|
|
24
55
|
/** The width of the column as CSS size (default: 1fr) */
|
|
25
56
|
size?: string;
|
|
26
57
|
/** Column's header label */
|
|
@@ -51,6 +82,8 @@ export interface Column<T extends Data> {
|
|
|
51
82
|
disableResizing?: boolean;
|
|
52
83
|
}
|
|
53
84
|
|
|
85
|
+
export type Column<T extends Data> = UnboundColumn<T> | BoundColumn<T>;
|
|
86
|
+
|
|
54
87
|
export interface ColumnMap {
|
|
55
88
|
[key: string]: string;
|
|
56
89
|
}
|
|
@@ -165,6 +165,24 @@ export const Default: StoryObj<StoryListType> = {
|
|
|
165
165
|
}),
|
|
166
166
|
};
|
|
167
167
|
|
|
168
|
+
export const WithUnboundColumn: StoryObj<StoryListType> = {
|
|
169
|
+
name: 'With unbound column',
|
|
170
|
+
args: {
|
|
171
|
+
columns: [
|
|
172
|
+
...defaultColumns,
|
|
173
|
+
{
|
|
174
|
+
// Columns don't have to be bound to a property.
|
|
175
|
+
// They can also just define a renderer and infer the cell data from the row data.
|
|
176
|
+
label: 'Unbound',
|
|
177
|
+
render: (_, data) => <span>{data.desc.substring(15, 20)}</span>,
|
|
178
|
+
key: 'unbound',
|
|
179
|
+
size: '100px',
|
|
180
|
+
},
|
|
181
|
+
],
|
|
182
|
+
},
|
|
183
|
+
render: Default.render,
|
|
184
|
+
};
|
|
185
|
+
|
|
168
186
|
export const Navigating: StoryObj<StoryListType> = {
|
|
169
187
|
name: 'Navigating using DOM links',
|
|
170
188
|
args: {
|
|
@@ -4,11 +4,12 @@ import { noop } from '../../../../helpers/utils';
|
|
|
4
4
|
import { ColumnSortKeys, SortData } from '../../List.model';
|
|
5
5
|
import classes from './ColumnLabel.scss';
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
/** Data object's property name associated with this column */
|
|
9
|
-
propertyName: keyof T;
|
|
7
|
+
interface ColumnLabelProps<T> {
|
|
10
8
|
/** Column label */
|
|
11
9
|
label?: string;
|
|
10
|
+
/** Data object's property name associated with this column */
|
|
11
|
+
propertyName: keyof T | undefined;
|
|
12
|
+
|
|
12
13
|
/** If set to false, disables sorting for this column (default: true) */
|
|
13
14
|
sortable?: boolean;
|
|
14
15
|
/** If set, allow to directly specify which sorting enum value to use */
|
|
@@ -20,15 +21,15 @@ export interface ColumnLabelProps<T> {
|
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
export const ColumnLabel = <T,>({
|
|
23
|
-
propertyName,
|
|
24
24
|
label,
|
|
25
|
+
propertyName,
|
|
25
26
|
sortable = true,
|
|
26
27
|
columnSortKeys,
|
|
27
28
|
sortData,
|
|
28
29
|
onSortChanged = noop,
|
|
29
30
|
}: PropsWithChildren<ColumnLabelProps<T>>): JSX.Element => {
|
|
30
31
|
/** Creates sort data object to be emitted back on change event. */
|
|
31
|
-
const getSortDir = (): SortData<T> => {
|
|
32
|
+
const getSortDir = (propertyName: keyof T): SortData<T> => {
|
|
32
33
|
if (sortData?.column === propertyName && sortData.direction === 'asc') {
|
|
33
34
|
return {
|
|
34
35
|
column: propertyName,
|
|
@@ -46,9 +47,9 @@ export const ColumnLabel = <T,>({
|
|
|
46
47
|
|
|
47
48
|
/** Determines if the current column is currently being used to sort and which direction. */
|
|
48
49
|
const direction =
|
|
49
|
-
sortData?.column === propertyName ? sortData
|
|
50
|
+
sortData?.column === propertyName ? sortData?.direction : undefined;
|
|
50
51
|
|
|
51
|
-
if (!sortable) {
|
|
52
|
+
if (!propertyName || !sortable) {
|
|
52
53
|
return (
|
|
53
54
|
<div
|
|
54
55
|
className={classes.container}
|
|
@@ -62,7 +63,9 @@ export const ColumnLabel = <T,>({
|
|
|
62
63
|
<div className={classes.container}>
|
|
63
64
|
<div
|
|
64
65
|
className={clsx(classes.clickWrapper, classes.sortable)}
|
|
65
|
-
onClick={
|
|
66
|
+
onClick={
|
|
67
|
+
propertyName && (() => onSortChanged(getSortDir(propertyName)))
|
|
68
|
+
}
|
|
66
69
|
data-test-id={`list-label:${String(propertyName)}`}
|
|
67
70
|
data-test-sort-dir={direction ?? 'none'}
|
|
68
71
|
>
|
|
@@ -84,9 +84,11 @@ setLocale(navigator.language);
|
|
|
84
84
|
function renderData<T extends Data>(
|
|
85
85
|
column: Column<T>,
|
|
86
86
|
rowData: T,
|
|
87
|
-
propertyName: keyof T,
|
|
88
87
|
): React.ReactNode {
|
|
89
|
-
|
|
88
|
+
if (!column.propertyName) {
|
|
89
|
+
return column.render!(undefined, rowData);
|
|
90
|
+
}
|
|
91
|
+
const value: unknown = rowData[column.propertyName];
|
|
90
92
|
if (column.render) {
|
|
91
93
|
return column.render(value, rowData);
|
|
92
94
|
}
|
|
@@ -197,14 +199,13 @@ export const ListRow = <T extends Data>({
|
|
|
197
199
|
typeof onItemClicked !== 'function';
|
|
198
200
|
|
|
199
201
|
const generateCells: JSX.Element[] = columns.map((column: Column<T>) => {
|
|
200
|
-
const columnData: React.ReactNode = renderData<T>(
|
|
201
|
-
column,
|
|
202
|
-
data,
|
|
203
|
-
column.propertyName,
|
|
204
|
-
);
|
|
202
|
+
const columnData: React.ReactNode = renderData<T>(column, data);
|
|
205
203
|
|
|
206
204
|
return (
|
|
207
|
-
<div
|
|
205
|
+
<div
|
|
206
|
+
key={column.key ?? (column.propertyName as string)}
|
|
207
|
+
className={classes.cellWrapper}
|
|
208
|
+
>
|
|
208
209
|
<div
|
|
209
210
|
className={classes.cell}
|
|
210
211
|
title={
|