@controleonline/ui-default 1.0.266 → 1.0.268
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/AGENTS.md +3 -2
- package/package.json +1 -1
- package/src/react/components/filters/CompactFilterSelector.js +110 -39
- package/src/react/components/filters/CompactFilterSelector.styles.js +34 -12
- package/src/react/components/inputs/DefaultInput.js +97 -33
- package/src/react/components/inputs/DefaultInput.styles.js +42 -4
- package/src/react/components/inputs/DefaultSelect.js +130 -41
- package/src/react/components/inputs/DefaultSelect.styles.js +3 -0
- package/src/react/components/inputs/defaultInputUtils.js +200 -32
- package/src/react/components/table/DefaultTable.js +13 -5
- package/src/react/components/table/DefaultTable.styles.js +56 -51
- package/src/react/components/table/DefaultTable.utils.js +33 -3
- package/src/react/components/table/DefaultTableCards.js +29 -11
- package/src/react/components/table/DefaultTableFooter.js +10 -1
- package/src/react/components/table/DefaultTableRowActions.js +43 -0
- package/src/react/components/table/DefaultTableRows.js +52 -19
- package/src/react/components/table/DefaultTableToolbar.js +8 -2
- package/src/react/components/table/useDefaultTableTheme.js +65 -16
- package/src/tests/react/components/inputs/DefaultSelect.test.js +72 -0
- package/src/tests/react/components/table/DefaultTable.test.js +55 -0
- package/src/tests/react/components/table/DefaultTable.utils.test.js +37 -0
- package/src/tests/react/inputs/defaultInputUtils.test.js +118 -15
|
@@ -182,4 +182,76 @@ describe('DefaultSelect', () => {
|
|
|
182
182
|
}),
|
|
183
183
|
});
|
|
184
184
|
});
|
|
185
|
+
|
|
186
|
+
it('keeps the status label visible when the row status has color but no icon', async () => {
|
|
187
|
+
global.t = {
|
|
188
|
+
t: jest.fn(() => 'Waiting payment'),
|
|
189
|
+
};
|
|
190
|
+
let tree;
|
|
191
|
+
|
|
192
|
+
await renderer.act(async () => {
|
|
193
|
+
tree = renderer.create(
|
|
194
|
+
React.createElement(DefaultSelect, {
|
|
195
|
+
column: {
|
|
196
|
+
name: 'status',
|
|
197
|
+
label: 'Status',
|
|
198
|
+
list: 'status/getItems',
|
|
199
|
+
translate: false,
|
|
200
|
+
format(value) {
|
|
201
|
+
return {
|
|
202
|
+
value: value.id,
|
|
203
|
+
label: global.t.t('orders', 'status', value.status),
|
|
204
|
+
color: value.color,
|
|
205
|
+
};
|
|
206
|
+
},
|
|
207
|
+
formatList(value) {
|
|
208
|
+
return {
|
|
209
|
+
value: value.id,
|
|
210
|
+
label: global.t.t('orders', 'status', value.status),
|
|
211
|
+
color: value.color,
|
|
212
|
+
};
|
|
213
|
+
},
|
|
214
|
+
},
|
|
215
|
+
row: {
|
|
216
|
+
status: {
|
|
217
|
+
id: 6,
|
|
218
|
+
status: 'waiting payment',
|
|
219
|
+
color: '#000000',
|
|
220
|
+
},
|
|
221
|
+
},
|
|
222
|
+
storeName: 'orders',
|
|
223
|
+
}),
|
|
224
|
+
);
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
const visibleStatus = tree.root
|
|
228
|
+
.findAllByType('Text')
|
|
229
|
+
.find(node => node.props.children === 'Waiting payment');
|
|
230
|
+
|
|
231
|
+
expect(visibleStatus).toBeTruthy();
|
|
232
|
+
expect(visibleStatus.props.style).toEqual(
|
|
233
|
+
expect.arrayContaining([
|
|
234
|
+
expect.objectContaining({
|
|
235
|
+
flex: 1,
|
|
236
|
+
fontSize: 13,
|
|
237
|
+
fontWeight: '600',
|
|
238
|
+
}),
|
|
239
|
+
{color: '#000000'},
|
|
240
|
+
]),
|
|
241
|
+
);
|
|
242
|
+
expect(visibleStatus.props.style).not.toEqual(
|
|
243
|
+
expect.arrayContaining([
|
|
244
|
+
expect.objectContaining({
|
|
245
|
+
backgroundColor: expect.any(String),
|
|
246
|
+
}),
|
|
247
|
+
]),
|
|
248
|
+
);
|
|
249
|
+
expect(visibleStatus.props.style).not.toEqual(
|
|
250
|
+
expect.arrayContaining([
|
|
251
|
+
expect.objectContaining({
|
|
252
|
+
borderColor: expect.any(String),
|
|
253
|
+
}),
|
|
254
|
+
]),
|
|
255
|
+
);
|
|
256
|
+
});
|
|
185
257
|
});
|
|
@@ -401,6 +401,61 @@ describe('DefaultTable', () => {
|
|
|
401
401
|
);
|
|
402
402
|
});
|
|
403
403
|
|
|
404
|
+
it('renders a custom row actions component with the configured actions width', () => {
|
|
405
|
+
mockWindowDimensions = {width: 1200, height: 800};
|
|
406
|
+
mockStores.orders = {
|
|
407
|
+
actions: {},
|
|
408
|
+
getters: {
|
|
409
|
+
columns: [
|
|
410
|
+
{key: 'id', label: 'ID', isIdentity: true},
|
|
411
|
+
{key: 'name', label: 'Nome'},
|
|
412
|
+
],
|
|
413
|
+
items: [{id: 12, name: 'Pedido'}],
|
|
414
|
+
visibleColumns: {},
|
|
415
|
+
},
|
|
416
|
+
};
|
|
417
|
+
const rowActionsComponent = props =>
|
|
418
|
+
React.createElement('row-actions', props, props.row.name);
|
|
419
|
+
let tree;
|
|
420
|
+
|
|
421
|
+
renderer.act(() => {
|
|
422
|
+
tree = renderer.create(
|
|
423
|
+
React.createElement(DefaultTable, {
|
|
424
|
+
onEditRow: jest.fn(),
|
|
425
|
+
rowActionsComponent,
|
|
426
|
+
rowActionsWidth: 180,
|
|
427
|
+
storeName: 'orders',
|
|
428
|
+
}),
|
|
429
|
+
);
|
|
430
|
+
});
|
|
431
|
+
|
|
432
|
+
const rowActions = tree.root.findByType('row-actions');
|
|
433
|
+
expect(rowActions.props.row).toEqual({id: 12, name: 'Pedido'});
|
|
434
|
+
expect(rowActions.props.storeName).toBe('orders');
|
|
435
|
+
expect(typeof rowActions.props.openEdit).toBe('function');
|
|
436
|
+
expect(rowActions.props.helpers).toEqual(
|
|
437
|
+
expect.objectContaining({
|
|
438
|
+
openEdit: expect.any(Function),
|
|
439
|
+
}),
|
|
440
|
+
);
|
|
441
|
+
|
|
442
|
+
const renderedStyles = [
|
|
443
|
+
...tree.root.findAllByType('View'),
|
|
444
|
+
...tree.root.findAllByType('TouchableOpacity'),
|
|
445
|
+
].map(node => flattenStyle(node.props.style));
|
|
446
|
+
|
|
447
|
+
expect(renderedStyles).toEqual(
|
|
448
|
+
expect.arrayContaining([
|
|
449
|
+
expect.objectContaining({
|
|
450
|
+
flexBasis: 180,
|
|
451
|
+
maxWidth: 180,
|
|
452
|
+
minWidth: 180,
|
|
453
|
+
width: 180,
|
|
454
|
+
}),
|
|
455
|
+
]),
|
|
456
|
+
);
|
|
457
|
+
});
|
|
458
|
+
|
|
404
459
|
it('keeps only the identity column pinned when row actions are not pinned', () => {
|
|
405
460
|
mockWindowDimensions = {width: 1200, height: 800};
|
|
406
461
|
mockStores.orders = {
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
const {describe, expect, it} = require('@jest/globals');
|
|
2
|
+
|
|
3
|
+
jest.mock('@store', () => ({
|
|
4
|
+
getAllStores: () => ({}),
|
|
5
|
+
}));
|
|
6
|
+
|
|
7
|
+
jest.mock('react-native', () => ({
|
|
8
|
+
Platform: {
|
|
9
|
+
select: value => value.web || value.default,
|
|
10
|
+
},
|
|
11
|
+
StyleSheet: {
|
|
12
|
+
create: value => value,
|
|
13
|
+
},
|
|
14
|
+
}));
|
|
15
|
+
|
|
16
|
+
jest.mock('@controleonline/ui-common/src/utils/formatter.js', () => ({}));
|
|
17
|
+
jest.mock('@controleonline/ui-common/src/react/utils/dateRangeFilter', () => ({
|
|
18
|
+
getDateRange: () => ({}),
|
|
19
|
+
}));
|
|
20
|
+
|
|
21
|
+
const {
|
|
22
|
+
getColumnMinWidth,
|
|
23
|
+
getColumnStyle,
|
|
24
|
+
} = require('../../../../react/components/table/DefaultTable.utils');
|
|
25
|
+
|
|
26
|
+
describe('DefaultTable utils', () => {
|
|
27
|
+
it('uses column width metadata from the store configuration', () => {
|
|
28
|
+
expect(getColumnMinWidth({name: 'status', minWidth: 180})).toBe(180);
|
|
29
|
+
expect(getColumnStyle({name: 'status', minWidth: 180})).toEqual(
|
|
30
|
+
expect.arrayContaining([
|
|
31
|
+
expect.objectContaining({
|
|
32
|
+
minWidth: 180,
|
|
33
|
+
}),
|
|
34
|
+
]),
|
|
35
|
+
);
|
|
36
|
+
});
|
|
37
|
+
});
|
|
@@ -1,19 +1,23 @@
|
|
|
1
|
-
const {describe, expect, it, jest} = require('@jest/globals');
|
|
2
|
-
|
|
3
|
-
jest.mock('@store', () => ({
|
|
4
|
-
getAllStores: () => ({}),
|
|
5
|
-
}));
|
|
1
|
+
const {describe, expect, it, jest} = require('@jest/globals');
|
|
2
|
+
|
|
3
|
+
jest.mock('@store', () => ({
|
|
4
|
+
getAllStores: () => ({}),
|
|
5
|
+
}));
|
|
6
6
|
|
|
7
7
|
jest.mock('@controleonline/ui-common/src/utils/formatter.js', () => ({}));
|
|
8
8
|
|
|
9
|
-
jest.mock('@controleonline/ui-common/src/react/utils/storeColumns', () => ({
|
|
10
|
-
formatStoreColumnValue: ({value}) => value,
|
|
11
|
-
}));
|
|
12
|
-
|
|
13
|
-
const {
|
|
9
|
+
jest.mock('@controleonline/ui-common/src/react/utils/storeColumns', () => ({
|
|
10
|
+
formatStoreColumnValue: ({value}) => value?.status || value?.category || value,
|
|
11
|
+
}));
|
|
12
|
+
|
|
13
|
+
const {
|
|
14
|
+
buildReadPresentationStyles,
|
|
15
|
+
mapOptions,
|
|
16
|
+
resolveCellPresentation,
|
|
17
|
+
} = require('../../../react/components/inputs/defaultInputUtils');
|
|
14
18
|
|
|
15
|
-
describe('defaultInputUtils', () => {
|
|
16
|
-
it('deduplicates list options by normalized key', () => {
|
|
19
|
+
describe('defaultInputUtils', () => {
|
|
20
|
+
it('deduplicates list options by normalized key', () => {
|
|
17
21
|
const column = {
|
|
18
22
|
formatList(item) {
|
|
19
23
|
return {
|
|
@@ -40,6 +44,105 @@ describe('defaultInputUtils', () => {
|
|
|
40
44
|
label: 'Cielo',
|
|
41
45
|
raw: {id: 4579, wallet: 'Cielo'},
|
|
42
46
|
},
|
|
43
|
-
]);
|
|
44
|
-
});
|
|
45
|
-
|
|
47
|
+
]);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('preserves option color and icon metadata from formatList', () => {
|
|
51
|
+
const column = {
|
|
52
|
+
formatList(item) {
|
|
53
|
+
return {
|
|
54
|
+
color: item.color,
|
|
55
|
+
icon: item.icon,
|
|
56
|
+
value: item.id,
|
|
57
|
+
label: item.status,
|
|
58
|
+
};
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const options = mapOptions(column, [
|
|
63
|
+
{id: 1, status: 'Em rota', color: '#2563EB', icon: 'truck'},
|
|
64
|
+
]);
|
|
65
|
+
|
|
66
|
+
expect(options).toEqual([
|
|
67
|
+
{
|
|
68
|
+
color: '#2563EB',
|
|
69
|
+
icon: 'truck',
|
|
70
|
+
key: '1',
|
|
71
|
+
label: 'Em rota',
|
|
72
|
+
raw: {id: 1, status: 'Em rota', color: '#2563EB', icon: 'truck'},
|
|
73
|
+
},
|
|
74
|
+
]);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('resolves table cell presentation from row value and column style', () => {
|
|
78
|
+
const presentation = resolveCellPresentation({
|
|
79
|
+
column: {
|
|
80
|
+
name: 'status',
|
|
81
|
+
style: row => ({color: row.status.color}),
|
|
82
|
+
},
|
|
83
|
+
row: {
|
|
84
|
+
status: {
|
|
85
|
+
status: 'Aprovado',
|
|
86
|
+
color: '#16A34A',
|
|
87
|
+
icon: 'check-circle',
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
storeName: 'orders',
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
expect(presentation).toEqual({
|
|
94
|
+
backgroundColor: undefined,
|
|
95
|
+
borderColor: undefined,
|
|
96
|
+
color: '#16A34A',
|
|
97
|
+
icon: 'check-circle',
|
|
98
|
+
image: undefined,
|
|
99
|
+
label: 'Aprovado',
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it('resolves table cell presentation from the column format object', () => {
|
|
104
|
+
const presentation = resolveCellPresentation({
|
|
105
|
+
column: {
|
|
106
|
+
name: 'status',
|
|
107
|
+
format(value) {
|
|
108
|
+
return {
|
|
109
|
+
label: value.status,
|
|
110
|
+
color: value.color,
|
|
111
|
+
icon: value.icon,
|
|
112
|
+
};
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
row: {
|
|
116
|
+
status: {
|
|
117
|
+
status: 'Preparando',
|
|
118
|
+
color: '#0EA5E9',
|
|
119
|
+
icon: 'clock',
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
storeName: 'orders',
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
expect(presentation).toEqual({
|
|
126
|
+
backgroundColor: undefined,
|
|
127
|
+
borderColor: undefined,
|
|
128
|
+
color: '#0EA5E9',
|
|
129
|
+
icon: 'clock',
|
|
130
|
+
image: undefined,
|
|
131
|
+
label: 'Preparando',
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it('builds subtle badge colors from resource colors', () => {
|
|
136
|
+
expect(buildReadPresentationStyles({
|
|
137
|
+
color: '#16A34A',
|
|
138
|
+
label: 'Aprovado',
|
|
139
|
+
})).toEqual({
|
|
140
|
+
badgeStyle: {
|
|
141
|
+
backgroundColor: 'rgba(22, 163, 74, 0.1)',
|
|
142
|
+
borderColor: 'rgba(22, 163, 74, 0.32)',
|
|
143
|
+
},
|
|
144
|
+
color: '#16A34A',
|
|
145
|
+
hasDecoration: true,
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
});
|