@usssa/component-library 1.0.0-alpha.10 → 1.0.0-alpha.100

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