@controleonline/ui-default 1.0.279 → 1.0.281

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.
@@ -1,5 +1,5 @@
1
- import {api} from '@controleonline/ui-common/src/api';
2
- import localDB from '@controleonline/ui-common/src/api/localDB';
1
+ import {api} from '@controleonline/ui-common/src/api';
2
+ import localDB from '@controleonline/ui-common/src/api/localDB';
3
3
  import {queue} from '@controleonline/ui-common/src/api/queue';
4
4
  import * as types from '@controleonline/ui-default/src/store/default/mutation_types';
5
5
 
@@ -150,23 +150,23 @@ const commitStoreError = (commit, error, storeMeta) => {
150
150
  buildStoreErrorCommitOptions(storeMeta),
151
151
  )
152
152
  }
153
-
154
- export const executeQueue = ({commit, getters}, func, callback) => {
155
- queue.executeQueue(func, callback);
156
- };
157
-
158
- export const addToQueue = ({commit, getters}, func) => {
159
- queue.addToQueue(func);
160
- };
161
- export const initQueue = ({commit, getters}, func) => {
162
- queue.initQueue(func);
163
- return queue;
164
- };
165
-
153
+
154
+ export const executeQueue = ({commit, getters}, func, callback) => {
155
+ queue.executeQueue(func, callback);
156
+ };
157
+
158
+ export const addToQueue = ({commit, getters}, func) => {
159
+ queue.addToQueue(func);
160
+ };
161
+ export const initQueue = ({commit, getters}, func) => {
162
+ queue.initQueue(func);
163
+ return queue;
164
+ };
165
+
166
166
  export const saveOffline = ({commit, getters}, data) => {
167
167
  return;
168
168
  };
169
-
169
+
170
170
  export const getOfflineItems = ({commit, getters}, params = {}) => {
171
171
  const {storeMeta} = splitStoreActionPayload(params)
172
172
  commit(types.SET_ISLOADING, true);
@@ -175,26 +175,26 @@ export const getOfflineItems = ({commit, getters}, params = {}) => {
175
175
  commit(types.SET_DEBUG, {});
176
176
 
177
177
  db = new localDB(getters);
178
-
179
- return db
180
- .getItemsByFilters()
181
- .then(async data => {
182
- if (!data || (Array.isArray(data) && data.length === 0))
183
- return getOnlineItems({commit, getters}, params).then(data => {
184
- commit(types.SET_ITEM, data);
185
- if (getters.offline) saveOffline({commit, getters}, data);
186
- return data;
187
- });
188
- })
178
+
179
+ return db
180
+ .getItemsByFilters()
181
+ .then(async data => {
182
+ if (!data || (Array.isArray(data) && data.length === 0))
183
+ return getOnlineItems({commit, getters}, params).then(data => {
184
+ commit(types.SET_ITEM, data);
185
+ if (getters.offline) saveOffline({commit, getters}, data);
186
+ return data;
187
+ });
188
+ })
189
189
  .catch(e => {
190
190
  commitStoreError(commit, e, storeMeta)
191
191
  throw e;
192
192
  })
193
- .finally(() => {
194
- commit(types.SET_ISLOADING, false);
195
- });
196
- };
197
-
193
+ .finally(() => {
194
+ commit(types.SET_ISLOADING, false);
195
+ });
196
+ };
197
+
198
198
  export const getOnlineItems = ({commit, getters}, params = {}) => {
199
199
  const {payload: requestParams, storeMeta} = splitStoreActionPayload(params)
200
200
  const {append: shouldAppend = false, ...queryParams} = isPlainObject(requestParams)
@@ -206,11 +206,12 @@ export const getOnlineItems = ({commit, getters}, params = {}) => {
206
206
  params: queryParams,
207
207
  })
208
208
 
209
+ const preserveQuery = storeMeta.preserveItems === true && getters.lastCompletedRequest?.requestKey === requestKey
209
210
  commit(types.SET_ACTIVE_REQUEST_KEY, requestKey)
210
- commit(types.SET_ISLOADING, true);
211
- commit(types.SET_ISLOADINGLIST, true)
211
+ commit(types.SET_ISLOADING, !preserveQuery);
212
+ commit(types.SET_ISLOADINGLIST, !preserveQuery)
212
213
  commit(types.SET_ERROR, null);
