Needs fixing , animator UI
This commit is contained in:
694
public/animator-simple.html
Normal file
694
public/animator-simple.html
Normal file
@@ -0,0 +1,694 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Re-Commander — Animator</title>
|
||||
|
||||
<!-- Google Fonts -->
|
||||
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap" rel="stylesheet">
|
||||
<!-- Material Icons -->
|
||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
||||
|
||||
<!-- Golden Layout -->
|
||||
<link rel="stylesheet" href="https://golden-layout.com/assets/css/goldenlayout-base.css">
|
||||
<link rel="stylesheet" href="https://golden-layout.com/assets/css/goldenlayout-dark-theme.css">
|
||||
<script src="https://cdn.jsdelivr.net/npm/golden-layout@2/dist/umd/index.js"></script>
|
||||
|
||||
<!-- Theatre.js (temporarily disabled) -->
|
||||
<!-- <script src="https://unpkg.com/@theatre/core@0.7.2/dist/theatre-core.umd.js"></script>
|
||||
<script src="https://unpkg.com/@theatre/studio@0.7.2/dist/theatre-studio.umd.js"></script> -->
|
||||
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Roboto', sans-serif;
|
||||
background: #121212;
|
||||
color: #ffffff;
|
||||
overflow: hidden;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* Material Design Top Bar */
|
||||
.top-bar {
|
||||
height: 64px;
|
||||
background: #1e1e1e;
|
||||
border-bottom: 1px solid #333;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 16px;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.3);
|
||||
z-index: 1000;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.logo-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-right: 32px;
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
background: linear-gradient(45deg, #2196F3, #1976D2);
|
||||
border-radius: 8px;
|
||||
margin-right: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.app-title {
|
||||
font-size: 20px;
|
||||
font-weight: 500;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
/* Dropdown Menus */
|
||||
.dropdown {
|
||||
position: relative;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.dropdown-button {
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: #ffffff;
|
||||
padding: 8px 16px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
transition: background 0.2s;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.dropdown-button:hover {
|
||||
background: rgba(255,255,255,0.1);
|
||||
}
|
||||
|
||||
.dropdown-menu {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
background: #2d2d2d;
|
||||
border: 1px solid #444;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.3);
|
||||
min-width: 160px;
|
||||
display: none;
|
||||
z-index: 1001;
|
||||
}
|
||||
|
||||
.dropdown-menu.show {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.dropdown-item {
|
||||
padding: 12px 16px;
|
||||
cursor: pointer;
|
||||
transition: background 0.2s;
|
||||
font-size: 14px;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.dropdown-item:hover {
|
||||
background: rgba(255,255,255,0.1);
|
||||
}
|
||||
|
||||
.dropdown-divider {
|
||||
height: 1px;
|
||||
background: #444;
|
||||
margin: 4px 0;
|
||||
}
|
||||
|
||||
/* Connection Status */
|
||||
.connection-status {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin-left: auto;
|
||||
margin-right: 16px;
|
||||
padding: 6px 12px;
|
||||
background: rgba(255,255,255,0.05);
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
||||
.status-dot {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
background: #666;
|
||||
animation: pulse 2s infinite;
|
||||
}
|
||||
|
||||
.status-dot.connected {
|
||||
background: #4CAF50;
|
||||
}
|
||||
|
||||
.status-dot.disconnected {
|
||||
background: #f44336;
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
0%, 100% { opacity: 1; }
|
||||
50% { opacity: 0.5; }
|
||||
}
|
||||
|
||||
.status-text {
|
||||
font-size: 12px;
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
/* Action Buttons */
|
||||
.action-buttons {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
.icon-button {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 50%;
|
||||
border: none;
|
||||
background: rgba(255,255,255,0.1);
|
||||
color: #ffffff;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.icon-button:hover {
|
||||
background: rgba(255,255,255,0.2);
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
/* Animation Name Section */
|
||||
.animation-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.animation-input {
|
||||
background: rgba(255,255,255,0.1);
|
||||
border: 1px solid #444;
|
||||
border-radius: 4px;
|
||||
padding: 8px 12px;
|
||||
color: #ffffff;
|
||||
font-size: 14px;
|
||||
width: 200px;
|
||||
transition: border-color 0.2s;
|
||||
}
|
||||
|
||||
.animation-input:focus {
|
||||
outline: none;
|
||||
border-color: #2196F3;
|
||||
}
|
||||
|
||||
.export-button {
|
||||
background: #2196F3;
|
||||
border: none;
|
||||
color: white;
|
||||
padding: 8px 16px;
|
||||
border-radius: 4px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: background 0.2s;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.export-button:hover {
|
||||
background: #1976D2;
|
||||
}
|
||||
|
||||
/* Golden Layout Container */
|
||||
#layout-container {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
background: #1a1a1a;
|
||||
}
|
||||
|
||||
/* Golden Layout Customization */
|
||||
.gl_container {
|
||||
background: #1a1a1a !important;
|
||||
}
|
||||
|
||||
.gl_tab {
|
||||
background: #2d2d2d !important;
|
||||
color: #ffffff !important;
|
||||
border-bottom: 2px solid #444 !important;
|
||||
padding: 8px 12px !important;
|
||||
font-size: 12px !important;
|
||||
}
|
||||
|
||||
.gl_tab.gl_active {
|
||||
background: #2196F3 !important;
|
||||
color: #ffffff !important;
|
||||
border-bottom: 2px solid #2196F3 !important;
|
||||
}
|
||||
|
||||
.gl_tab:hover {
|
||||
background: #333333 !important;
|
||||
}
|
||||
|
||||
.gl_tabBar {
|
||||
background: #2d2d2d !important;
|
||||
border-bottom: 1px solid #444 !important;
|
||||
}
|
||||
|
||||
.gl_header {
|
||||
background: #2d2d2d !important;
|
||||
border-bottom: 1px solid #444 !important;
|
||||
padding: 6px !important;
|
||||
}
|
||||
|
||||
.gl_splitter {
|
||||
background: #444 !important;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Material Design Top Bar -->
|
||||
<header class="top-bar">
|
||||
<!-- Logo/Title Section -->
|
||||
<div class="logo-section">
|
||||
<div class="logo">R</div>
|
||||
<div class="app-title">Re-Commander Animator</div>
|
||||
</div>
|
||||
|
||||
<!-- File Menu -->
|
||||
<div class="dropdown">
|
||||
<button class="dropdown-button" onclick="toggleDropdown('file-menu')">
|
||||
File <span class="material-icons" style="font-size: 16px;">arrow_drop_down</span>
|
||||
</button>
|
||||
<div class="dropdown-menu" id="file-menu">
|
||||
<div class="dropdown-item">New Animation</div>
|
||||
<div class="dropdown-item">Open Animation</div>
|
||||
<div class="dropdown-item">Save Animation</div>
|
||||
<div class="dropdown-item">Save As...</div>
|
||||
<div class="dropdown-divider"></div>
|
||||
<div class="dropdown-item">Import</div>
|
||||
<div class="dropdown-item">Export</div>
|
||||
<div class="dropdown-divider"></div>
|
||||
<div class="dropdown-item">Exit</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Edit Menu -->
|
||||
<div class="dropdown">
|
||||
<button class="dropdown-button" onclick="toggleDropdown('edit-menu')">
|
||||
Edit <span class="material-icons" style="font-size: 16px;">arrow_drop_down</span>
|
||||
</button>
|
||||
<div class="dropdown-menu" id="edit-menu">
|
||||
<div class="dropdown-item">Undo</div>
|
||||
<div class="dropdown-item">Redo</div>
|
||||
<div class="dropdown-divider"></div>
|
||||
<div class="dropdown-item">Cut</div>
|
||||
<div class="dropdown-item">Copy</div>
|
||||
<div class="dropdown-item">Paste</div>
|
||||
<div class="dropdown-item">Delete</div>
|
||||
<div class="dropdown-divider"></div>
|
||||
<div class="dropdown-item">Select All</div>
|
||||
<div class="dropdown-item">Preferences</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Connection Status -->
|
||||
<div class="connection-status">
|
||||
<div class="status-dot disconnected" id="status-dot"></div>
|
||||
<span class="status-text" id="status-text">Disconnected</span>
|
||||
</div>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="action-buttons">
|
||||
<button class="icon-button" title="Upload">
|
||||
<span class="material-icons">upload</span>
|
||||
</button>
|
||||
<button class="icon-button" title="Settings">
|
||||
<span class="material-icons">settings</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Animation Name & Export -->
|
||||
<div class="animation-section">
|
||||
<input type="text" class="animation-input" placeholder="Animation name..." id="animation-name">
|
||||
<button class="export-button">
|
||||
<span class="material-icons" style="font-size: 16px;">download</span>
|
||||
Export
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Golden Layout Container -->
|
||||
<div id="layout-container"></div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/golden-layout@2/dist/umd/index.js"></script>
|
||||
<script>
|
||||
// Dropdown functionality
|
||||
function toggleDropdown(menuId) {
|
||||
const menu = document.getElementById(menuId);
|
||||
const allMenus = document.querySelectorAll('.dropdown-menu');
|
||||
|
||||
allMenus.forEach(m => {
|
||||
if (m.id !== menuId) {
|
||||
m.classList.remove('show');
|
||||
}
|
||||
});
|
||||
|
||||
menu.classList.toggle('show');
|
||||
}
|
||||
|
||||
// Close dropdowns when clicking outside
|
||||
document.addEventListener('click', (e) => {
|
||||
if (!e.target.closest('.dropdown')) {
|
||||
document.querySelectorAll('.dropdown-menu').forEach(menu => {
|
||||
menu.classList.remove('show');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Simulate connection status
|
||||
let connected = false;
|
||||
function updateConnectionStatus() {
|
||||
const dot = document.getElementById('status-dot');
|
||||
const text = document.getElementById('status-text');
|
||||
|
||||
connected = !connected;
|
||||
if (connected) {
|
||||
dot.className = 'status-dot connected';
|
||||
text.textContent = 'Connected to Jibo';
|
||||
} else {
|
||||
dot.className = 'status-dot disconnected';
|
||||
text.textContent = 'Disconnected';
|
||||
}
|
||||
}
|
||||
|
||||
// Update connection status every 3 seconds for demo
|
||||
setInterval(updateConnectionStatus, 3000);
|
||||
|
||||
// Basic Timeline Initialization (without Theatre.js for now)
|
||||
function initializeTheatreTimeline(containerElement) {
|
||||
console.log('Initializing basic timeline...');
|
||||
|
||||
// Add playback controls
|
||||
const playBtn = containerElement.querySelector('#play-btn');
|
||||
const pauseBtn = containerElement.querySelector('#pause-btn');
|
||||
const stopBtn = containerElement.querySelector('#stop-btn');
|
||||
const timeDisplay = containerElement.querySelector('#time-display');
|
||||
const timelineContainer = containerElement.querySelector('#theatre-timeline');
|
||||
|
||||
let isPlaying = false;
|
||||
let startTime = 0;
|
||||
let currentTime = 0;
|
||||
let animationFrame = null;
|
||||
|
||||
// Create basic timeline visualization
|
||||
if (timelineContainer) {
|
||||
timelineContainer.innerHTML = `
|
||||
<div style="padding: 20px; height: 100%; background: #2d2d2d; border-radius: 4px; position: relative; overflow: hidden;">
|
||||
<div style="position: absolute; top: 20px; left: 20px; right: 20px; height: 2px; background: #444;">
|
||||
<div id="timeline-progress" style="width: 0%; height: 100%; background: #2196F3; transition: width 0.1s;"></div>
|
||||
</div>
|
||||
<div style="position: absolute; top: 40px; left: 20px; right: 20px; display: flex; justify-content: space-between; font-size: 10px; color: #666;">
|
||||
<span>0s</span>
|
||||
<span>1s</span>
|
||||
<span>2s</span>
|
||||
<span>3s</span>
|
||||
<span>4s</span>
|
||||
<span>5s</span>
|
||||
</div>
|
||||
<div style="position: absolute; top: 80px; left: 20px; right: 20px; bottom: 20px;">
|
||||
<div style="font-size: 12px; color: #ccc; margin-bottom: 10px;">Timeline Ready</div>
|
||||
<div style="background: #1e1e1e; padding: 10px; border-radius: 4px; font-size: 11px; color: #666;">
|
||||
Basic timeline component - Theatre.js integration pending
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
function updateTime() {
|
||||
if (isPlaying) {
|
||||
currentTime = (Date.now() - startTime) / 1000;
|
||||
timeDisplay.textContent = currentTime.toFixed(2) + 's';
|
||||
|
||||
// Update progress bar
|
||||
const progress = Math.min((currentTime / 5) * 100, 100); // 5 second timeline
|
||||
const progressBar = containerElement.querySelector('#timeline-progress');
|
||||
if (progressBar) {
|
||||
progressBar.style.width = progress + '%';
|
||||
}
|
||||
|
||||
animationFrame = requestAnimationFrame(updateTime);
|
||||
}
|
||||
}
|
||||
|
||||
if (playBtn) {
|
||||
playBtn.addEventListener('click', () => {
|
||||
if (!isPlaying) {
|
||||
isPlaying = true;
|
||||
startTime = Date.now() - (currentTime * 1000);
|
||||
updateTime();
|
||||
playBtn.style.background = '#666';
|
||||
pauseBtn.style.background = '#FF9800';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (pauseBtn) {
|
||||
pauseBtn.addEventListener('click', () => {
|
||||
isPlaying = false;
|
||||
if (animationFrame) {
|
||||
cancelAnimationFrame(animationFrame);
|
||||
}
|
||||
playBtn.style.background = '#4CAF50';
|
||||
pauseBtn.style.background = '#666';
|
||||
});
|
||||
}
|
||||
|
||||
if (stopBtn) {
|
||||
stopBtn.addEventListener('click', () => {
|
||||
isPlaying = false;
|
||||
currentTime = 0;
|
||||
startTime = Date.now();
|
||||
timeDisplay.textContent = '0.00s';
|
||||
|
||||
// Reset progress bar
|
||||
const progressBar = containerElement.querySelector('#timeline-progress');
|
||||
if (progressBar) {
|
||||
progressBar.style.width = '0%';
|
||||
}
|
||||
|
||||
if (animationFrame) {
|
||||
cancelAnimationFrame(animationFrame);
|
||||
}
|
||||
playBtn.style.background = '#4CAF50';
|
||||
pauseBtn.style.background = '#FF9800';
|
||||
});
|
||||
}
|
||||
|
||||
console.log('Basic timeline initialized successfully');
|
||||
}
|
||||
|
||||
// Initialize Golden Layout
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
// Wait for GoldenLayout to be available
|
||||
function waitForGoldenLayout() {
|
||||
if (typeof GoldenLayout === 'undefined') {
|
||||
console.log('GoldenLayout not yet available, retrying...');
|
||||
setTimeout(waitForGoldenLayout, 100);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('GoldenLayout found, initializing...');
|
||||
|
||||
const config = {
|
||||
root: {
|
||||
type: 'row',
|
||||
children: [
|
||||
{
|
||||
type: 'component',
|
||||
componentType: 'timeline',
|
||||
componentState: { title: 'Timeline' },
|
||||
title: 'Timeline',
|
||||
width: 30
|
||||
},
|
||||
{
|
||||
type: 'column',
|
||||
children: [
|
||||
{
|
||||
type: 'component',
|
||||
componentType: 'canvas',
|
||||
componentState: { title: 'Canvas' },
|
||||
title: 'Canvas',
|
||||
height: 60
|
||||
},
|
||||
{
|
||||
type: 'component',
|
||||
componentType: 'properties',
|
||||
componentState: { title: 'Properties' },
|
||||
title: 'Properties',
|
||||
height: 40
|
||||
}
|
||||
],
|
||||
width: 40
|
||||
},
|
||||
{
|
||||
type: 'column',
|
||||
children: [
|
||||
{
|
||||
type: 'component',
|
||||
componentType: 'library',
|
||||
componentState: { title: 'Animation Library' },
|
||||
title: 'Library',
|
||||
height: 50
|
||||
},
|
||||
{
|
||||
type: 'component',
|
||||
componentType: 'preview',
|
||||
componentState: { title: 'Preview' },
|
||||
title: 'Preview',
|
||||
height: 50
|
||||
}
|
||||
],
|
||||
width: 30
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
const componentRegistry = new GoldenLayout.ComponentRegistry();
|
||||
|
||||
componentRegistry.registerComponent('timeline', (container, state) => {
|
||||
container.element.innerHTML = `
|
||||
<div style="padding: 20px; color: white; height: 100%; overflow-y: auto;">
|
||||
<h3>${state.title}</h3>
|
||||
<div id="theatre-timeline" style="margin-top: 16px; height: 300px; background: #2d2d2d; border-radius: 4px; position: relative;"></div>
|
||||
<div id="theatre-controls" style="margin-top: 16px; display: flex; gap: 8px; align-items: center;">
|
||||
<button id="play-btn" style="background: #4CAF50; border: none; color: white; padding: 8px 16px; border-radius: 4px; cursor: pointer;">
|
||||
<span class="material-icons" style="font-size: 16px; vertical-align: middle;">play_arrow</span> Play
|
||||
</button>
|
||||
<button id="pause-btn" style="background: #FF9800; border: none; color: white; padding: 8px 16px; border-radius: 4px; cursor: pointer;">
|
||||
<span class="material-icons" style="font-size: 16px; vertical-align: middle;">pause</span> Pause
|
||||
</button>
|
||||
<button id="stop-btn" style="background: #f44336; border: none; color: white; padding: 8px 16px; border-radius: 4px; cursor: pointer;">
|
||||
<span class="material-icons" style="font-size: 16px; vertical-align: middle;">stop</span> Stop
|
||||
</button>
|
||||
<span style="margin-left: 16px; font-size: 12px; color: #ccc;">Time: <span id="time-display">0.00s</span></span>
|
||||
</div>
|
||||
<div style="margin-top: 16px;">
|
||||
<h4 style="margin-bottom: 8px; font-size: 14px; color: #ccc;">Animation Tracks</h4>
|
||||
<div id="tracks-list" style="background: #2d2d2d; padding: 12px; border-radius: 4px;">
|
||||
<div style="padding: 8px; margin-bottom: 4px; background: #1e1e1e; border-radius: 2px; font-size: 12px;">
|
||||
📍 Position Track
|
||||
</div>
|
||||
<div style="padding: 8px; margin-bottom: 4px; background: #1e1e1e; border-radius: 2px; font-size: 12px;">
|
||||
🎭 Animation Track
|
||||
</div>
|
||||
<div style="padding: 8px; margin-bottom: 4px; background: #1e1e1e; border-radius: 2px; font-size: 12px;">
|
||||
🎵 Audio Track
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Initialize Theatre.js timeline in this container
|
||||
setTimeout(() => {
|
||||
if (typeof Theatre !== 'undefined') {
|
||||
initializeTheatreTimeline(container.element);
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
|
||||
componentRegistry.registerComponent('canvas', (container, state) => {
|
||||
container.element.innerHTML = `
|
||||
<div style="padding: 20px; color: white; height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center;">
|
||||
<h3>${state.title}</h3>
|
||||
<div style="margin-top: 20px; width: 200px; height: 200px; background: #2d2d2d; border: 2px dashed #444; border-radius: 8px; display: flex; align-items: center; justify-content: center;">
|
||||
<span style="color: #666;">Animation Preview Area</span>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
|
||||
componentRegistry.registerComponent('properties', (container, state) => {
|
||||
container.element.innerHTML = `
|
||||
<div style="padding: 20px; color: white; height: 100%; overflow-y: auto;">
|
||||
<h3>${state.title}</h3>
|
||||
<div style="margin-top: 16px;">
|
||||
<div style="margin-bottom: 16px;">
|
||||
<label style="display: block; margin-bottom: 4px; font-size: 12px; color: #ccc;">Duration (ms)</label>
|
||||
<input type="number" value="1000" style="width: 100%; padding: 8px; background: #2d2d2d; border: 1px solid #444; border-radius: 4px; color: white;">
|
||||
</div>
|
||||
<div style="margin-bottom: 16px;">
|
||||
<label style="display: block; margin-bottom: 4px; font-size: 12px; color: #ccc;">Easing</label>
|
||||
<select style="width: 100%; padding: 8px; background: #2d2d2d; border: 1px solid #444; border-radius: 4px; color: white;">
|
||||
<option>Linear</option>
|
||||
<option>Ease In</option>
|
||||
<option>Ease Out</option>
|
||||
<option>Ease In Out</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
|
||||
componentRegistry.registerComponent('library', (container, state) => {
|
||||
container.element.innerHTML = `
|
||||
<div style="padding: 20px; color: white; height: 100%; overflow-y: auto;">
|
||||
<h3>${state.title}</h3>
|
||||
<div style="margin-top: 16px;">
|
||||
<div style="background: #2d2d2d; padding: 12px; border-radius: 4px; margin-bottom: 8px; cursor: pointer;">Eye Blink</div>
|
||||
<div style="background: #2d2d2d; padding: 12px; border-radius: 4px; margin-bottom: 8px; cursor: pointer;">Head Nod</div>
|
||||
<div style="background: #2d2d2d; padding: 12px; border-radius: 4px; margin-bottom: 8px; cursor: pointer;">Wave</div>
|
||||
<div style="background: #2d2d2d; padding: 12px; border-radius: 4px; margin-bottom: 8px; cursor: pointer;">Dance</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
|
||||
componentRegistry.registerComponent('preview', (container, state) => {
|
||||
container.element.innerHTML = `
|
||||
<div style="padding: 20px; color: white; height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center;">
|
||||
<h3>${state.title}</h3>
|
||||
<div style="margin-top: 20px; text-align: center;">
|
||||
<span class="material-icons" style="font-size: 48px; color: #666;">play_circle</span>
|
||||
<div style="margin-top: 8px; color: #666;">Click to preview</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
|
||||
const layout = new GoldenLayout(config, componentRegistry, document.querySelector('#layout-container'));
|
||||
layout.init();
|
||||
}
|
||||
|
||||
// Start the initialization process
|
||||
waitForGoldenLayout();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
40
public/golden-layout.js
Normal file
40
public/golden-layout.js
Normal file
@@ -0,0 +1,40 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.VirtualLayout = exports.StyleConstants = exports.EventHub = exports.EventEmitter = exports.LayoutManager = exports.Stack = exports.RowOrColumn = exports.ContentItem = exports.ComponentItem = exports.GoldenLayout = exports.Tab = exports.Header = exports.DragSource = exports.BrowserPopout = exports.ComponentContainer = void 0;
|
||||
const tslib_1 = require("tslib");
|
||||
tslib_1.__exportStar(require("./ts/config/config"), exports);
|
||||
tslib_1.__exportStar(require("./ts/config/resolved-config"), exports);
|
||||
var component_container_1 = require("./ts/container/component-container");
|
||||
Object.defineProperty(exports, "ComponentContainer", { enumerable: true, get: function () { return component_container_1.ComponentContainer; } });
|
||||
var browser_popout_1 = require("./ts/controls/browser-popout");
|
||||
Object.defineProperty(exports, "BrowserPopout", { enumerable: true, get: function () { return browser_popout_1.BrowserPopout; } });
|
||||
var drag_source_1 = require("./ts/controls/drag-source");
|
||||
Object.defineProperty(exports, "DragSource", { enumerable: true, get: function () { return drag_source_1.DragSource; } });
|
||||
var header_1 = require("./ts/controls/header");
|
||||
Object.defineProperty(exports, "Header", { enumerable: true, get: function () { return header_1.Header; } });
|
||||
var tab_1 = require("./ts/controls/tab");
|
||||
Object.defineProperty(exports, "Tab", { enumerable: true, get: function () { return tab_1.Tab; } });
|
||||
tslib_1.__exportStar(require("./ts/errors/external-error"), exports);
|
||||
var golden_layout_1 = require("./ts/golden-layout");
|
||||
Object.defineProperty(exports, "GoldenLayout", { enumerable: true, get: function () { return golden_layout_1.GoldenLayout; } });
|
||||
var component_item_1 = require("./ts/items/component-item");
|
||||
Object.defineProperty(exports, "ComponentItem", { enumerable: true, get: function () { return component_item_1.ComponentItem; } });
|
||||
var content_item_1 = require("./ts/items/content-item");
|
||||
Object.defineProperty(exports, "ContentItem", { enumerable: true, get: function () { return content_item_1.ContentItem; } });
|
||||
var row_or_column_1 = require("./ts/items/row-or-column");
|
||||
Object.defineProperty(exports, "RowOrColumn", { enumerable: true, get: function () { return row_or_column_1.RowOrColumn; } });
|
||||
var stack_1 = require("./ts/items/stack");
|
||||
Object.defineProperty(exports, "Stack", { enumerable: true, get: function () { return stack_1.Stack; } });
|
||||
var layout_manager_1 = require("./ts/layout-manager");
|
||||
Object.defineProperty(exports, "LayoutManager", { enumerable: true, get: function () { return layout_manager_1.LayoutManager; } });
|
||||
var event_emitter_1 = require("./ts/utils/event-emitter");
|
||||
Object.defineProperty(exports, "EventEmitter", { enumerable: true, get: function () { return event_emitter_1.EventEmitter; } });
|
||||
var event_hub_1 = require("./ts/utils/event-hub");
|
||||
Object.defineProperty(exports, "EventHub", { enumerable: true, get: function () { return event_hub_1.EventHub; } });
|
||||
tslib_1.__exportStar(require("./ts/utils/i18n-strings"), exports);
|
||||
var style_constants_1 = require("./ts/utils/style-constants");
|
||||
Object.defineProperty(exports, "StyleConstants", { enumerable: true, get: function () { return style_constants_1.StyleConstants; } });
|
||||
tslib_1.__exportStar(require("./ts/utils/types"), exports);
|
||||
var virtual_layout_1 = require("./ts/virtual-layout");
|
||||
Object.defineProperty(exports, "VirtualLayout", { enumerable: true, get: function () { return virtual_layout_1.VirtualLayout; } });
|
||||
//# sourceMappingURL=index.js.map
|
||||
319
public/goldenlayout-base.css
Normal file
319
public/goldenlayout-base.css
Normal file
@@ -0,0 +1,319 @@
|
||||
.lm_root {
|
||||
position: relative;
|
||||
}
|
||||
.lm_row > .lm_item {
|
||||
float: left;
|
||||
}
|
||||
.lm_content {
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
.lm_dragging,
|
||||
.lm_dragging * {
|
||||
cursor: move !important;
|
||||
-webkit-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
.lm_maximised {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 40;
|
||||
}
|
||||
.lm_maximise_placeholder {
|
||||
display: none;
|
||||
}
|
||||
.lm_splitter {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
touch-action: none;
|
||||
}
|
||||
.lm_splitter.lm_vertical .lm_drag_handle {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
cursor: ns-resize;
|
||||
touch-action: none;
|
||||
-webkit-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
.lm_splitter.lm_horizontal {
|
||||
float: left;
|
||||
height: 100%;
|
||||
}
|
||||
.lm_splitter.lm_horizontal .lm_drag_handle {
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
cursor: ew-resize;
|
||||
touch-action: none;
|
||||
-webkit-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
.lm_header {
|
||||
overflow: visible;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
-webkit-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
.lm_header [class^=lm_] {
|
||||
box-sizing: content-box !important;
|
||||
}
|
||||
.lm_header .lm_controls {
|
||||
position: absolute;
|
||||
right: 3px;
|
||||
display: flex;
|
||||
}
|
||||
.lm_header .lm_controls > * {
|
||||
cursor: pointer;
|
||||
float: left;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
text-align: center;
|
||||
}
|
||||
.lm_header .lm_tabs {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
}
|
||||
.lm_header .lm_tab {
|
||||
cursor: pointer;
|
||||
float: left;
|
||||
height: 14px;
|
||||
margin-top: 1px;
|
||||
padding: 0px 10px 5px;
|
||||
padding-right: 25px;
|
||||
position: relative;
|
||||
touch-action: none;
|
||||
}
|
||||
.lm_header .lm_tab i {
|
||||
width: 2px;
|
||||
height: 19px;
|
||||
position: absolute;
|
||||
}
|
||||
.lm_header .lm_tab i.lm_left {
|
||||
top: 0;
|
||||
left: -2px;
|
||||
}
|
||||
.lm_header .lm_tab i.lm_right {
|
||||
top: 0;
|
||||
right: -2px;
|
||||
}
|
||||
.lm_header .lm_tab .lm_title {
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.lm_header .lm_tab .lm_close_tab {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
text-align: center;
|
||||
}
|
||||
.lm_stack {
|
||||
position: relative;
|
||||
}
|
||||
.lm_stack > .lm_items {
|
||||
overflow: hidden;
|
||||
}
|
||||
.lm_stack.lm_left > .lm_items {
|
||||
position: absolute;
|
||||
left: 20px;
|
||||
top: 0;
|
||||
}
|
||||
.lm_stack.lm_right > .lm_items {
|
||||
position: absolute;
|
||||
right: 20px;
|
||||
top: 0;
|
||||
}
|
||||
.lm_stack.lm_right > .lm_header {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
}
|
||||
.lm_stack.lm_bottom > .lm_items {
|
||||
position: absolute;
|
||||
bottom: 20px;
|
||||
}
|
||||
.lm_stack.lm_bottom > .lm_header {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
}
|
||||
.lm_left.lm_stack .lm_header,
|
||||
.lm_right.lm_stack .lm_header {
|
||||
height: 100%;
|
||||
}
|
||||
.lm_left.lm_dragProxy .lm_header,
|
||||
.lm_right.lm_dragProxy .lm_header,
|
||||
.lm_left.lm_dragProxy .lm_items,
|
||||
.lm_right.lm_dragProxy .lm_items {
|
||||
float: left;
|
||||
}
|
||||
.lm_left.lm_dragProxy .lm_header,
|
||||
.lm_right.lm_dragProxy .lm_header,
|
||||
.lm_left.lm_stack .lm_header,
|
||||
.lm_right.lm_stack .lm_header {
|
||||
width: 20px;
|
||||
vertical-align: top;
|
||||
}
|
||||
.lm_left.lm_dragProxy .lm_header .lm_tabs,
|
||||
.lm_right.lm_dragProxy .lm_header .lm_tabs,
|
||||
.lm_left.lm_stack .lm_header .lm_tabs,
|
||||
.lm_right.lm_stack .lm_header .lm_tabs {
|
||||
transform-origin: left top;
|
||||
top: 0;
|
||||
width: 1000px;
|
||||
/*hack*/
|
||||
}
|
||||
.lm_left.lm_dragProxy .lm_header .lm_controls,
|
||||
.lm_right.lm_dragProxy .lm_header .lm_controls,
|
||||
.lm_left.lm_stack .lm_header .lm_controls,
|
||||
.lm_right.lm_stack .lm_header .lm_controls {
|
||||
bottom: 0;
|
||||
flex-flow: column;
|
||||
}
|
||||
.lm_dragProxy.lm_left .lm_header .lm_tabs,
|
||||
.lm_stack.lm_left .lm_header .lm_tabs {
|
||||
transform: rotate(-90deg) scaleX(-1);
|
||||
left: 0;
|
||||
}
|
||||
.lm_dragProxy.lm_left .lm_header .lm_tabs .lm_tab,
|
||||
.lm_stack.lm_left .lm_header .lm_tabs .lm_tab {
|
||||
transform: scaleX(-1);
|
||||
margin-top: 1px;
|
||||
}
|
||||
.lm_dragProxy.lm_left .lm_header .lm_tabdropdown_list,
|
||||
.lm_stack.lm_left .lm_header .lm_tabdropdown_list {
|
||||
top: initial;
|
||||
right: initial;
|
||||
left: 20px;
|
||||
}
|
||||
.lm_dragProxy.lm_right .lm_content {
|
||||
float: left;
|
||||
}
|
||||
.lm_dragProxy.lm_right .lm_header .lm_tabs,
|
||||
.lm_stack.lm_right .lm_header .lm_tabs {
|
||||
transform: rotate(90deg) scaleX(1);
|
||||
left: 100%;
|
||||
margin-left: 0;
|
||||
}
|
||||
.lm_dragProxy.lm_right .lm_header .lm_controls,
|
||||
.lm_stack.lm_right .lm_header .lm_controls {
|
||||
left: 3px;
|
||||
}
|
||||
.lm_dragProxy.lm_right .lm_header .lm_tabdropdown_list,
|
||||
.lm_stack.lm_right .lm_header .lm_tabdropdown_list {
|
||||
top: initial;
|
||||
right: 20px;
|
||||
}
|
||||
.lm_dragProxy.lm_bottom .lm_header,
|
||||
.lm_stack.lm_bottom .lm_header {
|
||||
width: 100%;
|
||||
}
|
||||
.lm_dragProxy.lm_bottom .lm_header .lm_tab,
|
||||
.lm_stack.lm_bottom .lm_header .lm_tab {
|
||||
margin-top: 0;
|
||||
border-top: none;
|
||||
}
|
||||
.lm_dragProxy.lm_bottom .lm_header .lm_controls,
|
||||
.lm_stack.lm_bottom .lm_header .lm_controls {
|
||||
top: 3px;
|
||||
}
|
||||
.lm_dragProxy.lm_bottom .lm_header .lm_tabdropdown_list,
|
||||
.lm_stack.lm_bottom .lm_header .lm_tabdropdown_list {
|
||||
top: initial;
|
||||
bottom: 20px;
|
||||
}
|
||||
.lm_drop_tab_placeholder {
|
||||
float: left;
|
||||
width: 100px;
|
||||
visibility: hidden;
|
||||
}
|
||||
.lm_header .lm_controls .lm_tabdropdown:before {
|
||||
content: '';
|
||||
width: 0;
|
||||
height: 0;
|
||||
vertical-align: middle;
|
||||
display: inline-block;
|
||||
border-top: 5px dashed;
|
||||
border-right: 5px solid transparent;
|
||||
border-left: 5px solid transparent;
|
||||
color: white;
|
||||
}
|
||||
.lm_header .lm_tabdropdown_list {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
right: 0;
|
||||
z-index: 5;
|
||||
overflow: hidden;
|
||||
}
|
||||
.lm_header .lm_tabdropdown_list .lm_tab {
|
||||
clear: both;
|
||||
padding-right: 10px;
|
||||
margin: 0;
|
||||
}
|
||||
.lm_header .lm_tabdropdown_list .lm_tab .lm_title {
|
||||
width: 100px;
|
||||
}
|
||||
.lm_header .lm_tabdropdown_list .lm_close_tab {
|
||||
display: none !important;
|
||||
}
|
||||
/***********************************
|
||||
* Drag Proxy
|
||||
***********************************/
|
||||
.lm_dragProxy {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 30;
|
||||
}
|
||||
.lm_dragProxy .lm_header {
|
||||
background: transparent;
|
||||
}
|
||||
.lm_dragProxy .lm_content {
|
||||
border-top: none;
|
||||
overflow: hidden;
|
||||
}
|
||||
.lm_dropTargetIndicator {
|
||||
display: none;
|
||||
position: absolute;
|
||||
z-index: 35;
|
||||
transition: all 200ms ease;
|
||||
}
|
||||
.lm_dropTargetIndicator .lm_inner {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
.lm_transition_indicator {
|
||||
display: none;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 20;
|
||||
}
|
||||
.lm_popin {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
z-index: 9999;
|
||||
}
|
||||
.lm_popin > * {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
.lm_popin > .lm_bg {
|
||||
z-index: 10;
|
||||
}
|
||||
.lm_popin > .lm_icon {
|
||||
z-index: 20;
|
||||
}
|
||||
139
public/goldenlayout-dark-theme.css
Normal file
139
public/goldenlayout-dark-theme.css
Normal file
@@ -0,0 +1,139 @@
|
||||
.lm_goldenlayout {
|
||||
background: #000000;
|
||||
}
|
||||
.lm_content {
|
||||
background: #222222;
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
.lm_dragProxy .lm_content {
|
||||
box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.9);
|
||||
}
|
||||
.lm_dropTargetIndicator {
|
||||
box-shadow: inset 0 0 30px #000000;
|
||||
outline: 1px dashed #cccccc;
|
||||
}
|
||||
.lm_dropTargetIndicator .lm_inner {
|
||||
background: #000000;
|
||||
opacity: 0.2;
|
||||
}
|
||||
.lm_splitter {
|
||||
background: #000000;
|
||||
opacity: 0.001;
|
||||
transition: opacity 200ms ease;
|
||||
}
|
||||
.lm_splitter:hover,
|
||||
.lm_splitter.lm_dragging {
|
||||
background: #444444;
|
||||
opacity: 1;
|
||||
}
|
||||
.lm_header {
|
||||
height: 20px;
|
||||
}
|
||||
.lm_header .lm_tab {
|
||||
font-family: Arial, sans-serif;
|
||||
font-size: 12px;
|
||||
color: #999999;
|
||||
background: #111111;
|
||||
box-shadow: 2px -2px 2px rgba(0, 0, 0, 0.3);
|
||||
margin-right: 2px;
|
||||
padding-bottom: 2px;
|
||||
padding-top: 2px;
|
||||
/*.lm_title // Present in LIGHT Theme
|
||||
{
|
||||
padding-top:1px;
|
||||
}*/
|
||||
}
|
||||
.lm_header .lm_tab .lm_close_tab {
|
||||
width: 11px;
|
||||
height: 11px;
|
||||
background-image: url('../../img/lm_close_white.png');
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
top: 4px;
|
||||
right: 6px;
|
||||
opacity: 0.4;
|
||||
}
|
||||
.lm_header .lm_tab .lm_close_tab:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
.lm_header .lm_tab.lm_active {
|
||||
border-bottom: none;
|
||||
box-shadow: 0 -2px 2px #000000;
|
||||
padding-bottom: 3px;
|
||||
}
|
||||
.lm_header .lm_tab.lm_active .lm_close_tab {
|
||||
opacity: 1;
|
||||
}
|
||||
.lm_header .lm_tab.lm_active.lm_focused {
|
||||
background-color: #354be3;
|
||||
}
|
||||
.lm_dragProxy.lm_right .lm_header .lm_tab.lm_active,
|
||||
.lm_stack.lm_right .lm_header .lm_tab.lm_active {
|
||||
box-shadow: 2px -2px 2px #000000;
|
||||
}
|
||||
.lm_dragProxy.lm_bottom .lm_header .lm_tab,
|
||||
.lm_stack.lm_bottom .lm_header .lm_tab {
|
||||
box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
.lm_dragProxy.lm_bottom .lm_header .lm_tab.lm_active,
|
||||
.lm_stack.lm_bottom .lm_header .lm_tab.lm_active {
|
||||
box-shadow: 0 2px 2px #000000;
|
||||
}
|
||||
.lm_selected .lm_header {
|
||||
background-color: #452500;
|
||||
}
|
||||
.lm_tab:hover,
|
||||
.lm_tab.lm_active {
|
||||
background: #222222;
|
||||
color: #dddddd;
|
||||
}
|
||||
.lm_header .lm_controls .lm_tabdropdown:before {
|
||||
color: #ffffff;
|
||||
}
|
||||
.lm_controls > * {
|
||||
position: relative;
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
opacity: 0.4;
|
||||
transition: opacity 300ms ease;
|
||||
}
|
||||
.lm_controls > *:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
.lm_controls .lm_popout {
|
||||
background-image: url('../../img/lm_popout_white.png');
|
||||
}
|
||||
.lm_controls .lm_maximise {
|
||||
background-image: url('../../img/lm_maximise_white.png');
|
||||
}
|
||||
.lm_controls .lm_close {
|
||||
background-image: url('../../img/lm_close_white.png');
|
||||
}
|
||||
.lm_maximised .lm_header {
|
||||
background-color: #000000;
|
||||
}
|
||||
.lm_maximised .lm_controls .lm_maximise {
|
||||
background-image: url('../../img/lm_minimize_white.png');
|
||||
}
|
||||
.lm_transition_indicator {
|
||||
background-color: #000000;
|
||||
border: 1px dashed #555555;
|
||||
}
|
||||
.lm_popin {
|
||||
cursor: pointer;
|
||||
}
|
||||
.lm_popin .lm_bg {
|
||||
background: #ffffff;
|
||||
opacity: 0.3;
|
||||
}
|
||||
.lm_popin .lm_icon {
|
||||
background-image: url('../../img/lm_popin_white.png');
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
border-left: 1px solid #eeeeee;
|
||||
border-top: 1px solid #eeeeee;
|
||||
opacity: 0.7;
|
||||
}
|
||||
.lm_popin:hover .lm_icon {
|
||||
opacity: 1;
|
||||
}
|
||||
0
public/theatre-core-umd.js
Normal file
0
public/theatre-core-umd.js
Normal file
6597
public/theatre-core.js
Normal file
6597
public/theatre-core.js
Normal file
File diff suppressed because it is too large
Load Diff
105
public/theatre-studio.js
Normal file
105
public/theatre-studio.js
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user