shaders 2.5.122 → 2.5.124

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 (135) hide show
  1. package/dist/core/{FloatingParticles-DKoG78j0.js → FloatingParticles-LMsFTJKp.js} +122 -7
  2. package/dist/core/ReflectivePlane-UIT4xlmn.js +230 -0
  3. package/dist/core/{VideoTexture-D9XxE1Hw.js → VideoTexture-ClutlOqj.js} +1 -1
  4. package/dist/core/{WebcamTexture-9Td8qQWm.js → WebcamTexture-D4e06ajM.js} +1 -1
  5. package/dist/core/index.js +42 -41
  6. package/dist/core/registry.js +42 -41
  7. package/dist/core/{shaderRegistry-BoqhBfun.js → shaderRegistry-DZDkRCt8.js} +79 -77
  8. package/dist/core/shaderRegistry.d.ts.map +1 -1
  9. package/dist/core/shaders/FloatingParticles/index.d.ts +1 -1
  10. package/dist/core/shaders/FloatingParticles/index.d.ts.map +1 -1
  11. package/dist/core/shaders/FloatingParticles/index.js +1 -1
  12. package/dist/core/shaders/ReflectivePlane/index.d.ts +46 -0
  13. package/dist/core/shaders/ReflectivePlane/index.d.ts.map +1 -0
  14. package/dist/core/shaders/ReflectivePlane/index.js +6 -0
  15. package/dist/core/shaders/Ring/index.js +1 -1
  16. package/dist/core/shaders/Ripples/index.js +1 -1
  17. package/dist/core/shaders/RoundedRect/index.js +1 -1
  18. package/dist/core/shaders/Saturation/index.js +1 -1
  19. package/dist/core/shaders/Sharpness/index.js +1 -1
  20. package/dist/core/shaders/Shatter/index.js +1 -1
  21. package/dist/core/shaders/SimplexNoise/index.js +1 -1
  22. package/dist/core/shaders/SineWave/index.js +1 -1
  23. package/dist/core/shaders/Smoke/index.js +1 -1
  24. package/dist/core/shaders/SmokeFill/index.js +1 -1
  25. package/dist/core/shaders/Solarize/index.js +1 -1
  26. package/dist/core/shaders/SolidColor/index.js +1 -1
  27. package/dist/core/shaders/Spherize/index.js +1 -1
  28. package/dist/core/shaders/Spiral/index.js +1 -1
  29. package/dist/core/shaders/Star/index.js +1 -1
  30. package/dist/core/shaders/Strands/index.js +1 -1
  31. package/dist/core/shaders/Stretch/index.js +1 -1
  32. package/dist/core/shaders/Stripes/index.js +1 -1
  33. package/dist/core/shaders/StudioBackground/index.js +1 -1
  34. package/dist/core/shaders/SunBurst/index.js +1 -1
  35. package/dist/core/shaders/Swirl/index.js +1 -1
  36. package/dist/core/shaders/TiltShift/index.js +1 -1
  37. package/dist/core/shaders/Tint/index.js +1 -1
  38. package/dist/core/shaders/Trapezoid/index.js +1 -1
  39. package/dist/core/shaders/Tritone/index.js +1 -1
  40. package/dist/core/shaders/Truchet/index.js +1 -1
  41. package/dist/core/shaders/Twirl/index.js +1 -1
  42. package/dist/core/shaders/VHS/index.js +1 -1
  43. package/dist/core/shaders/Vesica/index.js +1 -1
  44. package/dist/core/shaders/Vibrance/index.js +1 -1
  45. package/dist/core/shaders/VideoTexture/index.js +2 -2
  46. package/dist/core/shaders/Vignette/index.js +1 -1
  47. package/dist/core/shaders/Voronoi/index.js +1 -1
  48. package/dist/core/shaders/WaveDistortion/index.js +1 -1
  49. package/dist/core/shaders/Weave/index.js +1 -1
  50. package/dist/core/shaders/WebcamTexture/index.js +2 -2
  51. package/dist/core/shaders/WorleyNoise/index.js +1 -1
  52. package/dist/core/shaders/ZoomBlur/index.js +1 -1
  53. package/dist/js/createShader.js +1 -1
  54. package/dist/js/utils/generatePresetCode.d.ts.map +1 -1
  55. package/dist/js/utils/generatePresetCode.js +12 -1
  56. package/dist/react/Preview.js +1 -0
  57. package/dist/react/ReflectivePlane.js +217 -0
  58. package/dist/react/Shader.js +1 -1
  59. package/dist/react/bundle.js +207 -207
  60. package/dist/react/components/ReflectivePlane.d.ts +36 -0
  61. package/dist/react/components/ReflectivePlane.d.ts.map +1 -0
  62. package/dist/react/engine/Preview.d.ts.map +1 -1
  63. package/dist/react/index.d.ts +1 -0
  64. package/dist/react/index.d.ts.map +1 -1
  65. package/dist/react/index.js +2 -1
  66. package/dist/react/utils/generatePresetCode.d.ts.map +1 -1
  67. package/dist/react/utils/generatePresetCode.js +12 -1
  68. package/dist/registry.js +219 -2
  69. package/dist/solid/components/ReflectivePlane.d.ts +33 -0
  70. package/dist/solid/components/ReflectivePlane.d.ts.map +1 -0
  71. package/dist/solid/components/ReflectivePlane.js +228 -0
  72. package/dist/solid/engine/Preview.d.ts.map +1 -1
  73. package/dist/solid/engine/Preview.js +158 -156
  74. package/dist/solid/engine/Shader.js +1 -1
  75. package/dist/solid/index.d.ts +1 -0
  76. package/dist/solid/index.d.ts.map +1 -1
  77. package/dist/solid/index.js +82 -80
  78. package/dist/solid/utils/generatePresetCode.d.ts.map +1 -1
  79. package/dist/solid/utils/generatePresetCode.js +12 -1
  80. package/dist/svelte/components/ReflectivePlane.svelte.d.ts +23 -0
  81. package/dist/svelte/index.d.ts +1 -0
  82. package/dist/svelte/index.js +740 -540
  83. package/dist/svelte/source/components/ReflectivePlane.svelte +329 -0
  84. package/dist/svelte/source/engine/Preview.svelte +2 -0
  85. package/dist/svelte/source/index.js +1 -0
  86. package/dist/svelte/utils/generatePresetCode.js +12 -1
  87. package/dist/vue/Preview.vue_vue_type_script_setup_true_lang.js +2 -0
  88. package/dist/vue/ReflectivePlane.js +3 -0
  89. package/dist/vue/ReflectivePlane.vue_vue_type_script_setup_true_lang.js +218 -0
  90. package/dist/vue/Shader.vue_vue_type_script_setup_true_lang.js +1 -1
  91. package/dist/vue/components/ReflectivePlane.vue.d.ts +58 -0
  92. package/dist/vue/components/ReflectivePlane.vue.d.ts.map +1 -0
  93. package/dist/vue/index.d.ts +1 -0
  94. package/dist/vue/index.d.ts.map +1 -1
  95. package/dist/vue/index.js +2 -1
  96. package/dist/vue/utils/generatePresetCode.d.ts.map +1 -1
  97. package/dist/vue/utils/generatePresetCode.js +12 -1
  98. package/package.json +9 -1
  99. /package/dist/core/{Ring-CtnDtTY8.js → Ring-UT__kmzY.js} +0 -0
  100. /package/dist/core/{Ripples-B4H0VoZb.js → Ripples-CWVLSUP0.js} +0 -0
  101. /package/dist/core/{RoundedRect-tnt7Jr5b.js → RoundedRect-BPWHTT1j.js} +0 -0
  102. /package/dist/core/{Saturation-6FlxHXSi.js → Saturation-DFOp2yD9.js} +0 -0
  103. /package/dist/core/{Sharpness-C4cJlBuh.js → Sharpness-C-IEswPL.js} +0 -0
  104. /package/dist/core/{Shatter-CnkycTRD.js → Shatter-CUYQp-qy.js} +0 -0
  105. /package/dist/core/{SimplexNoise-BnRaoxON.js → SimplexNoise-LAxWw8fJ.js} +0 -0
  106. /package/dist/core/{SineWave-CZ4Fanvr.js → SineWave-CEQWxC9Q.js} +0 -0
  107. /package/dist/core/{Smoke-CXPjGG-b.js → Smoke-DO4yylWk.js} +0 -0
  108. /package/dist/core/{SmokeFill-DzEtYeKN.js → SmokeFill-Dm0sZS5F.js} +0 -0
  109. /package/dist/core/{Solarize-CynVlxjT.js → Solarize-mE7LU1li.js} +0 -0
  110. /package/dist/core/{SolidColor-dCAOGC_P.js → SolidColor-BljkSdvg.js} +0 -0
  111. /package/dist/core/{Spherize-C77QGVWj.js → Spherize-DARagREe.js} +0 -0
  112. /package/dist/core/{Spiral-eN65wa6O.js → Spiral-CumsIpkp.js} +0 -0
  113. /package/dist/core/{Star-0Flymgm9.js → Star-8fAlzR9L.js} +0 -0
  114. /package/dist/core/{Strands-DnWJDGiO.js → Strands-BB4RIsFz.js} +0 -0
  115. /package/dist/core/{Stretch-B5XGF1bF.js → Stretch-3S2atBkJ.js} +0 -0
  116. /package/dist/core/{Stripes-CNXJpFyr.js → Stripes-BGFVSZIt.js} +0 -0
  117. /package/dist/core/{StudioBackground-DtiE2mCf.js → StudioBackground-BtJ6b1Ki.js} +0 -0
  118. /package/dist/core/{SunBurst-D9X1-buZ.js → SunBurst-BJRFFYhs.js} +0 -0
  119. /package/dist/core/{Swirl-BV6pN94G.js → Swirl-KA9cEnLI.js} +0 -0
  120. /package/dist/core/{TiltShift-r4qzPb2k.js → TiltShift-DtQ3dRL-.js} +0 -0
  121. /package/dist/core/{Tint-CJ8FQdzA.js → Tint-W_EvzN1-.js} +0 -0
  122. /package/dist/core/{Trapezoid-JmybJMUr.js → Trapezoid-cQzS6-bh.js} +0 -0
  123. /package/dist/core/{Tritone-D_QvxjGc.js → Tritone-B3hI2nAi.js} +0 -0
  124. /package/dist/core/{Truchet-BJeZS_JQ.js → Truchet-s9PmowCP.js} +0 -0
  125. /package/dist/core/{Twirl-8ayqS0n8.js → Twirl-UDDXGkFl.js} +0 -0
  126. /package/dist/core/{VHS-Gbec95K_.js → VHS-DW1H7Wuy.js} +0 -0
  127. /package/dist/core/{Vesica-D7iqgpJg.js → Vesica-ChQBYWuw.js} +0 -0
  128. /package/dist/core/{Vibrance-COKHmh8r.js → Vibrance-DUj7hwzE.js} +0 -0
  129. /package/dist/core/{Vignette-Y_2yono-.js → Vignette-F9yxi-UM.js} +0 -0
  130. /package/dist/core/{Voronoi-DQ_f6k5D.js → Voronoi-D8HHP_WR.js} +0 -0
  131. /package/dist/core/{WaveDistortion-R5FfwKQN.js → WaveDistortion-CDIc5Uyk.js} +0 -0
  132. /package/dist/core/{Weave-DJ4s3Gwc.js → Weave-ou5shgl3.js} +0 -0
  133. /package/dist/core/{WorleyNoise-CWytDfGH.js → WorleyNoise-Uf6IPm7A.js} +0 -0
  134. /package/dist/core/{ZoomBlur-DWFQVFMK.js → ZoomBlur-DJ-RNKHM.js} +0 -0
  135. /package/dist/core/{browser-BamVDhaZ.js → browser-NUM-x2tw.js} +0 -0
