kmcom-nuxt-layers 1.1.4 → 1.1.6

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 (55) hide show
  1. package/layers/content/app/.DS_Store +0 -0
  2. package/layers/core/app/.DS_Store +0 -0
  3. package/layers/forms/app/.DS_Store +0 -0
  4. package/layers/layout/app/.DS_Store +0 -0
  5. package/layers/layout/app/assets/css/layout/grids.css +2 -6
  6. package/layers/layout/app/components/Layout/Grid/Item.vue +61 -36
  7. package/layers/motion/app/.DS_Store +0 -0
  8. package/layers/shader/app/.DS_Store +0 -0
  9. package/layers/shader/app/components/Node/Color.client.vue +51 -0
  10. package/layers/shader/app/components/Node/Fresnel.client.vue +53 -0
  11. package/layers/shader/app/components/Node/Gradient.client.vue +87 -0
  12. package/layers/shader/app/components/Node/Mix.client.vue +50 -0
  13. package/layers/shader/app/components/Node/Noise.client.vue +101 -0
  14. package/layers/shader/app/components/Preset/Aurora.client.vue +67 -0
  15. package/layers/shader/app/components/Preset/Flow.client.vue +61 -0
  16. package/layers/shader/app/components/Preset/GradientMesh.client.vue +61 -0
  17. package/layers/shader/app/components/Preset/Nebula.client.vue +61 -0
  18. package/layers/shader/app/components/Preset/Ocean.client.vue +61 -0
  19. package/layers/shader/app/components/Shader/Background.client.vue +168 -0
  20. package/layers/shader/app/components/Shader/Host.client.vue +149 -0
  21. package/layers/shader/app/components/Shader/Material.client.vue +49 -0
  22. package/layers/shader/app/components/Shader/Runtime.client.vue +47 -0
  23. package/layers/shader/app/composables/useAmbientMaterials.ts +283 -344
  24. package/layers/shader/app/composables/useShaderColor.ts +103 -0
  25. package/layers/shader/app/composables/useShaderFloat.ts +62 -0
  26. package/layers/shader/app/composables/useShaderGraph.ts +131 -0
  27. package/layers/shader/app/composables/useShaderRuntime.ts +96 -0
  28. package/layers/shader/app/composables/useShaderVec2.ts +99 -0
  29. package/layers/shader/app/shaders/common/palette.ts +1 -0
  30. package/layers/shader/app/utils/tsl/index.ts +2 -84
  31. package/layers/shader/app/utils/tsl/oklch.ts +91 -0
  32. package/layers/shader/app/utils/tsl/tween.ts +58 -0
  33. package/layers/shader/nuxt.config.ts +93 -14
  34. package/layers/theme/app/.DS_Store +0 -0
  35. package/layers/ui/app/.DS_Store +0 -0
  36. package/layers/ui/app/components/Typography/CodeBlock.vue +4 -1
  37. package/layers/ui/app/components/Typography/Headline.vue +6 -0
  38. package/layers/ui/app/components/Typography/QuoteBlock.vue +4 -2
  39. package/layers/ui/app/components/Typography/index.vue +3 -0
  40. package/layers/ui/app/composables/typography.ts +8 -0
  41. package/layers/ui/app/layouts/default.vue +12 -2
  42. package/layers/ui/app/types/typography.ts +22 -0
  43. package/package.json +70 -68
  44. package/layers/shader/app/components/Shader/Background.vue +0 -159
  45. package/layers/shader/app/components/WebGPUCanvas.client.vue +0 -245
  46. /package/layers/shader/app/components/Material/{AmbientAurora.vue → AmbientAurora.client.vue} +0 -0
  47. /package/layers/shader/app/components/Material/{AmbientFlow.vue → AmbientFlow.client.vue} +0 -0
  48. /package/layers/shader/app/components/Material/{AmbientGradientMesh.vue → AmbientGradientMesh.client.vue} +0 -0
  49. /package/layers/shader/app/components/Material/{AmbientNebula.vue → AmbientNebula.client.vue} +0 -0
  50. /package/layers/shader/app/components/Material/{AmbientOcean.vue → AmbientOcean.client.vue} +0 -0
  51. /package/layers/shader/app/components/Material/{Fresnel.vue → Fresnel.client.vue} +0 -0
  52. /package/layers/shader/app/components/Material/{Gradient.vue → Gradient.client.vue} +0 -0
  53. /package/layers/shader/app/components/Material/{Image.vue → Image.client.vue} +0 -0
  54. /package/layers/shader/app/components/Material/{Node.vue → Node.client.vue} +0 -0
  55. /package/layers/shader/app/components/Material/{Noise.vue → Noise.client.vue} +0 -0
