kmcom-nuxt-layers 2.2.5 → 2.2.8

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.
Files changed (218) hide show
  1. package/docs/FEEDS.md +197 -0
  2. package/docs/LAYERS-FIXES.md +101 -0
  3. package/docs/MIGRATION.md +627 -0
  4. package/docs/feed-layer.md +374 -0
  5. package/docs/patch-picture-provider-type.md +52 -0
  6. package/docs/shaderGuide.md +2071 -0
  7. package/docs/types-architecture.md +234 -0
  8. package/layers/animations/app/components/Motion/CountUp.vue +1 -1
  9. package/layers/animations/app/components/Motion/Magnetic.vue +1 -1
  10. package/layers/animations/app/components/Motion/Marquee.vue +3 -2
  11. package/layers/animations/app/components/Motion/MarqueeText.vue +3 -2
  12. package/layers/animations/app/components/Motion/Tilt.vue +1 -1
  13. package/layers/animations/app/composables/useCountUp.ts +4 -1
  14. package/layers/animations/app/composables/useMagneticElement.ts +2 -4
  15. package/layers/animations/app/composables/useMarqueeCopies.ts +4 -4
  16. package/layers/animations/app/composables/useTiltEffect.ts +1 -1
  17. package/layers/animations/app/types/animations.ts +8 -0
  18. package/layers/animations/app/types/index.ts +1 -0
  19. package/layers/animations/package.json +4 -1
  20. package/layers/canvas/app/components/ShaderCanvas.vue +4 -4
  21. package/layers/canvas/app/composables/useRendererCapabilities.ts +19 -15
  22. package/layers/canvas/app/types/index.ts +1 -0
  23. package/layers/canvas/package.json +2 -1
  24. package/layers/canvas/tsconfig.json +2 -1
  25. package/layers/content/app/components/Blog/Card.vue +5 -5
  26. package/layers/content/app/components/Gallery/AmbientImage.vue +3 -3
  27. package/layers/content/app/components/Gallery/Card.vue +3 -3
  28. package/layers/content/app/components/Gallery/Lightbox.vue +5 -1
  29. package/layers/content/app/components/NuxtContent/Detail.vue +5 -1
  30. package/layers/content/app/components/NuxtContent/Surround.vue +5 -3
  31. package/layers/content/app/components/NuxtContent/Toc.vue +1 -1
  32. package/layers/content/app/components/Portfolio/Card.vue +5 -5
  33. package/layers/content/app/components/content/Figure.vue +3 -3
  34. package/layers/content/app/composables/useBlogPosts.ts +2 -2
  35. package/layers/content/app/composables/useCollectionItem.ts +1 -3
  36. package/layers/content/app/composables/useGalleryItems.ts +2 -2
  37. package/layers/content/app/types/index.ts +1 -0
  38. package/layers/content/package.json +2 -1
  39. package/layers/core/app/composables/useCache.ts +0 -1
  40. package/layers/core/app/composables/useErrorLog.ts +9 -11
  41. package/layers/core/app/plugins/error-handler.ts +36 -36
  42. package/layers/core/app/plugins/feature-detection.client.ts +15 -15
  43. package/layers/core/app/plugins/init.ts +121 -129
  44. package/layers/core/app/plugins/loading.client.ts +27 -27
  45. package/layers/core/app/plugins/scroll-guard.client.ts +26 -26
  46. package/layers/core/app/utils/helpers.ts +14 -12
  47. package/layers/core/nuxt.config.ts +1 -0
  48. package/layers/feeds/app/plugins/feed-head.ts +62 -63
  49. package/layers/feeds/package.json +2 -1
  50. package/layers/feeds/server/routes/feed/discovery.get.ts +1 -2
  51. package/layers/feeds/server/utils/content-adapter.ts +3 -2
  52. package/layers/forms/app/components/Form/Field.vue +4 -4
  53. package/layers/forms/app/types/index.ts +1 -0
  54. package/layers/forms/package.json +2 -1
  55. package/layers/forms/server/api/contact.post.ts +1 -1
  56. package/layers/layout/app/components/Layout/Grid/Item.vue +33 -19
  57. package/layers/layout/app/components/Layout/Page/Container.vue +11 -11
  58. package/layers/layout/app/components/Layout/Page/Header.vue +1 -1
  59. package/layers/layout/app/components/Layout/Page/index.vue +1 -1
  60. package/layers/layout/app/components/Layout/Section/Gallery.vue +6 -1
  61. package/layers/layout/app/components/Layout/Section/Title.vue +1 -1
  62. package/layers/layout/app/types/index.ts +1 -0
  63. package/layers/layout/package.json +2 -1
  64. package/layers/mailer/app/types/index.ts +1 -0
  65. package/layers/mailer/app/types/mailer.ts +25 -0
  66. package/layers/mailer/package.json +2 -1
  67. package/layers/motion/package.json +2 -1
  68. package/layers/navigation/app/components/Links/Group.vue +1 -0
  69. package/layers/navigation/app/components/Links/Named.vue +2 -0
  70. package/layers/navigation/app/types/index.ts +1 -0
  71. package/layers/navigation/package.json +4 -1
  72. package/layers/page-transitions/app/plugins/page-transitions.client.ts +9 -9
  73. package/layers/page-transitions/package.json +4 -1
  74. package/layers/routing/app/plugins/feature-flags.client.ts +9 -9
  75. package/layers/routing/app/types/app-config.d.ts +3 -1
  76. package/layers/routing/app/types/index.ts +1 -0
  77. package/layers/routing/package.json +2 -1
  78. package/layers/scripts/app/composables/useGtm.ts +1 -1
  79. package/layers/scripts/app/types/index.ts +1 -0
  80. package/layers/scripts/app/types/scripts.ts +14 -0
  81. package/layers/scripts/package.json +2 -1
  82. package/layers/scroll/app/components/Motion/ScrollScene.vue +3 -1
  83. package/layers/scroll/app/composables/useScrollSteps.ts +2 -9
  84. package/layers/scroll/app/composables/useSectionProgress.ts +2 -1
  85. package/layers/scroll/app/plugins/locomotive-scroll.client.ts +54 -61
  86. package/layers/scroll/app/types/index.ts +1 -0
  87. package/layers/scroll/app/types/scroll.ts +32 -0
  88. package/layers/scroll/package.json +3 -0
  89. package/layers/seo/package.json +2 -1
  90. package/layers/shader/app/components/Material/Fresnel.client.vue +1 -1
  91. package/layers/shader/app/components/Material/Image.client.vue +1 -1
  92. package/layers/shader/app/components/Material/Node.client.vue +7 -7
  93. package/layers/shader/app/components/Material/Noise.client.vue +1 -1
  94. package/layers/shader/app/components/Node/Color.client.vue +17 -20
  95. package/layers/shader/app/components/Node/Noise.client.vue +31 -34
  96. package/layers/shader/app/components/Pipeline/Aurora.client.vue +4 -8
  97. package/layers/shader/app/components/Pipeline/BilinearGradient.client.vue +8 -11
  98. package/layers/shader/app/components/Pipeline/BillowNoise.client.vue +4 -8
  99. package/layers/shader/app/components/Pipeline/BrightnessContrast.client.vue +6 -2
  100. package/layers/shader/app/components/Pipeline/CellularNoise.client.vue +4 -8
  101. package/layers/shader/app/components/Pipeline/Checkerboard.client.vue +4 -8
  102. package/layers/shader/app/components/Pipeline/Circle.client.vue +5 -8
  103. package/layers/shader/app/components/Pipeline/Clouds.client.vue +4 -8
  104. package/layers/shader/app/components/Pipeline/ColorBurnBlend.client.vue +2 -19
  105. package/layers/shader/app/components/Pipeline/ColorDodgeBlend.client.vue +2 -19
  106. package/layers/shader/app/components/Pipeline/ColourRamp.client.vue +5 -9
  107. package/layers/shader/app/components/Pipeline/ConicGradient.client.vue +5 -8
  108. package/layers/shader/app/components/Pipeline/Cross.client.vue +4 -8
  109. package/layers/shader/app/components/Pipeline/CurlNoise.client.vue +3 -7
  110. package/layers/shader/app/components/Pipeline/DarkenBlend.client.vue +2 -19
  111. package/layers/shader/app/components/Pipeline/DayNightCycle.client.vue +5 -8
  112. package/layers/shader/app/components/Pipeline/DiagonalGradient.client.vue +5 -8
  113. package/layers/shader/app/components/Pipeline/DiamondGradient.client.vue +5 -8
  114. package/layers/shader/app/components/Pipeline/DifferenceBlend.client.vue +2 -19
  115. package/layers/shader/app/components/Pipeline/DomainWarpedNoise.client.vue +4 -8
  116. package/layers/shader/app/components/Pipeline/Dots.client.vue +4 -8
  117. package/layers/shader/app/components/Pipeline/DuoTone.client.vue +5 -9
  118. package/layers/shader/app/components/Pipeline/ExclusionBlend.client.vue +3 -23
  119. package/layers/shader/app/components/Pipeline/ExponentialFog.client.vue +4 -7
  120. package/layers/shader/app/components/Pipeline/FilmBurn.client.vue +4 -7
  121. package/layers/shader/app/components/Pipeline/Flame.client.vue +4 -8
  122. package/layers/shader/app/components/Pipeline/FocalGradient.client.vue +5 -8
  123. package/layers/shader/app/components/Pipeline/GodRays.client.vue +4 -7
  124. package/layers/shader/app/components/Pipeline/GradientNoise.client.vue +4 -8
  125. package/layers/shader/app/components/Pipeline/Grid.client.vue +4 -8
  126. package/layers/shader/app/components/Pipeline/Halation.client.vue +3 -7
  127. package/layers/shader/app/components/Pipeline/HardLightBlend.client.vue +2 -19
  128. package/layers/shader/app/components/Pipeline/Haze.client.vue +4 -7
  129. package/layers/shader/app/components/Pipeline/Hexagon.client.vue +4 -8
  130. package/layers/shader/app/components/Pipeline/LensFlare.client.vue +4 -7
  131. package/layers/shader/app/components/Pipeline/LightenBlend.client.vue +2 -19
  132. package/layers/shader/app/components/Pipeline/LinearGradient4.client.vue +2 -2
  133. package/layers/shader/app/components/Pipeline/Marble.client.vue +4 -8
  134. package/layers/shader/app/components/Pipeline/MonochromeTint.client.vue +3 -7
  135. package/layers/shader/app/components/Pipeline/MultiplyBlend.client.vue +2 -19
  136. package/layers/shader/app/components/Pipeline/NoisyGradient.client.vue +4 -8
  137. package/layers/shader/app/components/Pipeline/NoisyGradientBlend.client.vue +4 -8
  138. package/layers/shader/app/components/Pipeline/OverlayBlend.client.vue +2 -19
  139. package/layers/shader/app/components/Pipeline/Polygon.client.vue +4 -8
  140. package/layers/shader/app/components/Pipeline/RaymarchTunnel.client.vue +4 -7
  141. package/layers/shader/app/components/Pipeline/Rectangle.client.vue +4 -8
  142. package/layers/shader/app/components/Pipeline/RidgedNoise.client.vue +4 -8
  143. package/layers/shader/app/components/Pipeline/Ring.client.vue +4 -8
  144. package/layers/shader/app/components/Pipeline/ScreenBlend.client.vue +2 -19
  145. package/layers/shader/app/components/Pipeline/SkyAtmosphere.client.vue +6 -9
  146. package/layers/shader/app/components/Pipeline/SoftLightBlend.client.vue +2 -19
  147. package/layers/shader/app/components/Pipeline/SplitTone.client.vue +4 -8
  148. package/layers/shader/app/components/Pipeline/Star.client.vue +4 -8
  149. package/layers/shader/app/components/Pipeline/Stripes.client.vue +4 -8
  150. package/layers/shader/app/components/Pipeline/Tint.client.vue +4 -7
  151. package/layers/shader/app/components/Pipeline/Triangle.client.vue +4 -8
  152. package/layers/shader/app/components/Pipeline/ValueNoise.client.vue +4 -8
  153. package/layers/shader/app/components/Pipeline/VoronoiEdges.client.vue +4 -8
  154. package/layers/shader/app/components/Pipeline/Water.client.vue +5 -8
  155. package/layers/shader/app/components/Pipeline/WaveBendLayer.client.vue +4 -7
  156. package/layers/shader/app/components/Pipeline/WaveColourLayer.client.vue +3 -7
  157. package/layers/shader/app/components/Pipeline/Wood.client.vue +4 -8
  158. package/layers/shader/app/components/Preset/Aurora.client.vue +15 -21
  159. package/layers/shader/app/components/Preset/Flow.client.vue +2 -1
  160. package/layers/shader/app/components/Preset/GradientMesh.client.vue +2 -1
  161. package/layers/shader/app/components/Preset/Nebula.client.vue +2 -1
  162. package/layers/shader/app/components/Preset/Ocean.client.vue +2 -1
  163. package/layers/shader/app/components/Preset/ThemeAurora.client.vue +30 -90
  164. package/layers/shader/app/components/Preset/ThemeBubble.client.vue +30 -91
  165. package/layers/shader/app/components/Preset/ThemeFlow.client.vue +30 -90
  166. package/layers/shader/app/components/Preset/ThemeGradient.client.vue +30 -91
  167. package/layers/shader/app/components/Preset/ThemeLavaLamp.client.vue +30 -90
  168. package/layers/shader/app/components/Preset/ThemePlasma.client.vue +30 -90
  169. package/layers/shader/app/components/Preset/ThemeWave.client.vue +30 -90
  170. package/layers/shader/app/components/Shader/Background.client.vue +4 -4
  171. package/layers/shader/app/components/Shader/Host.client.vue +31 -33
  172. package/layers/shader/app/components/Shader/Runtime.client.vue +15 -23
  173. package/layers/shader/app/composables/useAmbientMaterials.ts +53 -51
  174. package/layers/shader/app/composables/useShaderMixBlend.ts +26 -0
  175. package/layers/shader/app/composables/useThemePreset.ts +75 -0
  176. package/layers/shader/app/plugins/shader.client.ts +21 -21
  177. package/layers/shader/app/shaders/common/noise.ts +2 -7
  178. package/layers/shader/app/shaders/types.ts +6 -6
  179. package/layers/shader/app/types/tsl.ts +7 -25
  180. package/layers/shader/app/types/uniforms.ts +2 -1
  181. package/layers/shader/app/utils/tsl/color.ts +7 -1
  182. package/layers/shader/package.json +2 -1
  183. package/layers/theme/app/components/ThemePicker/Colors.vue +1 -3
  184. package/layers/theme/app/plugins/theme.client.ts +54 -51
  185. package/layers/theme/app/types/app-config.d.ts +4 -2
  186. package/layers/theme/app/types/index.ts +1 -0
  187. package/layers/theme/app/types/theme.ts +3 -18
  188. package/layers/theme/package.json +2 -1
  189. package/layers/theme/server/plugins/theme-fouc.ts +1 -1
  190. package/layers/transitions/package.json +4 -1
  191. package/layers/typography/app/components/Typography/CodeBlock.vue +2 -2
  192. package/layers/typography/app/components/Typography/Headline.vue +2 -2
  193. package/layers/typography/app/components/Typography/HeadlineScreen.vue +1 -1
  194. package/layers/typography/app/components/Typography/QuoteBlock.vue +4 -1
  195. package/layers/typography/app/components/Typography/TextStroke.vue +2 -0
  196. package/layers/typography/app/components/Typography/index.vue +36 -27
  197. package/layers/typography/app/composables/typography.ts +27 -21
  198. package/layers/typography/app/types/colors.ts +9 -29
  199. package/layers/typography/app/types/index.ts +2 -0
  200. package/layers/typography/package.json +4 -1
  201. package/layers/ui/package.json +2 -1
  202. package/layers/visual/app/app.config.ts +5 -2
  203. package/layers/visual/app/components/Accent/Blob.vue +20 -20
  204. package/layers/visual/app/components/Accent/Scene.vue +2 -2
  205. package/layers/visual/app/components/Base/Modal.vue +2 -2
  206. package/layers/visual/app/components/Gradient/Background.vue +2 -2
  207. package/layers/visual/app/components/Gradient/Text.vue +2 -2
  208. package/layers/visual/app/components/Media/Picture.vue +3 -1
  209. package/layers/visual/app/components/Progress/Bar.vue +6 -6
  210. package/layers/visual/app/components/Tint/Overlay.vue +14 -14
  211. package/layers/visual/app/composables/accent.ts +10 -8
  212. package/layers/visual/app/composables/gradient.ts +2 -3
  213. package/layers/visual/app/composables/tint.ts +7 -7
  214. package/layers/visual/app/types/index.ts +6 -0
  215. package/layers/visual/app/types/media.ts +4 -2
  216. package/layers/visual/app/types/tint.ts +2 -1
  217. package/layers/visual/package.json +4 -1
  218. package/package.json +5 -2
