kmcom-nuxt-layers 2.2.10 → 2.2.11

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.
@@ -99,7 +99,7 @@
99
99
  directionFactors.value = new Array(texts.length).fill(1)
100
100
  animLastTime = performance.now()
101
101
 
102
- const firstContainer = containerRef.value[0]
102
+ const firstContainer = containerRef.value?.[0]
103
103
  if (firstContainer) {
104
104
  scrollTriggerInstance = ScrollTrigger.create({
105
105
  trigger: firstContainer,
@@ -15,10 +15,7 @@ export function useRendererCapabilities() {
15
15
  const isReady = ref(false)
16
16
 
17
17
  function detectFromRenderer(renderer: WebGPURenderer | WebGLRenderer) {
18
- const isWebGPU = renderer.constructor?.name === 'WebGPURenderer'
19
- const glCaps = renderer.capabilities
20
-
21
- if (isWebGPU || !glCaps) {
18
+ if (!('capabilities' in renderer)) {
22
19
  capabilities.value = {
23
20
  backend: 'webgpu',
24
21
  maxTextureSize: 16384,
@@ -35,6 +32,8 @@ export function useRendererCapabilities() {
35
32
  return
36
33
  }
37
34
 
35
+ const glCaps = renderer.capabilities
36
+
38
37
  capabilities.value = {
39
38
  backend: 'webgl',
40
39
  maxTextureSize: glCaps.maxTextureSize,
@@ -17,8 +17,8 @@
17
17
  const { data: item, status } = await useCollectionItem(collection, slug)
18
18
  const { data: surround } = await useCollectionSurround(collection, slug)
19
19
 
20
- const surroundLinks = computed(
21
- () => (surround.value ?? undefined) as ContentSurroundLink[] | undefined
20
+ const surroundLinks = computed<ContentSurroundLink[] | undefined>(
21
+ () => surround.value ?? undefined
22
22
  )
23
23
  const itemImage = computed(() => (item.value as { image?: string } | null)?.image)
24
24
 
@@ -51,7 +51,7 @@
51
51
  <slot name="after-content" :item />
52
52
 
53
53
  <USeparator class="my-8" />
54
- <NuxtContentSurround :surround="surroundLinks" />
54
+ <NuxtContentSurround v-bind="surroundLinks?.length ? { surround: surroundLinks } : {}" />
55
55
  </UPageBody>
56
56
 
57
57
  <template v-if="!hideToc" #right>
@@ -3,38 +3,77 @@ import type { H3Event } from 'h3'
3
3
 
4
4
  import type { FeedItem } from './types'
5
5
 
6
- type AnyContent = Record<string, unknown>
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's first argument is typed as a const collection name, but we pass
14
- // a dynamic string at runtime — the cast is intentional and safe here.
15
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
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 firstAuthor = Array.isArray(item.authors)
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: item.path ?? item._path ?? '',
34
- id: item.path ?? item._path ?? '',
35
- date: new Date(item.date ?? item.createdAt ?? Date.now()),
36
- author: firstAuthor ?? undefined,
37
- tags: Array.isArray(item.tags) ? item.tags : undefined,
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<string, number> = {
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(() => appConfig.themeLayer?.accents ?? [])
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.10",
4
+ "version": "2.2.11",
5
5
  "description": "Composable Nuxt 4 layers for building scalable Vue applications",
6
6
  "exports": {
7
7
  "./layers/core": "./layers/core/nuxt.config.ts",