Binary file
Binary file
Binary file
Binary file
@@ -48,16 +48,12 @@
48
48
 
49
49
  /* Tablet: 12 columns */
50
50
  @media (width >= 48rem) {
51
- :root {
52
- --grid-cols: 12;
53
- }
51
+ --grid-cols: 12;
54
52
  }
55
53
 
56
54
  /* Desktop: 18 columns */
57
55
  @media (width >= 80rem) {
58
- :root {
59
- --grid-cols: 18;
60
- }
56
+ --grid-cols: 18;
61
57
  }
62
58
  }
63
59
 
@@ -94,17 +94,27 @@ const getDefaultValue = <T,>(value: T | ResponsiveValue<T> | undefined, defaultV
94
94
  return value as T
95
95
  }
96
96
 
97
+ const getResponsiveValue = <T,>(
98
+ value: T | ResponsiveValue<T> | undefined,
99
+ breakpoint: 'md' | 'lg',
100
+ ): T | undefined => {
101
+ if (value === undefined) return undefined
102
+ if (typeof value === 'object' && value !== null && 'default' in value) {
103
+ return value[breakpoint]
104
+ }
105
+ return undefined
106
+ }
107
+
97
108
  const style = computed(() => {
98
109
  const styles: Record<string, string> = {}
99
110
 
100
- // Grid placement - use computed merged values
101
111
  const colStartVal = getDefaultValue(colStart.value, undefined)
102
112
  const colSpanVal = getDefaultValue(colSpan.value, 1)
103
113
  const rowStartVal = getDefaultValue(rowStart.value, undefined)
104
114
  const rowSpanVal = getDefaultValue(rowSpan.value, 1)
105
115
 
106
116
  if (bleed) {
107
- // Bleed overrides column positioning
117
+ // Bleed is non-responsive — keep as direct inline style
108
118
  if (bleed === 'both') {
109
119
  styles.gridColumn = '1 / -1'
110
120
  } else if (bleed === 'left') {
@@ -112,19 +122,40 @@ const style = computed(() => {
112
122
  } else if (bleed === 'right') {
113
123
  styles.gridColumn = `${colStartVal ?? 'auto'} / -1`
114
124
  }
125
+ styles.gridRow = `${rowStartVal ?? 'auto'} / span ${rowSpanVal}`
115
126
  } else {
116
- styles.gridColumn = `${colStartVal ?? 'auto'} / span ${colSpanVal}`
127
+ // Set CSS custom properties instead of grid-column/grid-row directly.
128
+ // The <style> block below reads these vars and applies them at each breakpoint,
129
+ // which correctly cascades without inline-style specificity conflicts.
130
+ styles['--_cs'] = String(colStartVal ?? 'auto')
131
+ styles['--_ce'] = String(colSpanVal)
132
+ styles['--_rs'] = String(rowStartVal ?? 'auto')
133
+ styles['--_re'] = String(rowSpanVal)
134
+
135
+ const mdColStart = getResponsiveValue(colStart.value, 'md')
136
+ const lgColStart = getResponsiveValue(colStart.value, 'lg')
137
+ const mdColSpan = getResponsiveValue(colSpan.value, 'md')
138
+ const lgColSpan = getResponsiveValue(colSpan.value, 'lg')
139
+ const mdRowStart = getResponsiveValue(rowStart.value, 'md')
140
+ const lgRowStart = getResponsiveValue(rowStart.value, 'lg')
141
+ const mdRowSpan = getResponsiveValue(rowSpan.value, 'md')
142
+ const lgRowSpan = getResponsiveValue(rowSpan.value, 'lg')
143
+
144
+ if (mdColStart !== undefined) styles['--_md-cs'] = String(mdColStart)
145
+ if (lgColStart !== undefined) styles['--_lg-cs'] = String(lgColStart)
146
+ if (mdColSpan !== undefined) styles['--_md-ce'] = String(mdColSpan)
147
+ if (lgColSpan !== undefined) styles['--_lg-ce'] = String(lgColSpan)
148
+ if (mdRowStart !== undefined) styles['--_md-rs'] = String(mdRowStart)
149
+ if (lgRowStart !== undefined) styles['--_lg-rs'] = String(lgRowStart)
150
+ if (mdRowSpan !== undefined) styles['--_md-re'] = String(mdRowSpan)
151
+ if (lgRowSpan !== undefined) styles['--_lg-re'] = String(lgRowSpan)
117
152
  }
118
153
 
119
- styles.gridRow = `${rowStartVal ?? 'auto'} / span ${rowSpanVal}`
120
-
121
- // Content alignment - make this element a grid container to center its children
154
+ // Content alignment
122
155
  if (align || justify) {
123
156
  styles.display = 'grid'
124
157
  styles.width = '100%'
125
158
  styles.height = '100%'
126
- // Use place-items to control how children fill the cell
127
- // align controls vertical, justify controls horizontal
128
159
  styles.placeItems = `${align ?? 'stretch'} ${justify ?? 'stretch'}`
129
160
  }
130
161
 
@@ -135,36 +166,9 @@ const style = computed(() => {
135
166
  return styles
136
167
  })
137
168
 
138
- const getResponsiveClasses = <T,>(
139
- value: T | ResponsiveValue<T> | undefined,
140
- classGenerator: (val: T) => string
141
- ): string[] => {
142
- if (value === undefined) return []
143
- if (typeof value === 'object' && value !== null && 'default' in value) {
144
- const classes: string[] = []
145
- if (value.md !== undefined) classes.push(`md:${classGenerator(value.md)}`)
146
- if (value.lg !== undefined) classes.push(`lg:${classGenerator(value.lg)}`)
147
- return classes
148
- }
149
- return []
150
- }
151
-
152
169
  const classes = computed(() => {
153
- const classList: string[] = ['@container', '@container/item']
154
-
155
- // Responsive column start - use merged values
156
- classList.push(...getResponsiveClasses(colStart.value, (val) => `col-start-${val}`))
170
+ const classList: string[] = ['gi-placed', '@container', '@container/item']
157
171
 
158
- // Responsive column span
159
- classList.push(...getResponsiveClasses(colSpan.value, (val) => `col-span-${val}`))
160
-
161
- // Responsive row start
162
- classList.push(...getResponsiveClasses(rowStart.value, (val) => `row-start-${val}`))
163
-
164
- // Responsive row span
165
- classList.push(...getResponsiveClasses(rowSpan.value, (val) => `row-span-${val}`))
166
-
167
- // Aspect ratio
168
172
  if (aspect) {
169
173
  classList.push(aspectClasses[aspect])
170
174
  }
@@ -178,3 +182,24 @@ const classes = computed(() => {
178
182
  <slot />
179
183
  </component>
180
184
  </template>
185
+
186
+ <style>
187
+ .gi-placed {
188
+ grid-column: var(--_cs, auto) / span var(--_ce, 1);
189
+ grid-row: var(--_rs, auto) / span var(--_re, 1);
190
+ }
191
+
192
+ @media (width >= 48rem) {
193
+ .gi-placed {
194
+ grid-column: var(--_md-cs, var(--_cs, auto)) / span var(--_md-ce, var(--_ce, 1));
195
+ grid-row: var(--_md-rs, var(--_rs, auto)) / span var(--_md-re, var(--_re, 1));
196
+ }
197
+ }
198
+
199
+ @media (width >= 80rem) {
200
+ .gi-placed {
201
+ grid-column: var(--_lg-cs, var(--_md-cs, var(--_cs, auto))) / span var(--_lg-ce, var(--_md-ce, var(--_ce, 1)));
202
+ grid-row: var(--_lg-rs, var(--_md-rs, var(--_rs, auto))) / span var(--_lg-re, var(--_md-re, var(--_re, 1)));
203
+ }
204
+ }
205
+ </style>
Binary file
Binary file
@@ -0,0 +1,51 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck - TSL types
3
+ import { Color } from 'three'
4
+ import { uniform, vec3 } from 'three/tsl'
5
+
6
+ const props = withDefaults(
7
+ defineProps<{
8
+ id?: string
9
+ color?: string
10
+ order?: number
11
+ blend?: 'normal' | 'add' | 'multiply' | 'screen' | 'overlay' | 'mix'
12
+ opacity?: number
13
+ }>(),
14
+ {
15
+ id: 'color',
16
+ color: '#ffffff',
17
+ order: 0,
18
+ blend: 'normal',
19
+ opacity: 1.0,
20
+ }
21
+ )
22
+
23
+ const graph = useShaderGraphContext()
24
+
25
+ // Create uniform once
26
+ const colorValue = new Color(props.color)
27
+ const colorNode = uniform(colorValue)
28
+
29
+ // Build TSL node once (references uniform by pointer)
30
+ const node = vec3(colorNode)
31
+
32
+ // Register in graph
33
+ graph.register(props.id, node, props.order, props.blend, props.opacity)
34
+
35
+ // Watch props to update uniform value (no recompilation)
36
+ watch(
37
+ () => props.color,
38
+ (hex) => {
39
+ colorValue.set(hex)
40
+ colorNode.value = colorValue
41
+ }
42
+ )
43
+
44
+ onUnmounted(() => {
45
+ graph.unregister(props.id)
46
+ })
47
+ </script>
48
+
49
+ <template>
50
+ <slot />
51
+ </template>
@@ -0,0 +1,53 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck - TSL types
3
+ import {
4
+ cameraPosition,
5
+ normalView,
6
+ positionWorld,
7
+ pow,
8
+ sub,
9
+ uniform,
10
+ vec3,
11
+ } from 'three/tsl'
12
+
13
+ const props = withDefaults(
14
+ defineProps<{
15
+ id?: string
16
+ power?: number
17
+ color?: string
18
+ order?: number
19
+ blend?: 'normal' | 'add' | 'multiply' | 'screen' | 'overlay' | 'mix'
20
+ opacity?: number
21
+ }>(),
22
+ {
23
+ id: 'fresnel',
24
+ power: 2.0,
25
+ color: '#ffffff',
26
+ order: 0,
27
+ blend: 'add',
28
+ opacity: 1.0,
29
+ }
30
+ )
31
+
32
+ const graph = useShaderGraphContext()
33
+
34
+ // Create uniforms once
35
+ const uPower = uniform(props.power)
36
+
37
+ // Build fresnel node
38
+ const viewDirection = positionWorld.sub(cameraPosition).normalize()
39
+ const fresnelFactor = pow(sub(1.0, normalView.dot(viewDirection.negate()).abs()), uPower)
40
+ const node = vec3(fresnelFactor, fresnelFactor, fresnelFactor)
41
+
42
+ graph.register(props.id, node, props.order, props.blend, props.opacity)
43
+
44
+ watch(() => props.power, (v) => { uPower.value = v })
45
+
46
+ onUnmounted(() => {
47
+ graph.unregister(props.id)
48
+ })
49
+ </script>
50
+
51
+ <template>
52
+ <slot />
53
+ </template>
@@ -0,0 +1,87 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck - TSL types
3
+ import { add, mul, time, uniform, uv } from 'three/tsl'
4
+ import { cosinePalette } from '#layers/shader/app/shaders/common/palette'
5
+
6
+ const props = withDefaults(
7
+ defineProps<{
8
+ id?: string
9
+ /** Cosine palette type or 'linear' for UV-based gradient */
10
+ type?: 'rainbow' | 'sunset' | 'ocean' | 'fire' | 'ice' | 'neon' | 'pastel' | 'custom'
11
+ speed?: number
12
+ /** Custom brightness for cosine palette [r,g,b] */
13
+ brightness?: [number, number, number]
14
+ /** Custom contrast for cosine palette [r,g,b] */
15
+ contrast?: [number, number, number]
16
+ /** Custom frequency for cosine palette [r,g,b] */
17
+ frequency?: [number, number, number]
18
+ /** Custom phase for cosine palette [r,g,b] */
19
+ phase?: [number, number, number]
20
+ order?: number
21
+ blend?: 'normal' | 'add' | 'multiply' | 'screen' | 'overlay' | 'mix'
22
+ opacity?: number
23
+ }>(),
24
+ {
25
+ id: 'gradient',
26
+ type: 'rainbow',
27
+ speed: 0.1,
28
+ brightness: () => [0.5, 0.5, 0.5],
29
+ contrast: () => [0.5, 0.5, 0.5],
30
+ frequency: () => [1.0, 1.0, 1.0],
31
+ phase: () => [0.0, 0.33, 0.67],
32
+ order: 0,
33
+ blend: 'normal',
34
+ opacity: 1.0,
35
+ }
36
+ )
37
+
38
+ const graph = useShaderGraphContext()
39
+
40
+ const uSpeed = uniform(props.speed)
41
+
42
+ // Palette presets
43
+ const palettePresets: Record<string, [[number, number, number], [number, number, number], [number, number, number], [number, number, number]]> = {
44
+ rainbow: [[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [1.0, 1.0, 1.0], [0.0, 0.33, 0.67]],
45
+ sunset: [[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [1.0, 0.7, 0.4], [0.0, 0.15, 0.2]],
46
+ ocean: [[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [1.0, 1.0, 1.0], [0.3, 0.2, 0.2]],
47
+ fire: [[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [1.0, 0.5, 0.0], [0.0, 0.1, 0.2]],
48
+ ice: [[0.5, 0.5, 0.5], [0.4, 0.4, 0.5], [0.0, 0.1, 0.2], [0.0, 0.0, 0.0]],
49
+ neon: [[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [2.0, 1.0, 0.0], [0.5, 0.2, 0.25]],
50
+ pastel: [[0.8, 0.8, 0.8], [0.2, 0.2, 0.2], [1.0, 1.0, 1.0], [0.0, 0.33, 0.67]],
51
+ }
52
+
53
+ function buildNode() {
54
+ const uvCoord = uv()
55
+ const t = add(uvCoord.x, mul(time, uSpeed))
56
+
57
+ const preset = palettePresets[props.type]
58
+ if (preset) {
59
+ return cosinePalette(t, preset[0], preset[1], preset[2], preset[3])
60
+ }
61
+
62
+ // Custom
63
+ return cosinePalette(t, props.brightness, props.contrast, props.frequency, props.phase)
64
+ }
65
+
66
+ let node = buildNode()
67
+ graph.register(props.id, node, props.order, props.blend, props.opacity)
68
+
69
+ watch(() => props.speed, (v) => { uSpeed.value = v })
70
+
71
+ // Rebuild on type or custom param changes
72
+ watch(
73
+ () => [props.type, props.brightness, props.contrast, props.frequency, props.phase] as const,
74
+ () => {
75
+ node = buildNode()
76
+ graph.update(props.id, node)
77
+ }
78
+ )
79
+
80
+ onUnmounted(() => {
81
+ graph.unregister(props.id)
82
+ })
83
+ </script>
84
+
85
+ <template>
86
+ <slot />
87
+ </template>
@@ -0,0 +1,50 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck - TSL types
3
+ /**
4
+ * Mix node -- combines child nodes registered in a nested shader graph.
5
+ * Children register into this component's own sub-graph, which is then
6
+ * composed and registered as a single node in the parent graph.
7
+ */
8
+ import { vec3 } from 'three/tsl'
9
+
10
+ const props = withDefaults(
11
+ defineProps<{
12
+ id?: string
13
+ order?: number
14
+ blend?: 'normal' | 'add' | 'multiply' | 'screen' | 'overlay' | 'mix'
15
+ opacity?: number
16
+ }>(),
17
+ {
18
+ id: 'mix',
19
+ order: 0,
20
+ blend: 'normal',
21
+ opacity: 1.0,
22
+ }
23
+ )
24
+
25
+ const parentGraph = useShaderGraphContext()
26
+
27
+ // Create a sub-graph for children
28
+ const subGraph = useShaderGraph()
29
+
30
+ // Watch sub-graph and register its composite into parent
31
+ watch(
32
+ subGraph.version,
33
+ () => {
34
+ const node = subGraph.finalNode.value || vec3(0, 0, 0)
35
+ if (parentGraph) {
36
+ // Re-register with updated composite node
37
+ parentGraph.register(props.id, node, props.order, props.blend, props.opacity)
38
+ }
39
+ },
40
+ { immediate: true }
41
+ )
42
+
43
+ onUnmounted(() => {
44
+ parentGraph.unregister(props.id)
45
+ })
46
+ </script>
47
+
48
+ <template>
49
+ <slot />
50
+ </template>
@@ -0,0 +1,101 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck - TSL types
3
+ import { add, mul, time, uniform, uv, vec2, vec3 } from 'three/tsl'
4
+ import {
5
+ simplexNoise2D,
6
+ fbm2D,
7
+ ridgedFbm2d,
8
+ voronoi2D,
9
+ fbm3dSimplex,
10
+ } from '#layers/shader/app/shaders/common/noise'
11
+
12
+ const props = withDefaults(
13
+ defineProps<{
14
+ id?: string
15
+ type?: 'simplex' | 'fbm' | 'voronoi' | 'ridged' | 'fbm3d'
16
+ scale?: number
17
+ speed?: number
18
+ octaves?: number
19
+ order?: number
20
+ blend?: 'normal' | 'add' | 'multiply' | 'screen' | 'overlay' | 'mix'
21
+ opacity?: number
22
+ }>(),
23
+ {
24
+ id: 'noise',
25
+ type: 'simplex',
26
+ scale: 3.0,
27
+ speed: 0.2,
28
+ octaves: 4,
29
+ order: 0,
30
+ blend: 'normal',
31
+ opacity: 1.0,
32
+ }
33
+ )
34
+
35
+ const graph = useShaderGraphContext()
36
+
37
+ // Create uniforms once
38
+ const uScale = uniform(props.scale)
39
+ const uSpeed = uniform(props.speed)
40
+
41
+ // Build TSL node
42
+ function buildNode() {
43
+ const uvCoord = uv()
44
+ const t = mul(time, uSpeed)
45
+ const scaledUV = mul(uvCoord, uScale)
46
+ const animatedUV = add(scaledUV, vec2(t, mul(t, 0.3)))
47
+
48
+ let noiseValue
49
+
50
+ switch (props.type) {
51
+ case 'fbm':
52
+ noiseValue = fbm2D(animatedUV, { octaves: props.octaves, frequency: 1.0 })
53
+ .mul(0.5)
54
+ .add(0.5)
55
+ break
56
+ case 'voronoi': {
57
+ const { distance } = voronoi2D(animatedUV, 1.0)
58
+ noiseValue = distance
59
+ break
60
+ }
61
+ case 'ridged':
62
+ noiseValue = ridgedFbm2d(animatedUV, { octaves: props.octaves, frequency: 1.0 })
63
+ break
64
+ case 'fbm3d':
65
+ noiseValue = fbm3dSimplex(vec3(scaledUV, t), { octaves: props.octaves })
66
+ .mul(0.5)
67
+ .add(0.5)
68
+ break
69
+ case 'simplex':
70
+ default:
71
+ noiseValue = simplexNoise2D(animatedUV).mul(0.5).add(0.5)
72
+ break
73
+ }
74
+
75
+ return vec3(noiseValue, noiseValue, noiseValue)
76
+ }
77
+
78
+ const node = buildNode()
79
+ graph.register(props.id, node, props.order, props.blend, props.opacity)
80
+
81
+ // Watch uniform-driven props (no recompilation)
82
+ watch(() => props.scale, (v) => { uScale.value = v })
83
+ watch(() => props.speed, (v) => { uSpeed.value = v })
84
+
85
+ // Watch topology-changing props (requires graph update)
86
+ watch(
87
+ () => [props.type, props.octaves] as const,
88
+ () => {
89
+ const newNode = buildNode()
90
+ graph.update(props.id, newNode)
91
+ }
92
+ )
93
+
94
+ onUnmounted(() => {
95
+ graph.unregister(props.id)
96
+ })
97
+ </script>
98
+
99
+ <template>
100
+ <slot />
101
+ </template>
@@ -0,0 +1,67 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck - TSL types
3
+ import { uniform } from 'three/tsl'
4
+ import {
5
+ createAmbientUniforms,
6
+ createAuroraColorNode,
7
+ } from '#layers/shader/app/composables/useAmbientMaterials'
8
+
9
+ const props = withDefaults(
10
+ defineProps<{
11
+ speed?: number
12
+ intensity?: number
13
+ mouseInteraction?: boolean
14
+ }>(),
15
+ {
16
+ speed: 1.0,
17
+ intensity: 1.0,
18
+ mouseInteraction: true,
19
+ }
20
+ )
21
+
22
+ const emit = defineEmits<{
23
+ node: [colorNode: any]
24
+ }>()
25
+
26
+ // Create uniforms once
27
+ const uniforms = createAmbientUniforms({
28
+ speed: props.speed,
29
+ intensity: props.intensity,
30
+ mouseInteraction: props.mouseInteraction,
31
+ })
32
+
33
+ // Build the TSL color node (references uniforms by pointer)
34
+ const colorNode = createAuroraColorNode(uniforms)
35
+
36
+ // Wire mouse from runtime if available
37
+ try {
38
+ const runtime = useShaderRuntimeContext()
39
+ watch(
40
+ () => [runtime.mouse.mouseX.value, runtime.mouse.mouseY.value],
41
+ ([mx, my]) => {
42
+ uniforms.mouseX.value = mx
43
+ uniforms.mouseY.value = my
44
+ },
45
+ { immediate: true }
46
+ )
47
+ } catch {
48
+ // No runtime -- mouse can be set externally
49
+ }
50
+
51
+ // Watch props to update uniforms (no recompilation)
52
+ watch(() => props.speed, (v) => { uniforms.speed.value = v })
53
+ watch(() => props.intensity, (v) => { uniforms.intensity.value = v })
54
+ watch(
55
+ () => props.mouseInteraction,
56
+ (v) => { uniforms.mouseStrength.value = v ? 0.5 : 0 }
57
+ )
58
+
59
+ // Emit the node for parent (ShaderHost) to consume
60
+ emit('node', colorNode)
61
+
62
+ defineExpose({ uniforms, colorNode })
63
+ </script>
64
+
65
+ <template>
66
+ <slot />
67
+ </template>
@@ -0,0 +1,61 @@
1
+ <script setup lang="ts">
2
+ // @ts-nocheck - TSL types
3
+ import {
4
+ createAmbientUniforms,
5
+ createFlowColorNode,
6
+ } from '#layers/shader/app/composables/useAmbientMaterials'
7
+
8
+ const props = withDefaults(
9
+ defineProps<{
10
+ speed?: number
11
+ intensity?: number
12
+ mouseInteraction?: boolean
13
+ }>(),
14
+ {
15
+ speed: 1.0,
16
+ intensity: 1.0,
17
+ mouseInteraction: true,
18
+ }
19
+ )
20
+
21
+ const emit = defineEmits<{
22
+ node: [colorNode: any]
23
+ }>()
24
+
25
+ const uniforms = createAmbientUniforms({
26
+ speed: props.speed,
27
+ intensity: props.intensity,
28
+ mouseInteraction: props.mouseInteraction,
29
+ })
30
+
31
+ const colorNode = createFlowColorNode(uniforms)
32
+
33
+ try {
34
+ const runtime = useShaderRuntimeContext()
35
+ watch(
36
+ () => [runtime.mouse.mouseX.value, runtime.mouse.mouseY.value],
37
+ ([mx, my]) => {
38
+ uniforms.mouseX.value = mx
39
+ uniforms.mouseY.value = my
40
+ },
41
+ { immediate: true }
42
+ )
43
+ } catch {
44
+ // No runtime
45
+ }
46
+
47
+ watch(() => props.speed, (v) => { uniforms.speed.value = v })
48
+ watch(() => props.intensity, (v) => { uniforms.intensity.value = v })
49
+ watch(
50
+ () => props.mouseInteraction,
51
+ (v) => { uniforms.mouseStrength.value = v ? 0.5 : 0 }
52
+ )
53
+
54
+ emit('node', colorNode)
55
+
56
+ defineExpose({ uniforms, colorNode })
57
+ </script>
58
+
59
+ <template>
60
+ <slot />
61
+ </template>