@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
@@ -0,0 +1,349 @@
1
+ <script setup>
2
+ import { onUnmounted, watch } from 'vue'
3
+ import UBtnStd from './UBtnStd.vue'
4
+
5
+ const emit = defineEmits(['onBackIconClick', 'onCloseDialog'])
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
+ dialogClass: {
14
+ type: String,
15
+ },
16
+ closeIconLabel: {
17
+ type: String,
18
+ default: 'close Icon',
19
+ },
20
+ dataTestId: {
21
+ type: String,
22
+ default: 'sheet-std',
23
+ },
24
+ heading: {
25
+ default: 'Select Option',
26
+ type: String,
27
+ },
28
+ headingCaption: {
29
+ default: null,
30
+ type: String,
31
+ },
32
+ isLeftIcon: {
33
+ type: Boolean,
34
+ default: false,
35
+ },
36
+ leftIcon: {
37
+ type: String,
38
+ default: 'fa-kit-duotone fa-circle-arrow-left',
39
+ },
40
+ leftIconLabel: {
41
+ type: String,
42
+ default: 'Back Icon',
43
+ },
44
+ showActionButtons: {
45
+ default: false,
46
+ type: Boolean,
47
+ },
48
+ })
49
+
50
+ // constants
51
+
52
+ let isDragging = false
53
+ const MAX_HEIGHT = 750
54
+ const MIN_HEIGHT = 40
55
+ let startHeight = 0
56
+ let startY = 0
57
+
58
+ // custom functions
59
+ const getDialogTransitions = (position) => {
60
+ let defaultTransition = { show: 'slide-up', hide: 'slide-down' }
61
+ if (position === 'right') {
62
+ defaultTransition = { show: 'slide-left', hide: 'slide-right' }
63
+ } else if (position === 'left') {
64
+ defaultTransition = { show: 'slide-right', hide: 'slide-left' }
65
+ }
66
+ return defaultTransition
67
+ }
68
+
69
+ const handleBackClick = () => {
70
+ return emit('onBackIconClick')
71
+ }
72
+
73
+ const handleCloseDialog = (index) => {
74
+ setTimeout(() => {
75
+ if (dialogs.value[index]) {
76
+ dialogs.value[index].open = false
77
+ }
78
+ }, 100)
79
+ // removing closed dialog data from the dialogs
80
+ setTimeout(() => {
81
+ dialogs.value.splice(index, 1)
82
+ }, 500)
83
+ emit('onCloseDialog')
84
+ }
85
+
86
+ const onDragEnd = () => {
87
+ isDragging = false
88
+ window.removeEventListener('mousemove', onDragMove)
89
+ window.removeEventListener('mouseup', onDragEnd)
90
+ window.removeEventListener('touchmove', onDragMove)
91
+ window.removeEventListener('touchend', onDragEnd)
92
+ }
93
+
94
+ const onDragMove = (index, event) => {
95
+ if (!isDragging || index !== dialogs.value.length - 1) return
96
+ event.preventDefault()
97
+ const currentY = event.touches ? event.touches[0].clientY : event.clientY
98
+ const deltaY = startY - currentY
99
+ const newHeight = startHeight + deltaY
100
+ // limiting dialog height to MAX HEIGHT
101
+ dialogs.value[index].height = Math.min(
102
+ Math.max(MIN_HEIGHT, newHeight),
103
+ MAX_HEIGHT
104
+ )
105
+ if (Math.min(Math.max(MIN_HEIGHT, newHeight), MAX_HEIGHT) <= MIN_HEIGHT) {
106
+ setTimeout(() => {
107
+ dialogs.value.splice(index, 1) // if user is dragging then it should close from here
108
+ }, 200)
109
+ }
110
+ // dialogs.value[index].height = Math.max(MIN_HEIGHT, startHeight + deltaY) // if limiting not required
111
+ }
112
+
113
+ const onMouseDown = (index, event) => {
114
+ if (index !== dialogs.value.length - 1) return // Only allow dragging for the topmost dialog
115
+ event.preventDefault()
116
+ isDragging = true
117
+ startY = event.clientY
118
+ startHeight = dialogs.value[index].height
119
+ window.addEventListener('mousemove', (e) => onDragMove(index, e))
120
+ window.addEventListener('mouseup', onDragEnd)
121
+ }
122
+
123
+ const onTouchStart = (index, event) => {
124
+ if (index !== dialogs.value.length - 1) return // Only allow dragging for the topmost dialog
125
+ event.preventDefault()
126
+ isDragging = true
127
+ startY = event.touches[0].clientY
128
+ startHeight = dialogs.value[index].height
129
+ window.addEventListener('touchmove', (e) => onDragMove(index, e))
130
+ window.addEventListener('touchend', onDragEnd)
131
+ }
132
+
133
+ onUnmounted(() => {
134
+ window.removeEventListener('mousemove', onDragMove)
135
+ window.removeEventListener('mouseup', onDragEnd)
136
+ window.removeEventListener('touchmove', onDragMove)
137
+ window.removeEventListener('touchend', onDragEnd)
138
+ })
139
+
140
+ watch(
141
+ dialogs,
142
+ (newVal) => {
143
+ const len = newVal.length
144
+ if (len > 1) {
145
+ if (dialogs.value[len - 2]) {
146
+ dialogs.value[len - 1].height = dialogs.value[len - 2].height // opening same height of previous dialog
147
+ }
148
+ }
149
+ },
150
+ { immediate: true }
151
+ )
152
+
153
+ watch(
154
+ dialogs, // to watch deep and for nested dialog
155
+ () => {
156
+ const index = dialogs.value.findIndex((dialog) => !dialog.open)
157
+ if (index > -1) {
158
+ handleCloseDialog(index)
159
+ }
160
+ },
161
+ { immediate: true, deep: true }
162
+ )
163
+ </script>
164
+
165
+ <template>
166
+ <q-dialog
167
+ v-bind="$attrs"
168
+ v-for="(dialog, key) in dialogs"
169
+ v-model="dialog.open"
170
+ :class="dialogClass"
171
+ :dataTestId="dataTestId"
172
+ :key="key"
173
+ :persistent="
174
+ typeof dialog.persistent === 'undefined' ? true : dialog.persistent
175
+ "
176
+ position="bottom"
177
+ :transition-duration="
178
+ dialog.transitionDuration ? dialog.transitionDuration : 300
179
+ "
180
+ :transition-hide="getDialogTransitions(dialog.position).hide"
181
+ :transition-show="getDialogTransitions(dialog.position).show"
182
+ >
183
+ <q-card
184
+ class="sheet-card-wrapper"
185
+ :style="{
186
+ height: dialog.height + 'px',
187
+ }"
188
+ >
189
+ <div
190
+ class="drag-handle-wrapper"
191
+ @mousedown="onMouseDown(key, $event)"
192
+ @touchstart="onTouchStart(key, $event)"
193
+ >
194
+ <div class="drag-handle" />
195
+ </div>
196
+
197
+ <q-card-section class="column q-pt-none q-pb-xs q-px-ba q-mt-ba">
198
+ <div class="row items-start justify-between no-wrap heading-row">
199
+ <div class="heading-wrapper row">
200
+ <div
201
+ class="flex items-center justify-center dialog-heading-container"
202
+ >
203
+ <UBtnStd
204
+ v-if="isLeftIcon"
205
+ class="dialog-action-icons q-mr-xs"
206
+ :aria-label="leftIconLabel"
207
+ :flat="true"
208
+ tabindex="0"
209
+ @click="handleBackClick()"
210
+ >
211
+ <q-icon
212
+ :class="`icon-close ${leftIcon}`"
213
+ size="1.5rem"
214
+ tabindex="-1"
215
+ />
216
+ </UBtnStd>
217
+ <div>
218
+ <div class="text-heading-xs">
219
+ {{ heading }}
220
+ </div>
221
+ <div>
222
+ <span
223
+ v-if="headingCaption"
224
+ class="text-body-sm dialog-caption"
225
+ >
226
+ {{ headingCaption }}
227
+ </span>
228
+ </div>
229
+ </div>
230
+ </div>
231
+ </div>
232
+ <UBtnStd
233
+ class="dialog-action-icons"
234
+ :aria-label="closeIconLabel"
235
+ :flat="true"
236
+ tabindex="0"
237
+ @click="handleCloseDialog(key)"
238
+ >
239
+ <q-icon
240
+ :class="`icon-close ${closeIcon} icon-secondary-opacity`"
241
+ size="1.5rem"
242
+ tabindex="-1"
243
+ />
244
+ </UBtnStd>
245
+ </div>
246
+ <slot name="header"></slot>
247
+ </q-card-section>
248
+ <q-card-section class="main-content-dialog q-px-ba" tabindex="-1">
249
+ <slot name="content"></slot>
250
+ </q-card-section>
251
+ </q-card>
252
+ <div
253
+ v-if="showActionButtons && dialog.height > 70"
254
+ class="sheet-action-wrapper"
255
+ >
256
+ <q-card-actions
257
+ class="sheet-action-buttons q-px-sm q-py-ba"
258
+ align="center"
259
+ >
260
+ <slot name="action_primary_one"></slot>
261
+ <slot name="action_primary_two"></slot>
262
+ </q-card-actions>
263
+ </div>
264
+ </q-dialog>
265
+ </template>
266
+
267
+ <style lang="sass">
268
+ .sheet-card-wrapper
269
+ display: flex
270
+ flex-direction: column
271
+ position: relative
272
+ width: 100%
273
+ overflow: hidden !important
274
+ transition: height 0.02s ease-in-out
275
+ background: $neutral-1
276
+ border-radius: $sm $sm 0 0 !important
277
+ box-shadow: none !important
278
+ touch-action: none
279
+
280
+ .q-btn.dialog-action-icons
281
+ padding: 0px 0px !important
282
+ min-width: 1.5rem !important
283
+ min-height: 0px !important
284
+ height: fit-content !important
285
+ border-radius: 0px
286
+
287
+ &:focus
288
+ outline: auto !important
289
+
290
+ .q-focus-helper
291
+ background: transparent !important
292
+
293
+ .drag-handle-wrapper
294
+ width: 100%
295
+ height: 0.9rem !important
296
+ z-index: 9
297
+ display: flex
298
+ align-items: center
299
+ justify-content: center
300
+
301
+ .drag-handle
302
+ width: 2rem
303
+ height: 0.25rem
304
+ cursor: ns-resize
305
+ background: $neutral-5
306
+ border-radius: $xxl !important
307
+
308
+ .outer-wrapper
309
+ overflow: auto
310
+
311
+ .sheet-action-buttons
312
+ display: flex
313
+ align-items: center
314
+ gap: $xs
315
+ flex-wrap: nowrap
316
+ .q-btn
317
+ margin: 0 !important
318
+ width: 50%
319
+
320
+ .destructive-item
321
+ .q-item__section
322
+ color: red !important
323
+
324
+ .sheet-action-wrapper
325
+ background: $neutral-1
326
+
327
+ .main-content-dialog
328
+ margin-bottom: 0px !important
329
+ padding-bottom: 0
330
+ flex-grow: 1
331
+ overflow-y: auto !important
332
+ overflow-x: hidden
333
+
334
+ .dialog-caption
335
+ color: $neutral-9
336
+
337
+ .heading-wrapper
338
+ justify-content: space-between
339
+ flex-wrap: nowrap
340
+ margin-bottom: 0px !important
341
+
342
+ .dialog-heading-container
343
+ gap: $xs
344
+
345
+ .action-wrapper
346
+ position: relative
347
+ width: 100%
348
+ background: $neutral-1
349
+ </style>
@@ -1,78 +1,104 @@
1
1
  <script setup>
