@usssa/component-library 1.0.0-alpha.27 → 1.0.0-alpha.271

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 (105) hide show
  1. package/README.md +8 -5
  2. package/package.json +30 -8
  3. package/src/assets/VS.svg +5 -0
  4. package/src/assets/fonts/CorneroRegular.woff +0 -0
  5. package/src/assets/fonts/CorneroRegular.woff2 +0 -0
  6. package/src/assets/logo.svg +19 -0
  7. package/src/assets/no-result.svg +25 -0
  8. package/src/assets/upload-illustration.svg +48 -0
  9. package/src/components/core/UAccordionSelect.vue +237 -0
  10. package/src/components/core/UAvatar.vue +90 -26
  11. package/src/components/core/UAvatarGroup.vue +62 -52
  12. package/src/components/core/UBadgeStd.vue +6 -1
  13. package/src/components/core/UBannerStd.vue +100 -31
  14. package/src/components/core/UBracket.vue +2181 -0
  15. package/src/components/core/UBreadCrumbs.vue +171 -0
  16. package/src/components/core/UBtnIcon.vue +106 -53
  17. package/src/components/core/UBtnStd.vue +38 -31
  18. package/src/components/core/UBtnToggle.vue +11 -6
  19. package/src/components/core/UCheckboxStd.vue +26 -20
  20. package/src/components/core/UChip.vue +107 -58
  21. package/src/components/core/UDate.vue +627 -0
  22. package/src/components/core/UDialogStd.vue +456 -58
  23. package/src/components/core/UDrawer/UDrawer.vue +479 -0
  24. package/src/components/core/UDrawer/UDrawerMenuItem.vue +130 -0
  25. package/src/components/core/UEventCard.vue +463 -0
  26. package/src/components/core/UExpansionStd.vue +380 -0
  27. package/src/components/core/UExpansionTableStd.vue +311 -0
  28. package/src/components/core/UFilter.vue +99 -0
  29. package/src/components/core/UGameObject.vue +478 -0
  30. package/src/components/core/UInnerLoader.vue +69 -0
  31. package/src/components/core/UInputAddressLookup.vue +535 -0
  32. package/src/components/core/UInputPhoneStd.vue +74 -67
  33. package/src/components/core/UInputTextStd.vue +99 -64
  34. package/src/components/core/UInputTypeahead.vue +44 -0
  35. package/src/components/core/UInputTypeaheadAdvanceSearch.vue +134 -0
  36. package/src/components/core/UMatchup.vue +404 -0
  37. package/src/components/core/UMenuButtonStd.vue +280 -0
  38. package/src/components/core/UMenuDropdown.vue +38 -33
  39. package/src/components/core/UMenuDropdownAdvancedSearch.vue +306 -0
  40. package/src/components/core/UMenuItem.vue +226 -0
  41. package/src/components/core/UMenuSearch.vue +73 -0
  42. package/src/components/core/UModal.vue +660 -0
  43. package/src/components/core/UMultiSelectStd.vue +521 -63
  44. package/src/components/core/UPagination.vue +76 -24
  45. package/src/components/core/URadioBtn.vue +66 -43
  46. package/src/components/core/URadioStd.vue +23 -14
  47. package/src/components/core/USelectStd.vue +441 -84
  48. package/src/components/core/USheet.vue +349 -0
  49. package/src/components/core/UStepper/UProgress.vue +157 -0
  50. package/src/components/core/UStepper/UStepper.vue +214 -0
  51. package/src/components/core/UTabBtnStd.vue +36 -22
  52. package/src/components/core/UTable/UTable.vue +2269 -57
  53. package/src/components/core/UTableStd.vue +1436 -286
  54. package/src/components/core/UTabsStd.vue +53 -23
  55. package/src/components/core/UToggleStd.vue +18 -13
  56. package/src/components/core/UToolbar/UCustomMenuIcon.vue +58 -0
  57. package/src/components/core/UToolbar/UToolbar.vue +226 -0
  58. package/src/components/core/UTooltip.vue +32 -10
  59. package/src/components/core/UTypeahead.vue +890 -0
  60. package/src/components/core/UUploader.vue +757 -0
  61. package/src/components/core/UVenueCard.vue +221 -0
  62. package/src/components/index.js +83 -30
  63. package/src/composables/useNotify.js +16 -16
  64. package/src/composables/useOverlayLoader.js +23 -0
  65. package/src/composables/useScreenType.js +30 -0
  66. package/src/css/app.sass +69 -36
  67. package/src/css/colors.sass +2 -0
  68. package/src/css/quasar.variables.sass +102 -70
  69. package/src/css/vars/colors.variables.sass +28 -41
  70. package/src/utils/bracket.json +1538 -0
  71. package/src/utils/data.ts +179 -0
  72. package/src/App.vue +0 -9
  73. package/src/boot/.gitkeep +0 -0
  74. package/src/components/core/UMenutem.vue +0 -130
  75. package/src/layouts/MainLayout.vue +0 -145
  76. package/src/pages/Avatar.vue +0 -77
  77. package/src/pages/AvatarGroup.vue +0 -139
  78. package/src/pages/BadgeStd.vue +0 -83
  79. package/src/pages/BannerPage.vue +0 -76
  80. package/src/pages/BtnIcon.vue +0 -120
  81. package/src/pages/BtnStd.vue +0 -126
  82. package/src/pages/BtnToggle.vue +0 -131
  83. package/src/pages/CheckBox.vue +0 -62
  84. package/src/pages/Chip.vue +0 -108
  85. package/src/pages/ComponentBase.vue +0 -54
  86. package/src/pages/Dialog.vue +0 -206
  87. package/src/pages/ErrorNotFound.vue +0 -11
  88. package/src/pages/IndexPage.vue +0 -11
  89. package/src/pages/InputPhone.vue +0 -152
  90. package/src/pages/InputText.vue +0 -140
  91. package/src/pages/MenuDropdown.vue +0 -79
  92. package/src/pages/MenuItem.vue +0 -68
  93. package/src/pages/MultiSelectStd.vue +0 -174
  94. package/src/pages/NotifyPage.vue +0 -109
  95. package/src/pages/Pagination.vue +0 -71
  96. package/src/pages/Radio.vue +0 -80
  97. package/src/pages/RadioBtn.vue +0 -104
  98. package/src/pages/SelectStd.vue +0 -160
  99. package/src/pages/TabButtonPage.vue +0 -126
  100. package/src/pages/TablePage.vue +0 -375
  101. package/src/pages/TabsPage.vue +0 -261
  102. package/src/pages/TogglePage.vue +0 -58
  103. package/src/pages/TooltipPage.vue +0 -125
  104. package/src/router/index.js +0 -34
  105. package/src/router/routes.js +0 -121
