@imaginario27/air-ui-ds 1.0.16 → 1.0.18
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/assets/css/main.css +237 -237
- package/assets/images/logo/air-ui-logo-color.svg +34 -34
- package/assets/images/logo/air-ui-logo-white.svg +8 -8
- package/components/layouts/Error.vue +238 -0
- package/components/layouts/Footer.vue +110 -0
- package/components/layouts/Heading.vue +39 -10
- package/components/layouts/Overtitle.vue +28 -2
- package/components/layouts/headers/ContentPageHeader.vue +0 -1
- package/eslint.config.mjs +15 -15
- package/models/enums/headings.ts +2 -0
- package/models/types/navigation.ts +4 -3
- package/models/types/pdfExportTable.ts +5 -5
- package/nuxt.config.ts +39 -39
- package/package.json +57 -57
- package/tsconfig.json +7 -7
- package/components/layouts/ContainerWrapper.vue +0 -13
- package/components/layouts/headers/WebAppHeader.vue +0 -54
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
:class="[
|
|
4
|
+
'w-full',
|
|
5
|
+
isFullScreen && 'h-screen',
|
|
6
|
+
'px-content-side-padding',
|
|
7
|
+
'py-[10vw] md:py-[20vw]',
|
|
8
|
+
'flex',
|
|
9
|
+
orientation === Orientation.VERTICAL ? 'flex-col' : 'flex-col md:flex-row',
|
|
10
|
+
'gap-9',
|
|
11
|
+
'items-center',
|
|
12
|
+
'justify-center',
|
|
13
|
+
]"
|
|
14
|
+
>
|
|
15
|
+
<!-- Slot for images, illustrations or other visual elements -->
|
|
16
|
+
<slot name="visual-left" />
|
|
17
|
+
|
|
18
|
+
<!-- Body -->
|
|
19
|
+
<div
|
|
20
|
+
:class="[
|
|
21
|
+
'w-full',
|
|
22
|
+
'gap-9',
|
|
23
|
+
'flex',
|
|
24
|
+
'flex-col',
|
|
25
|
+
contentAlignmentClass,
|
|
26
|
+
]"
|
|
27
|
+
>
|
|
28
|
+
<slot name="visual-top" />
|
|
29
|
+
|
|
30
|
+
<ContainedIcon
|
|
31
|
+
v-if="!$slots['visual-top'] && showIcon"
|
|
32
|
+
:color="ColorAccent.DANGER"
|
|
33
|
+
:icon
|
|
34
|
+
:size="IconContainerSize.XXL"
|
|
35
|
+
/>
|
|
36
|
+
|
|
37
|
+
<div
|
|
38
|
+
v-if="!$slots['description']"
|
|
39
|
+
:class="[
|
|
40
|
+
'flex',
|
|
41
|
+
'flex-col',
|
|
42
|
+
'gap-4',
|
|
43
|
+
contentAlignmentClass,
|
|
44
|
+
'w-full',
|
|
45
|
+
'max-w-[600px]',
|
|
46
|
+
]"
|
|
47
|
+
>
|
|
48
|
+
<!--
|
|
49
|
+
Overtitle will only display if useGenericErrorTitle is true.
|
|
50
|
+
Otherwise, it will not be displayed because the error code is shown as the title
|
|
51
|
+
-->
|
|
52
|
+
<Heading
|
|
53
|
+
:title="errorTitle"
|
|
54
|
+
:overtitle="useGenericErrorTitle ? error.statusCode.toString() : ''"
|
|
55
|
+
:align="alignContent"
|
|
56
|
+
:size="HeadingSize.MD"
|
|
57
|
+
:isMobileCentered
|
|
58
|
+
/>
|
|
59
|
+
|
|
60
|
+
<p
|
|
61
|
+
:class="[
|
|
62
|
+
'text-text-neutral-subtle',
|
|
63
|
+
'font-semibold',
|
|
64
|
+
textAlignmentClass,
|
|
65
|
+
'leading-6',
|
|
66
|
+
]"
|
|
67
|
+
>
|
|
68
|
+
{{
|
|
69
|
+
error.statusCode === 404
|
|
70
|
+
? pageNotFoundMessage
|
|
71
|
+
: error.message ?? genericErrorMessage
|
|
72
|
+
}}
|
|
73
|
+
</p>
|
|
74
|
+
</div>
|
|
75
|
+
|
|
76
|
+
<slot name="description" />
|
|
77
|
+
|
|
78
|
+
<!-- Actions -->
|
|
79
|
+
<div
|
|
80
|
+
:class="[
|
|
81
|
+
'w-full',
|
|
82
|
+
'flex',
|
|
83
|
+
'gap-3',
|
|
84
|
+
actionsAlignmentClass,
|
|
85
|
+
'flex-col',
|
|
86
|
+
'md:flex-row',
|
|
87
|
+
'mb-4 md:mb-10' // Visual fix to push content a bit up
|
|
88
|
+
]"
|
|
89
|
+
>
|
|
90
|
+
<ActionButton
|
|
91
|
+
v-if="!$slots['actions']"
|
|
92
|
+
:actionType="ButtonActionType.LINK"
|
|
93
|
+
:text="backToHomeText"
|
|
94
|
+
class="w-full md:w-auto"
|
|
95
|
+
:icon="backToHomeIcon"
|
|
96
|
+
:iconPosition="IconPosition.LEFT"
|
|
97
|
+
:to="homeRoute"
|
|
98
|
+
/>
|
|
99
|
+
|
|
100
|
+
<slot name="actions" />
|
|
101
|
+
</div>
|
|
102
|
+
</div>
|
|
103
|
+
|
|
104
|
+
<!-- Slot for images, illustrations or other visual elements -->
|
|
105
|
+
<slot name="visual-right" />
|
|
106
|
+
</div>
|
|
107
|
+
</template>
|
|
108
|
+
<script setup lang="ts">
|
|
109
|
+
// Imports
|
|
110
|
+
import type { NuxtError } from "#app"
|
|
111
|
+
|
|
112
|
+
// Props
|
|
113
|
+
const props = defineProps({
|
|
114
|
+
error: {
|
|
115
|
+
type: Object as PropType<NuxtError>,
|
|
116
|
+
required: true,
|
|
117
|
+
},
|
|
118
|
+
showIcon: {
|
|
119
|
+
type: Boolean as PropType<boolean>,
|
|
120
|
+
default: true,
|
|
121
|
+
},
|
|
122
|
+
icon: {
|
|
123
|
+
type: String as PropType<any>,
|
|
124
|
+
default: "mdiAlertCircleOutline",
|
|
125
|
+
},
|
|
126
|
+
pageNotFoundTitle: {
|
|
127
|
+
type: String as PropType<string>,
|
|
128
|
+
default: "Page not found",
|
|
129
|
+
},
|
|
130
|
+
pageNotFoundMessage: {
|
|
131
|
+
type: String as PropType<string>,
|
|
132
|
+
default: "The page you are looking for does not exist or may have been moved. Please try with another page.",
|
|
133
|
+
},
|
|
134
|
+
useGenericErrorTitle: {
|
|
135
|
+
type: Boolean as PropType<boolean>,
|
|
136
|
+
default: false,
|
|
137
|
+
},
|
|
138
|
+
genericErrorTitle: {
|
|
139
|
+
type: String as PropType<string>,
|
|
140
|
+
default: "Oops! Something went wrong",
|
|
141
|
+
},
|
|
142
|
+
genericErrorMessage: {
|
|
143
|
+
type: String as PropType<string>,
|
|
144
|
+
default: "Something went wrong on our end. Please try again later.",
|
|
145
|
+
},
|
|
146
|
+
backToHomeText: {
|
|
147
|
+
type: String as PropType<string>,
|
|
148
|
+
default: "Back to home page",
|
|
149
|
+
},
|
|
150
|
+
backToHomeIcon: {
|
|
151
|
+
type: String as PropType<string>,
|
|
152
|
+
default: "mdiHomeOutline",
|
|
153
|
+
},
|
|
154
|
+
homeRoute: {
|
|
155
|
+
type: String as PropType<string>,
|
|
156
|
+
default: "/",
|
|
157
|
+
},
|
|
158
|
+
isFullScreen: {
|
|
159
|
+
type: Boolean as PropType<boolean>,
|
|
160
|
+
default: true,
|
|
161
|
+
},
|
|
162
|
+
orientation: {
|
|
163
|
+
type: String as PropType<Orientation>,
|
|
164
|
+
default: Orientation.HORIZONTAL,
|
|
165
|
+
validator: (value: Orientation) => Object.values(Orientation).includes(value),
|
|
166
|
+
},
|
|
167
|
+
alignContent: {
|
|
168
|
+
type: String as PropType<Align>,
|
|
169
|
+
default: Align.LEFT,
|
|
170
|
+
validator: (value: Align) => Object.values(Align).includes(value),
|
|
171
|
+
},
|
|
172
|
+
isMobileCentered: {
|
|
173
|
+
type: Boolean as PropType<boolean>,
|
|
174
|
+
default: true,
|
|
175
|
+
},
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
// Computed
|
|
179
|
+
const errorTitle = computed(() => {
|
|
180
|
+
if (props.useGenericErrorTitle) {
|
|
181
|
+
return props.genericErrorTitle
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (props.error.statusCode === 404 || props.error.statusCode === 400) {
|
|
185
|
+
return props.pageNotFoundTitle
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return String(props.error.statusCode)
|
|
189
|
+
})
|
|
190
|
+
|
|
191
|
+
const pageTitleText = computed(() => errorTitle.value)
|
|
192
|
+
|
|
193
|
+
// Dynamically set the page title with a watcher (only for error page)
|
|
194
|
+
watchEffect(() => {
|
|
195
|
+
document.title = pageTitle(pageTitleText.value, App.NAME)
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
// Computed classes
|
|
199
|
+
const contentAlignmentClass = computed(() => {
|
|
200
|
+
const base = {
|
|
201
|
+
[Align.LEFT]: 'md:items-start',
|
|
202
|
+
[Align.CENTER]: 'md:items-center',
|
|
203
|
+
[Align.RIGHT]: 'md:items-end',
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return [
|
|
207
|
+
props.isMobileCentered ? 'items-center' : '',
|
|
208
|
+
base[props.alignContent as Align] || 'md:items-center',
|
|
209
|
+
].join(' ').trim()
|
|
210
|
+
})
|
|
211
|
+
|
|
212
|
+
const actionsAlignmentClass = computed(() => {
|
|
213
|
+
const base = {
|
|
214
|
+
[Align.LEFT]: 'md:items-start md:justify-start',
|
|
215
|
+
[Align.CENTER]: 'md:items-center md:justify-center',
|
|
216
|
+
[Align.RIGHT]: 'md:items-end md:justify-end',
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return [
|
|
220
|
+
props.isMobileCentered ? 'items-center justify-center' : '',
|
|
221
|
+
base[props.alignContent as Align] || 'md:items-center md:justify-center',
|
|
222
|
+
].join(' ').trim()
|
|
223
|
+
})
|
|
224
|
+
|
|
225
|
+
const textAlignmentClass = computed(() => {
|
|
226
|
+
const base = {
|
|
227
|
+
[Align.LEFT]: 'md:text-left',
|
|
228
|
+
[Align.CENTER]: 'md:text-center',
|
|
229
|
+
[Align.RIGHT]: 'md:text-right',
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return [
|
|
233
|
+
props.isMobileCentered ? 'text-center' : '',
|
|
234
|
+
base[props.alignContent as Align] || 'md:text-center',
|
|
235
|
+
].join(' ').trim()
|
|
236
|
+
})
|
|
237
|
+
|
|
238
|
+
</script>
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<footer
|
|
3
|
+
:class="[
|
|
4
|
+
'w-full',
|
|
5
|
+
'bg-background-surface',
|
|
6
|
+
'py-section-xs',
|
|
7
|
+
hasSidePadding && 'px-content-side-padding-mobile md:px-content-side-padding',
|
|
8
|
+
]"
|
|
9
|
+
>
|
|
10
|
+
<MaxWidthContainer
|
|
11
|
+
:class="[!hasContentMaxWidth && '!max-w-full']"
|
|
12
|
+
>
|
|
13
|
+
<template v-if="!$slots['default']">
|
|
14
|
+
<div
|
|
15
|
+
:class="[
|
|
16
|
+
'w-full',
|
|
17
|
+
'flex',
|
|
18
|
+
'flex-col',
|
|
19
|
+
isMobileCentered &&'items-center text-center',
|
|
20
|
+
'gap-10',
|
|
21
|
+
'lg:flex-row',
|
|
22
|
+
'lg:items-start',
|
|
23
|
+
'lg:text-left',
|
|
24
|
+
'lg:justify-between',
|
|
25
|
+
]"
|
|
26
|
+
>
|
|
27
|
+
<span class="text-sm text-text-neutral-subtle">
|
|
28
|
+
{{ credits }}
|
|
29
|
+
</span>
|
|
30
|
+
|
|
31
|
+
<nav v-if="menuItems.length">
|
|
32
|
+
<ul class="flex flex-col lg:flex-row gap-5">
|
|
33
|
+
<li
|
|
34
|
+
v-for="(item, index) in menuItems"
|
|
35
|
+
:key="index"
|
|
36
|
+
>
|
|
37
|
+
<NuxtLink
|
|
38
|
+
:to="item.to"
|
|
39
|
+
:class="[
|
|
40
|
+
'text-sm',
|
|
41
|
+
'hover:text-text-primary-brand-hover',
|
|
42
|
+
'transition-colors',
|
|
43
|
+
]"
|
|
44
|
+
>
|
|
45
|
+
{{ item.text }}
|
|
46
|
+
</NuxtLink>
|
|
47
|
+
</li>
|
|
48
|
+
</ul>
|
|
49
|
+
</nav>
|
|
50
|
+
|
|
51
|
+
<div v-if="socialNetworks.length" class="flex gap-5">
|
|
52
|
+
<a
|
|
53
|
+
v-for="(network, index) in socialNetworks"
|
|
54
|
+
:key="index"
|
|
55
|
+
:href="network.link"
|
|
56
|
+
target="_blank"
|
|
57
|
+
rel="noopener noreferrer"
|
|
58
|
+
:class="[
|
|
59
|
+
'text-text-neutral-subtle',
|
|
60
|
+
'hover:text-text-primary-brand-hover',
|
|
61
|
+
'transition-colors',
|
|
62
|
+
]"
|
|
63
|
+
:aria-label="network.name"
|
|
64
|
+
>
|
|
65
|
+
<img
|
|
66
|
+
:src="network.icon"
|
|
67
|
+
:alt="`${network.name} icon`"
|
|
68
|
+
width="20"
|
|
69
|
+
height="20"
|
|
70
|
+
class="min-w-[20px] min-h-[20px]"
|
|
71
|
+
/>
|
|
72
|
+
</a>
|
|
73
|
+
</div>
|
|
74
|
+
</div>
|
|
75
|
+
</template>
|
|
76
|
+
<template v-else>
|
|
77
|
+
<slot />
|
|
78
|
+
</template>
|
|
79
|
+
</MaxWidthContainer>
|
|
80
|
+
</footer>
|
|
81
|
+
</template>
|
|
82
|
+
<script setup lang="ts">
|
|
83
|
+
// Props
|
|
84
|
+
defineProps({
|
|
85
|
+
credits: {
|
|
86
|
+
type: String as PropType<string>,
|
|
87
|
+
default: '© <year> <your-company>. All rights reserved.',
|
|
88
|
+
},
|
|
89
|
+
menuItems: {
|
|
90
|
+
type: Array as PropType<MenuItem[]>,
|
|
91
|
+
default: () => [],
|
|
92
|
+
},
|
|
93
|
+
socialNetworks: {
|
|
94
|
+
type: Array as PropType<SocialNetwork[]>,
|
|
95
|
+
default: () => [],
|
|
96
|
+
},
|
|
97
|
+
hasContentMaxWidth: {
|
|
98
|
+
type: Boolean as PropType<boolean>,
|
|
99
|
+
default: false,
|
|
100
|
+
},
|
|
101
|
+
hasSidePadding: {
|
|
102
|
+
type: Boolean as PropType<boolean>,
|
|
103
|
+
default: true,
|
|
104
|
+
},
|
|
105
|
+
isMobileCentered: {
|
|
106
|
+
type: Boolean as PropType<boolean>,
|
|
107
|
+
default: false,
|
|
108
|
+
},
|
|
109
|
+
})
|
|
110
|
+
</script>
|
|
@@ -3,26 +3,32 @@
|
|
|
3
3
|
:class="[
|
|
4
4
|
'w-full flex flex-col',
|
|
5
5
|
alignmentClasses,
|
|
6
|
-
titleClass,
|
|
7
6
|
]"
|
|
8
7
|
>
|
|
9
8
|
<!-- Overtitle -->
|
|
10
|
-
<
|
|
9
|
+
<span
|
|
11
10
|
v-if="overtitle"
|
|
12
11
|
:class="[
|
|
13
12
|
'font-semibold',
|
|
14
13
|
overtitleSizeClass,
|
|
15
14
|
'text-text-secondary-brand-default',
|
|
16
15
|
spaceOvertitleClass,
|
|
16
|
+
isOverTitleUppercase && 'uppercase',
|
|
17
|
+
overtitleClass,
|
|
17
18
|
]"
|
|
18
19
|
>
|
|
19
20
|
{{ overtitle }}
|
|
20
|
-
</
|
|
21
|
+
</span>
|
|
21
22
|
|
|
22
23
|
<!-- Dynamic title -->
|
|
23
24
|
<component
|
|
24
25
|
:is="headingTag"
|
|
25
|
-
:class="[
|
|
26
|
+
:class="[
|
|
27
|
+
titleSizeClass,
|
|
28
|
+
'font-semibold',
|
|
29
|
+
'text-text-default',
|
|
30
|
+
titleClass,
|
|
31
|
+
]"
|
|
26
32
|
>
|
|
27
33
|
{{ title }}
|
|
28
34
|
</component>
|
|
@@ -30,7 +36,12 @@
|
|
|
30
36
|
<!-- Description -->
|
|
31
37
|
<p
|
|
32
38
|
v-if="description"
|
|
33
|
-
:class="[
|
|
39
|
+
:class="[
|
|
40
|
+
descriptionSizeClass,
|
|
41
|
+
'text-text-neutral-subtle',
|
|
42
|
+
spaceDescriptionClass,
|
|
43
|
+
descriptionClass,
|
|
44
|
+
]"
|
|
34
45
|
>
|
|
35
46
|
{{ description }}
|
|
36
47
|
</p>
|
|
@@ -41,6 +52,10 @@
|
|
|
41
52
|
// Props
|
|
42
53
|
const props = defineProps({
|
|
43
54
|
overtitle: String as PropType<string>,
|
|
55
|
+
isOverTitleUppercase: {
|
|
56
|
+
type: Boolean as PropType<boolean>,
|
|
57
|
+
default: false,
|
|
58
|
+
},
|
|
44
59
|
title: {
|
|
45
60
|
type: String as PropType<string>,
|
|
46
61
|
default: 'Heading title'
|
|
@@ -64,23 +79,25 @@ const props = defineProps({
|
|
|
64
79
|
Object.values(HeadingSpacing).includes(value as HeadingSpacing),
|
|
65
80
|
},
|
|
66
81
|
headingTag: {
|
|
67
|
-
type: [String, Number] as PropType<'h1' | 'h2' | 'h3'>,
|
|
82
|
+
type: [String, Number] as PropType<'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'>,
|
|
68
83
|
default: 'h1',
|
|
69
|
-
validator: (value: string | number) => ['h1', 'h2', 'h3'].includes(value as string)
|
|
84
|
+
validator: (value: string | number) => ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'].includes(value as string)
|
|
70
85
|
},
|
|
71
86
|
isMobileCentered: {
|
|
72
87
|
type: Boolean as PropType<boolean>,
|
|
73
88
|
default: false,
|
|
74
89
|
},
|
|
90
|
+
overtitleClass: String as PropType<string>,
|
|
75
91
|
titleClass: String as PropType<string>,
|
|
92
|
+
descriptionClass: String as PropType<string>,
|
|
76
93
|
})
|
|
77
94
|
|
|
78
95
|
// Computed classes
|
|
79
96
|
const alignmentClasses = computed(() => {
|
|
80
97
|
const alignMap = {
|
|
81
|
-
[Align.LEFT]: '
|
|
82
|
-
[Align.CENTER]: '
|
|
83
|
-
[Align.RIGHT]: '
|
|
98
|
+
[Align.LEFT]: 'md:items-start md:text-left',
|
|
99
|
+
[Align.CENTER]: 'md:items-center md:text-center',
|
|
100
|
+
[Align.RIGHT]: 'md:items-end md:text-right',
|
|
84
101
|
}
|
|
85
102
|
|
|
86
103
|
if (props.isMobileCentered) {
|
|
@@ -100,6 +117,8 @@ const alignmentClasses = computed(() => {
|
|
|
100
117
|
|
|
101
118
|
const titleSizeClass = computed(() => {
|
|
102
119
|
const map = {
|
|
120
|
+
[HeadingSize.XXS]: 'text-lg',
|
|
121
|
+
[HeadingSize.XS]: 'text-xl',
|
|
103
122
|
[HeadingSize.SM]: 'text-2xl',
|
|
104
123
|
[HeadingSize.MD]: 'text-3xl md:text-4xl',
|
|
105
124
|
[HeadingSize.LG]: 'text-4xl md:text-5xl',
|
|
@@ -110,6 +129,8 @@ const titleSizeClass = computed(() => {
|
|
|
110
129
|
|
|
111
130
|
const overtitleSizeClass = computed(() => {
|
|
112
131
|
const map = {
|
|
132
|
+
[HeadingSize.XXS]: 'text-xs',
|
|
133
|
+
[HeadingSize.XS]: 'text-sm',
|
|
113
134
|
[HeadingSize.SM]: 'text-sm',
|
|
114
135
|
[HeadingSize.MD]: 'text-base',
|
|
115
136
|
[HeadingSize.LG]: 'text-base',
|
|
@@ -120,6 +141,8 @@ const overtitleSizeClass = computed(() => {
|
|
|
120
141
|
|
|
121
142
|
const descriptionSizeClass = computed(() => {
|
|
122
143
|
const map = {
|
|
144
|
+
[HeadingSize.XXS]: 'text-sm',
|
|
145
|
+
[HeadingSize.XS]: 'text-sm',
|
|
123
146
|
[HeadingSize.SM]: 'text-sm',
|
|
124
147
|
[HeadingSize.MD]: 'text-lg',
|
|
125
148
|
[HeadingSize.LG]: 'text-lg',
|
|
@@ -130,6 +153,8 @@ const descriptionSizeClass = computed(() => {
|
|
|
130
153
|
|
|
131
154
|
const spaceOvertitleClass = computed(() => {
|
|
132
155
|
const map = {
|
|
156
|
+
[HeadingSize.XXS]: 'mb-1',
|
|
157
|
+
[HeadingSize.XS]: 'mb-1',
|
|
133
158
|
[HeadingSize.SM]: 'mb-1',
|
|
134
159
|
[HeadingSize.MD]: 'mb-3',
|
|
135
160
|
[HeadingSize.LG]: 'mb-3',
|
|
@@ -140,12 +165,16 @@ const spaceOvertitleClass = computed(() => {
|
|
|
140
165
|
|
|
141
166
|
const spaceDescriptionClass = computed(() => {
|
|
142
167
|
const normal = {
|
|
168
|
+
[HeadingSize.XXS]: 'mt-3',
|
|
169
|
+
[HeadingSize.XS]: 'mt-3',
|
|
143
170
|
[HeadingSize.SM]: 'mt-3',
|
|
144
171
|
[HeadingSize.MD]: 'mt-4',
|
|
145
172
|
[HeadingSize.LG]: 'mt-6',
|
|
146
173
|
[HeadingSize.XL]: 'mt-4',
|
|
147
174
|
}
|
|
148
175
|
const spaced = {
|
|
176
|
+
[HeadingSize.XXS]: 'mt-4',
|
|
177
|
+
[HeadingSize.XS]: 'mt-4',
|
|
149
178
|
[HeadingSize.SM]: 'mt-4',
|
|
150
179
|
[HeadingSize.MD]: 'mt-5',
|
|
151
180
|
[HeadingSize.LG]: 'mt-9',
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<span
|
|
3
3
|
:class="[
|
|
4
|
-
|
|
4
|
+
colorClass,
|
|
5
5
|
'text-sm',
|
|
6
6
|
'font-medium',
|
|
7
7
|
isUppercase && 'uppercase',
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
</template>
|
|
13
13
|
<script setup lang="ts">
|
|
14
14
|
// Props
|
|
15
|
-
defineProps({
|
|
15
|
+
const props = defineProps({
|
|
16
16
|
title: {
|
|
17
17
|
type: String as PropType<string>,
|
|
18
18
|
default: 'Overtitle'
|
|
@@ -20,6 +20,32 @@ defineProps({
|
|
|
20
20
|
isUppercase: {
|
|
21
21
|
type: Boolean as PropType<boolean>,
|
|
22
22
|
default: true,
|
|
23
|
+
},
|
|
24
|
+
color: {
|
|
25
|
+
type: String as PropType<
|
|
26
|
+
ColorAccent.PRIMARY_BRAND
|
|
27
|
+
| ColorAccent.SECONDARY_BRAND
|
|
28
|
+
| ColorAccent.NEUTRAL
|
|
29
|
+
>,
|
|
30
|
+
default: ColorAccent.SECONDARY_BRAND,
|
|
31
|
+
validator: (value: unknown): value is ColorAccent => {
|
|
32
|
+
return typeof value === 'string' &&
|
|
33
|
+
[
|
|
34
|
+
ColorAccent.PRIMARY_BRAND,
|
|
35
|
+
ColorAccent.SECONDARY_BRAND,
|
|
36
|
+
ColorAccent.NEUTRAL,
|
|
37
|
+
].includes(value as ColorAccent)
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
const colorClass = computed(() => {
|
|
43
|
+
const variant: Partial<Record<ColorAccent, string>> = {
|
|
44
|
+
[ColorAccent.NEUTRAL]: 'text-text-default',
|
|
45
|
+
[ColorAccent.PRIMARY_BRAND]: 'text-text-primary-brand-default',
|
|
46
|
+
[ColorAccent.SECONDARY_BRAND]: 'text-text-secondary-brand-default',
|
|
23
47
|
}
|
|
48
|
+
|
|
49
|
+
return variant[props.color as ColorAccent] || 'text-text-secondary-brand-default'
|
|
24
50
|
})
|
|
25
51
|
</script>
|
package/eslint.config.mjs
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
// https://eslint.nuxt.com/packages/module
|
|
2
|
-
|
|
3
|
-
// @ts-check
|
|
4
|
-
import withNuxt from './.nuxt/eslint.config.mjs'
|
|
5
|
-
|
|
6
|
-
export default withNuxt({
|
|
7
|
-
rules: {
|
|
8
|
-
'vue/attribute-hyphenation': 'off',
|
|
9
|
-
'vue/no-multiple-template-root': 'off',
|
|
10
|
-
'vue/require-default-prop': 'off',
|
|
11
|
-
'vue/multi-word-component-names': 'off',
|
|
12
|
-
'@typescript-eslint/no-explicit-any': 'warn',
|
|
13
|
-
'@typescript-eslint/ban-ts-comment': 'error'
|
|
14
|
-
}
|
|
15
|
-
})
|
|
1
|
+
// https://eslint.nuxt.com/packages/module
|
|
2
|
+
|
|
3
|
+
// @ts-check
|
|
4
|
+
import withNuxt from './.nuxt/eslint.config.mjs'
|
|
5
|
+
|
|
6
|
+
export default withNuxt({
|
|
7
|
+
rules: {
|
|
8
|
+
'vue/attribute-hyphenation': 'off',
|
|
9
|
+
'vue/no-multiple-template-root': 'off',
|
|
10
|
+
'vue/require-default-prop': 'off',
|
|
11
|
+
'vue/multi-word-component-names': 'off',
|
|
12
|
+
'@typescript-eslint/no-explicit-any': 'warn',
|
|
13
|
+
'@typescript-eslint/ban-ts-comment': 'error'
|
|
14
|
+
}
|
|
15
|
+
})
|
package/models/enums/headings.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export interface HeaderConfig {
|
|
2
|
-
field: string
|
|
3
|
-
callback?: (value: any) => string
|
|
4
|
-
}
|
|
5
|
-
|
|
1
|
+
export interface HeaderConfig {
|
|
2
|
+
field: string
|
|
3
|
+
callback?: (value: any) => string
|
|
4
|
+
}
|
|
5
|
+
|
|
6
6
|
export type Headers = Record<string, string | HeaderConfig>
|