kmcom-nuxt-layers 1.6.33 → 1.6.35

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.
@@ -1,3 +1,9 @@
1
- export default {
2
- contentLayer: {},
3
- }
1
+ export default defineAppConfig({
2
+ contentLayer: {
3
+ sections: {
4
+ blog: true as boolean,
5
+ portfolio: true as boolean,
6
+ gallery: true as boolean,
7
+ },
8
+ },
9
+ })
@@ -0,0 +1,32 @@
1
+ // @ts-nocheck
2
+ import type { PortfolioQueryOptions } from '../types/content'
3
+
4
+ export function createPortfolioComposables(collectionName: string) {
5
+ function useItems(options: PortfolioQueryOptions = {}) {
6
+ const { featured, tags, limit } = options
7
+
8
+ return useContentData(`${collectionName}-items`, async () => {
9
+ let items = await queryCollection(collectionName).order('year', 'DESC').all()
10
+
11
+ if (featured !== undefined) {
12
+ items = items.filter((item) => item.featured === featured)
13
+ }
14
+
15
+ if (tags?.length) {
16
+ items = items.filter((item) => item.tags?.some((tag: string) => tags.includes(tag)))
17
+ }
18
+
19
+ if (limit) {
20
+ items = items.slice(0, limit)
21
+ }
22
+
23
+ return items
24
+ })
25
+ }
26
+
27
+ function useItem(slug: string) {
28
+ return useCollectionItem(collectionName, slug)
29
+ }
30
+
31
+ return { useItems, useItem }
32
+ }
@@ -1,12 +1,19 @@
1
1
  <script setup lang="ts">
2
- definePageMeta({ name: 'content-blog-slug' })
2
+ definePageMeta({ name: 'content-blog-slug' })
3
3
 
4
- const route = useRoute()
5
- const slug = route.params.slug as string
4
+ const { contentLayer } = useAppConfig()
5
+ if (contentLayer?.sections?.blog === false) {
6
+ throw createError({ statusCode: 404, statusMessage: 'Not Found' })
7
+ }
8
+
9
+ const route = useRoute()
10
+ const slug = route.params.slug as string
6
11
  </script>
7
12
 
8
13
  <template>
9
- <UContainer>
10
- <BlogArticle :slug="slug" />
11
- </UContainer>
14
+ <LayoutSection>
15
+ <LayoutGridItem>
16
+ <BlogArticle :slug="slug" />
17
+ </LayoutGridItem>
18
+ </LayoutSection>
12
19
  </template>
@@ -1,15 +1,22 @@
1
1
  <script setup lang="ts">
2
- useSeoMeta({
3
- title: 'Blog',
4
- description: 'Latest articles and updates',
5
- })
2
+ const { contentLayer } = useAppConfig()
3
+ if (contentLayer?.sections?.blog === false) {
4
+ throw createError({ statusCode: 404, statusMessage: 'Not Found' })
5
+ }
6
+
7
+ useSeoMeta({
8
+ title: 'Blog',
9
+ description: 'Latest articles and updates',
10
+ })
6
11
  </script>
7
12
 
8
13
  <template>
9
- <UContainer>
10
- <UPageHeader title="Blog" description="Latest articles and updates" />
11
- <UPageBody>
12
- <BlogList />
13
- </UPageBody>
14
- </UContainer>
14
+ <LayoutSection>
15
+ <LayoutGridItem>
16
+ <UPageHeader title="Blog" description="Latest articles and updates" />
17
+ <UPageBody>
18
+ <BlogList />
19
+ </UPageBody>
20
+ </LayoutGridItem>
21
+ </LayoutSection>
15
22
  </template>
@@ -1,11 +1,18 @@
1
1
  <script setup lang="ts">
2
- const route = useRoute()
3
- const slug = route.params.slug as string
4
- const index = Number(route.params.imageId)
2
+ const { contentLayer } = useAppConfig()
3
+ if (contentLayer?.sections?.gallery === false) {
4
+ throw createError({ statusCode: 404, statusMessage: 'Not Found' })
5
+ }
6
+
7
+ const route = useRoute()
8
+ const slug = route.params.slug as string
9
+ const index = Number(route.params.imageId)
5
10
  </script>
6
11
 
7
12
  <template>
8
- <UContainer>
9
- <GalleryImageDetail :slug="slug" :index="index" />
10
- </UContainer>
13
+ <LayoutSection>
14
+ <LayoutGridItem>
15
+ <GalleryImageDetail :slug="slug" :index="index" />
16
+ </LayoutGridItem>
17
+ </LayoutSection>
11
18
  </template>
@@ -1,10 +1,17 @@
1
1
  <script setup lang="ts">