@@ -1,8 +1,7 @@
1
1
  <script setup lang="ts">
2
- import {
3
- createAmbientUniforms,
4
- createThemeWaveColorNode,
5
- } from '#layers/shader/app/composables/useAmbientMaterials'
2
+ import { createThemeWaveColorNode } from '#layers/shader/app/composables/useAmbientMaterials'
3
+ import { type ThemePresetProps } from '#layers/shader/app/composables/useThemePreset'
4
+ import type { TSLNode } from '#layers/shader/app/types/tsl'
6
5
 
7
6
  const {
8
7
  speed = 1.0,
@@ -13,98 +12,39 @@
13
12
  color2 = '#6366f1',
14
13
  color3 = '#a78bfa',
15
14
  color4 = '#38bdf8',
16
- } = defineProps<{
17
- speed?: number
18
- intensity?: number
19
- mouseInteraction?: boolean
20
- mouseStrength?: number
21
- color1?: string
22
- color2?: string
23
- color3?: string
24
- color4?: string
25
- }>()
15
+ } = defineProps<ThemePresetProps>()
26
16
 
27
17
  const emit = defineEmits<{
28
- node: [colorNode: any]
18
+ node: [colorNode: TSLNode]
29
19
  }>()
30
20
 
31
- const uniforms = createAmbientUniforms({
32
- speed: speed,
33
- intensity: intensity,
34
- mouseInteraction: mouseInteraction,
35
- })
36
- if (mouseInteraction) {
37
- uniforms.mouseStrength.value = mouseStrength
38
- }
39
-
40
- const c1 = useShaderColor(color1)
41
- const c2 = useShaderColor(color2)
42
- const c3 = useShaderColor(color3)
43
- const c4 = useShaderColor(color4)
44
-
45
- const colorNode = createThemeWaveColorNode(uniforms, {
46
- color1: c1.node,
47
- color2: c2.node,
48
- color3: c3.node,
49
- color4: c4.node,
21
+ const { uniforms, colorNode } = useThemePreset(createThemeWaveColorNode, {
22
+ get speed() {
23
+ return speed
24
+ },
25
+ get intensity() {
26
+ return intensity
27
+ },
28
+ get mouseInteraction() {
29
+ return mouseInteraction
30
+ },
31
+ get mouseStrength() {
32
+ return mouseStrength
33
+ },
34
+ get color1() {
35
+ return color1
36
+ },
37
+ get color2() {
38
+ return color2
39
+ },
40
+ get color3() {
41
+ return color3
42
+ },
43
+ get color4() {
44
+ return color4
45
+ },
50
46
  })
51
47
 
52
- watch(
53
- () => color1,
54
- (hex) => c1.tweenTo(hex, 0.8)
55
- )
56
- watch(
57
- () => color2,
58
- (hex) => c2.tweenTo(hex, 0.8)
59
- )
60
- watch(
61
- () => color3,
62
- (hex) => c3.tweenTo(hex, 0.8)
63
- )
64
- watch(
65
- () => color4,
66
- (hex) => c4.tweenTo(hex, 0.8)
67
- )
68
-
69
- try {
70
- const runtime = useShaderRuntimeContext()
71
- watch(
72
- () => [runtime.mouse.mouseX.value, runtime.mouse.mouseY.value],
73
- ([mx, my]) => {
74
- uniforms.mouseX.value = mx
75
- uniforms.mouseY.value = my
76
- },
77
- { immediate: true }
78
- )
79
- } catch {
80
- // No runtime context
81
- }
82
-
83
- watch(
84
- () => speed,
85
- (v) => {
86
- uniforms.speed.value = v
87
- }
88
- )
89
- watch(
90
- () => intensity,
91
- (v) => {
92
- uniforms.intensity.value = v
93
- }
94
- )
95
- watch(
96
- () => mouseInteraction,
97
- (v) => {
98
- uniforms.mouseStrength.value = v ? mouseStrength : 0
99
- }
100
- )
101
- watch(
102
- () => mouseStrength,
103
- (v) => {
104
- if (mouseInteraction) uniforms.mouseStrength.value = v
105
- }
106
- )
107
-
108
48
  emit('node', colorNode)
109
49
  defineExpose({ uniforms, colorNode })
110
50
  </script>
@@ -13,7 +13,7 @@
13
13
  Scene,
14
14
  SRGBColorSpace,
15
15
  } from 'three'
16
- import { WebGPURenderer } from 'three/webgpu'
16
+ import { MeshBasicNodeMaterial, WebGPURenderer } from 'three/webgpu'
17
17
 
18
18
  const {
19
19
  material = null,
@@ -25,7 +25,7 @@
25
25
  pointerEvents = 'none',
26
26
  } = defineProps<{
27
27
  /** The TSL node material to render */
28
- material?: any
28
+ material?: MeshBasicNodeMaterial | null
29
29
  /** Background clear color */
30
30
  clearColor?: string
31
31
  /** Tone mapping algorithm */
@@ -41,13 +41,13 @@
41
41
  }>()
42
42
 
43
43
  const emit = defineEmits<{
44
- ready: [renderer: any]
44
+ ready: [renderer: WebGPURenderer]
45
45
  }>()
46
46
 
47
47
  const canvasRef = useTemplateRef<HTMLCanvasElement>('canvasRef')
48
48
  const { width, height } = useWindowSize()
49
49
 
50
- let renderer: any
50
+ let renderer: WebGPURenderer | undefined
51
51
  let scene: Scene
52
52
  let camera: PerspectiveCamera
53
53
  let planeMesh: Mesh
@@ -1,36 +1,34 @@
1
1
  <script setup lang="ts">
2
2
  import type { Component } from 'vue'
3
+ import type { TSLNode } from '#layers/shader/app/types/tsl'
3
4
  import { tweenUniform } from '#layers/shader/app/utils/tsl/tween'
4
5
  import { DoubleSide } from 'three'
5
6
  import { mix as tslMix, uniform } from 'three/tsl'
6
7
  import { MeshBasicNodeMaterial } from 'three/webgpu'
7
8
 
8
- const props = withDefaults(
9
- defineProps<{
10
- /** The active preset component */
11
- preset?: Component | null
12
- /** Crossfade duration in seconds */
13
- transitionDuration?: number
14
- /** Props forwarded to the active preset component */
15
- presetProps?: Record<string, any>
16
- /** ShaderBackground props */
17
- clearColor?: string
18
- toneMapping?: 'aces' | 'reinhard' | 'cineon' | 'linear'
19
- fixed?: boolean
20
- zIndex?: number
21
- pointerEvents?: 'none' | 'auto'
22
- }>(),
23
- {
24
- preset: null,
25
- transitionDuration: 1.0,
26
- presetProps: () => ({}),
27
- clearColor: '#000000',
28
- toneMapping: 'aces',
29
- fixed: true,
30
- zIndex: -1,
31
- pointerEvents: 'none',
32
- }
33
- )
9
+ const {
10
+ preset = null,
11
+ transitionDuration = 1.0,
12
+ presetProps = {} as Record<string, unknown>,
13
+ clearColor = '#000000',
14
+ toneMapping = 'aces',
15
+ fixed = true,
16
+ zIndex = -1,
17
+ pointerEvents = 'none',
18
+ } = defineProps<{
19
+ /** The active preset component */
20
+ preset?: Component | null
21
+ /** Crossfade duration in seconds */
22
+ transitionDuration?: number
23
+ /** Props forwarded to the active preset component */
24
+ presetProps?: Record<string, unknown>
25
+ /** ShaderBackground props */
26
+ clearColor?: string
27
+ toneMapping?: 'aces' | 'reinhard' | 'cineon' | 'linear'
28
+ fixed?: boolean
29
+ zIndex?: number
30
+ pointerEvents?: 'none' | 'auto'
31
+ }>()
34
32
 
35
33
  const emit = defineEmits<{
36
34
  transitionStart: []
@@ -42,7 +40,7 @@
42
40
  const isTransitioning = ref(false)
43
41
 
44
42
  // Current and next preset tracking
45
- const currentPreset = shallowRef<Component | null>(props.preset)
43
+ const currentPreset = shallowRef<Component | null>(preset)
46
44
  const nextPreset = shallowRef<Component | null>(null)
47
45
 
48
46
  function setCurrentPreset(preset: Component | null) {
@@ -54,15 +52,15 @@
54
52
  material.side = DoubleSide
55
53
 
56
54
  // Current and next graph nodes (set by preset via @node event)
57
- let currentNode: any = null
58
- let nextNode: any = null
55
+ let currentNode: TSLNode | null = null
56
+ let nextNode: TSLNode | null = null
59
57
 
60
- function setCurrentNode(node: any) {
58
+ function setCurrentNode(node: TSLNode) {
61
59
  currentNode = node
62
60
  updateMaterialNode()
63
61
  }
64
62
 
65
- function setNextNode(node: any) {
63
+ function setNextNode(node: TSLNode) {
66
64
  nextNode = node
67
65
  updateMaterialNode()
68
66
  }
@@ -79,7 +77,7 @@
79
77
 
80
78
  // Watch preset changes for crossfade
81
79
  watch(
82
- () => props.preset,
80
+ () => preset,
83
81
  async (newPreset, oldPreset) => {
84
82
  if (!newPreset || newPreset === oldPreset) return
85
83
 
@@ -100,7 +98,7 @@
100
98
  transitionProgress,
101
99
  0,
102
100
  1,
103
- props.transitionDuration,
101
+ transitionDuration,
104
102
  (t) => t * t * (3 - 2 * t) // smoothstep
105
103
  )
106
104
 
@@ -1,41 +1,33 @@
1
1
  <script setup lang="ts">
2
- const props = withDefaults(
3
- defineProps<{
4
- speed?: number
5
- accentColor?: string
6
- darkMode?: boolean
7
- mouseSmoothing?: number
8
- }>(),
9
- {
10
- speed: 1.0,
11
- accentColor: '#8b5cf6',
12
- darkMode: true,
13
- mouseSmoothing: 0.1,
14
- }
15
- )
2
+ const {
3
+ speed = 1.0,
4
+ accentColor = '#8b5cf6',
5
+ darkMode = true,
6
+ mouseSmoothing = 0.1,
7
+ } = defineProps<{
8
+ speed?: number
9
+ accentColor?: string
10
+ darkMode?: boolean
11
+ mouseSmoothing?: number
12
+ }>()
16
13
 
17
- const runtime = useShaderRuntime({
18
- speed: props.speed,
19
- accentColor: props.accentColor,
20
- darkMode: props.darkMode,
21
- mouseSmoothing: props.mouseSmoothing,
22
- })
14
+ const runtime = useShaderRuntime({ speed, accentColor, darkMode, mouseSmoothing })
23
15
 
24
16
  // Watch props and update runtime uniforms
25
17
  watch(
26
- () => props.speed,
18
+ () => speed,
27
19
  (val) => runtime.time.setSpeed(val)
28
20
  )
29
21
 
30
22
  watch(
31
- () => props.accentColor,
23
+ () => accentColor,
32
24
  (val) => {
33
25
  runtime.accentColor.value = val
34
26
  }
35
27
  )
36
28
 
37
29
  watch(
38
- () => props.darkMode,
30
+ () => darkMode,
39
31
  (val) => {
40
32
  runtime.darkMode.value = val
41
33
  }
@@ -28,7 +28,35 @@ import {
28
28
  voronoi2D,
29
29
  } from '../shaders/common/noise'
30
30
  import { cosinePalette } from '../shaders/common/palette'
31
- import type { TSLNode } from '../shaders/types'
31
+ import type { FloatUniform, TSLNode, Vec3Uniform } from '../shaders/types'
32
+
33
+ // ============================================
34
+ // Private helpers
35
+ // ============================================
36
+
37
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
38
+ function buildFlowWarpedUV(uvCoord: any, t: any, mouseOffset: any): {
39
+ warpedUV: TSLNode
40
+ n1: TSLNode
41
+ n2: TSLNode
42
+ } {
43
+ const warpCoarse1 = simplexNoise2D(add(mul(uvCoord, 1.5), t))
44
+ const warpCoarse2 = simplexNoise2D(add(mul(uvCoord, 1.5), mul(t, -0.5), 7.0))
45
+ const warpedUV1 = add(uvCoord, mul(vec2(warpCoarse1, warpCoarse2), 0.25), mouseOffset)
46
+
47
+ const warpMed1 = simplexNoise2D(add(mul(warpedUV1, 3.0), mul(t, 0.7)))
48
+ const warpMed2 = simplexNoise2D(add(mul(warpedUV1, 3.0), mul(t, -0.3), 15.0))
49
+ const warpedUV2 = add(warpedUV1, mul(vec2(warpMed1, warpMed2), 0.12))
50
+
51
+ const warpFine1 = simplexNoise2D(add(mul(warpedUV2, 5.0), mul(t, 1.2)))
52
+ const warpFine2 = simplexNoise2D(add(mul(warpedUV2, 5.0), mul(t, -0.8), 25.0))
53
+ const warpedUV = add(warpedUV2, mul(vec2(warpFine1, warpFine2), 0.05))
54
+
55
+ const n1 = fbm2D(warpedUV, { octaves: 5, frequency: 2.0 }).mul(0.5).add(0.5)
56
+ const n2 = ridgedFbm2d(warpedUV, { octaves: 4, frequency: 1.5 })
57
+
58
+ return { warpedUV, n1, n2 }
59
+ }
32
60
 
33
61
  // ============================================
34
62
  // Types
@@ -42,11 +70,11 @@ export type AmbientMaterialOptions = {
42
70
  }
43
71
 
44
72
  export type AmbientUniforms = {
45
- speed: any
46
- intensity: any
47
- mouseX: any
48
- mouseY: any
49
- mouseStrength: any
73
+ speed: FloatUniform
74
+ intensity: FloatUniform
75
+ mouseX: FloatUniform
76
+ mouseY: FloatUniform
77
+ mouseStrength: FloatUniform
50
78
  }
51
79
 
52
80
  export type AmbientMaterialResult = {
@@ -55,7 +83,7 @@ export type AmbientMaterialResult = {
55
83
  }
56
84
 
57
85
  export type AmbientNodeResult = {
58
- colorNode: any
86
+ colorNode: TSLNode
59
87
  uniforms: AmbientUniforms
60
88
  }
61
89
 
@@ -78,7 +106,7 @@ export function createAmbientUniforms(options: AmbientMaterialOptions = {}): Amb
78
106
  // Color Node Creators (TSL node, no material)
79
107
  // ============================================
80
108
 
81
- export function createAuroraColorNode(uniforms: AmbientUniforms): any {
109
+ export function createAuroraColorNode(uniforms: AmbientUniforms): TSLNode {
82
110
  const {
83
111
  speed: uSpeed,
84
112
  intensity: uIntensity,
@@ -137,7 +165,7 @@ export function createAuroraColorNode(uniforms: AmbientUniforms): any {
137
165
  })()
138
166
  }
139
167
 
140
- export function createNebulaColorNode(uniforms: AmbientUniforms): any {
168
+ export function createNebulaColorNode(uniforms: AmbientUniforms): TSLNode {
141
169
  const {
142
170
  speed: uSpeed,
143
171
  intensity: uIntensity,
@@ -205,7 +233,7 @@ export function createNebulaColorNode(uniforms: AmbientUniforms): any {
205
233
  })()
206
234
  }
207
235
 
208
- export function createFlowColorNode(uniforms: AmbientUniforms): any {
236
+ export function createFlowColorNode(uniforms: AmbientUniforms): TSLNode {
209
237
  const {
210
238
  speed: uSpeed,
211
239
  intensity: uIntensity,
@@ -223,20 +251,7 @@ export function createFlowColorNode(uniforms: AmbientUniforms): any {
223
251
  mul(sub(uMouseY, 0.5), uMouseStrength, 0.3)
224
252
  )
225
253
 
226
- const warpCoarse1 = simplexNoise2D(add(mul(uvCoord, 1.5), t))
227
- const warpCoarse2 = simplexNoise2D(add(mul(uvCoord, 1.5), mul(t, -0.5), 7.0))
228
- const warpedUV1 = add(uvCoord, mul(vec2(warpCoarse1, warpCoarse2), 0.25), mouseOffset)
229
-
230
- const warpMed1 = simplexNoise2D(add(mul(warpedUV1, 3.0), mul(t, 0.7)))
231
- const warpMed2 = simplexNoise2D(add(mul(warpedUV1, 3.0), mul(t, -0.3), 15.0))
232
- const warpedUV2 = add(warpedUV1, mul(vec2(warpMed1, warpMed2), 0.12))
233
-
234
- const warpFine1 = simplexNoise2D(add(mul(warpedUV2, 5.0), mul(t, 1.2)))
235
- const warpFine2 = simplexNoise2D(add(mul(warpedUV2, 5.0), mul(t, -0.8), 25.0))
236
- const warpedUV = add(warpedUV2, mul(vec2(warpFine1, warpFine2), 0.05))
237
-
238
- const n1 = fbm2D(warpedUV, { octaves: 5, frequency: 2.0 }).mul(0.5).add(0.5)
239
- const n2 = ridgedFbm2d(warpedUV, { octaves: 4, frequency: 1.5 })
254
+ const { n1, n2 } = buildFlowWarpedUV(uvCoord, t, mouseOffset)
240
255
 
241
256
  const color1 = vec3(0.075, 0.306, 0.369)
242
257
  const color2 = vec3(0.443, 0.698, 0.502)
@@ -266,7 +281,7 @@ export function createFlowColorNode(uniforms: AmbientUniforms): any {
266
281
  })()
267
282
  }
268
283
 
269
- export function createGradientMeshColorNode(uniforms: AmbientUniforms): any {
284
+ export function createGradientMeshColorNode(uniforms: AmbientUniforms): TSLNode {
270
285
  const {
271
286
  speed: uSpeed,
272
287
  intensity: uIntensity,
@@ -353,16 +368,16 @@ export function createGradientMeshColorNode(uniforms: AmbientUniforms): any {
353
368
  }
354
369
 
355
370
  export type ThemeColorUniforms = {
356
- color1: any // TSL uniform node wrapping a THREE.Color
357
- color2: any
358
- color3: any
359
- color4: any
371
+ color1: Vec3Uniform
372
+ color2: Vec3Uniform
373
+ color3: Vec3Uniform
374
+ color4: Vec3Uniform
360
375
  }
361
376
 
362
377
  export function createThemeGradientColorNode(
363
378
  uniforms: AmbientUniforms,
364
379
  colors: ThemeColorUniforms
365
- ): any {
380
+ ): TSLNode {
366
381
  const {
367
382
  speed: uSpeed,
368
383
  intensity: uIntensity,
@@ -453,7 +468,7 @@ export function createThemeGradientColorNode(
453
468
  export function createThemeFlowColorNode(
454
469
  uniforms: AmbientUniforms,
455
470
  colors: ThemeColorUniforms
456
- ): any {
471
+ ): TSLNode {
457
472
  const {
458
473
  speed: uSpeed,
459
474
  intensity: uIntensity,
@@ -471,20 +486,7 @@ export function createThemeFlowColorNode(
471
486
  mul(sub(uMouseY, 0.5), uMouseStrength, 0.3)
472
487
  )
473
488
 
474
- const warpCoarse1 = simplexNoise2D(add(mul(uvCoord, 1.5), t))
475
- const warpCoarse2 = simplexNoise2D(add(mul(uvCoord, 1.5), mul(t, -0.5), 7.0))
476
- const warpedUV1 = add(uvCoord, mul(vec2(warpCoarse1, warpCoarse2), 0.25), mouseOffset)
477
-
478
- const warpMed1 = simplexNoise2D(add(mul(warpedUV1, 3.0), mul(t, 0.7)))
479
- const warpMed2 = simplexNoise2D(add(mul(warpedUV1, 3.0), mul(t, -0.3), 15.0))
480
- const warpedUV2 = add(warpedUV1, mul(vec2(warpMed1, warpMed2), 0.12))
481
-
482
- const warpFine1 = simplexNoise2D(add(mul(warpedUV2, 5.0), mul(t, 1.2)))
483
- const warpFine2 = simplexNoise2D(add(mul(warpedUV2, 5.0), mul(t, -0.8), 25.0))
484
- const warpedUV = add(warpedUV2, mul(vec2(warpFine1, warpFine2), 0.05))
485
-
486
- const n1 = fbm2D(warpedUV, { octaves: 5, frequency: 2.0 }).mul(0.5).add(0.5)
487
- const n2 = ridgedFbm2d(warpedUV, { octaves: 4, frequency: 1.5 })
489
+ const { n1, n2 } = buildFlowWarpedUV(uvCoord, t, mouseOffset)
488
490
 
489
491
  let colorNode = mix(colors.color1, colors.color2, n1)
490
492
  colorNode = mix(colorNode, colors.color3, mul(n2, 0.5))
@@ -506,7 +508,7 @@ export function createThemeFlowColorNode(
506
508
  export function createThemeAuroraColorNode(
507
509
  uniforms: AmbientUniforms,
508
510
  colors: ThemeColorUniforms
509
- ): any {
511
+ ): TSLNode {
510
512
  const {
511
513
  speed: uSpeed,
512
514
  intensity: uIntensity,
@@ -563,7 +565,7 @@ export function createThemeAuroraColorNode(
563
565
  export function createThemeWaveColorNode(
564
566
  uniforms: AmbientUniforms,
565
567
  colors: ThemeColorUniforms
566
- ): any {
568
+ ): TSLNode {
567
569
  const {
568
570
  speed: uSpeed,
569
571
  intensity: uIntensity,
@@ -613,7 +615,7 @@ export function createThemeWaveColorNode(
613
615
  export function createThemeLavaLampColorNode(
614
616
  uniforms: AmbientUniforms,
615
617
  colors: ThemeColorUniforms
616
- ): any {
618
+ ): TSLNode {
617
619
  const {
618
620
  speed: uSpeed,
619
621
  intensity: uIntensity,
@@ -681,7 +683,7 @@ export function createThemeLavaLampColorNode(
681
683
  export function createThemeBubbleColorNode(
682
684
  uniforms: AmbientUniforms,
683
685
  colors: ThemeColorUniforms
684
- ): any {
686
+ ): TSLNode {
685
687
  const {
686
688
  speed: uSpeed,
687
689
  intensity: uIntensity,
@@ -716,7 +718,7 @@ export function createThemeBubbleColorNode(
716
718
  export function createThemePlasmaColorNode(
717
719
  uniforms: AmbientUniforms,
718
720
  colors: ThemeColorUniforms
719
- ): any {
721
+ ): TSLNode {
720
722
  const {
721
723
  speed: uSpeed,
722
724
  intensity: uIntensity,
@@ -770,7 +772,7 @@ export function createThemePlasmaColorNode(
770
772
  })()
771
773
  }
772
774
 
773
- export function createOceanColorNode(uniforms: AmbientUniforms): any {
775
+ export function createOceanColorNode(uniforms: AmbientUniforms): TSLNode {
774
776
  const {
775
777
  speed: uSpeed,
776
778
  intensity: uIntensity,
@@ -0,0 +1,26 @@
1
+ import { Color } from 'three'
2
+ import { mix, uniform, vec4 } from 'three/tsl'
3
+
4
+ import type { TSLNode } from '../types/tsl'
5
+
6
+ export function useShaderMixBlend(
7
+ blendFn: (base: TSLNode, blend: TSLNode) => TSLNode,
8
+ colorGetter: () => string,
9
+ opacityGetter: () => number,
10
+ order: number = 0
11
+ ) {
12
+ const colorNode = uniform(new Color(colorGetter()))
13
+ const opacityNode = uniform(opacityGetter())
14
+
15
+ watch(colorGetter, (v) => {
16
+ colorNode.value.set(v)
17
+ })
18
+ watch(opacityGetter, (v) => {
19
+ opacityNode.value = v
20
+ })
21
+
22
+ useShaderStage(
23
+ (prev) => vec4(mix(prev.xyz, blendFn(prev.xyz, colorNode as unknown as TSLNode), opacityNode), prev.w),
24
+ order
25
+ )
26
+ }
@@ -0,0 +1,75 @@
1
+ import {
2
+ createAmbientUniforms,
3
+ type AmbientUniforms,
4
+ type ThemeColorUniforms,
5
+ } from '#layers/shader/app/composables/useAmbientMaterials'
6
+ import type { TSLNode } from '#layers/shader/app/types/tsl'
7
+
8
+ export type ThemePresetProps = {
9
+ speed?: number
10
+ intensity?: number
11
+ mouseInteraction?: boolean
12
+ mouseStrength?: number
13
+ color1?: string
14
+ color2?: string
15
+ color3?: string
16
+ color4?: string
17
+ }
18
+
19
+ export function useThemePreset(
20
+ colorNodeFactory: (uniforms: AmbientUniforms, colors: ThemeColorUniforms) => TSLNode,
21
+ props: Readonly<Required<ThemePresetProps>>
22
+ ) {
23
+ const uniforms = createAmbientUniforms({
24
+ speed: props.speed,
25
+ intensity: props.intensity,
26
+ mouseInteraction: props.mouseInteraction,
27
+ })
28
+ if (props.mouseInteraction) {
29
+ uniforms.mouseStrength.value = props.mouseStrength
30
+ }
31
+
32
+ const c1 = useShaderColor(props.color1)
33
+ const c2 = useShaderColor(props.color2)
34
+ const c3 = useShaderColor(props.color3)
35
+ const c4 = useShaderColor(props.color4)
36
+
37
+ const colorNode = colorNodeFactory(uniforms, {
38
+ color1: c1.node,
39
+ color2: c2.node,
40
+ color3: c3.node,
41
+ color4: c4.node,
42
+ })
43
+
44
+ watch(() => props.color1, (hex) => c1.tweenTo(hex, 0.8))
45
+ watch(() => props.color2, (hex) => c2.tweenTo(hex, 0.8))
46
+ watch(() => props.color3, (hex) => c3.tweenTo(hex, 0.8))
47
+ watch(() => props.color4, (hex) => c4.tweenTo(hex, 0.8))
48
+
49
+ try {
50
+ const runtime = useShaderRuntimeContext()
51
+ watch(
52
+ () => [runtime.mouse.mouseX.value, runtime.mouse.mouseY.value],
53
+ ([mx, my]) => {
54
+ uniforms.mouseX.value = mx
55
+ uniforms.mouseY.value = my
56
+ },
57
+ { immediate: true }
58
+ )
59
+ } catch {
60
+ // No runtime context
61
+ }
62
+
63
+ watch(() => props.speed, (v) => { uniforms.speed.value = v })
64
+ watch(() => props.intensity, (v) => { uniforms.intensity.value = v })
65
+ watch(
66
+ () => props.mouseInteraction,
67
+ (v) => { uniforms.mouseStrength.value = v ? props.mouseStrength : 0 }
68
+ )
69
+ watch(
70
+ () => props.mouseStrength,
71
+ (v) => { if (props.mouseInteraction) uniforms.mouseStrength.value = v }
72
+ )
73
+
74
+ return { uniforms, colorNode }
75
+ }