mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 10:53:59 +00:00
Add Director authoring, import previews and scene bundles
This commit is contained in:
1 parent
62f66c4b86
commit
078fc290ec
25 files changed
+1930
-48
No files matched your search
@@ -0,0 +1,137 @@
|
||||
/** Small owned modal for scene authoring and import review; text never becomes markup. */
|
||||
export function createSceneDialog(title, onClose) {
|
||||
const dialog = document.createElement('dialog');
|
||||
dialog.dataset.directorDialog = '';
|
||||
dialog.className = 'director-sharing-dialog';
|
||||
dialog.setAttribute('aria-label', title);
|
||||
Object.assign(dialog.style, {
|
||||
background: '#08141e',
|
||||
color: '#e3faff',
|
||||
border: '1px solid #397080',
|
||||
borderRadius: '6px',
|
||||
padding: '20px',
|
||||
width: 'min(720px,calc(100vw - 32px))',
|
||||
boxSizing: 'border-box',
|
||||
position: 'fixed',
|
||||
inset: '0',
|
||||
margin: 'auto',
|
||||
maxHeight: 'calc(100vh - 32px)',
|
||||
overflow: 'auto',
|
||||
font: '14px/1.5 sans-serif',
|
||||
});
|
||||
const heading = document.createElement('h2');
|
||||
heading.textContent = title;
|
||||
heading.style.marginBottom = '12px';
|
||||
dialog.append(heading);
|
||||
const body = document.createElement('div'),
|
||||
footer = document.createElement('div'),
|
||||
status = document.createElement('p');
|
||||
status.setAttribute('role', 'status');
|
||||
dialog.append(body, status, footer);
|
||||
const listeners = [];
|
||||
function listen(node, type, fn) {
|
||||
node.addEventListener(type, fn);
|
||||
listeners.push(() => node.removeEventListener(type, fn));
|
||||
}
|
||||
function text(value, parent = body) {
|
||||
const p = document.createElement('p');
|
||||
p.textContent = value;
|
||||
p.style.margin = '8px 0';
|
||||
parent.append(p);
|
||||
return p;
|
||||
}
|
||||
function button(label, fn, parent = footer) {
|
||||
const b = document.createElement('button');
|
||||
b.type = 'button';
|
||||
b.textContent = label;
|
||||
Object.assign(b.style, {
|
||||
background: '#10242e',
|
||||
color: '#e3faff',
|
||||
border: '1px solid #397080',
|
||||
borderRadius: '3px',
|
||||
padding: '7px 11px',
|
||||
margin: '6px 6px 6px 0',
|
||||
cursor: 'pointer',
|
||||
font: 'inherit',
|
||||
});
|
||||
listen(b, 'click', fn);
|
||||
parent.append(b);
|
||||
return b;
|
||||
}
|
||||
function input(label, value, { type = 'text', multiline = false } = {}) {
|
||||
const wrapper = document.createElement('label');
|
||||
wrapper.style.display = 'block';
|
||||
wrapper.textContent = label;
|
||||
const node = document.createElement(multiline ? 'textarea' : 'input');
|
||||
if (!multiline) node.type = type;
|
||||
node.value = value;
|
||||
node.setAttribute('aria-label', label);
|
||||
Object.assign(node.style, {
|
||||
display: 'block',
|
||||
boxSizing: 'border-box',
|
||||
width: '100%',
|
||||
padding: '7px',
|
||||
margin: '6px 0 14px',
|
||||
color: '#e3faff',
|
||||
background: '#10242e',
|
||||
border: '1px solid #397080',
|
||||
font: multiline ? '12px monospace' : 'inherit',
|
||||
});
|
||||
if (multiline) node.rows = 9;
|
||||
wrapper.append(node);
|
||||
body.append(wrapper);
|
||||
return node;
|
||||
}
|
||||
button('Cancel', onClose);
|
||||
listen(dialog, 'cancel', (event) => {
|
||||
event.preventDefault();
|
||||
onClose();
|
||||
});
|
||||
document.body.append(dialog);
|
||||
dialog.showModal();
|
||||
return {
|
||||
body,
|
||||
footer,
|
||||
status,
|
||||
text,
|
||||
button,
|
||||
input,
|
||||
listen,
|
||||
element: dialog,
|
||||
dispose() {
|
||||
for (const remove of listeners.splice(0)) remove();
|
||||
dialog.close();
|
||||
dialog.remove();
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/** Add controls only when their owner is present; dispose removes every listener and element. */
|
||||
export function mountSceneSharing(
|
||||
{ edit, share },
|
||||
panel = document.getElementById('scene-panel'),
|
||||
) {
|
||||
if (!panel) return () => {};
|
||||
const bar = document.createElement('div');
|
||||
bar.dataset.directorAuthoring = '';
|
||||
bar.className = 'scene-controls';
|
||||
const entries = [
|
||||
['EDIT DETAILS', edit],
|
||||
['SHARE SCENE', share],
|
||||
];
|
||||
const removers = [];
|
||||
for (const [text, fn] of entries) {
|
||||
const b = document.createElement('button');
|
||||
b.type = 'button';
|
||||
b.textContent = text;
|
||||
b.className = 'scene-btn';
|
||||
b.addEventListener('click', fn);
|
||||
removers.push(() => b.removeEventListener('click', fn));
|
||||
bar.append(b);
|
||||
}
|
||||
(panel.querySelector?.('.scene-panel-inner') || panel).appendChild(bar);
|
||||
return () => {
|
||||
for (const remove of removers) remove();
|
||||
bar.remove();
|
||||
};
|
||||
}
|
||||
Reference in new issue
Block a user