@sbc-connect/nuxt-forms 0.0.0-test-ld-20260520212549

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 (92) hide show
  1. package/.env.example +14 -0
  2. package/CHANGELOG.md +394 -0
  3. package/LICENSE +28 -0
  4. package/README.md +57 -0
  5. package/app/components/Connect/Fieldset.vue +87 -0
  6. package/app/components/Connect/Form/Address/City.vue +20 -0
  7. package/app/components/Connect/Form/Address/Country.vue +51 -0
  8. package/app/components/Connect/Form/Address/DeliveryInstructions.vue +20 -0
  9. package/app/components/Connect/Form/Address/PostalCode.vue +48 -0
  10. package/app/components/Connect/Form/Address/Region.vue +62 -0
  11. package/app/components/Connect/Form/Address/Street.vue +64 -0
  12. package/app/components/Connect/Form/Address/StreetAdditional.vue +18 -0
  13. package/app/components/Connect/Form/Address/index.vue +116 -0
  14. package/app/components/Connect/Form/FieldWrapper.vue +52 -0
  15. package/app/components/Connect/Form/Input.vue +38 -0
  16. package/app/components/Connect/Form/Phone/CountryCode.vue +128 -0
  17. package/app/components/Connect/Form/Phone/CountryFlag.vue +14 -0
  18. package/app/components/Connect/Form/Phone/index.vue +2 -0
  19. package/app/components/Connect/Form/Textarea.vue +39 -0
  20. package/app/components/Connect/Layout/Form.vue +21 -0
  21. package/app/components/HelloWorld/Forms.vue +12 -0
  22. package/app/composables/useCanadaPost.ts +74 -0
  23. package/app/coverage/base.css +224 -0
  24. package/app/coverage/block-navigation.js +87 -0
  25. package/app/coverage/clover.xml +2803 -0
  26. package/app/coverage/components/Connect/Fieldset.vue.html +310 -0
  27. package/app/coverage/components/Connect/Form/Address/City.vue.html +145 -0
  28. package/app/coverage/components/Connect/Form/Address/Country.vue.html +238 -0
  29. package/app/coverage/components/Connect/Form/Address/DeliveryInstructions.vue.html +145 -0
  30. package/app/coverage/components/Connect/Form/Address/PostalCode.vue.html +199 -0
  31. package/app/coverage/components/Connect/Form/Address/Region.vue.html +271 -0
  32. package/app/coverage/components/Connect/Form/Address/Street.vue.html +277 -0
  33. package/app/coverage/components/Connect/Form/Address/StreetAdditional.vue.html +139 -0
  34. package/app/coverage/components/Connect/Form/Address/index.html +221 -0
  35. package/app/coverage/components/Connect/Form/Address/index.vue.html +433 -0
  36. package/app/coverage/components/Connect/Form/FieldWrapper.vue.html +211 -0
  37. package/app/coverage/components/Connect/Form/Input.vue.html +199 -0
  38. package/app/coverage/components/Connect/Form/Phone/CountryCode.vue.html +457 -0
  39. package/app/coverage/components/Connect/Form/Phone/CountryFlag.vue.html +127 -0
  40. package/app/coverage/components/Connect/Form/Phone/index.html +146 -0
  41. package/app/coverage/components/Connect/Form/Phone/index.vue.html +91 -0
  42. package/app/coverage/components/Connect/Form/Textarea.vue.html +196 -0
  43. package/app/coverage/components/Connect/Form/index.html +146 -0
  44. package/app/coverage/components/Connect/Layout/Form.vue.html +148 -0
  45. package/app/coverage/components/Connect/Layout/index.html +116 -0
  46. package/app/coverage/components/Connect/index.html +116 -0
  47. package/app/coverage/components/HelloWorld/Forms.vue.html +121 -0
  48. package/app/coverage/components/HelloWorld/index.html +116 -0
  49. package/app/coverage/composables/index.html +116 -0
  50. package/app/coverage/composables/useCanadaPost.ts.html +307 -0
  51. package/app/coverage/coverage-final.json +29 -0
  52. package/app/coverage/enums/canada-post-address-datalevel.ts.html +106 -0
  53. package/app/coverage/enums/index.html +116 -0
  54. package/app/coverage/favicon.png +0 -0
  55. package/app/coverage/index.html +296 -0
  56. package/app/coverage/interfaces/canada-post.ts.html +199 -0
  57. package/app/coverage/interfaces/index.html +131 -0
  58. package/app/coverage/interfaces/phone-country.ts.html +127 -0
  59. package/app/coverage/layouts/ConnectForm.vue.html +100 -0
  60. package/app/coverage/layouts/index.html +116 -0
  61. package/app/coverage/prettify.css +1 -0
  62. package/app/coverage/prettify.js +2 -0
  63. package/app/coverage/sort-arrow-sprite.png +0 -0
  64. package/app/coverage/sorter.js +210 -0
  65. package/app/coverage/types/connect-fieldset.ts.html +88 -0
  66. package/app/coverage/types/index.html +116 -0
  67. package/app/coverage/utils/formHelpers.ts.html +124 -0
  68. package/app/coverage/utils/index.html +146 -0
  69. package/app/coverage/utils/index.ts.html +88 -0
  70. package/app/coverage/utils/isoCountriesList.ts.html +6193 -0
  71. package/app/coverage/utils/zod-schemas/addresses.ts.html +559 -0
  72. package/app/coverage/utils/zod-schemas/index.html +131 -0
  73. package/app/coverage/utils/zod-schemas/index.ts.html +88 -0
  74. package/app/enums/canada-post-address-datalevel.ts +7 -0
  75. package/app/interfaces/canada-post.ts +38 -0
  76. package/app/interfaces/phone-country.ts +14 -0
  77. package/app/layouts/ConnectForm.vue +5 -0
  78. package/app/types/connect-fieldset.ts +1 -0
  79. package/app/types/forms-page-meta.d.ts +5 -0
  80. package/app/utils/formHelpers.ts +13 -0
  81. package/app/utils/index.ts +1 -0
  82. package/app/utils/isoCountriesList.ts +2048 -0
  83. package/app/utils/zod-schemas/addresses.ts +159 -0
  84. package/app/utils/zod-schemas/index.ts +1 -0
  85. package/i18n/locales/en-CA.ts +49 -0
  86. package/i18n/locales/fr-CA.ts +3 -0
  87. package/nuxt.config.ts +58 -0
  88. package/package.json +40 -0
  89. package/playwright-report/index.html +85 -0
  90. package/public/css/addresscomplete-2.50.min.css +11 -0
  91. package/public/js/addresscomplete-2.50.min.js +260 -0
  92. package/test-results/.last-run.json +4 -0
