kmcom-nuxt-layers 2.2.10 → 2.2.12
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/docs/FALLOW-COMPLEXITY-DUPLICATION-AUDIT.md +65 -0
- package/docs/IMPROVE-AUDIT-README.md +30 -0
- package/docs/IMPROVE-AUDIT-RESULTS.md +52 -0
- package/docs/IMPROVE-DEEP-AUDIT-RESULTS.md +81 -0
- package/docs/fallow-refactor/apps-debug.md +27 -0
- package/docs/fallow-refactor/apps-playground.md +46 -0
- package/docs/fallow-refactor/apps-visual-identity.md +41 -0
- package/docs/fallow-refactor/layers-animations.md +34 -0
- package/docs/fallow-refactor/layers-canvas.md +32 -0
- package/docs/fallow-refactor/layers-content.md +33 -0
- package/docs/fallow-refactor/layers-core.md +39 -0
- package/docs/fallow-refactor/layers-feeds.md +39 -0
- package/docs/fallow-refactor/layers-forms.md +30 -0
- package/docs/fallow-refactor/layers-layout.md +42 -0
- package/docs/fallow-refactor/layers-mailer.md +32 -0
- package/docs/fallow-refactor/layers-motion.md +27 -0
- package/docs/fallow-refactor/layers-navigation.md +31 -0
- package/docs/fallow-refactor/layers-page-transitions.md +30 -0
- package/docs/fallow-refactor/layers-routing.md +33 -0
- package/docs/fallow-refactor/layers-scripts.md +35 -0
- package/docs/fallow-refactor/layers-scroll.md +38 -0
- package/docs/fallow-refactor/layers-seo.md +32 -0
- package/docs/fallow-refactor/layers-shader.md +53 -0
- package/docs/fallow-refactor/layers-theme.md +33 -0
- package/docs/fallow-refactor/layers-transitions.md +27 -0
- package/docs/fallow-refactor/layers-typography.md +29 -0
- package/docs/fallow-refactor/layers-ui.md +27 -0
- package/docs/fallow-refactor/layers-visual.md +34 -0
- package/layers/animations/app/components/Motion/MarqueeText.vue +1 -1
- package/layers/canvas/app/composables/useRendererCapabilities.ts +3 -4
- package/layers/content/app/components/NuxtContent/Detail.vue +3 -3
- package/layers/feeds/app/app.config.ts +4 -2
- package/layers/feeds/app/components/Feeds/Index.vue +229 -0
- package/layers/feeds/app/components/Feeds/RouteCard.vue +81 -0
- package/layers/feeds/app/plugins/feed-head.ts +27 -49
- package/layers/feeds/app/utils/feed-catalog.test.ts +71 -0
- package/layers/feeds/app/utils/feed-catalog.ts +179 -0
- package/layers/feeds/package.json +1 -0
- package/layers/feeds/server/routes/feed/discovery.get.ts +16 -14
- package/layers/feeds/server/utils/content-adapter.ts +58 -19
- package/layers/shader/app/components/Preset/Aurora.client.vue +2 -2
- package/layers/shader/app/components/Preset/Flow.client.vue +2 -2
- package/layers/shader/app/components/Preset/GradientMesh.client.vue +2 -2
- package/layers/shader/app/components/Preset/Nebula.client.vue +2 -2
- package/layers/shader/app/components/Preset/Ocean.client.vue +2 -2
- package/layers/shader/app/components/Shader/Background.client.vue +3 -2
- package/layers/shader/app/composables/useAmbientMaterials.ts +15 -15
- package/layers/shader/app/composables/useThemePreset.ts +2 -2
- package/layers/shader/app/shaders/types.ts +4 -1
- package/layers/theme/app/components/ThemePicker/Colors.vue +5 -1
- package/package.json +3 -2
|
@@ -1,28 +1,30 @@
|
|
|
1
|
+
import contentManifest from '#content/manifest'
|
|
2
|
+
|
|
3
|
+
import { createFeedCatalog } from '../../../app/utils/feed-catalog'
|
|
4
|
+
|
|
1
5
|
export default defineEventHandler((event) => {
|
|
2
6
|
const appConfig = useAppConfig()
|
|
3
|
-
const feedConfig = appConfig.feedsLayer?.feed ?? {}
|
|
4
|
-
const collections: string[] = feedConfig.collections ?? ['blog']
|
|
5
7
|
|
|
6
8
|
const requestUrl = getRequestURL(event)
|
|
7
9
|
// Always use the request origin so discovery URLs are reachable from wherever
|
|
8
10
|
// the request came from, not the configured canonical site URL.
|
|
9
11
|
const baseUrl = `${requestUrl.protocol}//${requestUrl.host}`
|
|
10
12
|
|
|
11
|
-
|
|
13
|
+
const catalog = createFeedCatalog({
|
|
14
|
+
site: appConfig.site,
|
|
15
|
+
feed: appConfig.feedsLayer?.feed,
|
|
16
|
+
manifest: contentManifest,
|
|
17
|
+
})
|
|
12
18
|
|
|
13
|
-
|
|
14
|
-
{ format: 'RSS 2.0', ext: 'rss', contentType: 'application/rss+xml' },
|
|
15
|
-
{ format: 'Atom 1.0', ext: 'atom', contentType: 'application/atom+xml' },
|
|
16
|
-
{ format: 'JSON Feed 1.1', ext: 'json', contentType: 'application/feed+json' },
|
|
17
|
-
]
|
|
19
|
+
setHeader(event, 'Cache-Control', 'public, max-age=300, s-maxage=3600')
|
|
18
20
|
|
|
19
21
|
return {
|
|
20
|
-
feeds:
|
|
21
|
-
|
|
22
|
-
collection,
|
|
23
|
-
format,
|
|
24
|
-
url: `${baseUrl}
|
|
25
|
-
contentType,
|
|
22
|
+
feeds: catalog.collectionGroups.flatMap((group) =>
|
|
23
|
+
group.routes.map((route) => ({
|
|
24
|
+
collection: group.collection,
|
|
25
|
+
format: route.label,
|
|
26
|
+
url: `${baseUrl}${route.path}`,
|
|
27
|
+
contentType: route.contentType ?? 'application/octet-stream',
|
|
26
28
|
}))
|
|
27
29
|
),
|
|
28
30
|
}
|
|
@@ -3,38 +3,77 @@ import type { H3Event } from 'h3'
|
|
|
3
3
|
|
|
4
4
|
import type { FeedItem } from './types'
|
|
5
5
|
|
|
6
|
-
type
|
|
6
|
+
type FeedSourceAuthor = {
|
|
7
|
+
name?: string | undefined
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
type FeedSourceItem = {
|
|
11
|
+
draft?: boolean | undefined
|
|
12
|
+
title?: string | undefined
|
|
13
|
+
description?: string | undefined
|
|
14
|
+
stem?: string | undefined
|
|
15
|
+
path?: string | undefined
|
|
16
|
+
_path?: string | undefined
|
|
17
|
+
date?: string | number | Date | undefined
|
|
18
|
+
createdAt?: string | number | Date | undefined
|
|
19
|
+
author?: FeedSourceAuthor | string | undefined
|
|
20
|
+
authors?: FeedSourceAuthor[] | undefined
|
|
21
|
+
tags?: string[] | undefined
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
type FeedCollectionQuery = {
|
|
25
|
+
all(): Promise<FeedSourceItem[]>
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const getFeedCollection = queryCollection as unknown as (
|
|
29
|
+
event: H3Event,
|
|
30
|
+
collection: string
|
|
31
|
+
) => FeedCollectionQuery
|
|
32
|
+
|
|
33
|
+
function resolveFeedAuthor(item: FeedSourceItem): string | undefined {
|
|
34
|
+
const firstAuthor = item.authors?.[0]
|
|
35
|
+
if (typeof firstAuthor?.name === 'string' && firstAuthor.name.length > 0) {
|
|
36
|
+
return firstAuthor.name
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (typeof item.author === 'string' && item.author.length > 0) {
|
|
40
|
+
return item.author
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (item.author && typeof item.author === 'object' && typeof item.author.name === 'string') {
|
|
44
|
+
return item.author.name
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return undefined
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function resolveFeedDate(item: FeedSourceItem): Date {
|
|
51
|
+
return new Date(item.date ?? item.createdAt ?? Date.now())
|
|
52
|
+
}
|
|
7
53
|
|
|
8
54
|
export async function getContentFeedItems(
|
|
9
55
|
event: H3Event,
|
|
10
56
|
collection: string = 'blog',
|
|
11
57
|
limit: number = 30
|
|
12
58
|
): Promise<FeedItem[]> {
|
|
13
|
-
// queryCollection
|
|
14
|
-
// a
|
|
15
|
-
|
|
16
|
-
const raw: AnyContent[] = await (queryCollection as any)(event, collection).all()
|
|
59
|
+
// queryCollection is keyed by literal collection names, but feed routes accept
|
|
60
|
+
// a runtime collection string; keep the unsafe bridge local here.
|
|
61
|
+
const raw = await getFeedCollection(event, collection).all()
|
|
17
62
|
|
|
18
63
|
return raw
|
|
19
64
|
.filter((item) => !item.draft)
|
|
20
|
-
.sort(
|
|
21
|
-
(a, b) =>
|
|
22
|
-
new Date(b.date ?? b.createdAt ?? 0).getTime() -
|
|
23
|
-
new Date(a.date ?? a.createdAt ?? 0).getTime()
|
|
24
|
-
)
|
|
65
|
+
.sort((a, b) => resolveFeedDate(b).getTime() - resolveFeedDate(a).getTime())
|
|
25
66
|
.slice(0, limit)
|
|
26
|
-
.map((item) => {
|
|
27
|
-
const
|
|
28
|
-
? item.authors[0]?.name
|
|
29
|
-
: (item.author?.name ?? (typeof item.author === 'string' ? item.author : undefined))
|
|
67
|
+
.map((item): FeedItem => {
|
|
68
|
+
const link = item.path ?? item._path ?? ''
|
|
30
69
|
return {
|
|
31
70
|
title: item.title ?? item.stem ?? '',
|
|
32
71
|
description: item.description,
|
|
33
|
-
link
|
|
34
|
-
id:
|
|
35
|
-
date:
|
|
36
|
-
author:
|
|
37
|
-
tags:
|
|
72
|
+
link,
|
|
73
|
+
id: link,
|
|
74
|
+
date: resolveFeedDate(item),
|
|
75
|
+
author: resolveFeedAuthor(item),
|
|
76
|
+
tags: item.tags,
|
|
38
77
|
}
|
|
39
78
|
})
|
|
40
79
|
}
|
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
watch(
|
|
32
32
|
() => [runtime.mouse.mouseX.value, runtime.mouse.mouseY.value],
|
|
33
33
|
([mx, my]) => {
|
|
34
|
-
uniforms.mouseX.value = mx
|
|
35
|
-
uniforms.mouseY.value = my
|
|
34
|
+
uniforms.mouseX.value = mx ?? 0.5
|
|
35
|
+
uniforms.mouseY.value = my ?? 0.5
|
|
36
36
|
},
|
|
37
37
|
{ immediate: true }
|
|
38
38
|
)
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
watch(
|
|
33
33
|
() => [runtime.mouse.mouseX.value, runtime.mouse.mouseY.value],
|
|
34
34
|
([mx, my]) => {
|
|
35
|
-
uniforms.mouseX.value = mx
|
|
36
|
-
uniforms.mouseY.value = my
|
|
35
|
+
uniforms.mouseX.value = mx ?? 0.5
|
|
36
|
+
uniforms.mouseY.value = my ?? 0.5
|
|
37
37
|
},
|
|
38
38
|
{ immediate: true }
|
|
39
39
|
)
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
watch(
|
|
33
33
|
() => [runtime.mouse.mouseX.value, runtime.mouse.mouseY.value],
|
|
34
34
|
([mx, my]) => {
|
|
35
|
-
uniforms.mouseX.value = mx
|
|
36
|
-
uniforms.mouseY.value = my
|
|
35
|
+
uniforms.mouseX.value = mx ?? 0.5
|
|
36
|
+
uniforms.mouseY.value = my ?? 0.5
|
|
37
37
|
},
|
|
38
38
|
{ immediate: true }
|
|
39
39
|
)
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
watch(
|
|
33
33
|
() => [runtime.mouse.mouseX.value, runtime.mouse.mouseY.value],
|
|
34
34
|
([mx, my]) => {
|
|
35
|
-
uniforms.mouseX.value = mx
|
|
36
|
-
uniforms.mouseY.value = my
|
|
35
|
+
uniforms.mouseX.value = mx ?? 0.5
|
|
36
|
+
uniforms.mouseY.value = my ?? 0.5
|
|
37
37
|
},
|
|
38
38
|
{ immediate: true }
|
|
39
39
|
)
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
watch(
|
|
33
33
|
() => [runtime.mouse.mouseX.value, runtime.mouse.mouseY.value],
|
|
34
34
|
([mx, my]) => {
|
|
35
|
-
uniforms.mouseX.value = mx
|
|
36
|
-
uniforms.mouseY.value = my
|
|
35
|
+
uniforms.mouseX.value = mx ?? 0.5
|
|
36
|
+
uniforms.mouseY.value = my ?? 0.5
|
|
37
37
|
},
|
|
38
38
|
{ immediate: true }
|
|
39
39
|
)
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
ReinhardToneMapping,
|
|
13
13
|
Scene,
|
|
14
14
|
SRGBColorSpace,
|
|
15
|
+
type ToneMapping,
|
|
15
16
|
} from 'three'
|
|
16
17
|
import { MeshBasicNodeMaterial, WebGPURenderer } from 'three/webgpu'
|
|
17
18
|
|
|
@@ -56,7 +57,7 @@
|
|
|
56
57
|
let initStarted = false
|
|
57
58
|
let disposed = false
|
|
58
59
|
|
|
59
|
-
const toneMappingMap: Record<
|
|
60
|
+
const toneMappingMap: Record<'aces' | 'reinhard' | 'cineon' | 'linear', ToneMapping> = {
|
|
60
61
|
aces: ACESFilmicToneMapping,
|
|
61
62
|
reinhard: ReinhardToneMapping,
|
|
62
63
|
cineon: CineonToneMapping,
|
|
@@ -175,7 +176,7 @@
|
|
|
175
176
|
)
|
|
176
177
|
|
|
177
178
|
watch([width, height], ([w, h]) => {
|
|
178
|
-
if (!initialized) return
|
|
179
|
+
if (!initialized || !renderer) return
|
|
179
180
|
camera.aspect = w / (h || 1)
|
|
180
181
|
camera.updateProjectionMatrix()
|
|
181
182
|
renderer.setSize(w, h)
|
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
voronoi2D,
|
|
29
29
|
} from '../shaders/common/noise'
|
|
30
30
|
import { cosinePalette } from '../shaders/common/palette'
|
|
31
|
-
import type { FloatUniform, TSLNode, Vec3Uniform } from '../shaders/types'
|
|
31
|
+
import type { ColorUniform, FloatUniform, TSLNode, Vec3Uniform } from '../shaders/types'
|
|
32
32
|
|
|
33
33
|
// ============================================
|
|
34
34
|
// Private helpers
|
|
@@ -368,10 +368,10 @@ export function createGradientMeshColorNode(uniforms: AmbientUniforms): TSLNode
|
|
|
368
368
|
}
|
|
369
369
|
|
|
370
370
|
export type ThemeColorUniforms = {
|
|
371
|
-
color1: Vec3Uniform
|
|
372
|
-
color2: Vec3Uniform
|
|
373
|
-
color3: Vec3Uniform
|
|
374
|
-
color4: Vec3Uniform
|
|
371
|
+
color1: ColorUniform | Vec3Uniform
|
|
372
|
+
color2: ColorUniform | Vec3Uniform
|
|
373
|
+
color3: ColorUniform | Vec3Uniform
|
|
374
|
+
color4: ColorUniform | Vec3Uniform
|
|
375
375
|
}
|
|
376
376
|
|
|
377
377
|
export function createThemeGradientColorNode(
|
|
@@ -448,10 +448,10 @@ export function createThemeGradientColorNode(
|
|
|
448
448
|
add(0.7, mul(nm4, 0.3))
|
|
449
449
|
)
|
|
450
450
|
|
|
451
|
-
let colorNode = mul(colors.color1, d1)
|
|
452
|
-
colorNode = add(colorNode, mul(colors.color2, d2))
|
|
453
|
-
colorNode = add(colorNode, mul(colors.color3, d3))
|
|
454
|
-
colorNode = add(colorNode, mul(colors.color4, d4))
|
|
451
|
+
let colorNode = mul(colors.color1.rgb, d1)
|
|
452
|
+
colorNode = add(colorNode, mul(colors.color2.rgb, d2))
|
|
453
|
+
colorNode = add(colorNode, mul(colors.color3.rgb, d3))
|
|
454
|
+
colorNode = add(colorNode, mul(colors.color4.rgb, d4))
|
|
455
455
|
|
|
456
456
|
// Normalise first, then vignette, then intensity
|
|
457
457
|
const totalWeight = add(d1, d2, d3, d4, 0.01)
|
|
@@ -555,8 +555,8 @@ export function createThemeAuroraColorNode(
|
|
|
555
555
|
const colorDriver = add(mul(curtain2, 0.6), mul(curtain3, 0.4))
|
|
556
556
|
const auroraColor = mix(colors.color1, colors.color2, colorDriver)
|
|
557
557
|
|
|
558
|
-
const skyColor = mul(colors.color1, 0.04)
|
|
559
|
-
const shimmerColor = mul(colors.color3, mul(shimmer, mul(aurora, 0.15)))
|
|
558
|
+
const skyColor = mul(colors.color1.rgb, 0.04)
|
|
559
|
+
const shimmerColor = mul(colors.color3.rgb, mul(shimmer, mul(aurora, 0.15)))
|
|
560
560
|
|
|
561
561
|
return add(mix(skyColor, auroraColor, aurora), shimmerColor)
|
|
562
562
|
})()
|
|
@@ -667,10 +667,10 @@ export function createThemeLavaLampColorNode(
|
|
|
667
667
|
|
|
668
668
|
// Weighted colour blend
|
|
669
669
|
const colorNode = add(
|
|
670
|
-
mul(colors.color1, w1),
|
|
671
|
-
mul(colors.color2, w2),
|
|
672
|
-
mul(colors.color3, w3),
|
|
673
|
-
mul(colors.color4, w4)
|
|
670
|
+
mul(colors.color1.rgb, w1),
|
|
671
|
+
mul(colors.color2.rgb, w2),
|
|
672
|
+
mul(colors.color3.rgb, w3),
|
|
673
|
+
mul(colors.color4.rgb, w4)
|
|
674
674
|
).div(wTotal.add(0.001))
|
|
675
675
|
|
|
676
676
|
// Darken space between blobs
|
|
@@ -51,8 +51,8 @@ export function useThemePreset(
|
|
|
51
51
|
watch(
|
|
52
52
|
() => [runtime.mouse.mouseX.value, runtime.mouse.mouseY.value],
|
|
53
53
|
([mx, my]) => {
|
|
54
|
-
uniforms.mouseX.value = mx
|
|
55
|
-
uniforms.mouseY.value = my
|
|
54
|
+
uniforms.mouseX.value = mx ?? 0.5
|
|
55
|
+
uniforms.mouseY.value = my ?? 0.5
|
|
56
56
|
},
|
|
57
57
|
{ immediate: true }
|
|
58
58
|
)
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
// This provides flexibility while maintaining code readability
|
|
8
8
|
|
|
9
9
|
import type { UniformNode } from 'three/webgpu'
|
|
10
|
-
import type { Vector3 } from 'three'
|
|
10
|
+
import type { Color, Vector3 } from 'three'
|
|
11
11
|
|
|
12
12
|
export type { TSLNode } from '../types/tsl'
|
|
13
13
|
|
|
@@ -17,5 +17,8 @@ export type FloatUniform = UniformNode<'float', number>
|
|
|
17
17
|
/** Vec3 uniform: `uniform(new Vector3(...))` */
|
|
18
18
|
export type Vec3Uniform = UniformNode<'vec3', Vector3>
|
|
19
19
|
|
|
20
|
+
/** Color uniform: `uniform(new Color(...))` */
|
|
21
|
+
export type ColorUniform = UniformNode<'color', Color>
|
|
22
|
+
|
|
20
23
|
// Re-export common Three types
|
|
21
24
|
export type { Color, Texture, Vector2, Vector3, Vector4 } from 'three'
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import type { AccentColor } from '#layers/theme/app/types/theme'
|
|
3
|
+
|
|
2
4
|
const appConfig = useAppConfig()
|
|
3
5
|
const { activeAccent, setAccent } = useAccentColor()
|
|
4
6
|
|
|
5
|
-
const accents = computed
|
|
7
|
+
const accents = computed<AccentColor[]>(
|
|
8
|
+
() => (appConfig.themeLayer?.accents ?? []) as AccentColor[]
|
|
9
|
+
)
|
|
6
10
|
</script>
|
|
7
11
|
|
|
8
12
|
<template>
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kmcom-nuxt-layers",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "2.2.
|
|
4
|
+
"version": "2.2.12",
|
|
5
5
|
"description": "Composable Nuxt 4 layers for building scalable Vue applications",
|
|
6
6
|
"exports": {
|
|
7
7
|
"./layers/core": "./layers/core/nuxt.config.ts",
|
|
@@ -201,7 +201,8 @@
|
|
|
201
201
|
"last 2 Chrome major versions",
|
|
202
202
|
"last 2 Firefox major versions",
|
|
203
203
|
"last 2 Safari major versions",
|
|
204
|
-
"last 2 Edge major versions"
|
|
204
|
+
"last 2 Edge major versions",
|
|
205
|
+
"baseline widely available"
|
|
205
206
|
],
|
|
206
207
|
"dependencies": {
|
|
207
208
|
"node-gyp": "^12.3.0",
|