@controleonline/ui-default 1.0.283 → 1.0.284

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@controleonline/ui-default",
3
- "version": "1.0.283",
3
+ "version": "1.0.284",
4
4
  "author": "ControleOnline",
5
5
  "description": "ControleOnline Default Quasar UI Component",
6
6
  "license": "MIT",
@@ -143,6 +143,9 @@ const DefaultTable = ({
143
143
  };
144
144
  const storeSelectable = storeDeclaredConfigs.selectable === true;
145
145
  const isCompactView = width > 0 && width <= compactBreakpoint;
146
+ // Mobile: no page buttons — infinite scroll only (desktop keeps pages mode when requested).
147
+ const resolvedPaginationMode =
148
+ width > 0 && width <= 768 && paginationMode === 'pages' ? 'infinite' : paginationMode;
146
149
  const addConfig = store?.getters?.add;
147
150
  const normalizedAddButtonPlacement = normalizeText(addButtonPlacement) || 'toolbar';
148
151
  const resolvedAddLabel =
@@ -184,7 +187,7 @@ const DefaultTable = ({
184
187
  onEndReached,
185
188
  onRefresh,
186
189
  pageSize,
187
- paginationMode,
190
+ paginationMode: resolvedPaginationMode,
188
191
  requestParams: requestParamsSeed,
189
192
  resolvedActions,
190
193
  resolvedSort,
@@ -235,7 +238,7 @@ const DefaultTable = ({
235
238
  () => ({
236
239
  ...storeDeclaredConfigs,
237
240
  appearance,
238
- paginationMode,
241
+ paginationMode: resolvedPaginationMode,
239
242
  currentPage,
240
243
  pageSizeNumber,
241
244
  onPageChange: goToPage,
@@ -310,7 +313,7 @@ const DefaultTable = ({
310
313
  viewMode: viewMode ? storeDeclaredConfigs.viewMode : effectiveViewMode,
311
314
  }),
312
315
  [
313
- appearance, paginationMode, currentPage, pageSizeNumber, goToPage, resolvedIsLoading,
316
+ appearance, resolvedPaginationMode, currentPage, pageSizeNumber, goToPage, resolvedIsLoading,
314
317
  add,
315
318
  normalizedAddButtonPlacement,
316
319
  resolvedAddLabel,
@@ -376,7 +379,7 @@ const DefaultTable = ({
376
379
  const defaultTableConfigsSignature = useMemo(
377
380
  () =>
378
381
  stableSerialize({
379
- appearance, paginationMode, currentPage, pageSizeNumber, resolvedIsLoading,
382
+ appearance, resolvedPaginationMode, currentPage, pageSizeNumber, resolvedIsLoading,
380
383
  configuredImport: storeDeclaredConfigs.import || null,
381
384
  add,
382
385
  addButtonPlacement: normalizedAddButtonPlacement,
@@ -415,7 +418,7 @@ const DefaultTable = ({
415
418
  toolbarActionsLength: Array.isArray(toolbarActions) ? toolbarActions.length : 0,
416
419
  }),
417
420
  [
418
- appearance, paginationMode, currentPage, pageSizeNumber, goToPage, resolvedIsLoading,
421
+ appearance, resolvedPaginationMode, currentPage, pageSizeNumber, goToPage, resolvedIsLoading,
419
422
  add,
420
423
  normalizedAddButtonPlacement,
421
424
  resolvedAddLabel,
@@ -276,9 +276,9 @@ emptyBox: {
276
276
  gap: 8,
277
277
  },
278
278
  footerBar: {
279
- minHeight: 40,
279
+ minHeight: 34,
280
280
  paddingHorizontal: 8,
281
- paddingVertical: 5,
281
+ paddingVertical: 3,
282
282
  borderTopWidth: 1,
283
283
  borderTopColor: '#E2E8F0',
284
284
  backgroundColor: '#FFFFFF',
@@ -311,13 +311,13 @@ footerSummaryItem: {
311
311
  },
312
312
  footerSummaryLabel: {
313
313
  color: '#64748B',
314
- fontSize: 9,
314
+ fontSize: 8,
315
315
  fontWeight: '900',
316
316
  textTransform: 'uppercase',
317
317
  },
318
318
  footerSummaryValue: {
319
319
  color: '#0F172A',
320
- fontSize: 13,
320
+ fontSize: 12,
321
321
  fontWeight: '900',
322
322
  },
323
323
  footerCountPill: {
@@ -329,7 +329,7 @@ footerCountPill: {
329
329
  paddingVertical: 5,
330
330
  },
331
331
  footerCountText: {
332
- fontSize: 11,
332
+ fontSize: 10,
333
333
  fontWeight: '900',
334
334
  },
335
335
  emptyText: {
@@ -9,7 +9,7 @@ export default StyleSheet.create({
9
9
  inputMobile: {fontSize: 16},
10
10
  button: {minHeight: 44, minWidth: 44, paddingHorizontal: 10, borderWidth: 1, borderRadius: 8, flexDirection: 'row', alignItems: 'center', justifyContent: 'center', gap: 6},
11
11
  label: {fontSize: 12, fontWeight: '600'},
12
- small: {fontSize: 12},
12
+ small: {fontSize: 11},
13
13
  chips: {flexDirection: 'row', flexWrap: 'wrap', gap: 6, alignItems: 'center'},
14
14
  chip: {minHeight: 30, maxWidth: '100%', borderWidth: 1, borderRadius: 18, paddingHorizontal: 9, flexDirection: 'row', alignItems: 'center', gap: 6},
15
15
  secondary: {flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', flexWrap: 'wrap', gap: 8},
@@ -19,9 +19,9 @@ export default StyleSheet.create({
19
19
  sheetHeader: {flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', gap: 10},
20
20
  sheetTitle: {fontSize: 17, fontWeight: '600'},
21
21
  option: {minHeight: 44, paddingVertical: 10, flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', gap: 8},
22
- footer: {padding: 10, flexShrink: 0, borderTopWidth: 1, flexDirection: 'row', flexWrap: 'wrap', alignItems: 'center', justifyContent: 'space-between', gap: 8},
23
- pager: {flexDirection: 'row', flexWrap: 'wrap', gap: 4, alignItems: 'center'},
24
- page: {minWidth: 44, minHeight: 44, borderWidth: 1, borderRadius: 7, justifyContent: 'center', alignItems: 'center'},
22
+ footer: {paddingVertical: 4, paddingHorizontal: 8, flexShrink: 0, borderTopWidth: 1, flexDirection: 'row', flexWrap: 'nowrap', alignItems: 'center', justifyContent: 'space-between', gap: 6, minHeight: 36},
23
+ pager: {flexDirection: 'row', flexWrap: 'nowrap', gap: 3, alignItems: 'center', flexShrink: 0},
24
+ page: {minWidth: 28, minHeight: 28, paddingHorizontal: 4, borderWidth: 1, borderRadius: 6, justifyContent: 'center', alignItems: 'center'},
25
25
  disabled: {opacity: 0.45},
26
26
  cardItem: {flexDirection: 'column', alignItems: 'stretch', borderWidth: 1, borderRadius: 12, overflow: 'hidden', margin: 0},
27
27
  cardActions: {alignSelf: 'stretch', flexDirection: 'row', justifyContent: 'flex-end', borderTopWidth: 1, paddingHorizontal: 12, paddingVertical: 8},
@@ -12,6 +12,7 @@ import {
12
12
  } from './DefaultTable.utils';
13
13
  import styles from './DefaultTable.styles';
14
14
  import useDefaultTableTheme from './useDefaultTableTheme';
15
+ import DefaultTablePaginationBar from './DefaultTablePaginationBar';
15
16
 
16
17
  const DefaultTableFooter = ({ storeName }) => {
17
18
  const store = useStore(storeName);
@@ -119,10 +120,16 @@ const DefaultTableFooter = ({ storeName }) => {
119
120
  : React.createElement(footerComponent, footerProps);
120
121
  }
121
122
 
122
- if (!shouldRenderFooterBar) {
123
+ // Keep a single footer row even when only pagination (pages mode, desktop) is present.
124
+ // PaginationBar returns null on mobile / infinite mode.
125
+ if (!shouldRenderFooterBar && configs.paginationMode !== 'pages') {
123
126
  return null;
124
127
  }
125
128
 
129
+ const hasSummaryOrCount =
130
+ (shouldRenderFooterTotalItems && !shouldRenderCompactToolbarTotalItems) ||
131
+ summaryEntries.length > 0;
132
+
126
133
  return (
127
134
  <View
128
135
  style={[
@@ -174,6 +181,7 @@ const DefaultTableFooter = ({ storeName }) => {
174
181
  </Text>
175
182
  </View>
176
183
  ) : null}
184
+ <DefaultTablePaginationBar storeName={storeName} embedded />
177
185
  </View>
178
186
  );
179
187
  };
@@ -6,12 +6,16 @@ import useDefaultTableTheme from './useDefaultTableTheme';
6
6
  import {getVisiblePageNumbers} from './DefaultTableCompact.helpers';
7
7
  import s from './DefaultTableCompact.styles';
8
8
 
9
- export default function DefaultTablePaginationBar({storeName}) {
9
+ /**
10
+ * Desktop/tablet only. Mobile keeps infinite scroll (no page buttons).
11
+ * Renders as a compact trailing segment for the unified footer row.
12
+ */
13
+ export default function DefaultTablePaginationBar({storeName, embedded = false}) {
10
14
  const mobile = useWindowDimensions().width <= 768;
11
15
  const store = useStore(storeName);
12
16
  const configs = store?.getters?.configs || {};
13
17
  const {themeColors: c} = useDefaultTableTheme();
14
- if (configs.paginationMode !== 'pages') return null;
18
+ if (mobile || configs.paginationMode !== 'pages') return null;
15
19
  const page = configs.currentPage || 1;
16
20
  const size = configs.pageSizeNumber || 20;
17
21
  const total = Number(store.getters.totalItems || 0);
@@ -20,19 +24,56 @@ export default function DefaultTablePaginationBar({storeName}) {
20
24
  const text = c.tableFooterText || c.textPrimary;
21
25
  const background = c.tableFooterBackground || c.panelBackground;
22
26
  const border = c.tableFooterBorder || c.inputBorder;
23
- const button = (value, icon, label, disabled = false) => <TouchableOpacity key={label} accessibilityRole="button" accessibilityLabel={label}
24
- accessibilityState={{disabled: disabled || busy, selected: !icon && page === value}} disabled={disabled || busy}
25
- onPress={() => configs.onPageChange?.(value)} style={[s.page, {backgroundColor: !icon && page === value ? c.chipSelectedBackground || c.badgeBackground : background, borderColor: border}, (disabled || busy) && s.disabled]}>
26
- {icon ? <Icon name={icon} size={16} color={text} /> : <Text style={[s.small, {color: text}]}>{value}</Text>}
27
- </TouchableOpacity>;
28
- return <View testID="default-table-pagination" style={[s.footer, {backgroundColor: background, borderTopColor: border}]}>
29
- <Text accessibilityLiveRegion="polite" style={[s.small, {color: text}]}>{configs.showTotalItemsInFooter === false ? `Página ${page}` : `${total ? (page - 1) * size + 1 : 0}–${Math.min(page * size, total)} de ${total}`}</Text>
30
- <View style={s.pager}>
31
- {!mobile ? button(1, 'chevrons-left', 'Primeira página', page === 1) : null}
32
- {button(page - 1, 'chevron-left', 'Página anterior', page === 1)}
33
- {getVisiblePageNumbers(page, pages).map(value => button(value, null, `Página ${value}`))}
34
- {button(page + 1, 'chevron-right', 'Próxima página', page >= pages)}
35
- {!mobile ? button(pages, 'chevrons-right', 'Última página', page >= pages) : null}
27
+ const button = (value, icon, label, disabled = false) => (
28
+ <TouchableOpacity
29
+ key={label}
30
+ accessibilityRole="button"
31
+ accessibilityLabel={label}
32
+ accessibilityState={{disabled: disabled || busy, selected: !icon && page === value}}
33
+ disabled={disabled || busy}
34
+ onPress={() => configs.onPageChange?.(value)}
35
+ style={[
36
+ s.page,
37
+ {
38
+ backgroundColor: !icon && page === value ? c.chipSelectedBackground || c.badgeBackground : background,
39
+ borderColor: border,
40
+ },
41
+ (disabled || busy) && s.disabled,
42
+ ]}>
43
+ {icon ? <Icon name={icon} size={13} color={text} /> : <Text style={[s.small, {color: text, fontSize: 11}]}>{value}</Text>}
44
+ </TouchableOpacity>
45
+ );
46
+ const t = global.t?.t;
47
+ const pageWord = t?.(storeName, 'label', 'page') || t?.('configs', 'label', 'page') || 'Página';
48
+ const ofWord = t?.(storeName, 'label', 'of') || t?.('configs', 'label', 'of') || 'de';
49
+ const rangeLabel =
50
+ configs.showTotalItemsInFooter === false
51
+ ? `${pageWord} ${page}`
52
+ : `${total ? (page - 1) * size + 1 : 0}–${Math.min(page * size, total)} ${ofWord} ${total}`;
53
+ const body = (
54
+ <>
55
+ <Text accessibilityLiveRegion="polite" style={[s.small, {color: text, fontSize: 11, flexShrink: 0}]}>
56
+ {rangeLabel}
57
+ </Text>
58
+ <View style={s.pager}>
59
+ {button(1, 'chevrons-left', 'Primeira página', page === 1)}
60
+ {button(page - 1, 'chevron-left', 'Página anterior', page === 1)}
61
+ {getVisiblePageNumbers(page, pages).map(value => button(value, null, `Página ${value}`))}
62
+ {button(page + 1, 'chevron-right', 'Próxima página', page >= pages)}
63
+ {button(pages, 'chevrons-right', 'Última página', page >= pages)}
64
+ </View>
65
+ </>
66
+ );
67
+ if (embedded) {
68
+ return (
69
+ <View testID="default-table-pagination" style={{flexDirection: 'row', alignItems: 'center', gap: 8, flexShrink: 0}}>
70
+ {body}
71
+ </View>
72
+ );
73
+ }
74
+ return (
75
+ <View testID="default-table-pagination" style={[s.footer, {backgroundColor: background, borderTopColor: border}]}>
76
+ {body}
36
77
  </View>
37
- </View>;
78
+ );
38
79
  }
@@ -1,7 +1,6 @@
1
1
  import React from 'react';
2
2
  import { Modal, Text, TouchableOpacity, View } from 'react-native';
3
3
  import Icon from 'react-native-vector-icons/Feather';
4
- import DefaultTablePaginationBar from './DefaultTablePaginationBar';
5
4
  import DefaultTableBody from './DefaultTableBody';
6
5
  import DefaultTableFooter from './DefaultTableFooter';
7
6
  import DefaultTableToolbar from './DefaultTableToolbar';
@@ -50,7 +49,6 @@ export default function DefaultTableView({
50
49
  ) : null}
51
50
  <DefaultTableBody storeName={storeName} />
52
51
  <DefaultTableFooter storeName={storeName} />
53
- <DefaultTablePaginationBar storeName={storeName} />
54
52
  {shouldRenderBottomAddButton ? (
55
53
  <View style={styles.bottomAddBar}>
56
54
  <TouchableOpacity
@@ -130,9 +130,9 @@ export const defaultUploadStyles = {
130
130
  attachmentsEmpty: {borderWidth: 1, borderColor: '#ddd', borderRadius: 8, padding: 10},
131
131
  attachmentsEmptyText: {color: '#666'},
132
132
  attachmentsList: {flexDirection: 'row', gap: 10},
133
- attachmentCard: {width: 240, borderWidth: 1, borderColor: '#ddd', borderRadius: 8, padding: 0, overflow: 'hidden', backgroundColor: '#fff'},
134
- attachmentThumb: {width: 240, height: 240, backgroundColor: '#f5f5f5', overflow: 'hidden', alignItems: 'center', justifyContent: 'center'},
135
- attachmentImage: {width: 240, height: 240},
133
+ attachmentCard: {width: 320, borderWidth: 1, borderColor: '#ddd', borderRadius: 8, padding: 0, overflow: 'hidden', backgroundColor: '#fff'},
134
+ attachmentThumb: {width: 320, height: 320, backgroundColor: '#f5f5f5', overflow: 'hidden', alignItems: 'center', justifyContent: 'center'},
135
+ attachmentImage: {width: 320, height: 320},
136
136
  attachmentActionsRow: {flexDirection: 'row', justifyContent: 'center', alignItems: 'center', gap: 8, marginTop: 2},
137
137
  attachmentIconButton: {width: 36, height: 36, borderRadius: 8, alignItems: 'center', justifyContent: 'center'},
138
138
  attachmentRemoveButton: {backgroundColor: '#b00020', paddingVertical: 6, borderRadius: 4},
@@ -76,20 +76,20 @@ export default function DefaultUploadAttachmentsList({
76
76
  key={row.id || fileId || index}
77
77
  style={[
78
78
  styles.attachmentCard,
79
- // app-community#813: card principal 240x240 (app-community#1275)
80
- {width: 240, padding: 0, overflow: 'hidden'},
79
+ // app-community#813: card principal 320x320
80
+ {width: 320, padding: 0, overflow: 'hidden'},
81
81
  ]}>
82
82
  <View
83
83
  style={[
84
84
  styles.attachmentThumb,
85
- {width: 240, height: 240, marginBottom: 0},
85
+ {width: 320, height: 320, marginBottom: 0},
86
86
  ]}>
87
87
  {file ? (
88
88
  <DefaultFile
89
89
  file={file}
90
90
  company={company}
91
91
  resizeMode="cover"
92
- style={{width: 240, height: 240}}
92
+ style={{width: 320, height: 320}}
93
93
  />
94
94
  ) : null}
95
95
  </View>