@usssa/component-library 1.0.0-alpha.15 → 1.0.0-alpha.151

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.
Files changed (57) hide show
  1. package/README.md +6 -3
  2. package/package.json +23 -5
  3. package/src/assets/logo.svg +19 -0
  4. package/src/assets/no-result.svg +25 -0
  5. package/src/assets/quasar-logo-vertical.svg +15 -0
  6. package/src/assets/upload-illustration.svg +48 -0
  7. package/src/components/core/UAvatar.vue +56 -24
  8. package/src/components/core/UAvatarGroup.vue +62 -52
  9. package/src/components/core/UBadgeStd.vue +6 -1
  10. package/src/components/core/UBannerStd.vue +100 -31
  11. package/src/components/core/UBreadCrumbs.vue +171 -0
  12. package/src/components/core/UBtnIcon.vue +58 -53
  13. package/src/components/core/UBtnStd.vue +39 -31
  14. package/src/components/core/UBtnToggle.vue +11 -6
  15. package/src/components/core/UCheckboxStd.vue +26 -20
  16. package/src/components/core/UChip.vue +76 -42
  17. package/src/components/core/UDate.vue +565 -0
  18. package/src/components/core/UDialogStd.vue +460 -53
  19. package/src/components/core/UDrawer.vue +321 -0
  20. package/src/components/core/UInnerLoader.vue +69 -0
  21. package/src/components/core/UInputAddressLookup.vue +471 -0
  22. package/src/components/core/UInputPhoneStd.vue +73 -68
  23. package/src/components/core/UInputTextStd.vue +133 -116
  24. package/src/components/core/UInputTypeahead.vue +44 -0
  25. package/src/components/core/UInputTypeaheadAdvanceSearch.vue +126 -0
  26. package/src/components/core/UMenuButtonStd.vue +280 -0
  27. package/src/components/core/UMenuDropdown.vue +80 -0
  28. package/src/components/core/UMenuDropdownAdvancedSearch.vue +293 -0
  29. package/src/components/core/UMenuItem.vue +161 -0
  30. package/src/components/core/UMenuSearch.vue +69 -0
  31. package/src/components/core/UMultiSelectStd.vue +258 -54
  32. package/src/components/core/UPagination.vue +67 -27
  33. package/src/components/core/URadioBtn.vue +66 -43
  34. package/src/components/core/URadioStd.vue +19 -12
  35. package/src/components/core/USelectStd.vue +360 -80
  36. package/src/components/core/USheet.vue +349 -0
  37. package/src/components/core/UTabBtnStd.vue +87 -59
  38. package/src/components/core/UTable/UTable.vue +811 -42
  39. package/src/components/core/UTableStd.vue +875 -275
  40. package/src/components/core/UTabsStd.vue +57 -16
  41. package/src/components/core/UToggleStd.vue +43 -29
  42. package/src/components/core/UToolbar/UCustomMenuIcon.vue +58 -0
  43. package/src/components/core/UToolbar/UToolbar.vue +210 -0
  44. package/src/components/core/UTooltip.vue +31 -10
  45. package/src/components/core/UTypeahead.vue +830 -0
  46. package/src/components/core/UUploader.vue +535 -0
  47. package/src/components/index.js +61 -21
  48. package/src/composables/useNotify.js +16 -16
  49. package/src/composables/useOverlayLoader.js +23 -0
  50. package/src/composables/useScreenType.js +30 -0
  51. package/src/css/app.sass +168 -0
  52. package/src/css/colors.sass +103 -0
  53. package/src/css/media.sass +1 -0
  54. package/src/css/quasar.variables.sass +121 -0
  55. package/src/css/typography.sass +0 -0
  56. package/src/css/vars/colors.variables.sass +127 -0
  57. package/src/utils/data.ts +146 -0
@@ -1,86 +1,117 @@
1
1
  <script setup>
2
+ import { useQuasar } from 'quasar'
3
+ import { computed, ref, watch } from 'vue'
4
+ import { useScreenType } from '..'
5
+ import UAvatar from './UAvatar.vue'
6
+ import UBtnIcon from './UBtnIcon.vue'
7
+ import UBtnStd from './UBtnStd.vue'
8
+ import UCheckboxStd from './UCheckboxStd.vue'
9
+ import UChip from './UChip.vue'
10
+ import UMenuDropdown from './UMenuDropdown.vue'
11
+ import UPagination from './UPagination.vue'
12
+ import UTable from './UTable/UTable.vue'
2
13
  import UTd from './UTable/UTd.vue'
3
14
  import UTh from './UTable/UTh.vue'
4
15
  import UTr from './UTable/UTr.vue'
5
- import UTable from './UTable/UTable.vue'
6
- import { computed, ref } from 'vue'
7
- import UCheckboxStd from './UCheckboxStd.vue'
8
- import UChip from './UChip.vue'
9
- import UAvatar from './UAvatar.vue'
10
- import UBtnStd from './UBtnStd.vue'
11
16
  import UTooltip from './UTooltip.vue'