2
2
  import UBadgeStd from './UBadgeStd.vue'
3
3
 
4
+ const emit = defineEmits(['onTabClick'])
5
+
6
+ const selectedTab = defineModel('selectedTab', {
7
+ type: [String, Number],
8
+ default: null,
9
+ })
10
+
4
11
  const props = defineProps({
5
- size: {
6
- type: String,
7
- default: 'md',
8
- },
9
- icon: {
10
- type: String,
11
- default: '',
12
+ buttonTabsOptions: {
13
+ type: Array,
14
+ default: () => [],
12
15
  },
13
- label: {
16
+ dataTestId: {
14
17
  type: String,
15
- default: null,
18
+ default: 'tab-btn-std',
16
19
  },
17
- badgeLabel: {
20
+ size: {
18
21
  type: String,
19
- default: null,
22
+ default: 'md',
20
23
  },
21
- selectedTab: {
22
- type: [String, Number],
23
- default: null,
24
+ standard: {
25
+ type: Boolean,
26
+ default: false,
24
27
  },
25
28
  })
29
+
30
+ const handleTabClick = (value) => {
31
+ emit('onTabClick', value)
32
+ }
26
33
  </script>
27
34
 
28
35
  <template>
29
36
  <q-tabs
37
+ :active-class="`u-tab-active ${standard ? 'tab-standard' : ''}`"
38
+ class="u-tabs-outer"
39
+ :dataTestId="dataTestId"
30
40
  dense
31
41
  indicator-color="transparent"
32
42
  inline-label
33
43
  :model-value="selectedTab"
34
44
  no-caps
35
- class="u-tabs-outer"
36
- active-class="u-tab-active"
37
45
  >
38
- <q-tab
39
- :class="`u-tab-button text-caption-${size} u-tab-${size}`"
40
- :ripple="false"
41
- name="tab-button"
42
- v-if="icon"
43
- aria-label="tab-button"
44
- >
45
- <template v-slot:default>
46
- <q-icon aria-label="Tab button Icon" v-if="icon" :class="`${icon}`" />
47
- <p class="u-tab-label truncated-label left-icon-label">
48
- {{ label ? label : '' }}
49
- </p>
50
- <UBadgeStd
51
- v-if="badgeLabel"
52
- :label="badgeLabel"
53
- color="primary"
54
- :size="size === 'md' ? 'md' : ''"
55
- :class="`q-ml-xs ${size === 'sm' ? 'badge-small' : ''}`"
56
- />
57
- </template>
58
- </q-tab>
59
- <q-tab
60
- :class="`u-tab-button text-caption-${size} u-tab-${size}`"
61
- :ripple="false"
62
- name="tab-button"
63
- v-else
64
- >
65
- <template v-slot:default>
66
- <p class="u-tab-label truncated-label">{{ label ? label : '' }}</p>
67
- <UBadgeStd
68
- v-if="badgeLabel"
69
- :label="badgeLabel"
70
- color="primary"
71
- :size="size === 'md' ? 'md' : ''"
72
- :class="`q-ml-xs ${size === 'sm' ? 'badge-small' : ''}`"
73
- />
74
- </template>
75
- </q-tab>
46
+ <template v-for="(tabOption, key) in buttonTabsOptions" :key="tabOption.id">
47
+ <q-tab
48
+ v-if="tabOption.icon"
49
+ :class="`u-tab-button text-caption-${size} u-tab-${size} ${
50
+ key !== buttonTabsOptions.length - 1 ? 'q-mr-xs' : ''
51
+ }`"
52
+ :aria-label="tabOption.label"
53
+ :disable="tabOption.disable"
54
+ :name="tabOption.id"
55
+ :ripple="false"
56
+ @click="handleTabClick(tabOption.id)"
57
+ >
58
+ <template v-slot:default>
59
+ <q-icon
60
+ v-if="tabOption.icon"
61
+ :class="tabOption.icon"
62
+ :alt="tabOption.label"
63
+ :aria-label="tabOption.label"
64
+ />
65
+ <p class="u-tab-label truncated-label left-icon-label">
66
+ {{ tabOption.label ? tabOption.label : '' }}
67
+ </p>
68
+ <UBadgeStd
69
+ v-if="tabOption.badgeLabel"
70
+ :class="`q-ml-xs ${size === 'sm' ? 'badge-small' : ''}`"
71
+ color="primary"
72
+ :label="tabOption.badgeLabel"
73
+ :size="size === 'md' ? 'md' : ''"
74
+ />
75
+ </template>
76
+ </q-tab>
77
+ <q-tab
78
+ v-else
79
+ :class="`u-tab-button text-caption-${size} u-tab-${size} ${
80
+ key !== buttonTabsOptions.length - 1 ? 'q-mr-xs' : ''
81
+ }`"
82
+ :aria-label="tabOption.label"
83
+ :disable="tabOption.disable"
84
+ :name="tabOption.id"
85
+ :ripple="false"
86
+ @click="handleTabClick(tabOption.id)"
87
+ >
88
+ <template v-slot:default>
89
+ <p class="u-tab-label truncated-label">
90
+ {{ tabOption.label ? tabOption.label : '' }}
91
+ </p>
92
+ <UBadgeStd
93
+ v-if="tabOption.badgeLabel"
94
+ :class="`q-ml-xs ${size === 'sm' ? 'badge-small' : ''}`"
95
+ color="primary"
96
+ :label="tabOption.badgeLabel"
97
+ :size="size === 'md' ? 'md' : ''"
98
+ />
99
+ </template>
100
+ </q-tab>
101
+ </template>
76
102
  </q-tabs>
77
103
  </template>
78
104
 
@@ -113,10 +139,10 @@ const props = defineProps({
113
139
  margin: $xxs
114
140
 
115
141
  .q-tab__content
116
- padding: 0.25rem 0
142
+ padding: $xxs 0
117
143
 
118
144
  .u-tab-label
119
- font-size: 0.75rem
145
+ font-size: $sm
120
146
 
121
147
  .q-icon
122
148
  font-size: 1rem
@@ -125,10 +151,9 @@ const props = defineProps({
125
151
 
126
152
  .u-tab-md
127
153
  padding: 0 $ba
128
- margin: $xs
129
154
 
130
155
  .q-tab__content
131
- padding: 0.5rem 0
156
+ padding: $xs 0
132
157
 
133
158
  .u-tab-label
134
159
  font-size: 0.875rem
@@ -138,11 +163,14 @@ const props = defineProps({
138
163
  position: absolute
139
164
  left: -8px
140
165
 
141
-
142
166
  .u-tab-active
143
167
  background: $blue-1 !important
144
168
  color: $primary !important
145
169
 
170
+ .tab-standard
171
+ background: $primary !important
172
+ color: $neutral-1 !important
173
+
146
174
  .u-tab-badge-sm
147
175
  font-size: $xs
148
176
  font-weight: 500