@sbc-connect/nuxt-base 0.1.29 → 0.2.0
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 +10 -0
- package/app/app.config.ts +3 -0
- package/app/components/Connect/Input.vue +36 -4
- package/app/components/Connect/InputDate.vue +107 -0
- package/package.json +3 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# @sbc-connect/nuxt-base
|
|
2
2
|
|
|
3
|
+
## 0.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#101](https://github.com/bcgov/connect-nuxt/pull/101) [`033f6c6`](https://github.com/bcgov/connect-nuxt/commit/033f6c624fbf953f1d7cf491c876cc9b58619b22) Thanks [@cameron-eyds](https://github.com/cameron-eyds)! - Implements dynamic slots/props while supporting explicit props
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- [#97](https://github.com/bcgov/connect-nuxt/pull/97) [`09323e1`](https://github.com/bcgov/connect-nuxt/commit/09323e1fcaff9a2738528c8161288c1d4bcd0677) Thanks [@deetz99](https://github.com/deetz99)! - feat: ConnectInputDate component
|
|
12
|
+
|
|
3
13
|
## 0.1.29
|
|
4
14
|
|
|
5
15
|
### Patch Changes
|
package/app/app.config.ts
CHANGED
|
@@ -278,6 +278,9 @@ export default defineAppConfig({
|
|
|
278
278
|
upload: 'i-mdi-upload'
|
|
279
279
|
},
|
|
280
280
|
input: {
|
|
281
|
+
slots: {
|
|
282
|
+
trailingIcon: 'text-neutral group-has-[div>input[aria-invalid=true]]:text-error group-focus-within:text-primary'
|
|
283
|
+
},
|
|
281
284
|
variants: {
|
|
282
285
|
size: {
|
|
283
286
|
bcGov: {
|
|
@@ -1,21 +1,42 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
|
|
2
|
+
import type { InputProps } from '@nuxt/ui'
|
|
3
3
|
|
|
4
|
-
defineProps<{
|
|
4
|
+
const props = defineProps<{
|
|
5
5
|
id: string
|
|
6
6
|
label: string
|
|
7
7
|
mask?: string
|
|
8
|
+
disabled?: boolean
|
|
9
|
+
autoFocus?: boolean
|
|
8
10
|
}>()
|
|
11
|
+
|
|
12
|
+
const model = defineModel<string | number | bigint | null | undefined>({ required: true })
|
|
13
|
+
|
|
14
|
+
// Inject props
|
|
15
|
+
const injectedProps = inject<InputProps>(
|
|
16
|
+
`UInput-props${props.id ? `-${props.id}` : ''}`,
|
|
17
|
+
{} as InputProps
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
// Inject slots
|
|
21
|
+
const injectedSlots = inject<{ [key: string]: VNode }>(
|
|
22
|
+
`UInput-slots${props.id ? `-${props.id}` : ''}`,
|
|
23
|
+
{}
|
|
24
|
+
)
|
|
9
25
|
</script>
|
|
10
26
|
|
|
11
27
|
<template>
|
|
12
28
|
<UInput
|
|
13
|
-
|
|
29
|
+
v-bind="{
|
|
30
|
+
id,
|
|
31
|
+
disabled,
|
|
32
|
+
autoFocus,
|
|
33
|
+
...injectedProps, // injected props will default when provided
|
|
34
|
+
}"
|
|
14
35
|
v-model.trim="model"
|
|
15
36
|
v-maska="mask"
|
|
37
|
+
class="w-full grow"
|
|
16
38
|
:data-testid="id"
|
|
17
39
|
placeholder=" "
|
|
18
|
-
class="w-full grow"
|
|
19
40
|
>
|
|
20
41
|
<label
|
|
21
42
|
:for="id"
|
|
@@ -23,5 +44,16 @@ defineProps<{
|
|
|
23
44
|
>
|
|
24
45
|
{{ label }}
|
|
25
46
|
</label>
|
|
47
|
+
|
|
48
|
+
<!-- Render injected slots -->
|
|
49
|
+
<template
|
|
50
|
+
v-for="(comp, name) in injectedSlots"
|
|
51
|
+
#[name]
|
|
52
|
+
:key="name"
|
|
53
|
+
>
|
|
54
|
+
<component
|
|
55
|
+
:is="comp"
|
|
56
|
+
/>
|
|
57
|
+
</template>
|
|
26
58
|
</UInput>
|
|
27
59
|
</template>
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
3
|
+
// https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/examples/datepicker-dialog/
|
|
4
|
+
// https://whatsock.com/Templates/Datepickers/Basic,%20Auto%20Open/index.htm
|
|
5
|
+
import type { ConnectInput, UCalendar } from '#components'
|
|
6
|
+
import { CalendarDate } from '@internationalized/date'
|
|
7
|
+
import { DateTime } from 'luxon'
|
|
8
|
+
|
|
9
|
+
// FUTURE: update props as needed (min/max/disabled days)
|
|
10
|
+
defineProps<{
|
|
11
|
+
label: string
|
|
12
|
+
id: string
|
|
13
|
+
}>()
|
|
14
|
+
|
|
15
|
+
const emit = defineEmits<{
|
|
16
|
+
blur: []
|
|
17
|
+
}>()
|
|
18
|
+
|
|
19
|
+
const externalModel = defineModel<string | null | undefined>({ required: true })
|
|
20
|
+
|
|
21
|
+
const localModel = computed({
|
|
22
|
+
get() {
|
|
23
|
+
if (externalModel.value) {
|
|
24
|
+
const dt = DateTime.fromISO(externalModel.value, { zone: 'America/Vancouver' })
|
|
25
|
+
if (dt.isValid) {
|
|
26
|
+
return new CalendarDate(dt.year, dt.month, dt.day)
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return undefined
|
|
30
|
+
},
|
|
31
|
+
set(v) {
|
|
32
|
+
if (v) {
|
|
33
|
+
externalModel.value = DateTime.fromObject({
|
|
34
|
+
year: v.year,
|
|
35
|
+
month: v.month,
|
|
36
|
+
day: v.day
|
|
37
|
+
}).toISODate()
|
|
38
|
+
} else {
|
|
39
|
+
externalModel.value = null
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
const open = ref(false)
|
|
45
|
+
const calendarRef = useTemplateRef('calendar-ref')
|
|
46
|
+
const inputRef = useTemplateRef<InstanceType<typeof ConnectInput>>('input-ref')
|
|
47
|
+
|
|
48
|
+
function focusCalendar() {
|
|
49
|
+
const button = (calendarRef.value as any).$el.querySelector('button')
|
|
50
|
+
if (button) {
|
|
51
|
+
(button as HTMLButtonElement).focus()
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function focusInput() {
|
|
56
|
+
const input = (inputRef.value as any).$el.querySelector('input')
|
|
57
|
+
if (input) {
|
|
58
|
+
(input as HTMLInputElement).focus()
|
|
59
|
+
}
|
|
60
|
+
open.value = false
|
|
61
|
+
emit('blur')
|
|
62
|
+
}
|
|
63
|
+
</script>
|
|
64
|
+
|
|
65
|
+
<template>
|
|
66
|
+
<UPopover
|
|
67
|
+
v-model:open="open"
|
|
68
|
+
:content="{
|
|
69
|
+
onOpenAutoFocus: (e) => e.preventDefault(),
|
|
70
|
+
onEscapeKeyDown: () => {
|
|
71
|
+
focusInput()
|
|
72
|
+
},
|
|
73
|
+
side: 'bottom',
|
|
74
|
+
align: 'start',
|
|
75
|
+
}"
|
|
76
|
+
@update:open="(v) => {
|
|
77
|
+
if (!v) {
|
|
78
|
+
$emit('blur')
|
|
79
|
+
}
|
|
80
|
+
}"
|
|
81
|
+
>
|
|
82
|
+
<template #default>
|
|
83
|
+
<div class="w-full group">
|
|
84
|
+
<ConnectInput
|
|
85
|
+
:id
|
|
86
|
+
ref="input-ref"
|
|
87
|
+
v-model="externalModel"
|
|
88
|
+
:label
|
|
89
|
+
mask="####-##-##"
|
|
90
|
+
trailing-icon="i-mdi-calendar"
|
|
91
|
+
@focus="open = true"
|
|
92
|
+
@click.stop="open = true"
|
|
93
|
+
@keydown.down.prevent="focusCalendar"
|
|
94
|
+
/>
|
|
95
|
+
</div>
|
|
96
|
+
</template>
|
|
97
|
+
|
|
98
|
+
<template #content>
|
|
99
|
+
<UCalendar
|
|
100
|
+
ref="calendar-ref"
|
|
101
|
+
v-model="localModel"
|
|
102
|
+
class="p-2"
|
|
103
|
+
@update:model-value="focusInput"
|
|
104
|
+
/>
|
|
105
|
+
</template>
|
|
106
|
+
</UPopover>
|
|
107
|
+
</template>
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sbc-connect/nuxt-base",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.2.0",
|
|
5
5
|
"repository": "github:bcgov/connect-nuxt",
|
|
6
6
|
"license": "BSD-3-Clause",
|
|
7
7
|
"main": "./nuxt.config.ts",
|
|
@@ -14,11 +14,13 @@
|
|
|
14
14
|
"dompurify": "^3.3.0",
|
|
15
15
|
"es-toolkit": "^1.41.0",
|
|
16
16
|
"launchdarkly-vue-client-sdk": "^2.4.1",
|
|
17
|
+
"luxon": "^3.7.2",
|
|
17
18
|
"maska": "^3.2.0",
|
|
18
19
|
"zod": "^4.1.12"
|
|
19
20
|
},
|
|
20
21
|
"devDependencies": {
|
|
21
22
|
"@axe-core/playwright": "4.11.0",
|
|
23
|
+
"@types/luxon": "^3.7.1",
|
|
22
24
|
"@vitest/coverage-v8": "3.2.4",
|
|
23
25
|
"dotenv": "17.2.3",
|
|
24
26
|
"nuxt": "4.1.3",
|