@usssa/component-library 1.0.0-alpha.174 → 1.0.0-alpha.175

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/README.md CHANGED
@@ -1,6 +1,6 @@
1
- # Component Library v1.0.0-alpha.174
1
+ # Component Library v1.0.0-alpha.175
2
2
 
3
- **This library provides custom UI components for USSSA applications.**
3
+ **This library provides custom UI components for USSSA applications**
4
4
 
5
5
  ## Installation
6
6
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@usssa/component-library",
3
- "version": "1.0.0-alpha.174",
3
+ "version": "1.0.0-alpha.175",
4
4
  "description": "A Quasar component library project",
5
5
  "productName": "Quasar component library App",
6
6
  "author": "Engineering Team <engineering@usssa.com>",
@@ -0,0 +1,222 @@
1
+ <script setup>
2
+ import { ref } from 'vue'
3
+
4
+ const props = defineProps({
5
+ caption: {
6
+ type: String,
7
+ default: '',
8
+ },
9
+ collapsedAriaLabel: {
10
+ type: String,
11
+ default: 'Collapsed',
12
+ },
13
+ dataTestId: {
14
+ type: String,
15
+ default: 'expansion-std',
16
+ },
17
+ disabled: {
18
+ type: Boolean,
19
+ default: false,
20
+ },
21
+ enableIconToggle: {
22
+ type: Boolean,
23
+ default: false,
24
+ },
25
+ expandAriaLabel: {
26
+ type: String,
27
+ default: 'Expand',
28
+ },
29
+ expansionIcon: {
30
+ type: String,
31
+ default: 'fa-kit fa-caret-down',
32
+ },
33
+ expansionIconColor: {
34
+ type: String,
35
+ default: 'description',
36
+ },
37
+ expansionIconSize: {
38
+ type: String,
39
+ default: '1rem', // accept px , rem and (xs|sm|md|lg|xl)
40
+ },
41
+ label: {
42
+ type: String,
43
+ default: '',
44
+ },
45
+ rowCardHeight: {
46
+ type: Number,
47
+ default: 20.563,
48
+ },
49
+ toggleIconLeft: {
50
+ type: Boolean,
51
+ default: false,
52
+ },
53
+ })
54
+
55
+ const isExpanded = ref(false)
56
+
57
+ const onIconKeydown = (event) => {
58
+ if (props.disabled) return
59
+ if (event.key === 'Enter' || event.key === ' ') {
60
+ event.preventDefault()
61
+ toggleExpansion()
62
+ }
63
+ }
64
+
65
+ const toggleExpansion = () => {
66
+ if (!props.disabled) {
67
+ isExpanded.value = !isExpanded.value
68
+ }
69
+ }
70
+ </script>
71
+
72
+ <template>
73
+ <!-- For expand on expansion icon -->
74
+ <q-expansion-item
75
+ v-bind="$attrs"
76
+ v-if="enableIconToggle"
77
+ v-model="isExpanded"
78
+ class="u-expansion"
79
+ :dataTestId="dataTestId"
80
+ :disable="disabled"
81
+ expand-icon-class="hidden"
82
+ expand-icon-toggle
83
+ :style="{
84
+ 'min-height': `${isExpanded ? rowCardHeight + 'rem' : 'auto'}`,
85
+ overflowX: 'hidden',
86
+ }"
87
+ >
88
+ <template v-slot:header>
89
+ <div class="u-expansion-header">
90
+ <q-icon
91
+ v-if="toggleIconLeft"
92
+ :class="[
93
+ 'cursor-pointer',
94
+ 'icon-secondary-opacity',
95
+ 'transition-all',
96
+ expansionIcon,
97
+ { 'rotate-180': isExpanded },
98
+ ]"
99
+ :aria-label="isExpanded ? collapsedAriaLabel : expandAriaLabel"
100
+ :color="expansionIconColor"
101
+ :size="expansionIconSize"
102
+ :tabindex="disabled ? -1 : 0"
103
+ @click.stop="toggleExpansion"
104
+ @keydown.stop="onIconKeydown"
105
+ >
106
+ </q-icon>
107
+ <slot name="avatar" />
108
+ <div class="column u-expansion-label">
109
+ <span class="text-caption-lg">{{ label }}</span>
110
+ <span class="text-body-xs">{{ caption }}</span>
111
+ </div>
112
+ <q-icon
113
+ v-if="!toggleIconLeft"
114
+ :class="[
115
+ 'cursor-pointer',
116
+ 'icon-secondary-opacity',
117
+ 'transition-all',
118
+ expansionIcon,
119
+ { 'rotate-180': isExpanded },
120
+ ]"
121
+ :aria-label="isExpanded ? collapsedAriaLabel : expandAriaLabel"
122
+ :color="expansionIconColor"
123
+ :size="expansionIconSize"
124
+ :tabindex="disabled ? -1 : 0"
125
+ @click.stop="toggleExpansion"
126
+ @keydown.stop="onIconKeydown"
127
+ >
128
+ </q-icon>
129
+ </div>
130
+ </template>
131
+ <slot name="body" />
132
+ <slot name="footer" />
133
+ </q-expansion-item>
134
+
135
+ <!-- For default expansion behaviour -->
136
+ <q-expansion-item
137
+ v-bind="$attrs"
138
+ v-else
139
+ v-model="isExpanded"
140
+ class="u-expansion"
141
+ :dataTestId="dataTestId"
142
+ :disable="disabled"
143
+ expand-icon-class="hidden"
144
+ :style="{
145
+ 'min-height': `${isExpanded ? rowCardHeight + 'rem' : 'auto'}`,
146
+ overflowX: 'hidden',
147
+ }"
148
+ :toggle-aria-label="isExpanded ? collapsedAriaLabel : expandAriaLabel"
149
+ @keydown.space.prevent
150
+ >
151
+ <template v-slot:header>
152
+ <div class="u-expansion-header">
153
+ <q-icon
154
+ v-if="toggleIconLeft"
155
+ :class="[
156
+ 'cursor-pointer',
157
+ 'icon-secondary-opacity',
158
+ 'transition-all',
159
+ expansionIcon,
160
+ { 'rotate-180': isExpanded },
161
+ ]"
162
+ :color="expansionIconColor"
163
+ :size="expansionIconSize"
164
+ >
165
+ </q-icon>
166
+ <slot name="avatar" />
167
+ <div class="column u-expansion-label">
168
+ <span class="text-caption-lg">{{ label }}</span>
169
+ <span class="text-body-xs">{{ caption }}</span>
170
+ </div>
171
+ <q-icon
172
+ v-if="!toggleIconLeft"
173
+ :class="[
174
+ 'cursor-pointer',
175
+ 'icon-secondary-opacity',
176
+ 'transition-all',
177
+ expansionIcon,
178
+ { 'rotate-180': isExpanded },
179
+ ]"
180
+ :color="expansionIconColor"
181
+ :size="expansionIconSize"
182
+ >
183
+ </q-icon>
184
+ </div>
185
+ </template>
186
+ <slot name="body" />
187
+ <slot name="footer" />
188
+ </q-expansion-item>
189
+ </template>
190
+
191
+ <style lang="sass">
192
+ .u-expansion
193
+ border-radius: $border-radius-sm
194
+ border: 1px solid $neutral-4
195
+ overflow: hidden
196
+ width: 100%
197
+
198
+ .q-item
199
+ padding: $ba !important
200
+
201
+ .u-expansion-header
202
+ width: 100%
203
+ display: flex
204
+ align-items: center
205
+ gap: $xs
206
+
207
+ .u-expansion-label
208
+ flex: 1 1 0
209
+ min-width: 0
210
+ word-break: break-word
211
+ overflow-wrap: break-word
212
+
213
+ .q-expansion-item__content > :first-child
214
+ padding: 0px $ba $ba $ba
215
+
216
+ .q-expansion-item__content > :nth-child(2)
217
+ padding: $ba
218
+
219
+ .rotate-180
220
+ transform: rotate(180deg)
221
+ transition: 0.3s
222
+ </style>
@@ -5,6 +5,7 @@ import { useScreenType } from '../../../composables/useScreenType'
5
5
  import UAvatar from '../UAvatar.vue'
