@bcrs-shared-components/base-address 3.0.3 → 3.0.4

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/BaseAddress.vue CHANGED
@@ -56,11 +56,11 @@
56
56
  :label="countryLabel"
57
57
  :rules="[...schemaLocal.country]"
58
58
  >
59
- <template #item="{item, props}">
59
+ <template #item="{item, props: autoCompleteProps}">
60
60
  <v-divider v-if="item.raw.divider" />
61
61
  <v-list-item
62
62
  v-else
63
- v-bind="props"
63
+ v-bind="autoCompleteProps"
64
64
  />
65
65
  </template>
66
66
  </v-autocomplete>
@@ -128,11 +128,11 @@
128
128
  :name="Math.random().toString()"
129
129
  :rules="[...schemaLocal.region]"
130
130
  >
131
- <template #item="{item, props}">
131
+ <template #item="{item, props: autoCompleteProps}">
132
132
  <v-divider v-if="item.raw.divider" />
133
133
  <v-list-item
134
134
  v-else
135
- v-bind="props"
135
+ v-bind="autoCompleteProps"
136
136
  />
137
137
  </template>
138
138
  </v-autocomplete>
@@ -174,153 +174,145 @@
174
174
  </div>
175
175
  </template>
176
176
 
177
- <script lang="ts">
178
- import { defineComponent, onMounted, toRefs, watch } from 'vue-demi'
177
+ <script setup lang="ts">
178
+ import { AddressIF, SchemaIF } from '@bcrs-shared-components/interfaces'
179
+ import { Ref, onMounted, toRef, watch } from 'vue'
179
180
  import {
180
181
  baseRules,
182
+ spaceRules,
181
183
  useAddress,
182
184
  useAddressComplete,
183
- useCountryRegions,
184
- useCountriesProvinces,
185
185
  useBaseValidations,
186
- spaceRules
187
- } from './factories'
188
- import { AddressIF, SchemaIF } from '@bcrs-shared-components/interfaces'
186
+ useCountriesProvinces,
187
+ useCountryRegions
188
+ } from '@bcrs-shared-components/base-address/factories'
189
189
  import { AddressValidationRules } from '@bcrs-shared-components/enums'
190
190
 