@@ -0,0 +1,535 @@
1
+ <script setup>
2
+ import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
3
+ import UInputTextStd from './UInputTextStd.vue'
4
+ import UTooltip from './UTooltip.vue'
5
+
6
+ const emit = defineEmits(['onRightIconClick', 'onUpdate', 'updateInputVal'])
7
+ const modelValue = defineModel()
8
+ defineOptions({
9
+ inheritAttrs: false,
10
+ })
11
+ const props = defineProps({
12
+ borderless: {
13
+ type: Boolean,
14
+ default: false,
15
+ },
16
+ dataTestId: {
17
+ type: String,
18
+ default: 'address-lookup',
19
+ },
20
+ disable: {
21
+ type: Boolean,
22
+ default: false,
23
+ },
24
+ error: {
25
+ type: Boolean,
26
+ },
27
+ errorMessage: {
28
+ type: String,
29
+ },
30
+ hintIcon: {
31
+ type: String,
32
+ },
33
+ hintText: {
34
+ type: String,
35
+ },
36
+ isRequired: {
37
+ type: Boolean,
38
+ default: false,
39
+ },
40
+ label: {
41
+ type: String,
42
+ },
43
+ leftBorderRadius: {
44
+ type: Boolean,
45
+ default: false,
46
+ },
47
+ leftIcon: {
48
+ type: String,
49
+ },
50
+ outlined: {
51
+ type: Boolean,
52
+ default: true,
53
+ },
54
+ parentClass: {
55
+ type: String,
56
+ },
57
+ placeholder: {
58
+ type: String,
59
+ },
60
+ readonly: {
61
+ type: Boolean,
62
+ default: false,
63
+ },
64
+ rightIcon: {
65
+ type: String,
66
+ },
67
+ rightIconAriaLabel: {
68
+ type: String,
69
+ },
70
+ selectedAddress: {
71
+ type: String,
72
+ default: '',
73
+ },
74
+ size: {
75
+ type: String,
76
+ default: 'md',
77
+ validator: (val) => ['sm', 'md', 'lg'].includes(val),
78
+ },
79
+ toolTipText: {
80
+ type: String,
81
+ },
82
+ validationRules: {
83
+ type: Array,
84
+ },
85
+ })
86
+
87
+ let sessionToken, autocompleteSuggestion
88
+
89
+ const inputRef = ref(null)
90
+ const menuWidth = ref(0)
91
+ const predictions = ref([])
92
+ const resultItem = ref(
93
+ props.selectedAddress?.length
94
+ ? { street_address: props.selectedAddress }
95
+ : modelValue.value?.length
96
+ ? { street_address: modelValue.value }
97
+ : {}
98
+ )
99
+ const resultsMenuRef = ref(null)
100
+ const resultsMenuShowing = ref(false)
101
+
102
+ const leftBorderRadius = computed(() => {
103
+ if (props.leftBorderRadius === true) {
104
+ return 'leftBorderRadius'
105
+ }
106
+ return ''
107
+ })
108
+
109
+ const handleUpdate = async (input) => {
110
+ // fetchAutocompleteSuggestions reference
111
+ // https://developers.google.com/maps/documentation/javascript/reference/autocomplete-data#AutocompleteRequest
112
+ const payload = {
113
+ input,
114
+ sessionToken,
115
+ language: 'en-US',
116
+ // locationRestriction: {
117
+ // west: 0,
118
+ // north: 0,
119
+ // east: 0,
120
+ // south: 0,
121
+ // }
122
+ // origin: { lat: 0, lng: 0 }
123
+ // region: 'us',
124
+ }
125
+
126
+ const { suggestions } =
127
+ await autocompleteSuggestion.fetchAutocompleteSuggestions(payload)
128
+
129
+ const result = []
130
+ for (let suggestion of suggestions) {
131
+ let prediction = suggestion.placePrediction.toPlace()
132
+ await prediction.fetchFields({
133
+ fields: [
134
+ 'addressComponents',
135
+ 'adrFormatAddress',
136
+ 'displayName',
137
+ 'formattedAddress',
138
+ 'googleMapsURI',
139
+ 'internationalPhoneNumber',
140
+ 'location',
141
+ 'nationalPhoneNumber',
142
+ 'websiteURI',
143
+ ],
144
+ })
145
+
146
+ const {
147
+ addressComponents,
148
+ adrFormatAddress,
149
+ displayName,
150
+ formattedAddress,
151
+ googleMapsURI,
152
+ internationalPhoneNumber,
153
+ location,
154
+ nationalPhoneNumber,
155
+ websiteURI,
156
+ } = prediction
157
+
158
+ const parsedAddressComponents = parseAddressComponents(addressComponents)
159
+ const finalResult = {
160
+ ...parsedAddressComponents,
161
+ adrFormatAddress,
162
+ coordinates: {
163
+ lat: location.lat(),
164
+ lng: location.lng(),
165
+ },
166
+ displayName,
167
+ formattedAddress,
168
+ googleMapsURI,
169
+ internationalPhoneNumber,
170
+ nationalPhoneNumber,
171
+ websiteURI,
172
+ }
173
+ result.push(finalResult)
174
+ }
175
+
176
+ predictions.value = result
177
+ }
178
+
179
+ const onClick = (item) => {
180
+ resultItem.value = item
181
+ resultsMenuRef.value.hide()
182
+ emit('onUpdate', item)
183
+ }
184
+
185
+ const onMenuShow = () => {
186
+ updateMenuWidth()
187
+ resultsMenuShowing.value = true
188
+ }
189
+
190
+ onMounted(async () => {
191
+ const { AutocompleteSessionToken, AutocompleteSuggestion } =
192
+ await google.maps.importLibrary('places')
193
+
194
+ sessionToken = new AutocompleteSessionToken()
195
+ autocompleteSuggestion = AutocompleteSuggestion
196
+ window.addEventListener('resize', updateMenuWidth)
197
+ })
198
+
199
+ const onResize = ({ width }) => {
200
+ resultsMenuShowing.value = false
201
+ updateMenuWidth()
202
+ }
203
+
204
+ onUnmounted(() => {
205
+ window.removeEventListener('resize', updateMenuWidth)
206
+ })
207
+
208
+ const parseAddressComponents = (addressComponents) => {
209
+ const address = {}
210
+ for (const component of addressComponents) {
211
+ const { types, longText, shortText } = component
212
+ if (types.includes('street_number')) address.street_number = longText
213
+ if (types.includes('route')) address.street = longText
214
+ if (types.includes('locality')) address.city = longText
215
+ if (types.includes('administrative_area_level_1')) address.state = shortText
216
+ if (types.includes('administrative_area_level_2')) address.county = longText
217
+ if (types.includes('country')) address.country = shortText
218
+ if (types.includes('postal_code')) address.postal_code = longText
219
+ if (types.includes('plus_code')) address.plus_code = longText
220
+ }
221
+ if (address.street && address.street_number)
222
+ address.street_address = `${address.street_number} ${address.street}`
223
+ if (address.street && !address.street_number)
224
+ address.street_address = address.street
225
+
226
+ return address
227
+ }
228
+
229
+ const updateInputVal = (val) => {
230
+ if (!val?.length) {
231
+ modelValue.value = ''
232
+ resultItem.value = {}
233
+ }
234
+ if (val?.length === 1) {
235
+ resultItem.value = {}
236
+ modelValue.value = val
237
+ nextTick(() => {
238
+ inputRef.value?.focus()
239
+ })
240
+ }
241
+ emit('updateInputVal', val)
242
+ }
243
+
244
+ const updateMenuWidth = () => {
245
+ const el =
246
+ inputRef.value?.$el.querySelector('.q-field__control') ||
247
+ inputRef.value?.$el
248
+ menuWidth.value = `${el?.offsetWidth || 0}px`
249
+ }
250
+
251
+ watch(modelValue, async (value) => {
252
+ if (value) {
253
+ if (!resultsMenuShowing.value && resultsMenuRef.value)
254
+ resultsMenuRef.value.show()
255
+ await handleUpdate(value)
256
+ } else {
257
+ if (resultsMenuShowing.value && resultsMenuRef.value)
258
+ resultsMenuRef.value.hide()
259
+ predictions.value = []
260
+ resultItem.value = {}
261
+ emit('onUpdate', {})
262
+ }
263
+ })
264
+
265
+ watch(
266
+ () => resultItem.value?.formattedAddress,
267
+ (value) => {
268
+ if (!value)
269
+ nextTick(() => {
270
+ inputRef.value?.focus()
271
+ })
272
+ }
273
+ )
274
+ </script>
275
+
276
+ <template>
277
+ <div
278
+ v-if="JSON.stringify(resultItem) === '{}'"
279
+ :class="`q-gutter-xs ${parentClass}`"
280
+ :dataTestId="dataTestId"
281
+ >
282
+ <label
283
+ v-if="label"
284
+ class="row items-center q-mb-xxs"
285
+ for="input"
286
+ role="label"
287
+ >
288
+ <div class="u-input-label text-body-sm">
289
+ <span>{{ label }}</span>
290
+ <span v-if="isRequired" class="text-red-5 text-body-sm q-mx-xs">
291
+ {{ '*' }}
292
+ </span>
293
+ </div>
294
+ <q-icon
295
+ v-if="toolTipText"
296
+ class="fa-kit-duotone fa-circle-info cursor-pointer"
297
+ :aria-label="toolTipText"
298
+ color="neutral-9"
299
+ size="1rem"
300
+ >
301
+ <UTooltip
302
+ anchor="top middle"
303
+ :description="toolTipText"
304
+ :offset="[0, 0]"
305
+ self="bottom middle"
306
+ />
307
+ </q-icon>
308
+ </label>
309
+ <div ref="inputWrapper">
310
+ <q-input
311
+ v-bind="$attrs"
312
+ v-model="modelValue"
313
+ :class="`u-input field-${size} ${leftBorderRadius}`"
314
+ :borderless="borderless"
315
+ :bottom-slots="!!hintText"
316
+ :debounce="500"
317
+ :disable="disable"
318
+ :error="error"
319
+ hide-bottom-space
320
+ id="input"
321
+ name="input"
322
+ :outlined="outlined"
323
+ :placeholder="placeholder"
324
+ :readonly="readonly"
325
+ ref="inputRef"
326
+ :rules="validationRules"
327
+ :standout="!outlined"
328
+ type="text"
329
+ @focus="onMenuShow"
330
+ @update:modelValue="updateInputVal($event)"
331
+ >
332
+ <!-- The 'fit' prop is used to ensure the menu matches the anchor's width for correct positioning,
333
+ while the manual width styling enforces a specific width for visual consistency. -->
334
+ <q-menu
335
+ v-model="resultsMenuShowing"
336
+ fit
337
+ no-focus
338
+ ref="resultsMenuRef"
339
+ :style="{ width: menuWidth }"
340
+ @hide="resultsMenuShowing = false"
341
+ @show="onMenuShow"
342
+ >
343
+ <q-list bordered>
344
+ <q-item
345
+ v-for="(p, i) of predictions"
346
+ clickable
347
+ :key="i"
348
+ @click="onClick(p)"
349
+ >
350
+ <q-item-section avatar>
351
+ <q-icon
352
+ class="fa-kit-duotone fa-location-dot"
353
+ color="primary"
354
+ />
355
+ </q-item-section>
356
+ <q-item-section>
357
+ <q-item-label>{{ p.displayName }}</q-item-label>
358
+ <q-item-label caption>
359
+ <span class="text-caption">
360
+ {{ p.formattedAddress }}
361
+ </span>
362
+ </q-item-label>
363
+ </q-item-section>
364
+ </q-item>
365
+ </q-list>
366
+ </q-menu>
367
+
368
+ <template v-if="leftIcon" #prepend>
369
+ <slot name="prepend"></slot>
370
+ <q-icon
371
+ v-if="!$slots.prepend"
372
+ :class="`slot-icon-size-${size} ${leftIcon}`"
373
+ />
374
+ </template>
375
+
376
+ <template v-if="hintText" #hint>
377
+ <div class="row items-center text-neutral-9 no-wrap">
378
+ <q-icon
379
+ v-if="hintIcon"
380
+ :class="hintIcon"
381
+ :aria-label="hintText"
382
+ size="1rem"
383
+ />
384
+ <div class="q-ml-xxs text-body-xs">{{ hintText }}</div>
385
+ </div>
386
+ </template>
387
+
388
+ <template #append>
389
+ <slot name="append">
390
+ <q-icon
391
+ v-if="rightIcon"
392
+ :class="`slot-icon-size-${size} ${rightIcon}`"
393
+ :aria-label="
394
+ rightIcon && rightIconAriaLabel
395
+ ? rightIconAriaLabel
396
+ : 'right input icon '
397
+ "
398
+ :tabindex="0"
399
+ @click="handleRightIconClick"
400
+ />
401
+ </slot>
402
+ </template>
403
+
404
+ <template v-slot:error>
405
+ <div v-if="errorMessage" class="row items-center no-wrap">
406
+ <q-icon
407
+ class="fa-kit-duotone fa-warning-octagon"
408
+ :aria-label="errorMessage"
409
+ size="1rem"
410
+ />
411
+ <div class="q-ml-xxs text-body-xs" role="validation error">
412
+ {{ errorMessage }}
413
+ </div>
414
+ </div>
415
+ </template>
416
+ </q-input>
417
+ <q-resize-observer @resize="onResize" />
418
+ </div>
419
+ </div>
420
+
421
+ <UInputTextStd
422
+ v-if="JSON.stringify(resultItem) !== '{}'"
423
+ v-model="resultItem.street_address"
424
+ :dataTestId="dataTestId"
425
+ :label="label"
426
+ :size="size"
427
+ @update:modelValue="updateInputVal($event)"
428
+ />
429
+ </template>
430
+
431
+ <style lang="sass">
432
+ .u-input
433
+ .q-field--with-bottom
434
+ padding-bottom: 0px
435
+ &.q-field--outlined.q-field--disabled .q-field__control
436
+ background: $neutral-3
437
+ &.leftBorderRadius
438
+ &.q-field--outlined .q-field__control
439
+ border-radius: 0px $xs $xs 0px
440
+ &.q-field--borderless
441
+ .q-field__control
442
+ border-radius: 0px $xs $xs 0px
443
+
444
+ .q-field__inner
445
+ border-radius: $xs
446
+
447
+ &.q-field--borderless
448
+ .q-field__control
449
+ padding: 0 $xs
450
+ background: $neutral-1
451
+ border-radius: $xs
452
+ &:hover
453
+ box-shadow : 0px 0px 0px 2px $primary-transparent
454
+
455
+ .q-field--standout .q-field__control
456
+ border-radius: $xs
457
+
458
+ .q-field__append.q-field__marginal.row.no-wrap.items-center.q-anchor--skip
459
+ display: none
460
+
461
+ .q-field__before,
462
+ .q-field__prepend
463
+ padding: 0 $xs
464
+ padding-left: 0
465
+
466
+ .q-field__after,
467
+ .q-field__append
468
+ padding-left: $xs
469
+
470
+ .q-icon
471
+ &.slot-icon-size-sm
472
+ font-size: $sm
473
+ &.slot-icon-size-md
474
+ font-size: $ba
475
+ &.slot-icon-size-lg
476
+ font-size: $ba
477
+
478
+ &.q-field--auto-height .q-field__control,
479
+ &.q-field--auto-height .q-field__native
480
+ min-height: $md
481
+
482
+ &.q-field--outlined .q-field__control
483
+ border-radius: $xs
484
+ padding: 0 $xs
485
+ background: $neutral-1
486
+
487
+ &::before
488
+ border:1.5px solid $neutral-4
489
+
490
+ &:hover::before
491
+ border:1.5px solid $primary
492
+
493
+ .q-field__control.relative-position.row.no-wrap.text-negative:focus-within
494
+ box-shadow: 0px 0px 0px 2px $accent-transparent
495
+
496
+ .q-field__control:focus-within
497
+ box-shadow : 0px 0px 0px 2px $primary-transparent
498
+
499
+ &.field-sm
500
+ .q-field__control,
501
+ .q-field__marginal
502
+ height: $md
503
+ &.q-field--outlined.q-field__control
504
+ padding: 0 $xs
505
+
506
+ &.q-field__prepend .q-field__marginal
507
+ padding: 0 $xs
508
+
509
+ &.field-md
510
+ .q-field__control,
511
+ .q-field__marginal
512
+ height: $lg
513
+ &.q-field--outlined.q-field__control
514
+ padding: 0 $xs
515
+
516
+ &.q-field__prepend.q-field__marginal
517
+ padding: 0 $xs
518
+ padding-left: 0
519
+
520
+ &.field-lg
521
+ .q-field__control,
522
+ .q-field__marginal
523
+ height: $xl
524
+ &.q-field--outlined .q-field__control
525
+ padding: 0 $sm
526
+ .q-field__prepend.q-field__marginal
527
+ padding-left: 0px
528
+
529
+ .q-field__bottom
530
+ padding: 0
531
+ align-items: center
532
+
533
+ .q-field__messages
534
+ margin-top: $xxs
535
+ </style>