213
- if (!shouldAppend) {
214
+ if (!shouldAppend && !preserveQuery) {
214
215
  if (getters.items != null) commit(types.SET_ITEMS, []);
215
216
  commit(types.SET_TOTALITEMS, 0);
216
217
  commit(types.SET_SUMMARY, {});
@@ -262,12 +263,12 @@ export const getOnlineItems = ({commit, getters}, params = {}) => {
262
263
  }
263
264
  });
264
265
  };
265
-
266
- export const getItems = ({commit, getters}, params = {}) => {
267
- //if (getters.offline) return getOfflineItems({commit, getters}, params); else
268
- return getOnlineItems({commit, getters}, params);
269
- };
270
-
266
+
267
+ export const getItems = ({commit, getters}, params = {}) => {
268
+ //if (getters.offline) return getOfflineItems({commit, getters}, params); else
269
+ return getOnlineItems({commit, getters}, params);
270
+ };
271
+
271
272
  export const get = ({commit, getters}, id) => {
272
273
  const {payload: requestId, storeMeta} = splitStoreActionPayload(id)
273
274
  const normalizedId = String(requestId?.id ?? requestId ?? '').replace(/\D/g, '')
@@ -359,15 +360,15 @@ export const remove = ({commit, getters}, id) => {
359
360
  .then(() => {
360
361
  commit(types.SET_ERROR, null);
361
362
  let items = getters.items ? [...getters.items] : [];
362
- const index = items.findIndex(i => {
363
- if (i && i['@id']) return i['@id'].toString().replace(/\D/g, '') === id;
364
- });
365
-
366
- if (index >= 0) items.splice(index, 1);
367
- else items = [];
368
- commit(types.SET_ITEMS, items);
369
- return;
370
- })
363
+ const index = items.findIndex(i => {
364
+ if (i && i['@id']) return i['@id'].toString().replace(/\D/g, '') === id;
365
+ });
366
+
367
+ if (index >= 0) items.splice(index, 1);
368
+ else items = [];
369
+ commit(types.SET_ITEMS, items);
370
+ return;
371
+ })
371
372
  .catch(e => {
372
373
  commitStoreError(commit, e, storeMeta)
373
374
  throw e;
@@ -375,39 +376,39 @@ export const remove = ({commit, getters}, id) => {
375
376
  .finally(() => {
376
377
  commit(types.SET_ISSAVING, false);
377
378
  });
378
- };
379
-
380
- export const setFilters = ({commit, getters}, params) => {
381
- commit(types.SET_FILTERS, params);
382
- };
383
-
384
- export const setItem = ({commit, getters}, params) => {
385
- commit(types.SET_ITEM, params);
386
- };
387
-
388
- export const setItems = ({commit, getters}, params) => {
389
- commit(types.SET_ITEMS, params);
390
- };
391
-
392
- export const setPrint = ({commit, getters}, params) => {
393
- commit(types.SET_PRINT, params);
394
- };
395
-
396
- export const setReload = ({commit, getters}, reload) => {
397
- commit(types.SET_RELOAD, reload);
398
- };
399
-
400
- export const setError = ({commit, getters}, error) => {
401
- commit(types.SET_ERROR, error);
402
- };
403
-
404
- export const setIsSaving = ({commit, getters}, IsSaving) => {
405
- commit(types.SET_ISSAVING, IsSaving);
406
- };
407
- export const setIsLoading = ({commit, getters}, IsLoading) => {
408
- commit(types.SET_ISLOADING, IsLoading);
409
- };
410
-
379
+ };
380
+
381
+ export const setFilters = ({commit, getters}, params) => {
382
+ commit(types.SET_FILTERS, params);
383
+ };
384
+
385
+ export const setItem = ({commit, getters}, params) => {
386
+ commit(types.SET_ITEM, params);
387
+ };
388
+
389
+ export const setItems = ({commit, getters}, params) => {
390
+ commit(types.SET_ITEMS, params);
391
+ };
392
+
393
+ export const setPrint = ({commit, getters}, params) => {
394
+ commit(types.SET_PRINT, params);
395
+ };
396
+
397
+ export const setReload = ({commit, getters}, reload) => {
398
+ commit(types.SET_RELOAD, reload);
399
+ };
400
+
401
+ export const setError = ({commit, getters}, error) => {
402
+ commit(types.SET_ERROR, error);
403
+ };
404
+
405
+ export const setIsSaving = ({commit, getters}, IsSaving) => {
406
+ commit(types.SET_ISSAVING, IsSaving);
407
+ };
408
+ export const setIsLoading = ({commit, getters}, IsLoading) => {
409
+ commit(types.SET_ISLOADING, IsLoading);
410
+ };
411
+
411
412
  export const setTotalItems = ({commit, getters}, totalItems) => {
412
413
  commit(types.SET_TOTALITEMS, totalItems);
413
414
  };
@@ -425,20 +426,20 @@ export const setConfigs = ({commit, getters}, configs) => {
425
426
  };
426
427
 
427
428
  export const setResourceEndpoint = (
428
- {commit, getters},
429
- resourceEndpoint = null,
430
- ) => {
431
- commit(types.SET_RESOURCE_ENDPOINT, resourceEndpoint);
432
- };
433
-
434
- export const setSelected = ({commit, getters}, selected) => {
435
- commit(types.SET_SELECTED, selected);
436
- };
437
-
438
- export const setMessage = ({commit, getters}, message) => {
439
- commit(types.SET_MESSAGE, message);
440
- };
441
-
429
+ {commit, getters},
430
+ resourceEndpoint = null,
431
+ ) => {
432
+ commit(types.SET_RESOURCE_ENDPOINT, resourceEndpoint);
433
+ };
434
+
435
+ export const setSelected = ({commit, getters}, selected) => {
436
+ commit(types.SET_SELECTED, selected);
437
+ };
438
+
439
+ export const setMessage = ({commit, getters}, message) => {
440
+ commit(types.SET_MESSAGE, message);
441
+ };
442
+
442
443
  export const setMessages = ({commit, getters}, messages) => {
443
444
  commit(types.SET_MESSAGES, messages);
444
445
  };
