@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.
- package/.env.example +14 -0
- package/CHANGELOG.md +394 -0
- package/LICENSE +28 -0
- package/README.md +57 -0
- package/app/components/Connect/Fieldset.vue +87 -0
- package/app/components/Connect/Form/Address/City.vue +20 -0
- package/app/components/Connect/Form/Address/Country.vue +51 -0
- package/app/components/Connect/Form/Address/DeliveryInstructions.vue +20 -0
- package/app/components/Connect/Form/Address/PostalCode.vue +48 -0
- package/app/components/Connect/Form/Address/Region.vue +62 -0
- package/app/components/Connect/Form/Address/Street.vue +64 -0
- package/app/components/Connect/Form/Address/StreetAdditional.vue +18 -0
- package/app/components/Connect/Form/Address/index.vue +116 -0
- package/app/components/Connect/Form/FieldWrapper.vue +52 -0
- package/app/components/Connect/Form/Input.vue +38 -0
- package/app/components/Connect/Form/Phone/CountryCode.vue +128 -0
- package/app/components/Connect/Form/Phone/CountryFlag.vue +14 -0
- package/app/components/Connect/Form/Phone/index.vue +2 -0
- package/app/components/Connect/Form/Textarea.vue +39 -0
- package/app/components/Connect/Layout/Form.vue +21 -0
- package/app/components/HelloWorld/Forms.vue +12 -0
- package/app/composables/useCanadaPost.ts +74 -0
- package/app/coverage/base.css +224 -0
- package/app/coverage/block-navigation.js +87 -0
- package/app/coverage/clover.xml +2803 -0
- package/app/coverage/components/Connect/Fieldset.vue.html +310 -0
- package/app/coverage/components/Connect/Form/Address/City.vue.html +145 -0
- package/app/coverage/components/Connect/Form/Address/Country.vue.html +238 -0
- package/app/coverage/components/Connect/Form/Address/DeliveryInstructions.vue.html +145 -0
- package/app/coverage/components/Connect/Form/Address/PostalCode.vue.html +199 -0
- package/app/coverage/components/Connect/Form/Address/Region.vue.html +271 -0
- package/app/coverage/components/Connect/Form/Address/Street.vue.html +277 -0
- package/app/coverage/components/Connect/Form/Address/StreetAdditional.vue.html +139 -0
- package/app/coverage/components/Connect/Form/Address/index.html +221 -0
- package/app/coverage/components/Connect/Form/Address/index.vue.html +433 -0
- package/app/coverage/components/Connect/Form/FieldWrapper.vue.html +211 -0
- package/app/coverage/components/Connect/Form/Input.vue.html +199 -0
- package/app/coverage/components/Connect/Form/Phone/CountryCode.vue.html +457 -0
- package/app/coverage/components/Connect/Form/Phone/CountryFlag.vue.html +127 -0
- package/app/coverage/components/Connect/Form/Phone/index.html +146 -0
- package/app/coverage/components/Connect/Form/Phone/index.vue.html +91 -0
- package/app/coverage/components/Connect/Form/Textarea.vue.html +196 -0
- package/app/coverage/components/Connect/Form/index.html +146 -0
- package/app/coverage/components/Connect/Layout/Form.vue.html +148 -0
- package/app/coverage/components/Connect/Layout/index.html +116 -0
- package/app/coverage/components/Connect/index.html +116 -0
- package/app/coverage/components/HelloWorld/Forms.vue.html +121 -0
- package/app/coverage/components/HelloWorld/index.html +116 -0
- package/app/coverage/composables/index.html +116 -0
- package/app/coverage/composables/useCanadaPost.ts.html +307 -0
- package/app/coverage/coverage-final.json +29 -0
- package/app/coverage/enums/canada-post-address-datalevel.ts.html +106 -0
- package/app/coverage/enums/index.html +116 -0
- package/app/coverage/favicon.png +0 -0
- package/app/coverage/index.html +296 -0
- package/app/coverage/interfaces/canada-post.ts.html +199 -0
- package/app/coverage/interfaces/index.html +131 -0
- package/app/coverage/interfaces/phone-country.ts.html +127 -0
- package/app/coverage/layouts/ConnectForm.vue.html +100 -0
- package/app/coverage/layouts/index.html +116 -0
- package/app/coverage/prettify.css +1 -0
- package/app/coverage/prettify.js +2 -0
- package/app/coverage/sort-arrow-sprite.png +0 -0
- package/app/coverage/sorter.js +210 -0
- package/app/coverage/types/connect-fieldset.ts.html +88 -0
- package/app/coverage/types/index.html +116 -0
- package/app/coverage/utils/formHelpers.ts.html +124 -0
- package/app/coverage/utils/index.html +146 -0
- package/app/coverage/utils/index.ts.html +88 -0
- package/app/coverage/utils/isoCountriesList.ts.html +6193 -0
- package/app/coverage/utils/zod-schemas/addresses.ts.html +559 -0
- package/app/coverage/utils/zod-schemas/index.html +131 -0
- package/app/coverage/utils/zod-schemas/index.ts.html +88 -0
- package/app/enums/canada-post-address-datalevel.ts +7 -0
- package/app/interfaces/canada-post.ts +38 -0
- package/app/interfaces/phone-country.ts +14 -0
- package/app/layouts/ConnectForm.vue +5 -0
- package/app/types/connect-fieldset.ts +1 -0
- package/app/types/forms-page-meta.d.ts +5 -0
- package/app/utils/formHelpers.ts +13 -0
- package/app/utils/index.ts +1 -0
- package/app/utils/isoCountriesList.ts +2048 -0
- package/app/utils/zod-schemas/addresses.ts +159 -0
- package/app/utils/zod-schemas/index.ts +1 -0
- package/i18n/locales/en-CA.ts +49 -0
- package/i18n/locales/fr-CA.ts +3 -0
- package/nuxt.config.ts +58 -0
- package/package.json +40 -0
- package/playwright-report/index.html +85 -0
- package/public/css/addresscomplete-2.50.min.css +11 -0
- package/public/js/addresscomplete-2.50.min.js +260 -0
- package/test-results/.last-run.json +4 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Canadian postal code regex (eg, accepts A1A 1A1 or A1A1A1).
|
|
5
|
+
* Ref: https://en.wikipedia.org/wiki/Postal_codes_in_Canada
|
|
6
|
+
*/
|
|
7
|
+
const CanadaPostalCodeRegex = /^[ABCEGHJ-NPRSTVXY][0-9][ABCEGHJ-NPRSTV-Z][ ]?[0-9][ABCEGHJ-NPRSTV-Z][0-9]$/i
|
|
8
|
+
const CanadaPostalCodeFormatOnlyRegex = /^[A-Z][0-9][A-Z][ ]?[0-9][A-Z][0-9]$/i
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* US ZIP code regex (eg, accepts 12345 or 12345-6789).
|
|
12
|
+
* Ref: https://faq.usps.com/s/article/ZIP-Code-The-Basics
|
|
13
|
+
*/
|
|
14
|
+
const USZipCodeRegex = /^\d{5}(?:-\d{4})?$/
|
|
15
|
+
|
|
16
|
+
export function getRequiredAddressSchema() {
|
|
17
|
+
const t = useNuxtApp().$i18n.t
|
|
18
|
+
|
|
19
|
+
return z.object({
|
|
20
|
+
street: z
|
|
21
|
+
.string()
|
|
22
|
+
.min(1, t('connect.validation.fieldRequired'))
|
|
23
|
+
.max(50, t('connect.validation.maxChars', { count: 50 })),
|
|
24
|
+
streetAdditional: z
|
|
25
|
+
.string()
|
|
26
|
+
.max(105, t('connect.validation.maxChars', { count: 105 }))
|
|
27
|
+
.optional(),
|
|
28
|
+
city: z
|
|
29
|
+
.string()
|
|
30
|
+
.min(1, t('connect.validation.fieldRequired'))
|
|
31
|
+
.max(40, t('connect.validation.maxChars', { count: 40 })),
|
|
32
|
+
region: z
|
|
33
|
+
.string()
|
|
34
|
+
.optional(),
|
|
35
|
+
postalCode: z
|
|
36
|
+
.string()
|
|
37
|
+
.max(15, t('connect.validation.maxChars', { count: 15 }))
|
|
38
|
+
.optional(),
|
|
39
|
+
country: z
|
|
40
|
+
.string()
|
|
41
|
+
.min(1, t('connect.validation.fieldRequired')),
|
|
42
|
+
locationDescription: z
|
|
43
|
+
.string()
|
|
44
|
+
.max(80, t('connect.validation.maxChars', { count: 80 }))
|
|
45
|
+
.optional()
|
|
46
|
+
}).superRefine((data, ctx) => {
|
|
47
|
+
const { country, region, postalCode } = data
|
|
48
|
+
|
|
49
|
+
if (region && region.length > 2) {
|
|
50
|
+
ctx.addIssue({
|
|
51
|
+
code: 'custom',
|
|
52
|
+
message: t('connect.validation.maxChars', { count: 2 }),
|
|
53
|
+
path: ['region']
|
|
54
|
+
})
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const isRequiredRegion = country === 'US' || country === 'CA'
|
|
58
|
+
const isRequiredPostalCode = !!country && !isNoPostalCodeCountry(country)
|
|
59
|
+
|
|
60
|
+
if (isRequiredRegion) {
|
|
61
|
+
if (!region) {
|
|
62
|
+
ctx.addIssue({
|
|
63
|
+
code: 'custom',
|
|
64
|
+
message: t('connect.validation.fieldRequired'),
|
|
65
|
+
path: ['region']
|
|
66
|
+
})
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (isRequiredPostalCode && !postalCode) {
|
|
71
|
+
ctx.addIssue({
|
|
72
|
+
code: 'custom',
|
|
73
|
+
message: t('connect.validation.fieldRequired'),
|
|
74
|
+
path: ['postalCode']
|
|
75
|
+
})
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (!postalCode) {
|
|
79
|
+
return
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (country === 'CA') {
|
|
83
|
+
if (!CanadaPostalCodeFormatOnlyRegex.test(postalCode)) {
|
|
84
|
+
ctx.addIssue({
|
|
85
|
+
code: 'custom',
|
|
86
|
+
message: t('connect.validation.invalidPostalCodeFormat'),
|
|
87
|
+
path: ['postalCode']
|
|
88
|
+
})
|
|
89
|
+
} else if (!CanadaPostalCodeRegex.test(postalCode)) {
|
|
90
|
+
ctx.addIssue({
|
|
91
|
+
code: 'custom',
|
|
92
|
+
message: t('connect.validation.invalidPostalCode'),
|
|
93
|
+
path: ['postalCode']
|
|
94
|
+
})
|
|
95
|
+
}
|
|
96
|
+
} else if (country === 'US') {
|
|
97
|
+
if (!USZipCodeRegex.test(postalCode)) {
|
|
98
|
+
ctx.addIssue({
|
|
99
|
+
code: 'custom',
|
|
100
|
+
message: t('connect.validation.invalidZipCodeFormat'),
|
|
101
|
+
path: ['postalCode']
|
|
102
|
+
})
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
})
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export function getNonRequiredAddressSchema() {
|
|
109
|
+
const t = useNuxtApp().$i18n.t
|
|
110
|
+
|
|
111
|
+
return z.object({
|
|
112
|
+
street: z
|
|
113
|
+
.string()
|
|
114
|
+
.min(1, t('connect.validation.fieldRequired'))
|
|
115
|
+
.max(50, t('connect.validation.maxChars', { count: 50 }))
|
|
116
|
+
.optional()
|
|
117
|
+
.or(z.literal('')),
|
|
118
|
+
streetAdditional: z
|
|
119
|
+
.string()
|
|
120
|
+
.max(50, t('connect.validation.maxChars', { count: 50 }))
|
|
121
|
+
.optional(),
|
|
122
|
+
city: z
|
|
123
|
+
.string()
|
|
124
|
+
.min(1, t('connect.validation.fieldRequired'))
|
|
125
|
+
.max(40, t('connect.validation.maxChars', { count: 40 }))
|
|
126
|
+
.optional()
|
|
127
|
+
.or(z.literal('')),
|
|
128
|
+
region: z
|
|
129
|
+
.string()
|
|
130
|
+
.optional(),
|
|
131
|
+
postalCode: z
|
|
132
|
+
.string()
|
|
133
|
+
.max(15, t('connect.validation.maxChars', { count: 15 }))
|
|
134
|
+
.optional(),
|
|
135
|
+
country: z
|
|
136
|
+
.string()
|
|
137
|
+
.min(1, t('connect.validation.fieldRequired'))
|
|
138
|
+
.optional()
|
|
139
|
+
.or(z.literal('')),
|
|
140
|
+
locationDescription: z
|
|
141
|
+
.string()
|
|
142
|
+
.max(80, t('connect.validation.maxChars', { count: 80 }))
|
|
143
|
+
.optional()
|
|
144
|
+
}).superRefine((data, ctx) => {
|
|
145
|
+
// validate region based on country
|
|
146
|
+
// required if country is US or CA
|
|
147
|
+
// optional and max 2 characters if not US or CA
|
|
148
|
+
// const country = data.country
|
|
149
|
+
const region = data.region
|
|
150
|
+
|
|
151
|
+
if (region && region.length > 2) {
|
|
152
|
+
ctx.addIssue({
|
|
153
|
+
code: 'custom',
|
|
154
|
+
message: t('connect.validation.maxChars', { count: 2 }),
|
|
155
|
+
path: ['region']
|
|
156
|
+
})
|
|
157
|
+
}
|
|
158
|
+
})
|
|
159
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './addresses'
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
/* Ordering should be alphabetical unless otherwise specified */
|
|
3
|
+
connect: {
|
|
4
|
+
label: {
|
|
5
|
+
address: 'Address',
|
|
6
|
+
addressResidential: 'Residential Address',
|
|
7
|
+
city: 'City',
|
|
8
|
+
code: 'Code',
|
|
9
|
+
country: 'Country',
|
|
10
|
+
countryCode: 'Country Code',
|
|
11
|
+
deliveryAddress: 'Delivery Address',
|
|
12
|
+
deliveryInstructions: 'Delivery Instructions',
|
|
13
|
+
deliveryInstructionsOpt: 'Delivery Instructions (Optional)',
|
|
14
|
+
line1: 'Address Line 1',
|
|
15
|
+
line2: 'Address Line 2 (Optional)',
|
|
16
|
+
locationDescription: 'Location Description',
|
|
17
|
+
locationDescriptionOpt: 'Location Description (Optional)',
|
|
18
|
+
mailingAddress: 'Mailing Address',
|
|
19
|
+
postalCode: 'Postal Code',
|
|
20
|
+
postalCodeOpt: 'Postal Code (Optional)',
|
|
21
|
+
province: 'Province',
|
|
22
|
+
region: 'Region',
|
|
23
|
+
regionOpt: 'Region (Optional)',
|
|
24
|
+
sameAsMailAddress: 'Same as Mailing Address',
|
|
25
|
+
sameAsDeliveryAddress: 'Same as Delivery Address',
|
|
26
|
+
state: 'State',
|
|
27
|
+
street: 'Street Address',
|
|
28
|
+
streetAdditional: 'Additional Street Address (Optional)',
|
|
29
|
+
streetName: 'Street Name',
|
|
30
|
+
streetNumber: 'Street Number',
|
|
31
|
+
unitNumber: 'Unit Number',
|
|
32
|
+
unitNumberOpt: 'Unit Number (Optional)',
|
|
33
|
+
zipCode: 'Zip Code'
|
|
34
|
+
},
|
|
35
|
+
text: {
|
|
36
|
+
addressCanBePOBox: 'Street address, PO box, rural route, or general delivery address.',
|
|
37
|
+
addressCannotBePOBox: 'Address cannot be a PO Box.'
|
|
38
|
+
},
|
|
39
|
+
validation: {
|
|
40
|
+
fieldRequired: 'This field is required',
|
|
41
|
+
maxChars: 'Maximum 0 characters | Maximum 1 character | Maximum {count} characters', // 0/1 most likely will never be used but required for pluralization
|
|
42
|
+
minChars: 'Minimum 0 characters | Minimum 1 character | Minimum {count} characters', // 0/1 most likely will never be used but required for pluralization
|
|
43
|
+
required: 'Required',
|
|
44
|
+
invalidPostalCode: 'Enter a valid postal code',
|
|
45
|
+
invalidPostalCodeFormat: 'Format must be A1A 1A1',
|
|
46
|
+
invalidZipCodeFormat: 'Format must be 12345 or 12345-6789'
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
package/nuxt.config.ts
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// https://nuxt.com/docs/api/configuration/nuxt-config
|
|
2
|
+
import { createResolver } from 'nuxt/kit'
|
|
3
|
+
|
|
4
|
+
const { resolve } = createResolver(import.meta.url)
|
|
5
|
+
|
|
6
|
+
export default defineNuxtConfig({
|
|
7
|
+
ssr: false,
|
|
8
|
+
|
|
9
|
+
devtools: { enabled: false },
|
|
10
|
+
|
|
11
|
+
compatibilityDate: '2025-07-10',
|
|
12
|
+
|
|
13
|
+
imports: {
|
|
14
|
+
dirs: ['enums', 'interfaces', 'types']
|
|
15
|
+
},
|
|
16
|
+
|
|
17
|
+
extends: ['@sbc-connect/nuxt-base'],
|
|
18
|
+
|
|
19
|
+
alias: {
|
|
20
|
+
'#forms': resolve('./')
|
|
21
|
+
},
|
|
22
|
+
|
|
23
|
+
app: {
|
|
24
|
+
head: {
|
|
25
|
+
link: [
|
|
26
|
+
{ rel: 'stylesheet', href: '/css/addresscomplete-2.50.min.css' }
|
|
27
|
+
],
|
|
28
|
+
script: [
|
|
29
|
+
{ src: '/js/addresscomplete-2.50.min.js', type: 'text/javascript', defer: true }
|
|
30
|
+
]
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
|
|
34
|
+
i18n: {
|
|
35
|
+
locales: [
|
|
36
|
+
{
|
|
37
|
+
name: 'English',
|
|
38
|
+
code: 'en-CA',
|
|
39
|
+
language: 'en-CA',
|
|
40
|
+
dir: 'ltr',
|
|
41
|
+
file: 'en-CA.ts'
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
name: 'Français',
|
|
45
|
+
code: 'fr-CA',
|
|
46
|
+
language: 'fr-CA',
|
|
47
|
+
dir: 'ltr',
|
|
48
|
+
file: 'fr-CA.ts'
|
|
49
|
+
}
|
|
50
|
+
]
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
runtimeConfig: {
|
|
54
|
+
public: {
|
|
55
|
+
addressCompleteKey: ''
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
})
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sbc-connect/nuxt-forms",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "0.0.0-test-ld-20260520212549",
|
|
5
|
+
"repository": "github:bcgov/connect-nuxt",
|
|
6
|
+
"license": "BSD-3-Clause",
|
|
7
|
+
"main": "./nuxt.config.ts",
|
|
8
|
+
"devDependencies": {
|
|
9
|
+
"@axe-core/playwright": "4.11.1",
|
|
10
|
+
"dotenv": "17.3.1",
|
|
11
|
+
"nuxt": "4.2.2",
|
|
12
|
+
"typescript": "5.9.3",
|
|
13
|
+
"vue-tsc": "3.2.5",
|
|
14
|
+
"@sbc-connect/vitest-config": "0.1.1",
|
|
15
|
+
"@sbc-connect/eslint-config": "0.0.8",
|
|
16
|
+
"@sbc-connect/playwright-config": "0.1.1"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"country-codes-list": "2.0.0",
|
|
20
|
+
"vue-country-flag-next": "2.3.2",
|
|
21
|
+
"@sbc-connect/nuxt-base": "0.0.0-test-ld-20260520212549"
|
|
22
|
+
},
|
|
23
|
+
"scripts": {
|
|
24
|
+
"preinstall": "npx only-allow pnpm",
|
|
25
|
+
"dev": "nuxi dev .playground --dotenv ../.env",
|
|
26
|
+
"build": "nuxt build .playground",
|
|
27
|
+
"build:test": "pnpm generate && npx serve .playground/.output/public",
|
|
28
|
+
"generate": "nuxt generate .playground --dotenv ../.env",
|
|
29
|
+
"preview": "npx serve .playground/.output/public",
|
|
30
|
+
"lint": "eslint .",
|
|
31
|
+
"lint:fix": "eslint --fix .",
|
|
32
|
+
"test": "pnpm run test:unit; pnpm run test:e2e",
|
|
33
|
+
"test:unit": "vitest run --passWithNoTests",
|
|
34
|
+
"test:unit:watch": "vitest",
|
|
35
|
+
"test:unit:cov": "vitest --dir tests/unit --coverage",
|
|
36
|
+
"test:e2e": "npx playwright test",
|
|
37
|
+
"test:e2e:ui": "npx playwright test --ui",
|
|
38
|
+
"typecheck": "npx nuxt typecheck"
|
|
39
|
+
}
|
|
40
|
+
}
|