@usssa/component-library 1.0.0-alpha.134 → 1.0.0-alpha.135

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,4 +1,4 @@
1
- # Component Library v1.0.0-alpha.133
1
+ # Component Library v1.0.0-alpha.135
2
2
 
3
3
  **This library provides custom UI components for USSSA applications.**
4
4
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@usssa/component-library",
3
- "version": "1.0.0-alpha.134",
3
+ "version": "1.0.0-alpha.135",
4
4
  "description": "A Quasar component library project",
5
5
  "productName": "Quasar component library App",
6
6
  "author": "Troy Moreland <troy.moreland@usssa.com>",
@@ -1,5 +1,5 @@
1
1
  <script setup>
2
- import { computed, ref } from 'vue'
2
+ import { computed } from 'vue'
3
3
 
4
4
  const emit = defineEmits(['onClick'])
5
5
  const props = defineProps({
@@ -22,6 +22,10 @@ const props = defineProps({
22
22
  iconClass: {
23
23
  type: String,
24
24
  },
25
+ inSheet: {
26
+ type: Boolean,
27
+ default: false,
28
+ },
25
29
  label: {
26
30
  type: String,
27
31
  },
@@ -45,7 +49,7 @@ const backgroundColor = computed(() => {
45
49
  if (props.selected && !props.destructive && !props.positive) {
46
50
  return 'bg-blue-1'
47
51
  }
48
- return 'bg-neutral-1'
52
+ return props.inSheet ? 'bg-neutral-2' : 'bg-neutral-1'
49
53
  })
50
54
 
51
55
  const iconColor = computed(() => {
@@ -62,7 +66,7 @@ const iconColor = computed(() => {
62
66
  const labelColor = computed(() => {
63
67
  if (props.destructive) {
64
68
  return 'text-accent'
65
- } else if (props.selected) {
69
+ } else if (props.selected && !props.inSheet) {
66
70
  return 'text-primary'
67
71
  } else if (props.positive) {
68
72
  return 'text-positive'
@@ -70,6 +74,13 @@ const labelColor = computed(() => {
70
74
  return 'text-dark'
71
75
  })
72
76
 
77
+ const labelStyle = computed(() => {
78
+ if (props.inSheet) {
79
+ return 'text-caption-lg'
80
+ }
81
+ return 'text-body-sm'
82
+ })
83
+
73
84
  const type = computed(() => {
74
85
  if (props.destructive) {
75
86
  return 'destructive'
@@ -105,7 +116,7 @@ const handleClick = () => {
105
116
  />
106
117
  </q-item-section>
107
118
  <slot name="leading_slot"></slot>
108
- <q-item-section :class="`${labelColor} text-body-sm label`">
119
+ <q-item-section :class="`${labelColor} ${labelStyle} label`">
109
120
  {{ label }}
110
121
  </q-item-section>
111
122
  <q-item-section v-if="rightIcon" side>
@@ -1,16 +1,25 @@
1
1
  <script setup>
2
- import { ref, watch} from 'vue'
2
+ import { ref, watch } from 'vue'
3
+ import UBtnStd from './UBtnStd.vue'
3
4
  import UChip from './UChip.vue'
4
5
  import UTooltip from './UTooltip.vue'
6
+ import USheet from './USheet.vue'
7
+ import UMenuItem from './UMenuItem.vue'
8
+ import { useScreenType } from '../../composables/useScreenType'
5
9
 
10
+ const emit = defineEmits(['update:modelValue'])
6
11
  const props = defineProps({
12
+ caption: {
13
+ type: String,
14
+ default: '',
15
+ },
7
16
  color: {
8
17
  type: String,
9
18
  default: 'neutral-7',
10
19
  },
11
- dataTestId:{
20
+ dataTestId: {
12
21
  type: String,
13
- default: 'multi-select'
22
+ default: 'multi-select',
14
23
  },
15
24
  filterFn: {
16
25
  type: Function,
@@ -77,12 +86,84 @@ const props = defineProps({
77
86
  useInput: {
78
87
  type: Boolean,
79
88
  required: false,
80
- }
89
+ },
81
90
  })
82
91
 
92
+ const $screen = useScreenType()
93
+
83
94
  const chipModelVal = ref(true)
95
+ const dialogs = ref([])
96
+ const filterOptions = ref([...props.options])
84
97
  const placeholderText = ref(props.placeholder)
98
+ const selectedItems = ref([...props.modelValue])
99
+ const sheetHeading = ref(props.label)
100
+
101
+ const filterSheetOptions = (val, update) => {
102
+ if (val === '') {
103
+ update(() => {
104
+ filterOptions.value = [...props.options]
105
+ })
106
+ return
107
+ }
85
108
 
109
+ const typeValue = val.toLowerCase()
110
+ update(() => {
111
+ filterOptions.value = props.options.filter((option) =>
112
+ option.label.toLowerCase().includes(typeValue)
113
+ )
114
+ })
115
+ }
116
+ const handleApply = () => {
117
+ dialogs.value[0].open = false
118
+ emit('update:modelValue', selectedItems.value)
119
+ }
120
+ const handleClick = (event) => {
121
+ const isSelectElement = event.target.closest('.q-field__control')
122
+ if ($screen.value.isMobile && isSelectElement) {
123
+ event.stopPropagation()
124
+ dialogs.value = [
125
+ {
126
+ open: true,
127
+ height: 350,
128
+ persistent: true,
129
+ transitionDuration: 500,
130
+ position: 'bottom',
131
+ },
132
+ ]
133
+ selectedItems.value = props.modelValue
134
+ }
135
+ }
136
+ const handleClose = () => {
137
+ dialogs.value[0].open = false
138
+ selectedItems.value = props.modelValue.length ? props.modelValue : []
139
+ }
140
+ const handleSheetItemClick = (val) => {
141
+ const exists = selectedItems.value.find((item) => item.value === val.value)
142
+ if (!exists) {
143
+ selectedItems.value = [...selectedItems.value, val]
144
+ } else {
145
+ selectedItems.value = selectedItems.value.filter(
146
+ (item) => item.value !== val.value
147
+ )
148
+ }
149
+ }
150
+ const handleSheetItemRemove = (item) => {
151
+ selectedItems.value = selectedItems.value.filter(
152
+ (option) => option.value !== item.value
153
+ )
154
+ }
155
+ const handleSheetSelectionUpdate = (val) => {
156
+ selectedItems.value = val
157
+ }
158
+ const isSelected = (value) => {
159
+ let getItems = selectedItems.value.filter((e) => e.value === value)
160
+ return getItems.length ? true : false
161
+ }
162
+ const removeItems = (item) => {
163
+ selectedItems.value = selectedItems.value.filter(
164
+ (option) => option.value !== item.value
165
+ )
166
+ }
86
167
  const updateVal = (val) => {
87
168
  props.updateFn(val)
88
169
  placeholderText.value = val.length ? '' : props.placeholder
@@ -94,11 +175,19 @@ watch(
94
175
  placeholderText.value = value
95
176
  }
96
177
  )
178
+ watch(
179
+ () => $screen.value,
180
+ (newValue) => {
181
+ if (newValue) {
182
+ selectedItems.value = [...props.modelValue]
183
+ }
184
+ }
185
+ )
97
186
  </script>
98
187
 
99
188
  <template>
100
- <div class="q-gutter-xs" :dataTestId="dataTestId">
101
- <label class="row items-center" for="select" >
189
+ <div class="q-gutter-xs" :dataTestId="dataTestId" @click="handleClick">
190
+ <label class="row items-center" for="select">
102
191
  <div class="u-select-label text-body-sm">
103
192
  <span>{{ label }}</span>
104
193
  <span v-if="isRequired" class="text-red-5 q-ml-xs">*</span>
@@ -121,6 +210,7 @@ watch(
121
210
  <q-select
122
211
  v-bind="$attrs"
123
212
  :class="`u-multi-select field-${size}`"
213
+ behavior="menu"
124
214
  bottom-slots
125
215
  :color="color"
126
216
  hide-bottom-space
@@ -133,7 +223,7 @@ watch(
133
223
  options-selected-class="primary bg-blue-1"
134
224
  :option-value="optionValue"
135
225
  outlined
136
- :placeholder="placeholderText"
226
+ :placeholder="modelValue.length ? '' : placeholderText"
137
227
  popup-content-class="u-option-menu"
138
228
  use-chips
139
229
  :use-input="useInput"
@@ -168,7 +258,7 @@ watch(
168
258
 
169
259
  <template v-if="hintText" v-slot:hint>
170
260
  <div class="row no-wrap items-center">
171
- <q-icon v-if="hintIcon" :class="hintIcon" size="1rem"/>
261
+ <q-icon v-if="hintIcon" :class="hintIcon" size="1rem" />
172
262
 
173
263
  <div class="q-mx-xxs text-body-xs">
174
264
  {{ hintText }}
@@ -177,7 +267,11 @@ watch(
177
267
  </template>
178
268
 
179
269
  <template v-slot:option="scope">
180
- <q-item v-bind="scope.itemProps" class="items-center u-custom-options">
270
+ <q-item
271
+ v-bind="scope.itemProps"
272
+ v-if="!$screen.isMobile"
273
+ class="items-center u-custom-options"
274
+ >
181
275
  <div v-if="scope.opt.icon" class="q-pr-xs">
182
276
  <q-icon :class="scope.opt.icon" color="neutral-13" size="1rem" />
183
277
  </div>
@@ -186,7 +280,7 @@ watch(
186
280
  <q-item-label class="text-body-sm">
187
281
  {{ scope.opt.label }}
188
282
  </q-item-label>
189
- <q-item-label v-if="scope.opt.description" caption>
283
+ <q-item-label v-if="scope.opt.description" caption>
190
284
  {{ scope.opt.description }}
191
285
  </q-item-label>
192
286
  </q-item-section>
@@ -212,6 +306,95 @@ watch(
212
306
  </template>
213
307
  </q-select>
214
308
  </div>
309
+ <USheet
310
+ v-if="$screen.isMobile"
311
+ v-model:dialogs="dialogs"
312
+ :heading="sheetHeading"
313
+ :heading-caption="caption"
314
+ :show-action-buttons="true"
315
+ >
316
+ <template #header>
317
+ <q-select
318
+ :model-value="selectedItems"
319
+ :class="`u-multi-select field-md q-mt-ba`"
320
+ behavior="menu"
321
+ multiple
322
+ outlined
323
+ :placeholder="selectedItems.length ? '' : placeholderText"
324
+ use-chips
325
+ :use-input="useInput"
326
+ @click="() => null"
327
+ @filter="filterSheetOptions"
328
+ @remove="handleSheetItemRemove"
329
+ @update:model-value="handleSheetSelectionUpdate"
330
+ >
331
+ <template v-if="leftIcon" v-slot:prepend>
332
+ <q-icon :class="leftIcon" size="1rem" />
333
+ </template>
334
+ <template v-slot:selected-item="scope">
335
+ <UChip
336
+ v-model="chipModelVal"
337
+ :chipLabel="scope.opt.label"
338
+ dense
339
+ :removable="true"
340
+ :tabindex="scope.tabindex"
341
+ @remove="removeItems(scope.opt)"
342
+ />
343
+ </template>
344
+ </q-select>
345
+ </template>
346
+ <template #content>
347
+ <template v-if="filterOptions.length > 0">
348
+ <template v-for="(item, index) in filterOptions" :key="index">
349
+ <UMenuItem
350
+ iconClass=""
351
+ :destructive="item.destructive"
352
+ :disable="item.disable"
353
+ :hide="item.hide"
354
+ :index="index"
355
+ :inSheet="true"
356
+ :label="item.label"
357
+ labelStyle="text-caption-lg"
358
+ :leftIcon="item.leftIcon"
359
+ :positive="item.positive"
360
+ :rightIcon="item.rightIcon"
361
+ :selected="isSelected(item.value)"
362
+ @onClick="handleSheetItemClick(item, index)"
363
+ >
364
+ <template #trailing_slot>
365
+ <slot name="trailing_slot">
366
+ <q-icon
367
+ v-if="isSelected(item.value)"
368
+ class="fa-kit-duotone fa-circle-check"
369
+ color="primary"
370
+ size="1rem"
371
+ />
372
+ </slot>
373
+ </template>
374
+ </UMenuItem>
375
+ </template>
376
+ </template>
377
+ <template v-else>
378
+ <q-item>
379
+ <q-item-section class="text-grey">
380
+ {{ noSearchText }}
381
+ </q-item-section>
382
+ </q-item>
383
+ </template>
384
+ </template>
385
+ <template #action_primary_one>
386
+ <UBtnStd
387
+ color="primary"
388
+ label="Cancel"
389
+ outline
390
+ size="md"
391
+ @onClick="handleClose"
392
+ />
393
+ </template>
394
+ <template #action_primary_two>
395
+ <UBtnStd color="primary" label="Apply" size="md" @onClick="handleApply" />
396
+ </template>
397
+ </USheet>
215
398
  </template>
216
399
 
217
400
  <style lang="sass">
@@ -273,4 +456,7 @@ watch(
273
456
  border-radius: $xxs
274
457
  padding: $xs
275
458
  min-height: $lg
459
+
460
+ .sheet-card-wrapper .q-select__dropdown-icon
461
+ display: none !important
276
462
  </style>
@@ -1,19 +1,27 @@
1
1
  <script setup>
2
2
  import { computed, ref, watch } from 'vue'
3
+ import { useScreenType } from '../../composables/useScreenType'
3
4
  import UAvatar from './UAvatar.vue'
5
+ import UBtnStd from './UBtnStd.vue'
6
+ import UInputTextStd from './UInputTextStd.vue'
4
7
  import UMenuItem from './UMenuItem.vue'
8
+ import USheet from './USheet.vue'
5
9
  import UTooltip from './UTooltip.vue'
6
10
 
7
11
  const emit = defineEmits(['update:modelValue'])
8
12
 
9
13
  const props = defineProps({
14
+ caption: {
15
+ type: String,
16
+ default: '',
17
+ },
10
18
  color: {
11
19
  type: String,
12
20
  default: 'neutral-7',
13
21
  },
14
- dataTestId:{
15
- type: String,
16
- default: 'select-std'
22
+ dataTestId: {
23
+ type: String,
24
+ default: 'select-std',
17
25
  },
18
26
  disableAvatar: {
19
27
  type: Boolean,
@@ -84,17 +92,71 @@ const props = defineProps({
84
92
  },
85
93
  })
86
94
 
95
+ const $screen = useScreenType()
96
+
97
+ const dialogs = ref([])
98
+ const initialOptions= ref([...props.options])
87
99
  const placeholderText = ref(props?.placeholder)
100
+ const search = ref('')
101
+ const selectedItem = ref(props.modelValue)
102
+ const sheetHeading = ref(props.label)
88
103
 
104
+ const filterOptions = computed(() => {
105
+ if (!search.value) return initialOptions.value
106
+ return props.options.filter((option) =>
107
+ option.label.toLowerCase().includes(search.value.toLocaleLowerCase())
108
+ )
109
+ })
89
110
  const model = computed({
90
111
  get() {
91
112
  return props.modelValue
92
113
  },
93
114
  set(value) {
115
+ selectedItem.value = value
94
116
  return emit('update:modelValue', value)
95
117
  },
96
118
  })
97
119
 
120
+ // sheet apply action
121
+ const handleApply = () => {
122
+ dialogs.value[0].open = false
123
+ model.value = selectedItem.value
124
+ }
125
+ // for opening the sheet in mobile screen
126
+ const handleClick = (event) => {
127
+ const isSelectElement = event.target.closest('.q-field__control')
128
+ if ($screen.value.isMobile && isSelectElement) {
129
+ event.stopPropagation()
130
+ dialogs.value = [
131
+ {
132
+ open: true,
133
+ height: 350,
134
+ persistent: true,
135
+ transitionDuration: 500,
136
+ position: 'bottom',
137
+ },
138
+ ]
139
+ search.value = ''
140
+ if (model.value === '') {
141
+ selectedItem.value = ''
142
+ } else {
143
+ selectedItem.value = model.value
144
+ }
145
+ }
146
+ }
147
+ // sheet closing action
148
+ const handleClose = () => {
149
+ dialogs.value[0].open = false
150
+ if (model.value) {
151
+ if (selectedItem.value) {
152
+ if (model.value !== selectedItem.value) {
153
+ selectedItem.value = model.value
154
+ }
155
+ }
156
+ } else {
157
+ selectedItem.value = ''
158
+ }
159
+ }
98
160
  // adding scroll if highlighted menu is not visible to user
99
161
  const handleKeydown = () => {
100
162
  setTimeout(() => {
@@ -119,6 +181,10 @@ const handleKeydown = () => {
119
181
  }
120
182
  }, 100)
121
183
  }
184
+ // selecting sheet items
185
+ const handleSheetItemClick = (item, key) => {
186
+ selectedItem.value = item.value
187
+ }
122
188
 
123
189
  const updateVal = (val) => {
124
190
  placeholderText.value = val?.length ? '' : props?.placeholder
@@ -130,10 +196,22 @@ watch(
130
196
  placeholderText.value = value
131
197
  }
132
198
  )
199
+ watch(
200
+ () => $screen.value,
201
+ (newValue) => {
202
+ if (newValue) {
203
+ selectedItem.value = props.modelValue
204
+ }
205
+ }
206
+ )
133
207
  </script>
134
208
 
135
209
  <template>
136
- <section class="column q-gutter-y-xs" :dataTestId="dataTestId">
210
+ <section
211
+ class="column q-gutter-y-xs"
212
+ :dataTestId="dataTestId"
213
+ @click="handleClick"
214
+ >
137
215
  <label class="row items-center" for="select">
138
216
  <div class="u-select-label text-body-sm">
139
217
  <span>{{ label }}</span>
@@ -160,6 +238,7 @@ watch(
160
238
  v-model="model"
161
239
  :class="`u-select field-${size}`"
162
240
  :popup-content-class="`u-options-menu ${popupClass}`"
241
+ behavior="menu"
163
242
  options-selected-class="primary bg-blue-1"
164
243
  bottom-slots
165
244
  :color="color"
@@ -203,12 +282,14 @@ watch(
203
282
  <template v-slot:option="scope">
204
283
  <UMenuItem
205
284
  v-bind="scope.itemProps"
285
+ v-if="!$screen.isMobile"
206
286
  class="q-ma-xxs"
207
287
  iconClass="icon-secondary-opacity"
208
288
  :label="scope.opt.label"
209
289
  :leftIcon="scope.opt.leftIcon"
290
+ :key="scope.opt.value"
210
291
  :rightIcon="scope.opt.rightIcon"
211
- :selected="scope.selected"
292
+ :selected="scope.selected || model === scope.label"
212
293
  >
213
294
  <template #leading_slot>
214
295
  <slot name="leading_slot" />
@@ -225,7 +306,7 @@ watch(
225
306
  <template #trailing_slot>
226
307
  <slot name="trailing_slot">
227
308
  <q-icon
228
- v-if="scope.selected"
309
+ v-if="scope.selected || model === scope.label"
229
310
  class="fa-kit-duotone fa-circle-check"
230
311
  color="primary"
231
312
  size="1rem"
@@ -235,6 +316,95 @@ watch(
235
316
  </UMenuItem>
236
317
  </template>
237
318
  </q-select>
319
+ <USheet
320
+ v-if="$screen.isMobile"
321
+ v-model:dialogs="dialogs"
322
+ :heading="sheetHeading"
323
+ :heading-caption="caption"
324
+ :show-action-buttons="true"
325
+ >
326
+ <template #header>
327
+ <UInputTextStd
328
+ v-if="useInput"
329
+ v-model="search"
330
+ class="q-mt-ba"
331
+ :leftIcon="leftIcon"
332
+ :placeholder="placeholder"
333
+ size="md"
334
+ />
335
+ </template>
336
+ <template #content>
337
+ <template v-if="filterOptions.length > 0">
338
+ <template v-for="(item, index) in filterOptions" :key="item.value">
339
+ <UMenuItem
340
+ iconClass=""
341
+ :destructive="item.destructive"
342
+ :disable="item.disable"
343
+ :hide="item.hide"
344
+ :inSheet="true"
345
+ :label="item.label"
346
+ labelStyle="text-caption-lg"
347
+ :leftIcon="item.leftIcon"
348
+ :positive="item.positive"
349
+ :rightIcon="item.rightIcon"
350
+ :selected="
351
+ item.value === selectedItem || item.label === selectedItem
352
+ "
353
+ @onClick="handleSheetItemClick(item, index)"
354
+ >
355
+ <template #leading_slot>
356
+ <slot name="leading_slot" />
357
+ <div v-if="!disableAvatar">
358
+ <UAvatar
359
+ v-if="item.avatarUrl"
360
+ :image="item.avatarUrl"
361
+ :name="item.label"
362
+ size="md"
363
+ />
364
+ <UAvatar v-else :name="item.label" size="md" />
365
+ </div>
366
+ </template>
367
+ <template #trailing_slot>
368
+ <slot name="trailing_slot">
369
+ <q-icon
370
+ v-if="
371
+ item.value === selectedItem || item.label === selectedItem
372
+ "
373
+ class="fa-kit-duotone fa-circle-check"
374
+ color="primary"
375
+ size="1rem"
376
+ />
377
+ </slot>
378
+ </template>
379
+ </UMenuItem>
380
+ </template>
381
+ </template>
382
+ <template v-else>
383
+ <q-item>
384
+ <q-item-section class="text-grey">
385
+ {{ noSearchText }}
386
+ </q-item-section>
387
+ </q-item>
388
+ </template>
389
+ </template>
390
+ <template #action_primary_one>
391
+ <UBtnStd
392
+ color="primary"
393
+ label="Cancel"
394
+ outline
395
+ size="md"
396
+ @onClick="handleClose"
397
+ />
398
+ </template>
399
+ <template #action_primary_two>
400
+ <UBtnStd
401
+ color="primary"
402
+ label="Apply"
403
+ size="md"
404
+ @onClick="handleApply"
405
+ />
406
+ </template>
407
+ </USheet>
238
408
  </section>
239
409
  </template>
240
410
 
@@ -290,4 +460,19 @@ watch(
290
460
  .u-options-menu
291
461
  .q-item:last-child
292
462
  margin-bottom: $xxs
463
+
464
+ .sheet-card-wrapper .q-card__section .q-item
465
+ padding:$ba $sm !important
466
+ margin-bottom: $xs !important
467
+ border-radius: $xs !important
468
+ .q-icon
469
+ font-size: $ms !important
470
+
471
+ .sheet-action-wrapper .action-buttons
472
+ gap: $ba !important
473
+ padding: $ba !important
474
+
475
+ .sheet-card-wrapper .main-content-dialog
476
+ padding-top: $xs !important
477
+ padding-bottom: $xs !important
293
478
  </style>
@@ -48,9 +48,10 @@ const props = defineProps({
48
48
  })
49
49
 
50
50
  // constants
51
+
52
+ let isDragging = false
51
53
  const MAX_HEIGHT = 750
52
54
  const MIN_HEIGHT = 40
53
- let isDragging = false
54
55
  let startHeight = 0
55
56
  let startY = 0
56
57
 
@@ -193,62 +194,67 @@ watch(
193
194
  </div>
194
195
 
195
196
  <q-card-section
196
- class="row items-start justify-between no-wrap q-pt-none q-pb-xs q-px-ba q-mt-ba"
197
- >
198
- <div class="heading-wrapper row">
199
- <div
200
- class="flex items-center justify-center dialog-heading-container"
201
- >
202
- <UBtnStd
203
- v-if="isLeftIcon"
204
- class="dialog-action-icons q-mr-xs"
205
- :aria-label="leftIconLabel"
206
- :flat="true"
207
- tabindex="0"
208
- @click="handleBackClick()"
197
+ class="column q-pt-none q-pb-xs q-px-ba q-mt-ba"
198
+ >
199
+ <div class="row items-start justify-between no-wrap">
200
+ <div class="heading-wrapper row">
201
+ <div
202
+ class="flex items-center justify-center dialog-heading-container"
209
203
  >
210
- <q-icon
211
- :class="`icon-close ${leftIcon}`"
212
- size="1.5rem"
213
- tabindex="-1"
214
- />
215
- </UBtnStd>
216
- <div>
217
- <div class="text-heading-xs">
218
- {{ heading }}
219
- </div>
204
+ <UBtnStd
205
+ v-if="isLeftIcon"
206
+ class="dialog-action-icons q-mr-xs"
207
+ :aria-label="leftIconLabel"
208
+ :flat="true"
209
+ tabindex="0"
210
+ @click="handleBackClick()"
211
+ >
212
+ <q-icon
213
+ :class="`icon-close ${leftIcon}`"
214
+ size="1.5rem"
215
+ tabindex="-1"
216
+ />
217
+ </UBtnStd>
220
218
  <div>
221
- <span v-if="headingCaption" class="text-body-sm dialog-caption">
222
- {{ headingCaption }}
223
- </span>
219
+ <div class="text-heading-xs">
220
+ {{ heading }}
221
+ </div>
222
+ <div>
223
+ <span
224
+ v-if="headingCaption"
225
+ class="text-body-sm dialog-caption"
226
+ >
227
+ {{ headingCaption }}
228
+ </span>
229
+ </div>
224
230
  </div>
225
231
  </div>
226
232
  </div>
227
- </div>
233
+ <UBtnStd
234
+ class="dialog-action-icons"
235
+ :aria-label="closeIconLabel"
236
+ :flat="true"
237
+ tabindex="0"
238
+ @click="handleCloseDialog(key)"
239
+ >
240
+ <q-icon
241
+ :class="`icon-close ${closeIcon} icon-secondary-opacity`"
242
+ size="1.5rem"
243
+ tabindex="-1"
244
+ />
245
+ </UBtnStd>
228
246
 
229
- <UBtnStd
230
- class="dialog-action-icons"
231
- :aria-label="closeIconLabel"
232
- :flat="true"
233
- tabindex="0"
234
- @click="handleCloseDialog(key)"
235
- >
236
- <q-icon
237
- :class="`icon-close ${closeIcon} icon-secondary-opacity`"
238
- size="1.5rem"
239
- tabindex="-1"
240
- />
241
- </UBtnStd>
242
- </q-card-section>
247
+ </div>
248
+ <slot name="header"></slot>
249
+ </q-card-section>
243
250
  <q-card-section
244
- class="main-content-dialog scroll q-px-ba"
245
- :style="{ height: dialog.height - 84 + 'px !important' }"
251
+ class="main-content-dialog q-px-ba"
246
252
  tabindex="-1"
247
253
  >
248
254
  <slot name="content"></slot>
249
255
  </q-card-section>
250
256
  </q-card>
251
- <div v-if="showActionButtons && dialog.height > 70" class="action-wrapper">
257
+ <div v-if="showActionButtons && dialog.height > 70" class="sheet-action-wrapper">
252
258
  <q-card-actions class="action-buttons q-px-sm q-py-ba" align="center">
253
259
  <slot name="action_primary_one"></slot>
254
260
  <slot name="action_primary_two"></slot>
@@ -259,9 +265,11 @@ watch(
259
265
 
260
266
  <style lang="sass">
261
267
  .sheet-card-wrapper
268
+ display: flex
269
+ flex-direction: column
262
270
  position: relative
263
271
  width: 100%
264
- overflow: hidden
272
+ overflow: hidden !important
265
273
  transition: height 0.02s ease-in-out
266
274
  background: $neutral-1
267
275
  border-radius: $sm $sm 0 0 !important
@@ -312,12 +320,15 @@ watch(
312
320
  .q-item__section
313
321
  color: red !important
314
322
 
315
- .action-wrapper
323
+ .sheet-action-wrapper
316
324
  background: $neutral-1
317
325
 
318
326
  .main-content-dialog
319
- margin-bottom: $ba
327
+ margin-bottom: 0px !important
320
328
  padding-bottom: 0
329
+ flex-grow: 1
330
+ overflow-y: auto !important
331
+ overflow-x: hidden
321
332
 
322
333
  .dialog-caption
323
334
  color: $neutral-9
@@ -329,4 +340,9 @@ watch(
329
340
 
330
341
  .dialog-heading-container
331
342
  gap: $xs
343
+
344
+ .action-wrapper
345
+ position: relative
346
+ width: 100%
347
+ background: $neutral-1
332
348
  </style>