2
- const route = useRoute()
3
- const slug = route.params.slug as string
2
+ const { contentLayer } = useAppConfig()
3
+ if (contentLayer?.sections?.gallery === false) {
4
+ throw createError({ statusCode: 404, statusMessage: 'Not Found' })
5
+ }
6
+
7
+ const route = useRoute()
8
+ const slug = route.params.slug as string
4
9
  </script>
5
10
 
6
11
  <template>
7
- <UContainer>
8
- <GalleryDetail :slug="slug" />
9
- </UContainer>
12
+ <LayoutSection>
13
+ <LayoutGridItem>
14
+ <GalleryDetail :slug="slug" />
15
+ </LayoutGridItem>
16
+ </LayoutSection>
10
17
  </template>
@@ -1,15 +1,22 @@
1
1
  <script setup lang="ts">
2
- useSeoMeta({
3
- title: 'Gallery',
4
- description: 'Photo collections and visual work',
5
- })
2
+ const { contentLayer } = useAppConfig()
3
+ if (contentLayer?.sections?.gallery === false) {
4
+ throw createError({ statusCode: 404, statusMessage: 'Not Found' })
5
+ }
6
+
7
+ useSeoMeta({
8
+ title: 'Gallery',
9
+ description: 'Photo collections and visual work',
10
+ })
6
11
  </script>
7
12
 
8
13
  <template>
9
- <UContainer>
10
- <UPageHeader title="Gallery" description="Photo collections and visual work" />
11
- <UPageBody>
12
- <GalleryGrid />
13
- </UPageBody>
14
- </UContainer>
14
+ <LayoutSection>
15
+ <LayoutGridItem>
16
+ <UPageHeader title="Gallery" description="Photo collections and visual work" />
17
+ <UPageBody>
18
+ <GalleryGrid />
19
+ </UPageBody>
20
+ </LayoutGridItem>
21
+ </LayoutSection>
15
22
  </template>
@@ -1,10 +1,17 @@
1
1
  <script setup lang="ts">
2
- const route = useRoute()
3
- const slug = route.params.slug as string
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
4
9
  </script>
5
10
 
6
11
  <template>
7
- <UContainer>
8
- <PortfolioDetail :slug="slug" />
9
- </UContainer>
12
+ <LayoutSection>
13
+ <LayoutGridItem>
14
+ <PortfolioDetail :slug="slug" />
15
+ </LayoutGridItem>
16
+ </LayoutSection>
10
17
  </template>
@@ -1,15 +1,22 @@
1
1
  <script setup lang="ts">
2
- useSeoMeta({
3
- title: 'Portfolio',
4
- description: 'Featured projects and work',
5
- })
2
+ const { contentLayer } = useAppConfig()
3
+ if (contentLayer?.sections?.portfolio === false) {
4
+ throw createError({ statusCode: 404, statusMessage: 'Not Found' })
5
+ }
6
+
7
+ useSeoMeta({
8
+ title: 'Portfolio',
9
+ description: 'Featured projects and work',
10
+ })
6
11
  </script>
7
12
 
8
13
  <template>
9
- <UContainer>
10
- <UPageHeader title="Portfolio" description="Featured projects and work" />
11
- <UPageBody>
12
- <PortfolioList />
13
- </UPageBody>
14
- </UContainer>
14
+ <LayoutSection>
15
+ <LayoutGridItem>
16
+ <UPageHeader title="Portfolio" description="Featured projects and work" />
17
+ <UPageBody>
18
+ <PortfolioList />
19
+ </UPageBody>
20
+ </LayoutGridItem>
21
+ </LayoutSection>
15
22
  </template>
@@ -2,6 +2,11 @@ declare module '@nuxt/schema' {
2
2
  interface AppConfigInput {
3
3
  contentLayer?: {
4
4
  name?: string
5
+ sections?: {
6
+ blog?: boolean
7
+ portfolio?: boolean
8
+ gallery?: boolean
9
+ }
5
10
  }
6
11
  }
7
12
  }
@@ -27,7 +27,11 @@ const { mode } = useGridConfig()
27
27
  </script>
28
28
 
29
29
  <template>
30
- <component :is="tag" :class="mode !== 'disabled' ? 'mastmain' : undefined">
30
+ <component
31
+ :is="tag"
32
+ :class="mode !== 'disabled' ? 'mastmain' : undefined"
33
+ :style="mode !== 'disabled' ? { paddingInline: 'var(--grid-padding, clamp(1rem, 2.5vw, 2rem))' } : undefined"
34
+ >
31
35
  <slot />
32
36
  </component>
33
37
  </template>
@@ -1,20 +1,20 @@
1
1
  <script setup lang="ts">
