@stevejtrettel/shader-sandbox 0.1.2 → 0.1.4
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/README.md +259 -235
- package/bin/cli.js +106 -14
- package/dist-lib/app/App.d.ts +143 -15
- package/dist-lib/app/App.d.ts.map +1 -1
- package/dist-lib/app/App.js +1343 -108
- package/dist-lib/app/app.css +349 -24
- package/dist-lib/app/types.d.ts +48 -5
- package/dist-lib/app/types.d.ts.map +1 -1
- package/dist-lib/editor/EditorPanel.d.ts +2 -2
- package/dist-lib/editor/EditorPanel.d.ts.map +1 -1
- package/dist-lib/editor/EditorPanel.js +1 -1
- package/dist-lib/editor/editor-panel.css +55 -32
- package/dist-lib/editor/prism-editor.css +16 -16
- package/dist-lib/embed.js +1 -1
- package/dist-lib/engine/{ShadertoyEngine.d.ts → ShaderEngine.d.ts} +134 -10
- package/dist-lib/engine/ShaderEngine.d.ts.map +1 -0
- package/dist-lib/engine/ShaderEngine.js +1523 -0
- package/dist-lib/engine/glHelpers.d.ts +24 -0
- package/dist-lib/engine/glHelpers.d.ts.map +1 -1
- package/dist-lib/engine/glHelpers.js +88 -0
- package/dist-lib/engine/std140.d.ts +47 -0
- package/dist-lib/engine/std140.d.ts.map +1 -0
- package/dist-lib/engine/std140.js +119 -0
- package/dist-lib/engine/types.d.ts +55 -5
- package/dist-lib/engine/types.d.ts.map +1 -1
- package/dist-lib/engine/types.js +1 -1
- package/dist-lib/index.d.ts +4 -3
- package/dist-lib/index.d.ts.map +1 -1
- package/dist-lib/index.js +2 -1
- package/dist-lib/layouts/SplitLayout.d.ts +2 -1
- package/dist-lib/layouts/SplitLayout.d.ts.map +1 -1
- package/dist-lib/layouts/SplitLayout.js +3 -0
- package/dist-lib/layouts/TabbedLayout.d.ts.map +1 -1
- package/dist-lib/layouts/UILayout.d.ts +55 -0
- package/dist-lib/layouts/UILayout.d.ts.map +1 -0
- package/dist-lib/layouts/UILayout.js +147 -0
- package/dist-lib/layouts/default.css +2 -2
- package/dist-lib/layouts/index.d.ts +11 -1
- package/dist-lib/layouts/index.d.ts.map +1 -1
- package/dist-lib/layouts/index.js +17 -1
- package/dist-lib/layouts/split.css +33 -31
- package/dist-lib/layouts/tabbed.css +127 -74
- package/dist-lib/layouts/types.d.ts +14 -3
- package/dist-lib/layouts/types.d.ts.map +1 -1
- package/dist-lib/main.js +33 -0
- package/dist-lib/project/configHelpers.d.ts +45 -0
- package/dist-lib/project/configHelpers.d.ts.map +1 -0
- package/dist-lib/project/configHelpers.js +196 -0
- package/dist-lib/project/generatedLoader.d.ts +2 -2
- package/dist-lib/project/generatedLoader.d.ts.map +1 -1
- package/dist-lib/project/generatedLoader.js +23 -5
- package/dist-lib/project/loadProject.d.ts +6 -6
- package/dist-lib/project/loadProject.d.ts.map +1 -1
- package/dist-lib/project/loadProject.js +396 -144
- package/dist-lib/project/loaderHelper.d.ts +4 -4
- package/dist-lib/project/loaderHelper.d.ts.map +1 -1
- package/dist-lib/project/loaderHelper.js +278 -116
- package/dist-lib/project/types.d.ts +292 -13
- package/dist-lib/project/types.d.ts.map +1 -1
- package/dist-lib/project/types.js +13 -1
- package/dist-lib/styles/base.css +5 -1
- package/dist-lib/uniforms/UniformControls.d.ts +60 -0
- package/dist-lib/uniforms/UniformControls.d.ts.map +1 -0
- package/dist-lib/uniforms/UniformControls.js +518 -0
- package/dist-lib/uniforms/UniformStore.d.ts +74 -0
- package/dist-lib/uniforms/UniformStore.d.ts.map +1 -0
- package/dist-lib/uniforms/UniformStore.js +145 -0
- package/dist-lib/uniforms/UniformsPanel.d.ts +53 -0
- package/dist-lib/uniforms/UniformsPanel.d.ts.map +1 -0
- package/dist-lib/uniforms/UniformsPanel.js +124 -0
- package/dist-lib/uniforms/index.d.ts +11 -0
- package/dist-lib/uniforms/index.d.ts.map +1 -0
- package/dist-lib/uniforms/index.js +8 -0
- package/package.json +16 -1
- package/src/app/App.ts +1469 -126
- package/src/app/app.css +349 -24
- package/src/app/types.ts +53 -5
- package/src/editor/EditorPanel.ts +5 -5
- package/src/editor/editor-panel.css +55 -32
- package/src/editor/prism-editor.css +16 -16
- package/src/embed.ts +1 -1
- package/src/engine/ShaderEngine.ts +1934 -0
- package/src/engine/glHelpers.ts +117 -0
- package/src/engine/std140.ts +136 -0
- package/src/engine/types.ts +69 -5
- package/src/index.ts +4 -3
- package/src/layouts/SplitLayout.ts +8 -3
- package/src/layouts/TabbedLayout.ts +3 -3
- package/src/layouts/UILayout.ts +185 -0
- package/src/layouts/default.css +2 -2
- package/src/layouts/index.ts +20 -1
- package/src/layouts/split.css +33 -31
- package/src/layouts/tabbed.css +127 -74
- package/src/layouts/types.ts +19 -3
- package/src/layouts/ui.css +289 -0
- package/src/main.ts +39 -1
- package/src/project/configHelpers.ts +225 -0
- package/src/project/generatedLoader.ts +27 -6
- package/src/project/loadProject.ts +459 -173
- package/src/project/loaderHelper.ts +377 -130
- package/src/project/types.ts +360 -14
- package/src/styles/base.css +5 -1
- package/src/styles/theme.css +292 -0
- package/src/uniforms/UniformControls.ts +660 -0
- package/src/uniforms/UniformStore.ts +166 -0
- package/src/uniforms/UniformsPanel.ts +163 -0
- package/src/uniforms/index.ts +13 -0
- package/src/uniforms/uniform-controls.css +342 -0
- package/src/uniforms/uniforms-panel.css +277 -0
- package/templates/shaders/example-buffer/config.json +1 -0
- package/dist-lib/engine/ShadertoyEngine.d.ts.map +0 -1
- package/dist-lib/engine/ShadertoyEngine.js +0 -704
- package/src/engine/ShadertoyEngine.ts +0 -929
package/src/layouts/index.ts
CHANGED
|
@@ -1,24 +1,38 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Layouts - Modular layout system for Shadertoy viewer
|
|
3
3
|
*
|
|
4
|
-
* Provides
|
|
4
|
+
* Provides five layout modes:
|
|
5
5
|
* - Default: Canvas centered with styling
|
|
6
6
|
* - Fullscreen: Canvas fills entire viewport
|
|
7
7
|
* - Split: Canvas on left, code viewer on right
|
|
8
8
|
* - Tabbed: Single window with tabs for shader and code
|
|
9
|
+
* - UI: Canvas on left, uniforms panel on right
|
|
9
10
|
*/
|
|
10
11
|
|
|
11
12
|
export { FullscreenLayout } from './FullscreenLayout';
|
|
12
13
|
export { DefaultLayout } from './DefaultLayout';
|
|
13
14
|
export { SplitLayout } from './SplitLayout';
|
|
14
15
|
export { TabbedLayout } from './TabbedLayout';
|
|
16
|
+
export { UILayout } from './UILayout';
|
|
15
17
|
export type { BaseLayout, LayoutOptions, LayoutMode } from './types';
|
|
16
18
|
|
|
17
19
|
import { FullscreenLayout } from './FullscreenLayout';
|
|
18
20
|
import { DefaultLayout } from './DefaultLayout';
|
|
19
21
|
import { SplitLayout } from './SplitLayout';
|
|
20
22
|
import { TabbedLayout } from './TabbedLayout';
|
|
23
|
+
import { UILayout } from './UILayout';
|
|
21
24
|
import { BaseLayout, LayoutOptions, LayoutMode } from './types';
|
|
25
|
+
import { ThemeMode } from '../project/types';
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Apply theme to the document.
|
|
29
|
+
* Sets the data-theme attribute on the html element.
|
|
30
|
+
*
|
|
31
|
+
* @param theme - Theme mode to apply ('light', 'dark', or 'system')
|
|
32
|
+
*/
|
|
33
|
+
export function applyTheme(theme: ThemeMode): void {
|
|
34
|
+
document.documentElement.setAttribute('data-theme', theme);
|
|
35
|
+
}
|
|
22
36
|
|
|
23
37
|
/**
|
|
24
38
|
* Factory function to create the appropriate layout based on mode.
|
|
@@ -31,6 +45,9 @@ export function createLayout(
|
|
|
31
45
|
mode: LayoutMode,
|
|
32
46
|
options: LayoutOptions
|
|
33
47
|
): BaseLayout {
|
|
48
|
+
// Apply theme from project configuration
|
|
49
|
+
applyTheme(options.project.theme);
|
|
50
|
+
|
|
34
51
|
switch (mode) {
|
|
35
52
|
case 'fullscreen':
|
|
36
53
|
return new FullscreenLayout(options);
|
|
@@ -40,5 +57,7 @@ export function createLayout(
|
|
|
40
57
|
return new SplitLayout(options);
|
|
41
58
|
case 'tabbed':
|
|
42
59
|
return new TabbedLayout(options);
|
|
60
|
+
case 'ui':
|
|
61
|
+
return new UILayout(options);
|
|
43
62
|
}
|
|
44
63
|
}
|
package/src/layouts/split.css
CHANGED
|
@@ -16,9 +16,9 @@
|
|
|
16
16
|
.layout-split .canvas-container {
|
|
17
17
|
position: relative;
|
|
18
18
|
flex: 1;
|
|
19
|
-
background:
|
|
19
|
+
background: var(--bg-canvas);
|
|
20
20
|
border-radius: 8px;
|
|
21
|
-
box-shadow:
|
|
21
|
+
box-shadow: var(--shadow-md), var(--shadow-sm);
|
|
22
22
|
overflow: hidden;
|
|
23
23
|
}
|
|
24
24
|
|
|
@@ -27,17 +27,17 @@
|
|
|
27
27
|
flex: 1;
|
|
28
28
|
display: flex;
|
|
29
29
|
flex-direction: column;
|
|
30
|
-
background:
|
|
30
|
+
background: var(--bg-secondary);
|
|
31
31
|
border-radius: 8px;
|
|
32
|
-
box-shadow:
|
|
32
|
+
box-shadow: var(--shadow-md), var(--shadow-sm);
|
|
33
33
|
overflow: hidden;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
/* ===== Code Panel ===== */
|
|
37
37
|
.tab-bar {
|
|
38
38
|
display: flex;
|
|
39
|
-
background:
|
|
40
|
-
border-bottom: 1px solid
|
|
39
|
+
background: var(--tab-bg);
|
|
40
|
+
border-bottom: 1px solid var(--border-primary);
|
|
41
41
|
padding: 8px 8px 0 8px;
|
|
42
42
|
gap: 4px;
|
|
43
43
|
}
|
|
@@ -50,17 +50,18 @@
|
|
|
50
50
|
font-size: 13px;
|
|
51
51
|
font-family: 'Monaco', 'Menlo', 'Courier New', monospace;
|
|
52
52
|
cursor: pointer;
|
|
53
|
-
transition: background 0.2s;
|
|
54
|
-
color:
|
|
53
|
+
transition: background 0.2s, color 0.2s;
|
|
54
|
+
color: var(--tab-text);
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
.tab-button:hover {
|
|
58
|
-
background:
|
|
58
|
+
background: var(--button-bg-hover);
|
|
59
|
+
color: var(--tab-text-hover);
|
|
59
60
|
}
|
|
60
61
|
|
|
61
62
|
.tab-button.active {
|
|
62
|
-
background:
|
|
63
|
-
color:
|
|
63
|
+
background: var(--bg-secondary);
|
|
64
|
+
color: var(--tab-text-active);
|
|
64
65
|
font-weight: 500;
|
|
65
66
|
}
|
|
66
67
|
|
|
@@ -69,10 +70,10 @@
|
|
|
69
70
|
top: 12px;
|
|
70
71
|
right: 12px;
|
|
71
72
|
padding: 6px;
|
|
72
|
-
background:
|
|
73
|
+
background: var(--button-bg);
|
|
73
74
|
border: none;
|
|
74
75
|
border-radius: 4px;
|
|
75
|
-
color:
|
|
76
|
+
color: var(--button-text);
|
|
76
77
|
cursor: pointer;
|
|
77
78
|
transition: all 0.2s;
|
|
78
79
|
z-index: 10;
|
|
@@ -82,8 +83,8 @@
|
|
|
82
83
|
}
|
|
83
84
|
|
|
84
85
|
.copy-button:hover {
|
|
85
|
-
background:
|
|
86
|
-
color:
|
|
86
|
+
background: var(--button-bg-hover);
|
|
87
|
+
color: var(--button-text-hover);
|
|
87
88
|
}
|
|
88
89
|
|
|
89
90
|
.copy-button:active {
|
|
@@ -91,7 +92,7 @@
|
|
|
91
92
|
}
|
|
92
93
|
|
|
93
94
|
.copy-button.copied {
|
|
94
|
-
color:
|
|
95
|
+
color: var(--success-text);
|
|
95
96
|
}
|
|
96
97
|
|
|
97
98
|
.code-viewer {
|
|
@@ -99,7 +100,7 @@
|
|
|
99
100
|
min-height: 0; /* Allow shrinking below content size in flexbox */
|
|
100
101
|
overflow: auto;
|
|
101
102
|
position: relative;
|
|
102
|
-
background:
|
|
103
|
+
background: var(--code-bg);
|
|
103
104
|
}
|
|
104
105
|
|
|
105
106
|
/* Prism.js syntax highlighting */
|
|
@@ -109,7 +110,8 @@
|
|
|
109
110
|
font-size: 13px;
|
|
110
111
|
line-height: 1.5;
|
|
111
112
|
font-family: 'Monaco', 'Menlo', 'Courier New', monospace;
|
|
112
|
-
background:
|
|
113
|
+
background: var(--code-bg);
|
|
114
|
+
color: var(--code-text);
|
|
113
115
|
}
|
|
114
116
|
|
|
115
117
|
.code-viewer code {
|
|
@@ -117,23 +119,23 @@
|
|
|
117
119
|
font-size: inherit;
|
|
118
120
|
}
|
|
119
121
|
|
|
120
|
-
/* Prism theme -
|
|
121
|
-
.token.comment { color:
|
|
122
|
-
.token.keyword { color:
|
|
123
|
-
.token.string { color:
|
|
124
|
-
.token.number { color:
|
|
125
|
-
.token.operator { color:
|
|
126
|
-
.token.function { color:
|
|
127
|
-
.token.class-name { color:
|
|
128
|
-
.token.punctuation { color:
|
|
122
|
+
/* Prism theme - uses CSS variables */
|
|
123
|
+
.token.comment { color: var(--syntax-comment); }
|
|
124
|
+
.token.keyword { color: var(--syntax-keyword); }
|
|
125
|
+
.token.string { color: var(--syntax-string); }
|
|
126
|
+
.token.number { color: var(--syntax-number); }
|
|
127
|
+
.token.operator { color: var(--syntax-operator); }
|
|
128
|
+
.token.function { color: var(--syntax-function); }
|
|
129
|
+
.token.class-name { color: var(--syntax-class); }
|
|
130
|
+
.token.punctuation { color: var(--syntax-punctuation); }
|
|
129
131
|
|
|
130
132
|
/* Image tab styling */
|
|
131
133
|
.tab-button.image-tab {
|
|
132
|
-
color:
|
|
134
|
+
color: var(--accent-secondary);
|
|
133
135
|
}
|
|
134
136
|
|
|
135
137
|
.tab-button.image-tab.active {
|
|
136
|
-
color:
|
|
138
|
+
color: var(--accent-secondary);
|
|
137
139
|
}
|
|
138
140
|
|
|
139
141
|
/* Image viewer */
|
|
@@ -143,7 +145,7 @@
|
|
|
143
145
|
justify-content: center;
|
|
144
146
|
height: 100%;
|
|
145
147
|
padding: 16px;
|
|
146
|
-
background:
|
|
148
|
+
background: var(--image-viewer-bg);
|
|
147
149
|
}
|
|
148
150
|
|
|
149
151
|
.image-viewer img {
|
|
@@ -151,7 +153,7 @@
|
|
|
151
153
|
max-height: 100%;
|
|
152
154
|
object-fit: contain;
|
|
153
155
|
border-radius: 4px;
|
|
154
|
-
box-shadow:
|
|
156
|
+
box-shadow: var(--shadow-sm);
|
|
155
157
|
}
|
|
156
158
|
|
|
157
159
|
/* ===== Responsive adjustments ===== */
|
package/src/layouts/tabbed.css
CHANGED
|
@@ -3,14 +3,6 @@
|
|
|
3
3
|
* Single window with tabs switching between shader and code views
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
/* ===== Theme Variables (for code viewer) ===== */
|
|
7
|
-
.layout-tabbed {
|
|
8
|
-
--tab-border: #e0e0e0;
|
|
9
|
-
--code-bg: white;
|
|
10
|
-
--code-text: #000;
|
|
11
|
-
--line-number-text: #999;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
6
|
.layout-tabbed {
|
|
15
7
|
width: 100%;
|
|
16
8
|
height: 100%;
|
|
@@ -30,7 +22,7 @@
|
|
|
30
22
|
height: 650px; /* 600px content + ~50px tabs */
|
|
31
23
|
max-height: 100%;
|
|
32
24
|
border-radius: 8px;
|
|
33
|
-
box-shadow:
|
|
25
|
+
box-shadow: var(--shadow-lg), var(--shadow-sm);
|
|
34
26
|
overflow: hidden;
|
|
35
27
|
}
|
|
36
28
|
|
|
@@ -39,8 +31,8 @@
|
|
|
39
31
|
display: flex;
|
|
40
32
|
align-items: center;
|
|
41
33
|
flex-shrink: 0;
|
|
42
|
-
background:
|
|
43
|
-
border-bottom: 1px solid
|
|
34
|
+
background: var(--tab-bg);
|
|
35
|
+
border-bottom: 1px solid var(--border-primary);
|
|
44
36
|
padding-right: 8px;
|
|
45
37
|
}
|
|
46
38
|
|
|
@@ -60,7 +52,7 @@
|
|
|
60
52
|
}
|
|
61
53
|
|
|
62
54
|
.tabbed-tab-bar::-webkit-scrollbar-thumb {
|
|
63
|
-
background:
|
|
55
|
+
background: var(--border-secondary);
|
|
64
56
|
border-radius: 2px;
|
|
65
57
|
}
|
|
66
58
|
|
|
@@ -73,18 +65,18 @@
|
|
|
73
65
|
font-family: 'Monaco', 'Menlo', 'Courier New', monospace;
|
|
74
66
|
cursor: pointer;
|
|
75
67
|
transition: color 0.15s, border-color 0.15s;
|
|
76
|
-
color:
|
|
68
|
+
color: var(--tab-text);
|
|
77
69
|
white-space: nowrap;
|
|
78
70
|
flex-shrink: 0;
|
|
79
71
|
}
|
|
80
72
|
|
|
81
73
|
.tabbed-tab-button:hover {
|
|
82
|
-
color:
|
|
74
|
+
color: var(--tab-text-hover);
|
|
83
75
|
}
|
|
84
76
|
|
|
85
77
|
.tabbed-tab-button.active {
|
|
86
|
-
color:
|
|
87
|
-
border-bottom-color:
|
|
78
|
+
color: var(--tab-text-active);
|
|
79
|
+
border-bottom-color: var(--tab-border-active);
|
|
88
80
|
}
|
|
89
81
|
|
|
90
82
|
.tabbed-tab-button.shader-tab {
|
|
@@ -92,12 +84,28 @@
|
|
|
92
84
|
}
|
|
93
85
|
|
|
94
86
|
.tabbed-tab-button.image-tab {
|
|
95
|
-
color:
|
|
87
|
+
color: var(--accent-secondary);
|
|
96
88
|
}
|
|
97
89
|
|
|
98
90
|
.tabbed-tab-button.image-tab.active {
|
|
99
|
-
color:
|
|
100
|
-
border-bottom-color:
|
|
91
|
+
color: var(--accent-secondary);
|
|
92
|
+
border-bottom-color: var(--accent-secondary);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.tabbed-tab-button.uniforms-tab {
|
|
96
|
+
color: var(--accent-tertiary, var(--accent-primary));
|
|
97
|
+
padding: 8px 12px;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.tabbed-tab-button.uniforms-tab.active {
|
|
101
|
+
color: var(--accent-tertiary, var(--accent-primary));
|
|
102
|
+
border-bottom-color: var(--accent-tertiary, var(--accent-primary));
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.tabbed-tab-button .uniforms-icon {
|
|
106
|
+
width: 18px;
|
|
107
|
+
height: 18px;
|
|
108
|
+
display: block;
|
|
101
109
|
}
|
|
102
110
|
|
|
103
111
|
/* ===== Content Area ===== */
|
|
@@ -105,7 +113,7 @@
|
|
|
105
113
|
flex: 1;
|
|
106
114
|
min-height: 0; /* Critical for flexbox scrolling */
|
|
107
115
|
position: relative;
|
|
108
|
-
background:
|
|
116
|
+
background: var(--bg-canvas);
|
|
109
117
|
overflow: hidden;
|
|
110
118
|
}
|
|
111
119
|
|
|
@@ -149,8 +157,8 @@
|
|
|
149
157
|
text-align: right;
|
|
150
158
|
padding-right: 16px;
|
|
151
159
|
margin-right: 16px;
|
|
152
|
-
border-right: 1px solid var(--
|
|
153
|
-
color: var(--line-number
|
|
160
|
+
border-right: 1px solid var(--code-line-border);
|
|
161
|
+
color: var(--code-line-number);
|
|
154
162
|
user-select: none;
|
|
155
163
|
flex-shrink: 0;
|
|
156
164
|
padding-left: 16px;
|
|
@@ -171,7 +179,7 @@
|
|
|
171
179
|
display: flex;
|
|
172
180
|
align-items: center;
|
|
173
181
|
justify-content: center;
|
|
174
|
-
background:
|
|
182
|
+
background: var(--image-viewer-bg);
|
|
175
183
|
padding: 20px;
|
|
176
184
|
box-sizing: border-box;
|
|
177
185
|
}
|
|
@@ -181,36 +189,18 @@
|
|
|
181
189
|
max-height: 100%;
|
|
182
190
|
object-fit: contain;
|
|
183
191
|
border-radius: 4px;
|
|
184
|
-
box-shadow:
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
/* ===== Prism Theme (
|
|
188
|
-
.tabbed-code-viewer .token.comment { color:
|
|
189
|
-
.tabbed-code-viewer .token.keyword { color:
|
|
190
|
-
.tabbed-code-viewer .token.string { color:
|
|
191
|
-
.tabbed-code-viewer .token.number { color:
|
|
192
|
-
.tabbed-code-viewer .token.operator { color:
|
|
193
|
-
.tabbed-code-viewer .token.function { color:
|
|
194
|
-
.tabbed-code-viewer .token.class-name { color:
|
|
195
|
-
.tabbed-code-viewer .token.punctuation { color:
|
|
196
|
-
|
|
197
|
-
/* ===== Prism Theme (Dark) ===== */
|
|
198
|
-
[data-bs-theme="dark"] .tabbed-code-viewer .token.comment,
|
|
199
|
-
.dark .tabbed-code-viewer .token.comment { color: #6a9955; }
|
|
200
|
-
[data-bs-theme="dark"] .tabbed-code-viewer .token.keyword,
|
|
201
|
-
.dark .tabbed-code-viewer .token.keyword { color: #569cd6; }
|
|
202
|
-
[data-bs-theme="dark"] .tabbed-code-viewer .token.string,
|
|
203
|
-
.dark .tabbed-code-viewer .token.string { color: #ce9178; }
|
|
204
|
-
[data-bs-theme="dark"] .tabbed-code-viewer .token.number,
|
|
205
|
-
.dark .tabbed-code-viewer .token.number { color: #b5cea8; }
|
|
206
|
-
[data-bs-theme="dark"] .tabbed-code-viewer .token.operator,
|
|
207
|
-
.dark .tabbed-code-viewer .token.operator { color: #d4d4d4; }
|
|
208
|
-
[data-bs-theme="dark"] .tabbed-code-viewer .token.function,
|
|
209
|
-
.dark .tabbed-code-viewer .token.function { color: #dcdcaa; }
|
|
210
|
-
[data-bs-theme="dark"] .tabbed-code-viewer .token.class-name,
|
|
211
|
-
.dark .tabbed-code-viewer .token.class-name { color: #4ec9b0; }
|
|
212
|
-
[data-bs-theme="dark"] .tabbed-code-viewer .token.punctuation,
|
|
213
|
-
.dark .tabbed-code-viewer .token.punctuation { color: #d4d4d4; }
|
|
192
|
+
box-shadow: var(--shadow-sm);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/* ===== Prism Theme (uses CSS variables) ===== */
|
|
196
|
+
.tabbed-code-viewer .token.comment { color: var(--syntax-comment); }
|
|
197
|
+
.tabbed-code-viewer .token.keyword { color: var(--syntax-keyword); }
|
|
198
|
+
.tabbed-code-viewer .token.string { color: var(--syntax-string); }
|
|
199
|
+
.tabbed-code-viewer .token.number { color: var(--syntax-number); }
|
|
200
|
+
.tabbed-code-viewer .token.operator { color: var(--syntax-operator); }
|
|
201
|
+
.tabbed-code-viewer .token.function { color: var(--syntax-function); }
|
|
202
|
+
.tabbed-code-viewer .token.class-name { color: var(--syntax-class); }
|
|
203
|
+
.tabbed-code-viewer .token.punctuation { color: var(--syntax-punctuation); }
|
|
214
204
|
|
|
215
205
|
/* ===== Responsive ===== */
|
|
216
206
|
@media (max-width: 1200px) {
|
|
@@ -244,7 +234,7 @@
|
|
|
244
234
|
width: 100%;
|
|
245
235
|
height: 100%;
|
|
246
236
|
overflow: hidden;
|
|
247
|
-
background:
|
|
237
|
+
background: var(--code-bg);
|
|
248
238
|
}
|
|
249
239
|
|
|
250
240
|
/* Button container for copy and recompile (in toolbar) */
|
|
@@ -260,9 +250,9 @@
|
|
|
260
250
|
display: flex;
|
|
261
251
|
align-items: center;
|
|
262
252
|
justify-content: center;
|
|
263
|
-
background:
|
|
264
|
-
border: 1px solid
|
|
265
|
-
color:
|
|
253
|
+
background: var(--button-bg);
|
|
254
|
+
border: 1px solid var(--button-border);
|
|
255
|
+
color: var(--button-text);
|
|
266
256
|
width: 32px;
|
|
267
257
|
height: 32px;
|
|
268
258
|
border-radius: 4px;
|
|
@@ -271,43 +261,43 @@
|
|
|
271
261
|
}
|
|
272
262
|
|
|
273
263
|
.tabbed-copy-button:hover {
|
|
274
|
-
background:
|
|
275
|
-
border-color:
|
|
276
|
-
color:
|
|
264
|
+
background: var(--button-bg-hover);
|
|
265
|
+
border-color: var(--button-border-hover);
|
|
266
|
+
color: var(--button-text-hover);
|
|
277
267
|
}
|
|
278
268
|
|
|
279
269
|
.tabbed-copy-button:active {
|
|
280
|
-
background:
|
|
270
|
+
background: var(--button-bg-hover);
|
|
281
271
|
}
|
|
282
272
|
|
|
283
273
|
.tabbed-copy-button.copied {
|
|
284
|
-
background:
|
|
285
|
-
border-color:
|
|
286
|
-
color:
|
|
274
|
+
background: var(--success-bg);
|
|
275
|
+
border-color: var(--success-border);
|
|
276
|
+
color: var(--success-text);
|
|
287
277
|
}
|
|
288
278
|
|
|
289
279
|
.tabbed-recompile-button {
|
|
290
280
|
display: flex;
|
|
291
281
|
align-items: center;
|
|
292
282
|
gap: 6px;
|
|
293
|
-
background:
|
|
283
|
+
background: var(--recompile-bg);
|
|
294
284
|
border: none;
|
|
295
|
-
color:
|
|
285
|
+
color: var(--recompile-text);
|
|
296
286
|
padding: 6px 12px;
|
|
297
287
|
border-radius: 4px;
|
|
298
288
|
cursor: pointer;
|
|
299
289
|
font-family: inherit;
|
|
300
290
|
font-size: 12px;
|
|
301
291
|
font-weight: 500;
|
|
302
|
-
transition: background 0.15s;
|
|
292
|
+
transition: background 0.15s, color 0.15s;
|
|
303
293
|
}
|
|
304
294
|
|
|
305
295
|
.tabbed-recompile-button:hover {
|
|
306
|
-
background:
|
|
296
|
+
background: var(--recompile-bg-hover);
|
|
307
297
|
}
|
|
308
298
|
|
|
309
299
|
.tabbed-recompile-button:active {
|
|
310
|
-
background:
|
|
300
|
+
background: var(--recompile-bg-active);
|
|
311
301
|
}
|
|
312
302
|
|
|
313
303
|
.tabbed-recompile-button svg {
|
|
@@ -319,23 +309,23 @@
|
|
|
319
309
|
bottom: 0;
|
|
320
310
|
left: 0;
|
|
321
311
|
right: 0;
|
|
322
|
-
background:
|
|
323
|
-
color:
|
|
312
|
+
background: var(--error-bg);
|
|
313
|
+
color: var(--error-text);
|
|
324
314
|
padding: 10px 14px;
|
|
325
315
|
font-family: 'Monaco', 'Menlo', 'Courier New', monospace;
|
|
326
316
|
font-size: 12px;
|
|
327
317
|
white-space: pre-wrap;
|
|
328
318
|
overflow: auto;
|
|
329
319
|
max-height: 120px;
|
|
330
|
-
border-top: 1px solid
|
|
320
|
+
border-top: 1px solid var(--error-border);
|
|
331
321
|
z-index: 10;
|
|
332
322
|
}
|
|
333
323
|
|
|
334
324
|
.tabbed-fallback-textarea {
|
|
335
325
|
width: 100%;
|
|
336
326
|
height: 100%;
|
|
337
|
-
background:
|
|
338
|
-
color:
|
|
327
|
+
background: var(--code-bg);
|
|
328
|
+
color: var(--code-text);
|
|
339
329
|
border: none;
|
|
340
330
|
padding: 12px;
|
|
341
331
|
font-family: 'Monaco', 'Menlo', 'Courier New', monospace;
|
|
@@ -343,3 +333,66 @@
|
|
|
343
333
|
resize: none;
|
|
344
334
|
outline: none;
|
|
345
335
|
}
|
|
336
|
+
|
|
337
|
+
/* ===== Uniforms Container (semi-transparent overlay) ===== */
|
|
338
|
+
.tabbed-uniforms-container {
|
|
339
|
+
position: absolute;
|
|
340
|
+
top: 0;
|
|
341
|
+
left: 0;
|
|
342
|
+
width: 100%;
|
|
343
|
+
height: 100%;
|
|
344
|
+
overflow-y: auto;
|
|
345
|
+
background: rgba(0, 0, 0, 0.5);
|
|
346
|
+
backdrop-filter: blur(8px);
|
|
347
|
+
display: flex;
|
|
348
|
+
justify-content: center;
|
|
349
|
+
padding: 20px;
|
|
350
|
+
box-sizing: border-box;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/* Center the uniform controls and constrain width */
|
|
354
|
+
.tabbed-uniforms-container .uniform-controls {
|
|
355
|
+
max-width: 400px;
|
|
356
|
+
width: 100%;
|
|
357
|
+
background: rgba(30, 30, 35, 0.95);
|
|
358
|
+
border-radius: 12px;
|
|
359
|
+
padding: 20px;
|
|
360
|
+
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.4);
|
|
361
|
+
height: fit-content;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/* Ensure text is visible in the overlay */
|
|
365
|
+
.tabbed-uniforms-container .uniform-control-label {
|
|
366
|
+
color: #e0e0e0;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
.tabbed-uniforms-container .uniform-control-value {
|
|
370
|
+
color: #a0a0a0;
|
|
371
|
+
background: rgba(0, 0, 0, 0.3);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
.tabbed-uniforms-container .uniform-controls-header {
|
|
375
|
+
color: #909090;
|
|
376
|
+
border-bottom-color: rgba(255, 255, 255, 0.1);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
.tabbed-uniforms-container .uniform-control-slider {
|
|
380
|
+
background: rgba(255, 255, 255, 0.1);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
.tabbed-uniforms-container .uniform-control-slider::-webkit-slider-thumb {
|
|
384
|
+
background: #ffffff;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
.tabbed-uniforms-container .uniform-control-slider::-moz-range-thumb {
|
|
388
|
+
background: #ffffff;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
.tabbed-uniforms-container .uniform-control-vec-component {
|
|
392
|
+
color: #909090;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
.tabbed-uniforms-container .uniform-control-vec-value {
|
|
396
|
+
color: #a0a0a0;
|
|
397
|
+
background: rgba(0, 0, 0, 0.3);
|
|
398
|
+
}
|
package/src/layouts/types.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Layout Types - Common interface for all layout modes
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { ShaderProject, PassName, UniformValue } from '../project/types';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Result of a recompilation attempt.
|
|
@@ -23,6 +23,16 @@ export type RecompileHandler = (
|
|
|
23
23
|
newSource: string
|
|
24
24
|
) => RecompileResult;
|
|
25
25
|
|
|
26
|
+
/**
|
|
27
|
+
* Callback for uniform value changes.
|
|
28
|
+
* @param name - Uniform name
|
|
29
|
+
* @param value - New uniform value
|
|
30
|
+
*/
|
|
31
|
+
export type UniformChangeHandler = (
|
|
32
|
+
name: string,
|
|
33
|
+
value: UniformValue
|
|
34
|
+
) => void;
|
|
35
|
+
|
|
26
36
|
/**
|
|
27
37
|
* Base interface that all layouts must implement.
|
|
28
38
|
*/
|
|
@@ -38,6 +48,12 @@ export interface BaseLayout {
|
|
|
38
48
|
*/
|
|
39
49
|
setRecompileHandler?(handler: RecompileHandler): void;
|
|
40
50
|
|
|
51
|
+
/**
|
|
52
|
+
* Set the uniform change handler for uniform controls.
|
|
53
|
+
* Called by App after initialization to wire up uniform changes.
|
|
54
|
+
*/
|
|
55
|
+
setUniformHandler?(handler: UniformChangeHandler): void;
|
|
56
|
+
|
|
41
57
|
/**
|
|
42
58
|
* Clean up all DOM elements and resources.
|
|
43
59
|
*/
|
|
@@ -49,10 +65,10 @@ export interface BaseLayout {
|
|
|
49
65
|
*/
|
|
50
66
|
export interface LayoutOptions {
|
|
51
67
|
container: HTMLElement;
|
|
52
|
-
project:
|
|
68
|
+
project: ShaderProject;
|
|
53
69
|
}
|
|
54
70
|
|
|
55
71
|
/**
|
|
56
72
|
* Available layout modes.
|
|
57
73
|
*/
|
|
58
|
-
export type LayoutMode = 'fullscreen' | 'default' | 'split' | 'tabbed';
|
|
74
|
+
export type LayoutMode = 'fullscreen' | 'default' | 'split' | 'tabbed' | 'ui';
|