@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,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
+ }
@@ -0,0 +1,3 @@
1
+ export default {
2
+ /* Ordering should be alphabetical unless otherwise specified */
3
+ }
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
+ }