2
- /**
3
- * BaseSection - Full-viewport section using subgrid
4
- *
5
- * Inherits the parent MastMain's 18-column grid lines using CSS subgrid.
6
- * Spans 12 rows (1 viewport height) for full-screen sections.
7
- * Child GridItem elements position themselves on these inherited grid lines.
8
- *
9
- * @prop {boolean} fullHeight - Optional min-height safety net
10
- * @prop {boolean} fullWidth - Break outside the grid gutters for edge-to-edge content
11
- */
12
- interface Props {
13
- fullHeight?: boolean
14
- fullWidth?: boolean
15
- }
2
+ /**
3
+ * BaseSection - Full-viewport section using subgrid
4
+ *
5
+ * Inherits the parent MastMain's 18-column grid lines using CSS subgrid.
6
+ * Spans 12 rows (1 viewport height) for full-screen sections.
7
+ * Child GridItem elements position themselves on these inherited grid lines.
8
+ *
9
+ * @prop {boolean} fullHeight - Optional min-height safety net
10
+ * @prop {boolean} fullWidth - Break outside the grid gutters for edge-to-edge content
11
+ */
12
+ interface Props {
13
+ fullHeight?: boolean
14
+ fullWidth?: boolean
15
+ }
16
16
 
17
- const { fullHeight = false, fullWidth = false } = defineProps<Props>()
17
+ const { fullHeight = false, fullWidth = false } = defineProps<Props>()
18
18
  </script>
19
19
 
20
20
  <template>
@@ -24,13 +24,13 @@ const { fullHeight = false, fullWidth = false } = defineProps<Props>()
24
24
  </template>
25
25
 
26
26
  <style scoped>
27
- .section-bleed {
28
- --bleed: var(--grid-padding, clamp(1rem, 2.5vw, 2rem));
29
- --gap: var(--grid-gap, clamp(0.75rem, 1.5vw, 1.5rem));
27
+ .section-bleed {
28
+ --bleed: var(--grid-padding, clamp(1rem, 2.5vw, 2rem));
29
+ --gap: var(--grid-gap, clamp(0.75rem, 1.5vw, 1.5rem));
30
30
 
31
- margin-inline: calc(-1 * var(--bleed));
32
- margin-block: calc(-0.5 * var(--gap));
33
- width: calc(100% + 2 * var(--bleed));
34
- max-width: none;
35
- }
31
+ margin-inline: calc(-1 * var(--bleed));
32
+ margin-block: calc(-0.5 * var(--gap));
33
+ width: calc(100% + 2 * var(--bleed));
34
+ max-width: none;
35
+ }
36
36
  </style>
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "kmcom-nuxt-layers",
3
3
  "private": false,
4
- "version": "1.6.33",
4
+ "version": "1.6.35",
5
5
  "description": "Composable Nuxt 4 layers for building scalable Vue applications",
6
6
  "files": [
7
7
  "layers/*/nuxt.config.ts",
@@ -97,7 +97,7 @@
97
97
  "@eslint/json": "^1.2.0",
98
98
  "@eslint/markdown": "^8.0.1",
99
99
  "@ianvs/prettier-plugin-sort-imports": "^4.7.1",
100
- "@iconify-json/lucide": "^1.2.105",
100
+ "@iconify-json/lucide": "^1.2.107",
101
101
  "@netlify/nuxt": "0.3.1",
102
102
  "@nuxt/eslint": "^1.15.2",
103
103
  "@nuxt/fonts": "^0.14.0",
@@ -107,8 +107,8 @@
107
107
  "@perplex-digital/stylelint-config": "^17.4.0",
108
108
  "@pinia/nuxt": "^0.11.3",
109
109
  "@types/node": "^25.6.0",
110
- "@typescript-eslint/eslint-plugin": "^8.59.2",
111
- "@typescript-eslint/parser": "^8.59.2",
110
+ "@typescript-eslint/eslint-plugin": "^8.59.3",
111
+ "@typescript-eslint/parser": "^8.59.3",
112
112
  "@vue/eslint-config-typescript": "^14.7.0",
113
113
  "@vueuse/core": "^14.3.0",
114
114
  "@vueuse/nuxt": "^14.3.0",
@@ -144,12 +144,12 @@
144
144
  "stylelint-no-unsupported-browser-features": "^8.1.1",
145
145
  "stylelint-prettier": "^5.0.3",
146
146
  "tailwindcss": "^4.2.4",
147
- "turbo": "^2.9.12",
147
+ "turbo": "^2.9.14",
148
148
  "typescript": "^6.0.3",
149
149
  "vite-plugin-checker": "^0.13.0",
150
- "vitest": "^4.1.5",
150
+ "vitest": "^4.1.6",
151
151
  "vue": "latest",
152
- "vue-tsc": "^3.2.8",
152
+ "vue-tsc": "^3.2.9",
153
153
  "zod": "^4.4.3",
154
154
  "zod-to-json-schema": "^3.25.2"
155
155
  },