@imaginario27/air-ui-ds 1.0.17 → 1.0.19
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.
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
:class="[
|
|
4
|
+
'w-full',
|
|
5
|
+
isFullScreen ? 'h-screen py-[10vw] md:py-[20vw]' : 'py-6',
|
|
6
|
+
'px-content-side-padding',
|
|
7
|
+
'flex',
|
|
8
|
+
orientation === Orientation.VERTICAL ? 'flex-col' : 'flex-col md:flex-row',
|
|
9
|
+
'gap-9',
|
|
10
|
+
'items-center',
|
|
11
|
+
'justify-center',
|
|
12
|
+
]"
|
|
13
|
+
>
|
|
14
|
+
<!-- Slot for images, illustrations or other visual elements -->
|
|
15
|
+
<slot name="visual-left" />
|
|
16
|
+
|
|
17
|
+
<!-- Body -->
|
|
18
|
+
<div
|
|
19
|
+
:class="[
|
|
20
|
+
'w-full',
|
|
21
|
+
'gap-9',
|
|
22
|
+
'flex',
|
|
23
|
+
'flex-col',
|
|
24
|
+
contentAlignmentClass,
|
|
25
|
+
]"
|
|
26
|
+
>
|
|
27
|
+
<slot name="visual-top" />
|
|
28
|
+
|
|
29
|
+
<ContainedIcon
|
|
30
|
+
v-if="!$slots['visual-top'] && showIcon"
|
|
31
|
+
:color="ColorAccent.DANGER"
|
|
32
|
+
:icon="resolvedErrorMapping.icon ?? icon"
|
|
33
|
+
:size="IconContainerSize.XXL"
|
|
34
|
+
/>
|
|
35
|
+
|
|
36
|
+
<div
|
|
37
|
+
v-if="!$slots['description']"
|
|
38
|
+
:class="[
|
|
39
|
+
'flex',
|
|
40
|
+
'flex-col',
|
|
41
|
+
'gap-4',
|
|
42
|
+
contentAlignmentClass,
|
|
43
|
+
'w-full',
|
|
44
|
+
'max-w-[600px]',
|
|
45
|
+
]"
|
|
46
|
+
>
|
|
47
|
+
<Heading
|
|
48
|
+
:title="resolvedErrorMapping.title"
|
|
49
|
+
:overtitle="showErrorCode ? statusCode.toString() : ''"
|
|
50
|
+
:align="alignContent"
|
|
51
|
+
:size="HeadingSize.MD"
|
|
52
|
+
:isMobileCentered
|
|
53
|
+
/>
|
|
54
|
+
|
|
55
|
+
<p
|
|
56
|
+
:class="[
|
|
57
|
+
'text-text-neutral-subtle',
|
|
58
|
+
'font-semibold',
|
|
59
|
+
textAlignmentClass,
|
|
60
|
+
'leading-6',
|
|
61
|
+
]"
|
|
62
|
+
>
|
|
63
|
+
{{ resolvedErrorMapping.message }}
|
|
64
|
+
</p>
|
|
65
|
+
</div>
|
|
66
|
+
|
|
67
|
+
<slot name="description" />
|
|
68
|
+
|
|
69
|
+
<!-- Actions -->
|
|
70
|
+
<div
|
|
71
|
+
:class="[
|
|
72
|
+
'w-full',
|
|
73
|
+
'flex',
|
|
74
|
+
'gap-3',
|
|
75
|
+
actionsAlignmentClass,
|
|
76
|
+
'flex-col',
|
|
77
|
+
'md:flex-row',
|
|
78
|
+
'mb-4 md:mb-10', // Visual fix to push content a bit up
|
|
79
|
+
]"
|
|
80
|
+
>
|
|
81
|
+
<ActionButton
|
|
82
|
+
v-if="!$slots['actions']"
|
|
83
|
+
:actionType="ButtonActionType.LINK"
|
|
84
|
+
:styleType="ButtonStyleType.PRIMARY_BRAND_FILLED"
|
|
85
|
+
:text="backToHomeText"
|
|
86
|
+
class="w-full md:w-auto"
|
|
87
|
+
:icon="backToHomeIcon"
|
|
88
|
+
:iconPosition="IconPosition.LEFT"
|
|
89
|
+
:to="homeRoute"
|
|
90
|
+
/>
|
|
91
|
+
|
|
92
|
+
<slot name="actions" />
|
|
93
|
+
</div>
|
|
94
|
+
</div>
|
|
95
|
+
|
|
96
|
+
<!-- Slot for images, illustrations or other visual elements -->
|
|
97
|
+
<slot name="visual-right" />
|
|
98
|
+
</div>
|
|
99
|
+
</template>
|
|
100
|
+
|
|
101
|
+
<script setup lang="ts">
|
|
102
|
+
// Props
|
|
103
|
+
const props = defineProps({
|
|
104
|
+
statusCode: {
|
|
105
|
+
type: Number,
|
|
106
|
+
required: true,
|
|
107
|
+
},
|
|
108
|
+
errorMappings: {
|
|
109
|
+
type: Array as PropType<ErrorMapping[]>,
|
|
110
|
+
default: () => [],
|
|
111
|
+
},
|
|
112
|
+
showIcon: {
|
|
113
|
+
type: Boolean as PropType<boolean>,
|
|
114
|
+
default: true,
|
|
115
|
+
},
|
|
116
|
+
showErrorCode: {
|
|
117
|
+
type: Boolean as PropType<boolean>,
|
|
118
|
+
default: true,
|
|
119
|
+
},
|
|
120
|
+
icon: {
|
|
121
|
+
type: String as PropType<any>,
|
|
122
|
+
default: 'mdiAlertCircleOutline',
|
|
123
|
+
},
|
|
124
|
+
backToHomeText: {
|
|
125
|
+
type: String as PropType<string>,
|
|
126
|
+
default: 'Back to home page',
|
|
127
|
+
},
|
|
128
|
+
backToHomeIcon: {
|
|
129
|
+
type: String as PropType<string>,
|
|
130
|
+
default: 'mdiHomeOutline',
|
|
131
|
+
},
|
|
132
|
+
homeRoute: {
|
|
133
|
+
type: String as PropType<string>,
|
|
134
|
+
default: '/',
|
|
135
|
+
},
|
|
136
|
+
isFullScreen: {
|
|
137
|
+
type: Boolean as PropType<boolean>,
|
|
138
|
+
default: true,
|
|
139
|
+
},
|
|
140
|
+
orientation: {
|
|
141
|
+
type: String as PropType<Orientation>,
|
|
142
|
+
default: Orientation.HORIZONTAL,
|
|
143
|
+
validator: (value: Orientation) => Object.values(Orientation).includes(value),
|
|
144
|
+
},
|
|
145
|
+
alignContent: {
|
|
146
|
+
type: String as PropType<Align>,
|
|
147
|
+
default: Align.CENTER,
|
|
148
|
+
validator: (value: Align) => Object.values(Align).includes(value),
|
|
149
|
+
},
|
|
150
|
+
isMobileCentered: {
|
|
151
|
+
type: Boolean as PropType<boolean>,
|
|
152
|
+
default: true,
|
|
153
|
+
},
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
// Constants
|
|
157
|
+
const defaultErrorMappings: ErrorMapping[] = [
|
|
158
|
+
// 4xx Client Errors
|
|
159
|
+
{
|
|
160
|
+
statusCode: 400,
|
|
161
|
+
title: 'Bad request',
|
|
162
|
+
message: 'The request could not be understood by the server due to malformed syntax.',
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
statusCode: 401,
|
|
166
|
+
title: 'Unauthorized',
|
|
167
|
+
message: 'You are not authorized to access this resource. Please log in.',
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
statusCode: 403,
|
|
171
|
+
title: 'Forbidden',
|
|
172
|
+
message: 'You do not have permission to access this page.',
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
statusCode: 404,
|
|
176
|
+
title: 'Page not found',
|
|
177
|
+
message: 'The page you are looking for does not exist or may have been moved.',
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
statusCode: 405,
|
|
181
|
+
title: 'Method not allowed',
|
|
182
|
+
message: 'The method is not allowed for the requested URL.',
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
statusCode: 408,
|
|
186
|
+
title: 'Request timeout',
|
|
187
|
+
message: 'The server timed out waiting for the request.',
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
statusCode: 429,
|
|
191
|
+
title: 'Too many requests',
|
|
192
|
+
message: 'You have made too many requests in a short period of time. Please try again later.',
|
|
193
|
+
},
|
|
194
|
+
|
|
195
|
+
// 5xx Server Errors
|
|
196
|
+
{
|
|
197
|
+
statusCode: 500,
|
|
198
|
+
title: 'Internal server error',
|
|
199
|
+
message: 'Something went wrong on our end. Please try again later.',
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
statusCode: 501,
|
|
203
|
+
title: 'Not implemented',
|
|
204
|
+
message: 'The server does not support the functionality required to fulfill the request.',
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
statusCode: 502,
|
|
208
|
+
title: 'Bad gateway',
|
|
209
|
+
message: 'The server received an invalid response from the upstream server.',
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
statusCode: 503,
|
|
213
|
+
title: 'Service unavailable',
|
|
214
|
+
message: 'The server is temporarily unable to handle the request. Please try again later.',
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
statusCode: 504,
|
|
218
|
+
title: 'Gateway timeout',
|
|
219
|
+
message: 'The upstream server failed to send a request in time.',
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
statusCode: 505,
|
|
223
|
+
title: 'HTTP version not supported',
|
|
224
|
+
message: 'The server does not support the HTTP protocol version used in the request.',
|
|
225
|
+
},
|
|
226
|
+
|
|
227
|
+
// Fallback for unknown errors
|
|
228
|
+
{
|
|
229
|
+
statusCode: -1,
|
|
230
|
+
title: 'Unexpected error',
|
|
231
|
+
message: 'An unknown error occurred. Please try again.',
|
|
232
|
+
}
|
|
233
|
+
]
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
// Computed
|
|
237
|
+
const resolvedErrorMapping = computed(() => {
|
|
238
|
+
const code = Number(props.statusCode)
|
|
239
|
+
|
|
240
|
+
const combined = [...props.errorMappings, ...defaultErrorMappings]
|
|
241
|
+
|
|
242
|
+
return (
|
|
243
|
+
combined.find(mapping => mapping.statusCode === code) ??
|
|
244
|
+
combined.find(mapping => mapping.statusCode === -1)!
|
|
245
|
+
)
|
|
246
|
+
})
|
|
247
|
+
const pageTitleText = computed(() => resolvedErrorMapping.value.title)
|
|
248
|
+
|
|
249
|
+
watchEffect(() => {
|
|
250
|
+
document.title = pageTitle(pageTitleText.value, App.NAME)
|
|
251
|
+
})
|
|
252
|
+
|
|
253
|
+
// Alignment classes
|
|
254
|
+
const contentAlignmentClass = computed(() => {
|
|
255
|
+
const base = {
|
|
256
|
+
[Align.LEFT]: 'md:items-start',
|
|
257
|
+
[Align.CENTER]: 'md:items-center',
|
|
258
|
+
[Align.RIGHT]: 'md:items-end',
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
return [
|
|
262
|
+
props.isMobileCentered ? 'items-center' : '',
|
|
263
|
+
base[props.alignContent as Align] || 'md:items-center',
|
|
264
|
+
].join(' ').trim()
|
|
265
|
+
})
|
|
266
|
+
|
|
267
|
+
const actionsAlignmentClass = computed(() => {
|
|
268
|
+
const base = {
|
|
269
|
+
[Align.LEFT]: 'md:items-start md:justify-start',
|
|
270
|
+
[Align.CENTER]: 'md:items-center md:justify-center',
|
|
271
|
+
[Align.RIGHT]: 'md:items-end md:justify-end',
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
return [
|
|
275
|
+
props.isMobileCentered ? 'items-center justify-center' : '',
|
|
276
|
+
base[props.alignContent as Align] || 'md:items-center md:justify-center',
|
|
277
|
+
].join(' ').trim()
|
|
278
|
+
})
|
|
279
|
+
|
|
280
|
+
const textAlignmentClass = computed(() => {
|
|
281
|
+
const base = {
|
|
282
|
+
[Align.LEFT]: 'md:text-left',
|
|
283
|
+
[Align.CENTER]: 'md:text-center',
|
|
284
|
+
[Align.RIGHT]: 'md:text-right',
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
return [
|
|
288
|
+
props.isMobileCentered ? 'text-center' : '',
|
|
289
|
+
base[props.alignContent as Align] || 'md:text-center',
|
|
290
|
+
].join(' ').trim()
|
|
291
|
+
})
|
|
292
|
+
</script>
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
{{ credits }}
|
|
29
29
|
</span>
|
|
30
30
|
|
|
31
|
-
<nav v-if="menuItems
|
|
31
|
+
<nav v-if="menuItems.length">
|
|
32
32
|
<ul class="flex flex-col lg:flex-row gap-5">
|
|
33
33
|
<li
|
|
34
34
|
v-for="(item, index) in menuItems"
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
</ul>
|
|
49
49
|
</nav>
|
|
50
50
|
|
|
51
|
-
<div v-if="socialNetworks
|
|
51
|
+
<div v-if="socialNetworks.length" class="flex gap-5">
|
|
52
52
|
<a
|
|
53
53
|
v-for="(network, index) in socialNetworks"
|
|
54
54
|
:key="index"
|
|
@@ -86,8 +86,14 @@ defineProps({
|
|
|
86
86
|
type: String as PropType<string>,
|
|
87
87
|
default: '© <year> <your-company>. All rights reserved.',
|
|
88
88
|
},
|
|
89
|
-
menuItems:
|
|
90
|
-
|
|
89
|
+
menuItems: {
|
|
90
|
+
type: Array as PropType<MenuItem[]>,
|
|
91
|
+
default: () => [],
|
|
92
|
+
},
|
|
93
|
+
socialNetworks: {
|
|
94
|
+
type: Array as PropType<SocialNetwork[]>,
|
|
95
|
+
default: () => [],
|
|
96
|
+
},
|
|
91
97
|
hasContentMaxWidth: {
|
|
92
98
|
type: Boolean as PropType<boolean>,
|
|
93
99
|
default: false,
|
|
@@ -95,9 +95,9 @@ const props = defineProps({
|
|
|
95
95
|
// Computed classes
|
|
96
96
|
const alignmentClasses = computed(() => {
|
|
97
97
|
const alignMap = {
|
|
98
|
-
[Align.LEFT]: '
|
|
99
|
-
[Align.CENTER]: '
|
|
100
|
-
[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',
|
|
101
101
|
}
|
|
102
102
|
|
|
103
103
|
if (props.isMobileCentered) {
|
package/package.json
CHANGED
|
@@ -1,57 +1,57 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@imaginario27/air-ui-ds",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"author": "imaginario27",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"homepage": "https://air-ui.netlify.app/",
|
|
7
|
-
"repository": {
|
|
8
|
-
"type": "git",
|
|
9
|
-
"url": "git+https://github.com/imaginario27/air-ui.git"
|
|
10
|
-
},
|
|
11
|
-
"publishConfig": {
|
|
12
|
-
"access": "public"
|
|
13
|
-
},
|
|
14
|
-
"scripts": {
|
|
15
|
-
"build": "nuxt build",
|
|
16
|
-
"dev": "nuxt dev",
|
|
17
|
-
"generate": "nuxt generate",
|
|
18
|
-
"preview": "nuxt preview",
|
|
19
|
-
"postinstall": "nuxt prepare",
|
|
20
|
-
"test": "vitest",
|
|
21
|
-
"generate-theme": "ts-node scripts/generate-theme.ts",
|
|
22
|
-
"update-theme-colors": "ts-node scripts/update-ui-theme-colors.ts",
|
|
23
|
-
"typecheck": "vue-tsc --noEmit -p tsconfig.typecheck.json"
|
|
24
|
-
},
|
|
25
|
-
"dependencies": {
|
|
26
|
-
"@jaxtheprime/vue3-dropzone": "3.4.0",
|
|
27
|
-
"@nuxt/content": "3.7.1",
|
|
28
|
-
"@nuxt/eslint": "1.9.0",
|
|
29
|
-
"@nuxt/image": "1.11.0",
|
|
30
|
-
"@nuxtjs/i18n": "10.1.0",
|
|
31
|
-
"@tailwindcss/vite": "4.1.13",
|
|
32
|
-
"@vueuse/core": "13.9.0",
|
|
33
|
-
"@vueuse/nuxt": "13.9.0",
|
|
34
|
-
"jspdf": "3.0.3",
|
|
35
|
-
"jspdf-autotable": "5.0.2",
|
|
36
|
-
"nuxt": "4.1.2",
|
|
37
|
-
"nuxt-mdi": "2.1.1",
|
|
38
|
-
"qrcode.vue": "3.6.0",
|
|
39
|
-
"tailwindcss": "4.1.13",
|
|
40
|
-
"vue": "3.5.22",
|
|
41
|
-
"vue-json-excel3": "1.0.30",
|
|
42
|
-
"vue-router": "4.5.1",
|
|
43
|
-
"vue3-toastify": "0.2.8"
|
|
44
|
-
},
|
|
45
|
-
"devDependencies": {
|
|
46
|
-
"@nuxt/test-utils": "3.19.2",
|
|
47
|
-
"@vitest/coverage-v8": "3.2.4",
|
|
48
|
-
"@vue/test-utils": "2.4.6",
|
|
49
|
-
"eslint": "9.36.0",
|
|
50
|
-
"happy-dom": "18.0.1",
|
|
51
|
-
"playwright-core": "1.55.1",
|
|
52
|
-
"prettier": "3.6.2",
|
|
53
|
-
"ts-node": "10.9.2",
|
|
54
|
-
"typescript": "5.9.3",
|
|
55
|
-
"vitest": "3.2.4"
|
|
56
|
-
}
|
|
57
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@imaginario27/air-ui-ds",
|
|
3
|
+
"version": "1.0.19",
|
|
4
|
+
"author": "imaginario27",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"homepage": "https://air-ui.netlify.app/",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/imaginario27/air-ui.git"
|
|
10
|
+
},
|
|
11
|
+
"publishConfig": {
|
|
12
|
+
"access": "public"
|
|
13
|
+
},
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "nuxt build",
|
|
16
|
+
"dev": "nuxt dev",
|
|
17
|
+
"generate": "nuxt generate",
|
|
18
|
+
"preview": "nuxt preview",
|
|
19
|
+
"postinstall": "nuxt prepare",
|
|
20
|
+
"test": "vitest",
|
|
21
|
+
"generate-theme": "ts-node scripts/generate-theme.ts",
|
|
22
|
+
"update-theme-colors": "ts-node scripts/update-ui-theme-colors.ts",
|
|
23
|
+
"typecheck": "vue-tsc --noEmit -p tsconfig.typecheck.json"
|
|
24
|
+
},
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"@jaxtheprime/vue3-dropzone": "3.4.0",
|
|
27
|
+
"@nuxt/content": "3.7.1",
|
|
28
|
+
"@nuxt/eslint": "1.9.0",
|
|
29
|
+
"@nuxt/image": "1.11.0",
|
|
30
|
+
"@nuxtjs/i18n": "10.1.0",
|
|
31
|
+
"@tailwindcss/vite": "4.1.13",
|
|
32
|
+
"@vueuse/core": "13.9.0",
|
|
33
|
+
"@vueuse/nuxt": "13.9.0",
|
|
34
|
+
"jspdf": "3.0.3",
|
|
35
|
+
"jspdf-autotable": "5.0.2",
|
|
36
|
+
"nuxt": "4.1.2",
|
|
37
|
+
"nuxt-mdi": "2.1.1",
|
|
38
|
+
"qrcode.vue": "3.6.0",
|
|
39
|
+
"tailwindcss": "4.1.13",
|
|
40
|
+
"vue": "3.5.22",
|
|
41
|
+
"vue-json-excel3": "1.0.30",
|
|
42
|
+
"vue-router": "4.5.1",
|
|
43
|
+
"vue3-toastify": "0.2.8"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"@nuxt/test-utils": "3.19.2",
|
|
47
|
+
"@vitest/coverage-v8": "3.2.4",
|
|
48
|
+
"@vue/test-utils": "2.4.6",
|
|
49
|
+
"eslint": "9.36.0",
|
|
50
|
+
"happy-dom": "18.0.1",
|
|
51
|
+
"playwright-core": "1.55.1",
|
|
52
|
+
"prettier": "3.6.2",
|
|
53
|
+
"ts-node": "10.9.2",
|
|
54
|
+
"typescript": "5.9.3",
|
|
55
|
+
"vitest": "3.2.4"
|
|
56
|
+
}
|
|
57
|
+
}
|