12
- import UPagination from './UPagination.vue'
17
+
18
+ const emit = defineEmits(['onCustomSort'])
19
+ const columns = defineModel('columns', {
20
+ default: () => [],
21
+ type: Array,
22
+ })
23
+ const filteredRows = defineModel('filteredRows', { default: [], type: Array })
24
+ const grid = defineModel('grid', {
25
+ default: false,
26
+ type: Boolean,
27
+ })
28
+ const loading = defineModel('loading', {
29
+ default: () => {},
30
+ type: Boolean,
31
+ })
32
+ const moreActionDialogData = defineModel('moreActionDialogData', {
33
+ type: Object,
34
+ default: null,
35
+ })
36
+ const pagination = defineModel('pagination', {
37
+ default: { page: 1, rowsPerPage: 5 },
38
+ type: Object,
39
+ })
40
+ const rows = defineModel('rows', {
41
+ default: () => [],
42
+ type: Array,
43
+ })
44
+ const selectedRows = defineModel('selectedRows', {
45
+ default: () => [],
46
+ type: Array,
47
+ })
48
+
13
49
  const props = defineProps({
14
- title: {
15
- type: String,
16
- default: '',
17
- },
18
- tableRowHover: {
50
+ bordered: {
19
51
  type: Boolean,
20
52
  default: false,
21
53
  },
22
- separator: {
54
+ customClass: {
23
55
  type: String,
24
- default: 'horizontal',
56
+ default: '',
25
57
  },
26
- multiSelection: {
27
- type: Boolean,
28
- default: false,
58
+ dataTestId: {
59
+ type: String,
60
+ default: 'table-std',
61
+ },
62
+ filter: {
63
+ type: String,
64
+ default: '',
29
65
  },
30
66
  flat: {
31
67
  type: Boolean,
32
68
  default: false,
33
69
  },
34
- bordered: {
70
+ isCustomSort: {
35
71
  type: Boolean,
36
72
  default: false,
37
73
  },
38
- grid: {
74
+ multiSelection: {
39
75
  type: Boolean,
40
76
  default: false,
41
77
  },
42
- virtualScroll: {
78
+ rowCardHeight: {
79
+ type: Number,
80
+ default: 25,
81
+ },
82
+ separator: {
83
+ type: String,
84
+ default: 'horizontal',
85
+ },
86
+ showPagination: {
43
87
  type: Boolean,
44
- default: false,
88
+ default: true,
45
89
  },
46
90
  stickyHeader: {
47
91
  type: Boolean,
48
92
  default: false,
49
93
  },
50
- isCustomSort: {
94
+ tableRowHover: {
51
95
  type: Boolean,
52
96
  default: false,
53
97
  },
54
- customClass: {
98
+ title: {
55
99
  type: String,
56
100
  default: '',
57
101
  },
58
- maxPageLink: {
59
- type: Number,
60
- default: 3,
102
+ verticalMoreActions: {
103
+ type: Boolean,
104
+ default: false,
105
+ },
106
+ virtualScroll: {
107
+ type: Boolean,
108
+ default: false,
61
109
  },
62
110
  })
63
111
 
64
- const selectedRows = defineModel('selectedRows', {
65
- default: () => [],
66
- type: Array,
67
- })
68
- const rows = defineModel('rows', {
69
- default: () => [],
70
- type: Array,
71
- })
72
- const columns = defineModel('columns', {
73
- default: () => [],
74
- type: Array,
75
- })
76
- const pagination = defineModel('pagination', {
77
- default: () => {},
78
- type: Object,
79
- })
80
- const loading = defineModel('loading', {
81
- default: () => {},
82
- type: Boolean,
83
- })
112
+ const $q = useQuasar()
113
+ const $screen = useScreenType()
114
+
84
115
  const customLoading = ref(false)
85
116
  const rowsPerPageOptions = ref([
86
117
  { label: '5 / per page', value: 5 },
@@ -89,20 +120,9 @@ const rowsPerPageOptions = ref([
89
120
  { label: '20 / per page', value: 20 },
90
121
  { label: '25 / per page', value: 25 },
91
122
  ])
92
-
93
123
  const tableDataChip = ref(true) // this is required to show chip
124
+ const tailClass = ref(null)
94
125
 
95
- //adding a new row to selectedRows
96
- const handleToSelectRow = (row) => {
97
- if (row) {
98
- const index = selectedRows.value.findIndex((item) => item._id === row._id)
99
- if (index === -1) {
100
- selectedRows.value.push(row)
101
- } else {
102
- selectedRows.value.splice(index, 1)
103
- }
104
- }
105
- }
106
126
  // if virtual scroll is enbaled then adding large rows per page to view in virtual scroll
107
127
  const getRowsPerPageOptions = computed(() => {
108
128
  if (props.virtualScroll) {
@@ -117,6 +137,55 @@ const getRowsPerPageOptions = computed(() => {
117
137
  }
118
138
  })
119
139
 
140
+ const isMobile = computed(() => $screen.value.isMobile)
141
+ const isMobileOrTablet = computed(
142
+ () => $screen.value.isMobile || $screen.value.isTablet
143
+ )
144
+ const isSmallDevices = computed(() => $q.screen.width < 390)
145
+
146
+ // chekcing the menu position after show
147
+ const checkMenuPosition = (id) => {
148
+ const menuElement = document.getElementById(`actionPopupRef-${id}`) // Access the menu by ID
149
+ const buttonElement = document.getElementById(`actionPopupRefBtn-${id}`) // Access the button element
150
+
151
+ if (menuElement && buttonElement) {
152
+ const menuRect = menuElement.getBoundingClientRect() // Menu position
153
+ const buttonRect = buttonElement.getBoundingClientRect() // Button position
154
+
155
+ // Determine if the menu opens above or below
156
+ if (menuRect.top < buttonRect.top) {
157
+ tailClass.value = 'tail-bottom' // Menu opens below, tail at the bottom
158
+ } else {
159
+ tailClass.value = 'tail-top' // Menu opens above, tail at the top
160
+ }
161
+ }
162
+ }
163
+
164
+ // sorting funtion to handle text and number type of data
165
+ const dataSort = (data, key, order, type) => {
166
+ if (type === 'text') {
167
+ return data.sort((a, b) =>
168
+ order === 'asc'
169
+ ? a[key].localeCompare(b[key])
170
+ : b[key].localeCompare(a[key])
171
+ )
172
+ } else {
173
+ return data.sort((a, b) =>
174
+ order === 'asc' ? a[key] - b[key] : b[key] - a[key]
175
+ )
176
+ }
177
+ }
178
+
179
+ //getting the chip color accroding to value of chip from row
180
+ const getChipColor = (data, value) => {
181
+ const foundObject = data.find((chip) => chip.value === value)
182
+ if (foundObject) {
183
+ return foundObject['color']
184
+ } else {
185
+ return 'neutral-3'
186
+ }
187
+ }
188
+
120
189
  //getting the sorted icon according the order
121
190
  const getSortingIcon = (col) => {
122
191
  if (col) {
@@ -128,59 +197,19 @@ const getSortingIcon = (col) => {
128
197
  }
129
198
  }
130
199
 
131
- // it is giving the selected row and setting the new selection
132
- const isRowSelected = (row) => {
133
- if (row) {
134
- const index = selectedRows.value.findIndex((item) => item._id === row._id)
135
- return computed({
136
- get: () => {
137
- return index === -1 ? false : true
138
- },
139
- set: () => {
140
- if (index === -1) {
141
- selectedRows.value.push(row)
142
- } else {
143
- selectedRows.value.splice(index, 1)
144
- }
145
- },
146
- })
147
- } else {
148
- return computed({
149
- get: () => {
150
- let dataLength = props.virtualScroll
151
- ? pagination.value.rowsPerPage
152
- : props.rows.length
153
- return selectedRows.value.length === dataLength
154
- ? true
155
- : selectedRows.value.length === 0
156
- ? false
157
- : null
158
- },
159
- set: (value) => {
160
- if (value !== null) {
161
- selectedRows.value.splice(0, selectedRows.value.length)
162
- } else {
163
- if (props.virtualScroll) {
164
- handleSelectAllData().then((res) => {
165
- if (res === 200) {
166
- customLoading.value = false
167
- }
168
- })
169
- } else {
170
- props.rows.forEach((element) => {
171
- if (
172
- selectedRows.value.findIndex(
173
- (item) => item._id === element._id
174
- ) === -1
175
- ) {
176
- selectedRows.value.push(element)
177
- }
178
- })
179
- }
180
- }
181
- },
182
- })
183
- }
200
+ const handleActionColClick = (e) => {
201
+ e.preventDefault()
202
+ e.stopPropagation()
203
+ }
204
+
205
+ //if user want to add custom sort on data
206
+ const handleCustomSort = (key, sortOrder, type) => {
207
+ emit('onCustomSort', key, sortOrder, type)
208
+ }
209
+
210
+ const handleMenuEventStop = (e) => {
211
+ e.preventDefault()
212
+ e.stopPropagation()
184
213
  }
185
214
 
186
215
  // handling the large selection data in chunks
@@ -189,7 +218,7 @@ const handleSelectAllData = () => {
189
218
  return new Promise((resolve, reject) => {
190
219
  let index = 0
191
220
  function processChunk() {
192
- if (index >= pagination.value.rowsPerPage) {
221
+ if (index >= rows.value.length) {
193
222
  resolve(200)
194
223
  return
195
224
  }
@@ -213,23 +242,6 @@ const handleSelectAllData = () => {
213
242
  })
214
243
  }
215
244
 
216
- const emit = defineEmits(['onCustomSort'])
217
-
218
- // sorting funtion to handle text and number type of data
219
- const dataSort = (data, key, order, type) => {
220
- if (type === 'text') {
221
- return data.sort((a, b) =>
222
- order === 'asc'
223
- ? a[key].localeCompare(b[key])
224
- : b[key].localeCompare(a[key])
225
- )
226
- } else {
227
- return data.sort((a, b) =>
228
- order === 'asc' ? a[key] - b[key] : b[key] - a[key]
229
- )
230
- }
231
- }
232
-
233
245
  //it is sorting the data according to type like text or number type of data
234
246
  const handleSort = (key, sortOrder, type) => {
235
247
  rows.value = dataSort(rows.value, key, sortOrder, type)
@@ -240,22 +252,64 @@ const handleSort = (key, sortOrder, type) => {
240
252
  })
241
253
  }
242
254
 
243
- //if user want to add custom sort on data
244
- const handleCustomSort = (key, sortOrder, type) => {
245
- emit('onCustomSort', key, sortOrder, type)
255
+ //adding a new row to selectedRows
256
+ const handleToSelectRow = (row) => {
257
+ if (row) {
258
+ const index = selectedRows.value.findIndex((item) => item._id === row._id)
259
+ if (index === -1) {
260
+ selectedRows.value.push(row)
261
+ } else {
262
+ selectedRows.value.splice(index, 1)
263
+ }
264
+ }
246
265
  }
247
266
 
248
- //adding a new row to selectedRows
249
- const onRowClick = (event, row) => {
250
- if (props.multiSelection) {
251
- event.stopPropagation()
252
- handleToSelectRow(row)
267
+ // it is giving the selected row and setting the new selection
268
+ const isRowSelected = (row) => {
269
+ if (row) {
270
+ const index = selectedRows.value.findIndex((item) => item._id === row._id)
271
+ return computed({
272
+ get: () => {
273
+ return index === -1 ? false : true
274
+ },
275
+ set: () => {
276
+ if (index === -1) {
277
+ selectedRows.value.push(row)
278
+ } else {
279
+ selectedRows.value.splice(index, 1)
280
+ }
281
+ },
282
+ })
283
+ } else {
284
+ return computed({
285
+ get: () => {
286
+ let dataLength = props.rows.length
287
+ return selectedRows.value.length === dataLength
288
+ ? true
289
+ : selectedRows.value.length === 0
290
+ ? false
291
+ : null
292
+ },
293
+ set: (value) => {
294
+ if (value !== null) {
295
+ selectedRows.value.splice(0, selectedRows.value.length)
296
+ } else {
297
+ handleSelectAllData().then((res) => {
298
+ if (res === 200) {
299
+ customLoading.value = false
300
+ }
301
+ })
302
+ }
303
+ },
304
+ })
253
305
  }
254
306
  }
255
307
 
256
- //getting the chip color accroding to value of chip from row
257
- const getChipColor = (data, value) => {
258
- return data.find((chip) => chip.value === value)['color']
308
+ // removing console error for show dialog
309
+ const onMoreActionButtonClick = (id) => {
310
+ if (moreActionDialogData.value) {
311
+ moreActionDialogData.value.showDialog[id] = false
312
+ }
259
313
  }
260
314
 
261
315
  // handle to change the page, and if virtual scroll is enabled and user scrolled to bottom it will take user to the top
@@ -263,125 +317,168 @@ const onPageChange = (value) => {
263
317
  pagination.value.page = value
264
318
  }
265
319
 
320
+ //adding a new row to selectedRows
321
+ const onRowClick = (event, row) => {
322
+ if (props.multiSelection) {
323
+ event.stopPropagation()
324
+ handleToSelectRow(row)
325
+ }
326
+ }
327
+
266
328
  //handle to change the rows per page
267
329
  const onRowPerPageChange = (value) => {
268
330
  pagination.value.rowsPerPage = value
269
331
  }
332
+
333
+ const updatedRows = computed(() => {
334
+ if (props.filter.length && filteredRows.value?.length)
335
+ return filteredRows.value
336
+ else if (props.filter.length) return []
337
+ return rows.value
338
+ })
339
+
340
+ // watchers
341
+ watch(
342
+ isMobileOrTablet,
343
+ (newVal) => {
344
+ grid.value = newVal
345
+ },
346
+ { immediate: true }
347
+ )
270
348
  </script>
271
349
 
272
350
  <template>
273
351
  <UTable
274
- :title="title"
275
- v-model:rows="rows"
276
352
  v-model:columns="columns"
277
- :separator="separator"
278
- :loading="loading"
279
- :flat="flat"
280
- :bordered="bordered"
353
+ v-model:filteredRows="filteredRows"
354
+ v-model:moreActionDialogData="moreActionDialogData"
281
355
  v-model:pagination="pagination"
356
+ v-model:rows="rows"
357
+ :class="customClass"
358
+ :bordered="bordered"
359
+ :dataTestId="dataTestId"
360
+ :filter="filter"
361
+ :flat="flat"
282
362
  :grid="grid"
283
- :virtualScroll="virtualScroll"
363
+ :loading="loading"
364
+ :row-card-height="rowCardHeight"
365
+ :separator="separator"
366
+ :showPagination="showPagination"
284
367
  :stickyHeader="stickyHeader"
285
- :class="customClass"
368
+ :title="title"
369
+ :virtualScroll="virtualScroll"
286
370
  >
287
371
  <!-- custom header slot to add customized header -->
288
372
  <template v-slot:header="props">
289
373
  <UTr :props="props" :tableRowHover="tableRowHover">
290
374
  <UTh
291
375
  v-if="multiSelection"
376
+ :separator="separator"
292
377
  style="width: 3% !important"
293
- :tableHeaderAutoWidth="false"
294
378
  tableHeadAlignment="left"
295
- :separator="separator"
379
+ :tableHeaderAutoWidth="false"
296
380
  >
297
381
  <UCheckboxStd
298
- :id="`u-checkbox-table-header`"
299
382
  v-model="isRowSelected(null).value"
300
- name="Table Header"
383
+ id="u-checkbox-table-header"
301
384
  :indeterminate="true"
385
+ name="Table Header"
302
386
  />
303
387
  </UTh>
304
- <UTh
305
- v-for="(col, key) in props.cols"
306
- :class="`${col.sortable ? 'cursor-pointer' : ''} ${
307
- col.headerClasses
308
- }`"
309
- :key="key"
310
- :tableHeaderAutoWidth="col.autoWidth"
311
- :tableHeadAlignment="col.field === 'action' ? col.align : col.align"
312
- @click="
313
- col.sortable
314
- ? isCustomSort
315
- ? handleCustomSort(col.field, col.sortOrder, col.type)
316
- : handleSort(col.field, col.sortOrder, col.type)
317
- : null
318
- "
319
- :separator="separator"
320
- :style="col.headerStyle"
321
- >
322
- {{ col.label }}
323
- <span v-if="col.sortable && col.field !== 'action'">
324
- <q-btn label="Sorting Button" :ripple="false" class="u-sorting-btn">
325
- <q-icon
326
- size="xs"
327
- :class="`${getSortingIcon(col)} sorting-icon`"
328
- :aria-label="col.label"
329
- alt="sort-desc"
330
- tabindex="0"
331
- ></q-icon>
332
- </q-btn>
333
- </span>
334
- </UTh>
388
+ <template v-for="(col, key) in props.cols">
389
+ <UTh
390
+ v-if="typeof col.show === 'undefined' || col.show"
391
+ :class="`${col.sortable ? 'cursor-pointer' : ''} ${
392
+ col.headerClasses
393
+ }`"
394
+ :key="key"
395
+ :separator="separator"
396
+ :style="col.headerStyle"
397
+ :tableHeadAlignment="col.field === 'action' ? col.align : col.align"
398
+ :tableHeaderAutoWidth="col.autoWidth"
399
+ @click="
400
+ col.sortable
401
+ ? isCustomSort
402
+ ? handleCustomSort(col.field, col.sortOrder, col.type)
403
+ : handleSort(col.field, col.sortOrder, col.type)
404
+ : null
405
+ "
406
+ >
407
+ <span
408
+ :class="`${col.field === 'action' ? 'hidden-header-label' : ''}`"
409
+ >
410
+ {{ col.field === 'action' ? 'Action' : col.label }}
411
+ </span>
412
+
413
+ <span v-if="col.sortable && col.field !== 'action'">
414
+ <UBtnIcon
415
+ :class="`more-action-icon cursor-pointer`"
416
+ :iconClass="`${getSortingIcon(col)}`"
417
+ :aria-label="`Sort ${col.label}`"
418
+ ref="btn-icon"
419
+ size="sm"
420
+ />
421
+ </span>
422
+ </UTh>
423
+ </template>
335
424
  </UTr>
336
425
  </template>
337
426
  <!-- custom body slots to add customized cell data -->
338
427
  <template v-slot:body="props">
339
428
  <UTr
429
+ :class="`${isRowSelected(props.row).value ? 'selected-data-row' : ''}`"
340
430
  :props="props"
341
- @click="onRowClick($event, props.row)"
342
431
  :tableRowHover="tableRowHover"
343
- :class="`${isRowSelected(props.row).value ? 'selected-data-row' : ''}`"
432
+ @click="onRowClick($event, props.row)"
344
433
  >
345
434
  <UTd
346
435
  v-if="multiSelection"
347
436
  :index="-1"
437
+ :separator="separator"
348
438
  tableDataAlignment="left"
349
439
  :tableHeaderAutoWidth="false"
350
- :separator="separator"
351
440
  >
352
441
  <UCheckboxStd
353
- :id="`u-checkbox-${props.row._id}`"
354
442
  v-model="isRowSelected(props.row).value"
443
+ :id="`u-checkbox-${props.row._id}`"
355
444
  :name="props.row._id"
356
445
  />
357
446
  </UTd>
447
+
358
448
  <template v-for="(col, index) in props.cols" :key="index">
359
449
  <!-- to show the cell data without the action cell -->
360
450
  <UTd
361
- v-if="col.field !== 'action'"
362
- :row="props.row"
451
+ v-if="
452
+ col.field !== 'action' &&
453
+ (typeof col.show === 'undefined' || col.show)
454
+ "
455
+ :class="col.classes"
363
456
  :col="col"
364
457
  :index="index"
365
- :tableDataAlignment="col.align"
366
- :tableDataAutoWidth="col.autoWidth"
458
+ :row="props.row"
367
459
  :separator="separator"
368
460
  :style="col.style"
369
- :class="col.classes"
461
+ :tableDataAlignment="col.align"
462
+ :tableDataAutoWidth="col.autoWidth"
370
463
  >
371
464
  <!-- to show the chips with different variant -->
372
465
  <template v-if="col.chipValues && col.chipValues.length > 0">
373
466
  <UChip
374
467
  v-model="tableDataChip"
375
- :type="getChipColor(col.chipValues, props.row[col.field])"
468
+ class="u-table-chip"
469
+ :anchor="col.anchor"
376
470
  avatarLabel=""
377
471
  :chipLabel="props.row[col.field].toString()"
472
+ :dense="col.denseChip"
473
+ :is-show-tooltip="col.showChipTooltip"
474
+ :offset="col.offset"
378
475
  :removable="false"
379
- class="u-table-chip"
476
+ :type="getChipColor(col.chipValues, props.row[col.field])"
380
477
  />
381
478
  </template>
382
479
  <!-- to show the avatar of user image with name and other details -->
383
480
  <template v-else-if="col.avatarKey">
384
- <div class="flex justify-start items-center">
481
+ <div class="flex justify-start items-center no-wrap">
385
482
  <div
386
483
  v-if="
387
484
  props.row[col.avatarKey] &&
@@ -391,29 +488,31 @@ const onRowPerPageChange = (value) => {
391
488
  >
392
489
  <UAvatar
393
490
  v-if="props.row[col.avatarKey]?.type === 'initials'"
394
- size="md"
395
491
  :name="`${props.row[col.avatarKey]?.value}`"
492
+ size="md"
396
493
  />
397
494
  <UAvatar
398
495
  v-else-if="props.row[col.avatarKey]?.type === 'image'"
399
- size="md"
496
+ :image="`${props.row[col.avatarKey]?.value}`"
400
497
  :name="
401
498
  props.row[col.avatarKey]?.name ??
402
499
  props.row[col.avatarKey]?.value
403
500
  "
404
- :image="`${props.row[col.avatarKey]?.value}`"
501
+ size="md"
405
502
  />
406
503
  </div>
407
504
  <div v-else class="table-data-avatar">
408
505
  <UAvatar
409
- size="md"
410
- :name="`${props.row[col.avatarKey]}`"
411
506
  :image="`${props.row[col.avatarKey]}`"
507
+ :name="`${props.row[col.avatarKey]}`"
508
+ size="md"
412
509
  />
413
510
  </div>
414
511
  <div class="td-grid-content">
415
- <div>{{ props.row[col.field] }}</div>
416
- <div class="td-caption text-body-xs" v-if="col.captionKey">
512
+ <div>
513
+ {{ props.row[col.field] }}
514
+ </div>
515
+ <div v-if="col.captionKey" class="td-caption text-body-xs">
417
516
  {{ props.row[col.captionKey] }}
418
517
  </div>
419
518
  </div>
@@ -421,76 +520,290 @@ const onRowPerPageChange = (value) => {
421
520
  </template>
422
521
  <!-- to show other cell data -->
423
522
  <template v-else>
424
- <div>
425
- <div>{{ props.row[col.field] }}</div>
426
- <div class="td-caption text-body-xs" v-if="col.captionKey">
523
+ <div class="td-grid-content">
524
+ <div v-if="col.type !== 'icon'">
525
+ {{ props.row[col.field] }}
526
+ </div>
527
+ <div v-else-if="col.type === 'icon'">
528
+ <template v-if="props.row[col.field]">
529
+ <q-icon
530
+ :class="props.row[col.field]"
531
+ :alt="props.row.ariaLabel"
532
+ :aria-label="props.row.ariaLabel"
533
+ :color="props?.row?.iconColor ?? 'primary'"
534
+ size="1.5rem"
535
+ />
536
+ </template>
537
+ </div>
538
+ <div
539
+ v-if="col.captionKey && col.type !== 'icon'"
540
+ class="td-caption text-body-xs"
541
+ >
427
542
  {{ props.row[col.captionKey] }}
428
543
  </div>
429
544
  </div>
430
545
  </template>
431
546
  </UTd>
432
547
  <!-- to the action cell, it can have single and multiple -->
548
+
433
549
  <UTd
434
- v-else
550
+ v-else-if="typeof col.show === 'undefined' || col.show"
551
+ :class="col.classes"
435
552
  :index="index"
436
- :tableDataAlignment="col.align"
437
- :tableDataAutoWidth="false"
438
- style="width: 3%"
439
553
  :separator="separator"
440
554
  :style="col.style"
441
- :class="col.classes"
555
+ style="width: 3%"
556
+ :tableDataAlignment="col.align"
557
+ :tableDataAutoWidth="false"
558
+ @click="handleActionColClick"
442
559
  >
443
560
  <template v-if="col.actions && col.actions.length === 1">
444
- <UBtnStd
445
- v-for="(action, key) in col.actions"
446
- :key="key"
447
- :size="action.size"
448
- :flat="action.flat"
449
- :label="action.label"
450
- :color="action.color"
451
- :leftIcon="action.icon"
452
- @onClick="action.handler(props.row)"
453
- />
561
+ <template v-for="(action, key) in col.actions" :key="key">
562
+ <UBtnStd
563
+ v-if="
564
+ typeof action.hide === 'function'
565
+ ? !action.hide(props.row)
566
+ : true
567
+ "
568
+ :color="
569
+ typeof action.color === 'function'
570
+ ? action.color(props.row)
571
+ : action.color
572
+ "
573
+ :disable="
574
+ typeof action.disable === 'function' &&
575
+ action.disable(props.row)
576
+ "
577
+ :flat="
578
+ typeof action.flat === 'function'
579
+ ? action.flat(props.row)
580
+ : action.flat
581
+ "
582
+ :key="key"
583
+ :label="
584
+ typeof action.label === 'function'
585
+ ? action.label(props.row)
586
+ : action.label
587
+ "
588
+ :leftIcon="
589
+ typeof action.icon === 'function'
590
+ ? action.icon(props.row)
591
+ : action.icon
592
+ "
593
+ :loading="
594
+ typeof action.loading === 'function'
595
+ ? action.loading(props.row)
596
+ : action.loading
597
+ "
598
+ :outline="
599
+ typeof action.outline === 'function'
600
+ ? action.outline(props.row)
601
+ : action.outline
602
+ "
603
+ :size="action.size"
604
+ @on-click="action.handler(props.row)"
605
+ >
606
+ <template #tooltip>
607
+ <UTooltip
608
+ v-if="
609
+ typeof action.tooltip === 'function'
610
+ ? action.tooltip(props.row)
611
+ : action.tooltip
612
+ "
613
+ :anchor="action.anchor"
614
+ :description="
615
+ typeof action.tooltip === 'function'
616
+ ? action.tooltip(props.row)
617
+ : action.tooltip
618
+ "
619
+ :offset="action.offset ? action.offset : [10, 40]"
620
+ :self="action.self"
621
+ />
622
+ </template>
623
+ </UBtnStd>
624
+ </template>
454
625
  </template>
455
626
  <!-- to show the actions list if the actions are multiple -->
456
627
  <template v-else>
457
- <q-icon
458
- size="xs"
459
- class="fa-kit fa-ellipsis-vertical action-icon cursor-pointer"
460
- aria-label="more-action-icon"
461
- alt="action-icon-more"
462
- tabindex="0"
628
+ <q-menu
629
+ v-if="
630
+ moreActionDialogData &&
631
+ moreActionDialogData.showDialog[props.row.id]
632
+ "
633
+ v-model="moreActionDialogData.showDialog[props.row.id]"
634
+ :class="`more-action-popup q-px-ba q-py-ba`"
635
+ anchor="top left"
636
+ :cover="false"
637
+ :fit="true"
638
+ :id="`actionPopupRef-${props.row.id}`"
639
+ :offset="[85, 0]"
640
+ role="list"
641
+ self="bottom middle"
642
+ transition-hide="scale"
643
+ transition-show="scale"
644
+ @show="checkMenuPosition(props.row.id)"
463
645
  >
464
- <UTooltip description="More Actions" />
465
- <q-menu
466
- transition-show="slide-left"
467
- transition-hide="slide-right"
468
- anchor="center start"
469
- self="center left"
470
- >
471
- <div
472
- class="flex justify-end items-center more-action-wrapper"
473
- >
474
- <template v-for="(action, key) in col.actions" :key="key">
475
- <UTooltip
476
- :target="`#more-action-${key}`"
477
- :description="action.tooltip"
478
- />
479
- <q-icon
480
- :size="action.size"
481
- :id="`more-action-${key}`"
482
- :class="`more-action-icon ${
483
- action.icon
484
- } cursor-pointer ${key > 0 ? 'q-ml-sm' : ''}`"
485
- :aria-label="action.label"
486
- :alt="`${action.label}-key`"
487
- @click="action.handler(props.row)"
488
- tabindex="0"
489
- />
490
- </template>
491
- </div>
492
- </q-menu>
493
- </q-icon>
646
+ <div :class="tailClass"></div>
647
+ <q-card class="more-action-popup-wrapper">
648
+ <q-card-section>
649
+ <div class="content-wrapper text-center">
650
+ <div class="q-pb-ba flex justify-center items-center">
651
+ <div
652
+ :class="`remove-icon-wrapper ${
653
+ moreActionDialogData.row.iconColor === 'accent'
654
+ ? 'icon-bg-accent'
655
+ : 'icon-bg-primary'
656
+ }`"
657
+ >
658
+ <q-icon
659
+ :class="`${moreActionDialogData.row.icon} ${
660
+ moreActionDialogData.row.iconColor === 'accent'
661
+ ? 'icon-text-accent'
662
+ : 'icon-text-primary'
663
+ }`"
664
+ alt="confirmation icon"
665
+ aria-label="confirmation icon"
666
+ size="1.5rem"
667
+ />
668
+ </div>
669
+ </div>
670
+
671
+ <div
672
+ class="text-heading-xxs primary-content-text q-pb-xxs"
673
+ >
674
+ {{ moreActionDialogData.row.title }}
675
+ </div>
676
+ <div
677
+ v-if="moreActionDialogData.row.description"
678
+ class="text-body-sm secondary-content-text q-pb-xs"
679
+ >
680
+ {{ moreActionDialogData.row.description }}
681
+ </div>
682
+ </div>
683
+ <!-- <p class="hidden-scope-value">{{ scope.value }}</p> -->
684
+ </q-card-section>
685
+
686
+ <q-card-actions align="right">
687
+ <UBtnStd
688
+ v-if="moreActionDialogData.secondaryAction"
689
+ :color="moreActionDialogData.secondaryAction.color"
690
+ :disable="moreActionDialogData.secondaryAction.disable"
691
+ :flat="moreActionDialogData.secondaryAction.flat"
692
+ :label="moreActionDialogData.secondaryAction.label"
693
+ :loading="moreActionDialogData.secondaryAction.loading"
694
+ :outline="moreActionDialogData.secondaryAction.outline"
695
+ :size="moreActionDialogData.secondaryAction.size"
696
+ @on-click="
697
+ moreActionDialogData.secondaryAction.handler(props.row)
698
+ "
699
+ />
700
+ <UBtnStd
701
+ v-if="moreActionDialogData.primaryAction"
702
+ class="confirm-primary-action"
703
+ :color="moreActionDialogData.primaryAction.color"
704
+ :disable="moreActionDialogData.primaryAction.disable"
705
+ :flat="moreActionDialogData.primaryAction.flat"
706
+ :label="moreActionDialogData.primaryAction.label"
707
+ :loading="moreActionDialogData.primaryAction.loading"
708
+ :outline="moreActionDialogData.primaryAction.outline"
709
+ :size="moreActionDialogData.primaryAction.size"
710
+ @on-click="
711
+ moreActionDialogData.primaryAction.handler(props.row)
712
+ "
713
+ />
714
+ </q-card-actions>
715
+ </q-card>
716
+ </q-menu>
717
+
718
+ <UBtnIcon
719
+ :class="`action-icon cursor-pointer`"
720
+ iconClass="fa-kit fa-ellipsis-vertical"
721
+ ariaLabel="More action"
722
+ :id="`actionPopupRefBtn-${props.row.id}`"
723
+ :key="index"
724
+ ref="btn-icon"
725
+ @click.stop="handleMenuEventStop"
726
+ @on-click="onMoreActionButtonClick(props.row.id)"
727
+ >
728
+ <template #menu>
729
+ <q-menu v-if="!verticalMoreActions" auto-close role="list">
730
+ <div
731
+ :class="`${
732
+ verticalMoreActions ? 'vertical' : 'horizontal'
733
+ }-more-action-wrapper more-action-common`"
734
+ >
735
+ <template v-for="(action, key) in col.actions" :key="key">
736
+ <UBtnIcon
737
+ v-if="
738
+ typeof action.hide === 'function'
739
+ ? !action.hide(props.row)
740
+ : true && !verticalMoreActions
741
+ "
742
+ :class="`more-action-icon cursor-pointer table-more-action`"
743
+ :iconClass="
744
+ typeof action.icon === 'function'
745
+ ? action.icon(props.row)
746
+ : action.icon
747
+ "
748
+ :anchor="action.anchor"
749
+ :ariaLabel="
750
+ typeof action.label === 'function'
751
+ ? action.label(props.row)
752
+ : action.label
753
+ "
754
+ :disable="
755
+ typeof action.disable === 'function' &&
756
+ action.disable(props.row)
757
+ "
758
+ :id="`more-action-${key}`"
759
+ :offset="action.offset ? action.offset : [10, 40]"
760
+ ref="btn-icon"
761
+ :self="action.self"
762
+ :size="action.size"
763
+ :tooltip="
764
+ typeof action.tooltip === 'function'
765
+ ? action.tooltip(props.row)
766
+ : action.tooltip
767
+ "
768
+ @click.stop="handleMenuEventStop"
769
+ @on-click="action.handler(props.row)"
770
+ />
771
+ </template>
772
+ </div>
773
+ </q-menu>
774
+
775
+ <q-menu v-else auto-close role="list">
776
+ <UMenuDropdown
777
+ v-if="verticalMoreActions"
778
+ :data="
779
+ col.actions.map((action) => {
780
+ return {
781
+ destructive: action.destructive,
782
+ disable:
783
+ typeof action.disable === 'function' &&
784
+ action.disable(props.row),
785
+ hide: !(typeof action.hide === 'function'
786
+ ? !action.hide(props.row)
787
+ : true),
788
+ label:
789
+ typeof action.label === 'function'
790
+ ? action.label(props.row)
791
+ : action.label,
792
+ leftIcon:
793
+ typeof action.icon === 'function'
794
+ ? action.icon(props.row)
795
+ : action.icon,
796
+ positive: action.positive,
797
+ handler: function () {
798
+ return action.handler(props.row)
799
+ },
800
+ }
801
+ })
802
+ "
803
+ />
804
+ </q-menu>
805
+ </template>
806
+ </UBtnIcon>
494
807
  </template>
495
808
  </UTd>
496
809
  </template>
@@ -508,16 +821,30 @@ const onRowPerPageChange = (value) => {
508
821
  </template> -->
509
822
  </UTable>
510
823
  <!-- customized pagination with the vitual scroll functionality and rows per page selection -->
511
- <div class="row justify-end items-center pagination-wrapper">
824
+ <div
825
+ v-if="showPagination"
826
+ :class="`row justify-end items-center pagination-wrapper${
827
+ grid ? ' grid-row-pagination' : ''
828
+ }${isSmallDevices ? ' small-device-pagination' : ''}`"
829
+ dataTestId="table-pagination"
830
+ >
512
831
  <UPagination
513
- v-if="rows.length >= 6"
832
+ v-if="updatedRows.length >= 6"
514
833
  v-model="pagination.page"
515
- :rowPerPage="pagination.rowsPerPage"
834
+ :maxPageLink="
835
+ Number(
836
+ Math.ceil(updatedRows.length / pagination.rowsPerPage) > 10
837
+ ? grid
838
+ ? 3
839
+ : 6
840
+ : 3
841
+ )
842
+ "
843
+ :maxPages="Number(Math.ceil(updatedRows.length / pagination.rowsPerPage))"
516
844
  :perPageOptions="getRowsPerPageOptions"
845
+ :rowPerPage="pagination.rowsPerPage"
517
846
  @onPageChange="onPageChange"
518
847
  @onRowChange="onRowPerPageChange"
519
- :maxPageLink="Number(maxPageLink)"
520
- :maxPages="Number(Math.ceil(rows.length / pagination.rowsPerPage))"
521
848
  />
522
849
  </div>
523
850
  <q-inner-loading :showing="customLoading" class="custom-table-loader" />
@@ -525,9 +852,16 @@ const onRowPerPageChange = (value) => {
525
852
 
526
853
  <style lang="sass">
527
854
  .action-icon
528
- height: $md
529
- width: $md
530
- color: $neutral-9
855
+ &:hover
856
+ background: $blue-1
857
+
858
+ .q-icon
859
+ height: $md !important
860
+ width: $md !important
861
+ color: $neutral-9 !important
862
+ font-size: $ba !important
863
+ &:hover
864
+ color: $primary !important
531
865
 
532
866
  .table-data-avatar
533
867
  padding: $xs
@@ -535,8 +869,10 @@ const onRowPerPageChange = (value) => {
535
869
 
536
870
  .td-caption
537
871
  color: $description
872
+ width: 12.5rem
873
+ word-break: break-word
538
874
 
539
- .more-action-wrapper
875
+ .more-action-common
540
876
  min-width: 3.125rem
541
877
  padding: $xs
542
878
  min-height: $xl
@@ -545,13 +881,42 @@ const onRowPerPageChange = (value) => {
545
881
  background: $surface-bg-1
546
882
  box-shadow: 0px 0px 4px 0px rgba(16, 17, 20, 0.08)
547
883
 
548
- .more-action-icon
549
- color: $neutral-9
884
+ .vertical-more-action-wrapper
885
+ display: grid
886
+ place-items: flex-start
887
+ place-content: center
888
+ padding: $xxs
889
+ gap: $xxs
550
890
 
551
- .sorting-icon
552
- color: $description
553
- padding-left: $xs
554
- font-size: $ba !important
891
+ .horizontal-more-action-wrapper
892
+ display: flex
893
+ align-items: center
894
+ justify-content: start
895
+
896
+ .vertical-single-action
897
+ width: 100%
898
+ gap: $xs
899
+ padding: 0 $xs
900
+ height: $lg
901
+
902
+ .q-item__section--main
903
+ color: $neutral-9
904
+ white-space: nowrap
905
+
906
+ .q-item__section--avatar
907
+ min-width: 0px
908
+
909
+ .q-item__section--side
910
+ padding-right: 0
911
+
912
+ .q-icon
913
+ color: $neutral-9
914
+ font-size: $ba
915
+
916
+ .more-action-icon
917
+ .q-icon
918
+ color: $neutral-9 !important
919
+ font-size: $ba !important
555
920
 
556
921
  .selected-data-row
557
922
  background: #F7F7F7
@@ -573,9 +938,97 @@ const onRowPerPageChange = (value) => {
573
938
  .u-virtualscroll-table
574
939
  height: 50rem
575
940
 
941
+ .u-virtualscroll-grid-table.grid-card-mobile
942
+ .q-table__grid-content
943
+ .grid-style-transition
944
+ padding-left: 0px
945
+ padding-right: 0px
946
+
947
+ .u-virtualscroll-grid-table.grid-card-tablet
948
+ .q-table__grid-content
949
+ > :nth-child(odd)
950
+ padding-left: 0px
951
+ > :nth-child(even)
952
+ padding-right: 0px
953
+
576
954
  .u-virtualscroll-grid-table
577
- max-height: 50rem
578
- overflow: auto
955
+ // max-height: 50rem
956
+ // overflow: auto
957
+ .q-table__middle
958
+ display: none
959
+
960
+ .q-item.q-item-type .q-item__section--main
961
+ padding-bottom: $xxs !important
962
+
963
+ .q-list
964
+ display: grid
965
+ row-gap: $xs
966
+ column-gap: $xs
967
+ grid-template-columns: 1fr 1fr
968
+ padding-left: $ba
969
+ padding-right: $ba
970
+ height: 100%
971
+ min-height: 26.125rem
972
+
973
+ .q-item__label
974
+ color: $neutral-9
975
+ font-size: 0.875rem
976
+ font-weight: 500
977
+ line-height: 1.063rem !important
978
+ opacity: 1
979
+ word-break: break-word
980
+
981
+ .q-item__label.q-item__label--caption
982
+ color: $dark
983
+ font-size: $ba
984
+ font-weight: 400
985
+ line-height: 1.188rem !important
986
+ word-break: break-word
987
+
988
+ .q-table__grid-content
989
+ .q-table__grid-item
990
+ padding: $xs
991
+
992
+ .q-card
993
+ overflow: auto
994
+ padding-top: 0px !important
995
+ border-radius: $xs
996
+ border: 1px solid $neutral-4
997
+ box-shadow: none
998
+
999
+ .mobile-centered-col
1000
+ grid-column: span 2
1001
+
1002
+ .q-item.q-item-type
1003
+ margin-top: 0px !important
1004
+ align-self: start
1005
+ height: auto
1006
+ display: grid !important
1007
+ padding: 0px !important
1008
+ .q-item__section--side
1009
+ align-items: flex-start
1010
+ padding-left: 0px
1011
+
1012
+ .q-item.q-item-type:last-child
1013
+ grid-column: span 2
1014
+ padding-top: $ba !important
1015
+ margin-bottom: $ba !important
1016
+
1017
+ .column.q-item__section--main
1018
+ display: none
1019
+
1020
+ .q-item.q-item-type:first-child
1021
+ grid-column: span 2
1022
+ padding-top: $sm !important
1023
+ padding-bottom: $sm !important
1024
+ .q-item__section--main
1025
+ display: none
1026
+ .q-item__label.q-item__label--caption span
1027
+ color: $dark
1028
+ font-size: 1rem
1029
+ font-weight: 500
1030
+ line-height: 1.063rem
1031
+ width: 100%
579
1032
 
580
1033
  .u-sticky-table-header
581
1034
  .q-table__top,
@@ -591,10 +1044,10 @@ const onRowPerPageChange = (value) => {
591
1044
  top: 0
592
1045
 
593
1046
  &.q-table--loading thead tr:last-child th
594
- top: 48px
1047
+ top: 3rem
595
1048
 
596
1049
  tbody
597
- scroll-margin-top: 48px
1050
+ scroll-margin-top: 3rem
598
1051
 
599
1052
  .u-sorting-btn
600
1053
  padding: 0
@@ -621,4 +1074,151 @@ const onRowPerPageChange = (value) => {
621
1074
  .custom-table-loader
622
1075
  .q-spinner
623
1076
  color: $primary
1077
+
1078
+ .td-grid-content
1079
+ text-wrap: balance
1080
+ word-break: break-all
1081
+
1082
+ .hidden-header-label
1083
+ visibility: hidden
1084
+
1085
+ .confirmation-dialog-wrapper
1086
+ border-radius: $border-radius-sm !important
1087
+ background: $neutral-1
1088
+ box-shadow: 0rem 0rem 0.75rem 0rem rgba(16, 17, 20, 0.16) !important
1089
+
1090
+ .confirmation-dialog-wrapper.mobile-confirmation-dialog
1091
+ max-width: 100% !important
1092
+ padding: 0px !important
1093
+
1094
+ .more-action-popup
1095
+ border-radius: $border-radius-sm
1096
+ background: $neutral-1
1097
+ box-shadow: 0rem 0rem 0.75rem 0rem rgba(16, 17, 20, 0.16)
1098
+ max-width: 18.375rem !important
1099
+ width: 100%
1100
+ position: relative
1101
+ overflow: visible
1102
+
1103
+ .more-action-popup-wrapper
1104
+ box-shadow: none !important
1105
+ max-width: 18.375rem !important
1106
+ width: 100%
1107
+ .hidden-scope-value
1108
+ display: none
1109
+ .q-card__section
1110
+ padding: 0
1111
+ .q-card__actions
1112
+ flex-wrap: nowrap
1113
+ padding: $ba 0 0 0
1114
+ .q-btn
1115
+ width: 50%
1116
+
1117
+ .content-wrapper
1118
+ display: grid
1119
+ place-content: center
1120
+ place-items: center
1121
+
1122
+ .secondary-content-text
1123
+ color: $description
1124
+
1125
+ .primary-content-text
1126
+ color: $dark
1127
+
1128
+ .remove-icon-wrapper
1129
+ border-radius: 7.75rem
1130
+ padding: $sm
1131
+ width: 3.125rem
1132
+ height: 3.125rem
1133
+ .q-icon
1134
+ color: $accent
1135
+
1136
+ .confirm-primary-action
1137
+ margin-left: $ba !important
1138
+
1139
+ .icon-bg-accent
1140
+ background-color: $red-1
1141
+
1142
+ .icon-bg-primary
1143
+ background-color: $blue-1
1144
+
1145
+ .icon-text-accent
1146
+ color: $accent
1147
+
1148
+ .icon-text-primary
1149
+ color: $primary !important
1150
+
1151
+ .tail-top
1152
+ width: 1.25rem
1153
+ height: 1.25rem
1154
+ transform: rotate(45deg)
1155
+ position: absolute
1156
+ right: 1.304rem
1157
+ top: -0.604rem
1158
+ border-top-left-radius: $border-radius-xs
1159
+ background: $neutral-1
1160
+ box-shadow: -3px -2px 5px -3px rgba(0, 0, 0, 0.2)
1161
+
1162
+ .tail-bottom
1163
+ width: 1.25rem
1164
+ height: 1.25rem
1165
+ transform: rotate(45deg)
1166
+ position: absolute
1167
+ right: 1.304rem
1168
+ bottom: -0.604rem
1169
+ border-bottom-right-radius: $border-radius-xs
1170
+ background: $neutral-1
1171
+ box-shadow: 3px 4px 5px -3px rgba(0, 0, 0, 0.2)
1172
+
1173
+ .mobile-tail-top
1174
+ right: 1.304rem !important
1175
+
1176
+ .mobile-tail-bottom
1177
+ right: 1.304rem !important
1178
+
1179
+ .grid-row-pagination
1180
+ .u-pagination-container
1181
+ flex-wrap: nowrap
1182
+ .q-pagination__middle
1183
+ flex-wrap: nowrap
1184
+
1185
+ .small-device-pagination
1186
+ .u-pagination-container
1187
+ flex-wrap: wrap
1188
+ gap: $xs
1189
+ justify-content: flex-end
1190
+
1191
+ .mobile-grid-more-action
1192
+ padding: 0px !important
1193
+ .q-item
1194
+ border-radius: $xs
1195
+
1196
+ .grid-more-action
1197
+ padding: $ba
1198
+ .q-item__section--avatar
1199
+ min-width: 0
1200
+ .q-item
1201
+ border-radius: $xs
1202
+
1203
+ .long-text-content
1204
+ display: block
1205
+ white-space: nowrap
1206
+ width: 5.5rem
1207
+ overflow: hidden
1208
+ text-overflow: ellipsis
1209
+
1210
+ .no-ellipsis-content
1211
+ white-space: normal !important
1212
+
1213
+ .full-width-text-content
1214
+ width: 19.5rem !important
1215
+
1216
+ .tablet-event-text
1217
+ width: 10.5rem
1218
+
1219
+ .mobile-primary-caption
1220
+ width: 11.5rem !important
1221
+ white-space: nowrap
1222
+ overflow: hidden
1223
+ text-overflow: ellipsis
624
1224
  </style>