fds-vue-core 7.2.3 → 7.2.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fds-vue-core",
3
- "version": "7.2.3",
3
+ "version": "7.2.5",
4
4
  "description": "FDS Vue Core Component Library",
5
5
  "type": "module",
6
6
  "main": "./dist/fds-vue-core.cjs.js",
@@ -1,5 +1,5 @@
1
1
  <script setup lang="ts">
2
- import { computed, ref, watch } from 'vue'
2
+ import { computed, ref, useAttrs, watch } from 'vue'
3
3
  import { useFdsI18n } from '../../../plugin/useFdsI18n'
4
4
  import FdsInput from '../FdsInput/FdsInput.vue'
5
5
  import { buildCountryOptions, sortCountryOptionsByName } from './countries'
@@ -11,8 +11,9 @@ defineOptions({
11
11
  inheritAttrs: false,
12
12
  })
13
13
 
14
- const nationalNumber = defineModel<string>({ default: '' })
14
+ const [nationalNumber, modelModifiers] = defineModel<string>({ default: '' })
15
15
  const country = defineModel<string>('country', { default: 'SE' })
16
+ const attrs = useAttrs()
16
17
 
17
18
  const props = withDefaults(defineProps<FdsPhonenumberProps>(), {
18
19
  label: undefined,
@@ -20,6 +21,16 @@ const props = withDefaults(defineProps<FdsPhonenumberProps>(), {
20
21
  optional: false,
21
22
  valid: undefined,
22
23
  invalidMessage: undefined,
24
+ id: undefined,
25
+ autocomplete: 'tel',
26
+ required: false,
27
+ placeholder: undefined,
28
+ maxlength: undefined,
29
+ minlength: undefined,
30
+ name: undefined,
31
+ autofocus: false,
32
+ readonly: false,
33
+ pattern: undefined,
23
34
  defaultCountry: 'SE',
24
35
  countries: undefined,
25
36
  locale: undefined,
@@ -35,6 +46,26 @@ const emit = defineEmits<FdsPhonenumberEmits>()
35
46
  const { t, locale: fdsLocale } = useFdsI18n()
36
47
 
37
48
  const resolvedLocale = computed(() => props.locale ?? fdsLocale.value)
49
+ const inputAttrs = computed(() => {
50
+ const { class: _class, style, ...rest } = attrs
51
+ return {
52
+ ...rest,
53
+ ...(style == null ? {} : { style: style as string | Record<string, unknown> }),
54
+ }
55
+ })
56
+ const forwardedInputProps = computed(() => ({
57
+ id: props.id,
58
+ autocomplete: props.autocomplete,
59
+ required: props.required,
60
+ placeholder: props.placeholder,
61
+ maxlength: props.maxlength,
62
+ minlength: props.minlength,
63
+ name: props.name,
64
+ autofocus: props.autofocus,
65
+ readonly: props.readonly,
66
+ pattern: props.pattern,
67
+ ...inputAttrs.value,
68
+ }))
38
69
 
39
70
  const countryItems = computed(() => {
40
71
  const options = props.countries?.length
@@ -52,6 +83,12 @@ const phoneValidationOptions = computed(() => ({ numberType: props.numberType })
52
83
  /** Set after the phone number field has blurred; validation does not run on input. */
53
84
  const committedValid = ref<boolean | null>(null)
54
85
 
86
+ const resolvedLabel = computed(() => (props.label === undefined ? t('FdsPhonenumber.phoneNumber') : props.label))
87
+
88
+ const resolvedInvalidMessage = computed(() =>
89
+ props.invalidMessage === undefined ? t('FdsPhonenumber.invalidPhone') : props.invalidMessage,
90
+ )
91
+
55
92
  const displayValid = computed((): boolean | null | undefined => {
56
93
  if (props.valid === false) return false
57
94
  if (props.valid === true) return true
@@ -61,7 +98,7 @@ const displayValid = computed((): boolean | null | undefined => {
61
98
  })
62
99
 
63
100
  const showInvalidMessage = computed(
64
- () => displayValid.value === false && !props.optional && props.invalidMessage && !props.disabled,
101
+ () => displayValid.value === false && !props.optional && !!resolvedInvalidMessage.value && !props.disabled,
65
102
  )
66
103
 
67
104
  const noCountryResults = ref(false)
@@ -99,8 +136,12 @@ function onNoCountryResults(value: boolean) {
99
136
 
100
137
  <template>
101
138
  <div class="w-full mb-6">
102
- <label v-if="label" class="block font-bold text-gray-900 cursor-pointer" :class="{ 'mb-0': meta, 'mb-1': !meta }">
103
- {{ label }}
139
+ <label
140
+ v-if="resolvedLabel"
141
+ class="block font-bold text-gray-900 cursor-pointer"
142
+ :class="{ 'mb-0': meta, 'mb-1': !meta }"
143
+ >
144
+ {{ resolvedLabel }}
104
145
  </label>
105
146
  <div v-if="meta" class="font-thin mb-1">
106
147
  {{ meta }}
@@ -118,6 +159,7 @@ function onNoCountryResults(value: boolean) {
118
159
  />
119
160
  <FdsInput
120
161
  v-model="nationalNumber"
162
+ :modelModifiers="modelModifiers"
121
163
  type="tel"
122
164
  :valid="displayValid"
123
165
  :disabled="disabled"
@@ -125,6 +167,7 @@ function onNoCountryResults(value: boolean) {
125
167
  :ariaLabel="t('FdsPhonenumber.phoneNumber')"
126
168
  :data-testid="dataTestid ? `${dataTestid}-number` : undefined"
127
169
  :class="['mb-0! min-w-0 flex-1', inputClass ?? '']"
170
+ v-bind="forwardedInputProps"
128
171
  @blur="handleBlur"
129
172
  />
130
173
  </div>
@@ -132,7 +175,7 @@ function onNoCountryResults(value: boolean) {
132
175
  {{ t('FdsPhonenumber.noCountryResults') }}
133
176
  </div>
134
177
  <div v-if="showInvalidMessage" class="text-red-700 font-bold mt-1">
135
- {{ invalidMessage }}
178
+ {{ resolvedInvalidMessage }}
136
179
  </div>
137
180
  </div>
138
181
  </template>
@@ -125,8 +125,7 @@ const arrowClasses = computed(() => [
125
125
  'pointer-events-none transition-transform duration-200 ease-in-out',
126
126
  {
127
127
  'fill-gray-500': props.disabled,
128
- 'fill-red-600': isInvalid.value && !props.disabled,
129
- 'fill-blue-500': !props.disabled && !isInvalid.value,
128
+ 'fill-blue-500': (!props.disabled && !isInvalid.value) || isInvalid.value,
130
129
  'rotate-180': dropdownOpen.value && !props.disabled,
131
130
  },
132
131
  ])
@@ -1,3 +1,4 @@
1
+ import type { FdsInputProps } from '../FdsInput/types'
1
2
  import type { CountryPhoneOption } from './countries'
2
3
 
3
4
  /**
@@ -6,13 +7,27 @@ import type { CountryPhoneOption } from './countries'
6
7
  */
7
8
  export type FdsPhonenumberNumberType = 'mobile' | 'any'
8
9
 
9
- export interface FdsPhonenumberProps {
10
+ type FdsPhonenumberInputPassthroughProps = Pick<
11
+ FdsInputProps,
12
+ | 'id'
13
+ | 'autocomplete'
14
+ | 'required'
15
+ | 'placeholder'
16
+ | 'maxlength'
17
+ | 'minlength'
18
+ | 'name'
19
+ | 'autofocus'
20
+ | 'readonly'
21
+ | 'pattern'
22
+ >
23
+
24
+ export interface FdsPhonenumberProps extends FdsPhonenumberInputPassthroughProps {
10
25
  label?: string
11
26
  meta?: string
12
27
  optional?: boolean
13
28
  valid?: boolean | null
14
29
  invalidMessage?: string
15
- /** National number (without country calling code). */
30
+ /** National number as typed by the user (without country calling code). */
16
31
  modelValue?: string
17
32
  /** ISO 3166-1 alpha-2 country code, e.g. `SE`. */
18
33
  country?: string
@@ -28,9 +43,17 @@ export interface FdsPhonenumberProps {
28
43
  dataTestid?: string
29
44
  selectClass?: string
30
45
  inputClass?: string
46
+ // Event handler props for consumer type inference
47
+ onValid?: ((value: boolean | null) => void) | Array<(value: boolean | null) => void>
48
+ onNoCountryResults?: ((value: boolean) => void) | Array<(value: boolean) => void>
49
+ onBlur?: ((event: FocusEvent) => void) | Array<(event: FocusEvent) => void>
50
+ 'onUpdate:modelValue'?: ((value: string) => void) | Array<(value: string) => void>
51
+ 'onUpdate:e164'?: ((value: string) => void) | Array<(value: string) => void>
52
+ 'onUpdate:country'?: ((value: string) => void) | Array<(value: string) => void>
31
53
  }
32
54
 
33
55
  export interface FdsPhonenumberEmits {
56
+ 'update:modelValue': [value: string]
34
57
  'update:country': [country: string]
35
58
  'update:e164': [phoneNumber: string]
36
59
  valid: [value: boolean | null]
package/src/lang/en.json CHANGED
@@ -44,6 +44,7 @@
44
44
  "FdsPagination.nextPage": "Go to next page",
45
45
  "FdsPagination.previousPage": "Go to previous page",
46
46
  "FdsPhonenumber.countryCode": "Country code",
47
+ "FdsPhonenumber.invalidPhone": "Enter a valid phone number",
47
48
  "FdsPhonenumber.noCountryResults": "No country matches your search",
48
49
  "FdsPhonenumber.phoneNumber": "Phone number",
49
50
  "FdsSearchSelectPro.loadingMore": "Loading more...",
package/src/lang/sv.json CHANGED
@@ -44,6 +44,7 @@
44
44
  "FdsPagination.nextPage": "Gå till nästa sida",
45
45
  "FdsPagination.previousPage": "Gå till föregående sida",
46
46
  "FdsPhonenumber.countryCode": "Landskod",
47
+ "FdsPhonenumber.invalidPhone": "Ange ett giltigt telefonnummer",
47
48
  "FdsPhonenumber.noCountryResults": "Inget land matchar sökningen",
48
49
  "FdsPhonenumber.phoneNumber": "Telefonnummer",
49
50
  "FdsSearchSelectPro.loadingMore": "Hämtar fler...",