diff --git a/site/decodal-site/src/pages/playground.astro b/site/decodal-site/src/pages/playground.astro
index 1a179a5..95aefba 100644
--- a/site/decodal-site/src/pages/playground.astro
+++ b/site/decodal-site/src/pages/playground.astro
@@ -9,14 +9,22 @@ import ManualLayout from '../layouts/ManualLayout.astro';
Virtual files are evaluated in the browser through WebAssembly. Use import paths such as ./schemas/service.dcdl.
-
-
+
+
+
+
+
+
+
+
+
Loading WASM...
-
-
diff --git a/site/decodal-site/src/scripts/playground.js b/site/decodal-site/src/scripts/playground.js
index 44128e6..ecb4af0 100644
--- a/site/decodal-site/src/scripts/playground.js
+++ b/site/decodal-site/src/scripts/playground.js
@@ -20,6 +20,7 @@ const activeFile = document.getElementById('active-file');
const newFile = document.getElementById('new-file');
const deleteFile = document.getElementById('delete-file');
const exampleSelect = document.getElementById('example-select');
+const entrySelect = document.getElementById('entry-select');
const loadExample = document.getElementById('load-example');
const project = loadProject();
@@ -178,18 +179,32 @@ function setActiveFile(path) {
}
project.activePath = normalized;
setEditorText(project.files[normalized]);
- activeFile.textContent = normalized === project.entryPath ? `${normalized} (entry)` : normalized;
+ activeFile.textContent = normalized;
deleteFile.disabled = Object.keys(project.files).length <= 1;
renderFileTree();
updateRunLabel();
saveProject();
}
-function updateRunLabel() {
+function updateEntrySelect() {
+ const paths = Object.keys(project.files).sort();
const entryPath = project.files[project.entryPath] === undefined ? project.activePath : project.entryPath;
project.entryPath = entryPath;
- run.textContent = `Run ${entryPath}`;
- run.title = `Materialize ${entryPath}`;
+ entrySelect.replaceChildren(
+ ...paths.map((path) => {
+ const option = document.createElement('option');
+ option.value = path;
+ option.textContent = path;
+ return option;
+ }),
+ );
+ entrySelect.value = entryPath;
+}
+
+function updateRunLabel() {
+ updateEntrySelect();
+ run.textContent = 'Run';
+ run.title = `Materialize ${project.entryPath}`;
}
function execute() {
@@ -247,8 +262,8 @@ function renderTreeList(children) {
const button = document.createElement('button');
button.type = 'button';
button.className = child.path === project.activePath ? 'file active' : 'file';
- button.textContent = child.path === project.entryPath ? `${child.name} *` : child.name;
- button.title = child.path === project.entryPath ? `${child.path} (entry point)` : child.path;
+ button.textContent = child.name;
+ button.title = child.path;
button.addEventListener('click', () => setActiveFile(child.path));
item.append(button);
} else {
@@ -277,6 +292,13 @@ try {
status.textContent = `Failed to load WASM: ${error?.message ?? error}`;
}
+entrySelect.addEventListener('change', () => {
+ const path = normalizePath(entrySelect.value);
+ if (project.files[path] === undefined) return;
+ project.entryPath = path;
+ updateRunLabel();
+ saveProject();
+});
run.addEventListener('click', execute);
formatButton.addEventListener('click', formatActiveFile);
loadExample.addEventListener('click', () => {
diff --git a/site/decodal-site/src/style.css b/site/decodal-site/src/style.css
index e155c96..0fcdc3c 100644
--- a/site/decodal-site/src/style.css
+++ b/site/decodal-site/src/style.css
@@ -293,11 +293,26 @@ main.playground {
align-items: center;
display: flex;
flex-wrap: wrap;
- gap: 8px;
+ gap: 10px;
justify-content: flex-end;
}
-.example-picker {
+.action-group {
+ align-items: center;
+ background: rgba(15, 23, 42, 0.55);
+ border: 1px solid var(--border);
+ border-radius: 12px;
+ display: flex;
+ gap: 8px;
+ padding: 6px;
+}
+
+.run-actions {
+ border-color: rgba(96, 165, 250, 0.35);
+}
+
+.example-picker,
+.entry-picker {
align-items: center;
color: var(--muted);
display: flex;
@@ -307,7 +322,8 @@ main.playground {
text-transform: uppercase;
}
-.example-picker select {
+.example-picker select,
+.entry-picker select {
background: var(--surface);
border: 1px solid var(--border);
border-radius: 8px;
@@ -318,6 +334,10 @@ main.playground {
text-transform: none;
}
+.entry-picker select {
+ max-width: 220px;
+}
+
button {
background: var(--link);
border: 0;