@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 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
- const model = defineModel<string | number | bigint | null | undefined>({ required: true })
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
- :id
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="&nbsp;"
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.1.29",
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",