@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,280 @@
1
+ <script setup>
2
+ import UAvatar from './UAvatar.vue'
3
+ import UBtnIcon from './UBtnIcon.vue'
4
+ import UBtnStd from './UBtnStd.vue'
5
+
6
+ const emit = defineEmits(['update-country', 'onClick'])
7
+
8
+ const props = defineProps({
9
+ anchor: {
10
+ type: String,
11
+ },
12
+ ariaLabel: {
13
+ type: String,
14
+ },
15
+ avatarUrl: {
16
+ type: String,
17
+ },
18
+ color: {
19
+ type: String,
20
+ },
21
+ dataTestId: {
22
+ type: String,
23
+ default: 'menu-button',
24
+ },
25
+ displayName: {
26
+ type: String,
27
+ },
28
+ iconClass: {
29
+ type: String,
30
+ },
31
+ label: {
32
+ type: String,
33
+ },
34
+ menuOffset: {
35
+ type: Array,
36
+ default: () => [4, 4],
37
+ },
38
+ outline: {
39
+ type: Boolean,
40
+ default: true,
41
+ },
42
+ selectedCountry: {
43
+ type: Object,
44
+ },
45
+ self: {
46
+ type: String,
47
+ },
48
+ size: {
49
+ type: String,
50
+ default: 'md',
51
+ validator: (val) => ['sm', 'md', 'lg'].includes(val),
52
+ },
53
+ states: {
54
+ type: String,
55
+ default: 'Basic',
56
+ validator: (val) =>
57
+ ['Basic', 'Icon', 'Button', 'Avatar', 'Prefix'].includes(val),
58
+ },
59
+ tooltip: {
60
+ type: String,
61
+ },
62
+ })
63
+
64
+ const handleClick = () => {
65
+ return emit('onClick')
66
+ }
67
+ const toLowerCase = (str) => str.toLowerCase()
68
+ </script>
69
+
70
+ <template>
71
+ <!-- 1. Menu button Basic state -->
72
+ <q-btn-dropdown
73
+ v-if="states === 'Basic'"
74
+ :class="`u-mb-btn u-mb-basic size-${size}`"
75
+ :aria-label="label"
76
+ :color="color"
77
+ :dataTestId="dataTestId"
78
+ flat
79
+ :menu-offset="menuOffset"
80
+ no-caps
81
+ text-color="dark"
82
+ >
83
+ <template #label>
84
+ <q-icon v-if="iconClass" :class="iconClass" size="sm" />
85
+ <div class="text-body-md q-ml-xs label">{{ label }}</div>
86
+ </template>
87
+ <slot name="menu" />
88
+ </q-btn-dropdown>
89
+
90
+ <!-- 2. Menu button Icon state -->
91
+ <UBtnIcon
92
+ v-bind="$attrs"
93
+ v-if="states === 'Icon'"
94
+ class="u-mb-icon"
95
+ :anchor="anchor"
96
+ :ariaLabel="ariaLabel"
97
+ :color="color"
98
+ :dataTestId="dataTestId"
99
+ :iconClass="iconClass"
100
+ :offset="menuOffset"
101
+ ref="btn-icon"
102
+ :self="self"
103
+ :size="size"
104
+ :tooltip="tooltip"
105
+ @onClick="handleClick"
106
+ >
107
+ <template v-slot:menu>
108
+ <slot name="menu" />
109
+ </template>
110
+ </UBtnIcon>
111
+
112
+ <!-- 3. Menu button Button state -->
113
+ <UBtnStd
114
+ v-bind="$attrs"
115
+ v-if="states === 'Button'"
116
+ class="u-mb-btn"
117
+ :color="color"
118
+ :dataTestId="dataTestId"
119
+ :label="label"
120
+ :left-icon="iconClass"
121
+ :outline="outline"
122
+ :size="size"
123
+ >
124
+ <template v-slot:menu>
125
+ <slot name="menu" />
126
+ </template>
127
+ </UBtnStd>
128
+
129
+ <!-- 4. Menu button Avatar state -->
130
+ <q-btn-dropdown
131
+ v-if="states === 'Avatar'"
132
+ :class="`u-mb-avatar size-${size}`"
133
+ content-class="u-options-menu"
134
+ :color="color"
135
+ :dataTestId="dataTestId"
136
+ :menu-offset="menuOffset"
137
+ no-caps
138
+ rounded
139
+ text-color="black"
140
+ unelevated
141
+ >
142
+ <template #label>
143
+ <q-item class="account-drop-down">
144
+ <q-item-section class="q-pr-xs" avatar>
145
+ <UAvatar
146
+ v-if="avatarUrl"
147
+ :image="avatarUrl"
148
+ :name="displayName"
149
+ :round="true"
150
+ :showIndicator="false"
151
+ size="md"
152
+ />
153
+ <UAvatar
154
+ v-else
155
+ :name="displayName"
156
+ :round="true"
157
+ :showIndicator="false"
158
+ size="md"
159
+ />
160
+ </q-item-section>
161
+ <q-item-section v-if="displayName">
162
+ <q-item-label class="text-body-md text-dark">
163
+ {{ displayName }}
164
+ </q-item-label>
165
+ </q-item-section>
166
+ </q-item>
167
+ </template>
168
+ <slot name="menu" />
169
+ </q-btn-dropdown>
170
+
171
+ <!-- 5. Menu button Prefix state -->
172
+ <q-btn-dropdown
173
+ v-if="states === 'Prefix'"
174
+ :class="`u-prefix-dropdown text-body-sm btn-field-${size}`"
175
+ content-class="u-prefix-dropdown-list"
176
+ :dataTestId="dataTestId"
177
+ flat
178
+ menu-anchor="top right"
179
+ :menu-offset="menuOffset"
180
+ menu-self="bottom middle"
181
+ rounded
182
+ >
183
+ <template #label>
184
+ <q-icon
185
+ :class="`fi fi-${toLowerCase(selectedCountry.flag)} q-mr-xxs`"
186
+ :aria-label="selectedCountry.name"
187
+ left
188
+ />
189
+ <label class="selected-code"> {{ selectedCountry.code }}</label>
190
+ </template>
191
+ <slot name="menu" />
192
+ </q-btn-dropdown>
193
+ </template>
194
+
195
+ <style lang="sass">
196
+ .u-mb-basic
197
+ .q-icon
198
+ font-size: 1.875rem
199
+ .label
200
+ text-wrap: wrap
201
+ overflow-wrap: anywhere
202
+
203
+ .u-mb-avatar
204
+ padding: 0rem $xs
205
+ align-items: center
206
+ &:hover::before
207
+ background-color: $neutral-3
208
+ .account-drop-down
209
+ padding: 0
210
+ min-height: 0
211
+ .q-item__section--avatar
212
+ min-width: 0
213
+ .q-btn__content
214
+ .q-icon
215
+ width:1rem
216
+ height:1rem
217
+
218
+ .u-mb-icon
219
+ &:hover::before
220
+ background-color: $blue-1
221
+ &:focus
222
+ border: 1.5px solid $primary
223
+ background-color: $blue-1
224
+ box-shadow: 0px 0px 0px 2px $primary-transparent
225
+
226
+ .u-mb-btn
227
+ border-radius: $xs
228
+ min-width: 5.5rem !important
229
+ &.bg-neutral
230
+ background-color: $neutral-3
231
+ &.size-sm
232
+ min-height: $md
233
+ padding: $xs $sm !important
234
+ &.size-md
235
+ min-height: $lg
236
+ padding: $xs $ba !important
237
+ &.size-lg
238
+ min-height: $xl
239
+ padding: $xs $ba !important
240
+
241
+ .u-mb-avatar
242
+ &.size-sm
243
+ min-height: $md
244
+ &.size-md
245
+ min-height: $lg
246
+ &.size-lg
247
+ min-height: $xl
248
+
249
+ .u-prefix-dropdown
250
+ border-radius: $xs 0px 0px $xs
251
+ border: 1.5px solid $neutral-4
252
+ background: $neutral-2
253
+ &:hover
254
+ border: 1.5px solid $primary
255
+ background-color: $neutral-2
256
+ &:focus
257
+ border: 1.5px solid $primary
258
+ background-color: $neutral-2
259
+ box-shadow: 0px 0px 0px 2px $primary-transparent
260
+ &.q-btn
261
+ height: 2rem
262
+ min-height: 2rem
263
+ padding: 0px $xs
264
+ .selected-code
265
+ width: 2rem
266
+ &.btn-field-sm
267
+ height: $md
268
+ &.btn-field-md
269
+ height: $lg
270
+ &.btn-field-lg
271
+ height: $xl
272
+ .q-icon.on-left
273
+ width: 1rem
274
+ height: 0.655rem
275
+
276
+ .q-btn-dropdown__arrow
277
+ width: 1rem
278
+ height: 1rem
279
+ margin-left: $xxs
280
+ </style>
@@ -0,0 +1,80 @@
1
+ <script setup>
2
+ import UMenuItem from './UMenuItem.vue'
3
+
4
+ const props = defineProps({
5
+ data: {
6
+ type: Array,
7
+ },
8
+ dataTestId: {
9
+ type: String,
10
+ default: 'menu-dropdown',
11
+ },
12
+ iconClass: {
13
+ type: String,
14
+ },
15
+ menuClass: {
16
+ type: String,
17
+ },
18
+ selected: {
19
+ type: Boolean,
20
+ },
21
+ size: {
22
+ type: String,
23
+ default: 'md',
24
+ validator: (val) => ['sm', 'md', 'lg'].includes(val),
25
+ },
26
+ })
27
+ </script>
28
+
29
+ <template>
30
+ <q-list
31
+ :class="`u-menu-dropdown size-${size} ${menuClass} q-gutter-y-xxs`"
32
+ :dataTestId="dataTestId"
33
+ >
34
+ <template v-for="(item, index) in data" :key="index">
35
+ <UMenuItem
36
+ :iconClass="iconClass"
37
+ :destructive="item.destructive"
38
+ :disable="item.disable"
39
+ :hide="item.hide"
40
+ :index="index"
41
+ :label="item.label"
42
+ :leftIcon="item.leftIcon"
43
+ :positive="item.positive"
44
+ :rightIcon="item.rightIcon"
45
+ @onClick="item.handler"
46
+ >
47
+ <template #leading_slot>
48
+ <slot name="leading_slot"></slot>
49
+ </template>
50
+ <template #trailing_slot>
51
+ <slot name="trailing_slot"></slot>
52
+ </template>
53
+ </UMenuItem>
54
+ </template>
55
+ </q-list>
56
+ </template>
57
+
58
+ <style lang="sass">
59
+ .u-menu-dropdown
60
+ width: 11.5rem
61
+ padding: $xxs
62
+ flex-direction: column
63
+ align-items: flex-start
64
+ gap: q-my-xxs
65
+ flex-shrink: 0
66
+ border-radius: $xs
67
+ background: $neutral-1
68
+ box-shadow: 0px 0px 4px 0px rgba(16, 17, 20, 0.08)
69
+ &.size-sm
70
+ min-width: 11.5rem
71
+ max-width: 11.5rem
72
+ &.size-md
73
+ min-width: 11.75rem
74
+ max-width: 15rem
75
+ &.size-lg
76
+ width: 18rem
77
+ .u-menu-link
78
+ &.q-item:last-child
79
+ margin-bottom: 0px
80
+ </style>
@@ -0,0 +1,293 @@
1
+ <script setup>
2
+ import UBtnStd from './UBtnStd.vue'
3
+ import UInputPhoneStd from './UInputPhoneStd.vue'
4
+ import UInputTextStd from './UInputTextStd.vue'
5
+ import UMultiSelectStd from './UMultiSelectStd.vue'
6
+ import USelectStd from './USelectStd.vue'
7
+ import { useScreenType } from '../../composables/useScreenType'
8
+
9
+ const props = defineProps({
10
+ disbaleApplyFilter: {
11
+ type: Boolean,
12
+ },
13
+ fields: {
14
+ type: Array,
15
+ },
16
+ labelIcon: {
17
+ type: String,
18
+ default: 'fa-kit-duotone fa-filter-search',
19
+ },
20
+ model: {
21
+ type: Object,
22
+ },
23
+ searchType: {
24
+ type: String,
25
+ },
26
+ showCustomMenu: {
27
+ type: Boolean,
28
+ default: false,
29
+ },
30
+ size: {
31
+ type: String,
32
+ default: 'md',
33
+ },
34
+ title: {
35
+ type: String,
36
+ default: 'Advanced search',
37
+ },
38
+ toggle: {
39
+ type: Boolean,
40
+ },
41
+ })
42
+
43
+ const emit = defineEmits([
44
+ 'updateModelVal',
45
+ 'updateCountry',
46
+ 'onClearAdvancedSearchFilter',
47
+ 'onApplyAdvancedSearchFilter',
48
+ 'updateAdvanceSearchToggle',
49
+ ])
50
+
51
+ const $screen = useScreenType()
52
+
53
+ const clearFields = () => {
54
+ emit('onClearAdvancedSearchFilter')
55
+ }
56
+
57
+ const getKeyValueByTitle = (label) => {
58
+ const model = props.model
59
+ const camelCaseKey = titleToCamelCase(label)
60
+ if (camelCaseKey in model) {
61
+ return model[camelCaseKey]
62
+ } else {
63
+ return ''
64
+ }
65
+ }
66
+
67
+ const onApply = () => {
68
+ emit('onApplyAdvancedSearchFilter')
69
+ }
70
+
71
+ const titleToCamelCase = (str) => {
72
+ return str
73
+ .split(' ')
74
+ .map((word, index) => {
75
+ if (index === 0) {
76
+ return word.toLowerCase()
77
+ } else {
78
+ return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()
79
+ }
80
+ })
81
+ .join('')
82
+ }
83
+
84
+ const updateCountry = (val, label) => {
85
+ emit('updateCountry', val, label)
86
+ }
87
+
88
+ const updateModelVal = (event, index) => {
89
+ emit('updateModelVal', event.trim(), index)
90
+ }
91
+
92
+ const updateToggle = (val) => {
93
+ emit('updateAdvanceSearchToggle', val)
94
+ }
95
+ </script>
96
+
97
+ <template>
98
+ <div>
99
+ <q-expansion-item
100
+ v-bind="$attrs"
101
+ :modelValue="toggle"
102
+ class="overflow-hidden u-expansion"
103
+ dense-toggle
104
+ header-class="bg-neutral-2"
105
+ :label="title"
106
+ :style="`width: ${size}`"
107
+ @update:modelValue="(val) => updateToggle(val)"
108
+ >
109
+ <template #header>
110
+ <div class="row items-center full-width">
111
+ <q-icon :class="`${labelIcon}`" color="neutral-9" size="1rem" />
112
+ <span class="q-ml-xs text-caption-sm text-neutral-13">
113
+ {{ title }}
114
+ </span>
115
+ </div>
116
+ </template>
117
+
118
+ <!-- Using slot for custom menu -->
119
+ <template v-if="showCustomMenu">
120
+ <slot name="custom-menu" />
121
+ </template>
122
+
123
+ <section v-else class="q-px-ba q-pb-ba bg-neutral-2">
124
+ <div class="row items-container">
125
+ <div
126
+ v-for="(item, index) in fields && fields.length ? fields : []"
127
+ :class="`${
128
+ size === 'sm'
129
+ ? 'full-width'
130
+ : `col-${item?.col || 12} ${
131
+ item?.col !== 12 ? 'half-width' : ''
132
+ }`
133
+ }`"
134
+ :key="index"
135
+ >
136
+ <UInputTextStd
137
+ v-if="item.inputType === 'Text'"
138
+ v-bind="item.props"
139
+ :modelValue="getKeyValueByTitle(item.label)"
140
+ :aria-label="item.label"
141
+ :hintText="item.hintText"
142
+ :label="item.label"
143
+ @update:modelValue="
144
+ updateModelVal($event, titleToCamelCase(item.label))
145
+ "
146
+ />
147
+ <USelectStd
148
+ v-if="item.inputType === 'Select'"
149
+ v-bind="item.props"
150
+ :modelValue="getKeyValueByTitle(item.label)"
151
+ :aria-label="item.label"
152
+ hintIcon=""
153
+ :hintText="item.hintText"
154
+ :label="item.label"
155
+ :options="item.options"
156
+ @update:modelValue="
157
+ updateModelVal($event, titleToCamelCase(item.label))
158
+ "
159
+ />
160
+ <UMultiSelectStd
161
+ v-if="item.inputType === 'Multiselect'"
162
+ v-bind="item.props"
163
+ :modelValue="getKeyValueByTitle(item.label)"
164
+ :aria-label="item.label"
165
+ :hintText="item.hintText"
166
+ :label="item.label"
167
+ :options="item.options"
168
+ @update:modelValue="
169
+ updateModelVal($event, titleToCamelCase(item.label))
170
+ "
171
+ />
172
+ <UInputPhoneStd
173
+ v-if="item.inputType === 'Phone'"
174
+ v-bind="item.props"
175
+ :modelValue="getKeyValueByTitle(item.label)"
176
+ :aria-label="item.label"
177
+ hintIcon=""
178
+ :hintText="item.hintText"
179
+ :label="item.label"
180
+ :options="item.options"
181
+ placeholder=""
182
+ :selected-country="model.selectedCountry"
183
+ :validationRules="[]"
184
+ @update-country="
185
+ updateCountry($event, titleToCamelCase(item.label))
186
+ "
187
+ @update:modelValue="
188
+ updateModelVal($event, titleToCamelCase(item.label))
189
+ "
190
+ />
191
+
192
+ <UInputTextStd
193
+ v-if="item.inputType === 'Date'"
194
+ v-bind="item.props"
195
+ :modelValue="getKeyValueByTitle(item.label)"
196
+ :aria-label="item.label"
197
+ :hintText="item.hintText"
198
+ :label="item.label"
199
+ outlined
200
+ parentClass="col"
201
+ @update:modelValue="
202
+ updateModelVal($event, titleToCamelCase(item.label))
203
+ "
204
+ >
205
+ <template v-slot:append>
206
+ <q-icon
207
+ class="fa-kit-duotone fa-calendar-range cursor-pointer icon-secondary-opacity"
208
+ aria-label="Birthday calendar"
209
+ color="neutral-9"
210
+ size="1rem"
211
+ tabindex="0"
212
+ >
213
+ <q-popup-proxy
214
+ cover
215
+ transition-hide="scale"
216
+ transition-show="scale"
217
+ >
218
+ <q-date
219
+ v-model="item.value"
220
+ v-bind="item.dateProps"
221
+ :modelValue="getKeyValueByTitle(item.label)"
222
+ mask="MM/DD/YYYY"
223
+ @update:modelValue="
224
+ updateModelVal($event, titleToCamelCase(item.label))
225
+ "
226
+ >
227
+ <div class="row items-center justify-end">
228
+ <q-btn
229
+ v-close-popup
230
+ color="primary"
231
+ flat
232
+ label="Close"
233
+ />
234
+ </div>
235
+ </q-date>
236
+ </q-popup-proxy>
237
+ </q-icon>
238
+ </template>
239
+ </UInputTextStd>
240
+ </div>
241
+ </div>
242
+
243
+ <!-- Action Buttons -->
244
+
245
+ <div class="action-wrapper q-mt-ba">
246
+ <UBtnStd
247
+ class="col"
248
+ color="primary"
249
+ flat
250
+ label="Clear All Fields"
251
+ leftIcon="fa-kit fa-rotate-left"
252
+ @onClick="clearFields"
253
+ />
254
+
255
+ <UBtnStd
256
+ class="col"
257
+ color="primary"
258
+ :disable="disbaleApplyFilter"
259
+ label="Apply"
260
+ @onClick="onApply"
261
+ />
262
+ </div>
263
+ </section>
264
+ </q-expansion-item>
265
+ </div>
266
+ </template>
267
+
268
+ <style lang="sass">
269
+ .u-expansion
270
+ border-radius: $xs
271
+ justify-content: space-between
272
+ align-items: center
273
+ align-self: stretch
274
+ .q-item
275
+ padding: $xs $xs $xs $ba
276
+ .q-item__section--side
277
+ padding-right: 0px
278
+ color: $neutral-9
279
+ .action-wrapper
280
+ display: flex
281
+ gap: $xs
282
+ background: $neutral-2 !important
283
+ .button-label
284
+ word-break: break-word
285
+ .q-card__actions
286
+ padding: 0px
287
+ margin: $ba 0px $ba 0px
288
+ .items-container
289
+ gap: $ba $xs
290
+ .half-width
291
+ flex: 1 1 calc(50% - 44px)
292
+ box-sizing: border-box
293
+ </style>