6
6
  import UBtnStd from '../UBtnStd.vue'
7
7
  import UChip from '../UChip.vue'
8
+ import UExpansionStd from '../UExpansionStd.vue'
8
9
  import USheet from '../USheet.vue'
9
10
  import UTooltip from '../UTooltip.vue'
10
11
 
@@ -32,7 +33,6 @@ const rows = defineModel('rows', {
32
33
  default: () => [],
33
34
  type: Array,
34
35
  })
35
-
36
36
  const props = defineProps({
37
37
  bordered: {
38
38
  type: Boolean,
@@ -40,7 +40,15 @@ const props = defineProps({
40
40
  },
41
41
  closeIconLabel: {
42
42
  type: String,
43
- default: 'Close Icon'
43
+ default: 'Close Icon',
44
+ },
45
+ enableIconToggle:{
46
+ type: Boolean,
47
+ default: false
48
+ },
49
+ expansion: {
50
+ type: Boolean,
51
+ default: false,
44
52
  },
45
53
  filter: {
46
54
  type: String,
@@ -64,7 +72,7 @@ const props = defineProps({
64
72
  },
65
73
  selectMoreOptions: {
66
74
  type: String,
67
- default: 'Select More Options'
75
+ default: 'Select More Options',
68
76
  },
69
77
  separator: {
70
78
  type: String,
@@ -84,7 +92,7 @@ const props = defineProps({
84
92
  },
85
93
  viewMoreLabel: {
86
94
  type: String,
87
- default: 'View More'
95
+ default: 'View More',
88
96
  },
89
97
  virtualScroll: {
90
98
  type: Boolean,
@@ -165,6 +173,27 @@ const getChipColor = (data, value) => {
165
173
  }
166
174
  }
167
175
 
176
+ // Helper to get the caption for the expansion item (from captionKey if present)
177
+ function getExpansionCaption(row, cols) {
178
+ const col = cols.find(
179
+ (c) => c.captionKey && (typeof c.show === 'undefined' || c.show)
180
+ )
181
+ if (col && row[col.captionKey]) {
182
+ return col.captionKeyTitle
183
+ ? `${col.captionKeyTitle}: ${row[col.captionKey]}`
184
+ : row[col.captionKey]
185
+ }
186
+ return ''
187
+ }
188
+
189
+ // Helper to get the label for the expansion item
190
+ function getExpansionLabel(row, cols) {
191
+ const col = cols.find(
192
+ (c) => (typeof c.show === 'undefined' || c.show) && c.field !== 'action'
193
+ )
194
+ return col ? row[col.field] : row[props.rowKey] || 'Details'
195
+ }
196
+
168
197
  const handleItemClick = (action, row) => {
169
198
  moreActionsDialogs.value[row.id][0].open = false
170
199
  setTimeout(() => {
@@ -256,6 +285,7 @@ watch(
256
285
  </template>
257
286
  <template v-slot:item="props">
258
287
  <div
288
+ v-if="expansion == false"
259
289
  class="q-pa-xs col-xs-12 col-sm-6 col-md-4 col-lg-3 grid-style-transition"
260
290
  :style="props.selected ? 'transform: scale(0.95);' : ''"
261
291
  >
@@ -930,6 +960,667 @@ watch(
930
960
  </q-list>
931
961
  </q-card>
932
962
  </div>
963
+ <UExpansionStd
964
+ v-else
965
+ class="q-mb-sm u-expansion-table"
966
+ :caption="getExpansionCaption(props.row, props.cols)"
967
+ :enableIconToggle="enableIconToggle"
968
+ :label="getExpansionLabel(props.row, props.cols)"
969
+ :props="props"
970
+ :rowCardHeight="rowCardHeight"
971
+ >
972
+ <template #avatar>
973
+ <template v-if="props.cols">
974
+ <template v-for="(col, _colInd) in props.cols" :key="_colInd">
975
+ <template v-if="col.avatarKey && col.isPrimary">
976
+ <div
977
+ v-if="
978
+ props.row[col.avatarKey] &&
979
+ typeof props.row[col.avatarKey] === 'object'
980
+ "
981
+ class="table-data-avatar"
982
+ >
983
+ <UAvatar
984
+ v-if="props.row[col.avatarKey]?.type === 'initials'"
985
+ :indicatorColor="
986
+ typeof col.indicatorColor === 'function' &&
987
+ col.indicatorColor(props.row)
988
+ ? col.indicatorColor(props.row)
989
+ : ''
990
+ "
991
+ :indicatorIcon="
992
+ typeof col.indicatorIcon === 'function' &&
993
+ col.indicatorIcon(props.row)
994
+ ? col.indicatorIcon(props.row)
995
+ : ''
996
+ "
997
+ :name="`${props.row[col.avatarKey]?.value}`"
998
+ :showIndicator="col.showIndicator"
999
+ size="lg"
1000
+ />
1001
+ <UAvatar
1002
+ v-else-if="props.row[col.avatarKey]?.type === 'image'"
1003
+ :image="`${props.row[col.avatarKey]?.value}`"
1004
+ :indicatorColor="
1005
+ typeof col.indicatorColor === 'function' &&
1006
+ col.indicatorColor(props.row)
1007
+ ? col.indicatorColor(props.row)
1008
+ : ''
1009
+ "
1010
+ :indicatorIcon="
1011
+ typeof col.indicatorIcon === 'function' &&
1012
+ col.indicatorIcon(props.row)
1013
+ ? col.indicatorIcon(props.row)
1014
+ : ''
1015
+ "
1016
+ :name="
1017
+ props.row[col.avatarKey]?.name ??
1018
+ props.row[col.avatarKey]?.value
1019
+ "
1020
+ :showIndicator="col.showIndicator"
1021
+ size="lg"
1022
+ />
1023
+ </div>
1024
+ <div v-else class="table-data-avatar">
1025
+ <UAvatar
1026
+ :image="`${props.row[col.avatarKey]}`"
1027
+ :indicatorColor="
1028
+ typeof col.indicatorColor === 'function' &&
1029
+ col.indicatorColor(props.row)
1030
+ ? col.indicatorColor(props.row)
1031
+ : ''
1032
+ "
1033
+ :indicatorIcon="
1034
+ typeof col.indicatorIcon === 'function' &&
1035
+ col.indicatorIcon(props.row)
1036
+ ? col.indicatorIcon(props.row)
1037
+ : ''
1038
+ "
1039
+ :name="`${props.row[col.avatarKey]}`"
1040
+ :showIndicator="col.showIndicator"
1041
+ size="lg"
1042
+ />
1043
+ </div>
1044
+ </template>
1045
+ </template>
1046
+ </template>
1047
+ </template>
1048
+
1049
+ <template #body>
1050
+ <div class="u-expansion-body">
1051
+ <template v-for="(col, _indB) in props.cols" :key="_indB">
1052
+ <!-- Skip the primary column -->
1053
+ <template
1054
+ v-if="
1055
+ !col.isPrimary &&
1056
+ (typeof col.show === 'undefined' || col.show) &&
1057
+ col.field !== 'action'
1058
+ "
1059
+ >
1060
+ <div class="col-12 col-sm-6">
1061
+ <!-- Label -->
1062
+ <div class="text-caption text-description">
1063
+ {{ col.label }}
1064
+ </div>
1065
+ <!-- Content -->
1066
+ <div class="flex items-center">
1067
+ <!-- Avatar (if present) -->
1068
+ <template v-if="col.avatarKey">
1069
+ <div
1070
+ v-if="
1071
+ props.row[col.avatarKey] &&
1072
+ typeof props.row[col.avatarKey] === 'object'
1073
+ "
1074
+ class="table-data-avatar"
1075
+ >
1076
+ <UAvatar
1077
+ v-if="props.row[col.avatarKey]?.type === 'initials'"
1078
+ :indicatorColor="
1079
+ typeof col.indicatorColor === 'function' &&
1080
+ col.indicatorColor(props.row)
1081
+ ? col.indicatorColor(props.row)
1082
+ : ''
1083
+ "
1084
+ :indicatorIcon="
1085
+ typeof col.indicatorIcon === 'function' &&
1086
+ col.indicatorIcon(props.row)
1087
+ ? col.indicatorIcon(props.row)
1088
+ : ''
1089
+ "
1090
+ :name="`${props.row[col.avatarKey]?.value}`"
1091
+ :showIndicator="col.showIndicator"
1092
+ size="lg"
1093
+ />
1094
+ <UAvatar
1095
+ v-else-if="props.row[col.avatarKey]?.type === 'image'"
1096
+ :image="`${props.row[col.avatarKey]?.value}`"
1097
+ :indicatorColor="
1098
+ typeof col.indicatorColor === 'function' &&
1099
+ col.indicatorColor(props.row)
1100
+ ? col.indicatorColor(props.row)
1101
+ : ''
1102
+ "
1103
+ :indicatorIcon="
1104
+ typeof col.indicatorIcon === 'function' &&
1105
+ col.indicatorIcon(props.row)
1106
+ ? col.indicatorIcon(props.row)
1107
+ : ''
1108
+ "
1109
+ :name="
1110
+ props.row[col.avatarKey]?.name ??
1111
+ props.row[col.avatarKey]?.value
1112
+ "
1113
+ :showIndicator="col.showIndicator"
1114
+ size="lg"
1115
+ />
1116
+ </div>
1117
+ <div v-else class="table-data-avatar">
1118
+ <UAvatar
1119
+ :image="`${props.row[col.avatarKey]}`"
1120
+ :indicatorColor="
1121
+ typeof col.indicatorColor === 'function' &&
1122
+ col.indicatorColor(props.row)
1123
+ ? col.indicatorColor(props.row)
1124
+ : ''
1125
+ "
1126
+ :indicatorIcon="
1127
+ typeof col.indicatorIcon === 'function' &&
1128
+ col.indicatorIcon(props.row)
1129
+ ? col.indicatorIcon(props.row)
1130
+ : ''
1131
+ "
1132
+ :name="`${props.row[col.avatarKey]}`"
1133
+ :showIndicator="col.showIndicator"
1134
+ size="lg"
1135
+ />
1136
+ </div>
1137
+ </template>
1138
+ <!-- Chip -->
1139
+ <UChip
1140
+ v-else-if="col.chipValues && col.chipValues.length > 0"
1141
+ v-model="tableDataChip"
1142
+ class="u-table-chip"
1143
+ :anchor="col.anchor"
1144
+ avatarLabel=""
1145
+ :chipLabel="props.row[col.field]?.toString()"
1146
+ :dense="isMobile || isTablet ? true : col.denseChip"
1147
+ :is-show-tooltip="col.showChipTooltip"
1148
+ :offset="col.offset"
1149
+ :removable="false"
1150
+ :type="getChipColor(col.chipValues, props.row[col.field])"
1151
+ />
1152
+ <!-- Icon -->
1153
+ <q-icon
1154
+ v-else-if="col.type === 'icon' && props.row[col.field]"
1155
+ :class="props.row[col.field]"
1156
+ :alt="props.row.ariaLabel"
1157
+ :aria-label="props.row.ariaLabel"
1158
+ :color="props?.row?.iconColor ?? 'primary'"
1159
+ size="1.5rem"
1160
+ />
1161
+ <!-- Text -->
1162
+ <span v-else class="text-body-sm">
1163
+ {{ props.row[col.field] }}
1164
+ </span>
1165
+ </div>
1166
+ <!-- Caption (if any) -->
1167
+ <div
1168
+ v-if="col.captionKey"
1169
+ class="td-caption mobile-primary-caption text-body-sm"
1170
+ >
1171
+ <template v-if="col.captionKeyTitle">
1172
+ {{ col.captionKeyTitle }}:
1173
+ </template>
1174
+ {{ props.row[col.captionKey] }}
1175
+ </div>
1176
+ </div>
1177
+ </template>
1178
+ </template>
1179
+ </div>
1180
+ <!-- Actions Footer -->
1181
+ </template>
1182
+ <template #footer>
1183
+ <div class="row">
1184
+ <template v-for="(col, _indF) in props.cols" :key="_indF">
1185
+ <template v-if="col.actions && col.actions.length">
1186
+ <!-- Single Action -->
1187
+ <template v-if="col.actions.length === 1">
1188
+ <template v-for="(action, key) in col.actions" :key="key">
1189
+ <UBtnStd
1190
+ v-if="
1191
+ typeof action.hide === 'function'
1192
+ ? !action.hide(props.row)
1193
+ : true
1194
+ "
1195
+ class="full-width"
1196
+ :color="
1197
+ typeof action.color === 'function'
1198
+ ? action.color(props.row)
1199
+ : action.color
1200
+ "
1201
+ :disable="
1202
+ typeof action.disable === 'function' &&
1203
+ action.disable(props.row)
1204
+ "
1205
+ :flat="
1206
+ typeof action.flat === 'function'
1207
+ ? action.flat(props.row)
1208
+ : action.flat
1209
+ "
1210
+ :label="
1211
+ typeof action.label === 'function'
1212
+ ? action.label(props.row)
1213
+ : action.label
1214
+ "
1215
+ :leftIcon="
1216
+ typeof action.icon === 'function'
1217
+ ? action.icon(props.row)
1218
+ : action.icon
1219
+ "
1220
+ :loading="
1221
+ typeof action.loading === 'function'
1222
+ ? action.loading(props.row)
1223
+ : action.loading
1224
+ "
1225
+ :outline="
1226
+ typeof action.outline === 'function'
1227
+ ? action.outline(props.row)
1228
+ : action.outline
1229
+ "
1230
+ :size="action.size"
1231
+ @on-click="action.handler(props.row)"
1232
+ >
1233
+ <template #tooltip>
1234
+ <UTooltip
1235
+ v-if="
1236
+ typeof action.tooltip === 'function'
1237
+ ? action.tooltip(props.row)
1238
+ : action.tooltip
1239
+ "
1240
+ :anchor="action.anchor"
1241
+ :description="
1242
+ typeof action.tooltip === 'function'
1243
+ ? action.tooltip(props.row)
1244
+ : action.tooltip
1245
+ "
1246
+ :offset="action.offset ? action.offset : [10, 40]"
1247
+ :self="action.anchor"
1248
+ />
1249
+ </template>
1250
+ </UBtnStd>
1251
+ </template>
1252
+ </template>
1253
+ <!-- Multiple Actions -->
1254
+ <template v-else-if="col.actions.length > 1">
1255
+ <q-dialog
1256
+ v-if="
1257
+ isTablet &&
1258
+ moreActionDialogData &&
1259
+ moreActionDialogData.showDialog[props.row.id]
1260
+ "
1261
+ v-model="moreActionDialogData.showDialog[props.row.id]"
1262
+ class="more-action-popup"
1263
+ persistent
1264
+ >
1265
+ <q-card
1266
+ class="more-action-popup-wrapper confirmation-dialog-wrapper q-px-ba q-py-ba"
1267
+ >
1268
+ <q-card-section>
1269
+ <div class="content-wrapper text-center">
1270
+ <div class="q-pb-ba flex justify-center items-center">
1271
+ <div
1272
+ :class="`remove-icon-wrapper ${
1273
+ moreActionDialogData.row.iconColor === 'accent'
1274
+ ? 'icon-bg-accent'
1275
+ : 'icon-bg-primary'
1276
+ }`"
1277
+ >
1278
+ <q-icon
1279
+ :class="`${moreActionDialogData.row.icon} ${
1280
+ moreActionDialogData.row.iconColor ===
1281
+ 'accent'
1282
+ ? 'icon-text-accent'
1283
+ : 'icon-text-primary'
1284
+ }`"
1285
+ alt="confirmation icon"
1286
+ aria-label="confirmation icon"
1287
+ size="1.5rem"
1288
+ />
1289
+ </div>
1290
+ </div>
1291
+
1292
+ <div
1293
+ class="text-heading-xxs primary-content-text q-pb-xxs"
1294
+ >
1295
+ {{ moreActionDialogData.row.title }}
1296
+ </div>
1297
+ <div
1298
+ v-if="moreActionDialogData.row.description"
1299
+ class="text-body-sm secondary-content-text q-pb-xs"
1300
+ >
1301
+ {{ moreActionDialogData.row.description }}
1302
+ </div>
1303
+ </div>
1304
+ <!-- <p class="hidden-scope-value">{{ scope.value }}</p> -->
1305
+ </q-card-section>
1306
+
1307
+ <q-card-actions align="right">
1308
+ <UBtnStd
1309
+ v-if="moreActionDialogData.secondaryAction"
1310
+ :color="moreActionDialogData.secondaryAction.color"
1311
+ :disable="
1312
+ moreActionDialogData.secondaryAction.disable
1313
+ "
1314
+ :flat="moreActionDialogData.secondaryAction.flat"
1315
+ :label="moreActionDialogData.secondaryAction.label"
1316
+ :loading="
1317
+ moreActionDialogData.secondaryAction.loading
1318
+ "
1319
+ :outline="
1320
+ moreActionDialogData.secondaryAction.outline
1321
+ "
1322
+ :size="moreActionDialogData.secondaryAction.size"
1323
+ @on-click="
1324
+ moreActionDialogData.secondaryAction.handler(
1325
+ props.row
1326
+ )
1327
+ "
1328
+ />
1329
+ <UBtnStd
1330
+ v-if="moreActionDialogData.primaryAction"
1331
+ class="confirm-primary-action"
1332
+ :color="moreActionDialogData.primaryAction.color"
1333
+ :disable="moreActionDialogData.primaryAction.disable"
1334
+ :flat="moreActionDialogData.primaryAction.flat"
1335
+ :label="moreActionDialogData.primaryAction.label"
1336
+ :loading="moreActionDialogData.primaryAction.loading"
1337
+ :outline="moreActionDialogData.primaryAction.outline"
1338
+ :size="moreActionDialogData.primaryAction.size"
1339
+ @on-click="
1340
+ moreActionDialogData.primaryAction.handler(
1341
+ props.row
1342
+ )
1343
+ "
1344
+ />
1345
+ </q-card-actions>
1346
+ </q-card>
1347
+ </q-dialog>
1348
+
1349
+ <UBtnStd
1350
+ v-if="!isMobile"
1351
+ class="full-width"
1352
+ color="primary"
1353
+ full-width
1354
+ :id="`actionPopupRefBtn-${props.row.id}`"
1355
+ :label="viewMoreLabel"
1356
+ outline
1357
+ >
1358
+ <template #menu>
1359
+ <q-menu
1360
+ class="more-action-popup"
1361
+ auto-close
1362
+ fit
1363
+ :id="`actionPopupRef-${props.row.id}`"
1364
+ :offset="[10, 20]"
1365
+ transition-hide="jump-up"
1366
+ transition-show="jump-down"
1367
+ @show="checkMenuPosition(props.row.id)"
1368
+ >
1369
+ <div :class="tailClass" />
1370
+ <div
1371
+ class="q-pt-ba q-px-ba q-pb-none text-heading-xxs text-dark"
1372
+ >
1373
+ Select More Options
1374
+ </div>
1375
+ <q-list class="grid-more-action">
1376
+ <template v-for="(action, __i) in col.actions">
1377
+ <q-item
1378
+ v-if="
1379
+ typeof action.hide === 'function'
1380
+ ? !action.hide(props.row)
1381
+ : true
1382
+ "
1383
+ class="q-px-sm q-py-ba bg-neutral-2 q-mb-xs"
1384
+ :aria-label="
1385
+ typeof action.label === 'function'
1386
+ ? action.label(props.row)
1387
+ : action.label
1388
+ "
1389
+ clickable
1390
+ :key="__i"
1391
+ tabindex="-1"
1392
+ @click="action.handler(props.row)"
1393
+ >
1394
+ <q-item-section class="q-pr-xs" avatar>
1395
+ <q-icon
1396
+ v-if="
1397
+ typeof action.icon === 'function'
1398
+ ? action.icon(props.row)
1399
+ : action.icon
1400
+ "
1401
+ :class="`${
1402
+ typeof action.icon === 'function'
1403
+ ? action.icon(props.row)
1404
+ : action.icon
1405
+ } text-${getActionItemColor(
1406
+ action,
1407
+ props.row
1408
+ )}`"
1409
+ size="1.5rem"
1410
+ tabindex="-1"
1411
+ />
1412
+ </q-item-section>
1413
+ <q-item-section
1414
+ :class="`text-caption-lg text-${getActionItemColor(
1415
+ action,
1416
+ props.row
1417
+ )}`"
1418
+ tabindex="0"
1419
+ >
1420
+ {{
1421
+ typeof action.label === 'function'
1422
+ ? action.label(props.row)
1423
+ : action.label
1424
+ }}
1425
+ </q-item-section>
1426
+ </q-item>
1427
+ </template>
1428
+ </q-list>
1429
+ </q-menu>
1430
+ </template>
1431
+ </UBtnStd>
1432
+ <template v-if="isMobile">
1433
+ <UBtnStd
1434
+ color="primary"
1435
+ full-width
1436
+ :id="`view-more-actions-${props.row['id']}`"
1437
+ :label="viewMoreLabel"
1438
+ class="full-width"
1439
+ outline
1440
+ @on-click="handleOpenMobileMoreActions(props.row['id'])"
1441
+ />
1442
+ <USheet
1443
+ v-if="
1444
+ moreActionDialogData &&
1445
+ moreActionDialogData.showDialog[props.row.id]
1446
+ "
1447
+ v-model:dialogs="mobileActionsDialog[props.row['id']]"
1448
+ :close-icon-label="closeIconLabel"
1449
+ :heading="moreActionDialogData.row.title"
1450
+ :is-left-icon="false"
1451
+ :show-action-buttons="true"
1452
+ >
1453
+ <template #content>
1454
+ <q-card
1455
+ class="more-action-popup-wrapper confirmation-dialog-wrapper mobile-confirmation-dialog q-px-ba q-py-ba"
1456
+ >
1457
+ <q-card-section>
1458
+ <div class="content-wrapper text-center">
1459
+ <div
1460
+ class="q-pb-ba flex justify-center items-center"
1461
+ >
1462
+ <div
1463
+ :class="`remove-icon-wrapper ${
1464
+ moreActionDialogData.row.iconColor ===
1465
+ 'accent'
1466
+ ? 'icon-bg-accent'
1467
+ : 'icon-bg-primary'
1468
+ }`"
1469
+ >
1470
+ <q-icon
1471
+ :class="`${moreActionDialogData.row.icon} ${
1472
+ moreActionDialogData.row.iconColor ===
1473
+ 'accent'
1474
+ ? 'icon-text-accent'
1475
+ : 'icon-text-primary'
1476
+ }`"
1477
+ alt="confirmation icon"
1478
+ aria-label="confirmation icon"
1479
+ size="1.5rem"
1480
+ />
1481
+ </div>
1482
+ </div>
1483
+
1484
+ <div
1485
+ class="text-heading-xxs primary-content-text q-pb-xxs"
1486
+ >
1487
+ {{ moreActionDialogData.row.title }}
1488
+ </div>
1489
+ <div
1490
+ v-if="moreActionDialogData.row.description"
1491
+ class="text-body-sm secondary-content-text q-pb-xs"
1492
+ >
1493
+ {{ moreActionDialogData.row.description }}
1494
+ </div>
1495
+ </div>
1496
+ </q-card-section>
1497
+ </q-card>
1498
+ </template>
1499
+ <template
1500
+ v-if="
1501
+ moreActionDialogData &&
1502
+ moreActionDialogData.showDialog[props.row.id] &&
1503
+ moreActionDialogData.secondaryAction
1504
+ "
1505
+ #action_primary_one
1506
+ >
1507
+ <UBtnStd
1508
+ :color="moreActionDialogData.secondaryAction.color"
1509
+ :disable="
1510
+ moreActionDialogData.secondaryAction.disable
1511
+ "
1512
+ :flat="moreActionDialogData.secondaryAction.flat"
1513
+ :label="moreActionDialogData.secondaryAction.label"
1514
+ :loading="
1515
+ moreActionDialogData.secondaryAction.loading
1516
+ "
1517
+ :outline="
1518
+ moreActionDialogData.secondaryAction.outline
1519
+ "
1520
+ :size="moreActionDialogData.secondaryAction.size"
1521
+ @on-click="
1522
+ moreActionDialogData.secondaryAction.handler(
1523
+ props.row
1524
+ )
1525
+ "
1526
+ />
1527
+ </template>
1528
+ <template
1529
+ v-if="
1530
+ moreActionDialogData &&
1531
+ moreActionDialogData.showDialog[props.row.id] &&
1532
+ moreActionDialogData.primaryAction
1533
+ "
1534
+ #action_primary_two
1535
+ >
1536
+ <UBtnStd
1537
+ class="confirm-primary-action"
1538
+ :color="moreActionDialogData.primaryAction.color"
1539
+ :disable="moreActionDialogData.primaryAction.disable"
1540
+ :flat="moreActionDialogData.primaryAction.flat"
1541
+ :label="moreActionDialogData.primaryAction.label"
1542
+ :loading="moreActionDialogData.primaryAction.loading"
1543
+ :outline="moreActionDialogData.primaryAction.outline"
1544
+ :size="moreActionDialogData.primaryAction.size"
1545
+ @on-click="
1546
+ moreActionDialogData.primaryAction.handler(
1547
+ props.row
1548
+ )
1549
+ "
1550
+ />
1551
+ </template>
1552
+ </USheet>
1553
+ <USheet
1554
+ v-model:dialogs="moreActionsDialogs[props.row['id']]"
1555
+ :close-icon-label="closeIconLabel"
1556
+ :heading="selectMoreOptions"
1557
+ :is-left-icon="false"
1558
+ :show-action-buttons="false"
1559
+ >
1560
+ <template #content>
1561
+ <q-list class="mobile-grid-more-action">
1562
+ <template v-for="(action, __i) in col.actions">
1563
+ <q-item
1564
+ v-if="
1565
+ typeof action.hide === 'function'
1566
+ ? !action.hide(props.row)
1567
+ : true
1568
+ "
1569
+ class="q-px-sm q-py-ba bg-neutral-2 q-mb-xs"
1570
+ :aria-label="
1571
+ typeof action.label === 'function'
1572
+ ? action.label(props.row)
1573
+ : action.label
1574
+ "
1575
+ clickable
1576
+ :key="__i"
1577
+ tabindex="-1"
1578
+ @click="handleItemClick(action, props.row)"
1579
+ >
1580
+ <q-item-section class="q-pr-xs" avatar>
1581
+ <q-icon
1582
+ v-if="
1583
+ typeof action.icon === 'function'
1584
+ ? action.icon(props.row)
1585
+ : action.icon
1586
+ "
1587
+ :class="`${
1588
+ typeof action.icon === 'function'
1589
+ ? action.icon(props.row)
1590
+ : action.icon
1591
+ } text-${getActionItemColor(
1592
+ action,
1593
+ props.row
1594
+ )}`"
1595
+ size="1.5rem"
1596
+ tabindex="-1"
1597
+ />
1598
+ </q-item-section>
1599
+ <q-item-section
1600
+ :class="`text-caption-lg text-${getActionItemColor(
1601
+ action,
1602
+ props.row
1603
+ )}`"
1604
+ tabindex="0"
1605
+ >
1606
+ {{
1607
+ typeof action.label === 'function'
1608
+ ? action.label(props.row)
1609
+ : action.label
1610
+ }}
1611
+ </q-item-section>
1612
+ </q-item>
1613
+ </template>
1614
+ </q-list>
1615
+ </template>
1616
+ </USheet>
1617
+ </template>
1618
+ </template>
1619
+ </template>
1620
+ </template>
1621
+ </div>
1622
+ </template>
1623
+ </UExpansionStd>
933
1624
  </template>
934
1625
  </q-table>
935
1626
  </template>
@@ -45,7 +45,6 @@ const selectedRows = defineModel('selectedRows', {
45
45
  default: () => [],
46
46
  type: Array,
47
47
  })
48
-
49
48
  const props = defineProps({
50
49
  actionBtnAriaLabel: {
51
50
  type: String,
@@ -75,6 +74,14 @@ const props = defineProps({
75
74
  type: String,
76
75
  default: 'table-std',
77
76
  },
77
+ enableIconToggle:{
78
+ type: Boolean,
79
+ default: false
80
+ },
81
+ expansion: {
82
+ type: Boolean,
83
+ default: false
84
+ },
78
85
  filter: {
79
86
  type: String,
80
87
  default: '',
@@ -394,6 +401,8 @@ watch(
394
401
  :bordered="bordered"
395
402
  :close-icon-label="closeIconLabel"
396
403
  :dataTestId="dataTestId"
404
+ :enableIconToggle="enableIconToggle"
405
+ :expansion="expansion"
397
406
  :filter="filter"
398
407
  :flat="flat"
399
408
  :grid="grid"
@@ -1366,4 +1375,21 @@ watch(
1366
1375
  justify-content: flex-start
1367
1376
  align-items: center
1368
1377
  gap: $xxs
1378
+
1379
+ .u-expansion-table
1380
+ .u-expansion-body
1381
+ display: flex
1382
+ flex-wrap: wrap
1383
+ gap: $xs
1384
+
1385
+ > .col-12
1386
+ width: 100%
1387
+ > .col-sm-6
1388
+ width: 100%
1389
+ @media (min-width: 600px)
1390
+ width: calc(50% - #{$xs} / 2)
1391
+
1392
+ > *:not(:last-child)
1393
+ margin-bottom: $ba
1394
+
1369
1395
  </style>
@@ -12,6 +12,7 @@ import UChip from './core/UChip.vue'
12
12
  import UDate from './core/UDate.vue'
13
13
  import UDialogStd from './core/UDialogStd.vue'
14
14
  import UDrawer from './core/UDrawer/UDrawer.vue'
15
+ import UExpansionStd from './core/UExpansionStd.vue'
15
16
  import UInnerLoader from './core/UInnerLoader.vue'
16
17
  import UInputAddressLookup from './core/UInputAddressLookup.vue'
17
18
  import UInputPhoneStd from './core/UInputPhoneStd.vue'
@@ -57,6 +58,7 @@ export {
57
58
  UDate,
58
59
  UDialogStd,
59
60
  UDrawer,
61
+ UExpansionStd,
60
62
  UInnerLoader,
61
63
  UInputAddressLookup,
62
64
  UInputPhoneStd,