@@ -0,0 +1,20 @@
1
+ <script setup lang="ts">
2
+ defineProps<{
3
+ parentId: string
4
+ schemaPrefix: string
5
+ disabled?: boolean
6
+ }>()
7
+
8
+ const model = defineModel<string | undefined>({ required: true })
9
+ </script>
10
+
11
+ <template>
12
+ <ConnectFormTextarea
13
+ v-model="model"
14
+ :data-testid="`${parentId}-field-locationDescription`"
15
+ :input-id="`${parentId}-input-locationDescription`"
16
+ :name="schemaPrefix + '.locationDescription'"
17
+ :disabled
18
+ :label="$t('connect.label.deliveryInstructionsOpt')"
19
+ />
20
+ </template>
@@ -0,0 +1,48 @@
1
+ <script setup lang="ts">
2
+ defineProps<{
3
+ parentId: string
4
+ schemaPrefix: string
5
+ disabled?: boolean
6
+ country?: string
7
+ required?: boolean
8
+ }>()
9
+
10
+ const isOptionalPostalCodeCountry = (country?: string) => {
11
+ if (!country) {
12
+ return false
13
+ }
14
+
15
+ return isNoPostalCodeCountry(country)
16
+ }
17
+
18
+ const model = defineModel<string | undefined>({
19
+ set(value) {
20
+ if (value) {
21
+ return value.toUpperCase()
22
+ }
23
+ },
24
+ required: true
25
+ })
26
+ </script>
27
+
28
+ <template>
29
+ <ConnectFormInput
30
+ v-model="model"
31
+ :name="schemaPrefix + '.postalCode'"
32
+ :data-testid="`${parentId}-field-postalCode`"
33
+ :input-id="`${parentId}-input-postalCode`"
34
+ :disabled
35
+ :required="required && !isOptionalPostalCodeCountry(country)"
36
+ :label="country === 'US'
37
+ ? $t('connect.label.zipCode')
38
+ : isOptionalPostalCodeCountry(country)
39
+ ? $t('connect.label.postalCodeOpt')
40
+ : $t('connect.label.postalCode')
41
+ "
42
+ :mask="country === 'CA'
43
+ ? '*** ***'
44
+ : country === 'US'
45
+ ? '#####-####'
46
+ : undefined"
47
+ />
48
+ </template>
@@ -0,0 +1,62 @@
1
+ <script setup lang="ts">
2
+ const {
3
+ maxlength = '1000',
4
+ country
5
+ } = defineProps<{
6
+ parentId: string
7
+ country?: string
8
+ schemaPrefix: string
9
+ disabled?: boolean
10
+ maxlength?: string
11
+ required?: boolean
12
+ }>()
13
+
14
+ const model = defineModel<string | undefined>({ required: true })
15
+
16
+ const regions = computed(() => {
17
+ switch (country) {
18
+ case 'US':
19
+ return countrySubdivisions.us
20
+ case 'CA':
21
+ return countrySubdivisions.ca
22
+ default:
23
+ return []
24
+ }
25
+ })
26
+ </script>
27
+
28
+ <template>
29
+ <UFormField
30
+ :name="schemaPrefix + '.region'"
31
+ class="grow flex-1"
32
+ :data-testid="`${parentId}-field-region`"
33
+ >
34
+ <template #default="{ error }">
35
+ <ConnectSelect
36
+ v-if="country === 'US' || country === 'CA'"
37
+ :id="`${parentId}-input-region`"
38
+ v-model="model"
39
+ :label="country === 'CA' ? $t('connect.label.province') : $t('connect.label.state')"
40
+ :items="regions"
41
+ value-key="code"
42
+ label-key="name"
43
+ :required
44
+ :disabled
45
+ class="w-full grow"
46
+ />
47
+ <ConnectInput
48
+ v-else
49
+ :id="`${parentId}-input-region`"
50
+ v-model="model"
51
+ :data-testid="`${parentId}-input-region`"
52
+ :disabled
53
+ :label="$t('connect.label.regionOpt')"
54
+ :maxlength
55
+ />
56
+ <div
57
+ v-if="!$slots.help && !error"
58
+ class="h-4 mt-1"
59
+ />
60
+ </template>
61
+ </UFormField>
62
+ </template>
@@ -0,0 +1,64 @@
1
+ <script setup lang="ts">
2
+ const {
3
+ schemaPrefix,
4
+ helpText = 'none',
5
+ country,
6
+ disableAddressComplete,
7
+ parentId
8
+ } = defineProps<{
9
+ parentId: string
10
+ country?: string
11
+ schemaPrefix: string
12
+ disableAddressComplete?: boolean
13
+ helpText?: 'allow-po' | 'no-po' | 'none'
14
+ required?: boolean
15
+ }>()
16
+
17
+ const model = defineModel<string | undefined>({ required: true })
18
+
19
+ const emit = defineEmits<{
20
+ addressComplete: [value: ConnectAddress]
21
+ }>()
22
+
23
+ const { address: canadaPostAddress, enableAddressComplete, destroyAddressComplete } = useCanadaPost()
24
+
25
+ const addressComplete = (id: string) => {
26
+ if (!disableAddressComplete && country === 'CA') {
27
+ enableAddressComplete(id, country, false)
28
+ }
29
+ }
30
+
31
+ watch(canadaPostAddress, (newAddress) => {
32
+ emit('addressComplete', newAddress)
33
+ })
34
+
35
+ watch(
36
+ () => country,
37
+ (v) => {
38
+ if (v !== 'CA') {
39
+ destroyAddressComplete()
40
+ } else if (!disableAddressComplete) {
41
+ enableAddressComplete(`${parentId}-input-street`, v, false)
42
+ }
43
+ }
44
+ )
45
+ </script>
46
+
47
+ <template>
48
+ <ConnectFormInput
49
+ v-model="model"
50
+ :data-testid="`${parentId}-field-street`"
51
+ :input-id="`${parentId}-input-street`"
52
+ :name="schemaPrefix + '.street'"
53
+ :help="helpText === 'none'
54
+ ? undefined
55
+ : helpText === 'no-po'
56
+ ? $t('connect.text.addressCannotBePOBox')
57
+ : $t('connect.text.addressCanBePOBox')
58
+ "
59
+ :label="$t('connect.label.street')"
60
+ :required
61
+ @keypress.once="addressComplete(`${parentId}-input-street`)"
62
+ @click="addressComplete(`${parentId}-input-street`)"
63
+ />
64
+ </template>
@@ -0,0 +1,18 @@
1
+ <script setup lang="ts">
2
+ defineProps<{
3
+ parentId: string
4
+ schemaPrefix: string
5
+ }>()
6
+
7
+ const model = defineModel<string | undefined>({ required: true })
8
+ </script>
9
+
10
+ <template>
11
+ <ConnectFormInput
12
+ v-model="model"
13
+ :name="schemaPrefix + '.streetAdditional'"
14
+ :data-testid="`${parentId}-field-streetAdditional`"
15
+ :input-id="`${parentId}-input-streetAdditional`"
16
+ :label="$t('connect.label.streetAdditional')"
17
+ />
18
+ </template>
@@ -0,0 +1,116 @@
1
+ <script setup lang="ts">
2
+ const {
3
+ disabledFields,
4
+ excludedFields = ['streetName', 'streetNumber', 'unitNumber'],
5
+ schemaPrefix,
6
+ streetHelpText = 'none'
7
+ } = defineProps<{
8
+ id: string
9
+ schemaPrefix: string
10
+ disabledFields?: Array<keyof ConnectAddress>
11
+ excludedFields?: Array<keyof ConnectAddress>
12
+ disableAddressComplete?: boolean
13
+ streetHelpText?: 'allow-po' | 'no-po' | 'none'
14
+ required?: boolean
15
+ }>()
16
+
17
+ const emit = defineEmits<{
18
+ 'should-validate': []
19
+ }>()
20
+
21
+ const state = defineModel<Partial<ConnectAddress>>({ required: true })
22
+
23
+ async function populateAddressComplete(e: ConnectAddress) {
24
+ // get disabled/excluded fields
25
+ const disabledSet = new Set(disabledFields)
26
+ const excludedSet = new Set(excludedFields)
27
+
28
+ // get array of valid keys
29
+ const validKeys = (Object.keys(e) as Array<keyof ConnectAddress>).filter(key =>
30
+ !disabledSet.has(key) && !excludedSet.has(key)
31
+ )
32
+
33
+ // set state for each valid key
34
+ validKeys.forEach((key) => {
35
+ state.value[key] = e[key]
36
+ })
37
+
38
+ // wait for dom to populate inputs
39
+ await nextTick()
40
+ emit('should-validate')
41
+ }
42
+ </script>
43
+
44
+ <template>
45
+ <div class="space-y-2" :data-testid="id + '-container'">
46
+ <ConnectFormAddressCountry
47
+ v-if="!excludedFields.includes('country')"
48
+ v-model="state.country"
49
+ :parent-id="id"
50
+ :schema-prefix="schemaPrefix"
51
+ :disabled="disabledFields?.includes('country')"
52
+ :required
53
+ @change="state.region = ''"
54
+ />
55
+
56
+ <ConnectFormAddressStreet
57
+ v-if="!excludedFields.includes('street')"
58
+ v-model="state.street"
59
+ :parent-id="id"
60
+ :schema-prefix="schemaPrefix"
61
+ :country="state.country"
62
+ :disable-address-complete="disableAddressComplete"
63
+ :disabled="disabledFields?.includes('street')"
64
+ :help-text="streetHelpText"
65
+ :required
66
+ @address-complete="populateAddressComplete"
67
+ />
68
+
69
+ <ConnectFormAddressStreetAdditional
70
+ v-if="!excludedFields.includes('streetAdditional')"
71
+ v-model="state.streetAdditional"
72
+ :parent-id="id"
73
+ :schema-prefix="schemaPrefix"
74
+ :disabled="disabledFields?.includes('streetAdditional')"
75
+ />
76
+
77
+ <div class="flex flex-col gap-2 sm:gap-4 sm:flex-row">
78
+ <ConnectFormAddressCity
79
+ v-if="!excludedFields.includes('city')"
80
+ v-model="state.city"
81
+ :parent-id="id"
82
+ :schema-prefix="schemaPrefix"
83
+ :disabled="disabledFields?.includes('city')"
84
+ :required
85
+ />
86
+
87
+ <ConnectFormAddressRegion
88
+ v-if="!excludedFields.includes('region')"
89
+ v-model="state.region"
90
+ :parent-id="id"
91
+ :schema-prefix="schemaPrefix"
92
+ :country="state.country"
93
+ :disabled="disabledFields?.includes('region')"
94
+ :required
95
+ />
96
+
97
+ <ConnectFormAddressPostalCode
98
+ v-if="!excludedFields.includes('postalCode')"
99
+ v-model="state.postalCode"
100
+ :parent-id="id"
101
+ :schema-prefix="schemaPrefix"
102
+ :country="state.country"
103
+ :disabled="disabledFields?.includes('postalCode')"
104
+ :required
105
+ />
106
+ </div>
107
+
108
+ <ConnectFormAddressDeliveryInstructions
109
+ v-if="!excludedFields.includes('locationDescription')"
110
+ v-model="state.locationDescription"
111
+ :parent-id="id"
112
+ :schema-prefix="schemaPrefix"
113
+ :disabled="disabledFields?.includes('locationDescription')"
114
+ />
115
+ </div>
116
+ </template>
@@ -0,0 +1,52 @@
1
+ <script setup lang="ts">
2
+ import type { FormError } from '@nuxt/ui'
3
+
4
+ const {
5
+ orientation = 'horizontal',
6
+ paddingClass = 'x-default',
7
+ detailsAriaHidden = false
8
+ } = defineProps<{
9
+ label: string
10
+ error?: FormError | boolean
11
+ detailsAriaHidden?: boolean
12
+ showErrorMsg?: boolean
13
+ orientation?: 'vertical' | 'horizontal'
14
+ paddingClass?: 'x-default' | 'xy-default' | string
15
+ }>()
16
+
17
+ const padding = paddingClass === 'x-default'
18
+ ? 'padding-x-default'
19
+ : paddingClass === 'xy-default'
20
+ ? 'padding-xy-default'
21
+ : paddingClass
22
+ </script>
23
+
24
+ <template>
25
+ <div
26
+ :class="[
27
+ 'flex gap-4 sm:gap-6',
28
+ padding,
29
+ orientation === 'horizontal' ? 'flex-col sm:flex-row' : 'flex-col',
30
+ error ? 'shadow-section-error' : '',
31
+ ]"
32
+ >
33
+ <span
34
+ :aria-hidden="detailsAriaHidden"
35
+ class="text-base text-neutral-highlighted font-bold"
36
+ :class="{ 'w-full sm:basis-1/4': orientation === 'horizontal' }"
37
+ >
38
+ <div class="flex flex-col gap-1">
39
+ <span>{{ label }}</span>
40
+ <span
41
+ v-if="error && typeof error === 'object' && 'message' in error && showErrorMsg"
42
+ class="font-normal text-error"
43
+ >
44
+ {{ error.message }}
45
+ </span>
46
+ </div>
47
+ </span>
48
+ <div class="flex-1">
49
+ <slot />
50
+ </div>
51
+ </div>
52
+ </template>
@@ -0,0 +1,38 @@
1
+ <script setup lang="ts">
2
+ defineProps<{
3
+ name: string
4
+ label: string
5
+ inputId: string
6
+ required?: boolean
7
+ autofocus?: boolean
8
+ mask?: string
9
+ disabled?: boolean
10
+ help?: string
11
+ }>()
12
+
13
+ const model = defineModel<string | number | bigint | null | undefined>({ required: true })
14
+ </script>
15
+
16
+ <template>
17
+ <UFormField
18
+ :name
19
+ :help
20
+ class="grow flex-1"
21
+ >
22
+ <template #default="{ error }">
23
+ <ConnectInput
24
+ :id="inputId"
25
+ v-model="model"
26
+ :mask
27
+ :aria-required="required"
28
+ :label
29
+ :autofocus
30
+ :disabled
31
+ />
32
+ <div
33
+ v-if="!help && !error"
34
+ class="h-4 mt-1"
35
+ />
36
+ </template>
37
+ </UFormField>
38
+ </template>
@@ -0,0 +1,128 @@
1
+ <script setup lang="ts">
2
+ import countryList from 'country-codes-list'
3
+ import CountryFlag from '#forms/app/components/Connect/Form/Phone/CountryFlag.vue'
4
+ import type { PhoneCountry } from '#forms/app/interfaces/phone-country'
5
+
6
+ defineProps<{
7
+ isInvalid: boolean | undefined
8
+ }>()
9
+
10
+ const countryCallingCode = defineModel<string | undefined>('countryCallingCode', { required: false })
11
+ watch(countryCallingCode, (val) => {
12
+ // this is needed for when something outside this component changes the callingCode model value
13
+ if (!val) {
14
+ countryIso2.value = undefined
15
+ } else if (selectedCountry.value?.callingCode !== val) {
16
+ countryIso2.value = search(val)[0]?.iso2
17
+ }
18
+ })
19
+
20
+ const countryIso2 = defineModel<string | undefined>('countryIso2', { required: false })
21
+ watch(countryIso2, (val) => {
22
+ if (!val) {
23
+ selectedCountry.value = undefined
24
+ } else if (val && selectedCountry.value?.iso2 !== val) {
25
+ selectCountry(val)
26
+ }
27
+ })
28
+
29
+ const selectedCountry = ref<PhoneCountry | undefined>(undefined)
30
+ watch(selectedCountry, (newVal) => {
31
+ if (newVal?.callingCode !== countryCallingCode.value) {
32
+ countryCallingCode.value = newVal?.callingCode
33
+ }
34
+ if (newVal?.iso2 !== countryIso2.value) {
35
+ countryIso2.value = newVal?.iso2
36
+ }
37
+ })
38
+
39
+ const _countryListOptions = countryList.customList(
40
+ 'countryCode', '{countryCallingCode},{countryNameEn},{countryNameLocal}')
41
+
42
+ const manualInput = (event: Event) => {
43
+ const target = event.target as HTMLInputElement
44
+ selectedCountry.value = {
45
+ callingCode: target.value
46
+ }
47
+ }
48
+
49
+ const countryListOptions: Array<PhoneCountry> = Object.keys(_countryListOptions).map((key) => {
50
+ const parts = (_countryListOptions[key] ?? '').split(',')
51
+ const callingCode = parts[0] ?? ''
52
+ const nameEn = parts[1]
53
+ const nameLocal = parts[2]
54
+ return {
55
+ iso2: key,
56
+ callingCode,
57
+ label: `+${callingCode}`,
58
+ nameLocal,
59
+ nameEn
60
+ }
61
+ }).sort((a, b) => a.callingCode.localeCompare(b.callingCode))
62
+
63
+ const search = (q: string) => countryListOptions.filter((lo) => {
64
+ return lo.callingCode.includes(q)
65
+ || lo.iso2?.includes(q)
66
+ || lo.nameLocal?.includes(q)
67
+ || lo.nameEn?.includes(q)
68
+ || lo.label?.includes(q)
69
+ })
70
+
71
+ const selectCountry = (iso2: string) => {
72
+ selectedCountry.value = countryListOptions.find(item => item.iso2 === iso2)
73
+ }
74
+
75
+ onMounted(() => {
76
+ if (countryIso2.value !== undefined) {
77
+ selectCountry(countryIso2.value)
78
+ } else if (countryCallingCode.value) {
79
+ // Set a country based on the calling code if available
80
+ const iso2 = search(countryCallingCode.value)[0]?.iso2
81
+ if (iso2) {
82
+ selectCountry(iso2)
83
+ } else {
84
+ selectedCountry.value = {
85
+ callingCode: countryCallingCode.value,
86
+ label: `+${countryCallingCode.value}`
87
+ }
88
+ }
89
+ }
90
+ })
91
+ </script>
92
+
93
+ <template>
94
+ <UInputMenu
95
+ v-model="selectedCountry"
96
+ :items="countryListOptions"
97
+ :color="selectedCountry?.callingCode ? 'primary' : undefined"
98
+ :search="search"
99
+ :label-key="undefined"
100
+ :trailing-icon="'i-mdi-chevron-down'"
101
+ class="cursor-pointer"
102
+ :aria-required="true"
103
+ :aria-invalid="isInvalid"
104
+ :aria-label="$t('connect.label.countryCode')"
105
+ @input="manualInput($event)"
106
+ >
107
+ <template v-if="!!selectedCountry?.iso2" #leading="{ modelValue }">
108
+ <div class="flex">
109
+ <CountryFlag
110
+ :tooltip-text="selectedCountry?.nameEn"
111
+ :country-code-iso2letter="selectedCountry?.iso2"
112
+ />
113
+ <span class="ml-2 mt-2 truncate">{{ (modelValue as PhoneCountry)?.label }}</span>
114
+ </div>
115
+ </template>
116
+
117
+ <template #item="{ item }">
118
+ <div v-if="item" class="flex items-end cursor-pointer">
119
+ <CountryFlag
120
+ :tooltip-text="(item as PhoneCountry).nameLocal"
121
+ :country-code-iso2letter="(item as PhoneCountry).iso2 ?? ''"
122
+ />
123
+ <span class="ml-2 truncate">{{ (item as PhoneCountry).label }}</span>
124
+ <span class="sr-only">{{ (item as PhoneCountry).nameLocal }}</span>
125
+ </div>
126
+ </template>
127
+ </UInputMenu>
128
+ </template>
@@ -0,0 +1,14 @@
1
+ <script setup lang="ts">
2
+ import CountryFlag from 'vue-country-flag-next'
3
+
4
+ defineProps<{
5
+ countryCodeIso2letter: string
6
+ }>()
7
+ </script>
8
+
9
+ <template>
10
+ <CountryFlag
11
+ class="mb-2"
12
+ :country="countryCodeIso2letter"
13
+ />
14
+ </template>
@@ -0,0 +1,2 @@
1
+ <!-- Placeholder for compound phone component -->
2
+ <!-- This component will be used to capture phone number details including country code, number input and ext. -->
@@ -0,0 +1,39 @@
1
+ <script setup lang="ts">
2
+ import type { TextareaProps } from '@nuxt/ui'
3
+
4
+ defineProps<{
5
+ name: string
6
+ label: string
7
+ inputId: string
8
+ required?: boolean
9
+ autofocus?: boolean
10
+ disabled?: boolean
11
+ help?: string
12
+ }>()
13
+
14
+ const model = defineModel<Exclude<TextareaProps['modelValue'], null>>({ required: true })
15
+ </script>
16
+
17
+ <template>
18
+ <UFormField
19
+ :name
20
+ :help
21
+ class="grow flex-1"
22
+ >
23
+ <template #default="{ error }">
24
+ <ConnectTextarea
25
+ :id="inputId"
26
+ v-model="model"
27
+ :data-testid="inputId"
28
+ :required
29
+ :label
30
+ :autofocus
31
+ :disabled
32
+ />
33
+ <div
34
+ v-if="!help && !error"
35
+ class="h-4 mt-1"
36
+ />
37
+ </template>
38
+ </UFormField>
39
+ </template>
@@ -0,0 +1,21 @@
1
+ <template>
2
+ <ConnectLayout>
3
+ <template #header>
4
+ <!-- Exposes the header slot of the base layout -->
5
+ <slot name="header">
6
+ <ConnectHeader />
7
+ </slot>
8
+ </template>
9
+ <template #body>
10
+ <!-- Exposes the body slot of the base layout -->
11
+ <slot name="body">
12
+ <div class="grow max-w-full overflow-hidden">
13
+ <slot />
14
+ </div>
15
+ </slot>
16
+ </template>
17
+ <template #topFooters>
18
+ <ConnectButtonControlWrapper />
19
+ </template>
20
+ </ConnectLayout>
21
+ </template>
@@ -0,0 +1,12 @@
1
+ <template>
2
+ <div class="bg-red-100 p-5">
3
+ Forms - should have bg-red-100
4
+ <HelloWorld />
5
+ <h3 class="text-green-900">
6
+ Forms - should be green-900
7
+ </h3>
8
+ <p class="text-neutral-highlighted">
9
+ Forms - should be neutral-highlighted
10
+ </p>
11
+ </div>
12
+ </template>