191
- export default defineComponent({
192
- name: 'BaseAddress',
193
- props: {
194
- value: {
195
- type: Object as () => AddressIF,
196
- default: () => ({
197
- streetAddress: '',
198
- streetAddressAdditional: '',
199
- addressCity: '',
200
- addressRegion: '',
201
- postalCode: '',
202
- addressCountry: null,
203
- deliveryInstructions: ''
204
- })
205
- },
206
- /* used for readonly mode vs edit mode */
207
- editing: {
208
- type: Boolean,
209
- default: false
210
- },
211
- /* contains validation for each field */
212
- schema: {
213
- type: Object as () => SchemaIF,
214
- default: null
215
- },
216
- /* triggers all current form validation errors */
217
- triggerErrors: {
218
- type: Boolean,
219
- default: false
220
- },
221
- /* Hides the persistent hint field on Address Input */
222
- hideAddressHint: {
223
- type: Boolean,
224
- default: false
225
- },
226
- /* Hides Delivery Address field (e.g. for Unit Notes) */
227
- hideDeliveryAddress: {
228
- type: Boolean,
229
- default: false
230
- }
231
- },
232
- emits: ['valid'],
233
- setup (props, { emit }) {
234
- // eslint-disable-next-line vue/no-setup-props-destructure
235
- const localSchema = { ...props.schema }
236
- const {
237
- addressLocal,
238
- country,
239
- schemaLocal,
240
- isSchemaRequired,
241
- labels
242
- } = useAddress(toRefs(props).value, localSchema)
243
-
244
- const origPostalCodeRules = localSchema.postalCode
245
- const origRegionRules = localSchema.region
191
+ const props = withDefaults(defineProps<{
192
+ value: AddressIF
193
+ editing: boolean
194
+ schema: SchemaIF
195
+ triggerErrors: boolean
196
+ hideAddressHint: boolean
197
+ hideDeliveryAddress: boolean
198
+ }>(), {
199
+ value: () => ({
200
+ streetAddress: '',
201
+ streetAddressAdditional: '',
202
+ addressCity: '',
203
+ addressRegion: '',
204
+ postalCode: '',
205
+ addressCountry: null,
206
+ deliveryInstructions: ''
207
+ }),
208
+ /* used for readonly mode vs edit mode */
209
+ editing: false,
210
+ /* contains validation for each field */
211
+ schema: null,
212
+ /* triggers all current form validation errors */
213
+ triggerErrors: false,
214
+ /* Hides the persistent hint field on Address Input */
215
+ hideAddressHint: false,
216
+ /* Hides Delivery Address field (e.g. for Unit Notes) */
217
+ hideDeliveryAddress: false
218
+ })
246
219
 
247
- const { addressForm, resetValidation, validate } = useBaseValidations()
220
+ const emits = defineEmits<{
221
+ 'update-address': [address: AddressIF]
222
+ valid: [valid: boolean]
223
+ }>()
248
224
 
249
- const { enableAddressComplete, uniqueIds } = useAddressComplete(addressLocal)
225
+ // eslint-disable-next-line vue/no-setup-props-destructure
226
+ const localSchema = { ...props.schema }
227
+ const {
228
+ addressLocal,
229
+ country,
230
+ schemaLocal,
231
+ labels
232
+ } = useAddress(toRef(props.value) as Ref<AddressIF>, localSchema)
250
233
 
251
- const countryProvincesHelpers = useCountriesProvinces()
234
+ const origPostalCodeRules = localSchema.postalCode
235
+ const origRegionRules = localSchema.region
252
236
 
253
- const countryChangeHandler = (val: string, oldVal: string) => {
254
- // do not trigger any changes if it is view only (summary instance)
255
- if (!props.editing) return
237
+ const { addressForm, resetValidation, validate } = useBaseValidations()
256
238
 
257
- if (val === 'CA') {
258
- localSchema.postalCode = origPostalCodeRules.concat([baseRules.postalCode])
259
- localSchema.region = origRegionRules
260
- } else if (val === 'US') {
261
- localSchema.postalCode = origPostalCodeRules.concat([baseRules.zipCode])
262
- localSchema.region = origRegionRules
263
- } else {
264
- localSchema.postalCode = origPostalCodeRules.concat([baseRules[AddressValidationRules.MAX_LENGTH](15)])
265
- localSchema.region = [baseRules[AddressValidationRules.MAX_LENGTH](2), ...spaceRules]
266
- }
267
- // reset other address fields (check is for loading an existing address)
268
- if (oldVal) {
269
- addressLocal.value.streetAddress = ''
270
- addressLocal.value.streetAddressAdditional = ''
271
- addressLocal.value.addressCity = ''
272
- addressLocal.value.addressRegion = ''
273
- addressLocal.value.postalCode = ''
274
- }
275
- // wait for schema update and validate the form
276
- setTimeout(() => {
277
- props.triggerErrors ? validate() : resetValidation()
278
- }, 5)
279
- }
239
+ const { enableAddressComplete, uniqueIds } = useAddressComplete(addressLocal)
280
240
 
281
- onMounted(() => {
282
- countryChangeHandler(addressLocal.value.addressCountry, null)
283
- })
241
+ const countryProvincesHelpers = useCountriesProvinces()
284
242
 
285
- watch(() => addressLocal.value, (val) => {
286
- let valid = true
287
- /** checks each field against the schema rules to see if the address is valid or not
288
- * NOTE: we don't want it to trigger error msgs yet which is why this does not call validate()
289
- */
290
- for (const key in val) {
291
- for (const index in schemaLocal.value[key]) {
292
- if (schemaLocal.value[key][index](val[key]) !== true) {
293
- valid = false
294
- break
295
- }
296
- }
297
- if (!valid) break
298
- }
299
- emit('valid', valid)
300
- }, { immediate: true, deep: true })
243
+ const countryChangeHandler = (val: string, oldVal: string) => {
244
+ // do not trigger any changes if it is view only (summary instance)
245
+ if (!props.editing) return
301
246
 
302
- watch(() => country.value, (val, oldVal) => {
303
- countryChangeHandler(val, oldVal)
304
- })
247
+ if (val === 'CA') {
248
+ localSchema.postalCode = origPostalCodeRules.concat([baseRules.postalCode])
249
+ localSchema.region = origRegionRules
250
+ } else if (val === 'US') {
251
+ localSchema.postalCode = origPostalCodeRules.concat([baseRules.zipCode])
252
+ localSchema.region = origRegionRules
253
+ } else {
254
+ localSchema.postalCode = origPostalCodeRules.concat([baseRules[AddressValidationRules.MAX_LENGTH](15)])
255
+ localSchema.region = [baseRules[AddressValidationRules.MAX_LENGTH](2), ...spaceRules]
256
+ }
257
+ // reset other address fields (check is for loading an existing address)
258
+ if (oldVal) {
259
+ addressLocal.value.streetAddress = ''
260
+ addressLocal.value.streetAddressAdditional = ''
261
+ addressLocal.value.addressCity = ''
262
+ addressLocal.value.addressRegion = ''
263
+ addressLocal.value.postalCode = ''
264
+ }
265
+ // wait for schema update and validate the form
266
+ setTimeout(() => {
267
+ props.triggerErrors ? validate() : resetValidation()
268
+ }, 5)
269
+ }
305
270
 
306
- watch(() => props.triggerErrors, () => {
307
- validate()
308
- })
271
+ onMounted(() => {
272
+ countryChangeHandler(addressLocal.value.addressCountry, null)
273
+ })
309
274
 
310
- return {
311
- addressForm,
312
- addressLocal,
313
- country,
314
- ...countryProvincesHelpers,
315
- enableAddressComplete,
316
- isSchemaRequired,
317
- ...labels,
318
- schemaLocal,
319
- useCountryRegions,
320
- ...uniqueIds,
321
- validate
275
+ watch(() => addressLocal.value, (val) => {
276
+ let valid = true
277
+ /** checks each field against the schema rules to see if the address is valid or not
278
+ * NOTE: we don't want it to trigger error msgs yet which is why this does not call validate()
279
+ */
280
+ for (const key in val) {
281
+ for (const index in schemaLocal.value[key]) {
282
+ if (schemaLocal.value[key][index](val[key]) !== true) {
283
+ valid = false
284
+ break
285
+ }
322
286
  }
287
+ if (!valid) break
323
288
  }
289
+ emits('valid', valid)
290
+ emits('update-address', val)
291
+ }, { immediate: true, deep: true })
292
+
293
+ watch(() => country.value, (val, oldVal) => {
294
+ countryChangeHandler(val, oldVal)
295
+ })
296
+
297
+ watch(() => props.triggerErrors, () => {
298
+ validate()
299
+ })
300
+
301
+ const { getCountries, getCountryName, getCountryRegions } = countryProvincesHelpers
302
+ const {
303
+ countryLabel,
304
+ streetLabel,
305
+ streetAdditionalLabel,
306
+ cityLabel,
307
+ regionLabel,
308
+ postalCodeLabel,
309
+ deliveryInstructionsLabel
310
+ } = labels
311
+ const { streetId, countryId } = uniqueIds
312
+
313
+ defineExpose({
314
+ addressForm,
315
+ validate
324
316
  })
325
317
  </script>
326
318
 
@@ -370,17 +362,17 @@ export default defineComponent({
370
362
  .v-text-field.v-input--is-readonly {
371
363
  pointer-events: none;
372
364
 
373
- ::v-deep .v-label {
365
+ :deep(.v-label) {
374
366
  // set label colour to same as disabled
375
367
  color: rgba(0,0,0,.38);
376
368
  }
377
369
 
378
- ::v-deep .v-select__selection {
370
+ :deep(.v-select__selection) {
379
371
  // set selection colour to same as disabled
380
372
  color: rgba(0,0,0,.38);
381
373
  }
382
374
 
383
- ::v-deep .v-icon {
375
+ :deep(.v-icon) {
384
376
  // set error icon colour to same as disabled
385
377
  color: rgba(0,0,0,.38) !important;
386
378
  opacity: 0.6;
@@ -1,5 +1,5 @@
1
1
  /* eslint-disable */
2
- import { computed, reactive, ref, Ref } from 'vue-demi'
2
+ import { computed, reactive, ref, Ref } from 'vue'
3
3
  import { uniqueId } from 'lodash'
4
4
 
5
5
  import { AddressIF, SchemaIF } from '@bcrs-shared-components/interfaces'
@@ -37,7 +37,7 @@ export function useCountriesProvinces () {
37
37
  * @param code The short code of the country.
38
38
  * @returns The long name of the country.
39
39
  */
40
- const getCountryName = (code: string): string => {
40
+ const getCountryName = (code: string): string | null => {
41
41
  if (!code) return null
42
42
  if (window['countryNameCache'][code]) return window['countryNameCache'][code]
43
43
  const country = window['countries'].find(c => c.code === code)
@@ -1,4 +1,4 @@
1
- import { ref } from 'vue-demi'
1
+ import { ref } from 'vue'
2
2
 
3
3
  import { AddressValidationRules } from '@bcrs-shared-components/enums'
4
4
 
package/package.json CHANGED
@@ -1,21 +1,14 @@
1
1
  {
2
2
  "name": "@bcrs-shared-components/base-address",
3
- "version": "3.0.3",
3
+ "version": "3.0.4",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
7
7
  "dependencies": {
8
8
  "@bcrs-shared-components/enums": "^2.0.0",
9
- "@bcrs-shared-components/interfaces": "^2.0.0",
10
- "@bcrs-shared-components/mixins": "^2.0.1",
11
- "@vuelidate/core": "^2.0.3",
12
- "lodash.uniqueid": "^4.0.1",
13
- "vue": "^2.7.14",
14
- "vuelidate": "0.6.2"
9
+ "@bcrs-shared-components/interfaces": "^2.0.1",
10
+ "@bcrs-shared-components/mixins": "^2.0.2",
11
+ "lodash.uniqueid": "^4.0.1"
15
12
  },
16
- "devDependencies": {
17
- "vue-property-decorator": "^9.1.2",
18
- "vuelidate-property-decorators": "1.0.28"
19
- },
20
- "gitHead": "d80832aa4a621fdabf26d3e1d479f0701cf50fad"
13
+ "gitHead": "60abfe87e91cdc56175ad09b16fb27b5acaea9ea"
21
14
  }
@@ -1,118 +0,0 @@
1
- /* FUTURE:
2
- * Delete this if we decide not to move forward with vuelidate
3
- * Fix it to work otherwise
4
- */
5
- import { computed, Ref, reactive } from 'vue-demi'
6
-
7
- import { AddressIF, SchemaIF } from '@bcrs-shared-components/interfaces'
8
-
9
- import useVuelidate from '@vuelidate/core'
10
-
11
- export function useValidations (schema: Ref<SchemaIF>, address: Ref<AddressIF>) {
12
- const validations = reactive({ addressLocal: schema.value })
13
- const $v = useVuelidate(validations, reactive({ addressLocal: address.value }))
14
-
15
- /**
16
- * Misc Vuetify rules.
17
- * @param prop The name of the property object to validate.
18
- * @param key The name of the property key (field) to validate.
19
- * @returns True if the rule passes, otherwise an error string.
20
- */
21
- const vuetifyRules = {
22
- requiredRule: (prop: string, key: string): boolean | string => {
23
- return Boolean($v.value[prop] && !$v.value[prop][key].required.$invalid) || 'This field is required'
24
- },
25
- minLengthRule: (prop: string, key: string): boolean | string => {
26
- const min = validations.addressLocal[key].max
27
- const msg = min ? `Minimum length is ${min}` : 'Text is below minimum length'
28
- return Boolean($v.value[prop] && !$v.value[prop][key].minLength.$invalid) || msg
29
- },
30
- maxLengthRule: (prop: string, key: string): boolean | string => {
31
- const max = validations.addressLocal[key].max
32
- const msg = max ? `Maximum length is ${max}` : 'Text is over maximum length'
33
- return Boolean($v.value[prop] && !$v.value[prop][key].maxLength.$invalid) || msg
34
- },
35
- // FUTURE: generalize this rule to take a validation parameter (ie, 'CA')
36
- isCanadaRule: (prop: string, key: string): boolean | string => {
37
- return Boolean($v.value[prop] && !$v.value[prop][key].isCanada.$invalid) || 'Address must be in Canada'
38
- },
39
- // FUTURE: generalize this rule to take a validation parameter (ie, 'BC')
40
- isBCRule: (prop: string, key: string): boolean | string => {
41
- return Boolean($v.value[prop] && !$v.value[prop][key].isBC.$invalid) || 'Address must be in BC'
42
- }
43
- }
44
-
45
- /**
46
- * Creates a Vuetify rules object from the Vuelidate state.
47
- * @param model The name of the model we are validating.
48
- * @returns A Vuetify rules object.
49
- */
50
- const createVuetifyRulesObject = (model: string): { [attr: string]: Array<Function> } => {
51
- const obj = {
52
- street: [],
53
- streetAdditional: [],
54
- city: [],
55
- region: [],
56
- postalCode: [],
57
- country: [],
58
- deliveryInstructions: []
59
- }
60
-
61
- // ensure Vuelidate state object is initialized
62
- if ($v && $v.value[model]) {
63
- // iterate over Vuelidate object properties
64
- Object.keys($v.value[model])
65
- // only look at validation properties
66
- .filter(prop => prop.charAt(0) !== '$')
67
- .forEach(prop => {
68
- // create array for each validation property
69
- obj[prop] = []
70
- // iterate over validation property params
71
- Object.keys($v.value[model][prop])
72
- .forEach(param => {
73
- // add specified validation functions to array
74
- switch (param) {
75
- case 'required': obj[prop].push(() => vuetifyRules.requiredRule(model, prop)); break
76
- case 'minLength': obj[prop].push(() => vuetifyRules.minLengthRule(model, prop)); break
77
- case 'maxLength': obj[prop].push(() => vuetifyRules.maxLengthRule(model, prop)); break
78
- case 'isCanada': obj[prop].push(() => vuetifyRules.isCanadaRule(model, prop)); break
79
- case 'isBC': obj[prop].push(() => vuetifyRules.isBCRule(model, prop)); break
80
- // FUTURE: add extra validation functions here
81
- default: break
82
- }
83
- })
84
- })
85
- }
86
-
87
- // sample return object
88
- // street: [
89
- // () => this.requiredRule('addressLocal', 'street'),
90
- // () => this.minLengthRule('addressLocal', 'street'),
91
- // () => this.maxLengthRule('addressLocal', 'street')
92
- // ],
93
- // ...
94
-
95
- return obj
96
- }
97
-
98
- /**
99
- * The Vuetify rules object. Used to display any validation errors/styling.
100
- * NB: As a getter, this is initialized between created() and mounted().
101
- * @returns the Vuetify validation rules object
102
- */
103
- const rules = computed((): { [attr: string]: Array<Function> } => {
104
- return createVuetifyRulesObject('addressLocal')
105
- })
106
-
107
- /** Array of validation rules used by input elements to prevent extra whitespace. */
108
- const spaceRules = [
109
- (v: string) => !/^\s/g.test(v) || 'Invalid spaces', // leading spaces
110
- (v: string) => !/\s$/g.test(v) || 'Invalid spaces', // trailing spaces
111
- (v: string) => !/\s\s/g.test(v) || 'Invalid word spacing' // multiple inline spaces
112
- ]
113
- return {
114
- $v,
115
- rules,
116
- spaceRules
117
- }
118
- }