@sbc-connect/nuxt-base 0.1.29 → 0.3.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,29 @@
1
1
  # @sbc-connect/nuxt-base
2
2
 
3
+ ## 0.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#102](https://github.com/bcgov/connect-nuxt/pull/102) [`d714785`](https://github.com/bcgov/connect-nuxt/commit/d71478573f1fe11be34d5d588d68fb75eb5fd159) Thanks [@deetz99](https://github.com/deetz99)! - - ConnectTransitionFade component
8
+ - configure UContainer app config with default spacing and padding
9
+ - configure UAlert subtle/warning app config with correct bg styling
10
+
11
+ ### Patch Changes
12
+
13
+ - [#104](https://github.com/bcgov/connect-nuxt/pull/104) [`5f1b383`](https://github.com/bcgov/connect-nuxt/commit/5f1b3839ed993654a7f20fe161047ba38ab86274) Thanks [@deetz99](https://github.com/deetz99)! - - change overflow-hidden to overflow-clip in main layout component, allowing position sticky to work correctly
14
+ - cancel and close i18n translations
15
+ - Type aliases for Dates
16
+
17
+ ## 0.2.0
18
+
19
+ ### Minor Changes
20
+
21
+ - [#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
22
+
23
+ ### Patch Changes
24
+
25
+ - [#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
26
+
3
27
  ## 0.1.29
4
28
 
5
29
  ### Patch Changes
package/app/app.config.ts CHANGED
@@ -19,7 +19,7 @@ export default defineAppConfig({
19
19
  color: 'warning',
20
20
  variant: 'subtle',
21
21
  class: {
22
- root: 'text-highlighted bg-yellow-400/25 ring-2 ring-yellow-400',
22
+ root: 'py-4 px-6 relative bg-white text-highlighted ring-2 ring-brand-inverted before:content-[""] before:absolute before:inset-0 before:bg-brand-inverted/10 before:z-10',
23
23
  icon: 'text-warning',
24
24
  title: 'font-bold text-nuetral-highlighted',
25
25
  description: 'text-nuetral-highlighted'
@@ -166,6 +166,9 @@ export default defineAppConfig({
166
166
  }
167
167
  ]
168
168
  },
169
+ container: {
170
+ base: 'px-0 sm:px-0 lg:px-0 py-6 space-y-6 sm:py-10 sm:space-y-10'
171
+ },
169
172
  dropdownMenu: {
170
173
  slots: {
171
174
  content: 'min-w-32 max-h-[75dvh] shadow-lg rounded-sm',
@@ -278,6 +281,9 @@ export default defineAppConfig({
278
281
  upload: 'i-mdi-upload'
279
282
  },
280
283
  input: {
284
+ slots: {
285
+ trailingIcon: 'text-neutral group-has-[div>input[aria-invalid=true]]:text-error group-focus-within:text-primary'
286
+ },
281
287
  variants: {
282
288
  size: {
283
289
  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>
@@ -12,7 +12,7 @@
12
12
  <slot name="bottomHeaders" />
13
13
  <main class="app-body px-2 sm:px-4">
14
14
  <slot name="body">
15
- <div class="app-inner-container grow flex flex-col overflow-hidden">
15
+ <div class="app-inner-container grow flex flex-col overflow-clip">
16
16
  <slot />
17
17
  </div>
18
18
  </slot>
@@ -0,0 +1,31 @@
1
+ <template>
2
+ <Transition name="fade">
3
+ <slot />
4
+ </Transition>
5
+ </template>
6
+
7
+ <style>
8
+ .fade-enter-active {
9
+ transition: opacity 0.3s ease-in-out;
10
+ }
11
+ .fade-leave-active {
12
+ transition: opacity 0s ease-in-out;
13
+ }
14
+ .fade-enter-from,
15
+ .fade-leave-to {
16
+ opacity: 0;
17
+ }
18
+
19
+ @media (prefers-reduced-motion) {
20
+ .fade-enter-active {
21
+ transition: opacity 0s ease-in-out;
22
+ }
23
+ .fade-leave-active {
24
+ transition: opacity 0s ease-in-out;
25
+ }
26
+ .fade-enter-from,
27
+ .fade-leave-to {
28
+ opacity: 0;
29
+ }
30
+ }
31
+ </style>
@@ -0,0 +1,17 @@
1
+ /**
2
+ * ISO date string (YYYY-MM-DD), assumed to be in Pacific timezone.
3
+ * @example "2021-12-31"
4
+ */
5
+ export type IsoDatePacific = string
6
+
7
+ /**
8
+ * API date-time string (YYYY-MM-DDTHH:MM:SS[.MMMMMM]+00.00), assumed to be in UTC.
9
+ * @example "2022-05-09T16:26:14.839032+00:00"
10
+ */
11
+ export type ApiDateTimeUtc = string
12
+
13
+ /**
14
+ * Formatted date-time string with explicit GMT timezone (ie, UTC).
15
+ * @example "Tue, 19 Apr 2022 16:40:18 GMT"
16
+ */
17
+ export type FormattedDateTimeGmt = string
@@ -21,6 +21,8 @@ export default {
21
21
  appVersion: 'App Version',
22
22
  bcApp: 'A BC Online Application',
23
23
  bcGovLogo: 'Government of British Columbia Logo',
24
+ cancel: 'Cancel',
25
+ close: 'Close',
24
26
  contactInformation: 'Contact Information',
25
27
  copyright: 'Copyright',
26
28
  disclaimer: 'Disclaimer',
@@ -38,6 +38,7 @@
38
38
  --ui-shade-highlighted: var(--color-blue-50);
39
39
  --ui-shade-warning: #FAE9E9;
40
40
  --ui-radius: 0.1667rem;
41
+ --ui-container: var(--container-bcGovLg);
41
42
  }
42
43
 
43
44
  /* FUTURE: add dark themed colours (currently set to be the same) */
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.3.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",