@@ -461,22 +462,22 @@ export const setLastCompletedRequest = (
461
462
  ) => {
462
463
  commit(types.SET_LAST_COMPLETED_REQUEST, lastCompletedRequest);
463
464
  };
464
-
465
- export const setVisibleColumns = ({commit, getters}, visibleColumns) => {
466
- commit(types.SET_VISIBLECOLUMNS, visibleColumns);
467
- };
468
-
469
- export const setIsLoadingList = ({commit, getters}, isLoadingList) => {
470
- commit(types.SET_ISLOADINGLIST, isLoadingList);
471
- };
472
-
473
- export const setStore = ({commit, getters}, store) => {
474
- commit(types.SET_STORE, store);
475
- };
476
-
477
- export const setOffline = ({commit, getters}, offline) => {
478
- commit(types.SET_OFFLINE, offline);
479
- };
480
- export const setPayable = ({commit, getters}, payable) => {
481
- commit(types.SET_PAYABLE, payable);
482
- };
465
+
466
+ export const setVisibleColumns = ({commit, getters}, visibleColumns) => {
467
+ commit(types.SET_VISIBLECOLUMNS, visibleColumns);
468
+ };
469
+
470
+ export const setIsLoadingList = ({commit, getters}, isLoadingList) => {
471
+ commit(types.SET_ISLOADINGLIST, isLoadingList);
472
+ };
473
+
474
+ export const setStore = ({commit, getters}, store) => {
475
+ commit(types.SET_STORE, store);
476
+ };
477
+
478
+ export const setOffline = ({commit, getters}, offline) => {
479
+ commit(types.SET_OFFLINE, offline);
480
+ };
481
+ export const setPayable = ({commit, getters}, payable) => {
482
+ commit(types.SET_PAYABLE, payable);
483
+ };
@@ -0,0 +1,14 @@
1
+ // app-community #1092: the compact layout is the DefaultTable default.
2
+ // Pages (Order History, Financial Hub) must inherit it instead of opting in.
3
+ const fs = require('node:fs');
4
+ const path = require('node:path');
5
+
6
+ const read = relative => fs.readFileSync(path.join(__dirname, relative), 'utf8');
7
+
8
+ it('uses the compact layout as the DefaultTable default appearance', () => {
9
+ expect(read('../../../../react/components/table/DefaultTable.js')).toMatch(/^\s+appearance = 'compact',$/m);
10
+ });
11
+
12
+ it('keeps legacy appearance reachable through an explicit prop', () => {
13
+ expect(read('../../../../react/components/table/DefaultTableToolbar.js')).toMatch(/configs\.appearance === 'compact'/);
14
+ });
@@ -19,6 +19,7 @@ it('can show only search in the toolbar while hiding configured actions and cont
19
19
  renderer.act(() => {
20
20
  tree = renderer.create(
21
21
  React.createElement(DefaultTable, {
22
+ appearance: 'default',
22
23
  columns: [{key: 'name', label: 'Nome', searchable: true}],
23
24
  data: [],
24
25
  showToolbarActions: false,
@@ -42,6 +43,7 @@ it('keeps the list/card toggle visible on compact layouts even when cards are fo
42
43
  renderer.act(() => {
43
44
  tree = renderer.create(
44
45
  React.createElement(DefaultTable, {
46
+ appearance: 'default',
45
47
  columns: [{key: 'name', label: 'Nome'}],
46
48
  data: [],
47
49
  showColumnFiltersButton: false,
@@ -68,6 +70,7 @@ it('respects the compact grid/list toggle in the table body', () => {
68
70
  renderer.act(() => {
69
71
  tree = renderer.create(
70
72
  React.createElement(DefaultTable, {
73
+ appearance: 'default',
71
74
  data: [{id: 1, name: 'Pedido'}],
72
75
  showColumnFiltersButton: false,
73
76
  storeName: 'orders',
@@ -87,6 +90,7 @@ it('respects the compact grid/list toggle in the table body', () => {
87
90
  toggleViewButton.props.onPress();
88
91
  tree.update(
89
92
  React.createElement(DefaultTable, {
93
+ appearance: 'default',
90
94
  data: [{id: 1, name: 'Pedido'}],
91
95
  showColumnFiltersButton: false,
92
96
  storeName: 'orders',
@@ -118,6 +122,7 @@ it('pins identity and action columns on table view', () => {
118
122
  renderer.act(() => {
119
123
  tree = renderer.create(
120
124
  React.createElement(DefaultTable, {
125
+ appearance: 'default',
121
126
  rowActionsComponent,
122
127
  storeName: 'orders',
123
128
  }),
@@ -178,6 +183,7 @@ it('renders a custom row actions component with the configured actions width', (
178
183
  renderer.act(() => {
179
184
  tree = renderer.create(
180
185
  React.createElement(DefaultTable, {
186
+ appearance: 'default',
181
187
  onEditRow: jest.fn(),
182
188
  rowActionsComponent,
183
189
  rowActionsWidth: 180,
@@ -231,6 +237,7 @@ it('keeps only the identity column pinned when row actions are not pinned', () =
231
237
  renderer.act(() => {
232
238
  tree = renderer.create(
233
239
  React.createElement(DefaultTable, {
240
+ appearance: 'default',
234
241
  pinRowActions: false,
235
242
  rowActionsComponent,
236
243
  storeName: 'orders',
@@ -293,6 +300,7 @@ it('keeps the complete search aligned in the toolbar when there is enough room',
293
300
  renderer.act(() => {
294
301
  tree = renderer.create(
295
302
  React.createElement(DefaultTable, {
303
+ appearance: 'default',
296
304
  columns: [{key: 'name', label: 'Nome'}],
297
305
  data: [],
298
306
  storeName: 'orders',
@@ -316,6 +324,7 @@ it('hides the toolbar when the screen disables it', () => {
316
324
  renderer.act(() => {
317
325
  tree = renderer.create(
318
326
  React.createElement(DefaultTable, {
327
+ appearance: 'default',
319
328
  columns: [{key: 'name', label: 'Nome', searchable: true}],
320
329
  data: [],
321
330
  showToolbar: false,
@@ -344,6 +353,7 @@ it('keeps add available as a floating button when the toolbar is hidden', () =>
344
353
  renderer.act(() => {
345
354
  tree = renderer.create(
346
355
  React.createElement(DefaultTable, {
356
+ appearance: 'default',
347
357
  columns: [{key: 'name', label: 'Nome', searchable: true}],
348
358
  data: [],
349
359
  onAdd,
@@ -380,6 +390,7 @@ it('opens the default create form when add has no custom handler', () => {
380
390
  renderer.act(() => {
381
391
  tree = renderer.create(
382
392
  React.createElement(DefaultTable, {
393
+ appearance: 'default',
383
394
  requestParams: {receiver: 21},
384
395
  showToolbar: false,
385
396
  storeName: 'invoice',
@@ -418,6 +429,7 @@ it('collapses search into an icon on narrow toolbars and opens the search modal'
418
429
  renderer.act(() => {
419
430
  tree = renderer.create(
420
431
  React.createElement(DefaultTable, {
432
+ appearance: 'default',
421
433
  columns: [{key: 'name', label: 'Nome'}],
422
434
  data: [],
423
435
  storeName: 'orders',
@@ -13,6 +13,7 @@ it('gives collapsed search a stable accessible name without a placeholder', () =
13
13
  renderer.act(() => {
14
14
  tree = renderer.create(
15
15
  React.createElement(DefaultTable, {
16
+ appearance: 'default',
16
17
  columns: [{key: 'name', label: 'Nome'}],
17
18
  data: [],
18
19
  storeName: 'orders',
@@ -41,6 +42,7 @@ it('keeps the financial compact toolbar aligned when the total is already in the
41
42
  renderer.act(() => {
42
43
  tree = renderer.create(
43
44
  React.createElement(DefaultTable, {
45
+ appearance: 'default',
44
46
  columns: [{key: 'name', label: 'Nome'}],
45
47
  data: [],
46
48
  showTotalItemsInCompactToolbar: true,
@@ -80,6 +82,7 @@ it('opens the filters modal with filterable columns only', () => {
80
82
  renderer.act(() => {
81
83
  tree = renderer.create(
82
84
  React.createElement(DefaultTable, {
85
+ appearance: 'default',
83
86
  data: [],
84
87
  storeName: 'orders',
85
88
  }),
@@ -117,6 +120,7 @@ it('persists filters and sort under default-table[store][route]', () => {
117
120
  renderer.act(() => {
118
121
  tree = renderer.create(
119
122
  React.createElement(DefaultTable, {
123
+ appearance: 'default',
120
124
  storeName: 'orders',
121
125
  }),
122
126
  );
@@ -195,6 +199,7 @@ it('hydrates the saved sort using a stable preference key on auto tables', async
195
199
  await renderer.act(async () => {
196
200
  renderer.create(
197
201
  React.createElement(DefaultTable, {
202
+ appearance: 'default',
198
203
  storeName: 'orders',
199
204
  visibleColumnsPreferenceKey: 'order-history-page',
200
205
  }),
@@ -244,6 +249,7 @@ it('hydrates and persists controlled filters under default-table[store][route]',
244
249
  renderer.act(() => {
245
250
  tree = renderer.create(
246
251
  React.createElement(DefaultTable, {
252
+ appearance: 'default',
247
253
  filters: {},
248
254
  onFilterChange,
249
255
  storeName: 'product_showcase_items',
@@ -257,6 +263,7 @@ it('hydrates and persists controlled filters under default-table[store][route]',
257
263
  renderer.act(() => {
258
264
  tree.update(
259
265
  React.createElement(DefaultTable, {
266
+ appearance: 'default',
260
267
  filters: {integration: 'ifood'},
261
268
  onFilterChange,
262
269
  storeName: 'product_showcase_items',
@@ -294,6 +301,7 @@ it('preserves the compact toolbar total when the footer total is disabled', () =
294
301
  renderer.act(() => {
295
302
  tree = renderer.create(
296
303
  React.createElement(DefaultTable, {
304
+ appearance: 'default',
297
305
  columns: [{key: 'name', label: 'Nome'}],
298
306
  data: [],
299
307
  showTotalItemsInCompactToolbar: true,
@@ -307,6 +315,7 @@ it('preserves the compact toolbar total when the footer total is disabled', () =
307
315
  });
308
316
  it('forces cards when entering compact mode and still toggles between cards and list', () => {
309
317
  const props = {
318
+ appearance: 'default',
310
319
  columns: [{key: 'name', label: 'Nome'}],
311
320
  data: [{id: 1, name: 'Pedido 1'}],
312
321
  showColumnFiltersButton: false,
@@ -360,6 +369,7 @@ it('applies a custom rowStyle to rendered table rows', () => {
360
369
  renderer.act(() => {
361
370
  tree = renderer.create(
362
371
  React.createElement(DefaultTable, {
372
+ appearance: 'default',
363
373
  columns: [{key: 'name', label: 'Nome'}],
364
374
  data: [{id: 1, name: 'Pedido 1'}],
365
375
  onRowPress: () => {},
@@ -398,6 +408,7 @@ it('blocks row navigation while an inline cell is editing or saving', async () =
398
408
  renderer.act(() => {
399
409
  tree = renderer.create(
400
410
  React.createElement(DefaultTable, {
411
+ appearance: 'default',
401
412
  storeName: 'orders',
402
413
  actions: {save},
403
414
  columns: [{key: 'name', label: 'Nome', editable: true}],
@@ -7,6 +7,7 @@ it('protects custom card openRow while a card field is editing', () => {
7
7
  renderer.act(() => {
8
8
  tree = renderer.create(
9
9
  React.createElement(DefaultTable, {
10
+ appearance: 'default',
10
11
  columns: [{key: 'name', label: 'Nome', editable: true}],
11
12
  data: [{id: 1, name: 'Cliente'}],
12
13
  onRowPress,
@@ -44,6 +45,7 @@ it('protects both custom row action navigation callbacks during inline editing',
44
45
  mockState.windowDimensions = {width: 1024, height: 800};
45
46
  let tree;
46
47
  renderer.act(() => {tree = renderer.create(React.createElement(DefaultTable, {
48
+ appearance: 'default',
47
49
  columns: [{key: 'name', label: 'Nome', editable: true}],
48
50
  data: [{id: 1, name: 'Cliente'}], onRowPress,
49
51
  rowActionsComponent: props => React.createElement('CustomRowActions', props),
@@ -82,6 +84,7 @@ it('renders a custom footer component when provided', () => {
82
84
  renderer.act(() => {
83
85
  tree = renderer.create(
84
86
  React.createElement(DefaultTable, {
87
+ appearance: 'default',
85
88
  columns: [{key: 'name', label: 'Nome'}],
86
89
  data: [{id: 1, name: 'Pedido 1'}],
87
90
  footerComponent: FooterComponent,
@@ -113,6 +116,7 @@ it('keeps infinite scroll loading transparent over existing rows', () => {
113
116
  renderer.act(() => {
114
117
  tree = renderer.create(
115
118
  React.createElement(DefaultTable, {
119
+ appearance: 'default',
116
120
  showColumnFiltersButton: false,
117
121
  showRowActions: false,
118
122
  storeName: 'invoices',
@@ -157,6 +161,7 @@ it('uses the configured summary and labels before the store summary', () => {
157
161
  renderer.act(() => {
158
162
  tree = renderer.create(
159
163
  React.createElement(DefaultTable, {
164
+ appearance: 'default',
160
165
  columns: [{key: 'status', label: 'Situação'}],
161
166
  data: [{id: 332, status: 'Pago'}],
162
167
  showColumnFiltersButton: false,
@@ -200,6 +205,7 @@ it('opens a debug query modal when the store exposes debug.query', () => {
200
205
  renderer.act(() => {
201
206
  tree = renderer.create(
202
207
  React.createElement(DefaultTable, {
208
+ appearance: 'default',
203
209
  requestParams: {itemsPerPage: 50},
204
210
  storeName: 'orders',
205
211
  }),
@@ -239,6 +245,7 @@ it('uses store actions when no explicit table actions are passed', async () => {
239
245
  await renderer.act(async () => {
240
246
  renderer.create(
241
247
  React.createElement(DefaultTable, {
248
+ appearance: 'default',
242
249
  columns: [
243
250
  {
244
251
  key: 'jobTitle',
@@ -11,6 +11,7 @@ jest.mock('react-native', () => {
11
11
  Text: props => React.createElement('Text', props, props.children),
12
12
  FlatList: props => React.createElement('List', {}, props.data.map((item, index) => props.renderItem({item, index}))),
13
13
  StyleSheet: {create: value => value},
14
+ useWindowDimensions: () => ({width: 1024, height: 800}),
14
15
  Platform: {select: value => value.web},
15
16
  };
16
17
  });
@@ -73,6 +73,7 @@ jest.mock('react-native', () => {
73
73
 
74
74
  return {
75
75
  FlatList,
76
+ KeyboardAvoidingView: createComponent('KeyboardAvoidingView'),
76
77
  Modal: createComponent('Modal'),
77
78
  Platform: {
78
79
  OS: 'web',