@usssa/component-library 1.0.0-alpha.122 → 1.0.0-alpha.124
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 +1 -1
- package/package.json +1 -1
- package/src/components/core/UBtnIcon.vue +44 -42
- package/src/components/core/UBtnStd.vue +20 -20
- package/src/components/core/UDrawer.vue +10 -5
- package/src/components/core/UPagination.vue +5 -0
- package/src/components/core/USelectStd.vue +14 -10
- package/src/components/core/USheet.vue +317 -0
- package/src/components/core/UToolbar/UCustomMenuIcon.vue +60 -0
- package/src/components/core/UToolbar/UToolbar.vue +206 -0
- package/src/components/core/UTooltip.vue +13 -8
- package/src/components/index.js +7 -1
- package/src/composables/useScreenType.js +30 -0
- package/src/components/core/UToolbar.vue +0 -101
package/README.md
CHANGED
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import { computed } from 'vue'
|
|
3
3
|
import UTooltip from './UTooltip.vue'
|
|
4
|
+
|
|
5
|
+
const emit = defineEmits(['onClick'])
|
|
4
6
|
const props = defineProps({
|
|
5
|
-
|
|
7
|
+
anchor: {
|
|
6
8
|
type: String,
|
|
7
|
-
|
|
8
|
-
default: 'fa-kit-duotone fa-circle-bolt',
|
|
9
|
+
default: 'center left',
|
|
9
10
|
},
|
|
10
11
|
ariaLabel: {
|
|
11
12
|
type: String,
|
|
@@ -15,10 +16,27 @@ const props = defineProps({
|
|
|
15
16
|
type: String,
|
|
16
17
|
default: 'primary',
|
|
17
18
|
},
|
|
19
|
+
dataTestId: {
|
|
20
|
+
type: String,
|
|
21
|
+
default: 'button-icon',
|
|
22
|
+
},
|
|
23
|
+
iconClass: {
|
|
24
|
+
type: String,
|
|
25
|
+
required: true,
|
|
26
|
+
default: 'fa-kit-duotone fa-circle-bolt',
|
|
27
|
+
},
|
|
28
|
+
offset: {
|
|
29
|
+
type: Array,
|
|
30
|
+
default: () => [4, 4],
|
|
31
|
+
},
|
|
18
32
|
round: {
|
|
19
33
|
type: Boolean,
|
|
20
34
|
default: true,
|
|
21
35
|
},
|
|
36
|
+
self: {
|
|
37
|
+
type: String,
|
|
38
|
+
default: 'center end',
|
|
39
|
+
},
|
|
22
40
|
size: {
|
|
23
41
|
type: String,
|
|
24
42
|
default: 'md',
|
|
@@ -32,26 +50,20 @@ const props = defineProps({
|
|
|
32
50
|
type: String,
|
|
33
51
|
default: 'top',
|
|
34
52
|
},
|
|
35
|
-
anchor: {
|
|
36
|
-
type: String,
|
|
37
|
-
default: 'center left',
|
|
38
|
-
},
|
|
39
|
-
self: {
|
|
40
|
-
type: String,
|
|
41
|
-
default: 'center end',
|
|
42
|
-
},
|
|
43
|
-
offset: {
|
|
44
|
-
type: Array,
|
|
45
|
-
default: () => [4, 4],
|
|
46
|
-
},
|
|
47
53
|
})
|
|
48
54
|
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
+
const btnClass = computed(() => {
|
|
56
|
+
if (props.color === 'neutral') {
|
|
57
|
+
return 'neutral-4'
|
|
58
|
+
}
|
|
59
|
+
return props.color
|
|
60
|
+
})
|
|
61
|
+
const iconColor = computed(() => {
|
|
62
|
+
if (props.color === 'neutral') {
|
|
63
|
+
return 'neutral-9'
|
|
64
|
+
}
|
|
65
|
+
return props.color
|
|
66
|
+
})
|
|
55
67
|
const iconSize = computed(() => {
|
|
56
68
|
if (props.size === 'sm') {
|
|
57
69
|
return 'xs'
|
|
@@ -62,47 +74,37 @@ const iconSize = computed(() => {
|
|
|
62
74
|
if (props.size === 'lg') {
|
|
63
75
|
return 'md'
|
|
64
76
|
}
|
|
65
|
-
|
|
66
77
|
return props.size
|
|
67
78
|
})
|
|
68
|
-
const iconColor = computed(() => {
|
|
69
|
-
if (props.color === 'neutral') {
|
|
70
|
-
return 'neutral-9'
|
|
71
|
-
}
|
|
72
|
-
return props.color
|
|
73
|
-
})
|
|
74
79
|
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}
|
|
79
|
-
return props.color
|
|
80
|
-
})
|
|
80
|
+
const handleClick = () => {
|
|
81
|
+
return emit('onClick')
|
|
82
|
+
}
|
|
81
83
|
</script>
|
|
82
84
|
|
|
83
85
|
<template>
|
|
84
86
|
<q-btn
|
|
85
|
-
|
|
87
|
+
:class="`u-btn-icon size-${size} ${btnClass}`"
|
|
88
|
+
:aria-label="ariaLabel"
|
|
89
|
+
:dataTestId="dataTestId"
|
|
86
90
|
flat="flat"
|
|
87
91
|
:round="round"
|
|
88
|
-
|
|
89
|
-
class="u-btn-icon"
|
|
90
|
-
:class="`size-${size} ${btnClass}`"
|
|
92
|
+
@click="handleClick"
|
|
91
93
|
>
|
|
92
94
|
<template #default>
|
|
93
95
|
<q-icon
|
|
94
|
-
:color="iconColor"
|
|
95
|
-
:aria-hidden="true"
|
|
96
96
|
:class="`${iconClass} size-${size}`"
|
|
97
|
+
:aria-hidden="true"
|
|
98
|
+
:color="iconColor"
|
|
97
99
|
:size="iconSize"
|
|
98
100
|
/>
|
|
99
101
|
|
|
100
102
|
<UTooltip
|
|
101
103
|
v-if="tooltip"
|
|
102
|
-
:description="tooltip"
|
|
103
104
|
:anchor="anchor"
|
|
104
|
-
:
|
|
105
|
+
:description="tooltip"
|
|
105
106
|
:offset="offset"
|
|
107
|
+
:self="self"
|
|
106
108
|
/>
|
|
107
109
|
<slot name="menu" />
|
|
108
110
|
</template>
|
|
@@ -10,7 +10,7 @@ const props = defineProps({
|
|
|
10
10
|
},
|
|
11
11
|
dataTestId: {
|
|
12
12
|
type: String,
|
|
13
|
-
default: 'button-std'
|
|
13
|
+
default: 'button-std',
|
|
14
14
|
},
|
|
15
15
|
disable: {
|
|
16
16
|
type: Boolean,
|
|
@@ -31,6 +31,11 @@ const props = defineProps({
|
|
|
31
31
|
leftIcon: {
|
|
32
32
|
type: String,
|
|
33
33
|
},
|
|
34
|
+
leftIconSize: {
|
|
35
|
+
type: String,
|
|
36
|
+
default: 'ba',
|
|
37
|
+
validator: (val) => ['sm', 'md', 'lg', 'ms', 'ba'].includes(val),
|
|
38
|
+
},
|
|
34
39
|
outline: {
|
|
35
40
|
type: Boolean,
|
|
36
41
|
default: false,
|
|
@@ -45,9 +50,12 @@ const props = defineProps({
|
|
|
45
50
|
},
|
|
46
51
|
})
|
|
47
52
|
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
53
|
+
const isFullWidth = computed(() => {
|
|
54
|
+
if (props.fullWidth === true) {
|
|
55
|
+
return 'full-width'
|
|
56
|
+
}
|
|
57
|
+
return ''
|
|
58
|
+
})
|
|
51
59
|
|
|
52
60
|
const textClass = computed(() => {
|
|
53
61
|
if (props.color === 'neutral') {
|
|
@@ -56,25 +64,21 @@ const textClass = computed(() => {
|
|
|
56
64
|
return ''
|
|
57
65
|
})
|
|
58
66
|
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
63
|
-
return ''
|
|
64
|
-
})
|
|
67
|
+
const handleClick = () => {
|
|
68
|
+
return emit('onClick')
|
|
69
|
+
}
|
|
65
70
|
</script>
|
|
66
71
|
|
|
67
72
|
<template>
|
|
68
73
|
<q-btn
|
|
69
|
-
class="u-btn q-py-none"
|
|
70
|
-
:class="`size-${size} ${textClass} focus-${color} ${isFullWidth}`"
|
|
74
|
+
:class="`u-btn q-py-none size-${size} ${textClass} focus-${color} ${isFullWidth}`"
|
|
71
75
|
:color="color"
|
|
72
76
|
:dataTestId="dataTestId"
|
|
73
77
|
:disable="disable"
|
|
74
78
|
:flat="flat"
|
|
75
79
|
no-caps
|
|
76
|
-
:unelevated="!outline"
|
|
77
80
|
:outline="outline"
|
|
81
|
+
:unelevated="!outline"
|
|
78
82
|
@click="handleClick"
|
|
79
83
|
>
|
|
80
84
|
<template #default>
|
|
@@ -82,10 +86,9 @@ const isFullWidth = computed(() => {
|
|
|
82
86
|
<div class="row items-center no-wrap">
|
|
83
87
|
<q-icon
|
|
84
88
|
v-if="leftIcon"
|
|
85
|
-
:class="leftIcon"
|
|
86
|
-
class="q-mr-xs"
|
|
89
|
+
:class="`q-mr-xs ${leftIcon}`"
|
|
87
90
|
left
|
|
88
|
-
size="
|
|
91
|
+
:size="leftIconSize"
|
|
89
92
|
/>
|
|
90
93
|
|
|
91
94
|
<div class="text-center text-caption-md button-label">
|
|
@@ -93,8 +96,7 @@ const isFullWidth = computed(() => {
|
|
|
93
96
|
</div>
|
|
94
97
|
<q-icon
|
|
95
98
|
v-if="rightIcon"
|
|
96
|
-
:class="rightIcon"
|
|
97
|
-
class="q-ml-xs"
|
|
99
|
+
:class="`q-ml-xs ${rightIcon}`"
|
|
98
100
|
right
|
|
99
101
|
size="1rem"
|
|
100
102
|
/>
|
|
@@ -123,12 +125,10 @@ const isFullWidth = computed(() => {
|
|
|
123
125
|
min-height: $lg
|
|
124
126
|
padding: 0 $ba !important
|
|
125
127
|
|
|
126
|
-
|
|
127
128
|
&.size-lg
|
|
128
129
|
min-height: $xl
|
|
129
130
|
padding: 0 $ba !important
|
|
130
131
|
|
|
131
|
-
|
|
132
132
|
.button-label
|
|
133
133
|
word-break: break-all
|
|
134
134
|
</style>
|
|
@@ -17,21 +17,25 @@ const open = defineModel('open', {
|
|
|
17
17
|
type: Boolean,
|
|
18
18
|
})
|
|
19
19
|
const props = defineProps({
|
|
20
|
-
menu: {
|
|
21
|
-
default: () => [],
|
|
22
|
-
type: Array,
|
|
23
|
-
},
|
|
24
20
|
brandLogo: {
|
|
25
21
|
default: '',
|
|
26
22
|
},
|
|
27
23
|
brandMiniLogo: {
|
|
28
24
|
default: '',
|
|
29
25
|
},
|
|
26
|
+
dataTestId:{
|
|
27
|
+
default:'drawer-std',
|
|
28
|
+
type: String
|
|
29
|
+
},
|
|
30
30
|
homeLink: {
|
|
31
31
|
required: true,
|
|
32
32
|
default: '/home',
|
|
33
33
|
type: String,
|
|
34
34
|
},
|
|
35
|
+
menu: {
|
|
36
|
+
default: () => [],
|
|
37
|
+
type: Array,
|
|
38
|
+
}
|
|
35
39
|
})
|
|
36
40
|
|
|
37
41
|
const $router = useRouter()
|
|
@@ -64,6 +68,7 @@ const handleCloseDrawer = () => {
|
|
|
64
68
|
v-model="open"
|
|
65
69
|
:class="`u-drawer ${miniState ? 'u-mini-drawer' : ''}`"
|
|
66
70
|
:breakpoint="400"
|
|
71
|
+
:dataTestId="dataTestId"
|
|
67
72
|
:mini="miniState"
|
|
68
73
|
:mini-width="64"
|
|
69
74
|
show-if-above
|
|
@@ -183,7 +188,7 @@ const handleCloseDrawer = () => {
|
|
|
183
188
|
outline: auto !important
|
|
184
189
|
.q-focus-helper
|
|
185
190
|
display: none
|
|
186
|
-
|
|
191
|
+
|
|
187
192
|
.u-drawer-scrollable-area
|
|
188
193
|
height: calc(100% - 0px)
|
|
189
194
|
margin-top: 0px
|
|
@@ -7,6 +7,10 @@ const emit = defineEmits(['update:modelValue', 'onRowChange', 'onPageChange'])
|
|
|
7
7
|
const model = defineModel()
|
|
8
8
|
|
|
9
9
|
const props = defineProps({
|
|
10
|
+
dataTestId:{
|
|
11
|
+
type: String,
|
|
12
|
+
default:'pagination-std'
|
|
13
|
+
},
|
|
10
14
|
maxPageLink: {
|
|
11
15
|
//Maximum number of page links to display at a time
|
|
12
16
|
type: Number,
|
|
@@ -62,6 +66,7 @@ watch(currentPage, (newValue) => {
|
|
|
62
66
|
active-color="primary"
|
|
63
67
|
boundary-numbers
|
|
64
68
|
color="dark"
|
|
69
|
+
:dataTestId="dataTestId"
|
|
65
70
|
direction-links
|
|
66
71
|
flat
|
|
67
72
|
gutter="sm"
|
|
@@ -11,6 +11,10 @@ const props = defineProps({
|
|
|
11
11
|
type: String,
|
|
12
12
|
default: 'neutral-7',
|
|
13
13
|
},
|
|
14
|
+
dataTestId:{
|
|
15
|
+
type: String,
|
|
16
|
+
default: 'select-std'
|
|
17
|
+
},
|
|
14
18
|
disableAvatar: {
|
|
15
19
|
type: Boolean,
|
|
16
20
|
default: true,
|
|
@@ -44,19 +48,16 @@ const props = defineProps({
|
|
|
44
48
|
type: String,
|
|
45
49
|
required: false,
|
|
46
50
|
},
|
|
47
|
-
options: {
|
|
48
|
-
type: Array,
|
|
49
|
-
required: true,
|
|
50
|
-
},
|
|
51
|
-
optionValue: {
|
|
52
|
-
type: String,
|
|
53
|
-
},
|
|
54
51
|
optionLabel: {
|
|
55
52
|
type: String,
|
|
56
53
|
},
|
|
57
|
-
|
|
54
|
+
optionValue: {
|
|
58
55
|
type: String,
|
|
59
56
|
},
|
|
57
|
+
options: {
|
|
58
|
+
type: Array,
|
|
59
|
+
required: true,
|
|
60
|
+
},
|
|
60
61
|
placeholder: {
|
|
61
62
|
type: String,
|
|
62
63
|
default: 'Select',
|
|
@@ -74,6 +75,9 @@ const props = defineProps({
|
|
|
74
75
|
default: 'md',
|
|
75
76
|
validator: (val) => ['sm', 'md', 'lg'].includes(val),
|
|
76
77
|
},
|
|
78
|
+
toolTipText: {
|
|
79
|
+
type: String,
|
|
80
|
+
},
|
|
77
81
|
useInput: {
|
|
78
82
|
type: Boolean,
|
|
79
83
|
required: false,
|
|
@@ -116,7 +120,7 @@ const handleKeydown = () => {
|
|
|
116
120
|
</script>
|
|
117
121
|
|
|
118
122
|
<template>
|
|
119
|
-
<section class="column q-gutter-y-xs">
|
|
123
|
+
<section class="column q-gutter-y-xs" :dataTestId="dataTestId">
|
|
120
124
|
<label class="row items-center" for="select">
|
|
121
125
|
<div class="u-select-label text-body-sm">
|
|
122
126
|
<span>{{ label }}</span>
|
|
@@ -143,6 +147,7 @@ const handleKeydown = () => {
|
|
|
143
147
|
v-model="model"
|
|
144
148
|
:class="`u-select field-${size}`"
|
|
145
149
|
:popup-content-class="`u-options-menu ${popupClass}`"
|
|
150
|
+
options-selected-class="primary bg-blue-1"
|
|
146
151
|
bottom-slots
|
|
147
152
|
:color="color"
|
|
148
153
|
emit-value
|
|
@@ -154,7 +159,6 @@ const handleKeydown = () => {
|
|
|
154
159
|
:option-label="optionLabel"
|
|
155
160
|
:option-value="optionValue"
|
|
156
161
|
:options="options"
|
|
157
|
-
options-selected-class="primary bg-blue-1"
|
|
158
162
|
outlined
|
|
159
163
|
:placeholder="placeholder"
|
|
160
164
|
:use-input="useInput"
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { onUnmounted, watch } from 'vue'
|
|
3
|
+
import UBtnStd from './UBtnStd.vue'
|
|
4
|
+
|
|
5
|
+
const emit = defineEmits(['onBackIconClick'])
|
|
6
|
+
const dialogs = defineModel('dialogs', { default: () => [], type: Array })
|
|
7
|
+
const props = defineProps({
|
|
8
|
+
closeIcon: {
|
|
9
|
+
default: 'fa-kit-duotone fa-circle-xmark',
|
|
10
|
+
type: String,
|
|
11
|
+
},
|
|
12
|
+
closeIconLabel: { type: String, default: 'close Icon' },
|
|
13
|
+
heading: {
|
|
14
|
+
default: 'Select Option',
|
|
15
|
+
type: String,
|
|
16
|
+
},
|
|
17
|
+
headingCaption: {
|
|
18
|
+
default: null,
|
|
19
|
+
type: String,
|
|
20
|
+
},
|
|
21
|
+
isLeftIcon: { type: Boolean, default: false },
|
|
22
|
+
leftIcon: { type: String, default: 'fa-kit-duotone fa-circle-arrow-left' },
|
|
23
|
+
leftIconLabel: { type: String, default: 'Back Icon' },
|
|
24
|
+
showActionButtons: {
|
|
25
|
+
default: false,
|
|
26
|
+
type: Boolean,
|
|
27
|
+
},
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
// constants
|
|
31
|
+
const MAX_HEIGHT = 750
|
|
32
|
+
const MIN_HEIGHT = 40
|
|
33
|
+
let isDragging = false
|
|
34
|
+
let startHeight = 0
|
|
35
|
+
let startY = 0
|
|
36
|
+
|
|
37
|
+
// custom functions
|
|
38
|
+
const getDialogTransitions = (position) => {
|
|
39
|
+
let defaultTransition = { show: 'slide-up', hide: 'slide-down' }
|
|
40
|
+
if (position === 'right') {
|
|
41
|
+
defaultTransition = { show: 'slide-left', hide: 'slide-right' }
|
|
42
|
+
} else if (position === 'left') {
|
|
43
|
+
defaultTransition = { show: 'slide-right', hide: 'slide-left' }
|
|
44
|
+
}
|
|
45
|
+
return defaultTransition
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const handleBackClick = () => {
|
|
49
|
+
return emit('onBackIconClick')
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const handleCloseDialog = (index) => {
|
|
53
|
+
setTimeout(() => {
|
|
54
|
+
if (dialogs.value[index]) {
|
|
55
|
+
dialogs.value[index].open = false
|
|
56
|
+
}
|
|
57
|
+
}, 100)
|
|
58
|
+
// removing closed dialog data from the dialogs
|
|
59
|
+
setTimeout(() => {
|
|
60
|
+
dialogs.value.splice(index, 1)
|
|
61
|
+
}, 500)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const onDragEnd = () => {
|
|
65
|
+
isDragging = false
|
|
66
|
+
window.removeEventListener('mousemove', onDragMove)
|
|
67
|
+
window.removeEventListener('mouseup', onDragEnd)
|
|
68
|
+
window.removeEventListener('touchmove', onDragMove)
|
|
69
|
+
window.removeEventListener('touchend', onDragEnd)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const onDragMove = (index, event) => {
|
|
73
|
+
if (!isDragging || index !== dialogs.value.length - 1) return
|
|
74
|
+
event.preventDefault()
|
|
75
|
+
const currentY = event.touches ? event.touches[0].clientY : event.clientY
|
|
76
|
+
const deltaY = startY - currentY
|
|
77
|
+
const newHeight = startHeight + deltaY
|
|
78
|
+
// limiting dialog height to MAX HEIGHT
|
|
79
|
+
dialogs.value[index].height = Math.min(
|
|
80
|
+
Math.max(MIN_HEIGHT, newHeight),
|
|
81
|
+
MAX_HEIGHT
|
|
82
|
+
)
|
|
83
|
+
if (Math.min(Math.max(MIN_HEIGHT, newHeight), MAX_HEIGHT) <= MIN_HEIGHT) {
|
|
84
|
+
setTimeout(() => {
|
|
85
|
+
dialogs.value.splice(index, 1) // if user is dragging then it should close from here
|
|
86
|
+
}, 200)
|
|
87
|
+
}
|
|
88
|
+
// dialogs.value[index].height = Math.max(MIN_HEIGHT, startHeight + deltaY) // if limiting not required
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const onMouseDown = (index, event) => {
|
|
92
|
+
if (index !== dialogs.value.length - 1) return // Only allow dragging for the topmost dialog
|
|
93
|
+
event.preventDefault()
|
|
94
|
+
isDragging = true
|
|
95
|
+
startY = event.clientY
|
|
96
|
+
startHeight = dialogs.value[index].height
|
|
97
|
+
window.addEventListener('mousemove', (e) => onDragMove(index, e))
|
|
98
|
+
window.addEventListener('mouseup', onDragEnd)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const onTouchStart = (index, event) => {
|
|
102
|
+
if (index !== dialogs.value.length - 1) return // Only allow dragging for the topmost dialog
|
|
103
|
+
event.preventDefault()
|
|
104
|
+
isDragging = true
|
|
105
|
+
startY = event.touches[0].clientY
|
|
106
|
+
startHeight = dialogs.value[index].height
|
|
107
|
+
window.addEventListener('touchmove', (e) => onDragMove(index, e))
|
|
108
|
+
window.addEventListener('touchend', onDragEnd)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
onUnmounted(() => {
|
|
112
|
+
window.removeEventListener('mousemove', onDragMove)
|
|
113
|
+
window.removeEventListener('mouseup', onDragEnd)
|
|
114
|
+
window.removeEventListener('touchmove', onDragMove)
|
|
115
|
+
window.removeEventListener('touchend', onDragEnd)
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
watch(
|
|
119
|
+
dialogs,
|
|
120
|
+
(newVal) => {
|
|
121
|
+
const len = newVal.length
|
|
122
|
+
if (len > 1) {
|
|
123
|
+
if (dialogs.value[len - 2]) {
|
|
124
|
+
dialogs.value[len - 1].height = dialogs.value[len - 2].height // opening same height of previous dialog
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
{ immediate: true }
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
watch(
|
|
132
|
+
dialogs, // to watch deep and for nested dialog
|
|
133
|
+
() => {
|
|
134
|
+
const index = dialogs.value.findIndex((dialog) => !dialog.open)
|
|
135
|
+
if (index > -1) {
|
|
136
|
+
handleCloseDialog(index)
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
{ immediate: true, deep: true }
|
|
140
|
+
)
|
|
141
|
+
</script>
|
|
142
|
+
|
|
143
|
+
<template>
|
|
144
|
+
<q-dialog
|
|
145
|
+
v-for="(dialog, key) in dialogs"
|
|
146
|
+
v-model="dialog.open"
|
|
147
|
+
:key="key"
|
|
148
|
+
:persistent="
|
|
149
|
+
typeof dialog.persistent === 'undefined' ? true : dialog.persistent
|
|
150
|
+
"
|
|
151
|
+
position="bottom"
|
|
152
|
+
:transition-duration="
|
|
153
|
+
dialog.transitionDuration ? dialog.transitionDuration : 300
|
|
154
|
+
"
|
|
155
|
+
:transition-hide="getDialogTransitions(dialog.position).hide"
|
|
156
|
+
:transition-show="getDialogTransitions(dialog.position).show"
|
|
157
|
+
>
|
|
158
|
+
<div>
|
|
159
|
+
<q-card
|
|
160
|
+
class="sheet-card-wrapper"
|
|
161
|
+
:style="{
|
|
162
|
+
height: dialog.height + 'px',
|
|
163
|
+
}"
|
|
164
|
+
>
|
|
165
|
+
<div
|
|
166
|
+
class="drag-handle-wrapper"
|
|
167
|
+
@mousedown="onMouseDown(key, $event)"
|
|
168
|
+
@touchstart="onTouchStart(key, $event)"
|
|
169
|
+
>
|
|
170
|
+
<div class="drag-handle" />
|
|
171
|
+
</div>
|
|
172
|
+
|
|
173
|
+
<q-card-section
|
|
174
|
+
class="row items-start justify-between no-wrap q-pt-none q-pb-xs q-px-ba"
|
|
175
|
+
>
|
|
176
|
+
<div class="heading-wrapper row">
|
|
177
|
+
<div
|
|
178
|
+
class="flex items-center justify-center dialog-heading-container"
|
|
179
|
+
>
|
|
180
|
+
<UBtnStd
|
|
181
|
+
v-if="isLeftIcon"
|
|
182
|
+
class="dialog-action-icons q-mr-xs"
|
|
183
|
+
:aria-label="leftIconLabel"
|
|
184
|
+
:flat="true"
|
|
185
|
+
tabindex="0"
|
|
186
|
+
@click="handleBackClick()"
|
|
187
|
+
>
|
|
188
|
+
<q-icon
|
|
189
|
+
:class="`icon-close ${leftIcon}`"
|
|
190
|
+
size="1.5rem"
|
|
191
|
+
tabindex="-1"
|
|
192
|
+
/>
|
|
193
|
+
</UBtnStd>
|
|
194
|
+
<div>
|
|
195
|
+
<div class="text-heading-xs">
|
|
196
|
+
{{ heading }}
|
|
197
|
+
</div>
|
|
198
|
+
<div>
|
|
199
|
+
<span
|
|
200
|
+
v-if="headingCaption"
|
|
201
|
+
class="text-body-sm dialog-caption"
|
|
202
|
+
>
|
|
203
|
+
{{ headingCaption }}
|
|
204
|
+
</span>
|
|
205
|
+
</div>
|
|
206
|
+
</div>
|
|
207
|
+
</div>
|
|
208
|
+
</div>
|
|
209
|
+
|
|
210
|
+
<UBtnStd
|
|
211
|
+
class="dialog-action-icons"
|
|
212
|
+
:aria-label="closeIconLabel"
|
|
213
|
+
:flat="true"
|
|
214
|
+
tabindex="0"
|
|
215
|
+
@click="handleCloseDialog(key)"
|
|
216
|
+
>
|
|
217
|
+
<q-icon
|
|
218
|
+
:class="`icon-close ${closeIcon} icon-secondary-opacity`"
|
|
219
|
+
size="1.5rem"
|
|
220
|
+
tabindex="-1"
|
|
221
|
+
/>
|
|
222
|
+
</UBtnStd>
|
|
223
|
+
</q-card-section>
|
|
224
|
+
<q-card-section
|
|
225
|
+
class="main-content-dialog scroll q-px-ba"
|
|
226
|
+
:style="{ height: dialog.height - 84 + 'px !important' }"
|
|
227
|
+
tabindex="-1"
|
|
228
|
+
>
|
|
229
|
+
<slot name="content"></slot>
|
|
230
|
+
</q-card-section>
|
|
231
|
+
</q-card>
|
|
232
|
+
<div
|
|
233
|
+
v-if="showActionButtons && dialog.height > 70"
|
|
234
|
+
class="action-wrapper"
|
|
235
|
+
>
|
|
236
|
+
<q-card-actions class="action-buttons q-px-sm" align="center">
|
|
237
|
+
<slot name="action_primary_one"></slot>
|
|
238
|
+
<slot name="action_primary_two"></slot>
|
|
239
|
+
</q-card-actions>
|
|
240
|
+
</div>
|
|
241
|
+
</div>
|
|
242
|
+
</q-dialog>
|
|
243
|
+
</template>
|
|
244
|
+
|
|
245
|
+
<style lang="sass">
|
|
246
|
+
.sheet-card-wrapper
|
|
247
|
+
position: relative
|
|
248
|
+
width: 100%
|
|
249
|
+
overflow: hidden
|
|
250
|
+
transition: height 0.02s ease-in-out
|
|
251
|
+
background: $neutral-1
|
|
252
|
+
border-radius: $sm $sm 0 0 !important
|
|
253
|
+
box-shadow: none !important
|
|
254
|
+
touch-action: none
|
|
255
|
+
|
|
256
|
+
.q-btn.dialog-action-icons
|
|
257
|
+
padding: 0px 0px !important
|
|
258
|
+
min-width: 1.5rem !important
|
|
259
|
+
min-height: 0px !important
|
|
260
|
+
height: fit-content !important
|
|
261
|
+
border-radius: 0px
|
|
262
|
+
|
|
263
|
+
&:focus
|
|
264
|
+
outline: auto !important
|
|
265
|
+
|
|
266
|
+
.q-focus-helper
|
|
267
|
+
background: transparent !important
|
|
268
|
+
|
|
269
|
+
.drag-handle-wrapper
|
|
270
|
+
width: 100%
|
|
271
|
+
height: 1rem
|
|
272
|
+
z-index: 9
|
|
273
|
+
display: flex
|
|
274
|
+
align-items: center
|
|
275
|
+
justify-content: center
|
|
276
|
+
|
|
277
|
+
.drag-handle
|
|
278
|
+
width: 2rem
|
|
279
|
+
height: 0.25rem
|
|
280
|
+
cursor: ns-resize
|
|
281
|
+
background: $neutral-5
|
|
282
|
+
border-radius: $xxl !important
|
|
283
|
+
|
|
284
|
+
.outer-wrapper
|
|
285
|
+
overflow: auto
|
|
286
|
+
|
|
287
|
+
.action-buttons
|
|
288
|
+
display: flex
|
|
289
|
+
align-items: center
|
|
290
|
+
gap: $xs
|
|
291
|
+
flex-wrap: nowrap
|
|
292
|
+
.q-btn
|
|
293
|
+
margin: 0 !important
|
|
294
|
+
width: 50%
|
|
295
|
+
|
|
296
|
+
.destructive-item
|
|
297
|
+
.q-item__section
|
|
298
|
+
color: red !important
|
|
299
|
+
|
|
300
|
+
.action-wrapper
|
|
301
|
+
background: $neutral-1
|
|
302
|
+
|
|
303
|
+
.main-content-dialog
|
|
304
|
+
margin-bottom: $ba
|
|
305
|
+
padding-bottom: 0
|
|
306
|
+
|
|
307
|
+
.dialog-caption
|
|
308
|
+
color: $neutral-9
|
|
309
|
+
|
|
310
|
+
.heading-wrapper
|
|
311
|
+
justify-content: space-between
|
|
312
|
+
flex-wrap: nowrap
|
|
313
|
+
margin-bottom: 0px !important
|
|
314
|
+
|
|
315
|
+
.dialog-heading-container
|
|
316
|
+
gap: $xs
|
|
317
|
+
</style>
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
const emit = defineEmits(['toggleDrawer'])
|
|
3
|
+
const props = defineProps({
|
|
4
|
+
menuOpen: {
|
|
5
|
+
type: Boolean,
|
|
6
|
+
default: true,
|
|
7
|
+
},
|
|
8
|
+
})
|
|
9
|
+
const toggleDrawer = () => {
|
|
10
|
+
emit('toggleDrawer')
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
console.log('menu', props.menuOpen)
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
<template>
|
|
17
|
+
<div class="menu-container q-ml-ba" @click="toggleDrawer">
|
|
18
|
+
<div class="bar top" :class="{ open: !menuOpen }" />
|
|
19
|
+
<div class="bar bottom" :class="{ open: !menuOpen }" />
|
|
20
|
+
</div>
|
|
21
|
+
</template>
|
|
22
|
+
|
|
23
|
+
<style lang="sass">
|
|
24
|
+
$bar-width: 1.25rem
|
|
25
|
+
$bar-height: 0.125rem
|
|
26
|
+
$tap-area: $md
|
|
27
|
+
$transition-speed: 0.2s
|
|
28
|
+
|
|
29
|
+
.menu-container
|
|
30
|
+
width: $tap-area
|
|
31
|
+
height: $tap-area
|
|
32
|
+
display: flex
|
|
33
|
+
justify-content: center
|
|
34
|
+
align-items: center
|
|
35
|
+
position: relative
|
|
36
|
+
cursor: pointer
|
|
37
|
+
|
|
38
|
+
.bar
|
|
39
|
+
width: $bar-width
|
|
40
|
+
height: $bar-height
|
|
41
|
+
background-color: black
|
|
42
|
+
position: absolute
|
|
43
|
+
transition: transform $transition-speed ease-in-out
|
|
44
|
+
|
|
45
|
+
&.top
|
|
46
|
+
top: 50%
|
|
47
|
+
transform: translateY(-4px)
|
|
48
|
+
|
|
49
|
+
&.bottom
|
|
50
|
+
top: 50%
|
|
51
|
+
transform: translateY(4px)
|
|
52
|
+
|
|
53
|
+
/* Morphing into X */
|
|
54
|
+
&.open
|
|
55
|
+
&.top
|
|
56
|
+
transform: translateY(0) rotate(-45deg)
|
|
57
|
+
|
|
58
|
+
&.bottom
|
|
59
|
+
transform: translateY(0) rotate(45deg)
|
|
60
|
+
</style>
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { computed } from 'vue'
|
|
3
|
+
import UBtnIcon from '../UBtnIcon.vue'
|
|
4
|
+
import UBtnStd from '../UBtnStd.vue'
|
|
5
|
+
import UCustomMenuIcon from './UCustomMenuIcon.vue'
|
|
6
|
+
import { useScreenType } from '../../../composables/useScreenType'
|
|
7
|
+
|
|
8
|
+
const emit = defineEmits(['navigateBack', 'toggleDrawer', 'onLogoClick'])
|
|
9
|
+
const props = defineProps({
|
|
10
|
+
dataTestId: {
|
|
11
|
+
type: String,
|
|
12
|
+
default: 'toolbar',
|
|
13
|
+
},
|
|
14
|
+
isMiniState: {
|
|
15
|
+
type: Boolean,
|
|
16
|
+
required: true,
|
|
17
|
+
},
|
|
18
|
+
isSubPage: {
|
|
19
|
+
type: Boolean,
|
|
20
|
+
required: true,
|
|
21
|
+
},
|
|
22
|
+
title: {
|
|
23
|
+
type: String,
|
|
24
|
+
required: true,
|
|
25
|
+
},
|
|
26
|
+
})
|
|
27
|
+
const $screen = useScreenType()
|
|
28
|
+
|
|
29
|
+
// Computed property for the title text
|
|
30
|
+
const pageTitle = computed(() => {
|
|
31
|
+
return props.isSubPage ? `Back to ${props.title} ` : props.title
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
// Function to handle the back navigation
|
|
35
|
+
const handleClick = () => {
|
|
36
|
+
emit('navigateBack')
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const onLogoClick = () => {
|
|
40
|
+
emit('onLogoClick')
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const toggleDrawer = () => {
|
|
44
|
+
emit('toggleDrawer')
|
|
45
|
+
}
|
|
46
|
+
</script>
|
|
47
|
+
|
|
48
|
+
<template>
|
|
49
|
+
<q-toolbar
|
|
50
|
+
v-if="$screen.isTablet"
|
|
51
|
+
class="u-header-toolbar-container"
|
|
52
|
+
:dataTestId="dataTestId"
|
|
53
|
+
>
|
|
54
|
+
<UCustomMenuIcon
|
|
55
|
+
aria-label="Menu icon"
|
|
56
|
+
:menuOpen="isMiniState"
|
|
57
|
+
tabindex="0"
|
|
58
|
+
@toggleDrawer="toggleDrawer"
|
|
59
|
+
/>
|
|
60
|
+
|
|
61
|
+
<section class="fit row justify-between items-center q-ml-xxs q-mr-ba">
|
|
62
|
+
<UBtnStd
|
|
63
|
+
class="q-pa-none"
|
|
64
|
+
aria-label="usssa logo"
|
|
65
|
+
flat
|
|
66
|
+
:ripple="false"
|
|
67
|
+
@click="onLogoClick"
|
|
68
|
+
>
|
|
69
|
+
<img
|
|
70
|
+
class="mini-state-logo full-logo"
|
|
71
|
+
alt="usssa-logo"
|
|
72
|
+
aria-label="usssa logo"
|
|
73
|
+
src="/images/logo.svg"
|
|
74
|
+
/>
|
|
75
|
+
</UBtnStd>
|
|
76
|
+
|
|
77
|
+
<!-- Action element container -->
|
|
78
|
+
<div class="u-header-toolbar-action-container">
|
|
79
|
+
<slot name="right_section" />
|
|
80
|
+
</div>
|
|
81
|
+
</section>
|
|
82
|
+
</q-toolbar>
|
|
83
|
+
|
|
84
|
+
<q-toolbar
|
|
85
|
+
v-if="$screen.isMobile"
|
|
86
|
+
class="u-header-toolbar-container"
|
|
87
|
+
:dataTestId="dataTestId"
|
|
88
|
+
>
|
|
89
|
+
<section class="fit row items-center q-mr-ba">
|
|
90
|
+
<UCustomMenuIcon
|
|
91
|
+
aria-label="Menu icon"
|
|
92
|
+
:menuOpen="isMiniState"
|
|
93
|
+
tabindex="0"
|
|
94
|
+
@toggleDrawer="toggleDrawer"
|
|
95
|
+
/>
|
|
96
|
+
|
|
97
|
+
<div class="logo-container-mb items-center justify-center">
|
|
98
|
+
<!-- Add logo click emitter -->
|
|
99
|
+
<UBtnStd
|
|
100
|
+
class="q-pa-none"
|
|
101
|
+
aria-label="usssa logo"
|
|
102
|
+
flat
|
|
103
|
+
:ripple="false"
|
|
104
|
+
size="sm"
|
|
105
|
+
@click="onLogoClick"
|
|
106
|
+
>
|
|
107
|
+
<img
|
|
108
|
+
class="mini-state-logo full-logo"
|
|
109
|
+
alt="usssa-logo"
|
|
110
|
+
aria-label="usssa logo"
|
|
111
|
+
src="/images/logo.svg"
|
|
112
|
+
/>
|
|
113
|
+
</UBtnStd>
|
|
114
|
+
</div>
|
|
115
|
+
|
|
116
|
+
<!-- Action element container -->
|
|
117
|
+
<div class="u-header-toolbar-action-container">
|
|
118
|
+
<slot name="right_section" />
|
|
119
|
+
</div>
|
|
120
|
+
</section>
|
|
121
|
+
</q-toolbar>
|
|
122
|
+
|
|
123
|
+
<q-toolbar
|
|
124
|
+
v-if="$screen.isDesktop"
|
|
125
|
+
class="u-header-toolbar-container"
|
|
126
|
+
:dataTestId="dataTestId"
|
|
127
|
+
>
|
|
128
|
+
<!-- Expand icon to open sidebar or drawer-->
|
|
129
|
+
<UBtnIcon
|
|
130
|
+
v-if="isMiniState"
|
|
131
|
+
class="q-ml-xxs"
|
|
132
|
+
ariaLabel="Sidebar expand icon"
|
|
133
|
+
color="primary"
|
|
134
|
+
dataTestId="expand-button"
|
|
135
|
+
iconClass="fa-kit-duotone fa-sidebar-expand"
|
|
136
|
+
size="md"
|
|
137
|
+
/>
|
|
138
|
+
|
|
139
|
+
<section class="fit row justify-between items-center q-ml-xs q-mr-ba">
|
|
140
|
+
<!-- Title container with dynamic title and optional back button -->
|
|
141
|
+
<UBtnStd
|
|
142
|
+
v-if="isSubPage"
|
|
143
|
+
class="back_to_button icon-secondary-opacity"
|
|
144
|
+
:aria-label="pageTitle"
|
|
145
|
+
color="primary"
|
|
146
|
+
dataTestId="back-button"
|
|
147
|
+
:flat="true"
|
|
148
|
+
:label="pageTitle"
|
|
149
|
+
leftIconSize="ms"
|
|
150
|
+
left-icon="fa-kit-duotone fa-circle-arrow-left"
|
|
151
|
+
tabindex="0"
|
|
152
|
+
@click="handleClick"
|
|
153
|
+
/>
|
|
154
|
+
<span
|
|
155
|
+
v-else
|
|
156
|
+
class="q-my-none text-heading-xxs q-ml-xxs"
|
|
157
|
+
dataTestId="toolbar-title"
|
|
158
|
+
tabindex="0"
|
|
159
|
+
>
|
|
160
|
+
{{ pageTitle }}
|
|
161
|
+
</span>
|
|
162
|
+
|
|
163
|
+
<!-- Action element container -->
|
|
164
|
+
<div class="u-header-toolbar-action-container">
|
|
165
|
+
<slot name="right_section" />
|
|
166
|
+
</div>
|
|
167
|
+
</section>
|
|
168
|
+
</q-toolbar>
|
|
169
|
+
</template>
|
|
170
|
+
|
|
171
|
+
<style lang="sass">
|
|
172
|
+
.u-header-toolbar-container
|
|
173
|
+
background-color: white
|
|
174
|
+
width: 100%
|
|
175
|
+
padding: 0px
|
|
176
|
+
display: flex
|
|
177
|
+
align-items: center
|
|
178
|
+
align-self: stretch
|
|
179
|
+
padding: $xs 0
|
|
180
|
+
|
|
181
|
+
.full-logo
|
|
182
|
+
width: 5.918rem
|
|
183
|
+
height: $md
|
|
184
|
+
margin-top: $xxs
|
|
185
|
+
|
|
186
|
+
.logo-container-mb
|
|
187
|
+
flex: 1
|
|
188
|
+
display: flex
|
|
189
|
+
|
|
190
|
+
.u-header-toolbar-inner-container
|
|
191
|
+
width: 100%
|
|
192
|
+
|
|
193
|
+
.u-header-toolbar-title-container
|
|
194
|
+
display: flex
|
|
195
|
+
align-items: center
|
|
196
|
+
gap: $xs
|
|
197
|
+
|
|
198
|
+
.u-header-toolbar-action-container
|
|
199
|
+
display: flex
|
|
200
|
+
align-items: center
|
|
201
|
+
gap: $sm
|
|
202
|
+
|
|
203
|
+
.back_to_button
|
|
204
|
+
.button-label
|
|
205
|
+
color: $dark !important
|
|
206
|
+
</style>
|
|
@@ -1,23 +1,27 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
-
import { computed, useSlots
|
|
2
|
+
import { computed, useSlots } from 'vue'
|
|
3
3
|
|
|
4
4
|
const props = defineProps({
|
|
5
|
-
|
|
5
|
+
anchor: {
|
|
6
6
|
type: String,
|
|
7
7
|
},
|
|
8
|
-
|
|
8
|
+
dataTestId: {
|
|
9
9
|
type: String,
|
|
10
|
-
|
|
10
|
+
default: 'tooltip-std',
|
|
11
11
|
},
|
|
12
|
-
|
|
12
|
+
description: {
|
|
13
13
|
type: String,
|
|
14
|
+
required: true,
|
|
14
15
|
},
|
|
15
|
-
|
|
16
|
+
icon: {
|
|
16
17
|
type: String,
|
|
17
18
|
},
|
|
18
19
|
offset: {
|
|
19
20
|
type: Array,
|
|
20
21
|
},
|
|
22
|
+
self: {
|
|
23
|
+
type: String,
|
|
24
|
+
},
|
|
21
25
|
target: {
|
|
22
26
|
type: String,
|
|
23
27
|
default: '',
|
|
@@ -40,17 +44,18 @@ const getTooltipText = computed(() => {
|
|
|
40
44
|
|
|
41
45
|
<template>
|
|
42
46
|
<q-tooltip
|
|
43
|
-
v-if="getTooltipText || slots.item"
|
|
44
47
|
v-bind="$attrs"
|
|
48
|
+
v-if="getTooltipText || slots.item"
|
|
45
49
|
class="u-tooltip shadow-2 bg-dark row"
|
|
46
50
|
:anchor="anchor"
|
|
51
|
+
:dataTestId="dataTestId"
|
|
47
52
|
:offset="offset"
|
|
48
53
|
:self="self"
|
|
49
54
|
:target="target"
|
|
50
55
|
>
|
|
51
56
|
<div class="row no-wrap tooltip-content">
|
|
52
57
|
<div v-if="icon" class="flex items-center">
|
|
53
|
-
<q-icon :class="icon" size="1rem"
|
|
58
|
+
<q-icon :class="icon" size="1rem" />
|
|
54
59
|
</div>
|
|
55
60
|
<div class="text-body-xs tooltip-text">{{ getTooltipText }}</div>
|
|
56
61
|
<slot name="item" />
|
package/src/components/index.js
CHANGED
|
@@ -23,19 +23,22 @@ import UMenuDropdownAdvancedSearch from './core/UMenuDropdownAdvancedSearch.vue'
|
|
|
23
23
|
import UMenuItem from './core/UMenuItem.vue'
|
|
24
24
|
import UMenuSearch from './core/UMenuSearch.vue'
|
|
25
25
|
import UMultiSelectStd from './core/UMultiSelectStd.vue'
|
|
26
|
+
import UPagination from './core/UPagination.vue'
|
|
26
27
|
import URadioBtn from './core/URadioBtn.vue'
|
|
27
28
|
import URadioStd from './core/URadioStd.vue'
|
|
28
29
|
import USelectStd from './core/USelectStd.vue'
|
|
30
|
+
import USheet from './core/USheet.vue'
|
|
29
31
|
import UTabBtnStd from './core/UTabBtnStd.vue'
|
|
30
32
|
import UTableStd from './core/UTableStd.vue'
|
|
31
33
|
import UTabsStd from './core/UTabsStd.vue'
|
|
32
34
|
import UToggleStd from './core/UToggleStd.vue'
|
|
33
|
-
import UToolbar from './core/UToolbar.vue'
|
|
35
|
+
import UToolbar from './core/UToolbar/UToolbar.vue'
|
|
34
36
|
import UTooltip from './core/UTooltip.vue'
|
|
35
37
|
import UUploader from './core/UUploader.vue'
|
|
36
38
|
|
|
37
39
|
import { useNotify } from '../composables/useNotify.js'
|
|
38
40
|
import { useOverlayLoader } from '../composables/useOverlayLoader.js'
|
|
41
|
+
import { useScreenType } from '../composables/useScreenType.js'
|
|
39
42
|
|
|
40
43
|
export {
|
|
41
44
|
UAvatar,
|
|
@@ -62,9 +65,11 @@ export {
|
|
|
62
65
|
UMenuItem,
|
|
63
66
|
UMenuSearch,
|
|
64
67
|
UMultiSelectStd,
|
|
68
|
+
UPagination,
|
|
65
69
|
URadioBtn,
|
|
66
70
|
URadioStd,
|
|
67
71
|
USelectStd,
|
|
72
|
+
USheet,
|
|
68
73
|
UTabBtnStd,
|
|
69
74
|
UTableStd,
|
|
70
75
|
UTabsStd,
|
|
@@ -74,4 +79,5 @@ export {
|
|
|
74
79
|
UUploader,
|
|
75
80
|
useNotify,
|
|
76
81
|
useOverlayLoader,
|
|
82
|
+
useScreenType,
|
|
77
83
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { computed, ref, watch } from 'vue'
|
|
2
|
+
import { useQuasar } from 'quasar'
|
|
3
|
+
|
|
4
|
+
export const useScreenType = () => {
|
|
5
|
+
const $q = useQuasar()
|
|
6
|
+
|
|
7
|
+
const getScreenType = () => {
|
|
8
|
+
if ($q.screen.xs) return 'mobile' // Extra small screens (phones)
|
|
9
|
+
if ($q.screen.sm) return 'tablet' // Small screens (tablets)
|
|
10
|
+
return 'desktop' // Default is desktop
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const screenType = ref(getScreenType())
|
|
14
|
+
|
|
15
|
+
const screen = computed(() => ({
|
|
16
|
+
isDesktop: screenType.value === 'desktop',
|
|
17
|
+
isMobile: screenType.value === 'mobile',
|
|
18
|
+
isTablet: screenType.value === 'tablet',
|
|
19
|
+
}))
|
|
20
|
+
|
|
21
|
+
// Watch for Quasar's screen changes and update `screenType`
|
|
22
|
+
watch(
|
|
23
|
+
() => $q.screen.name,
|
|
24
|
+
() => {
|
|
25
|
+
screenType.value = getScreenType()
|
|
26
|
+
}
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
return screen
|
|
30
|
+
}
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
<script setup>
|
|
2
|
-
import { computed } from 'vue'
|
|
3
|
-
import UBtnIcon from './UBtnIcon.vue'
|
|
4
|
-
import UBtnStd from './UBtnStd.vue'
|
|
5
|
-
|
|
6
|
-
const emit = defineEmits(['navigateBack'])
|
|
7
|
-
const props = defineProps({
|
|
8
|
-
dataTestId: {
|
|
9
|
-
type: String,
|
|
10
|
-
default: 'toolbar',
|
|
11
|
-
},
|
|
12
|
-
isMiniState: {
|
|
13
|
-
type: Boolean,
|
|
14
|
-
required: true,
|
|
15
|
-
},
|
|
16
|
-
isSubPage: {
|
|
17
|
-
type: Boolean,
|
|
18
|
-
required: true,
|
|
19
|
-
},
|
|
20
|
-
title: {
|
|
21
|
-
type: String,
|
|
22
|
-
required: true,
|
|
23
|
-
},
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
// Computed property for the title text
|
|
27
|
-
const pageTitle = computed(() => {
|
|
28
|
-
return props.isSubPage ? `Back to ${props.title} ` : props.title
|
|
29
|
-
})
|
|
30
|
-
|
|
31
|
-
// Function to handle the back navigation
|
|
32
|
-
const handleClick = () => {
|
|
33
|
-
emit('navigateBack')
|
|
34
|
-
}
|
|
35
|
-
</script>
|
|
36
|
-
|
|
37
|
-
<template>
|
|
38
|
-
<q-toolbar class="u-header-toolbar-container" :dataTestId="dataTestId">
|
|
39
|
-
<!-- Expand icon to open sidebar or drawer-->
|
|
40
|
-
<UBtnIcon
|
|
41
|
-
v-if="isMiniState"
|
|
42
|
-
class="q-ml-xxs"
|
|
43
|
-
ariaLabel="Sidebar expand icon"
|
|
44
|
-
color="primary"
|
|
45
|
-
dataTestId="expand-button"
|
|
46
|
-
iconClass="fa-kit-duotone fa-sidebar-shrink"
|
|
47
|
-
size="md"
|
|
48
|
-
/>
|
|
49
|
-
|
|
50
|
-
<section class="fit row justify-between items-center q-mx-ms">
|
|
51
|
-
<!-- Title container with dynamic title and optional back button -->
|
|
52
|
-
<UBtnStd
|
|
53
|
-
v-if="isSubPage"
|
|
54
|
-
class="back_to_button"
|
|
55
|
-
:aria-label="pageTitle"
|
|
56
|
-
color="primary"
|
|
57
|
-
dataTestId="back-button"
|
|
58
|
-
:flat="true"
|
|
59
|
-
:label="pageTitle"
|
|
60
|
-
left-icon="fa-kit-duotone fa-circle-arrow-left"
|
|
61
|
-
@click="handleClick"
|
|
62
|
-
/>
|
|
63
|
-
<span v-else class="q-my-none text-heading-sm" dataTestId="toolbar-title">
|
|
64
|
-
{{ pageTitle }}
|
|
65
|
-
</span>
|
|
66
|
-
|
|
67
|
-
<!-- Action element container -->
|
|
68
|
-
<div class="u-header-toolbar-action-container">
|
|
69
|
-
<slot name="right_section" />
|
|
70
|
-
</div>
|
|
71
|
-
</section>
|
|
72
|
-
</q-toolbar>
|
|
73
|
-
</template>
|
|
74
|
-
|
|
75
|
-
<style lang="sass">
|
|
76
|
-
.u-header-toolbar-container
|
|
77
|
-
background-color: white
|
|
78
|
-
width: 100%
|
|
79
|
-
padding: 0px
|
|
80
|
-
display: flex
|
|
81
|
-
align-items: center
|
|
82
|
-
align-self: stretch
|
|
83
|
-
padding: $sm 0
|
|
84
|
-
|
|
85
|
-
.u-header-toolbar-inner-container
|
|
86
|
-
width: 100%
|
|
87
|
-
|
|
88
|
-
.u-header-toolbar-title-container
|
|
89
|
-
display: flex
|
|
90
|
-
align-items: center
|
|
91
|
-
gap: $xs
|
|
92
|
-
|
|
93
|
-
.u-header-toolbar-action-container
|
|
94
|
-
display: flex
|
|
95
|
-
align-items: center
|
|
96
|
-
gap: $sm
|
|
97
|
-
|
|
98
|
-
.back_to_button
|
|
99
|
-
.button-label
|
|
100
|
-
color: $dark !important
|
|
101
|
-
</style>
|