@konitif/theme 0.284.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +21 -0
- package/README.md +56 -0
- package/package.json +56 -0
- package/reference/README.md +10 -0
- package/reference/catalog.json +129 -0
- package/reference/diagrams.json +60 -0
- package/src/ambient/SpatialAmbientCanvas.svelte +148 -0
- package/src/ambient/SpatialAmbientParticles.svelte +89 -0
- package/src/ambient/SpatialAmbientRuntime.svelte +306 -0
- package/src/ambient/SpatialProjectionGrid.svelte +252 -0
- package/src/ambient/shaders/noise.glsl +1 -0
- package/src/ambient/shaders/particleField.glsl +1 -0
- package/src/ambient/shaders/spatialAmbient.frag.glsl +1 -0
- package/src/ambient/shaders/spatialAmbient.vert.glsl +1 -0
- package/src/ambient/shaders/volumetricFog.glsl +1 -0
- package/src/ambient/spatialAmbientStore.ts +3 -0
- package/src/ambient/spatialAmbientTypes.ts +11 -0
- package/src/ambient/spatialProjectionGridModel.ts +276 -0
- package/src/ambient/spatialProjectionGridPresets.ts +152 -0
- package/src/ambient/spatialProjectionGridTypes.ts +72 -0
- package/src/ambient/themeToAmbientUniforms.ts +3 -0
- package/src/components/KonitifBadge.svelte +2 -0
- package/src/components/KonitifButton.svelte +2 -0
- package/src/components/KonitifCard.svelte +2 -0
- package/src/components/KonitifGlassSurface.svelte +3 -0
- package/src/components/KonitifIconFrame.svelte +2 -0
- package/src/components/KonitifPanel.svelte +2 -0
- package/src/depth/SpatialDepthLayer.svelte +49 -0
- package/src/depth/SpatialDepthStack.svelte +25 -0
- package/src/depth/spatialDepthTokens.css +82 -0
- package/src/depth/spatialDepthTypes.ts +79 -0
- package/src/focus/FocusPlaneProvider.svelte +43 -0
- package/src/focus/PerceptualSurface.svelte +146 -0
- package/src/focus/focusDepthMap.ts +33 -0
- package/src/focus/perceptualFocusStore.ts +98 -0
- package/src/focus/perceptualFocusTypes.ts +38 -0
- package/src/focus/usePerceptualFocus.ts +18 -0
- package/src/index.ts +22 -0
- package/src/konitifRuntimePhaseTokens.ts +15 -0
- package/src/konitifTheme.ts +2 -0
- package/src/konitifThemeAdapter.ts +13 -0
- package/src/konitifTokens.css +201 -0
- package/src/konitifWorkbenchThemeRuntime.ts +35 -0
- package/src/runtime/RuntimePhaseTintProvider.svelte +28 -0
- package/src/runtime/runtimePhaseIconMap.ts +1 -0
- package/src/runtime/runtimePhaseVisualMap.ts +37 -0
- package/src/runtime/runtimeSpatialReactivity.ts +307 -0
- package/src/runtime/runtimeSpatialStateStore.ts +53 -0
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { onDestroy, onMount } from 'svelte';
|
|
3
|
+
import type { StageAmbientProjection } from '@konitif/workbench';
|
|
4
|
+
import { globalPerceptualFocusStore } from '../focus/perceptualFocusStore';
|
|
5
|
+
import { normalizeKonitifRuntimePhase, type RuntimePhase } from '../konitifRuntimePhaseTokens';
|
|
6
|
+
import {
|
|
7
|
+
createRuntimeSpatialState,
|
|
8
|
+
interpolateRuntimeSpatialState,
|
|
9
|
+
type RuntimeSpatialState
|
|
10
|
+
} from '../runtime/runtimeSpatialReactivity';
|
|
11
|
+
import SpatialAmbientCanvas from './SpatialAmbientCanvas.svelte';
|
|
12
|
+
import SpatialAmbientParticles from './SpatialAmbientParticles.svelte';
|
|
13
|
+
import SpatialProjectionGrid from './SpatialProjectionGrid.svelte';
|
|
14
|
+
import type { AmbientQuality } from './spatialAmbientTypes';
|
|
15
|
+
import type { SpatialProjectionGridConfig } from './spatialProjectionGridTypes';
|
|
16
|
+
|
|
17
|
+
export let phase: RuntimePhase = 'LAUNCH_GATE';
|
|
18
|
+
export let quality: AmbientQuality = 'medium';
|
|
19
|
+
export let reducedMotion = false;
|
|
20
|
+
export let themeMode: 'dark' | 'light' = 'dark';
|
|
21
|
+
export let spatialOverrides: Partial<RuntimeSpatialState> | null = null;
|
|
22
|
+
export let gridConfig: Partial<SpatialProjectionGridConfig> | null = null;
|
|
23
|
+
export let stageAmbient: StageAmbientProjection | null = null;
|
|
24
|
+
|
|
25
|
+
let prefersReducedMotion = false;
|
|
26
|
+
let isDocumentHidden = false;
|
|
27
|
+
let reducedMotionQuery: MediaQueryList | null = null;
|
|
28
|
+
let focusState = globalPerceptualFocusStore.getState();
|
|
29
|
+
let renderedPhase: RuntimePhase | null = null;
|
|
30
|
+
let renderedSpatialState: RuntimeSpatialState | null = null;
|
|
31
|
+
let vectorTransitionTarget: RuntimePhase | null = null;
|
|
32
|
+
let vectorTransitionFrame: number | null = null;
|
|
33
|
+
let vectorTransitionStartedAt = 0;
|
|
34
|
+
|
|
35
|
+
const phaseVectorFadeDuration = 680;
|
|
36
|
+
|
|
37
|
+
$: resolvedPhase = normalizeKonitifRuntimePhase(phase);
|
|
38
|
+
$: effectiveReducedMotion = reducedMotion || prefersReducedMotion || isDocumentHidden;
|
|
39
|
+
$: targetSpatialState = {
|
|
40
|
+
...createRuntimeSpatialState(resolvedPhase, {
|
|
41
|
+
quality,
|
|
42
|
+
reducedMotion: reducedMotion || prefersReducedMotion,
|
|
43
|
+
hidden: isDocumentHidden
|
|
44
|
+
}),
|
|
45
|
+
...(spatialOverrides ?? {}),
|
|
46
|
+
phase: resolvedPhase
|
|
47
|
+
};
|
|
48
|
+
$: activeSpatialState = renderedSpatialState ?? targetSpatialState;
|
|
49
|
+
$: ambientStyle = createAmbientStyle(activeSpatialState);
|
|
50
|
+
$: if (quality !== 'off') {
|
|
51
|
+
syncRuntimeVector(resolvedPhase, targetSpatialState, effectiveReducedMotion);
|
|
52
|
+
} else {
|
|
53
|
+
clearVectorTransition();
|
|
54
|
+
renderedPhase = null;
|
|
55
|
+
renderedSpatialState = null;
|
|
56
|
+
vectorTransitionTarget = null;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
onMount(() => {
|
|
60
|
+
const unsubscribeFocus = globalPerceptualFocusStore.subscribe((state) => {
|
|
61
|
+
focusState = state;
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
if (typeof document !== 'undefined') {
|
|
65
|
+
isDocumentHidden = document.hidden;
|
|
66
|
+
const handleVisibilityChange = (): void => {
|
|
67
|
+
isDocumentHidden = document.hidden;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
document.addEventListener('visibilitychange', handleVisibilityChange);
|
|
71
|
+
|
|
72
|
+
if (typeof window === 'undefined' || !window.matchMedia) {
|
|
73
|
+
return () => {
|
|
74
|
+
document.removeEventListener('visibilitychange', handleVisibilityChange);
|
|
75
|
+
unsubscribeFocus();
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
reducedMotionQuery = window.matchMedia('(prefers-reduced-motion: reduce)');
|
|
80
|
+
prefersReducedMotion = reducedMotionQuery.matches;
|
|
81
|
+
|
|
82
|
+
const handleChange = (event: MediaQueryListEvent): void => {
|
|
83
|
+
prefersReducedMotion = event.matches;
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
reducedMotionQuery.addEventListener('change', handleChange);
|
|
87
|
+
|
|
88
|
+
return () => {
|
|
89
|
+
document.removeEventListener('visibilitychange', handleVisibilityChange);
|
|
90
|
+
reducedMotionQuery?.removeEventListener('change', handleChange);
|
|
91
|
+
unsubscribeFocus();
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return unsubscribeFocus;
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
onDestroy(() => {
|
|
99
|
+
clearVectorTransition();
|
|
100
|
+
reducedMotionQuery = null;
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
function createAmbientStyle(state: RuntimeSpatialState): string {
|
|
104
|
+
const focusPoint = stageAmbient?.focusPoint ?? focusState.focusPoint;
|
|
105
|
+
const focusStrength = stageAmbient
|
|
106
|
+
? Math.max(0.2, 1 - stageAmbient.focusDepth * 0.42)
|
|
107
|
+
: focusState.focusStrength;
|
|
108
|
+
|
|
109
|
+
return [
|
|
110
|
+
`--k-runtime-tint: ${state.tint}`,
|
|
111
|
+
`--k-runtime-tint-rgb: ${state.tintRgb}`,
|
|
112
|
+
`--k-runtime-intensity: ${state.lightIntensity}`,
|
|
113
|
+
`--k-runtime-fog-density: ${state.fogDensity}`,
|
|
114
|
+
`--k-runtime-particle-density: ${state.particleDensity}`,
|
|
115
|
+
`--k-runtime-particle-speed: ${state.particleSpeed}`,
|
|
116
|
+
`--k-runtime-motion-intensity: ${state.motionIntensity}`,
|
|
117
|
+
`--k-runtime-tilt-strength: ${state.tiltStrength}`,
|
|
118
|
+
`--k-runtime-focus-falloff: ${state.focusFalloff}`,
|
|
119
|
+
`--k-runtime-instability: ${state.instability}`,
|
|
120
|
+
`--k-focus-x: ${focusPoint.x}`,
|
|
121
|
+
`--k-focus-y: ${focusPoint.y}`,
|
|
122
|
+
`--k-focus-strength: ${focusStrength}`
|
|
123
|
+
].join('; ');
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function syncRuntimeVector(
|
|
127
|
+
phaseValue: RuntimePhase,
|
|
128
|
+
state: RuntimeSpatialState,
|
|
129
|
+
shouldReduceMotion: boolean
|
|
130
|
+
): void {
|
|
131
|
+
if (typeof window === 'undefined' || shouldReduceMotion || renderedSpatialState === null || renderedPhase === null) {
|
|
132
|
+
clearVectorTransition();
|
|
133
|
+
renderedPhase = phaseValue;
|
|
134
|
+
renderedSpatialState = { ...state };
|
|
135
|
+
vectorTransitionTarget = null;
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (phaseValue === renderedPhase) {
|
|
140
|
+
if (vectorTransitionTarget === null) {
|
|
141
|
+
renderedSpatialState = { ...state };
|
|
142
|
+
}
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (phaseValue === vectorTransitionTarget) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
startVectorTransition(renderedSpatialState, { ...state }, phaseValue);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function startVectorTransition(fromState: RuntimeSpatialState, toState: RuntimeSpatialState, targetPhase: RuntimePhase): void {
|
|
154
|
+
if (typeof window === 'undefined') {
|
|
155
|
+
renderedPhase = targetPhase;
|
|
156
|
+
renderedSpatialState = { ...toState };
|
|
157
|
+
vectorTransitionTarget = null;
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
clearVectorTransition();
|
|
162
|
+
vectorTransitionTarget = targetPhase;
|
|
163
|
+
vectorTransitionStartedAt = window.performance.now();
|
|
164
|
+
|
|
165
|
+
const step = (now: number): void => {
|
|
166
|
+
const progress = (now - vectorTransitionStartedAt) / phaseVectorFadeDuration;
|
|
167
|
+
renderedSpatialState = interpolateRuntimeSpatialState(fromState, toState, progress);
|
|
168
|
+
|
|
169
|
+
if (progress < 1) {
|
|
170
|
+
vectorTransitionFrame = window.requestAnimationFrame(step);
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
renderedPhase = targetPhase;
|
|
175
|
+
renderedSpatialState = { ...toState };
|
|
176
|
+
vectorTransitionTarget = null;
|
|
177
|
+
vectorTransitionFrame = null;
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
vectorTransitionFrame = window.requestAnimationFrame(step);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function clearVectorTransition(): void {
|
|
184
|
+
if (typeof window !== 'undefined' && vectorTransitionFrame !== null) {
|
|
185
|
+
window.cancelAnimationFrame(vectorTransitionFrame);
|
|
186
|
+
}
|
|
187
|
+
vectorTransitionFrame = null;
|
|
188
|
+
}
|
|
189
|
+
</script>
|
|
190
|
+
|
|
191
|
+
{#if quality !== 'off' && activeSpatialState}
|
|
192
|
+
<div
|
|
193
|
+
class="konitif-ambient workbench-theme-ambient"
|
|
194
|
+
data-workbench-theme-ambient
|
|
195
|
+
data-workbench-theme-family="konitif"
|
|
196
|
+
data-quality={quality}
|
|
197
|
+
data-theme-mode={themeMode}
|
|
198
|
+
aria-hidden="true"
|
|
199
|
+
>
|
|
200
|
+
<div
|
|
201
|
+
class="konitif-ambient__phase-layer"
|
|
202
|
+
style={ambientStyle}
|
|
203
|
+
data-phase={activeSpatialState.phase}
|
|
204
|
+
data-reduced-motion={effectiveReducedMotion}
|
|
205
|
+
>
|
|
206
|
+
<SpatialAmbientCanvas
|
|
207
|
+
phase={activeSpatialState.phase}
|
|
208
|
+
{quality}
|
|
209
|
+
reducedMotion={effectiveReducedMotion}
|
|
210
|
+
spatialState={activeSpatialState}
|
|
211
|
+
{themeMode}
|
|
212
|
+
/>
|
|
213
|
+
<SpatialProjectionGrid
|
|
214
|
+
phase={activeSpatialState.phase}
|
|
215
|
+
{quality}
|
|
216
|
+
reducedMotion={effectiveReducedMotion}
|
|
217
|
+
config={gridConfig}
|
|
218
|
+
{themeMode}
|
|
219
|
+
/>
|
|
220
|
+
<SpatialAmbientParticles
|
|
221
|
+
phase={activeSpatialState.phase}
|
|
222
|
+
{quality}
|
|
223
|
+
reducedMotion={effectiveReducedMotion}
|
|
224
|
+
spatialState={activeSpatialState}
|
|
225
|
+
{themeMode}
|
|
226
|
+
/>
|
|
227
|
+
<div class="konitif-frustum-vignette"></div>
|
|
228
|
+
<div class="konitif-corner-tilt"></div>
|
|
229
|
+
</div>
|
|
230
|
+
</div>
|
|
231
|
+
{/if}
|
|
232
|
+
|
|
233
|
+
<style>
|
|
234
|
+
.konitif-ambient {
|
|
235
|
+
position: absolute;
|
|
236
|
+
inset: 0;
|
|
237
|
+
z-index: 0;
|
|
238
|
+
overflow: hidden;
|
|
239
|
+
pointer-events: none;
|
|
240
|
+
background: var(--k-bg-root);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
.konitif-ambient__phase-layer {
|
|
244
|
+
position: absolute;
|
|
245
|
+
inset: 0;
|
|
246
|
+
overflow: hidden;
|
|
247
|
+
pointer-events: none;
|
|
248
|
+
background:
|
|
249
|
+
radial-gradient(circle at 50% 35%, rgba(var(--k-runtime-tint-rgb), calc(var(--k-runtime-intensity) * 0.34)), transparent 34%),
|
|
250
|
+
radial-gradient(circle at 12% 18%, var(--k-frustum-light), transparent 28%),
|
|
251
|
+
linear-gradient(180deg, var(--k-bg-space, var(--k-bg-root)), var(--k-bg-space-deep, var(--k-bg-root)));
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
.konitif-ambient[data-theme-mode='light'] .konitif-ambient__phase-layer {
|
|
255
|
+
background:
|
|
256
|
+
radial-gradient(circle at 68% 16%, var(--k-frustum-light-core), transparent 18%),
|
|
257
|
+
radial-gradient(circle at 50% 44%, rgba(var(--k-runtime-tint-rgb), calc(var(--k-runtime-intensity) * 0.085)), transparent 30%),
|
|
258
|
+
radial-gradient(ellipse at 50% 56%, var(--k-frustum-fog), transparent 44%),
|
|
259
|
+
linear-gradient(135deg, rgba(255, 246, 230, 0.26) 0%, transparent 32%),
|
|
260
|
+
linear-gradient(315deg, var(--k-frustum-shadow) 0%, transparent 30%),
|
|
261
|
+
linear-gradient(180deg, var(--k-bg-space), var(--k-bg-space-deep));
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
.konitif-frustum-vignette,
|
|
265
|
+
.konitif-corner-tilt {
|
|
266
|
+
position: absolute;
|
|
267
|
+
inset: 0;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
.konitif-frustum-vignette {
|
|
271
|
+
background:
|
|
272
|
+
radial-gradient(circle at 50% 42%, transparent 0%, transparent 42%, rgba(0, 0, 0, calc(0.18 + var(--k-runtime-fog-density) * 0.18)) 100%),
|
|
273
|
+
linear-gradient(115deg, transparent 0%, rgba(var(--k-runtime-tint-rgb), 0.035) 48%, transparent 68%);
|
|
274
|
+
mix-blend-mode: multiply;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
.konitif-ambient[data-theme-mode='light'] .konitif-frustum-vignette {
|
|
278
|
+
background:
|
|
279
|
+
radial-gradient(circle at 50% 42%, transparent 0%, transparent 54%, rgba(110, 135, 165, calc(0.08 + var(--k-runtime-fog-density) * 0.08)) 100%),
|
|
280
|
+
linear-gradient(35deg, rgba(110, 135, 165, 0.08) 0%, transparent 38%),
|
|
281
|
+
linear-gradient(120deg, transparent 0%, rgba(var(--k-runtime-tint-rgb), 0.026) 48%, transparent 72%);
|
|
282
|
+
mix-blend-mode: multiply;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
.konitif-corner-tilt {
|
|
286
|
+
inset: -8%;
|
|
287
|
+
background:
|
|
288
|
+
linear-gradient(135deg, transparent 0%, rgba(255, 255, 255, 0.035) 48%, transparent 64%),
|
|
289
|
+
linear-gradient(315deg, transparent 0%, rgba(var(--k-runtime-tint-rgb), 0.045) 52%, transparent 72%);
|
|
290
|
+
opacity: 0.72;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
.konitif-ambient[data-theme-mode='light'] .konitif-corner-tilt {
|
|
294
|
+
background:
|
|
295
|
+
linear-gradient(135deg, rgba(255, 238, 205, 0.14) 0%, transparent 38%),
|
|
296
|
+
linear-gradient(315deg, rgba(110, 135, 165, 0.1) 0%, transparent 34%);
|
|
297
|
+
opacity: 0.58;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
@media (prefers-reduced-motion: reduce) {
|
|
301
|
+
.konitif-corner-tilt {
|
|
302
|
+
animation: none;
|
|
303
|
+
transform: none;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
</style>
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
<script context="module" lang="ts">
|
|
2
|
+
let spatialProjectionGridInstanceSequence = 0;
|
|
3
|
+
</script>
|
|
4
|
+
|
|
5
|
+
<script lang="ts">
|
|
6
|
+
import type { RuntimePhase } from '../konitifRuntimePhaseTokens';
|
|
7
|
+
import type { AmbientQuality } from './spatialAmbientTypes';
|
|
8
|
+
import {
|
|
9
|
+
createSpatialProjectionGridGeometry,
|
|
10
|
+
resolveSpatialProjectionGridConfig
|
|
11
|
+
} from './spatialProjectionGridModel';
|
|
12
|
+
import type { SpatialProjectionGridConfig } from './spatialProjectionGridTypes';
|
|
13
|
+
|
|
14
|
+
export let config: Partial<SpatialProjectionGridConfig> | null = null;
|
|
15
|
+
export let phase: RuntimePhase | string = 'LAUNCH_GATE';
|
|
16
|
+
export let quality: AmbientQuality = 'medium';
|
|
17
|
+
export let reducedMotion = false;
|
|
18
|
+
export let animated = true;
|
|
19
|
+
export let themeMode: 'dark' | 'light' = 'dark';
|
|
20
|
+
|
|
21
|
+
const instanceId = `konitif-grid-${++spatialProjectionGridInstanceSequence}`;
|
|
22
|
+
|
|
23
|
+
$: resolvedConfig = resolveSpatialProjectionGridConfig({ phase, quality, reducedMotion, config });
|
|
24
|
+
$: renderConfig = resolveRenderConfig(resolvedConfig, themeMode);
|
|
25
|
+
$: geometry = createSpatialProjectionGridGeometry(renderConfig);
|
|
26
|
+
$: shouldRender = quality !== 'off' && renderConfig.enabled;
|
|
27
|
+
$: shouldAnimate = animated && !reducedMotion && renderConfig.animationSpeed > 0;
|
|
28
|
+
$: gridStyle = [
|
|
29
|
+
`--k-space-grid-major-opacity: ${renderConfig.majorLineOpacity}`,
|
|
30
|
+
`--k-space-grid-minor-opacity: ${renderConfig.minorLineOpacity}`,
|
|
31
|
+
`--k-space-grid-node-opacity: ${renderConfig.nodeOpacity}`,
|
|
32
|
+
`--k-space-grid-origin-opacity: ${renderConfig.originNodeOpacity}`,
|
|
33
|
+
`--k-space-grid-glow: ${renderConfig.glowIntensity}`,
|
|
34
|
+
`--k-space-grid-fog-opacity: ${renderConfig.fogIntensity}`,
|
|
35
|
+
`--k-space-grid-drift-duration: ${Math.max(18, 54 - renderConfig.animationSpeed * 34)}s`
|
|
36
|
+
].join('; ');
|
|
37
|
+
|
|
38
|
+
function resolveRenderConfig(
|
|
39
|
+
currentConfig: SpatialProjectionGridConfig,
|
|
40
|
+
mode: 'dark' | 'light'
|
|
41
|
+
): SpatialProjectionGridConfig {
|
|
42
|
+
if (mode !== 'light') {
|
|
43
|
+
return currentConfig;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
...currentConfig,
|
|
48
|
+
majorLineOpacity: clamp01(currentConfig.majorLineOpacity * 1.14 + 0.025),
|
|
49
|
+
minorLineOpacity: clamp01(currentConfig.minorLineOpacity * 0.56),
|
|
50
|
+
nodeOpacity: clamp01(currentConfig.nodeOpacity * 1.08),
|
|
51
|
+
originNodeOpacity: clamp01(currentConfig.originNodeOpacity * 1.12),
|
|
52
|
+
glowIntensity: clamp01(currentConfig.glowIntensity * 0.58),
|
|
53
|
+
fogIntensity: clamp01(currentConfig.fogIntensity * 0.72),
|
|
54
|
+
animationSpeed: clamp01(currentConfig.animationSpeed * 0.72)
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function clamp01(value: number): number {
|
|
59
|
+
return Math.min(1, Math.max(0, value));
|
|
60
|
+
}
|
|
61
|
+
</script>
|
|
62
|
+
|
|
63
|
+
{#if shouldRender}
|
|
64
|
+
<div
|
|
65
|
+
class:spatial-grid--animated={shouldAnimate}
|
|
66
|
+
class="spatial-grid"
|
|
67
|
+
data-quality={quality}
|
|
68
|
+
data-phase={phase}
|
|
69
|
+
data-theme-mode={themeMode}
|
|
70
|
+
style={gridStyle}
|
|
71
|
+
aria-hidden="true"
|
|
72
|
+
>
|
|
73
|
+
<div class="spatial-grid__fog"></div>
|
|
74
|
+
<svg
|
|
75
|
+
class="spatial-grid__svg"
|
|
76
|
+
viewBox={`0 0 ${geometry.width} ${geometry.height}`}
|
|
77
|
+
preserveAspectRatio="none"
|
|
78
|
+
focusable="false"
|
|
79
|
+
role="presentation"
|
|
80
|
+
>
|
|
81
|
+
<defs>
|
|
82
|
+
<filter id={`${instanceId}-node-glow`} x="-160%" y="-160%" width="420%" height="420%">
|
|
83
|
+
<feGaussianBlur stdDeviation="4" result="blur" />
|
|
84
|
+
<feMerge>
|
|
85
|
+
<feMergeNode in="blur" />
|
|
86
|
+
<feMergeNode in="SourceGraphic" />
|
|
87
|
+
</feMerge>
|
|
88
|
+
</filter>
|
|
89
|
+
<linearGradient id={`${instanceId}-depth-fade`} x1="0" x2="0" y1="1" y2="0">
|
|
90
|
+
<stop offset="0%" stop-color="white" stop-opacity="1" />
|
|
91
|
+
<stop offset="54%" stop-color="white" stop-opacity="0.52" />
|
|
92
|
+
<stop offset="100%" stop-color="white" stop-opacity="0" />
|
|
93
|
+
</linearGradient>
|
|
94
|
+
<radialGradient id={`${instanceId}-lateral-fade`} cx="50%" cy="76%" r="72%">
|
|
95
|
+
<stop offset="0%" stop-color="white" stop-opacity="1" />
|
|
96
|
+
<stop offset="58%" stop-color="white" stop-opacity="0.74" />
|
|
97
|
+
<stop offset="100%" stop-color="white" stop-opacity="0" />
|
|
98
|
+
</radialGradient>
|
|
99
|
+
<mask id={`${instanceId}-mask`}>
|
|
100
|
+
<rect width={geometry.width} height={geometry.height} fill={`url(#${instanceId}-depth-fade)`} />
|
|
101
|
+
<rect width={geometry.width} height={geometry.height} fill={`url(#${instanceId}-lateral-fade)`} opacity="0.82" />
|
|
102
|
+
</mask>
|
|
103
|
+
</defs>
|
|
104
|
+
|
|
105
|
+
<g class="spatial-grid__layer" mask={`url(#${instanceId}-mask)`}>
|
|
106
|
+
{#each geometry.lines as line (line.id)}
|
|
107
|
+
<line
|
|
108
|
+
class={`spatial-grid__line spatial-grid__line--${line.kind}`}
|
|
109
|
+
x1={line.x1}
|
|
110
|
+
y1={line.y1}
|
|
111
|
+
x2={line.x2}
|
|
112
|
+
y2={line.y2}
|
|
113
|
+
opacity={line.opacity}
|
|
114
|
+
/>
|
|
115
|
+
{/each}
|
|
116
|
+
|
|
117
|
+
{#each geometry.nodes as node (node.id)}
|
|
118
|
+
<circle
|
|
119
|
+
class:spatial-grid__node--origin={node.origin}
|
|
120
|
+
class="spatial-grid__node"
|
|
121
|
+
cx={node.x}
|
|
122
|
+
cy={node.y}
|
|
123
|
+
r={node.radius}
|
|
124
|
+
opacity={node.opacity}
|
|
125
|
+
filter={`url(#${instanceId}-node-glow)`}
|
|
126
|
+
/>
|
|
127
|
+
{/each}
|
|
128
|
+
</g>
|
|
129
|
+
</svg>
|
|
130
|
+
</div>
|
|
131
|
+
{/if}
|
|
132
|
+
|
|
133
|
+
<style>
|
|
134
|
+
.spatial-grid {
|
|
135
|
+
position: absolute;
|
|
136
|
+
inset: 0;
|
|
137
|
+
overflow: hidden;
|
|
138
|
+
pointer-events: none;
|
|
139
|
+
opacity: var(--k-space-grid-opacity, 0.92);
|
|
140
|
+
filter: blur(var(--k-space-grid-blur, 0px));
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
.spatial-grid::after {
|
|
144
|
+
position: absolute;
|
|
145
|
+
inset: 0;
|
|
146
|
+
content: '';
|
|
147
|
+
pointer-events: none;
|
|
148
|
+
opacity: 0;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
.spatial-grid__fog,
|
|
152
|
+
.spatial-grid__svg {
|
|
153
|
+
position: absolute;
|
|
154
|
+
inset: 0;
|
|
155
|
+
width: 100%;
|
|
156
|
+
height: 100%;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
.spatial-grid__fog {
|
|
160
|
+
background:
|
|
161
|
+
radial-gradient(ellipse at 50% 45%, var(--k-space-grid-horizon), transparent 28%),
|
|
162
|
+
radial-gradient(ellipse at 50% 72%, var(--k-space-grid-fog), transparent 44%);
|
|
163
|
+
opacity: var(--k-space-grid-fog-opacity, 0.32);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.spatial-grid[data-theme-mode='light'] .spatial-grid__fog {
|
|
167
|
+
background:
|
|
168
|
+
radial-gradient(ellipse at 72% 18%, rgba(255, 238, 205, 0.2), transparent 24%),
|
|
169
|
+
radial-gradient(ellipse at 50% 48%, var(--k-space-grid-horizon), transparent 28%),
|
|
170
|
+
radial-gradient(ellipse at 50% 72%, var(--k-space-grid-fog), transparent 48%);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.spatial-grid__svg {
|
|
174
|
+
overflow: visible;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.spatial-grid__layer {
|
|
178
|
+
transform-origin: 50% 82%;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.spatial-grid--animated .spatial-grid__layer {
|
|
182
|
+
animation: konitif-grid-drift var(--k-space-grid-drift-duration, 42s) ease-in-out infinite alternate;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
.spatial-grid__line {
|
|
186
|
+
vector-effect: non-scaling-stroke;
|
|
187
|
+
stroke-linecap: round;
|
|
188
|
+
mix-blend-mode: screen;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
.spatial-grid[data-theme-mode='light'] .spatial-grid__line {
|
|
192
|
+
mix-blend-mode: multiply;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
.spatial-grid__line--axis {
|
|
196
|
+
stroke: var(--k-space-grid-axis);
|
|
197
|
+
stroke-width: 1.25;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
.spatial-grid__line--major {
|
|
201
|
+
stroke: var(--k-space-grid-major);
|
|
202
|
+
stroke-width: 0.9;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
.spatial-grid__line--minor {
|
|
206
|
+
stroke: var(--k-space-grid-minor);
|
|
207
|
+
stroke-width: 0.56;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
.spatial-grid__line--tertiary {
|
|
211
|
+
stroke: var(--k-space-grid-tertiary);
|
|
212
|
+
stroke-width: 0.42;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
.spatial-grid__node {
|
|
216
|
+
fill: var(--k-space-grid-node);
|
|
217
|
+
mix-blend-mode: screen;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
.spatial-grid[data-theme-mode='light'] .spatial-grid__node {
|
|
221
|
+
mix-blend-mode: normal;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
.spatial-grid__node--origin {
|
|
225
|
+
fill: var(--k-space-grid-origin);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
.spatial-grid[data-theme-mode='light']::after {
|
|
229
|
+
background:
|
|
230
|
+
radial-gradient(circle at 50% 82%, rgba(75, 135, 190, 0.08), transparent 22%),
|
|
231
|
+
linear-gradient(35deg, rgba(110, 135, 165, 0.12) 0%, transparent 34%),
|
|
232
|
+
linear-gradient(160deg, rgba(255, 238, 205, 0.12) 0%, transparent 28%);
|
|
233
|
+
mix-blend-mode: multiply;
|
|
234
|
+
opacity: 1;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
@keyframes konitif-grid-drift {
|
|
238
|
+
from {
|
|
239
|
+
transform: translate3d(0, 3px, 0);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
to {
|
|
243
|
+
transform: translate3d(0, -5px, 0);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
@media (prefers-reduced-motion: reduce) {
|
|
248
|
+
.spatial-grid--animated .spatial-grid__layer {
|
|
249
|
+
animation: none;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
</style>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
float hash(vec2 p){return fract(sin(dot(p,vec2(127.1,311.7)))*43758.5453123);}float noise(vec2 p){vec2 i=floor(p),f=fract(p);float a=hash(i),b=hash(i+vec2(1.,0.)),c=hash(i+vec2(0.,1.)),d=hash(i+vec2(1.,1.));vec2 u=f*f*(3.-2.*f);return mix(a,b,u.x)+(c-a)*u.y*(1.-u.x)+(d-b)*u.x*u.y;}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
float particleField(vec2 uv,float time){float v=0.0;for(int i=0;i<8;i++){vec2 p=fract(uv*float(i+3)+time*.01*float(i+1));v+=smoothstep(.995,1.0,1.0-length(p-.5));}return v;}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
precision mediump float;varying vec2 vUv;uniform float uTime;uniform vec3 uFogColor;uniform vec3 uLightColor;uniform float uIntensity;#include "noise.glsl" void main(){vec2 p=vUv-.5;float r=length(p);float beam=smoothstep(.42,0.,abs(p.x))*smoothstep(.55,.05,p.y+.15);float n=noise(vUv*8.+uTime*.03);vec3 col=mix(uFogColor,uLightColor,beam*.55+n*.08)*uIntensity*(1.-r*.8);gl_FragColor=vec4(col,max(0.,.42-r*.55));}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
attribute vec2 position;varying vec2 vUv;void main(){vUv=position*.5+.5;gl_Position=vec4(position,0.,1.);}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
float volumetricFog(vec2 uv,float depth){float center=1.0-length(uv-0.5);return smoothstep(0.0,1.0,center)*depth;}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { RuntimePhase } from '../konitifRuntimePhaseTokens';
|
|
2
|
+
|
|
3
|
+
export type AmbientQuality = 'off' | 'low' | 'medium' | 'high';
|
|
4
|
+
|
|
5
|
+
export type SpatialAmbientConfig = {
|
|
6
|
+
phase: RuntimePhase;
|
|
7
|
+
quality: AmbientQuality;
|
|
8
|
+
reducedMotion: boolean;
|
|
9
|
+
focusX: number;
|
|
10
|
+
focusY: number;
|
|
11
|
+
};
|