@sbc-connect/nuxt-forms 0.7.11 → 0.7.12

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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @sbc-connect/nuxt-forms
2
2
 
3
+ ## 0.7.12
4
+
5
+ ### Patch Changes
6
+
7
+ - [#199](https://github.com/bcgov/connect-nuxt/pull/199) [`bb10de7`](https://github.com/bcgov/connect-nuxt/commit/bb10de7f8fd3b05673cbe38ee30b0bcb9d49d778) Thanks [@eve-git](https://github.com/eve-git)! - Switch the address form's Country field from the custom `ConnectCombobox` to Nuxt UI's `UInputMenu`, with word-start search filtering, Canada/US pinned to the top of the list, and correct label display and Enter-to-select behavior after searching.
8
+
3
9
  ## 0.7.11
4
10
 
5
11
  ### Patch Changes
@@ -1,6 +1,6 @@
1
1
  <script setup lang="ts">
2
- import type { SelectItem } from '@nuxt/ui'
3
2
  import { isoCountriesListSortedByName as countries } from '#forms/app/utils/isoCountriesList'
3
+ import type { Iso3166_1Country } from '#forms/app/utils/isoCountriesList'
4
4
 
5
5
  defineProps<{
6
6
  parentId: string
@@ -15,12 +15,54 @@ defineEmits<{
15
15
 
16
16
  const model = defineModel<string | undefined>({ required: true })
17
17
 
18
- const options: SelectItem[] = [
18
+ /**
19
+ * Matches when `search` appears in `text` starting at a word boundary (the
20
+ * start of `text`, or right after a non-letter/non-number character).
21
+ * E.g. matchesWordStart('Pending Review', 're') === true (via 'Review')
22
+ * matchesWordStart('Expired', 're') === false ('re' is mid-word, not a word start)
23
+ * matchesWordStart('United States', 'united s') === true (matches from the start)
24
+ */
25
+ function matchesWordStart(text: string, search: string): boolean {
26
+ const needle = search.trim().toLowerCase().replace(/\s+/g, ' ')
27
+ if (!needle) {
28
+ return true
29
+ }
30
+ const haystack = text.toLowerCase()
31
+ for (let index = haystack.indexOf(needle); index !== -1; index = haystack.indexOf(needle, index + 1)) {
32
+ if (index === 0 || /[^\p{L}\p{N}]/u.test(haystack.charAt(index - 1))) {
33
+ return true
34
+ }
35
+ }
36
+ return false
37
+ }
38
+
39
+ // UInputMenu only allows value-key/label-key to be a key that every item type
40
+ // has in common. `{ type: 'separator' }` alone shares no keys with
41
+ // Iso3166_1Country, which would make value-key="alpha_2" a type error. Giving
42
+ // it Iso3166_1Country's keys as optional fixes the type without changing
43
+ // anything at runtime - the separator object itself stays `{ type: 'separator' }`.
44
+ type CountryOption = Iso3166_1Country | (Partial<Iso3166_1Country> & { type: 'separator' })
45
+
46
+ const options: Array<CountryOption> = [
19
47
  countries.find(c => c.alpha_2 === 'CA')!,
20
48
  countries.find(c => c.alpha_2 === 'US')!,
21
49
  { type: 'separator' },
22
- ...countries
50
+ ...countries.filter(c => c.alpha_2 !== 'CA' && c.alpha_2 !== 'US')
23
51
  ]
52
+
53
+ const searchTerm = ref('')
54
+
55
+ const filteredItems = computed(() => {
56
+ if (!searchTerm.value.trim()) {
57
+ return options
58
+ }
59
+ return options.filter((item) => {
60
+ if ('type' in item) {
61
+ return false
62
+ }
63
+ return matchesWordStart(item.name, searchTerm.value)
64
+ })
65
+ })
24
66
  </script>
25
67
 
26
68
  <template>
@@ -30,18 +72,30 @@ const options: SelectItem[] = [
30
72
  class="grow"
31
73
  >
32
74
  <template #default="{ error }">
33
- <ConnectSelect
34
- :id="`${parentId}-input-country`"
35
- v-model="model"
75
+ <ConnectFloatingLabel
76
+ :id="`${parentId}-input-country-label`"
36
77
  :label="$t('connect.label.country')"
37
- :items="options"
38
- value-key="alpha_2"
39
- label-key="name"
40
- class="w-full"
41
- :disabled
42
- :required
43
- @change="$emit('change')"
44
- />
78
+ variant="input"
79
+ >
80
+ <UInputMenu
81
+ :id="`${parentId}-input-country`"
82
+ v-model="model"
83
+ v-model:search-term="searchTerm"
84
+ :data-testid="`${parentId}-input-country`"
85
+ :aria-labelledby="`${parentId}-input-country-label`"
86
+ ignore-filter
87
+ openOnFocus
88
+ :items="filteredItems"
89
+ value-key="alpha_2"
90
+ label-key="name"
91
+ placeholder="&nbsp;"
92
+ class="w-full"
93
+ :ui="{ viewport: 'overflow-x-hidden' }"
94
+ :disabled
95
+ :required
96
+ @change="$emit('change')"
97
+ />
98
+ </ConnectFloatingLabel>
45
99
  <div
46
100
  v-if="!$slots.help && !error"
47
101
  class="h-4 mt-1"
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sbc-connect/nuxt-forms",
3
3
  "type": "module",
4
- "version": "0.7.11",
4
+ "version": "0.7.12",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "github:bcgov/connect-nuxt"