@sbc-connect/nuxt-base 0.1.4 → 0.1.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/CHANGELOG.md +17 -0
- package/app/app.config.ts +72 -14
- package/app/components/Connect/Breadcrumb.vue +1 -1
- package/app/components/Connect/Header/Wrapper.vue +2 -2
- package/app/components/Connect/I18n/Helper.vue +24 -0
- package/app/components/Connect/Input.vue +32 -0
- package/app/components/Connect/PageSection.vue +57 -0
- package/app/components/Connect/Slideover/WhatsNew.vue +2 -2
- package/app/components/Connect/Spinner.vue +94 -0
- package/app/components/Connect/SystemBanner.vue +2 -2
- package/app/components/Connect/Textarea.vue +30 -0
- package/app/plugins/maska.client.ts +10 -0
- package/app/spa-loading-template.html +60 -38
- package/app/types/base-app-config.d.ts +15 -0
- package/app/types/base-page-meta.d.ts +8 -0
- package/app/utils/parseSpecialCharacters.ts +25 -0
- package/app/utils/setBreadcrumbs.ts +5 -0
- package/i18n/locales/en-CA.ts +3 -2
- package/modules/assets/runtime/assets/core-tw.css +10 -8
- package/nuxt.config.ts +20 -2
- package/package.json +6 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# @sbc-connect/nuxt-base
|
|
2
2
|
|
|
3
|
+
## 0.1.5
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#19](https://github.com/bcgov/connect-nuxt/pull/19) [`4231254`](https://github.com/bcgov/connect-nuxt/commit/42312540f5eec65f5d3979d5492bdfaa9bb0b079) Thanks [@deetz99](https://github.com/deetz99)! - Several components and utils
|
|
8
|
+
|
|
9
|
+
- ConnectInput
|
|
10
|
+
- ConnectTextarea
|
|
11
|
+
- ConnectI18nHelper
|
|
12
|
+
- ConnectSpinner
|
|
13
|
+
- ConnectPageSection
|
|
14
|
+
- parseSpecialCharacters util
|
|
15
|
+
- setBreadcrumbs util
|
|
16
|
+
- set nuxt ui default icons to use mdi instead of lucide icons
|
|
17
|
+
|
|
18
|
+
issue: bcgov/entity#29334
|
|
19
|
+
|
|
3
20
|
## 0.1.4
|
|
4
21
|
|
|
5
22
|
### Patch Changes
|
package/app/app.config.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable max-len */
|
|
1
2
|
export default defineAppConfig({
|
|
2
3
|
connect: {
|
|
3
4
|
header: {
|
|
@@ -39,12 +40,83 @@ export default defineAppConfig({
|
|
|
39
40
|
base: 'cursor-pointer'
|
|
40
41
|
}
|
|
41
42
|
},
|
|
43
|
+
card: {
|
|
44
|
+
slots: {
|
|
45
|
+
root: 'rounded-md'
|
|
46
|
+
}
|
|
47
|
+
},
|
|
42
48
|
dropdownMenu: {
|
|
43
49
|
slots: {
|
|
44
50
|
content: 'bg-secondary ring-0',
|
|
45
51
|
group: 'p-0'
|
|
46
52
|
}
|
|
47
53
|
},
|
|
54
|
+
icons: {
|
|
55
|
+
arrowLeft: 'i-mdi-arrow-left',
|
|
56
|
+
arrowRight: 'i-mdi-arrow-right',
|
|
57
|
+
check: 'i-mdi-check',
|
|
58
|
+
chevronDoubleLeft: 'i-mdi-chevron-double-left',
|
|
59
|
+
chevronDoubleRight: 'i-mdi-chevron-double-right',
|
|
60
|
+
chevronDown: 'i-mdi-menu-down',
|
|
61
|
+
chevronLeft: 'i-mdi-menu-left',
|
|
62
|
+
chevronRight: 'i-mdi-menu-right',
|
|
63
|
+
chevronUp: 'i-mdi-menu-up',
|
|
64
|
+
close: 'i-mdi-close',
|
|
65
|
+
ellipsis: 'i-mdi-dots-horizontal',
|
|
66
|
+
external: 'i-mdi-open-in-new',
|
|
67
|
+
file: 'i-mdi-file',
|
|
68
|
+
folder: 'i-mdi-folder',
|
|
69
|
+
folderOpen: 'i-mdi-folder-open',
|
|
70
|
+
loading: 'i-mdi-loading',
|
|
71
|
+
minus: 'i-mdi-minus',
|
|
72
|
+
plus: 'i-mdi-plus',
|
|
73
|
+
search: 'i-mdi-magnify',
|
|
74
|
+
upload: 'i-mdi-upload'
|
|
75
|
+
},
|
|
76
|
+
input: {
|
|
77
|
+
variants: {
|
|
78
|
+
size: {
|
|
79
|
+
bcGovLg: {
|
|
80
|
+
base: 'px-2.5 pb-2 pt-6 text-base gap-1.5',
|
|
81
|
+
leading: 'ps-2.5',
|
|
82
|
+
trailing: 'pe-2.5',
|
|
83
|
+
leadingIcon: 'size-5',
|
|
84
|
+
leadingAvatarSize: '2xs',
|
|
85
|
+
trailingIcon: 'size-5'
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
variant: {
|
|
89
|
+
bcGov: 'ring-0 ring-transparent peer rounded-t-sm rounded-b-none bg-shadePrimary shadow-input focus:ring-0 focus:outline-none focus:shadow-inputFocus text-neutralDark'
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
defaultVariants: {
|
|
93
|
+
size: 'bcGovLg',
|
|
94
|
+
color: 'primary',
|
|
95
|
+
variant: 'bcGov'
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
textarea: {
|
|
99
|
+
variants: {
|
|
100
|
+
size: {
|
|
101
|
+
bcGovLg: {
|
|
102
|
+
base: 'px-2.5 pb-1.5 pt-5 text-base gap-1.5',
|
|
103
|
+
leading: 'ps-2.5',
|
|
104
|
+
trailing: 'pe-2.5',
|
|
105
|
+
leadingIcon: 'size-5',
|
|
106
|
+
leadingAvatarSize: '2xs',
|
|
107
|
+
trailingIcon: 'size-5'
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
variant: {
|
|
111
|
+
bcGov: 'peer rounded-t-sm rounded-b-none bg-shadePrimary focus:ring-0 focus:outline-none shadow-input focus:shadow-inputFocus text-neutralDark'
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
defaultVariants: {
|
|
115
|
+
size: 'bcGovLg',
|
|
116
|
+
color: 'primary',
|
|
117
|
+
variant: 'bcGov'
|
|
118
|
+
}
|
|
119
|
+
},
|
|
48
120
|
tooltip: {
|
|
49
121
|
slots: {
|
|
50
122
|
content: 'bg-neutral ring-neutral text-secondary p-4',
|
|
@@ -53,17 +125,3 @@ export default defineAppConfig({
|
|
|
53
125
|
}
|
|
54
126
|
}
|
|
55
127
|
})
|
|
56
|
-
|
|
57
|
-
declare module '@nuxt/schema' {
|
|
58
|
-
interface AppConfigInput {
|
|
59
|
-
connect?: {
|
|
60
|
-
header?: {
|
|
61
|
-
localeSelect?: boolean
|
|
62
|
-
whatsNew?: boolean
|
|
63
|
-
}
|
|
64
|
-
footer?: {
|
|
65
|
-
versions?: string[]
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
@@ -38,7 +38,7 @@ function resolveBackHref() {
|
|
|
38
38
|
v-if="$route.meta.hideBreadcrumbs !== true"
|
|
39
39
|
class="bg-blue-350"
|
|
40
40
|
>
|
|
41
|
-
<div class="app-inner-container flex items-center px-4 py-2 gap-3">
|
|
41
|
+
<div class="app-inner-container flex items-center p-2 sm:px-4 py-2 gap-3">
|
|
42
42
|
<UButton
|
|
43
43
|
class="size-[28px] rounded-full px-1 bg-secondary hover:bg-secondary/75"
|
|
44
44
|
:disabled="breadcrumbs.length < 2"
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
<header
|
|
3
3
|
id="connect-header-wrapper"
|
|
4
4
|
data-testid="connect-header-wrapper"
|
|
5
|
-
class="relative border-b-2 border-brandLight bg-brandDark"
|
|
5
|
+
class="relative border-b-2 border-brandLight bg-brandDark p-2 sm:px-4"
|
|
6
6
|
>
|
|
7
7
|
<nav
|
|
8
|
-
class="app-inner-container
|
|
8
|
+
class="app-inner-container"
|
|
9
9
|
:aria-label="$t('connect.header.navLabel')"
|
|
10
10
|
>
|
|
11
11
|
<slot />
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
const props = defineProps({
|
|
3
|
+
translationPath: { type: String, required: true }
|
|
4
|
+
})
|
|
5
|
+
|
|
6
|
+
const attrs = useAttrs()
|
|
7
|
+
const { t } = useI18n()
|
|
8
|
+
|
|
9
|
+
const textToDisplay = computed(() => {
|
|
10
|
+
const translationProps = {
|
|
11
|
+
...attrs,
|
|
12
|
+
boldStart: '<strong>',
|
|
13
|
+
boldEnd: '</strong>',
|
|
14
|
+
italicStart: '<em>',
|
|
15
|
+
italicEnd: '</em>'
|
|
16
|
+
}
|
|
17
|
+
return t(props.translationPath, translationProps)
|
|
18
|
+
})
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
<template>
|
|
22
|
+
<!-- eslint-disable-next-line vue/no-v-html -->
|
|
23
|
+
<span v-html="textToDisplay" />
|
|
24
|
+
</template>
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
const model = defineModel<string>({ required: true })
|
|
3
|
+
|
|
4
|
+
defineProps<{
|
|
5
|
+
id: string
|
|
6
|
+
label: string
|
|
7
|
+
mask?: string
|
|
8
|
+
invalid?: boolean
|
|
9
|
+
}>()
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<template>
|
|
13
|
+
<UInput
|
|
14
|
+
:id
|
|
15
|
+
v-model.trim="model"
|
|
16
|
+
v-maska="mask"
|
|
17
|
+
:data-testid="id"
|
|
18
|
+
placeholder=" "
|
|
19
|
+
class="w-full grow"
|
|
20
|
+
:ui="{
|
|
21
|
+
base: invalid ? 'ring-0 shadow-inputError focus:shadow-inputError' : '',
|
|
22
|
+
}"
|
|
23
|
+
>
|
|
24
|
+
<label
|
|
25
|
+
:for="id"
|
|
26
|
+
class="floating-label-input"
|
|
27
|
+
:class="invalid ? 'text-error' : ''"
|
|
28
|
+
>
|
|
29
|
+
{{ label }}
|
|
30
|
+
</label>
|
|
31
|
+
</UInput>
|
|
32
|
+
</template>
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { ButtonProps } from '#ui/types'
|
|
3
|
+
|
|
4
|
+
defineProps<{
|
|
5
|
+
heading?: {
|
|
6
|
+
label?: string
|
|
7
|
+
labelClass?: string
|
|
8
|
+
level?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'
|
|
9
|
+
icon?: string
|
|
10
|
+
iconClass?: string
|
|
11
|
+
ui?: string
|
|
12
|
+
}
|
|
13
|
+
uiBody?: string
|
|
14
|
+
actions?: ButtonProps[]
|
|
15
|
+
}>()
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
<template>
|
|
19
|
+
<UCard
|
|
20
|
+
as="section"
|
|
21
|
+
class="w-full"
|
|
22
|
+
variant="outline"
|
|
23
|
+
:ui="{
|
|
24
|
+
header: heading?.ui ?? 'bg-shadeSecondary px-4 py-4 sm:px-4 rounded-t-md',
|
|
25
|
+
body: uiBody ?? 'p-0 sm:p-0',
|
|
26
|
+
footer: 'p-0 sm:p-0',
|
|
27
|
+
}"
|
|
28
|
+
>
|
|
29
|
+
<template v-if="heading?.label || $slots.header" #header>
|
|
30
|
+
<slot name="header">
|
|
31
|
+
<div class="flex items-center justify-between gap-2.5">
|
|
32
|
+
<component :is="heading?.level || 'h2'">
|
|
33
|
+
<div class="flex items-center gap-2.5">
|
|
34
|
+
<UIcon
|
|
35
|
+
v-if="heading?.icon"
|
|
36
|
+
:name="heading.icon"
|
|
37
|
+
:class="heading?.iconClass || 'size-6 shrink-0 text-primary'"
|
|
38
|
+
/>
|
|
39
|
+
<span :class="heading?.labelClass || 'font-semibold text-neutralDark text-base'">
|
|
40
|
+
{{ heading?.label }}
|
|
41
|
+
</span>
|
|
42
|
+
</div>
|
|
43
|
+
</component>
|
|
44
|
+
|
|
45
|
+
<div class="flex items-center gap-2.5">
|
|
46
|
+
<UButton
|
|
47
|
+
v-for="(action, i) in actions"
|
|
48
|
+
:key="i"
|
|
49
|
+
v-bind="action"
|
|
50
|
+
/>
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
</slot>
|
|
54
|
+
</template>
|
|
55
|
+
<slot />
|
|
56
|
+
</UCard>
|
|
57
|
+
</template>
|
|
@@ -14,7 +14,7 @@ defineProps<{
|
|
|
14
14
|
:close="{
|
|
15
15
|
color: 'neutral',
|
|
16
16
|
variant: 'ghost',
|
|
17
|
-
class: 'cursor-pointer hover:bg-
|
|
17
|
+
class: 'cursor-pointer hover:bg-shadePrimary/50 focus-visible:bg-transparent focus-visible:ring-2 rounded-full',
|
|
18
18
|
}"
|
|
19
19
|
:ui="{
|
|
20
20
|
header: 'bg-brandLight',
|
|
@@ -55,7 +55,7 @@ defineProps<{
|
|
|
55
55
|
<!-- must style globally for vhtml style to work -->
|
|
56
56
|
<style>
|
|
57
57
|
.vhtml a {
|
|
58
|
-
color: var(--ui-
|
|
58
|
+
color: var(--ui-mark);
|
|
59
59
|
text-decoration: underline;
|
|
60
60
|
}
|
|
61
61
|
</style>
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
const props = defineProps({
|
|
3
|
+
fullscreen: {
|
|
4
|
+
type: Boolean,
|
|
5
|
+
default: false
|
|
6
|
+
},
|
|
7
|
+
size: {
|
|
8
|
+
type: Number,
|
|
9
|
+
default: 75
|
|
10
|
+
}
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
const spinnerStyle = computed(() => ({
|
|
14
|
+
'--spinner-size': `${props.size}px`,
|
|
15
|
+
'--spinner-margin': `${props.size / -2}px`
|
|
16
|
+
}))
|
|
17
|
+
</script>
|
|
18
|
+
|
|
19
|
+
<template>
|
|
20
|
+
<!-- eslint-disable tailwindcss/no-custom-classname -->
|
|
21
|
+
<Teleport v-if="fullscreen" to="body">
|
|
22
|
+
<div class="fixed inset-0 z-[999] h-screen w-screen bg-gray-100 opacity-50" />
|
|
23
|
+
<svg
|
|
24
|
+
class="spinner fixed"
|
|
25
|
+
viewBox="0 0 50 50"
|
|
26
|
+
:style="spinnerStyle"
|
|
27
|
+
>
|
|
28
|
+
<circle
|
|
29
|
+
class="path"
|
|
30
|
+
cx="25"
|
|
31
|
+
cy="25"
|
|
32
|
+
r="20"
|
|
33
|
+
fill="none"
|
|
34
|
+
stroke-width="5"
|
|
35
|
+
/>
|
|
36
|
+
</svg>
|
|
37
|
+
</Teleport>
|
|
38
|
+
<svg
|
|
39
|
+
v-else
|
|
40
|
+
class="spinner absolute"
|
|
41
|
+
viewBox="0 0 50 50"
|
|
42
|
+
:style="spinnerStyle"
|
|
43
|
+
>
|
|
44
|
+
<circle
|
|
45
|
+
class="path"
|
|
46
|
+
cx="25"
|
|
47
|
+
cy="25"
|
|
48
|
+
r="20"
|
|
49
|
+
fill="none"
|
|
50
|
+
stroke-width="5"
|
|
51
|
+
/>
|
|
52
|
+
</svg>
|
|
53
|
+
</template>
|
|
54
|
+
|
|
55
|
+
<style scoped>
|
|
56
|
+
.spinner {
|
|
57
|
+
animation: rotate 1.5s linear infinite;
|
|
58
|
+
z-index: 10000;
|
|
59
|
+
top: 50%;
|
|
60
|
+
left: 50%;
|
|
61
|
+
margin-top: var(--spinner-margin, -37.5px);
|
|
62
|
+
margin-left: var(--spinner-margin, -37.5px);
|
|
63
|
+
width: var(--spinner-size, 75px);
|
|
64
|
+
height: var(--spinner-size, 75px);
|
|
65
|
+
transform-origin: 50% 50%;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.spinner .path {
|
|
69
|
+
stroke: #1669bb;
|
|
70
|
+
stroke-linecap: round;
|
|
71
|
+
animation: dash 1.25s ease-in-out infinite;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
@keyframes rotate {
|
|
75
|
+
100% {
|
|
76
|
+
transform: rotate(360deg);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
@keyframes dash {
|
|
81
|
+
0% {
|
|
82
|
+
stroke-dasharray: 1, 150;
|
|
83
|
+
stroke-dashoffset: 0;
|
|
84
|
+
}
|
|
85
|
+
50% {
|
|
86
|
+
stroke-dasharray: 90, 150;
|
|
87
|
+
stroke-dashoffset: -35;
|
|
88
|
+
}
|
|
89
|
+
100% {
|
|
90
|
+
stroke-dasharray: 90, 150;
|
|
91
|
+
stroke-dashoffset: -124;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
</style>
|
|
@@ -15,7 +15,7 @@ onMounted(async () => {
|
|
|
15
15
|
</script>
|
|
16
16
|
|
|
17
17
|
<template>
|
|
18
|
-
<div class="bg-brandLight
|
|
18
|
+
<div class="bg-brandLight">
|
|
19
19
|
<UAlert
|
|
20
20
|
v-show="!!message && !close"
|
|
21
21
|
class="py-0"
|
|
@@ -23,7 +23,7 @@ onMounted(async () => {
|
|
|
23
23
|
:close="dismissible"
|
|
24
24
|
close-icon="i-mdi-close"
|
|
25
25
|
:ui="{
|
|
26
|
-
root: 'rounded-none bg-brandLight p-
|
|
26
|
+
root: 'rounded-none bg-brandLight p-2 sm:px-4 app-inner-container',
|
|
27
27
|
wrapper: 'bg-brandLight',
|
|
28
28
|
close: 'mt-2 text-neutralDark',
|
|
29
29
|
}"
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
const model = defineModel<string>({ required: true })
|
|
3
|
+
|
|
4
|
+
defineProps<{
|
|
5
|
+
id: string
|
|
6
|
+
label: string
|
|
7
|
+
invalid?: boolean
|
|
8
|
+
}>()
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
<template>
|
|
12
|
+
<UTextarea
|
|
13
|
+
:id
|
|
14
|
+
v-model.trim="model"
|
|
15
|
+
:data-testid="id"
|
|
16
|
+
placeholder=" "
|
|
17
|
+
class="w-full grow"
|
|
18
|
+
:ui="{
|
|
19
|
+
base: invalid ? 'ring-0 shadow-inputError focus:shadow-inputError resize-none' : 'resize-none',
|
|
20
|
+
}"
|
|
21
|
+
>
|
|
22
|
+
<label
|
|
23
|
+
class="floating-label-textarea bg-shadePrimary w-[96%] flex-1 pt-1 -mt-1"
|
|
24
|
+
:class="invalid ? 'text-error' : ''"
|
|
25
|
+
:for="id"
|
|
26
|
+
>
|
|
27
|
+
{{ label }}
|
|
28
|
+
</label>
|
|
29
|
+
</UTextarea>
|
|
30
|
+
</template>
|
|
@@ -1,39 +1,61 @@
|
|
|
1
|
-
<
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
border: solid 5px transparent;
|
|
14
|
-
border-top-color: #1669bb;
|
|
15
|
-
border-left-color: #1669bb;
|
|
16
|
-
border-bottom-color: #efefef;
|
|
17
|
-
border-right-color: #efefef;
|
|
18
|
-
border-radius: 50%;
|
|
19
|
-
-webkit-animation: loader 400ms linear infinite;
|
|
20
|
-
animation: loader 400ms linear infinite;
|
|
21
|
-
}
|
|
1
|
+
<head>
|
|
2
|
+
<title>Loading...</title>
|
|
3
|
+
<style>
|
|
4
|
+
.loading-container {
|
|
5
|
+
position: fixed;
|
|
6
|
+
inset: 0;
|
|
7
|
+
z-index: 9999;
|
|
8
|
+
background-color: rgba(241, 243, 245, 0.8);
|
|
9
|
+
display: flex;
|
|
10
|
+
justify-content: center;
|
|
11
|
+
align-items: center;
|
|
12
|
+
}
|
|
22
13
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
14
|
+
.loader {
|
|
15
|
+
display: block;
|
|
16
|
+
width: 75px;
|
|
17
|
+
height: 75px;
|
|
18
|
+
animation: rotate 1.5s linear infinite;
|
|
19
|
+
transform-origin: 50% 50%;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.loader .path {
|
|
23
|
+
stroke: #1669bb;
|
|
24
|
+
stroke-linecap: round;
|
|
25
|
+
animation: dash 1.25s ease-in-out infinite;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@keyframes rotate {
|
|
29
|
+
100% {
|
|
30
|
+
transform: rotate(360deg);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@keyframes dash {
|
|
35
|
+
0% {
|
|
36
|
+
stroke-dasharray: 1, 150;
|
|
37
|
+
stroke-dashoffset: 0;
|
|
38
|
+
}
|
|
39
|
+
50% {
|
|
40
|
+
stroke-dasharray: 90, 150;
|
|
41
|
+
stroke-dashoffset: -35;
|
|
42
|
+
}
|
|
43
|
+
100% {
|
|
44
|
+
stroke-dasharray: 90, 150;
|
|
45
|
+
stroke-dashoffset: -124;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
</style>
|
|
49
|
+
</head>
|
|
50
|
+
<div class="loading-container">
|
|
51
|
+
<svg class="loader" viewBox="0 0 50 50">
|
|
52
|
+
<circle
|
|
53
|
+
class="path"
|
|
54
|
+
cx="25"
|
|
55
|
+
cy="25"
|
|
56
|
+
r="20"
|
|
57
|
+
fill="none"
|
|
58
|
+
stroke-width="5"
|
|
59
|
+
/>
|
|
60
|
+
</svg>
|
|
61
|
+
</div>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parses a string to decode HTML entities and remove HTML tags.
|
|
3
|
+
*
|
|
4
|
+
* @param text The string to parse.
|
|
5
|
+
* @param fallback The fallback text to return if the input is null or undefined.
|
|
6
|
+
* @returns The sanitized string.
|
|
7
|
+
*/
|
|
8
|
+
export function parseSpecialCharacters(text: string | undefined | null, fallback = 'N/A'): string {
|
|
9
|
+
// Return fallback text if the input is null or undefined.
|
|
10
|
+
if (text === null || text === undefined) {
|
|
11
|
+
return fallback
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const inputText = String(text)
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
const parser = new DOMParser()
|
|
18
|
+
const doc = parser.parseFromString(inputText, 'text/html')
|
|
19
|
+
|
|
20
|
+
return doc.body.textContent || fallback
|
|
21
|
+
} catch (error) {
|
|
22
|
+
console.error(`Error parsing special characters in: ${inputText}`, error)
|
|
23
|
+
return fallback
|
|
24
|
+
}
|
|
25
|
+
}
|
package/i18n/locales/en-CA.ts
CHANGED
|
@@ -54,10 +54,11 @@ export default {
|
|
|
54
54
|
}
|
|
55
55
|
},
|
|
56
56
|
test: {
|
|
57
|
-
|
|
57
|
+
i18n: {
|
|
58
58
|
strong: 'This should have {boldStart} bold {boldEnd} text',
|
|
59
59
|
strongWithProps: 'This should have {boldStart} bold {boldEnd} text and allow a {prop}',
|
|
60
|
-
italic: 'Italic test {italicStart} goes here {italicEnd}.'
|
|
60
|
+
italic: 'Italic test {italicStart} goes here {italicEnd}.',
|
|
61
|
+
computed: 'This text will be updated. Updated {boldStart}{count}{boldEnd} times.'
|
|
61
62
|
}
|
|
62
63
|
}
|
|
63
64
|
}
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
--ui-lineDark: #6F7780;
|
|
18
18
|
--ui-lineLight: var(--color-gray-300);
|
|
19
19
|
--ui-lineSpecial: #899EB2;
|
|
20
|
-
--ui-
|
|
21
|
-
--ui-
|
|
20
|
+
--ui-mark: #1A5A96;
|
|
21
|
+
--ui-markHover: #0000EE;
|
|
22
22
|
--ui-neutral: var(--color-gray-700);
|
|
23
23
|
--ui-neutralDark: var(--color-gray-900);
|
|
24
24
|
--ui-neutralLight: #757575;
|
|
@@ -45,8 +45,8 @@
|
|
|
45
45
|
--ui-lineDark: #6F7780;
|
|
46
46
|
--ui-lineLight: var(--color-gray-300);
|
|
47
47
|
--ui-lineSpecial: #899EB2;
|
|
48
|
-
--ui-
|
|
49
|
-
--ui-
|
|
48
|
+
--ui-mark: #1A5A96;
|
|
49
|
+
--ui-markHover: #0000EE;
|
|
50
50
|
--ui-neutral: var(--color-gray-700);
|
|
51
51
|
--ui-neutralDark: var(--color-gray-900);
|
|
52
52
|
--ui-neutralLight: #757575;
|
|
@@ -67,14 +67,16 @@
|
|
|
67
67
|
/* widths */
|
|
68
68
|
--container-bcGovMd: 1020px;
|
|
69
69
|
--container-bcGovLg: 1360px;
|
|
70
|
-
--container-
|
|
70
|
+
--container-input: 600px;
|
|
71
71
|
|
|
72
72
|
/* list style types */
|
|
73
73
|
--marker-alpha: lower-alpha;
|
|
74
74
|
--marker-upper-alpha: upper-alpha;
|
|
75
75
|
|
|
76
76
|
/* box shadow */
|
|
77
|
-
--shadow-
|
|
77
|
+
--shadow-input: inset 0 -1px 0 0px var(--ui-neutral);
|
|
78
|
+
--shadow-inputFocus: inset 0 -2px 0 0px var(--ui-primary);
|
|
79
|
+
--shadow-inputError: inset 0 -2px 0 0px var(--ui-error);
|
|
78
80
|
|
|
79
81
|
/* GRAY */
|
|
80
82
|
--color-gray-50: #f8f9fa;
|
|
@@ -250,10 +252,10 @@ body {
|
|
|
250
252
|
|
|
251
253
|
/* floating labels */
|
|
252
254
|
.floating-label-input {
|
|
253
|
-
@apply pointer-events-none absolute left-0 top-
|
|
255
|
+
@apply pointer-events-none absolute left-0 top-3 text-neutralDark transition-all motion-reduce:transition-none duration-200 text-xs font-medium px-2.5 peer-focus:top-3 peer-focus:text-xs peer-placeholder-shown:text-sm peer-placeholder-shown:top-1/2 -translate-y-1/2 peer-focus:text-primary;
|
|
254
256
|
}
|
|
255
257
|
|
|
256
258
|
.floating-label-textarea {
|
|
257
|
-
@apply pointer-events-none absolute left-0 top-1 text-neutralDark text-xs font-medium px-2.5 transition-all peer-focus:top-1 peer-focus:text-xs peer-placeholder-shown:text-sm peer-placeholder-shown:top-2.5 peer-focus:translate-none peer-focus:text-primary;
|
|
259
|
+
@apply pointer-events-none absolute left-0 top-1 text-neutralDark text-xs font-medium px-2.5 transition-all duration-200 peer-focus:top-1 peer-focus:text-xs peer-placeholder-shown:text-sm peer-placeholder-shown:top-2.5 peer-focus:translate-none peer-focus:text-primary;
|
|
258
260
|
}
|
|
259
261
|
}
|
package/nuxt.config.ts
CHANGED
|
@@ -19,7 +19,7 @@ export default defineNuxtConfig({
|
|
|
19
19
|
compatibilityDate: '2025-07-10',
|
|
20
20
|
|
|
21
21
|
imports: {
|
|
22
|
-
dirs: ['interfaces']
|
|
22
|
+
dirs: ['interfaces', 'types']
|
|
23
23
|
},
|
|
24
24
|
|
|
25
25
|
modules: [
|
|
@@ -85,10 +85,28 @@ export default defineNuxtConfig({
|
|
|
85
85
|
clientBundle: {
|
|
86
86
|
icons: [
|
|
87
87
|
'mdi:arrow-left',
|
|
88
|
+
'mdi:arrow-right',
|
|
88
89
|
'mdi:info-outline',
|
|
89
90
|
'mdi:information',
|
|
90
91
|
'mdi:web',
|
|
91
|
-
'mdi:check'
|
|
92
|
+
'mdi:check',
|
|
93
|
+
'mdi:chevron-double-left',
|
|
94
|
+
'mdi:chevron-double-right',
|
|
95
|
+
'mdi:menu-down',
|
|
96
|
+
'mdi:menu-left',
|
|
97
|
+
'mdi:menu-right',
|
|
98
|
+
'mdi:menu-up',
|
|
99
|
+
'mdi:close',
|
|
100
|
+
'mdi:dots-horizontal',
|
|
101
|
+
'mdi:open-in-new',
|
|
102
|
+
'mdi:file',
|
|
103
|
+
'mdi:folder',
|
|
104
|
+
'mdi:folder-open',
|
|
105
|
+
'mdi:loading',
|
|
106
|
+
'mdi:minus',
|
|
107
|
+
'mdi:plus',
|
|
108
|
+
'mdi:magnify',
|
|
109
|
+
'mdi:upload'
|
|
92
110
|
]
|
|
93
111
|
}
|
|
94
112
|
},
|
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.
|
|
4
|
+
"version": "0.1.5",
|
|
5
5
|
"repository": "github:bcgov/connect-nuxt",
|
|
6
6
|
"license": "BSD-3-Clause",
|
|
7
7
|
"main": "./nuxt.config.ts",
|
|
@@ -13,19 +13,20 @@
|
|
|
13
13
|
"launchdarkly-vue-client-sdk": "^2.4.1",
|
|
14
14
|
"@vueuse/nuxt": "^13.5.0",
|
|
15
15
|
"@vueuse/core": "^13.5.0",
|
|
16
|
-
"lodash-es": "^4.17.21"
|
|
16
|
+
"lodash-es": "^4.17.21",
|
|
17
|
+
"maska": "^3.1.1"
|
|
17
18
|
},
|
|
18
19
|
"devDependencies": {
|
|
19
20
|
"@axe-core/playwright": "^4.10.2",
|
|
20
21
|
"@vitest/coverage-v8": "^3.2.4",
|
|
21
22
|
"dotenv": "^17.2.0",
|
|
22
|
-
"nuxt": "4.0.0",
|
|
23
|
+
"nuxt": "^4.0.0",
|
|
23
24
|
"typescript": "^5.8.3",
|
|
24
25
|
"vue-tsc": "^3.0.3",
|
|
25
26
|
"@types/lodash-es": "^4.17.12",
|
|
26
|
-
"@sbc-connect/eslint-config": "0.0.5",
|
|
27
27
|
"@sbc-connect/playwright-config": "0.0.4",
|
|
28
|
-
"@sbc-connect/vitest-config": "0.0.5"
|
|
28
|
+
"@sbc-connect/vitest-config": "0.0.5",
|
|
29
|
+
"@sbc-connect/eslint-config": "0.0.5"
|
|
29
30
|
},
|
|
30
31
|
"scripts": {
|
|
31
32
|
"preinstall": "npx only-allow pnpm",
|