@@ -0,0 +1,329 @@
1
+ <script lang="ts">
2
+ import { getContext, setContext, onMount, onDestroy } from 'svelte';
3
+ import {
4
+ createUniformsMap,
5
+ type UniformsMap,
6
+ type BlendMode,
7
+ type NodeMetadata,
8
+ type PropConfig,
9
+ type MaskConfig,
10
+ type PropDriver,
11
+ type TransformConfig
12
+ } from '../../../core/index.js';
13
+ import {setColorSpaceMode} from '../../../core/utilities/transformations/index.js';
14
+
15
+ // @ts-ignore - this import is replaced at build time
16
+ import { componentDefinition, type ComponentProps } from '../../../core/shaders/ReflectivePlane/index.js';
17
+
18
+ // Warn once per page load if this is an experimental component
19
+ let _experimentalWarnedOnce = false;
20
+ if ((componentDefinition as any).experimental && !_experimentalWarnedOnce) {
21
+ _experimentalWarnedOnce = true;
22
+ const _e = (componentDefinition as any).experimental;
23
+ console.info(`%c⚠ [Shaders] ${componentDefinition.name} is experimental: ${_e.message}`, 'color: #f59e0b; font-weight: bold');
24
+ }
25
+
26
+ /**
27
+ * Define component props including blend mode, opacity, visibility, masking, and transformation
28
+ */
29
+ interface ExtendedComponentProps extends Partial<ComponentProps> {
30
+ height?: ComponentProps['height'] | PropDriver;
31
+ distance?: ComponentProps['distance'] | PropDriver;
32
+ falloff?: ComponentProps['falloff'] | PropDriver;
33
+ blur?: ComponentProps['blur'] | PropDriver;
34
+ blendMode?: BlendMode;
35
+ opacity?: number;
36
+ visible?: boolean;
37
+ id?: string;
38
+ maskSource?: string;
39
+ maskType?: string;
40
+ renderOrder?: number;
41
+ transform?: Partial<TransformConfig>;
42
+ children?: import('svelte').Snippet;
43
+ }
44
+
45
+ function isPropDriver(value: unknown): value is PropDriver {
46
+ return typeof value === 'object' && value !== null && 'type' in value &&
47
+ ((value as any).type === 'map' || (value as any).type === 'mouse' || (value as any).type === 'mouse-position' || (value as any).type === 'auto-animate');
48
+ }
49
+
50
+ /**
51
+ * Default transform configuration (optimized for zero overhead)
52
+ */
53
+ const DEFAULT_TRANSFORM: TransformConfig = {
54
+ offsetX: 0,
55
+ offsetY: 0,
56
+ rotation: 0,
57
+ scale: 1,
58
+ anchorX: 0.5,
59
+ anchorY: 0.5,
60
+ edges: 'transparent'
61
+ };
62
+
63
+ // Define the component props and their default values from the shader definition
64
+ const componentDefaults = {
65
+ blendMode: 'normal' as BlendMode,
66
+ visible: true,
67
+ // opacity intentionally has no default - handled by renderer
68
+ // transform intentionally has no default - handled by effectiveTransform
69
+ ...Object.entries(componentDefinition.props).reduce(
70
+ (acc, [key, config]) => {
71
+ acc[key] = (config as unknown as PropConfig<typeof config>).default;
72
+ return acc;
73
+ },
74
+ {} as Record<string, any>
75
+ )
76
+ };
77
+
78
+ // Declare props using Svelte 5's syntax
79
+ const props: ExtendedComponentProps = $props();
80
+
81
+ // Apply defaults manually since Svelte 5 doesn't have withDefaults equivalent
82
+ // Use $derived so the metadata $effect re-runs when any of these change at runtime
83
+ const blendMode = $derived(props.blendMode ?? componentDefaults.blendMode);
84
+ const opacity = $derived(props.opacity); // No default - handled by renderer
85
+ const visible = $derived(props.visible ?? componentDefaults.visible); // Default to true
86
+ const id = $derived(props.id);
87
+ const maskSource = $derived(props.maskSource);
88
+ const maskType = $derived(props.maskType);
89
+ const renderOrder = $derived(props.renderOrder);
90
+ const { children } = props;
91
+
92
+ // Collect PropDriver values from shader props into the maps metadata structure
93
+ const mapsFromProps = $derived.by(() => {
94
+ const maps: Record<string, PropDriver> = {};
95
+ for (const key of Object.keys(componentDefinition.props)) {
96
+ const val = (props as any)[key];
97
+ if (isPropDriver(val)) maps[key] = val as PropDriver;
98
+ }
99
+ return Object.keys(maps).length > 0 ? maps : undefined;
100
+ });
101
+
102
+ /**
103
+ * Computed transform that merges user-provided values with defaults
104
+ */
105
+ const effectiveTransform = $derived({
106
+ ...DEFAULT_TRANSFORM,
107
+ ...props.transform
108
+ });
109
+
110
+ /**
111
+ * FIRST: Get the parent ID from context BEFORE setting our own context
112
+ */
113
+ const parentId = getContext<string>('shaderParentId');
114
+ if (parentId === undefined) {
115
+ throw new Error('Shader components must be used inside an <Shader> component or another shader component');
116
+ }
117
+
118
+ /**
119
+ * Use the provided ID or generate a unique identifier for this component instance
120
+ */
121
+ const instanceId = (id ? id.replace(/[^a-zA-Z0-9_]/g, '_') : null) || Math.random().toString(36).substring(2, 10);
122
+
123
+ /**
124
+ * THEN: Provide our unique identifier to child components
125
+ */
126
+ setContext('shaderParentId', instanceId);
127
+
128
+ /**
129
+ * Creates a non-reactive object containing only props that differ from defaults
130
+ * This optimization prevents unnecessary GPU uniform updates for unchanged values
131
+ * Special props like blendMode and opacity are handled separately
132
+ */
133
+ const shaderReadyProps = $derived.by(() => {
134
+ let baseProps = { ...componentDefaults };
135
+
136
+ // Only include props that differ from defaults (excluding special props and PropDrivers)
137
+ for (const key in props) {
138
+ if (key !== 'blendMode' && key !== 'opacity' && key !== 'visible' &&
139
+ key !== 'id' && key !== 'maskSource' && key !== 'maskType' && key !== 'renderOrder' &&
140
+ key !== 'transform' && key !== 'children') {
141
+ const propValue = (props as any)[key];
142
+ if (isPropDriver(propValue)) continue; // PropDrivers go to metadata.maps, not uniforms
143
+ const defaultValue = (componentDefaults as any)[key];
144
+ if (propValue !== undefined && propValue !== defaultValue) {
145
+ (baseProps as any)[key] = propValue;
146
+ }
147
+ }
148
+ }
149
+ return baseProps;
150
+ });
151
+
152
+ /**
153
+ * Get the color space from the root Shader component.
154
+ * Used to set the global color space mode before creating uniforms.
155
+ */
156
+ const shaderColorSpace = getContext<() => 'p3-linear' | 'srgb'>('shaderColorSpace');
157
+
158
+ /**
159
+ * Creates the GPU uniform values map using only the changed props
160
+ * Set the global color space mode before creating uniforms so colors are transformed correctly
161
+ * Note: Intentionally captures initial value - props are immutable after initialization
162
+ */
163
+ if (shaderColorSpace) {
164
+ setColorSpaceMode(shaderColorSpace());
165
+ }
166
+ // svelte-ignore state_referenced_locally
167
+ const uniforms: UniformsMap = createUniformsMap(componentDefinition, shaderReadyProps, instanceId);
168
+
169
+ /**
170
+ * Get the node registration function from parent context
171
+ */
172
+ const parentRegister = getContext<(id: string, fragmentNodeFunc: any, parentId: string | null, metadata: NodeMetadata | null, uniforms: UniformsMap | null, componentDefinition: any, domCanvas?: HTMLCanvasElement) => void>('shaderNodeRegister');
173
+ if (parentRegister === undefined) {
174
+ throw new Error('Shader components must be used inside an <Shader> component or another shader component');
175
+ }
176
+
177
+ /**
178
+ * Get the uniform update function from parent context
179
+ */
180
+ const parentUniformUpdate = getContext<(nodeId: string, uniformName: string, value: any) => void>('shaderUniformUpdate');
181
+ if (parentUniformUpdate === undefined) {
182
+ throw new Error('Shader components require shaderUniformUpdate from parent');
183
+ }
184
+
185
+ /**
186
+ * Get the metadata update function from parent context
187
+ */
188
+ const parentMetadataUpdate = getContext<(nodeId: string, metadata: NodeMetadata) => void>('shaderMetadataUpdate');
189
+ if (parentMetadataUpdate === undefined) {
190
+ throw new Error('Shader components require shaderMetadataUpdate from parent');
191
+ }
192
+
193
+ // capturesDOM — canvas layoutsubtree portal for DOMTexture-style shaders
194
+ const isCapturesDOM = !!(componentDefinition as any).capturesDOM;
195
+ let captureCanvas: HTMLCanvasElement | undefined;
196
+ let captureW = $state(typeof window !== 'undefined' ? Math.round(window.innerWidth * Math.min(window.devicePixelRatio, 2)) : 0);
197
+ let captureH = $state(typeof window !== 'undefined' ? Math.round(window.innerHeight * Math.min(window.devicePixelRatio, 2)) : 0);
198
+
199
+ function teleportToBody(node: HTMLElement) {
200
+ document.body.appendChild(node);
201
+ return { destroy() { node.remove(); } };
202
+ }
203
+
204
+ if (isCapturesDOM) {
205
+ const onWinResize = () => {
206
+ const d = Math.min(window.devicePixelRatio, 2);
207
+ captureW = Math.round(window.innerWidth * d);
208
+ captureH = Math.round(window.innerHeight * d);
209
+ };
210
+ onMount(() => { window.addEventListener('resize', onWinResize); });
211
+ onDestroy(() => { window.removeEventListener('resize', onWinResize); });
212
+ }
213
+
214
+ // DOM marker ref for determining render order from template position
215
+ let orderMarker: HTMLSpanElement;
216
+
217
+ // Stores the DOM-detected render order
218
+ let detectedRenderOrder: number | undefined = undefined;
219
+
220
+ // Flag to track when component is registered
221
+ let isRegistered = $state(false);
222
+
223
+ // Setup uniform watchers with registration guard
224
+ Object.entries(uniforms).forEach(([propName, { uniform, transform }]) => {
225
+ $effect(() => {
226
+ // Only run after component is registered
227
+ if (!isRegistered) return;
228
+
229
+ if (uniform && uniform.value !== undefined) {
230
+ const newValue = (props as any)[propName];
231
+ if (newValue !== undefined && !isPropDriver(newValue)) {
232
+ // Send raw value - renderer will handle transformation
233
+ // PropDriver values go to metadata.maps, not uniforms
234
+ parentUniformUpdate(instanceId, propName, newValue);
235
+ }
236
+ }
237
+ });
238
+ });
239
+
240
+ // Watch blend mode, opacity, visibility, masking, transformations, and prop maps changes
241
+ $effect(() => {
242
+ // Only run after component is registered
243
+ if (!isRegistered) return;
244
+
245
+ const metadata: NodeMetadata = {
246
+ blendMode,
247
+ opacity,
248
+ visible: visible === false ? false : true,
249
+ id,
250
+ mask: maskSource ? {
251
+ source: maskSource,
252
+ type: (maskType || 'alpha') as MaskConfig['type']
253
+ } : undefined,
254
+ maps: mapsFromProps,
255
+ renderOrder: renderOrder ?? detectedRenderOrder,
256
+ transform: effectiveTransform
257
+ };
258
+ parentMetadataUpdate(instanceId, metadata);
259
+ });
260
+
261
+ // Register this component after mount to ensure parent is ready
262
+ onMount(() => {
263
+ // Register this component with safety check
264
+ if (componentDefinition && typeof componentDefinition.fragmentNode === 'function') {
265
+ parentRegister(
266
+ instanceId,
267
+ componentDefinition.fragmentNode,
268
+ parentId,
269
+ {
270
+ blendMode,
271
+ opacity,
272
+ visible: visible !== false ? true : false,
273
+ id,
274
+ mask: maskSource ? {
275
+ source: maskSource,
276
+ type: (maskType || 'alpha') as MaskConfig['type']
277
+ } as MaskConfig : undefined,
278
+ maps: mapsFromProps,
279
+ renderOrder: renderOrder ?? detectedRenderOrder,
280
+ transform: effectiveTransform
281
+ },
282
+ uniforms,
283
+ componentDefinition,
284
+ isCapturesDOM ? captureCanvas : undefined
285
+ );
286
+
287
+ // Set flag to enable effects after successful registration
288
+ isRegistered = true;
289
+
290
+ // Detect DOM position for correct render ordering
291
+ if (renderOrder === undefined && orderMarker) {
292
+ const parent = orderMarker.parentElement;
293
+ if (parent) {
294
+ const siblings = parent.querySelectorAll(':scope > [data-shader-id]');
295
+ const position = Array.from(siblings).indexOf(orderMarker);
296
+ if (position >= 0) {
297
+ detectedRenderOrder = position;
298
+ parentMetadataUpdate(instanceId, { renderOrder: position } as NodeMetadata);
299
+ }
300
+ }
301
+ }
302
+ } else {
303
+ console.error('componentDefinition.fragmentNode is not a function:', {
304
+ componentDefinition,
305
+ fragmentNode: componentDefinition?.fragmentNode,
306
+ type: typeof componentDefinition?.fragmentNode
307
+ });
308
+ }
309
+ });
310
+
311
+ // Clean up node from registry when component is unmounted
312
+ onDestroy(() => {
313
+ isRegistered = false;
314
+ parentRegister(instanceId, null, null, null, null);
315
+ });
316
+ </script>
317
+
318
+ <span bind:this={orderMarker} style="display:contents" data-shader-id={instanceId}>
319
+ {#if !isCapturesDOM}
320
+ {@render children?.()}
321
+ {/if}
322
+ </span>
323
+ {#if isCapturesDOM}
324
+ <canvas use:teleportToBody bind:this={captureCanvas} layoutsubtree
325
+ width={captureW} height={captureH}
326
+ style="position:fixed;inset:0;width:100vw;height:100vh;z-index:-9999">
327
+ {@render children?.()}
328
+ </canvas>
329
+ {/if}
@@ -83,6 +83,7 @@ import Posterize from '../components/Posterize.svelte'
83
83
  import ProgressiveBlur from '../components/ProgressiveBlur.svelte'
84
84
  import RadialGradient from '../components/RadialGradient.svelte'
85
85
  import RectangularCoordinates from '../components/RectangularCoordinates.svelte'
86
+ import ReflectivePlane from '../components/ReflectivePlane.svelte'
86
87
  import Ring from '../components/Ring.svelte'
87
88
  import Ripples from '../components/Ripples.svelte'
88
89
  import RoundedRect from '../components/RoundedRect.svelte'
@@ -203,6 +204,7 @@ const componentMap: Record<string, any> = {
203
204
  ProgressiveBlur,
204
205
  RadialGradient,
205
206
  RectangularCoordinates,
207
+ ReflectivePlane,
206
208
  Ring,
207
209
  Ripples,
208
210
  RoundedRect,
@@ -76,6 +76,7 @@ export { default as Posterize } from './components/Posterize.svelte';
76
76
  export { default as ProgressiveBlur } from './components/ProgressiveBlur.svelte';
77
77
  export { default as RadialGradient } from './components/RadialGradient.svelte';
78
78
  export { default as RectangularCoordinates } from './components/RectangularCoordinates.svelte';
79
+ export { default as ReflectivePlane } from './components/ReflectivePlane.svelte';
79
80
  export { default as Ring } from './components/Ring.svelte';
80
81
  export { default as Ripples } from './components/Ripples.svelte';
81
82
  export { default as RoundedRect } from './components/RoundedRect.svelte';
@@ -473,7 +473,7 @@ var shaderMetadata = {
473
473
  "randomness": .25,
474
474
  "speed": .25,
475
475
  "angle": 90,
476
- "particleSize": 1,
476
+ "particleSize": 2,
477
477
  "particleSoftness": 0,
478
478
  "twinkle": .5,
479
479
  "count": 5,
@@ -977,6 +977,16 @@ var shaderMetadata = {
977
977
  "intensity": 1,
978
978
  "edges": "transparent"
979
979
  },
980
+ "ReflectivePlane": {
981
+ "opacity": 1,
982
+ "blendMode": "normal",
983
+ "height": .7,
984
+ "distance": .5,
985
+ "falloff": .5,
986
+ "blur": 3,
987
+ "blurDistance": .3,
988
+ "edges": "stretch"
989
+ },
980
990
  "Ring": {
981
991
  "opacity": 1,
982
992
  "blendMode": "normal",
@@ -1652,6 +1662,7 @@ const availableComponents = [
1652
1662
  "ProgressiveBlur",
1653
1663
  "RadialGradient",
1654
1664
  "RectangularCoordinates",
1665
+ "ReflectivePlane",
1655
1666
  "Ring",
1656
1667
  "Ripples",
1657
1668
  "RoundedRect",
@@ -76,6 +76,7 @@ import Posterize_default from "./Posterize.js";
76
76
  import ProgressiveBlur_default from "./ProgressiveBlur.js";
77
77
  import RadialGradient_default from "./RadialGradient.js";
78
78
  import RectangularCoordinates_default from "./RectangularCoordinates.js";
79
+ import ReflectivePlane_default from "./ReflectivePlane.js";
79
80
  import Ring_default from "./Ring.js";
80
81
  import Ripples_default from "./Ripples.js";
81
82
  import RoundedRect_default from "./RoundedRect.js";
@@ -249,6 +250,7 @@ var Preview_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ define
249
250
  ProgressiveBlur: ProgressiveBlur_default,
250
251
  RadialGradient: RadialGradient_default,
251
252
  RectangularCoordinates: RectangularCoordinates_default,
253
+ ReflectivePlane: ReflectivePlane_default,
252
254
  Ring: Ring_default,
253
255
  Ripples: Ripples_default,
254
256
  RoundedRect: RoundedRect_default,
@@ -0,0 +1,3 @@
1
+ import ReflectivePlane_vue_vue_type_script_setup_true_lang_default from "./ReflectivePlane.vue_vue_type_script_setup_true_lang.js";
2
+ var ReflectivePlane_default = ReflectivePlane_vue_vue_type_script_setup_true_lang_default;
3
+ export { ReflectivePlane_default as default };
@@ -0,0 +1,218 @@
1
+ import { Fragment, Teleport, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, defineComponent, effectScope, inject, mergeDefaults, mergeProps, onBeforeUnmount, onMounted, openBlock, provide, ref, renderSlot, toValue, unref, useId, watch } from "vue";
2
+ import { createUniformsMap } from "../core/index.js";
3
+ import { setColorSpaceMode } from "../core/utilities/transformations/index.js";
4
+ import { componentDefinition } from "../core/shaders/ReflectivePlane/index.js";
5
+ var _hoisted_1 = ["data-shader-id"];
6
+ var _hoisted_2 = ["width", "height"];
7
+ var ReflectivePlane_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
8
+ __name: "ReflectivePlane",
9
+ props: /* @__PURE__ */ mergeDefaults({
10
+ height: {},
11
+ distance: {},
12
+ falloff: {},
13
+ blur: {},
14
+ blendMode: {},
15
+ opacity: {},
16
+ visible: { type: Boolean },
17
+ id: {},
18
+ maskSource: {},
19
+ maskType: {},
20
+ renderOrder: {},
21
+ transform: {},
22
+ blurDistance: {},
23
+ edges: {}
24
+ }, {
25
+ blendMode: "normal",
26
+ visible: true,
27
+ ...Object.entries(componentDefinition.props).reduce((acc, [key, config]) => {
28
+ acc[key] = config.default;
29
+ return acc;
30
+ }, {})
31
+ }),
32
+ setup(__props) {
33
+ let _experimentalWarnedOnce = false;
34
+ if (componentDefinition.experimental && !_experimentalWarnedOnce) {
35
+ _experimentalWarnedOnce = true;
36
+ const _e = componentDefinition.experimental;
37
+ console.info(`%c⚠ [Shaders] ${componentDefinition.name} is experimental: ${_e.message}`, "color: #f59e0b; font-weight: bold");
38
+ }
39
+ function isPropDriver(value) {
40
+ return typeof value === "object" && value !== null && "type" in value && (value.type === "map" || value.type === "mouse" || value.type === "mouse-position" || value.type === "auto-animate");
41
+ }
42
+ const props = __props;
43
+ const instanceId = (props.id ? props.id.replace(/[^a-zA-Z0-9_]/g, "_") : null) || useId().replace(/[^a-zA-Z0-9_]/g, "");
44
+ provide("shaderParentId", instanceId);
45
+ const DEFAULT_TRANSFORM = {
46
+ offsetX: 0,
47
+ offsetY: 0,
48
+ rotation: 0,
49
+ scale: 1,
50
+ anchorX: .5,
51
+ anchorY: .5,
52
+ edges: "transparent"
53
+ };
54
+ const effectiveTransform = computed(() => ({
55
+ ...DEFAULT_TRANSFORM,
56
+ ...props.transform
57
+ }));
58
+ const shaderReadyProps = computed(() => {
59
+ let baseProps = { ...Object.entries(componentDefinition.props).reduce((acc, [key, config]) => {
60
+ acc[key] = config.default;
61
+ return acc;
62
+ }, {}) };
63
+ for (const key in props) if (key !== "blendMode" && key !== "opacity" && key !== "visible" && key !== "id" && key !== "maskSource" && key !== "maskType" && key !== "renderOrder" && key !== "transform") {
64
+ const val = toValue(props[key]);
65
+ if (isPropDriver(val)) continue;
66
+ if (val !== Object.entries(componentDefinition.props).reduce((acc, [key$1, config]) => {
67
+ acc[key$1] = config.default;
68
+ return acc;
69
+ }, {})[key]) baseProps[key] = val;
70
+ }
71
+ return baseProps;
72
+ });
73
+ const mapsFromProps = computed(() => {
74
+ const maps = {};
75
+ for (const key of Object.keys(componentDefinition.props)) {
76
+ const val = props[key];
77
+ if (isPropDriver(val)) maps[key] = val;
78
+ }
79
+ return Object.keys(maps).length > 0 ? maps : void 0;
80
+ });
81
+ const shaderColorSpace = inject("shaderColorSpace");
82
+ if (shaderColorSpace) setColorSpaceMode(shaderColorSpace.value);
83
+ const uniforms = createUniformsMap(componentDefinition, shaderReadyProps.value, instanceId);
84
+ const parentId = inject("shaderParentId");
85
+ if (parentId === void 0) throw new Error("Shader components must be used inside an <Shader> component or another shader component");
86
+ const parentRegister = inject("shaderNodeRegister");
87
+ if (parentRegister === void 0) throw new Error("Shader components must be used inside an <Shader> component or another shader component");
88
+ const parentUniformUpdate = inject("shaderUniformUpdate");
89
+ if (parentUniformUpdate === void 0) throw new Error("Shader components require shaderUniformUpdate from parent");
90
+ const parentMetadataUpdate = inject("shaderMetadataUpdate");
91
+ if (parentMetadataUpdate === void 0) throw new Error("Shader components require shaderMetadataUpdate from parent");
92
+ const rendererResetSignal = inject("shaderRendererResetSignal");
93
+ const orderMarker = ref(null);
94
+ const isCapturesDOM = !!componentDefinition.capturesDOM;
95
+ const captureCanvas = ref(null);
96
+ const captureW = ref(typeof window !== "undefined" ? Math.round(window.innerWidth * Math.min(window.devicePixelRatio, 2)) : 0);
97
+ const captureH = ref(typeof window !== "undefined" ? Math.round(window.innerHeight * Math.min(window.devicePixelRatio, 2)) : 0);
98
+ const captureStyle = {
99
+ position: "fixed",
100
+ inset: "0",
101
+ width: "100vw",
102
+ height: "100vh",
103
+ zIndex: "-9999"
104
+ };
105
+ if (isCapturesDOM) {
106
+ const onWinResize = () => {
107
+ const d = Math.min(window.devicePixelRatio, 2);
108
+ captureW.value = Math.round(window.innerWidth * d);
109
+ captureH.value = Math.round(window.innerHeight * d);
110
+ };
111
+ onMounted(() => {
112
+ const d = Math.min(window.devicePixelRatio, 2);
113
+ captureW.value = Math.round(window.innerWidth * d);
114
+ captureH.value = Math.round(window.innerHeight * d);
115
+ window.addEventListener("resize", onWinResize);
116
+ });
117
+ onBeforeUnmount(() => {
118
+ window.removeEventListener("resize", onWinResize);
119
+ });
120
+ }
121
+ let detectedRenderOrder = void 0;
122
+ const registerWithRenderer = () => {
123
+ parentRegister(instanceId, componentDefinition.fragmentNode, parentId, {
124
+ blendMode: props.blendMode,
125
+ opacity: props.opacity,
126
+ visible: props.visible === false ? false : true,
127
+ id: props.id,
128
+ mask: props.maskSource ? {
129
+ source: props.maskSource,
130
+ type: props.maskType || "alpha"
131
+ } : void 0,
132
+ maps: mapsFromProps.value,
133
+ renderOrder: props.renderOrder ?? detectedRenderOrder,
134
+ transform: effectiveTransform.value
135
+ }, uniforms, componentDefinition, isCapturesDOM ? captureCanvas.value ?? void 0 : void 0);
136
+ };
137
+ onMounted(() => {
138
+ if (props.renderOrder === void 0 && orderMarker.value) {
139
+ const parent = orderMarker.value.parentElement;
140
+ if (parent) {
141
+ const siblings = parent.querySelectorAll(":scope > [data-shader-id]");
142
+ const position = Array.from(siblings).indexOf(orderMarker.value);
143
+ if (position >= 0) {
144
+ detectedRenderOrder = position;
145
+ parentMetadataUpdate(instanceId, { renderOrder: position });
146
+ }
147
+ }
148
+ }
149
+ });
150
+ const setupUniformWatchers = () => {
151
+ const scope = effectScope();
152
+ scope.run(() => {
153
+ Object.entries(uniforms).forEach(([propName, { uniform, transform }]) => {
154
+ watch(() => props[propName], (newValue) => {
155
+ if (uniform && uniform.value !== void 0 && !isPropDriver(newValue)) parentUniformUpdate(instanceId, propName, newValue);
156
+ }, { deep: true });
157
+ });
158
+ watch(() => [
159
+ props.blendMode,
160
+ props.opacity,
161
+ props.visible,
162
+ props.id,
163
+ props.maskSource,
164
+ props.maskType,
165
+ props.renderOrder,
166
+ props.transform,
167
+ mapsFromProps.value
168
+ ], ([blendMode, opacity, visible]) => {
169
+ parentMetadataUpdate(instanceId, {
170
+ blendMode,
171
+ opacity,
172
+ visible: visible === false ? false : true,
173
+ id: props.id,
174
+ mask: props.maskSource ? {
175
+ source: props.maskSource,
176
+ type: props.maskType || "alpha"
177
+ } : void 0,
178
+ maps: mapsFromProps.value,
179
+ renderOrder: props.renderOrder ?? detectedRenderOrder,
180
+ transform: effectiveTransform.value
181
+ });
182
+ }, { deep: true });
183
+ if (rendererResetSignal) watch(() => rendererResetSignal.value, (newValue) => {
184
+ if (newValue > 0) registerWithRenderer();
185
+ }, { immediate: true });
186
+ });
187
+ onBeforeUnmount(() => {
188
+ scope.stop();
189
+ });
190
+ };
191
+ if (isCapturesDOM) onMounted(() => {
192
+ setupUniformWatchers();
193
+ });
194
+ else setupUniformWatchers();
195
+ onBeforeUnmount(() => {
196
+ parentRegister(instanceId, null, null, null, null, null);
197
+ });
198
+ return (_ctx, _cache) => {
199
+ return openBlock(), createElementBlock(Fragment, null, [createElementVNode("span", {
200
+ ref_key: "orderMarker",
201
+ ref: orderMarker,
202
+ style: { "display": "contents" },
203
+ "data-shader-id": unref(instanceId)
204
+ }, [!isCapturesDOM ? renderSlot(_ctx.$slots, "default", { key: 0 }) : createCommentVNode("", true)], 8, _hoisted_1), isCapturesDOM ? (openBlock(), createBlock(Teleport, {
205
+ key: 0,
206
+ to: "body"
207
+ }, [createElementVNode("canvas", mergeProps({
208
+ ref_key: "captureCanvas",
209
+ ref: captureCanvas
210
+ }, { "layoutsubtree": "" }, {
211
+ width: captureW.value,
212
+ height: captureH.value,
213
+ style: captureStyle
214
+ }), [renderSlot(_ctx.$slots, "default")], 16, _hoisted_2)])) : createCommentVNode("", true)], 64);
215
+ };
216
+ }
217
+ });
218
+ export { ReflectivePlane_vue_vue_type_script_setup_true_lang_default as default };
@@ -60,7 +60,7 @@ var Shader_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineC
60
60
  const startTelemetryWhenReady = () => {
61
61
  const checkRendering = () => {
62
62
  if (rendererInstance.value.getPerformanceStats().fps > 0) {
63
- telemetryCollector = startTelemetry(rendererInstance.value, "2.5.122", props.disableTelemetry, props.isPreview);
63
+ telemetryCollector = startTelemetry(rendererInstance.value, "2.5.124", props.disableTelemetry, props.isPreview);
64
64
  if (telemetryCollector) telemetryCollector.start();
65
65
  telemetryStartTimeout = null;
66
66
  } else telemetryStartTimeout = setTimeout(checkRendering, 500);