kmcom-nuxt-layers 1.6.43 → 1.6.46
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/layers/content/app/components/Portfolio/ItemPage.vue +19 -0
- package/layers/content/app/{pages/portfolio/index.vue → components/Portfolio/Page.vue} +8 -8
- package/layers/forms/app/components/Form/Contact.vue +45 -38
- package/layers/motion/app/composables/useSmoothScroll.ts +3 -4
- package/package.json +5 -1
- package/layers/content/app/pages/portfolio/[slug].vue +0 -17
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
const { contentLayer } = useAppConfig()
|
|
3
|
+
if (contentLayer?.sections?.portfolio === false) {
|
|
4
|
+
throw createError({ statusCode: 404, statusMessage: 'Not Found' })
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
const { slug, collection = 'portfolio' } = defineProps<{
|
|
8
|
+
slug: string
|
|
9
|
+
collection?: string
|
|
10
|
+
}>()
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<template>
|
|
14
|
+
<LayoutSection>
|
|
15
|
+
<LayoutGridItem>
|
|
16
|
+
<PortfolioDetail :slug :collection />
|
|
17
|
+
</LayoutGridItem>
|
|
18
|
+
</LayoutSection>
|
|
19
|
+
</template>
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
const { contentLayer } = useAppConfig()
|
|
3
|
+
if (contentLayer?.sections?.portfolio === false) {
|
|
4
|
+
throw createError({ statusCode: 404, statusMessage: 'Not Found' })
|
|
5
|
+
}
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
useSeoMeta({
|
|
8
|
+
title: 'Portfolio',
|
|
9
|
+
description: 'Featured projects and work',
|
|
10
|
+
})
|
|
11
11
|
</script>
|
|
12
12
|
|
|
13
13
|
<template>
|
|
@@ -1,52 +1,59 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
// @ts-nocheck
|
|
3
|
-
import type { FormSubmitEvent } from '@nuxt/ui'
|
|
4
|
-
import { z } from 'zod'
|
|
5
|
-
import { fieldConfigs } from '../../config/fields'
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import type { FormSubmitEvent } from '@nuxt/ui'
|
|
4
|
+
import { z } from 'zod'
|
|
6
5
|
|
|
7
|
-
|
|
8
|
-
submit: [data: FormState]
|
|
9
|
-
}>()
|
|
6
|
+
import { fieldConfigs } from '../../config/fields'
|
|
10
7
|
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
message: fieldConfigs.textarea.validation.pipe(
|
|
15
|
-
z.string().min(8, 'Message must be at least 8 characters')
|
|
16
|
-
),
|
|
17
|
-
})
|
|
8
|
+
const emit = defineEmits<{
|
|
9
|
+
submit: [data: FormState]
|
|
10
|
+
}>()
|
|
18
11
|
|
|
19
|
-
|
|
12
|
+
const schema = z.object({
|
|
13
|
+
name: fieldConfigs.name.validation.pipe(
|
|
14
|
+
z.string().min(3, 'Name must be at least 3 characters')
|
|
15
|
+
),
|
|
16
|
+
email: fieldConfigs.email.validation,
|
|
17
|
+
message: fieldConfigs.textarea.validation.pipe(
|
|
18
|
+
z.string().min(8, 'Message must be at least 8 characters')
|
|
19
|
+
),
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
type FormState = z.infer<typeof schema>
|
|
23
|
+
|
|
24
|
+
const state = reactive({ name: '', email: '', message: '' })
|
|
20
25
|
|
|
21
|
-
const
|
|
26
|
+
const toast = useToast()
|
|
27
|
+
const isLoading = ref(false)
|
|
22
28
|
|
|
23
|
-
|
|
24
|
-
|
|
29
|
+
async function onSubmit(event: FormSubmitEvent<FormState>) {
|
|
30
|
+
isLoading.value = true
|
|
31
|
+
try {
|
|
32
|
+
await $fetch('/api/contact', { method: 'POST', body: event.data })
|
|
33
|
+
toast.add({
|
|
34
|
+
title: 'Message sent!',
|
|
35
|
+
description: 'Thanks for reaching out.',
|
|
36
|
+
color: 'success',
|
|
37
|
+
})
|
|
38
|
+
emit('submit', event.data)
|
|
39
|
+
} catch {
|
|
40
|
+
toast.add({
|
|
41
|
+
title: 'Something went wrong',
|
|
42
|
+
description: 'Please try again later.',
|
|
43
|
+
color: 'error',
|
|
44
|
+
})
|
|
45
|
+
} finally {
|
|
46
|
+
isLoading.value = false
|
|
47
|
+
}
|
|
48
|
+
}
|
|
25
49
|
|
|
26
|
-
async function
|
|
27
|
-
isLoading.value = true
|
|
28
|
-
try {
|
|
29
|
-
await $fetch('/api/contact', { method: 'POST', body: event.data })
|
|
30
|
-
toast.add({ title: 'Message sent!', description: 'Thanks for reaching out.', color: 'success' })
|
|
31
|
-
emit('submit', event.data)
|
|
32
|
-
} catch {
|
|
50
|
+
async function onError() {
|
|
33
51
|
toast.add({
|
|
34
|
-
title: '
|
|
35
|
-
description: '
|
|
52
|
+
title: 'Error',
|
|
53
|
+
description: 'There was an error submitting the form.',
|
|
36
54
|
color: 'error',
|
|
37
55
|
})
|
|
38
|
-
} finally {
|
|
39
|
-
isLoading.value = false
|
|
40
56
|
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
async function onError() {
|
|
44
|
-
toast.add({
|
|
45
|
-
title: 'Error',
|
|
46
|
-
description: 'There was an error submitting the form.',
|
|
47
|
-
color: 'error',
|
|
48
|
-
})
|
|
49
|
-
}
|
|
50
57
|
</script>
|
|
51
58
|
|
|
52
59
|
<template>
|
|
@@ -70,10 +70,9 @@ export function useSmoothScroll() {
|
|
|
70
70
|
* Unlock scrolling (enable scroll)
|
|
71
71
|
*/
|
|
72
72
|
function unlockScrolling() {
|
|
73
|
-
if (import.meta.client
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}
|
|
73
|
+
if (!import.meta.client) return
|
|
74
|
+
document.documentElement.style.overflow = ''
|
|
75
|
+
locomotiveScroll.value?.start()
|
|
77
76
|
}
|
|
78
77
|
|
|
79
78
|
/**
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kmcom-nuxt-layers",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "1.6.
|
|
4
|
+
"version": "1.6.46",
|
|
5
5
|
"description": "Composable Nuxt 4 layers for building scalable Vue applications",
|
|
6
6
|
"exports": {
|
|
7
7
|
"./layers/core": "./layers/core/nuxt.config.ts",
|
|
@@ -23,6 +23,10 @@
|
|
|
23
23
|
"layers/*/app/**",
|
|
24
24
|
"docs/"
|
|
25
25
|
],
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "https://github.com/kieranmansfield/nuxt-layers"
|
|
29
|
+
},
|
|
26
30
|
"keywords": [],
|
|
27
31
|
"author": "Kieran Mansfield",
|
|
28
32
|
"license": "ISC",
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
const { contentLayer } = useAppConfig()
|
|
3
|
-
if (contentLayer?.sections?.portfolio === false) {
|
|
4
|
-
throw createError({ statusCode: 404, statusMessage: 'Not Found' })
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
const route = useRoute()
|
|
8
|
-
const slug = route.params.slug as string
|
|
9
|
-
</script>
|
|
10
|
-
|
|
11
|
-
<template>
|
|
12
|
-
<LayoutSection>
|
|
13
|
-
<LayoutGridItem>
|
|
14
|
-
<PortfolioDetail :slug="slug" />
|
|
15
|
-
</LayoutGridItem>
|
|
16
|
-
</LayoutSection>
|
|
17
|
-
</template>
|