@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
package/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Licence — @konitif/theme
|
|
2
|
+
|
|
3
|
+
SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
|
4
|
+
|
|
5
|
+
The original KONITIF / Workbench code in this v0.x package is made available
|
|
6
|
+
under the PolyForm Noncommercial License 1.0.0:
|
|
7
|
+
https://polyformproject.org/licenses/noncommercial/1.0.0
|
|
8
|
+
|
|
9
|
+
This notice incorporates the standard terms by reference; it is not a modified
|
|
10
|
+
version of the licence. This is source-available software, not OSI open source.
|
|
11
|
+
Third-party components retain their own licences and notices.
|
|
12
|
+
|
|
13
|
+
Uses outside the standard licence's permitted purposes require a separate
|
|
14
|
+
written licence. A public repository or npm download grants no additional
|
|
15
|
+
commercial rights. Any free professional authorization must be explicit,
|
|
16
|
+
nominative and limited to the agreed products; none is granted by this notice.
|
|
17
|
+
|
|
18
|
+
The KONITIF name, logo and official identity belong to Maxime Mouflard.
|
|
19
|
+
Descriptive reference is permitted. No third-party version may claim to be
|
|
20
|
+
official, certified or approved without authorization. This trademark notice
|
|
21
|
+
is separate from the software licence and does not amend its terms.
|
package/README.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# @konitif/theme
|
|
2
|
+
|
|
3
|
+
Theme tokens, spatial ambience and perceptual focus projections for compatible
|
|
4
|
+
KONITIF Workbench hosts.
|
|
5
|
+
|
|
6
|
+
## Installation
|
|
7
|
+
|
|
8
|
+
```sh
|
|
9
|
+
npm install @konitif/theme
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## What it provides
|
|
13
|
+
|
|
14
|
+
- Authored light and dark theme tokens.
|
|
15
|
+
- Svelte surfaces for ambient depth, focus and spatial presentation.
|
|
16
|
+
- Deterministic mappings from runtime phases to visual states.
|
|
17
|
+
- Explicit CSS entry points for base and depth tokens.
|
|
18
|
+
|
|
19
|
+
## Authority boundary
|
|
20
|
+
|
|
21
|
+
This package owns the KONITIF visual identity and its local projection state.
|
|
22
|
+
The host owns workspace state, runtime phases and semantic selection. Applying
|
|
23
|
+
or animating a theme never changes those authorities.
|
|
24
|
+
|
|
25
|
+
## Quick start
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
import {
|
|
29
|
+
applyKonitifTheme,
|
|
30
|
+
konitifWorkbenchThemeRuntime
|
|
31
|
+
} from '@konitif/theme';
|
|
32
|
+
import '@konitif/theme/styles.css';
|
|
33
|
+
import '@konitif/theme/depth/styles.css';
|
|
34
|
+
|
|
35
|
+
applyKonitifTheme('konitif-dark');
|
|
36
|
+
export const themeRuntime = konitifWorkbenchThemeRuntime;
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Public entry points
|
|
40
|
+
|
|
41
|
+
| Entry | Purpose |
|
|
42
|
+
| --- | --- |
|
|
43
|
+
| `@konitif/theme` | Theme identity, visual mappings and Svelte projection components. |
|
|
44
|
+
| `@konitif/theme/styles.css` | Base KONITIF design tokens. |
|
|
45
|
+
| `@konitif/theme/depth/styles.css` | Spatial depth tokens and layer styles. |
|
|
46
|
+
|
|
47
|
+
## Reference
|
|
48
|
+
|
|
49
|
+
See [`reference/`](reference/) for the machine-readable capability catalog and
|
|
50
|
+
authority diagram. These artifacts describe the package and do not configure a
|
|
51
|
+
host.
|
|
52
|
+
|
|
53
|
+
## License
|
|
54
|
+
|
|
55
|
+
Source-available under [PolyForm Noncommercial 1.0.0](LICENSE.md), not OSI open
|
|
56
|
+
source. Commercial use requires separate written authorization.
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@konitif/theme",
|
|
3
|
+
"license": "PolyForm-Noncommercial-1.0.0",
|
|
4
|
+
"version": "0.284.2",
|
|
5
|
+
"private": false,
|
|
6
|
+
"type": "module",
|
|
7
|
+
"description": "KONITIF theme tokens, spatial ambience and perceptual focus projections for compatible workbench hosts.",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/LeMouf/konitif-theme.git"
|
|
11
|
+
},
|
|
12
|
+
"publishConfig": {
|
|
13
|
+
"access": "public",
|
|
14
|
+
"registry": "https://registry.npmjs.org/"
|
|
15
|
+
},
|
|
16
|
+
"svelte": "./src/index.ts",
|
|
17
|
+
"files": [
|
|
18
|
+
"LICENSE.md",
|
|
19
|
+
"src/ambient",
|
|
20
|
+
"src/components",
|
|
21
|
+
"src/depth",
|
|
22
|
+
"src/focus",
|
|
23
|
+
"src/runtime",
|
|
24
|
+
"src/index.ts",
|
|
25
|
+
"src/konitifRuntimePhaseTokens.ts",
|
|
26
|
+
"src/konitifTheme.ts",
|
|
27
|
+
"src/konitifThemeAdapter.ts",
|
|
28
|
+
"src/konitifTokens.css",
|
|
29
|
+
"src/konitifWorkbenchThemeRuntime.ts",
|
|
30
|
+
"README.md",
|
|
31
|
+
"package.json",
|
|
32
|
+
"reference"
|
|
33
|
+
],
|
|
34
|
+
"exports": {
|
|
35
|
+
".": {
|
|
36
|
+
"svelte": "./src/index.ts",
|
|
37
|
+
"default": "./src/index.ts"
|
|
38
|
+
},
|
|
39
|
+
"./styles.css": "./src/konitifTokens.css",
|
|
40
|
+
"./depth/styles.css": "./src/depth/spatialDepthTokens.css"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"@konitif/workbench": "0.284.2",
|
|
44
|
+
"svelte": "4.2.20"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"typescript": "5.9.3"
|
|
48
|
+
},
|
|
49
|
+
"scripts": {
|
|
50
|
+
"typecheck": "tsc -p tsconfig.json",
|
|
51
|
+
"test": "node --test tests/*.test.mjs",
|
|
52
|
+
"verify:package": "node scripts/verify-package.mjs",
|
|
53
|
+
"prepack": "npm run typecheck && npm test",
|
|
54
|
+
"prepublishOnly": "node -e \"throw new Error('Publish only the verified .release/package.tgz archive with scripts disabled')\""
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Theme reference
|
|
2
|
+
|
|
3
|
+
This directory contains the machine-readable capability catalog and authority
|
|
4
|
+
diagram for `@konitif/theme`.
|
|
5
|
+
|
|
6
|
+
- [`catalog.json`](catalog.json) groups the public visual contracts by responsibility.
|
|
7
|
+
- [`diagrams.json`](diagrams.json) describes the runtime-signal-to-perception flow.
|
|
8
|
+
|
|
9
|
+
These files support documentation tooling. They are not runtime configuration,
|
|
10
|
+
workspace state or theme preferences.
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": "1.0.0",
|
|
3
|
+
"package": "@konitif/theme",
|
|
4
|
+
"intent": "Project KONITIF visual and spatial direction without changing the functional authority of the host.",
|
|
5
|
+
"clusters": [
|
|
6
|
+
{
|
|
7
|
+
"id": "theme-tokens",
|
|
8
|
+
"title": "Theme and runtime phases",
|
|
9
|
+
"summary": "Theme tokens and visual mappings for runtime phases.",
|
|
10
|
+
"authority": "Authored visual contract.",
|
|
11
|
+
"owns": [
|
|
12
|
+
"tokens",
|
|
13
|
+
"visual mapping"
|
|
14
|
+
],
|
|
15
|
+
"doesNotOwn": [
|
|
16
|
+
"runtime phase"
|
|
17
|
+
],
|
|
18
|
+
"workflow": [
|
|
19
|
+
"Define",
|
|
20
|
+
"Map",
|
|
21
|
+
"Apply"
|
|
22
|
+
],
|
|
23
|
+
"sources": [
|
|
24
|
+
"konitifTheme.ts",
|
|
25
|
+
"konitifWorkbenchThemeRuntime.ts",
|
|
26
|
+
"konitifRuntimePhaseTokens.ts",
|
|
27
|
+
"runtimePhaseVisualMap.ts"
|
|
28
|
+
]
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"id": "spatial-runtime",
|
|
32
|
+
"title": "Spatial reactivity",
|
|
33
|
+
"summary": "Derived spatial state and reactions to runtime signals.",
|
|
34
|
+
"authority": "Derived spatial projection.",
|
|
35
|
+
"owns": [
|
|
36
|
+
"reactivity",
|
|
37
|
+
"spatial state"
|
|
38
|
+
],
|
|
39
|
+
"doesNotOwn": [
|
|
40
|
+
"runtime signal"
|
|
41
|
+
],
|
|
42
|
+
"workflow": [
|
|
43
|
+
"Observe",
|
|
44
|
+
"Derive",
|
|
45
|
+
"Animate"
|
|
46
|
+
],
|
|
47
|
+
"sourcePrefixes": [
|
|
48
|
+
"runtime/"
|
|
49
|
+
]
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"id": "ambient",
|
|
53
|
+
"title": "Ambience and grid",
|
|
54
|
+
"summary": "Ambient-depth models, presets and components.",
|
|
55
|
+
"authority": "Ambient visual projection.",
|
|
56
|
+
"owns": [
|
|
57
|
+
"grid",
|
|
58
|
+
"uniforms",
|
|
59
|
+
"ambience"
|
|
60
|
+
],
|
|
61
|
+
"doesNotOwn": [
|
|
62
|
+
"workspace"
|
|
63
|
+
],
|
|
64
|
+
"workflow": [
|
|
65
|
+
"Configure",
|
|
66
|
+
"Project",
|
|
67
|
+
"Render"
|
|
68
|
+
],
|
|
69
|
+
"sourcePrefixes": [
|
|
70
|
+
"ambient/"
|
|
71
|
+
],
|
|
72
|
+
"sources": [
|
|
73
|
+
"SpatialAmbientRuntime.svelte",
|
|
74
|
+
"SpatialProjectionGrid.svelte"
|
|
75
|
+
]
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"id": "focus-depth",
|
|
79
|
+
"title": "Focus and depth",
|
|
80
|
+
"summary": "Perceptual hierarchy, focus planes and depth layers.",
|
|
81
|
+
"authority": "Local perceptual state.",
|
|
82
|
+
"owns": [
|
|
83
|
+
"focus",
|
|
84
|
+
"depth"
|
|
85
|
+
],
|
|
86
|
+
"doesNotOwn": [
|
|
87
|
+
"domain selection"
|
|
88
|
+
],
|
|
89
|
+
"workflow": [
|
|
90
|
+
"Declare",
|
|
91
|
+
"Compute",
|
|
92
|
+
"Project"
|
|
93
|
+
],
|
|
94
|
+
"sourcePrefixes": [
|
|
95
|
+
"focus/",
|
|
96
|
+
"depth/"
|
|
97
|
+
],
|
|
98
|
+
"sources": [
|
|
99
|
+
"FocusPlaneProvider.svelte",
|
|
100
|
+
"PerceptualSurface.svelte",
|
|
101
|
+
"SpatialDepthStack.svelte",
|
|
102
|
+
"SpatialDepthLayer.svelte"
|
|
103
|
+
]
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
"id": "surfaces",
|
|
107
|
+
"title": "Visual surfaces",
|
|
108
|
+
"summary": "Surface components for the KONITIF visual direction.",
|
|
109
|
+
"authority": "Surface rendering.",
|
|
110
|
+
"owns": [
|
|
111
|
+
"visual material"
|
|
112
|
+
],
|
|
113
|
+
"doesNotOwn": [
|
|
114
|
+
"projected content"
|
|
115
|
+
],
|
|
116
|
+
"workflow": [
|
|
117
|
+
"Receive",
|
|
118
|
+
"Style",
|
|
119
|
+
"Render"
|
|
120
|
+
],
|
|
121
|
+
"sourcePrefixes": [
|
|
122
|
+
"components/"
|
|
123
|
+
],
|
|
124
|
+
"sources": [
|
|
125
|
+
"KonitifGlassSurface.svelte"
|
|
126
|
+
]
|
|
127
|
+
}
|
|
128
|
+
]
|
|
129
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": "1.0.0",
|
|
3
|
+
"package": "@konitif/theme",
|
|
4
|
+
"diagrams": [
|
|
5
|
+
{
|
|
6
|
+
"id": "runtime-to-perception",
|
|
7
|
+
"title": "From runtime signal to perception",
|
|
8
|
+
"kind": "mechanism",
|
|
9
|
+
"summary": "The theme combines authored tokens and observed signals to produce a purely projective spatial reaction.",
|
|
10
|
+
"nodes": [
|
|
11
|
+
{
|
|
12
|
+
"id": "tokens",
|
|
13
|
+
"label": "Theme tokens",
|
|
14
|
+
"description": "Colors, depth and materials are defined."
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"id": "signal",
|
|
18
|
+
"label": "Runtime signal",
|
|
19
|
+
"description": "A phase or observation is received.",
|
|
20
|
+
"tone": "observation"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"id": "map",
|
|
24
|
+
"label": "Visual mapping",
|
|
25
|
+
"description": "The signal is mapped to a perceptual expression."
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"id": "spatial",
|
|
29
|
+
"label": "Spatial state",
|
|
30
|
+
"description": "Focus, ambience and depth are derived."
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"id": "surface",
|
|
34
|
+
"label": "Rendered surface",
|
|
35
|
+
"description": "Components project the result.",
|
|
36
|
+
"tone": "projection"
|
|
37
|
+
}
|
|
38
|
+
],
|
|
39
|
+
"edges": [
|
|
40
|
+
{
|
|
41
|
+
"from": "tokens",
|
|
42
|
+
"to": "signal"
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"from": "signal",
|
|
46
|
+
"to": "map"
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"from": "map",
|
|
50
|
+
"to": "spatial"
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"from": "spatial",
|
|
54
|
+
"to": "surface"
|
|
55
|
+
}
|
|
56
|
+
],
|
|
57
|
+
"caption": "Changing the theme does not modify runtime or semantic workspace state."
|
|
58
|
+
}
|
|
59
|
+
]
|
|
60
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { onMount } from 'svelte';
|
|
3
|
+
import type { RuntimePhase } from '../konitifRuntimePhaseTokens';
|
|
4
|
+
import type { RuntimeSpatialState } from '../runtime/runtimeSpatialReactivity';
|
|
5
|
+
import type { AmbientQuality } from './spatialAmbientTypes';
|
|
6
|
+
|
|
7
|
+
export let phase: RuntimePhase = 'LAUNCH_GATE';
|
|
8
|
+
export let quality: AmbientQuality = 'medium';
|
|
9
|
+
export let reducedMotion = false;
|
|
10
|
+
export let spatialState: RuntimeSpatialState | null = null;
|
|
11
|
+
export let themeMode: 'dark' | 'light' = 'dark';
|
|
12
|
+
|
|
13
|
+
let canvas: HTMLCanvasElement | null = null;
|
|
14
|
+
let context: CanvasRenderingContext2D | null = null;
|
|
15
|
+
let mounted = false;
|
|
16
|
+
let drawFrame = 0;
|
|
17
|
+
|
|
18
|
+
$: if (mounted) {
|
|
19
|
+
phase;
|
|
20
|
+
quality;
|
|
21
|
+
reducedMotion;
|
|
22
|
+
spatialState;
|
|
23
|
+
themeMode;
|
|
24
|
+
scheduleDraw();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
onMount(() => {
|
|
28
|
+
context = canvas?.getContext('2d') ?? null;
|
|
29
|
+
|
|
30
|
+
if (!canvas || !context) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
mounted = true;
|
|
35
|
+
const resizeObserver =
|
|
36
|
+
typeof ResizeObserver === 'function'
|
|
37
|
+
? new ResizeObserver(() => {
|
|
38
|
+
scheduleDraw();
|
|
39
|
+
})
|
|
40
|
+
: null;
|
|
41
|
+
|
|
42
|
+
resizeObserver?.observe(canvas);
|
|
43
|
+
scheduleDraw();
|
|
44
|
+
|
|
45
|
+
return () => {
|
|
46
|
+
mounted = false;
|
|
47
|
+
resizeObserver?.disconnect();
|
|
48
|
+
|
|
49
|
+
if (drawFrame !== 0) {
|
|
50
|
+
cancelAnimationFrame(drawFrame);
|
|
51
|
+
drawFrame = 0;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
context = null;
|
|
55
|
+
};
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
function scheduleDraw(): void {
|
|
59
|
+
if (!mounted || drawFrame !== 0 || typeof requestAnimationFrame !== 'function') {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
drawFrame = requestAnimationFrame(() => {
|
|
64
|
+
drawFrame = 0;
|
|
65
|
+
drawAmbientCanvas();
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function drawAmbientCanvas(): void {
|
|
70
|
+
if (!canvas || !context) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const dpr = Math.min(devicePixelRatio || 1, 2);
|
|
75
|
+
const width = Math.max(1, Math.round(canvas.clientWidth * dpr));
|
|
76
|
+
const height = Math.max(1, Math.round(canvas.clientHeight * dpr));
|
|
77
|
+
const style = getComputedStyle(canvas);
|
|
78
|
+
const isLight = themeMode === 'light';
|
|
79
|
+
const tintRgb = spatialState?.tintRgb ?? (style.getPropertyValue('--k-runtime-tint-rgb').trim() || '34, 211, 238');
|
|
80
|
+
const intensity = spatialState?.lightIntensity ?? (Number.parseFloat(style.getPropertyValue('--k-runtime-intensity')) || 0.5);
|
|
81
|
+
const fogDensity = spatialState?.fogDensity ?? (Number.parseFloat(style.getPropertyValue('--k-runtime-fog-density')) || 0.24);
|
|
82
|
+
|
|
83
|
+
if (canvas.width !== width || canvas.height !== height) {
|
|
84
|
+
canvas.width = width;
|
|
85
|
+
canvas.height = height;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
context.clearRect(0, 0, width, height);
|
|
89
|
+
|
|
90
|
+
const centerX = width * 0.5;
|
|
91
|
+
const centerY = height * (isLight ? 0.44 : 0.38);
|
|
92
|
+
const gradient = context.createRadialGradient(
|
|
93
|
+
centerX,
|
|
94
|
+
centerY,
|
|
95
|
+
0,
|
|
96
|
+
centerX,
|
|
97
|
+
centerY,
|
|
98
|
+
Math.max(width, height) * 0.72
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
gradient.addColorStop(0, `rgba(${tintRgb}, ${isLight ? 0.06 * intensity + 0.025 * fogDensity : 0.18 * intensity + 0.05 * fogDensity})`);
|
|
102
|
+
gradient.addColorStop(0.38, `rgba(${tintRgb}, ${isLight ? 0.025 * intensity + 0.018 * fogDensity : 0.06 * intensity + 0.035 * fogDensity})`);
|
|
103
|
+
gradient.addColorStop(1, 'rgba(0, 0, 0, 0)');
|
|
104
|
+
context.fillStyle = gradient;
|
|
105
|
+
context.fillRect(0, 0, width, height);
|
|
106
|
+
|
|
107
|
+
if (isLight) {
|
|
108
|
+
const warmLight = context.createRadialGradient(
|
|
109
|
+
width * 0.76,
|
|
110
|
+
height * 0.12,
|
|
111
|
+
0,
|
|
112
|
+
width * 0.76,
|
|
113
|
+
height * 0.12,
|
|
114
|
+
Math.max(width, height) * 0.48
|
|
115
|
+
);
|
|
116
|
+
warmLight.addColorStop(0, `rgba(255, 236, 198, ${0.12 + intensity * 0.05})`);
|
|
117
|
+
warmLight.addColorStop(0.42, `rgba(255, 236, 198, ${0.045 + intensity * 0.025})`);
|
|
118
|
+
warmLight.addColorStop(1, 'rgba(255, 236, 198, 0)');
|
|
119
|
+
context.fillStyle = warmLight;
|
|
120
|
+
context.fillRect(0, 0, width, height);
|
|
121
|
+
|
|
122
|
+
const coldEdge = context.createLinearGradient(0, height, width * 0.55, height * 0.28);
|
|
123
|
+
coldEdge.addColorStop(0, `rgba(110, 135, 165, ${0.095 + fogDensity * 0.025})`);
|
|
124
|
+
coldEdge.addColorStop(0.42, 'rgba(110, 135, 165, 0.035)');
|
|
125
|
+
coldEdge.addColorStop(1, 'rgba(110, 135, 165, 0)');
|
|
126
|
+
context.fillStyle = coldEdge;
|
|
127
|
+
context.fillRect(0, 0, width, height);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
</script>
|
|
131
|
+
|
|
132
|
+
<canvas bind:this={canvas} class="ambient-canvas" data-phase={phase} data-quality={quality} data-theme-mode={themeMode}></canvas>
|
|
133
|
+
|
|
134
|
+
<style>
|
|
135
|
+
.ambient-canvas {
|
|
136
|
+
position: absolute;
|
|
137
|
+
inset: 0;
|
|
138
|
+
width: 100%;
|
|
139
|
+
height: 100%;
|
|
140
|
+
filter: blur(0.2px);
|
|
141
|
+
opacity: 0.95;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.ambient-canvas[data-theme-mode='light'] {
|
|
145
|
+
filter: blur(0.1px);
|
|
146
|
+
opacity: 0.72;
|
|
147
|
+
}
|
|
148
|
+
</style>
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { RuntimePhase } from '../konitifRuntimePhaseTokens';
|
|
3
|
+
import type { RuntimeSpatialState } from '../runtime/runtimeSpatialReactivity';
|
|
4
|
+
import type { AmbientQuality } from './spatialAmbientTypes';
|
|
5
|
+
|
|
6
|
+
export let phase: RuntimePhase = 'LAUNCH_GATE';
|
|
7
|
+
export let quality: AmbientQuality = 'medium';
|
|
8
|
+
export let reducedMotion = false;
|
|
9
|
+
export let spatialState: RuntimeSpatialState | null = null;
|
|
10
|
+
export let themeMode: 'dark' | 'light' = 'dark';
|
|
11
|
+
|
|
12
|
+
const countByQuality: Record<AmbientQuality, number> = {
|
|
13
|
+
off: 0,
|
|
14
|
+
low: 18,
|
|
15
|
+
medium: 42,
|
|
16
|
+
high: 72
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
$: particleCount = Math.round(countByQuality[quality] * (spatialState?.particleDensity ?? 1));
|
|
20
|
+
$: speedFactor = Math.max(0.08, spatialState?.particleSpeed ?? 0.3);
|
|
21
|
+
$: particles = Array.from({ length: particleCount }, (_, index) => ({
|
|
22
|
+
id: index,
|
|
23
|
+
x: (index * 37) % 100,
|
|
24
|
+
y: (index * 61) % 100,
|
|
25
|
+
size: 1 + (index % 4),
|
|
26
|
+
duration: (10 + (index % 9)) / speedFactor,
|
|
27
|
+
depth: 0.22 + (index % 7) * 0.08
|
|
28
|
+
}));
|
|
29
|
+
</script>
|
|
30
|
+
|
|
31
|
+
<div
|
|
32
|
+
class:reducedMotion
|
|
33
|
+
class="particles"
|
|
34
|
+
data-phase={phase}
|
|
35
|
+
data-theme-mode={themeMode}
|
|
36
|
+
style={`--particle-speed:${speedFactor};`}
|
|
37
|
+
>
|
|
38
|
+
{#each particles as particle (particle.id)}
|
|
39
|
+
<i
|
|
40
|
+
style={`--x:${particle.x}%; --y:${particle.y}%; --s:${particle.size}px; --d:${particle.duration}s; --depth:${particle.depth};`}
|
|
41
|
+
></i>
|
|
42
|
+
{/each}
|
|
43
|
+
</div>
|
|
44
|
+
|
|
45
|
+
<style>
|
|
46
|
+
.particles {
|
|
47
|
+
position: absolute;
|
|
48
|
+
inset: 0;
|
|
49
|
+
overflow: hidden;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.particles i {
|
|
53
|
+
position: absolute;
|
|
54
|
+
left: var(--x);
|
|
55
|
+
top: var(--y);
|
|
56
|
+
width: var(--s);
|
|
57
|
+
height: var(--s);
|
|
58
|
+
border-radius: 999px;
|
|
59
|
+
background: var(--k-particle-color);
|
|
60
|
+
box-shadow:
|
|
61
|
+
0 0 calc(12px + 18px * var(--depth)) rgba(var(--k-runtime-tint-rgb), 0.22),
|
|
62
|
+
0 0 18px var(--k-particle-glow, var(--k-frustum-light));
|
|
63
|
+
opacity: calc(0.28 + var(--depth) * 0.38);
|
|
64
|
+
animation: float var(--d) ease-in-out infinite alternate;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.particles[data-theme-mode='light'] i {
|
|
68
|
+
box-shadow:
|
|
69
|
+
0 0 calc(8px + 12px * var(--depth)) rgba(var(--k-runtime-tint-rgb), 0.12),
|
|
70
|
+
0 0 12px var(--k-particle-glow);
|
|
71
|
+
opacity: calc(0.2 + var(--depth) * 0.24);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.reducedMotion i {
|
|
75
|
+
animation: none;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
@keyframes float {
|
|
79
|
+
from {
|
|
80
|
+
filter: blur(0.2px);
|
|
81
|
+
transform: translate3d(-8px, 6px, 0) scale(calc(0.8 + var(--depth)));
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
to {
|
|
85
|
+
filter: blur(1.4px);
|
|
86
|
+
transform: translate3d(10px, -14px, 0) scale(calc(0.95 + var(--depth)));
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
</style>
|