@juuno-sdk/cli 1.0.8 → 1.0.11
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 +80 -41
- package/bin/cli.js +62 -36
- package/dist/assets/main-B2BPnfea.js +1 -0
- package/dist/assets/main-Bf2N9gBQ.js +1 -0
- package/dist/assets/main-Bo8Yyr87.js +1 -0
- package/dist/assets/main-C3hW0d-b.css +1 -0
- package/dist/assets/main-C6ZAJydH.js +1 -0
- package/dist/assets/main-CCYNXtGp.css +1 -0
- package/dist/assets/main-CnpUG-52.js +1 -0
- package/dist/assets/main-D0353jp3.js +1 -0
- package/dist/assets/main-D7UD6CXw.css +1 -0
- package/dist/assets/main-DC3n4QV-.css +1 -0
- package/dist/assets/main-DWrNgA-L.js +1 -0
- package/dist/assets/main-HbFBqUMx.js +1 -0
- package/dist/assets/main-jQYqLcLk.js +1 -0
- package/dist/assets/main-n0Bs5Mcx.css +1 -0
- package/dist/cli/src/deploy/index.d.ts.map +1 -1
- package/dist/cli/src/deploy/index.js +84 -9
- package/dist/cli/src/dev/index.d.ts +24 -0
- package/dist/cli/src/dev/index.d.ts.map +1 -0
- package/dist/cli/src/dev/index.js +197 -0
- package/dist/cli/src/monorepo/index.d.ts +37 -0
- package/dist/cli/src/monorepo/index.d.ts.map +1 -0
- package/dist/cli/src/monorepo/index.js +94 -0
- package/dist/cli/src/simulator/index.d.ts +18 -7
- package/dist/cli/src/simulator/index.d.ts.map +1 -1
- package/dist/cli/src/simulator/index.js +47 -21
- package/dist/cli/src/utils/fs.d.ts +12 -0
- package/dist/cli/src/utils/fs.d.ts.map +1 -0
- package/dist/cli/src/utils/fs.js +29 -0
- package/dist/cli/tsconfig.build.tsbuildinfo +1 -1
- package/dist/index.html +2 -2
- package/package.json +12 -11
package/README.md
CHANGED
|
@@ -19,16 +19,45 @@ npm install --save-dev @juuno-sdk/cli
|
|
|
19
19
|
|
|
20
20
|
## Commands
|
|
21
21
|
|
|
22
|
-
###
|
|
22
|
+
### Development: Unified Dev Command (Recommended)
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
The easiest way to develop your app - just run one command from your app directory:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
cd my-juuno-app
|
|
28
|
+
npx juuno-cli dev
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
This automatically:
|
|
32
|
+
|
|
33
|
+
1. Detects your app structure (Vite config, package.json)
|
|
34
|
+
2. Starts the Vite dev server with HMR (Hot Module Replacement)
|
|
35
|
+
3. Launches the simulator pointing to the dev server
|
|
36
|
+
|
|
37
|
+
**Output:**
|
|
38
|
+
|
|
39
|
+
```text
|
|
40
|
+
🔍 Detecting app structure...
|
|
41
|
+
|
|
42
|
+
Package manager: pnpm
|
|
43
|
+
Vite config: found
|
|
44
|
+
Dev server: http://localhost:3000
|
|
45
|
+
|
|
46
|
+
🚀 Starting Vite dev server...
|
|
47
|
+
⏳ Waiting for Vite dev server...
|
|
48
|
+
✅ Vite dev server ready at http://localhost:3000
|
|
49
|
+
|
|
50
|
+
🎮 Starting simulator...
|
|
51
|
+
🌍 Simulator: http://localhost:5004
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Manual Mode: Point to External URL
|
|
55
|
+
|
|
56
|
+
If you prefer to manage the build and server yourself:
|
|
25
57
|
|
|
26
58
|
```bash
|
|
27
59
|
# Point to your dev server
|
|
28
60
|
npx juuno-cli dev --app http://localhost:3000
|
|
29
|
-
|
|
30
|
-
# Or point to a deployed URL
|
|
31
|
-
npx juuno-cli dev --app https://cdn.example.com/my-app/
|
|
32
61
|
```
|
|
33
62
|
|
|
34
63
|
### Authentication
|
|
@@ -83,9 +112,8 @@ Add to your `package.json`:
|
|
|
83
112
|
```json
|
|
84
113
|
{
|
|
85
114
|
"scripts": {
|
|
86
|
-
"dev": "
|
|
115
|
+
"dev": "juuno-cli dev",
|
|
87
116
|
"build": "vite build",
|
|
88
|
-
"test:player": "juuno-cli dev --app http://localhost:3000",
|
|
89
117
|
"deploy": "juuno-cli deploy"
|
|
90
118
|
}
|
|
91
119
|
}
|
|
@@ -97,12 +125,9 @@ Then run:
|
|
|
97
125
|
# One-time setup: Login to Juuno
|
|
98
126
|
npx juuno-cli login
|
|
99
127
|
|
|
100
|
-
#
|
|
128
|
+
# Start development (one command does everything!)
|
|
101
129
|
npm run dev
|
|
102
130
|
|
|
103
|
-
# Terminal 2: Simulator
|
|
104
|
-
npm run test:player
|
|
105
|
-
|
|
106
131
|
# Deploy to production
|
|
107
132
|
npm run build
|
|
108
133
|
npm run deploy
|
|
@@ -110,10 +135,10 @@ npm run deploy
|
|
|
110
135
|
|
|
111
136
|
## How It Works
|
|
112
137
|
|
|
113
|
-
1. **Your App**:
|
|
138
|
+
1. **Your App**: Served by Vite dev server (e.g., `localhost:3000`) with HMR
|
|
114
139
|
2. **Simulator**: Loads at `localhost:5004`
|
|
115
140
|
3. **Import Maps**: Simulator loads your app via ES module import
|
|
116
|
-
4. **
|
|
141
|
+
4. **HMR**: Vite's Hot Module Replacement provides instant updates without full page reloads
|
|
117
142
|
|
|
118
143
|
## Requirements
|
|
119
144
|
|
|
@@ -121,15 +146,26 @@ Your app must:
|
|
|
121
146
|
|
|
122
147
|
- Export ES modules
|
|
123
148
|
- Provide player and config components
|
|
124
|
-
-
|
|
149
|
+
- Use `@juuno/vite-plugin-app-dev` for development:
|
|
150
|
+
|
|
125
151
|
```js
|
|
126
152
|
// vite.config.ts
|
|
153
|
+
import { defineConfig } from 'vite';
|
|
154
|
+
import vue from '@vitejs/plugin-vue';
|
|
155
|
+
import { juunoAppDev } from '@juuno/vite-plugin-app-dev';
|
|
156
|
+
|
|
127
157
|
export default {
|
|
158
|
+
plugins: [
|
|
159
|
+
vue(),
|
|
160
|
+
juunoAppDev(), // Enables dev server entry point routing
|
|
161
|
+
],
|
|
128
162
|
build: {
|
|
129
163
|
lib: {
|
|
130
|
-
entry:
|
|
164
|
+
entry: {
|
|
165
|
+
player: './src/player/index.ts',
|
|
166
|
+
config: './src/config/index.ts',
|
|
167
|
+
},
|
|
131
168
|
formats: ['es'],
|
|
132
|
-
fileName: 'index',
|
|
133
169
|
},
|
|
134
170
|
rollupOptions: {
|
|
135
171
|
external: ['vue', '@juuno-sdk/app-sdk'],
|
|
@@ -140,51 +176,54 @@ Your app must:
|
|
|
140
176
|
|
|
141
177
|
## Development Workflow
|
|
142
178
|
|
|
143
|
-
|
|
179
|
+
### Recommended: Unified Dev Command
|
|
144
180
|
|
|
145
|
-
|
|
181
|
+
The simplest workflow - one command handles everything:
|
|
146
182
|
|
|
147
183
|
```bash
|
|
148
184
|
cd my-juuno-app
|
|
149
|
-
|
|
150
|
-
# Watches for changes and rebuilds automatically
|
|
185
|
+
npx juuno-cli dev
|
|
151
186
|
```
|
|
152
187
|
|
|
153
|
-
**
|
|
188
|
+
**Development Flow:**
|
|
154
189
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
# Serves the built bundle at localhost:3000
|
|
159
|
-
```
|
|
190
|
+
1. Edit your app's source code
|
|
191
|
+
2. Vite's HMR instantly updates the browser (no full page reload!)
|
|
192
|
+
3. See changes reflected in the simulator immediately
|
|
160
193
|
|
|
161
|
-
|
|
194
|
+
### Alternative: Manual Mode
|
|
162
195
|
|
|
163
|
-
|
|
164
|
-
npx juuno-cli dev --app http://localhost:3000/index.js
|
|
165
|
-
# → localhost:5004
|
|
166
|
-
```
|
|
196
|
+
If you prefer more control, you can point the simulator to your own dev server:
|
|
167
197
|
|
|
168
|
-
|
|
198
|
+
```bash
|
|
199
|
+
# Start your own dev server
|
|
200
|
+
cd my-juuno-app
|
|
201
|
+
npm run dev # or: npx vite
|
|
169
202
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
4. See changes reflected in the simulator
|
|
203
|
+
# In another terminal, start the simulator pointing to your server
|
|
204
|
+
npx juuno-cli dev --app http://localhost:3000
|
|
205
|
+
```
|
|
174
206
|
|
|
175
|
-
**Note:**
|
|
207
|
+
**Note:** For the best experience, use `@juuno/vite-plugin-app-dev` in your Vite config to enable proper entry point routing during development.
|
|
176
208
|
|
|
177
209
|
## CLI Options
|
|
178
210
|
|
|
179
|
-
###
|
|
211
|
+
### Dev Command
|
|
180
212
|
|
|
181
213
|
```bash
|
|
182
214
|
juuno-cli dev [options]
|
|
183
215
|
|
|
216
|
+
# Unified mode (recommended) - run from your app directory:
|
|
217
|
+
juuno-cli dev
|
|
218
|
+
|
|
219
|
+
# Manual mode - point to external URL:
|
|
220
|
+
juuno-cli dev --app <url>
|
|
221
|
+
|
|
184
222
|
Options:
|
|
185
|
-
--app <url>
|
|
186
|
-
--port <number>
|
|
187
|
-
--
|
|
223
|
+
--app <url> URL of external app (omit for unified mode)
|
|
224
|
+
--port <number> Port for simulator (default: 5004)
|
|
225
|
+
--serve-port <number> Port for Vite dev server in unified mode (default: 3000)
|
|
226
|
+
--help Show help
|
|
188
227
|
```
|
|
189
228
|
|
|
190
229
|
### Login Command
|
package/bin/cli.js
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Juuno CLI - Official CLI for Juuno external app development.
|
|
5
|
+
*
|
|
6
|
+
* Usage: npx juuno-cli <command> [options]
|
|
7
|
+
*
|
|
8
|
+
* For development, run `pnpm build` first to compile TypeScript.
|
|
9
|
+
*/
|
|
10
|
+
|
|
3
11
|
import { fileURLToPath } from 'url';
|
|
4
12
|
import { dirname, join } from 'path';
|
|
5
13
|
import { runCommand } from './cli-router.js';
|
|
@@ -7,13 +15,10 @@ import { runCommand } from './cli-router.js';
|
|
|
7
15
|
const __filename = fileURLToPath(import.meta.url);
|
|
8
16
|
const __dirname = dirname(__filename);
|
|
9
17
|
|
|
10
|
-
// Parse command line arguments.
|
|
11
18
|
const args = process.argv.slice(2);
|
|
12
|
-
|
|
13
|
-
// Check if first argument is a command.
|
|
14
19
|
const command = args[0];
|
|
15
20
|
|
|
16
|
-
//
|
|
21
|
+
// --- Help Command ---
|
|
17
22
|
if (args.includes('--help') || args.includes('-h') || command === 'help') {
|
|
18
23
|
console.log(`
|
|
19
24
|
Juuno CLI - Official CLI for Juuno external app development
|
|
@@ -25,7 +30,7 @@ Commands:
|
|
|
25
30
|
login Authenticate with Juuno
|
|
26
31
|
logout Remove stored credentials
|
|
27
32
|
whoami Show authentication status
|
|
28
|
-
dev Launch the app simulator
|
|
33
|
+
dev Launch the app simulator
|
|
29
34
|
deploy Deploy your app to Juuno
|
|
30
35
|
list List your deployed apps
|
|
31
36
|
info <app-id> Show detailed information about an app
|
|
@@ -42,9 +47,18 @@ Authentication Commands:
|
|
|
42
47
|
whoami
|
|
43
48
|
Show current authentication status.
|
|
44
49
|
|
|
50
|
+
Dev Command (Unified Workflow):
|
|
51
|
+
juuno-cli dev
|
|
52
|
+
Auto-detects app, starts Vite dev server with HMR, and launches simulator.
|
|
53
|
+
Run from your app directory - no arguments needed!
|
|
54
|
+
|
|
55
|
+
juuno-cli dev --app <url>
|
|
56
|
+
Manual mode: point to an external app URL.
|
|
57
|
+
|
|
45
58
|
Simulator Options:
|
|
46
|
-
--app <url>
|
|
47
|
-
--port <number>
|
|
59
|
+
--app <url> URL of your external app (omit for auto mode)
|
|
60
|
+
--port <number> Port for simulator (default: 5004)
|
|
61
|
+
--serve-port <number> Port for Vite dev server in auto mode (default: 3000)
|
|
48
62
|
|
|
49
63
|
Deploy Options:
|
|
50
64
|
--build-dir <dir> Build directory to deploy (default: ./dist)
|
|
@@ -64,7 +78,11 @@ Examples:
|
|
|
64
78
|
# Authenticate (one-time setup)
|
|
65
79
|
juuno-cli login
|
|
66
80
|
|
|
67
|
-
# Start
|
|
81
|
+
# Start unified dev environment (recommended)
|
|
82
|
+
cd my-juuno-app
|
|
83
|
+
juuno-cli dev
|
|
84
|
+
|
|
85
|
+
# Manual mode: point to external app URL
|
|
68
86
|
juuno-cli dev --app http://localhost:3000
|
|
69
87
|
|
|
70
88
|
# Deploy app (uses saved credentials)
|
|
@@ -86,7 +104,7 @@ Examples:
|
|
|
86
104
|
process.exit(0);
|
|
87
105
|
}
|
|
88
106
|
|
|
89
|
-
//
|
|
107
|
+
// --- Auth/Deploy/List/Info Commands ---
|
|
90
108
|
if (
|
|
91
109
|
command === 'login' ||
|
|
92
110
|
command === 'logout' ||
|
|
@@ -99,34 +117,42 @@ if (
|
|
|
99
117
|
process.exit(exitCode);
|
|
100
118
|
}
|
|
101
119
|
|
|
102
|
-
//
|
|
103
|
-
|
|
104
|
-
let simulatorArgs = args;
|
|
120
|
+
// --- Dev/Simulator Command ---
|
|
121
|
+
let devArgs = args;
|
|
105
122
|
if (command === 'dev') {
|
|
106
|
-
|
|
123
|
+
devArgs = args.slice(1);
|
|
107
124
|
}
|
|
108
125
|
|
|
109
|
-
const appUrlIndex =
|
|
110
|
-
const portIndex =
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
126
|
+
const appUrlIndex = devArgs.indexOf('--app');
|
|
127
|
+
const portIndex = devArgs.indexOf('--port');
|
|
128
|
+
const servePortIndex = devArgs.indexOf('--serve-port');
|
|
129
|
+
|
|
130
|
+
const simulatorDistPath = join(__dirname, '..', 'dist');
|
|
131
|
+
|
|
132
|
+
if (appUrlIndex !== -1) {
|
|
133
|
+
// Manual mode: user provided --app URL.
|
|
134
|
+
const appUrl = devArgs[appUrlIndex + 1];
|
|
135
|
+
const port = portIndex !== -1 ? devArgs[portIndex + 1] : '5004';
|
|
136
|
+
|
|
137
|
+
if (!appUrl) {
|
|
138
|
+
console.error('Error: --app parameter requires a URL value');
|
|
139
|
+
process.exit(1);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const { launchSimulator } = await import(
|
|
143
|
+
'../dist/cli/src/simulator/index.js'
|
|
144
|
+
);
|
|
145
|
+
launchSimulator(appUrl, port, simulatorDistPath);
|
|
146
|
+
} else {
|
|
147
|
+
// Unified dev mode: auto-detect app and start everything.
|
|
148
|
+
const simulatorPort = portIndex !== -1 ? devArgs[portIndex + 1] : '5004';
|
|
149
|
+
const servePort =
|
|
150
|
+
servePortIndex !== -1 ? devArgs[servePortIndex + 1] : '3000';
|
|
151
|
+
|
|
152
|
+
const { runDev } = await import('../dist/cli/src/dev/index.js');
|
|
153
|
+
await runDev({
|
|
154
|
+
simulatorPort,
|
|
155
|
+
servePort,
|
|
156
|
+
simulatorDistPath,
|
|
157
|
+
});
|
|
117
158
|
}
|
|
118
|
-
|
|
119
|
-
const appUrl = simulatorArgs[appUrlIndex + 1];
|
|
120
|
-
const port = portIndex !== -1 ? simulatorArgs[portIndex + 1] : '5004';
|
|
121
|
-
|
|
122
|
-
if (!appUrl) {
|
|
123
|
-
console.error('Error: --app parameter requires a URL value');
|
|
124
|
-
process.exit(1);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// Path to the built dist directory.
|
|
128
|
-
const distPath = join(__dirname, '..', 'dist');
|
|
129
|
-
|
|
130
|
-
// Launch simulator (imports from built JS).
|
|
131
|
-
const { launchSimulator } = await import('../dist/cli/src/simulator/index.js');
|
|
132
|
-
launchSimulator(appUrl, port, distPath);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{defineComponent as V,ref as w,computed as M,onMounted as j,onUnmounted as D,createElementBlock as d,openBlock as r,normalizeClass as m,createElementVNode as e,createCommentVNode as A,toDisplayString as _,createTextVNode as O,withDirectives as R,createBlock as $,resolveDynamicComponent as U,vShow as B,shallowRef as T,reactive as I,unref as J,markRaw as P,createApp as q}from"vue";import{provideAppConfigContext as z}from"@juuno-sdk/app-sdk";(function(){const y=document.createElement("link").relList;if(y&&y.supports&&y.supports("modulepreload"))return;for(const o of document.querySelectorAll('link[rel="modulepreload"]'))b(o);new MutationObserver(o=>{for(const l of o)if(l.type==="childList")for(const n of l.addedNodes)n.tagName==="LINK"&&n.rel==="modulepreload"&&b(n)}).observe(document,{childList:!0,subtree:!0});function h(o){const l={};return o.integrity&&(l.integrity=o.integrity),o.referrerPolicy&&(l.referrerPolicy=o.referrerPolicy),o.crossOrigin==="use-credentials"?l.credentials="include":o.crossOrigin==="anonymous"?l.credentials="omit":l.credentials="same-origin",l}function b(o){if(o.ep)return;o.ep=!0;const l=h(o);fetch(o.href,l)}})();const H="modulepreload",W=function(a){return"/"+a},N={},F=function(y,h,b){let o=Promise.resolve();if(h&&h.length>0){let n=function(s){return Promise.all(s.map(p=>Promise.resolve(p).then(x=>({status:"fulfilled",value:x}),x=>({status:"rejected",reason:x}))))};document.getElementsByTagName("link");const i=document.querySelector("meta[property=csp-nonce]"),f=(i==null?void 0:i.nonce)||(i==null?void 0:i.getAttribute("nonce"));o=n(h.map(s=>{if(s=W(s),s in N)return;N[s]=!0;const p=s.endsWith(".css"),x=p?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${s}"]${x}`))return;const k=document.createElement("link");if(k.rel=p?"stylesheet":H,p||(k.as="script"),k.crossOrigin="",k.href=s,f&&k.setAttribute("nonce",f),document.head.appendChild(k),p)return new Promise((E,L)=>{k.addEventListener("load",E),k.addEventListener("error",()=>L(new Error(`Unable to preload CSS for ${s}`)))})}))}function l(n){const i=new Event("vite:preloadError",{cancelable:!0});if(i.payload=n,window.dispatchEvent(i),!i.defaultPrevented)throw n}return o.then(n=>{for(const i of n||[])i.status==="rejected"&&l(i.reason);return y().catch(l)})},K={class:"header"},X={class:"header-left"},G={class:"app-info"},Q={class:"app-name"},Y={key:0,class:"app-version"},Z={class:"header-right"},ee={key:0,class:"status-badge live"},te={key:0,width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2"},oe={key:1,width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2"},ne={key:0,class:"loading-state"},le={class:"url-info"},se={key:1,class:"error-state"},ie={class:"error-message"},ae={class:"error-details"},re={key:2,class:"main-content"},ue={class:"tabs"},ce={key:0,class:"tab-controls"},de={class:"tab-panels"},ve={class:"player-frame"},pe={key:1,class:"placeholder"},fe={class:"player-controls"},me={class:"controls-group"},ye=["title"],he={key:0,width:"20",height:"20",viewBox:"0 0 24 24",fill:"currentColor"},ge={key:1,width:"20",height:"20",viewBox:"0 0 24 24",fill:"currentColor"},we=["title"],ke={key:0,width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2"},Ce={key:1,width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2"},be=["title"],xe={key:0,width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2"},_e={key:1,width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2"},Ee={class:"controls-info"},Le={class:"tab-panel config-panel"},Se={key:1,class:"placeholder"},Me={class:"tab-panel meta-panel"},Ae={class:"meta-code"},Pe={name:"SimulatorLayout"},Re=V({...Pe,props:{playerComponent:{},configComponent:{},scene:{},appUrl:{},isLoading:{type:Boolean},error:{},manifest:{},liveReloadActive:{type:Boolean}},emits:["reload"],setup(a,{emit:y}){const h=a,b=y,o=w("player"),l=w("landscape"),n=w(!1),i=w(!1),f=w(!0),s=w(!0),p=w(!1),x=w(3e4),k=M(()=>{var v;return((v=h.manifest)==null?void 0:v.name)||"External App"}),E=M(()=>{var v;return((v=h.manifest)==null?void 0:v.version)||""}),L=M(()=>l.value==="landscape"?"aspect-landscape":"aspect-portrait"),S=M(()=>{var v;try{return JSON.stringify(((v=h.scene)==null?void 0:v.meta)||{},null,2)}catch{return"{}"}});function g(){b("reload")}async function C(){try{await navigator.clipboard.writeText(S.value)}catch{console.warn("Failed to copy to clipboard")}}function u(v){v.key==="Escape"&&n.value&&(n.value=!1)}return j(()=>{window.addEventListener("keydown",u)}),D(()=>{window.removeEventListener("keydown",u)}),(v,t)=>(r(),d("div",{class:m(["simulator-layout",{"dark-mode":i.value}])},[e("header",K,[e("div",X,[t[11]||(t[11]=e("h1",null,"Juuno Simulator",-1)),e("div",G,[e("span",Q,_(k.value),1),E.value?(r(),d("span",Y,"v"+_(E.value),1)):A("",!0)])]),e("div",Z,[a.liveReloadActive?(r(),d("div",ee,[...t[12]||(t[12]=[e("span",{class:"status-dot"},null,-1),O(" Live ",-1)])])):A("",!0),e("button",{class:"icon-btn",title:"Reload app",onClick:g},[...t[13]||(t[13]=[e("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2"},[e("path",{d:"M23 4v6h-6M1 20v-6h6M3.51 9a9 9 0 0114.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0020.49 15"})],-1)])]),e("button",{class:"icon-btn",title:"Toggle dark mode",onClick:t[0]||(t[0]=c=>i.value=!i.value)},[i.value?(r(),d("svg",oe,[...t[15]||(t[15]=[e("path",{d:"M21 12.79A9 9 0 1111.21 3 7 7 0 0021 12.79z"},null,-1)])])):(r(),d("svg",te,[...t[14]||(t[14]=[e("circle",{cx:"12",cy:"12",r:"5"},null,-1),e("path",{d:"M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"},null,-1)])]))])])]),a.isLoading?(r(),d("div",ne,[t[16]||(t[16]=e("div",{class:"spinner"},null,-1)),t[17]||(t[17]=e("p",null,"Loading app...",-1)),e("p",le,_(a.appUrl),1)])):a.error?(r(),d("div",se,[t[19]||(t[19]=e("div",{class:"error-icon"},"!",-1)),t[20]||(t[20]=e("h2",null,"Failed to Load App",-1)),e("p",ie,_(a.error),1),e("div",ae,[e("p",null,[t[18]||(t[18]=e("strong",null,"App URL:",-1)),O(" "+_(a.appUrl),1)]),e("button",{class:"retry-btn",onClick:g},"Try Again")])])):(r(),d("div",re,[e("div",ue,[e("button",{class:m(["tab",{active:o.value==="player"}]),onClick:t[1]||(t[1]=c=>o.value="player")}," Player ",2),e("button",{class:m(["tab",{active:o.value==="config"}]),onClick:t[2]||(t[2]=c=>o.value="config")}," Config ",2),e("button",{class:m(["tab",{active:o.value==="meta"}]),onClick:t[3]||(t[3]=c=>o.value="meta")}," Scene Meta ",2),o.value==="player"?(r(),d("div",ce,[e("button",{class:m(["control-btn",{active:l.value==="landscape"}]),title:"Landscape (16:9)",onClick:t[4]||(t[4]=c=>l.value="landscape")},[...t[21]||(t[21]=[e("svg",{width:"18",height:"12",viewBox:"0 0 18 12",fill:"currentColor"},[e("rect",{x:"0.5",y:"0.5",width:"17",height:"11",rx:"1",fill:"none",stroke:"currentColor"})],-1)])],2),e("button",{class:m(["control-btn",{active:l.value==="portrait"}]),title:"Portrait (9:16)",onClick:t[5]||(t[5]=c=>l.value="portrait")},[...t[22]||(t[22]=[e("svg",{width:"12",height:"18",viewBox:"0 0 12 18",fill:"currentColor"},[e("rect",{x:"0.5",y:"0.5",width:"11",height:"17",rx:"1",fill:"none",stroke:"currentColor"})],-1)])],2),e("button",{class:m(["control-btn",{active:n.value}]),title:"Fullscreen (Esc to exit)",onClick:t[6]||(t[6]=c=>n.value=!n.value)},[...t[23]||(t[23]=[e("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2"},[e("path",{d:"M8 3H5a2 2 0 00-2 2v3m18 0V5a2 2 0 00-2-2h-3m0 18h3a2 2 0 002-2v-3M3 16v3a2 2 0 002 2h3"})],-1)])],2)])):A("",!0)]),e("div",de,[R(e("div",{class:m(["tab-panel player-panel",{fullscreen:n.value}])},[e("div",{class:m(["player-container",L.value])},[e("div",ve,[a.playerComponent?(r(),$(U(a.playerComponent),{key:a.scene.idx,scene:a.scene,playing:f.value,"is-visible":s.value,"duration-ms":x.value,muted:p.value},null,8,["scene","playing","is-visible","duration-ms","muted"])):(r(),d("div",pe,"No player component"))])],2),e("div",fe,[e("div",me,[e("button",{class:m(["player-btn",{active:f.value}]),title:f.value?"Pause":"Play",onClick:t[7]||(t[7]=c=>f.value=!f.value)},[f.value?(r(),d("svg",he,[...t[24]||(t[24]=[e("rect",{x:"6",y:"4",width:"4",height:"16"},null,-1),e("rect",{x:"14",y:"4",width:"4",height:"16"},null,-1)])])):(r(),d("svg",ge,[...t[25]||(t[25]=[e("polygon",{points:"5,3 19,12 5,21"},null,-1)])]))],10,ye),e("button",{class:m(["player-btn",{active:!s.value}]),title:s.value?"Hide (simulate off-screen)":"Show",onClick:t[8]||(t[8]=c=>s.value=!s.value)},[s.value?(r(),d("svg",ke,[...t[26]||(t[26]=[e("path",{d:"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"},null,-1),e("circle",{cx:"12",cy:"12",r:"3"},null,-1)])])):(r(),d("svg",Ce,[...t[27]||(t[27]=[e("path",{d:"M17.94 17.94A10.07 10.07 0 0112 20c-7 0-11-8-11-8a18.45 18.45 0 015.06-5.94M9.9 4.24A9.12 9.12 0 0112 4c7 0 11 8 11 8a18.5 18.5 0 01-2.16 3.19m-6.72-1.07a3 3 0 11-4.24-4.24"},null,-1),e("line",{x1:"1",y1:"1",x2:"23",y2:"23"},null,-1)])]))],10,we),e("button",{class:m(["player-btn",{active:p.value}]),title:p.value?"Unmute":"Mute",onClick:t[9]||(t[9]=c=>p.value=!p.value)},[p.value?(r(),d("svg",_e,[...t[29]||(t[29]=[e("polygon",{points:"11,5 6,9 2,9 2,15 6,15 11,19"},null,-1),e("line",{x1:"23",y1:"9",x2:"17",y2:"15"},null,-1),e("line",{x1:"17",y1:"9",x2:"23",y2:"15"},null,-1)])])):(r(),d("svg",xe,[...t[28]||(t[28]=[e("polygon",{points:"11,5 6,9 2,9 2,15 6,15 11,19"},null,-1),e("path",{d:"M19.07 4.93a10 10 0 010 14.14M15.54 8.46a5 5 0 010 7.07"},null,-1)])]))],10,be)]),e("div",Ee,[e("span",{class:m(["state-badge",{inactive:!f.value}])},_(f.value?"Playing":"Paused"),3),e("span",{class:m(["state-badge",{inactive:!s.value}])},_(s.value?"Visible":"Hidden"),3),e("span",{class:m(["state-badge",{inactive:!p.value}])},_(p.value?"Muted":"Sound On"),3)])]),n.value?(r(),d("button",{key:0,class:"exit-fullscreen",onClick:t[10]||(t[10]=c=>n.value=!1)}," Exit Fullscreen ")):A("",!0)],2),[[B,o.value==="player"]]),R(e("div",Le,[a.configComponent?(r(),$(U(a.configComponent),{key:"config-"+a.scene.idx})):(r(),d("div",Se,"No config component"))],512),[[B,o.value==="config"]]),R(e("div",Me,[e("div",{class:"meta-header"},[t[30]||(t[30]=e("h3",null,"scene.meta",-1)),e("button",{class:"copy-btn",onClick:C},"Copy")]),e("pre",Ae,_(S.value),1)],512),[[B,o.value==="meta"]])])]))],2))}}),Be=(a,y)=>{const h=a.__vccOpts||a;for(const[b,o]of y)h[b]=o;return h},$e=Be(Re,[["__scopeId","data-v-d3c29943"]]),Oe={name:"JuunoCLI"},Ue=V({...Oe,setup(a){const y=w(window.__JUUNO_EXTERNAL_APP_URL__||"http://localhost:5002/index.js"),h=w(!1),b=w(null),o=[],l=T(null),n=T(null),i=w(!0),f=w(null),s=I({idx:"simulator-scene-1",name:"Simulator Test Scene",app:null,app_idx:"simulator-app-1",created_at:new Date().toISOString(),display_time:5e3,language:"en",order:0,playlist_idx:"simulator-playlist-1",updated_at:new Date().toISOString(),translations:{},meta:{title:"Test App",backgroundColor:"#2c3e50",textColor:"#ecf0f1"},mediaAssets:[]}),x=z({async save(g){console.log("Simulator: Scene updated",g),Object.assign(s,g)}},{scene:s});async function k(){try{const g=await fetch(`${y.value}/manifest.json`);if(g.ok){const C=await g.json();return b.value=C,C}}catch{}return b.value=null,null}function E(g){o.forEach(C=>C.remove()),o.length=0,g.forEach(C=>{const u=document.createElement("link");u.rel="stylesheet",u.href=new URL(C,y.value).toString(),document.head.appendChild(u),o.push(u)})}async function L(){var g,C;try{i.value=!0,f.value=null,console.log(`Loading external app from: ${y.value}`);const u=await k(),v=[];(g=u==null?void 0:u.resources)!=null&&g.player&&v.push(...u.resources.player.filter(c=>c.endsWith(".css"))),(C=u==null?void 0:u.resources)!=null&&C.config&&v.push(...u.resources.config.filter(c=>c.endsWith(".css"))),v.length>0&&(console.log("Loading CSS files:",v),E(v));const t=await F(()=>import("external-app/player"),[]);if(t.default)l.value=P(t.default);else if(typeof t.render=="function")l.value=P(t.render());else throw new Error("External app must export a default component or render function from /player");try{const c=await F(()=>import("external-app/config"),[]);c.default?n.value=P(c.default):typeof c.render=="function"?n.value=P(c.render()):n.value=null}catch{n.value=null}x.load(s),console.log("✅ External app loaded successfully"),i.value=!1}catch(u){console.error("Failed to load external app:",u),f.value=u instanceof Error?u.message:"Failed to load external app",i.value=!1}}function S(){console.log("🔄 Reloading app..."),window.location.reload()}return j(L),(g,C)=>(r(),$(J($e),{"player-component":l.value,"config-component":n.value,scene:s,"app-url":y.value,"is-loading":i.value,error:f.value,manifest:b.value,"live-reload-active":h.value,onReload:S},null,8,["player-component","config-component","scene","app-url","is-loading","error","manifest","live-reload-active"]))}}),Te=q(Ue);Te.mount("#app");
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{defineComponent as A,ref as g,shallowRef as y,reactive as P,onMounted as k,createElementBlock as f,openBlock as d,createElementVNode as t,toDisplayString as _,createTextVNode as h,createBlock as E,resolveDynamicComponent as x,createApp as O}from"vue";import{provideAppConfigContext as I}from"@juuno-sdk/app-sdk";(function(){const a=document.createElement("link").relList;if(a&&a.supports&&a.supports("modulepreload"))return;for(const o of document.querySelectorAll('link[rel="modulepreload"]'))u(o);new MutationObserver(o=>{for(const r of o)if(r.type==="childList")for(const l of r.addedNodes)l.tagName==="LINK"&&l.rel==="modulepreload"&&u(l)}).observe(document,{childList:!0,subtree:!0});function i(o){const r={};return o.integrity&&(r.integrity=o.integrity),o.referrerPolicy&&(r.referrerPolicy=o.referrerPolicy),o.crossOrigin==="use-credentials"?r.credentials="include":o.crossOrigin==="anonymous"?r.credentials="omit":r.credentials="same-origin",r}function u(o){if(o.ep)return;o.ep=!0;const r=i(o);fetch(o.href,r)}})();const b="modulepreload",R=function(p){return"/"+p},C={},L=function(a,i,u){let o=Promise.resolve();if(i&&i.length>0){let l=function(n){return Promise.all(n.map(e=>Promise.resolve(e).then(m=>({status:"fulfilled",value:m}),m=>({status:"rejected",reason:m}))))};document.getElementsByTagName("link");const s=document.querySelector("meta[property=csp-nonce]"),v=(s==null?void 0:s.nonce)||(s==null?void 0:s.getAttribute("nonce"));o=l(i.map(n=>{if(n=R(n),n in C)return;C[n]=!0;const e=n.endsWith(".css"),m=e?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${n}"]${m}`))return;const c=document.createElement("link");if(c.rel=e?"stylesheet":b,e||(c.as="script"),c.crossOrigin="",c.href=n,v&&c.setAttribute("nonce",v),document.head.appendChild(c),e)return new Promise((w,S)=>{c.addEventListener("load",w),c.addEventListener("error",()=>S(new Error(`Unable to preload CSS for ${n}`)))})}))}function r(l){const s=new Event("vite:preloadError",{cancelable:!0});if(s.payload=l,window.dispatchEvent(s),!s.defaultPrevented)throw l}return o.then(l=>{for(const s of l||[])s.status==="rejected"&&r(s.reason);return a().catch(r)})},U={class:"juuno-cli"},N={class:"header"},T={class:"header-content"},j={class:"header-info"},D={class:"app-url"},V={key:0,class:"loading-state"},q={class:"url-info"},B={key:1,class:"error-state"},F={class:"error-message"},J={class:"error-details"},$={key:2,class:"container"},M={class:"player-section"},K={class:"player-preview"},W={key:1,class:"placeholder"},X={class:"config-section"},z={class:"config-panel"},G={key:1,class:"placeholder"},H={name:"JuunoCLI"},Q=A({...H,setup(p){const a=g(window.__JUUNO_EXTERNAL_APP_URL__||"http://localhost:5002/index.js"),i=y(null),u=y(null),o=g(!0),r=g(null),l=P({idx:"simulator-scene-1",name:"Simulator Test Scene",app:null,app_idx:"simulator-app-1",created_at:new Date().toISOString(),display_time:5e3,language:"en",order:0,playlist_idx:"simulator-playlist-1",updated_at:new Date().toISOString(),translations:{},meta:{title:"Test App",backgroundColor:"#2c3e50",textColor:"#ecf0f1"},mediaAssets:[]}),v=I({async save(n){console.log("Simulator: Scene updated",n),Object.assign(l,n)}},{scene:l});return k(async()=>{try{o.value=!0,r.value=null,console.log(`Loading external app from: ${a.value}`);const n=await L(()=>import("external-app/player"),[]);if(n.default)i.value=n.default;else if(typeof n.render=="function")i.value=n.render();else throw new Error("External app must export a default component or render function from /player");try{const e=await L(()=>import("external-app/config"),[]);e.default?u.value=e.default:typeof e.render=="function"?u.value=e.render():u.value=null}catch(e){console.warn("Config component not found or failed to load:",e),u.value=null}v.load(l),console.log("✅ External app loaded successfully"),o.value=!1}catch(n){console.error("Failed to load external app:",n),r.value=n instanceof Error?n.message:"Failed to load external app",o.value=!1}}),(n,e)=>(d(),f("div",U,[t("header",N,[t("div",T,[e[0]||(e[0]=t("h1",null,"Juuno CLI",-1)),t("div",j,[t("span",D,_(a.value),1)])])]),o.value?(d(),f("div",V,[e[1]||(e[1]=t("div",{class:"spinner"},null,-1)),e[2]||(e[2]=t("p",null,"Loading external app...",-1)),t("p",q,_(a.value),1)])):r.value?(d(),f("div",B,[e[6]||(e[6]=t("div",{class:"error-icon"},"⚠️",-1)),e[7]||(e[7]=t("h2",null,"Failed to Load App",-1)),t("p",F,_(r.value),1),t("div",J,[t("p",null,[e[3]||(e[3]=t("strong",null,"App URL:",-1)),h(" "+_(a.value),1)]),e[4]||(e[4]=t("p",null,[t("strong",null,"Common Issues:")],-1)),e[5]||(e[5]=t("ul",null,[t("li",null,"App dev server not running"),t("li",null,"CORS not enabled on app dev server"),t("li",null," App doesn't export required components from /player and /config "),t("li",null,"Incorrect URL provided"),t("li",null,"Missing exports field in package.json")],-1))])])):(d(),f("div",$,[t("div",M,[e[8]||(e[8]=t("h2",null,"Player View",-1)),t("div",K,[i.value?(d(),E(x(i.value),{key:0,scene:l},null,8,["scene"])):(d(),f("div",W,"No player component found"))])]),t("div",X,[e[9]||(e[9]=t("h2",null,"Configuration UI",-1)),t("div",z,[u.value?(d(),E(x(u.value),{key:0})):(d(),f("div",G,"No config component found"))])])])),e[10]||(e[10]=t("footer",{class:"footer"},[t("p",null,[t("strong",null,"Juuno CLI"),h(" - Test your external app in a production-like environment ")])],-1))]))}}),Y=(p,a)=>{const i=p.__vccOpts||p;for(const[u,o]of a)i[u]=o;return i},Z=Y(Q,[["__scopeId","data-v-b2010f22"]]),ee=O(Z);ee.mount("#app");
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{defineComponent as V,ref as w,computed as S,onMounted as D,onUnmounted as F,createElementBlock as d,openBlock as r,normalizeClass as y,createElementVNode as e,createCommentVNode as A,toDisplayString as _,createTextVNode as O,withDirectives as $,createBlock as B,resolveDynamicComponent as U,vShow as R,shallowRef as N,reactive as I,unref as J,markRaw as P,createApp as q}from"vue";import{provideAppConfigContext as z}from"@juuno-sdk/app-sdk";(function(){const h=document.createElement("link").relList;if(h&&h.supports&&h.supports("modulepreload"))return;for(const o of document.querySelectorAll('link[rel="modulepreload"]'))b(o);new MutationObserver(o=>{for(const l of o)if(l.type==="childList")for(const n of l.addedNodes)n.tagName==="LINK"&&n.rel==="modulepreload"&&b(n)}).observe(document,{childList:!0,subtree:!0});function p(o){const l={};return o.integrity&&(l.integrity=o.integrity),o.referrerPolicy&&(l.referrerPolicy=o.referrerPolicy),o.crossOrigin==="use-credentials"?l.credentials="include":o.crossOrigin==="anonymous"?l.credentials="omit":l.credentials="same-origin",l}function b(o){if(o.ep)return;o.ep=!0;const l=p(o);fetch(o.href,l)}})();const H="modulepreload",W=function(a){return"/"+a},T={},j=function(h,p,b){let o=Promise.resolve();if(p&&p.length>0){let n=function(s){return Promise.all(s.map(f=>Promise.resolve(f).then(x=>({status:"fulfilled",value:x}),x=>({status:"rejected",reason:x}))))};document.getElementsByTagName("link");const i=document.querySelector("meta[property=csp-nonce]"),m=(i==null?void 0:i.nonce)||(i==null?void 0:i.getAttribute("nonce"));o=n(p.map(s=>{if(s=W(s),s in T)return;T[s]=!0;const f=s.endsWith(".css"),x=f?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${s}"]${x}`))return;const k=document.createElement("link");if(k.rel=f?"stylesheet":H,f||(k.as="script"),k.crossOrigin="",k.href=s,m&&k.setAttribute("nonce",m),document.head.appendChild(k),f)return new Promise((E,L)=>{k.addEventListener("load",E),k.addEventListener("error",()=>L(new Error(`Unable to preload CSS for ${s}`)))})}))}function l(n){const i=new Event("vite:preloadError",{cancelable:!0});if(i.payload=n,window.dispatchEvent(i),!i.defaultPrevented)throw n}return o.then(n=>{for(const i of n||[])i.status==="rejected"&&l(i.reason);return h().catch(l)})},K={class:"header"},X={class:"header-left"},G={class:"app-info"},Q={class:"app-name"},Y={key:0,class:"app-version"},Z={class:"header-right"},ee={key:0,class:"status-badge live"},te={key:0,width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2"},oe={key:1,width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2"},ne={key:0,class:"loading-state"},le={class:"url-info"},se={key:1,class:"error-state"},ie={class:"error-message"},ae={class:"error-details"},re={key:2,class:"main-content"},ue={class:"tabs"},ce={key:0,class:"tab-controls"},de={class:"tab-panels"},ve={class:"player-frame"},pe={key:1,class:"placeholder"},fe={class:"player-controls"},me={class:"controls-group"},ye=["title"],he={key:0,width:"20",height:"20",viewBox:"0 0 24 24",fill:"currentColor"},ge={key:1,width:"20",height:"20",viewBox:"0 0 24 24",fill:"currentColor"},we=["title"],ke={key:0,width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2"},Ce={key:1,width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2"},be=["title"],xe={key:0,width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2"},_e={key:1,width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2"},Ee={class:"controls-info"},Le={class:"tab-panel config-panel"},Me={key:1,class:"placeholder"},Se={class:"tab-panel meta-panel"},Ae={class:"meta-code"},Pe={name:"SimulatorLayout"},$e=V({...Pe,props:{playerComponent:{},configComponent:{},scene:{},appUrl:{},isLoading:{type:Boolean},error:{},manifest:{},liveReloadActive:{type:Boolean}},emits:["reload"],setup(a,{emit:h}){const p=a,b=h,o=w("player"),l=w("landscape"),n=w(!1),i=w(!1),m=w(!0),s=w(!0),f=w(!1),x=w(3e4),k=S(()=>{var v;return((v=p.manifest)==null?void 0:v.name)||"External App"}),E=S(()=>{var v;return((v=p.manifest)==null?void 0:v.version)||""}),L=S(()=>l.value==="landscape"?"aspect-landscape":"aspect-portrait"),M=S(()=>{var v;try{return JSON.stringify(((v=p.scene)==null?void 0:v.meta)||{},null,2)}catch{return"{}"}});function g(){b("reload")}async function C(){try{await navigator.clipboard.writeText(M.value)}catch{console.warn("Failed to copy to clipboard")}}function u(v){v.key==="Escape"&&n.value&&(n.value=!1)}return D(()=>{window.addEventListener("keydown",u)}),F(()=>{window.removeEventListener("keydown",u)}),(v,t)=>(r(),d("div",{class:y(["simulator-layout",{"dark-mode":i.value}])},[e("header",K,[e("div",X,[t[11]||(t[11]=e("h1",null,"Juuno Simulator",-1)),e("div",G,[e("span",Q,_(k.value),1),E.value?(r(),d("span",Y,"v"+_(E.value),1)):A("",!0)])]),e("div",Z,[a.liveReloadActive?(r(),d("div",ee,[...t[12]||(t[12]=[e("span",{class:"status-dot"},null,-1),O(" Live ",-1)])])):A("",!0),e("button",{class:"icon-btn",title:"Reload app",onClick:g},[...t[13]||(t[13]=[e("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2"},[e("path",{d:"M23 4v6h-6M1 20v-6h6M3.51 9a9 9 0 0114.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0020.49 15"})],-1)])]),e("button",{class:"icon-btn",title:"Toggle dark mode",onClick:t[0]||(t[0]=c=>i.value=!i.value)},[i.value?(r(),d("svg",oe,[...t[15]||(t[15]=[e("path",{d:"M21 12.79A9 9 0 1111.21 3 7 7 0 0021 12.79z"},null,-1)])])):(r(),d("svg",te,[...t[14]||(t[14]=[e("circle",{cx:"12",cy:"12",r:"5"},null,-1),e("path",{d:"M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"},null,-1)])]))])])]),a.isLoading?(r(),d("div",ne,[t[16]||(t[16]=e("div",{class:"spinner"},null,-1)),t[17]||(t[17]=e("p",null,"Loading app...",-1)),e("p",le,_(a.appUrl),1)])):a.error?(r(),d("div",se,[t[19]||(t[19]=e("div",{class:"error-icon"},"!",-1)),t[20]||(t[20]=e("h2",null,"Failed to Load App",-1)),e("p",ie,_(a.error),1),e("div",ae,[e("p",null,[t[18]||(t[18]=e("strong",null,"App URL:",-1)),O(" "+_(a.appUrl),1)]),e("button",{class:"retry-btn",onClick:g},"Try Again")])])):(r(),d("div",re,[e("div",ue,[e("button",{class:y(["tab",{active:o.value==="player"}]),onClick:t[1]||(t[1]=c=>o.value="player")}," Player ",2),e("button",{class:y(["tab",{active:o.value==="config"}]),onClick:t[2]||(t[2]=c=>o.value="config")}," Config ",2),e("button",{class:y(["tab",{active:o.value==="meta"}]),onClick:t[3]||(t[3]=c=>o.value="meta")}," Scene Meta ",2),o.value==="player"?(r(),d("div",ce,[e("button",{class:y(["control-btn",{active:l.value==="landscape"}]),title:"Landscape (16:9)",onClick:t[4]||(t[4]=c=>l.value="landscape")},[...t[21]||(t[21]=[e("svg",{width:"18",height:"12",viewBox:"0 0 18 12",fill:"currentColor"},[e("rect",{x:"0.5",y:"0.5",width:"17",height:"11",rx:"1",fill:"none",stroke:"currentColor"})],-1)])],2),e("button",{class:y(["control-btn",{active:l.value==="portrait"}]),title:"Portrait (9:16)",onClick:t[5]||(t[5]=c=>l.value="portrait")},[...t[22]||(t[22]=[e("svg",{width:"12",height:"18",viewBox:"0 0 12 18",fill:"currentColor"},[e("rect",{x:"0.5",y:"0.5",width:"11",height:"17",rx:"1",fill:"none",stroke:"currentColor"})],-1)])],2),e("button",{class:y(["control-btn",{active:n.value}]),title:"Fullscreen (Esc to exit)",onClick:t[6]||(t[6]=c=>n.value=!n.value)},[...t[23]||(t[23]=[e("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2"},[e("path",{d:"M8 3H5a2 2 0 00-2 2v3m18 0V5a2 2 0 00-2-2h-3m0 18h3a2 2 0 002-2v-3M3 16v3a2 2 0 002 2h3"})],-1)])],2)])):A("",!0)]),e("div",de,[$(e("div",{class:y(["tab-panel player-panel",{fullscreen:n.value}])},[e("div",{class:y(["player-container",L.value])},[e("div",ve,[a.playerComponent?(r(),B(U(a.playerComponent),{key:a.scene.idx,scene:a.scene,playing:m.value,"is-visible":s.value,"duration-ms":x.value,muted:f.value},null,8,["scene","playing","is-visible","duration-ms","muted"])):(r(),d("div",pe,"No player component"))])],2),e("div",fe,[e("div",me,[e("button",{class:y(["player-btn",{active:m.value}]),title:m.value?"Pause":"Play",onClick:t[7]||(t[7]=c=>m.value=!m.value)},[m.value?(r(),d("svg",he,[...t[24]||(t[24]=[e("rect",{x:"6",y:"4",width:"4",height:"16"},null,-1),e("rect",{x:"14",y:"4",width:"4",height:"16"},null,-1)])])):(r(),d("svg",ge,[...t[25]||(t[25]=[e("polygon",{points:"5,3 19,12 5,21"},null,-1)])]))],10,ye),e("button",{class:y(["player-btn",{active:!s.value}]),title:s.value?"Hide (simulate off-screen)":"Show",onClick:t[8]||(t[8]=c=>s.value=!s.value)},[s.value?(r(),d("svg",ke,[...t[26]||(t[26]=[e("path",{d:"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"},null,-1),e("circle",{cx:"12",cy:"12",r:"3"},null,-1)])])):(r(),d("svg",Ce,[...t[27]||(t[27]=[e("path",{d:"M17.94 17.94A10.07 10.07 0 0112 20c-7 0-11-8-11-8a18.45 18.45 0 015.06-5.94M9.9 4.24A9.12 9.12 0 0112 4c7 0 11 8 11 8a18.5 18.5 0 01-2.16 3.19m-6.72-1.07a3 3 0 11-4.24-4.24"},null,-1),e("line",{x1:"1",y1:"1",x2:"23",y2:"23"},null,-1)])]))],10,we),e("button",{class:y(["player-btn",{active:f.value}]),title:f.value?"Unmute":"Mute",onClick:t[9]||(t[9]=c=>f.value=!f.value)},[f.value?(r(),d("svg",_e,[...t[29]||(t[29]=[e("polygon",{points:"11,5 6,9 2,9 2,15 6,15 11,19"},null,-1),e("line",{x1:"23",y1:"9",x2:"17",y2:"15"},null,-1),e("line",{x1:"17",y1:"9",x2:"23",y2:"15"},null,-1)])])):(r(),d("svg",xe,[...t[28]||(t[28]=[e("polygon",{points:"11,5 6,9 2,9 2,15 6,15 11,19"},null,-1),e("path",{d:"M19.07 4.93a10 10 0 010 14.14M15.54 8.46a5 5 0 010 7.07"},null,-1)])]))],10,be)]),e("div",Ee,[e("span",{class:y(["state-badge",{inactive:!m.value}])},_(m.value?"Playing":"Paused"),3),e("span",{class:y(["state-badge",{inactive:!s.value}])},_(s.value?"Visible":"Hidden"),3),e("span",{class:y(["state-badge",{inactive:!f.value}])},_(f.value?"Muted":"Sound On"),3)])]),n.value?(r(),d("button",{key:0,class:"exit-fullscreen",onClick:t[10]||(t[10]=c=>n.value=!1)}," Exit Fullscreen ")):A("",!0)],2),[[R,o.value==="player"]]),$(e("div",Le,[a.configComponent?(r(),B(U(a.configComponent),{key:"config-"+a.scene.idx})):(r(),d("div",Me,"No config component"))],512),[[R,o.value==="config"]]),$(e("div",Se,[e("div",{class:"meta-header"},[t[30]||(t[30]=e("h3",null,"scene.meta",-1)),e("button",{class:"copy-btn",onClick:C},"Copy")]),e("pre",Ae,_(M.value),1)],512),[[R,o.value==="meta"]])])]))],2))}}),Re=(a,h)=>{const p=a.__vccOpts||a;for(const[b,o]of h)p[b]=o;return p},Be=Re($e,[["__scopeId","data-v-d3c29943"]]),Oe={name:"JuunoCLI"},Ue=V({...Oe,setup(a){const h=w(window.__JUUNO_EXTERNAL_APP_URL__||"http://localhost:5002/index.js"),p=w(window.__JUUNO_LIVE_RELOAD__||!1),b=w(null),o=[],l=N(null),n=N(null),i=w(!0),m=w(null),s=I({idx:"simulator-scene-1",name:"Simulator Test Scene",app:null,app_idx:"simulator-app-1",created_at:new Date().toISOString(),display_time:5e3,language:"en",order:0,playlist_idx:"simulator-playlist-1",updated_at:new Date().toISOString(),translations:{},meta:{title:"Test App",backgroundColor:"#2c3e50",textColor:"#ecf0f1"},mediaAssets:[]}),x=z({async save(g){console.log("Simulator: Scene updated",g),Object.assign(s,g)}},{scene:s});async function k(){try{const g=await fetch(`${h.value}/manifest.json`);if(g.ok){const C=await g.json();return b.value=C,C}}catch{}return b.value=null,null}function E(g){o.forEach(C=>C.remove()),o.length=0,g.forEach(C=>{const u=document.createElement("link");u.rel="stylesheet",u.href=`${h.value}${C}`,document.head.appendChild(u),o.push(u)})}async function L(){var g,C;try{i.value=!0,m.value=null,console.log(`Loading external app from: ${h.value}`);const u=await k(),v=[];(g=u==null?void 0:u.resources)!=null&&g.player&&v.push(...u.resources.player.filter(c=>c.endsWith(".css"))),(C=u==null?void 0:u.resources)!=null&&C.config&&v.push(...u.resources.config.filter(c=>c.endsWith(".css"))),v.length>0&&(console.log("Loading CSS files:",v),E(v));const t=await j(()=>import("external-app/player"),[]);if(t.default)l.value=P(t.default);else if(typeof t.render=="function")l.value=P(t.render());else throw new Error("External app must export a default component or render function from /player");try{const c=await j(()=>import("external-app/config"),[]);c.default?n.value=P(c.default):typeof c.render=="function"?n.value=P(c.render()):n.value=null}catch{n.value=null}x.load(s),console.log("✅ External app loaded successfully"),i.value=!1}catch(u){console.error("Failed to load external app:",u),m.value=u instanceof Error?u.message:"Failed to load external app",i.value=!1}}function M(){console.log("🔄 Reloading app..."),window.location.reload()}return typeof window<"u"&&(window.addEventListener("juuno:live-reload-connected",()=>{p.value=!0}),window.addEventListener("juuno:live-reload-disconnected",()=>{p.value=!1})),D(L),(g,C)=>(r(),B(J(Be),{"player-component":l.value,"config-component":n.value,scene:s,"app-url":h.value,"is-loading":i.value,error:m.value,manifest:b.value,"live-reload-active":p.value,onReload:M},null,8,["player-component","config-component","scene","app-url","is-loading","error","manifest","live-reload-active"]))}}),Ne=q(Ue);Ne.mount("#app");
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
[data-v-b2010f22]{box-sizing:border-box}.juuno-cli[data-v-b2010f22]{min-height:100vh;display:flex;flex-direction:column;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,sans-serif;background-color:#f5f5f5}.header[data-v-b2010f22]{background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;padding:1.5rem 2rem;box-shadow:0 2px 4px #0000001a}.header-content[data-v-b2010f22]{max-width:1600px;margin:0 auto}.header h1[data-v-b2010f22]{margin:0 0 .5rem;font-size:1.75rem;font-weight:600}.header-info[data-v-b2010f22]{display:flex;justify-content:space-between;align-items:center;gap:1rem}.app-url[data-v-b2010f22]{font-size:.875rem;opacity:.9;font-family:Courier New,monospace}.loading-state[data-v-b2010f22],.error-state[data-v-b2010f22]{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:3rem;text-align:center}.spinner[data-v-b2010f22]{width:50px;height:50px;border:4px solid #f3f3f3;border-top:4px solid #667eea;border-radius:50%;animation:spin-b2010f22 1s linear infinite}@keyframes spin-b2010f22{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.url-info[data-v-b2010f22]{margin-top:1rem;font-size:.875rem;color:#666;font-family:Courier New,monospace}.error-icon[data-v-b2010f22]{font-size:4rem;margin-bottom:1rem}.error-message[data-v-b2010f22]{color:#d32f2f;font-weight:500;margin:1rem 0}.error-details[data-v-b2010f22]{background:#fff;border-radius:8px;padding:1.5rem;margin-top:2rem;text-align:left;max-width:600px}.error-details ul[data-v-b2010f22]{margin:.5rem 0 0 1.5rem;padding:0}.error-details li[data-v-b2010f22]{margin:.25rem 0}.container[data-v-b2010f22]{flex:1;display:grid;grid-template-columns:1fr 1fr;gap:2rem;padding:2rem;max-width:1600px;margin:0 auto;width:100%}.player-section[data-v-b2010f22],.config-section[data-v-b2010f22]{background:#fff;border-radius:8px;padding:1.5rem;box-shadow:0 1px 3px #0000001a}.player-section h2[data-v-b2010f22],.config-section h2[data-v-b2010f22]{margin:0 0 1rem;font-size:1.25rem;font-weight:600;color:#333}.player-preview[data-v-b2010f22]{aspect-ratio:16 / 9;background:#000;border-radius:4px;overflow:hidden;box-shadow:0 4px 6px #0000001a}.config-panel[data-v-b2010f22]{background:#fafafa;border-radius:4px;padding:1rem;min-height:400px}.placeholder[data-v-b2010f22]{display:flex;align-items:center;justify-content:center;height:100%;color:#999;font-style:italic}.footer[data-v-b2010f22]{background:#fff;padding:1.5rem;text-align:center;border-top:1px solid #e0e0e0;color:#666;font-size:.875rem}.footer p[data-v-b2010f22]{margin:0}@media (max-width: 1200px){.container[data-v-b2010f22]{grid-template-columns:1fr}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{defineComponent as D,ref as w,computed as A,createElementBlock as m,openBlock as d,normalizeClass as k,createElementVNode as t,createCommentVNode as R,toDisplayString as x,createTextVNode as U,withDirectives as P,createBlock as $,resolveDynamicComponent as B,vShow as O,shallowRef as N,reactive as F,onMounted as I,unref as V,markRaw as M,createApp as J}from"vue";import{provideAppConfigContext as q}from"@juuno-sdk/app-sdk";(function(){const p=document.createElement("link").relList;if(p&&p.supports&&p.supports("modulepreload"))return;for(const o of document.querySelectorAll('link[rel="modulepreload"]'))g(o);new MutationObserver(o=>{for(const n of o)if(n.type==="childList")for(const l of n.addedNodes)l.tagName==="LINK"&&l.rel==="modulepreload"&&g(l)}).observe(document,{childList:!0,subtree:!0});function u(o){const n={};return o.integrity&&(n.integrity=o.integrity),o.referrerPolicy&&(n.referrerPolicy=o.referrerPolicy),o.crossOrigin==="use-credentials"?n.credentials="include":o.crossOrigin==="anonymous"?n.credentials="omit":n.credentials="same-origin",n}function g(o){if(o.ep)return;o.ep=!0;const n=u(o);fetch(o.href,n)}})();const W="modulepreload",z=function(r){return"/"+r},T={},j=function(p,u,g){let o=Promise.resolve();if(u&&u.length>0){let l=function(a){return Promise.all(a.map(C=>Promise.resolve(C).then(h=>({status:"fulfilled",value:h}),h=>({status:"rejected",reason:h}))))};document.getElementsByTagName("link");const s=document.querySelector("meta[property=csp-nonce]"),b=(s==null?void 0:s.nonce)||(s==null?void 0:s.getAttribute("nonce"));o=l(u.map(a=>{if(a=z(a),a in T)return;T[a]=!0;const C=a.endsWith(".css"),h=C?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${a}"]${h}`))return;const v=document.createElement("link");if(v.rel=C?"stylesheet":W,C||(v.as="script"),v.crossOrigin="",v.href=a,b&&v.setAttribute("nonce",b),document.head.appendChild(v),C)return new Promise((E,_)=>{v.addEventListener("load",E),v.addEventListener("error",()=>_(new Error(`Unable to preload CSS for ${a}`)))})}))}function n(l){const s=new Event("vite:preloadError",{cancelable:!0});if(s.payload=l,window.dispatchEvent(s),!s.defaultPrevented)throw l}return o.then(l=>{for(const s of l||[])s.status==="rejected"&&n(s.reason);return p().catch(n)})},H={class:"header"},K={class:"header-left"},X={class:"app-info"},G={class:"app-name"},Q={key:0,class:"app-version"},Y={class:"header-right"},Z={key:0,class:"status-badge live"},ee={key:0,width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2"},te={key:1,width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2"},oe={key:0,class:"loading-state"},ne={class:"url-info"},le={key:1,class:"error-state"},se={class:"error-message"},re={class:"error-details"},ae={key:2,class:"main-content"},ie={class:"tabs"},ce={key:0,class:"tab-controls"},ue={class:"tab-panels"},de={class:"player-frame"},pe={key:1,class:"placeholder"},ve={class:"tab-panel config-panel"},fe={key:1,class:"placeholder"},me={class:"tab-panel meta-panel"},ge={class:"meta-header"},he={class:"meta-code"},ye={name:"SimulatorLayout"},we=D({...ye,props:{playerComponent:{},configComponent:{},scene:{},appUrl:{},isLoading:{type:Boolean},error:{},manifest:{},liveReloadActive:{type:Boolean}},emits:["reload"],setup(r,{emit:p}){const u=r,g=p,o=w("player"),n=w("landscape"),l=w(!1),s=w(!1);w(!0);const b=A(()=>{var f;return((f=u.manifest)==null?void 0:f.name)||"External App"}),a=A(()=>{var f;return((f=u.manifest)==null?void 0:f.version)||""}),C=A(()=>n.value==="landscape"?"aspect-landscape":"aspect-portrait"),h=A(()=>{var f;try{return JSON.stringify(((f=u.scene)==null?void 0:f.meta)||{},null,2)}catch{return"{}"}});function v(){l.value=!l.value}function E(){s.value=!s.value}function _(){g("reload")}return(f,e)=>(d(),m("div",{class:k(["simulator-layout",{"dark-mode":s.value}])},[t("header",H,[t("div",K,[e[7]||(e[7]=t("h1",null,"Juuno Simulator",-1)),t("div",X,[t("span",G,x(b.value),1),a.value?(d(),m("span",Q,"v"+x(a.value),1)):R("",!0)])]),t("div",Y,[r.liveReloadActive?(d(),m("div",Z,[...e[8]||(e[8]=[t("span",{class:"status-dot"},null,-1),U(" Live ",-1)])])):R("",!0),t("button",{class:"icon-btn",title:"Reload app",onClick:_},[...e[9]||(e[9]=[t("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2"},[t("path",{d:"M23 4v6h-6M1 20v-6h6M3.51 9a9 9 0 0114.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0020.49 15"})],-1)])]),t("button",{class:"icon-btn",title:"Toggle dark mode",onClick:E},[s.value?(d(),m("svg",te,[...e[11]||(e[11]=[t("path",{d:"M21 12.79A9 9 0 1111.21 3 7 7 0 0021 12.79z"},null,-1)])])):(d(),m("svg",ee,[...e[10]||(e[10]=[t("circle",{cx:"12",cy:"12",r:"5"},null,-1),t("path",{d:"M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"},null,-1)])]))])])]),r.isLoading?(d(),m("div",oe,[e[12]||(e[12]=t("div",{class:"spinner"},null,-1)),e[13]||(e[13]=t("p",null,"Loading app...",-1)),t("p",ne,x(r.appUrl),1)])):r.error?(d(),m("div",le,[e[15]||(e[15]=t("div",{class:"error-icon"},"!",-1)),e[16]||(e[16]=t("h2",null,"Failed to Load App",-1)),t("p",se,x(r.error),1),t("div",re,[t("p",null,[e[14]||(e[14]=t("strong",null,"App URL:",-1)),U(" "+x(r.appUrl),1)]),t("button",{class:"retry-btn",onClick:_},"Try Again")])])):(d(),m("div",ae,[t("div",ie,[t("button",{class:k(["tab",{active:o.value==="player"}]),onClick:e[0]||(e[0]=i=>o.value="player")}," Player ",2),t("button",{class:k(["tab",{active:o.value==="config"}]),onClick:e[1]||(e[1]=i=>o.value="config")}," Config ",2),t("button",{class:k(["tab",{active:o.value==="meta"}]),onClick:e[2]||(e[2]=i=>o.value="meta")}," Scene Meta ",2),o.value==="player"?(d(),m("div",ce,[t("button",{class:k(["control-btn",{active:n.value==="landscape"}]),title:"Landscape (16:9)",onClick:e[3]||(e[3]=i=>n.value="landscape")},[...e[17]||(e[17]=[t("svg",{width:"18",height:"12",viewBox:"0 0 18 12",fill:"currentColor"},[t("rect",{x:"0.5",y:"0.5",width:"17",height:"11",rx:"1",fill:"none",stroke:"currentColor"})],-1)])],2),t("button",{class:k(["control-btn",{active:n.value==="portrait"}]),title:"Portrait (9:16)",onClick:e[4]||(e[4]=i=>n.value="portrait")},[...e[18]||(e[18]=[t("svg",{width:"12",height:"18",viewBox:"0 0 12 18",fill:"currentColor"},[t("rect",{x:"0.5",y:"0.5",width:"11",height:"17",rx:"1",fill:"none",stroke:"currentColor"})],-1)])],2),t("button",{class:k(["control-btn",{active:l.value}]),title:"Fullscreen",onClick:v},[...e[19]||(e[19]=[t("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2"},[t("path",{d:"M8 3H5a2 2 0 00-2 2v3m18 0V5a2 2 0 00-2-2h-3m0 18h3a2 2 0 002-2v-3M3 16v3a2 2 0 002 2h3"})],-1)])],2)])):R("",!0)]),t("div",ue,[P(t("div",{class:k(["tab-panel player-panel",{fullscreen:l.value}])},[t("div",{class:k(["player-container",C.value])},[t("div",de,[r.playerComponent?(d(),$(B(r.playerComponent),{key:r.scene.idx,scene:r.scene,playing:!0,"is-visible":!0,"duration-ms":5e3},null,8,["scene"])):(d(),m("div",pe,"No player component"))])],2),l.value?(d(),m("button",{key:0,class:"exit-fullscreen",onClick:e[5]||(e[5]=i=>l.value=!1)}," Exit Fullscreen ")):R("",!0)],2),[[O,o.value==="player"]]),P(t("div",ve,[r.configComponent?(d(),$(B(r.configComponent),{key:"config-"+r.scene.idx})):(d(),m("div",fe,"No config component"))],512),[[O,o.value==="config"]]),P(t("div",me,[t("div",ge,[e[20]||(e[20]=t("h3",null,"scene.meta",-1)),t("button",{class:"copy-btn",onClick:e[6]||(e[6]=i=>f.navigator.clipboard.writeText(h.value))}," Copy ")]),t("pre",he,x(h.value),1)],512),[[O,o.value==="meta"]])])]))],2))}}),Ce=(r,p)=>{const u=r.__vccOpts||r;for(const[g,o]of p)u[g]=o;return u},ke=Ce(we,[["__scopeId","data-v-2641604d"]]),be={name:"JuunoCLI"},_e=D({...be,setup(r){const p=w(window.__JUUNO_EXTERNAL_APP_URL__||"http://localhost:5002/index.js"),u=w(window.__JUUNO_LIVE_RELOAD__||!1),g=w(null),o=[],n=N(null),l=N(null),s=w(!0),b=w(null),a=F({idx:"simulator-scene-1",name:"Simulator Test Scene",app:null,app_idx:"simulator-app-1",created_at:new Date().toISOString(),display_time:5e3,language:"en",order:0,playlist_idx:"simulator-playlist-1",updated_at:new Date().toISOString(),translations:{},meta:{title:"Test App",backgroundColor:"#2c3e50",textColor:"#ecf0f1"},mediaAssets:[]}),h=q({async save(e){console.log("Simulator: Scene updated",e),Object.assign(a,e)}},{scene:a});async function v(){try{const e=await fetch(`${p.value}/manifest.json`);if(e.ok){const i=await e.json();return g.value=i,i}}catch{}return g.value=null,null}function E(e){o.forEach(i=>i.remove()),o.length=0,e.forEach(i=>{const c=document.createElement("link");c.rel="stylesheet",c.href=`${p.value}${i}`,document.head.appendChild(c),o.push(c)})}async function _(){var e,i;try{s.value=!0,b.value=null,console.log(`Loading external app from: ${p.value}`);const c=await v(),L=[];(e=c==null?void 0:c.resources)!=null&&e.player&&L.push(...c.resources.player.filter(y=>y.endsWith(".css"))),(i=c==null?void 0:c.resources)!=null&&i.config&&L.push(...c.resources.config.filter(y=>y.endsWith(".css"))),L.length>0&&(console.log("Loading CSS files:",L),E(L));const S=await j(()=>import("external-app/player"),[]);if(S.default)n.value=M(S.default);else if(typeof S.render=="function")n.value=M(S.render());else throw new Error("External app must export a default component or render function from /player");try{const y=await j(()=>import("external-app/config"),[]);y.default?l.value=M(y.default):typeof y.render=="function"?l.value=M(y.render()):l.value=null}catch(y){console.warn("Config component not found or failed to load:",y),l.value=null}h.load(a),console.log("✅ External app loaded successfully"),s.value=!1}catch(c){console.error("Failed to load external app:",c),b.value=c instanceof Error?c.message:"Failed to load external app",s.value=!1}}function f(){console.log("🔄 Reloading app..."),window.location.reload()}return typeof window<"u"&&(window.addEventListener("juuno:live-reload-connected",()=>{u.value=!0}),window.addEventListener("juuno:live-reload-disconnected",()=>{u.value=!1})),I(_),(e,i)=>(d(),$(V(ke),{"player-component":n.value,"config-component":l.value,scene:a,"app-url":p.value,"is-loading":s.value,error:b.value,manifest:g.value,"live-reload-active":u.value,onReload:f},null,8,["player-component","config-component","scene","app-url","is-loading","error","manifest","live-reload-active"]))}}),xe=J(_e);xe.mount("#app");
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
[data-v-2641604d]{box-sizing:border-box}.simulator-layout[data-v-2641604d]{min-height:100vh;display:flex;flex-direction:column;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;background-color:#f8f9fa;color:#1a1a2e;transition:background-color .2s,color .2s}.simulator-layout.dark-mode[data-v-2641604d]{background-color:#1a1a2e;color:#e8e8e8}.header[data-v-2641604d]{display:flex;justify-content:space-between;align-items:center;padding:.75rem 1.5rem;background:linear-gradient(135deg,#6366f1,#8b5cf6);color:#fff}.header-left[data-v-2641604d]{display:flex;align-items:center;gap:1.5rem}.header h1[data-v-2641604d]{margin:0;font-size:1.125rem;font-weight:600;letter-spacing:-.02em}.app-info[data-v-2641604d]{display:flex;align-items:center;gap:.5rem;padding:.25rem .75rem;background:#ffffff26;border-radius:4px;font-size:.8125rem}.app-name[data-v-2641604d]{font-weight:500}.app-version[data-v-2641604d]{opacity:.8;font-size:.75rem}.header-right[data-v-2641604d]{display:flex;align-items:center;gap:.75rem}.status-badge[data-v-2641604d]{display:flex;align-items:center;gap:.375rem;padding:.25rem .625rem;border-radius:999px;font-size:.75rem;font-weight:500}.status-badge.live[data-v-2641604d]{background:#22c55e33;color:#86efac}.status-dot[data-v-2641604d]{width:6px;height:6px;border-radius:50%;background:#22c55e;animation:pulse-2641604d 2s infinite}@keyframes pulse-2641604d{0%,to{opacity:1}50%{opacity:.5}}.icon-btn[data-v-2641604d]{display:flex;align-items:center;justify-content:center;width:32px;height:32px;border:none;border-radius:6px;background:#ffffff1a;color:#fff;cursor:pointer;transition:background .15s}.icon-btn[data-v-2641604d]:hover{background:#fff3}.loading-state[data-v-2641604d],.error-state[data-v-2641604d]{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:3rem;text-align:center}.spinner[data-v-2641604d]{width:40px;height:40px;border:3px solid #e5e7eb;border-top-color:#6366f1;border-radius:50%;animation:spin-2641604d .8s linear infinite}.dark-mode .spinner[data-v-2641604d]{border-color:#374151;border-top-color:#8b5cf6}@keyframes spin-2641604d{to{transform:rotate(360deg)}}.url-info[data-v-2641604d]{margin-top:.75rem;font-size:.8125rem;color:#6b7280;font-family:SF Mono,Monaco,monospace}.error-icon[data-v-2641604d]{width:48px;height:48px;display:flex;align-items:center;justify-content:center;background:#fef2f2;color:#dc2626;border-radius:50%;font-size:1.5rem;font-weight:700;margin-bottom:1rem}.dark-mode .error-icon[data-v-2641604d]{background:#450a0a}.error-message[data-v-2641604d]{color:#dc2626;font-weight:500;margin:.5rem 0}.error-details[data-v-2641604d]{margin-top:1.5rem;padding:1rem;background:#fff;border-radius:8px;font-size:.875rem}.dark-mode .error-details[data-v-2641604d]{background:#1f2937}.retry-btn[data-v-2641604d]{margin-top:1rem;padding:.5rem 1rem;background:#6366f1;color:#fff;border:none;border-radius:6px;font-weight:500;cursor:pointer;transition:background .15s}.retry-btn[data-v-2641604d]:hover{background:#4f46e5}.main-content[data-v-2641604d]{flex:1;display:flex;flex-direction:column;padding:1rem;gap:1rem}.tabs[data-v-2641604d]{display:flex;align-items:center;gap:.25rem;padding:.25rem;background:#fff;border-radius:8px;box-shadow:0 1px 2px #0000000d}.dark-mode .tabs[data-v-2641604d]{background:#1f2937}.tab[data-v-2641604d]{padding:.5rem 1rem;border:none;border-radius:6px;background:transparent;color:#6b7280;font-size:.875rem;font-weight:500;cursor:pointer;transition:all .15s}.tab[data-v-2641604d]:hover{color:#1f2937}.dark-mode .tab[data-v-2641604d]:hover{color:#e5e7eb}.tab.active[data-v-2641604d]{background:#6366f1;color:#fff}.tab-controls[data-v-2641604d]{margin-left:auto;display:flex;gap:.25rem}.control-btn[data-v-2641604d]{display:flex;align-items:center;justify-content:center;width:36px;height:32px;border:none;border-radius:6px;background:transparent;color:#9ca3af;cursor:pointer;transition:all .15s}.control-btn[data-v-2641604d]:hover{background:#f3f4f6;color:#4b5563}.dark-mode .control-btn[data-v-2641604d]:hover{background:#374151;color:#d1d5db}.control-btn.active[data-v-2641604d]{background:#ede9fe;color:#6366f1}.dark-mode .control-btn.active[data-v-2641604d]{background:#4c1d95;color:#c4b5fd}.tab-panels[data-v-2641604d]{flex:1;display:flex;flex-direction:column}.tab-panel[data-v-2641604d]{flex:1;background:#fff;border-radius:8px;box-shadow:0 1px 3px #0000000d;overflow:auto}.dark-mode .tab-panel[data-v-2641604d]{background:#1f2937}.player-panel[data-v-2641604d]{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:2rem;background:#111827}.player-panel.fullscreen[data-v-2641604d]{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1000;border-radius:0;padding:0}.player-container[data-v-2641604d]{width:100%;max-width:960px;transition:all .3s ease}.player-container.aspect-landscape[data-v-2641604d]{aspect-ratio:16 / 9}.player-container.aspect-portrait[data-v-2641604d]{aspect-ratio:9 / 16;max-width:400px}.fullscreen .player-container[data-v-2641604d]{max-width:none;width:100%;height:100%}.fullscreen .player-container.aspect-portrait[data-v-2641604d]{max-width:none;width:auto;height:100%}.player-frame[data-v-2641604d]{position:relative;width:100%;height:100%;background:#000;border-radius:4px;overflow:hidden}.player-frame[data-v-2641604d]>*{position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%}.fullscreen .player-frame[data-v-2641604d]{border-radius:0}.exit-fullscreen[data-v-2641604d]{position:fixed;top:1rem;right:1rem;padding:.5rem 1rem;background:#000000bf;color:#fff;border:none;border-radius:6px;font-size:.875rem;cursor:pointer;z-index:1001}.exit-fullscreen[data-v-2641604d]:hover{background:#000000e6}.config-panel[data-v-2641604d]{padding:1.5rem;overflow-y:auto}.meta-panel[data-v-2641604d]{padding:1rem}.meta-header[data-v-2641604d]{display:flex;justify-content:space-between;align-items:center;margin-bottom:.75rem}.meta-header h3[data-v-2641604d]{margin:0;font-size:.875rem;font-weight:600;color:#6b7280}.copy-btn[data-v-2641604d]{padding:.25rem .5rem;background:#f3f4f6;border:none;border-radius:4px;font-size:.75rem;color:#4b5563;cursor:pointer}.dark-mode .copy-btn[data-v-2641604d]{background:#374151;color:#d1d5db}.copy-btn[data-v-2641604d]:hover{background:#e5e7eb}.dark-mode .copy-btn[data-v-2641604d]:hover{background:#4b5563}.meta-code[data-v-2641604d]{margin:0;padding:1rem;background:#f9fafb;border-radius:6px;font-family:SF Mono,Monaco,Courier New,monospace;font-size:.8125rem;line-height:1.6;overflow-x:auto;white-space:pre-wrap;word-break:break-word}.dark-mode .meta-code[data-v-2641604d]{background:#111827;color:#e5e7eb}.placeholder[data-v-2641604d]{display:flex;align-items:center;justify-content:center;height:100%;min-height:200px;color:#9ca3af;font-style:italic}@media (max-width: 640px){.header[data-v-2641604d]{padding:.5rem 1rem}.header h1[data-v-2641604d]{font-size:1rem}.app-info[data-v-2641604d]{display:none}.tabs[data-v-2641604d]{flex-wrap:wrap}.tab-controls[data-v-2641604d]{width:100%;justify-content:center;margin-top:.5rem;margin-left:0}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{defineComponent as D,ref as y,computed as S,createElementBlock as d,openBlock as r,normalizeClass as g,createElementVNode as e,createCommentVNode as A,toDisplayString as _,createTextVNode as O,withDirectives as R,createBlock as B,resolveDynamicComponent as U,vShow as $,shallowRef as N,reactive as V,onMounted as F,unref as I,markRaw as P,createApp as J}from"vue";import{provideAppConfigContext as q}from"@juuno-sdk/app-sdk";(function(){const h=document.createElement("link").relList;if(h&&h.supports&&h.supports("modulepreload"))return;for(const o of document.querySelectorAll('link[rel="modulepreload"]'))b(o);new MutationObserver(o=>{for(const n of o)if(n.type==="childList")for(const s of n.addedNodes)s.tagName==="LINK"&&s.rel==="modulepreload"&&b(s)}).observe(document,{childList:!0,subtree:!0});function v(o){const n={};return o.integrity&&(n.integrity=o.integrity),o.referrerPolicy&&(n.referrerPolicy=o.referrerPolicy),o.crossOrigin==="use-credentials"?n.credentials="include":o.crossOrigin==="anonymous"?n.credentials="omit":n.credentials="same-origin",n}function b(o){if(o.ep)return;o.ep=!0;const n=v(o);fetch(o.href,n)}})();const z="modulepreload",H=function(a){return"/"+a},T={},j=function(h,v,b){let o=Promise.resolve();if(v&&v.length>0){let s=function(l){return Promise.all(l.map(p=>Promise.resolve(p).then(x=>({status:"fulfilled",value:x}),x=>({status:"rejected",reason:x}))))};document.getElementsByTagName("link");const i=document.querySelector("meta[property=csp-nonce]"),m=(i==null?void 0:i.nonce)||(i==null?void 0:i.getAttribute("nonce"));o=s(v.map(l=>{if(l=H(l),l in T)return;T[l]=!0;const p=l.endsWith(".css"),x=p?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${l}"]${x}`))return;const k=document.createElement("link");if(k.rel=p?"stylesheet":z,p||(k.as="script"),k.crossOrigin="",k.href=l,m&&k.setAttribute("nonce",m),document.head.appendChild(k),p)return new Promise((E,L)=>{k.addEventListener("load",E),k.addEventListener("error",()=>L(new Error(`Unable to preload CSS for ${l}`)))})}))}function n(s){const i=new Event("vite:preloadError",{cancelable:!0});if(i.payload=s,window.dispatchEvent(i),!i.defaultPrevented)throw s}return o.then(s=>{for(const i of s||[])i.status==="rejected"&&n(i.reason);return h().catch(n)})},W={class:"header"},K={class:"header-left"},X={class:"app-info"},G={class:"app-name"},Q={key:0,class:"app-version"},Y={class:"header-right"},Z={key:0,class:"status-badge live"},ee={key:0,width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2"},te={key:1,width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2"},oe={key:0,class:"loading-state"},ne={class:"url-info"},le={key:1,class:"error-state"},se={class:"error-message"},ie={class:"error-details"},ae={key:2,class:"main-content"},re={class:"tabs"},ue={key:0,class:"tab-controls"},ce={class:"tab-panels"},de={class:"player-frame"},ve={key:1,class:"placeholder"},pe={class:"player-controls"},fe={class:"controls-group"},me=["title"],ge={key:0,width:"20",height:"20",viewBox:"0 0 24 24",fill:"currentColor"},he={key:1,width:"20",height:"20",viewBox:"0 0 24 24",fill:"currentColor"},ye=["title"],we={key:0,width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2"},ke={key:1,width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2"},Ce=["title"],be={key:0,width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2"},xe={key:1,width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2"},_e={class:"controls-info"},Ee={class:"tab-panel config-panel"},Le={key:1,class:"placeholder"},Me={class:"tab-panel meta-panel"},Se={class:"meta-header"},Ae={class:"meta-code"},Pe={name:"SimulatorLayout"},Re=D({...Pe,props:{playerComponent:{},configComponent:{},scene:{},appUrl:{},isLoading:{type:Boolean},error:{},manifest:{},liveReloadActive:{type:Boolean}},emits:["reload"],setup(a,{emit:h}){const v=a,b=h,o=y("player"),n=y("landscape"),s=y(!1),i=y(!1);y(!0);const m=y(!0),l=y(!0),p=y(!1),x=y(3e4),k=S(()=>{var f;return((f=v.manifest)==null?void 0:f.name)||"External App"}),E=S(()=>{var f;return((f=v.manifest)==null?void 0:f.version)||""}),L=S(()=>n.value==="landscape"?"aspect-landscape":"aspect-portrait"),M=S(()=>{var f;try{return JSON.stringify(((f=v.scene)==null?void 0:f.meta)||{},null,2)}catch{return"{}"}});function w(){s.value=!s.value}function C(){i.value=!i.value}function u(){b("reload")}return(f,t)=>(r(),d("div",{class:g(["simulator-layout",{"dark-mode":i.value}])},[e("header",W,[e("div",K,[t[10]||(t[10]=e("h1",null,"Juuno Simulator",-1)),e("div",X,[e("span",G,_(k.value),1),E.value?(r(),d("span",Q,"v"+_(E.value),1)):A("",!0)])]),e("div",Y,[a.liveReloadActive?(r(),d("div",Z,[...t[11]||(t[11]=[e("span",{class:"status-dot"},null,-1),O(" Live ",-1)])])):A("",!0),e("button",{class:"icon-btn",title:"Reload app",onClick:u},[...t[12]||(t[12]=[e("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2"},[e("path",{d:"M23 4v6h-6M1 20v-6h6M3.51 9a9 9 0 0114.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0020.49 15"})],-1)])]),e("button",{class:"icon-btn",title:"Toggle dark mode",onClick:C},[i.value?(r(),d("svg",te,[...t[14]||(t[14]=[e("path",{d:"M21 12.79A9 9 0 1111.21 3 7 7 0 0021 12.79z"},null,-1)])])):(r(),d("svg",ee,[...t[13]||(t[13]=[e("circle",{cx:"12",cy:"12",r:"5"},null,-1),e("path",{d:"M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"},null,-1)])]))])])]),a.isLoading?(r(),d("div",oe,[t[15]||(t[15]=e("div",{class:"spinner"},null,-1)),t[16]||(t[16]=e("p",null,"Loading app...",-1)),e("p",ne,_(a.appUrl),1)])):a.error?(r(),d("div",le,[t[18]||(t[18]=e("div",{class:"error-icon"},"!",-1)),t[19]||(t[19]=e("h2",null,"Failed to Load App",-1)),e("p",se,_(a.error),1),e("div",ie,[e("p",null,[t[17]||(t[17]=e("strong",null,"App URL:",-1)),O(" "+_(a.appUrl),1)]),e("button",{class:"retry-btn",onClick:u},"Try Again")])])):(r(),d("div",ae,[e("div",re,[e("button",{class:g(["tab",{active:o.value==="player"}]),onClick:t[0]||(t[0]=c=>o.value="player")}," Player ",2),e("button",{class:g(["tab",{active:o.value==="config"}]),onClick:t[1]||(t[1]=c=>o.value="config")}," Config ",2),e("button",{class:g(["tab",{active:o.value==="meta"}]),onClick:t[2]||(t[2]=c=>o.value="meta")}," Scene Meta ",2),o.value==="player"?(r(),d("div",ue,[e("button",{class:g(["control-btn",{active:n.value==="landscape"}]),title:"Landscape (16:9)",onClick:t[3]||(t[3]=c=>n.value="landscape")},[...t[20]||(t[20]=[e("svg",{width:"18",height:"12",viewBox:"0 0 18 12",fill:"currentColor"},[e("rect",{x:"0.5",y:"0.5",width:"17",height:"11",rx:"1",fill:"none",stroke:"currentColor"})],-1)])],2),e("button",{class:g(["control-btn",{active:n.value==="portrait"}]),title:"Portrait (9:16)",onClick:t[4]||(t[4]=c=>n.value="portrait")},[...t[21]||(t[21]=[e("svg",{width:"12",height:"18",viewBox:"0 0 12 18",fill:"currentColor"},[e("rect",{x:"0.5",y:"0.5",width:"11",height:"17",rx:"1",fill:"none",stroke:"currentColor"})],-1)])],2),e("button",{class:g(["control-btn",{active:s.value}]),title:"Fullscreen",onClick:w},[...t[22]||(t[22]=[e("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2"},[e("path",{d:"M8 3H5a2 2 0 00-2 2v3m18 0V5a2 2 0 00-2-2h-3m0 18h3a2 2 0 002-2v-3M3 16v3a2 2 0 002 2h3"})],-1)])],2)])):A("",!0)]),e("div",ce,[R(e("div",{class:g(["tab-panel player-panel",{fullscreen:s.value}])},[e("div",{class:g(["player-container",L.value])},[e("div",de,[a.playerComponent?(r(),B(U(a.playerComponent),{key:a.scene.idx,scene:a.scene,playing:m.value,"is-visible":l.value,"duration-ms":x.value,muted:p.value},null,8,["scene","playing","is-visible","duration-ms","muted"])):(r(),d("div",ve,"No player component"))])],2),e("div",pe,[e("div",fe,[e("button",{class:g(["player-btn",{active:m.value}]),title:m.value?"Pause":"Play",onClick:t[5]||(t[5]=c=>m.value=!m.value)},[m.value?(r(),d("svg",ge,[...t[23]||(t[23]=[e("rect",{x:"6",y:"4",width:"4",height:"16"},null,-1),e("rect",{x:"14",y:"4",width:"4",height:"16"},null,-1)])])):(r(),d("svg",he,[...t[24]||(t[24]=[e("polygon",{points:"5,3 19,12 5,21"},null,-1)])]))],10,me),e("button",{class:g(["player-btn",{active:!l.value}]),title:l.value?"Hide (simulate off-screen)":"Show",onClick:t[6]||(t[6]=c=>l.value=!l.value)},[l.value?(r(),d("svg",we,[...t[25]||(t[25]=[e("path",{d:"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"},null,-1),e("circle",{cx:"12",cy:"12",r:"3"},null,-1)])])):(r(),d("svg",ke,[...t[26]||(t[26]=[e("path",{d:"M17.94 17.94A10.07 10.07 0 0112 20c-7 0-11-8-11-8a18.45 18.45 0 015.06-5.94M9.9 4.24A9.12 9.12 0 0112 4c7 0 11 8 11 8a18.5 18.5 0 01-2.16 3.19m-6.72-1.07a3 3 0 11-4.24-4.24"},null,-1),e("line",{x1:"1",y1:"1",x2:"23",y2:"23"},null,-1)])]))],10,ye),e("button",{class:g(["player-btn",{active:p.value}]),title:p.value?"Unmute":"Mute",onClick:t[7]||(t[7]=c=>p.value=!p.value)},[p.value?(r(),d("svg",xe,[...t[28]||(t[28]=[e("polygon",{points:"11,5 6,9 2,9 2,15 6,15 11,19"},null,-1),e("line",{x1:"23",y1:"9",x2:"17",y2:"15"},null,-1),e("line",{x1:"17",y1:"9",x2:"23",y2:"15"},null,-1)])])):(r(),d("svg",be,[...t[27]||(t[27]=[e("polygon",{points:"11,5 6,9 2,9 2,15 6,15 11,19"},null,-1),e("path",{d:"M19.07 4.93a10 10 0 010 14.14M15.54 8.46a5 5 0 010 7.07"},null,-1)])]))],10,Ce)]),e("div",_e,[e("span",{class:g(["state-badge",{inactive:!m.value}])},_(m.value?"Playing":"Paused"),3),e("span",{class:g(["state-badge",{inactive:!l.value}])},_(l.value?"Visible":"Hidden"),3),e("span",{class:g(["state-badge",{inactive:!p.value}])},_(p.value?"Muted":"Sound On"),3)])]),s.value?(r(),d("button",{key:0,class:"exit-fullscreen",onClick:t[8]||(t[8]=c=>s.value=!1)}," Exit Fullscreen ")):A("",!0)],2),[[$,o.value==="player"]]),R(e("div",Ee,[a.configComponent?(r(),B(U(a.configComponent),{key:"config-"+a.scene.idx})):(r(),d("div",Le,"No config component"))],512),[[$,o.value==="config"]]),R(e("div",Me,[e("div",Se,[t[29]||(t[29]=e("h3",null,"scene.meta",-1)),e("button",{class:"copy-btn",onClick:t[9]||(t[9]=c=>f.navigator.clipboard.writeText(M.value))}," Copy ")]),e("pre",Ae,_(M.value),1)],512),[[$,o.value==="meta"]])])]))],2))}}),$e=(a,h)=>{const v=a.__vccOpts||a;for(const[b,o]of h)v[b]=o;return v},Be=$e(Re,[["__scopeId","data-v-2ce117d9"]]),Oe={name:"JuunoCLI"},Ue=D({...Oe,setup(a){const h=y(window.__JUUNO_EXTERNAL_APP_URL__||"http://localhost:5002/index.js"),v=y(window.__JUUNO_LIVE_RELOAD__||!1),b=y(null),o=[],n=N(null),s=N(null),i=y(!0),m=y(null),l=V({idx:"simulator-scene-1",name:"Simulator Test Scene",app:null,app_idx:"simulator-app-1",created_at:new Date().toISOString(),display_time:5e3,language:"en",order:0,playlist_idx:"simulator-playlist-1",updated_at:new Date().toISOString(),translations:{},meta:{title:"Test App",backgroundColor:"#2c3e50",textColor:"#ecf0f1"},mediaAssets:[]}),x=q({async save(w){console.log("Simulator: Scene updated",w),Object.assign(l,w)}},{scene:l});async function k(){try{const w=await fetch(`${h.value}/manifest.json`);if(w.ok){const C=await w.json();return b.value=C,C}}catch{}return b.value=null,null}function E(w){o.forEach(C=>C.remove()),o.length=0,w.forEach(C=>{const u=document.createElement("link");u.rel="stylesheet",u.href=`${h.value}${C}`,document.head.appendChild(u),o.push(u)})}async function L(){var w,C;try{i.value=!0,m.value=null,console.log(`Loading external app from: ${h.value}`);const u=await k(),f=[];(w=u==null?void 0:u.resources)!=null&&w.player&&f.push(...u.resources.player.filter(c=>c.endsWith(".css"))),(C=u==null?void 0:u.resources)!=null&&C.config&&f.push(...u.resources.config.filter(c=>c.endsWith(".css"))),f.length>0&&(console.log("Loading CSS files:",f),E(f));const t=await j(()=>import("external-app/player"),[]);if(t.default)n.value=P(t.default);else if(typeof t.render=="function")n.value=P(t.render());else throw new Error("External app must export a default component or render function from /player");try{const c=await j(()=>import("external-app/config"),[]);c.default?s.value=P(c.default):typeof c.render=="function"?s.value=P(c.render()):s.value=null}catch{s.value=null}x.load(l),console.log("✅ External app loaded successfully"),i.value=!1}catch(u){console.error("Failed to load external app:",u),m.value=u instanceof Error?u.message:"Failed to load external app",i.value=!1}}function M(){console.log("🔄 Reloading app..."),window.location.reload()}return typeof window<"u"&&(window.addEventListener("juuno:live-reload-connected",()=>{v.value=!0}),window.addEventListener("juuno:live-reload-disconnected",()=>{v.value=!1})),F(L),(w,C)=>(r(),B(I(Be),{"player-component":n.value,"config-component":s.value,scene:l,"app-url":h.value,"is-loading":i.value,error:m.value,manifest:b.value,"live-reload-active":v.value,onReload:M},null,8,["player-component","config-component","scene","app-url","is-loading","error","manifest","live-reload-active"]))}}),Ne=J(Ue);Ne.mount("#app");
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{defineComponent as B,ref as h,computed as x,createElementBlock as f,openBlock as u,normalizeClass as k,createElementVNode as e,createCommentVNode as E,toDisplayString as b,createTextVNode as R,withDirectives as A,createBlock as M,resolveDynamicComponent as P,vShow as S,shallowRef as O,reactive as N,onMounted as T,unref as D,markRaw as L,createApp as j}from"vue";import{provideAppConfigContext as F}from"@juuno-sdk/app-sdk";(function(){const p=document.createElement("link").relList;if(p&&p.supports&&p.supports("modulepreload"))return;for(const o of document.querySelectorAll('link[rel="modulepreload"]'))m(o);new MutationObserver(o=>{for(const n of o)if(n.type==="childList")for(const l of n.addedNodes)l.tagName==="LINK"&&l.rel==="modulepreload"&&m(l)}).observe(document,{childList:!0,subtree:!0});function c(o){const n={};return o.integrity&&(n.integrity=o.integrity),o.referrerPolicy&&(n.referrerPolicy=o.referrerPolicy),o.crossOrigin==="use-credentials"?n.credentials="include":o.crossOrigin==="anonymous"?n.credentials="omit":n.credentials="same-origin",n}function m(o){if(o.ep)return;o.ep=!0;const n=c(o);fetch(o.href,n)}})();const I="modulepreload",V=function(s){return"/"+s},$={},U=function(p,c,m){let o=Promise.resolve();if(c&&c.length>0){let l=function(d){return Promise.all(d.map(g=>Promise.resolve(g).then(y=>({status:"fulfilled",value:y}),y=>({status:"rejected",reason:y}))))};document.getElementsByTagName("link");const a=document.querySelector("meta[property=csp-nonce]"),w=(a==null?void 0:a.nonce)||(a==null?void 0:a.getAttribute("nonce"));o=l(c.map(d=>{if(d=V(d),d in $)return;$[d]=!0;const g=d.endsWith(".css"),y=g?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${d}"]${y}`))return;const v=document.createElement("link");if(v.rel=g?"stylesheet":I,g||(v.as="script"),v.crossOrigin="",v.href=d,w&&v.setAttribute("nonce",w),document.head.appendChild(v),g)return new Promise((_,r)=>{v.addEventListener("load",_),v.addEventListener("error",()=>r(new Error(`Unable to preload CSS for ${d}`)))})}))}function n(l){const a=new Event("vite:preloadError",{cancelable:!0});if(a.payload=l,window.dispatchEvent(a),!a.defaultPrevented)throw l}return o.then(l=>{for(const a of l||[])a.status==="rejected"&&n(a.reason);return p().catch(n)})},J={class:"header"},q={class:"header-left"},z={class:"app-info"},H={class:"app-name"},K={key:0,class:"app-version"},W={class:"header-right"},X={key:0,class:"status-badge live"},G={key:0,width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2"},Q={key:1,width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2"},Y={key:0,class:"loading-state"},Z={class:"url-info"},ee={key:1,class:"error-state"},te={class:"error-message"},oe={class:"error-details"},ne={key:2,class:"main-content"},le={class:"tabs"},ae={key:0,class:"tab-controls"},se={class:"tab-panels"},re={class:"player-frame"},ie={key:1,class:"placeholder"},ce={class:"tab-panel config-panel"},ue={key:1,class:"placeholder"},de={class:"tab-panel meta-panel"},pe={class:"meta-header"},ve={class:"meta-code"},fe={name:"SimulatorLayout"},me=B({...fe,props:{playerComponent:{},configComponent:{},scene:{},appUrl:{},isLoading:{type:Boolean},error:{},manifest:{},liveReloadActive:{type:Boolean}},emits:["reload"],setup(s,{emit:p}){const c=s,m=p,o=h("player"),n=h("landscape"),l=h(!1),a=h(!1);h(!0);const w=x(()=>{var i;return((i=c.manifest)==null?void 0:i.name)||"External App"}),d=x(()=>{var i;return((i=c.manifest)==null?void 0:i.version)||""}),g=x(()=>n.value==="landscape"?"aspect-landscape":"aspect-portrait"),y=x(()=>{var i;try{return JSON.stringify(((i=c.scene)==null?void 0:i.meta)||{},null,2)}catch{return"{}"}});function v(){l.value=!l.value}function _(){a.value=!a.value}function r(){m("reload")}return(i,t)=>(u(),f("div",{class:k(["simulator-layout",{"dark-mode":a.value}])},[e("header",J,[e("div",q,[t[7]||(t[7]=e("h1",null,"Juuno Simulator",-1)),e("div",z,[e("span",H,b(w.value),1),d.value?(u(),f("span",K,"v"+b(d.value),1)):E("",!0)])]),e("div",W,[s.liveReloadActive?(u(),f("div",X,[...t[8]||(t[8]=[e("span",{class:"status-dot"},null,-1),R(" Live ",-1)])])):E("",!0),e("button",{class:"icon-btn",title:"Reload app",onClick:r},[...t[9]||(t[9]=[e("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2"},[e("path",{d:"M23 4v6h-6M1 20v-6h6M3.51 9a9 9 0 0114.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0020.49 15"})],-1)])]),e("button",{class:"icon-btn",title:"Toggle dark mode",onClick:_},[a.value?(u(),f("svg",Q,[...t[11]||(t[11]=[e("path",{d:"M21 12.79A9 9 0 1111.21 3 7 7 0 0021 12.79z"},null,-1)])])):(u(),f("svg",G,[...t[10]||(t[10]=[e("circle",{cx:"12",cy:"12",r:"5"},null,-1),e("path",{d:"M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"},null,-1)])]))])])]),s.isLoading?(u(),f("div",Y,[t[12]||(t[12]=e("div",{class:"spinner"},null,-1)),t[13]||(t[13]=e("p",null,"Loading app...",-1)),e("p",Z,b(s.appUrl),1)])):s.error?(u(),f("div",ee,[t[15]||(t[15]=e("div",{class:"error-icon"},"!",-1)),t[16]||(t[16]=e("h2",null,"Failed to Load App",-1)),e("p",te,b(s.error),1),e("div",oe,[e("p",null,[t[14]||(t[14]=e("strong",null,"App URL:",-1)),R(" "+b(s.appUrl),1)]),e("button",{class:"retry-btn",onClick:r},"Try Again")])])):(u(),f("div",ne,[e("div",le,[e("button",{class:k(["tab",{active:o.value==="player"}]),onClick:t[0]||(t[0]=C=>o.value="player")}," Player ",2),e("button",{class:k(["tab",{active:o.value==="config"}]),onClick:t[1]||(t[1]=C=>o.value="config")}," Config ",2),e("button",{class:k(["tab",{active:o.value==="meta"}]),onClick:t[2]||(t[2]=C=>o.value="meta")}," Scene Meta ",2),o.value==="player"?(u(),f("div",ae,[e("button",{class:k(["control-btn",{active:n.value==="landscape"}]),title:"Landscape (16:9)",onClick:t[3]||(t[3]=C=>n.value="landscape")},[...t[17]||(t[17]=[e("svg",{width:"18",height:"12",viewBox:"0 0 18 12",fill:"currentColor"},[e("rect",{x:"0.5",y:"0.5",width:"17",height:"11",rx:"1",fill:"none",stroke:"currentColor"})],-1)])],2),e("button",{class:k(["control-btn",{active:n.value==="portrait"}]),title:"Portrait (9:16)",onClick:t[4]||(t[4]=C=>n.value="portrait")},[...t[18]||(t[18]=[e("svg",{width:"12",height:"18",viewBox:"0 0 12 18",fill:"currentColor"},[e("rect",{x:"0.5",y:"0.5",width:"11",height:"17",rx:"1",fill:"none",stroke:"currentColor"})],-1)])],2),e("button",{class:k(["control-btn",{active:l.value}]),title:"Fullscreen",onClick:v},[...t[19]||(t[19]=[e("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2"},[e("path",{d:"M8 3H5a2 2 0 00-2 2v3m18 0V5a2 2 0 00-2-2h-3m0 18h3a2 2 0 002-2v-3M3 16v3a2 2 0 002 2h3"})],-1)])],2)])):E("",!0)]),e("div",se,[A(e("div",{class:k(["tab-panel player-panel",{fullscreen:l.value}])},[e("div",{class:k(["player-container",g.value])},[e("div",re,[s.playerComponent?(u(),M(P(s.playerComponent),{key:0,scene:s.scene,playing:!0,"is-visible":!0,"duration-ms":5e3},null,8,["scene"])):(u(),f("div",ie,"No player component"))])],2),l.value?(u(),f("button",{key:0,class:"exit-fullscreen",onClick:t[5]||(t[5]=C=>l.value=!1)}," Exit Fullscreen ")):E("",!0)],2),[[S,o.value==="player"]]),A(e("div",ce,[s.configComponent?(u(),M(P(s.configComponent),{key:0})):(u(),f("div",ue,"No config component"))],512),[[S,o.value==="config"]]),A(e("div",de,[e("div",pe,[t[20]||(t[20]=e("h3",null,"scene.meta",-1)),e("button",{class:"copy-btn",onClick:t[6]||(t[6]=C=>i.navigator.clipboard.writeText(y.value))}," Copy ")]),e("pre",ve,b(y.value),1)],512),[[S,o.value==="meta"]])])]))],2))}}),ge=(s,p)=>{const c=s.__vccOpts||s;for(const[m,o]of p)c[m]=o;return c},ye=ge(me,[["__scopeId","data-v-e190f6cf"]]),he={name:"JuunoCLI"},we=B({...he,setup(s){const p=h(window.__JUUNO_EXTERNAL_APP_URL__||"http://localhost:5002/index.js"),c=h(window.__JUUNO_LIVE_RELOAD__||!1),m=h(null),o=O(null),n=O(null),l=h(!0),a=h(null),w=N({idx:"simulator-scene-1",name:"Simulator Test Scene",app:null,app_idx:"simulator-app-1",created_at:new Date().toISOString(),display_time:5e3,language:"en",order:0,playlist_idx:"simulator-playlist-1",updated_at:new Date().toISOString(),translations:{},meta:{title:"Test App",backgroundColor:"#2c3e50",textColor:"#ecf0f1"},mediaAssets:[]}),g=F({async save(r){console.log("Simulator: Scene updated",r),Object.assign(w,r)}},{scene:w});async function y(){try{const r=await fetch(`${p.value}/manifest.json`);r.ok&&(m.value=await r.json())}catch{m.value=null}}async function v(){try{l.value=!0,a.value=null,console.log(`Loading external app from: ${p.value}`),y();const r=await U(()=>import("external-app/player"),[]);if(r.default)o.value=L(r.default);else if(typeof r.render=="function")o.value=L(r.render());else throw new Error("External app must export a default component or render function from /player");try{const i=await U(()=>import("external-app/config"),[]);i.default?n.value=L(i.default):typeof i.render=="function"?n.value=L(i.render()):n.value=null}catch(i){console.warn("Config component not found or failed to load:",i),n.value=null}g.load(w),console.log("✅ External app loaded successfully"),l.value=!1}catch(r){console.error("Failed to load external app:",r),a.value=r instanceof Error?r.message:"Failed to load external app",l.value=!1}}function _(){console.log("🔄 Reloading app..."),window.location.reload()}return typeof window<"u"&&(window.addEventListener("juuno:live-reload-connected",()=>{c.value=!0}),window.addEventListener("juuno:live-reload-disconnected",()=>{c.value=!1})),T(v),(r,i)=>(u(),M(D(ye),{"player-component":o.value,"config-component":n.value,scene:w,"app-url":p.value,"is-loading":l.value,error:a.value,manifest:m.value,"live-reload-active":c.value,onReload:_},null,8,["player-component","config-component","scene","app-url","is-loading","error","manifest","live-reload-active"]))}}),ke=j(we);ke.mount("#app");
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
[data-v-2ce117d9]{box-sizing:border-box}.simulator-layout[data-v-2ce117d9]{min-height:100vh;display:flex;flex-direction:column;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;background-color:#f8f9fa;color:#1a1a2e;transition:background-color .2s,color .2s}.simulator-layout.dark-mode[data-v-2ce117d9]{background-color:#1a1a2e;color:#e8e8e8}.header[data-v-2ce117d9]{display:flex;justify-content:space-between;align-items:center;padding:.75rem 1.5rem;background:linear-gradient(135deg,#6366f1,#8b5cf6);color:#fff}.header-left[data-v-2ce117d9]{display:flex;align-items:center;gap:1.5rem}.header h1[data-v-2ce117d9]{margin:0;font-size:1.125rem;font-weight:600;letter-spacing:-.02em}.app-info[data-v-2ce117d9]{display:flex;align-items:center;gap:.5rem;padding:.25rem .75rem;background:#ffffff26;border-radius:4px;font-size:.8125rem}.app-name[data-v-2ce117d9]{font-weight:500}.app-version[data-v-2ce117d9]{opacity:.8;font-size:.75rem}.header-right[data-v-2ce117d9]{display:flex;align-items:center;gap:.75rem}.status-badge[data-v-2ce117d9]{display:flex;align-items:center;gap:.375rem;padding:.25rem .625rem;border-radius:999px;font-size:.75rem;font-weight:500}.status-badge.live[data-v-2ce117d9]{background:#22c55e33;color:#86efac}.status-dot[data-v-2ce117d9]{width:6px;height:6px;border-radius:50%;background:#22c55e;animation:pulse-2ce117d9 2s infinite}@keyframes pulse-2ce117d9{0%,to{opacity:1}50%{opacity:.5}}.icon-btn[data-v-2ce117d9]{display:flex;align-items:center;justify-content:center;width:32px;height:32px;border:none;border-radius:6px;background:#ffffff1a;color:#fff;cursor:pointer;transition:background .15s}.icon-btn[data-v-2ce117d9]:hover{background:#fff3}.loading-state[data-v-2ce117d9],.error-state[data-v-2ce117d9]{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:3rem;text-align:center}.spinner[data-v-2ce117d9]{width:40px;height:40px;border:3px solid #e5e7eb;border-top-color:#6366f1;border-radius:50%;animation:spin-2ce117d9 .8s linear infinite}.dark-mode .spinner[data-v-2ce117d9]{border-color:#374151;border-top-color:#8b5cf6}@keyframes spin-2ce117d9{to{transform:rotate(360deg)}}.url-info[data-v-2ce117d9]{margin-top:.75rem;font-size:.8125rem;color:#6b7280;font-family:SF Mono,Monaco,monospace}.error-icon[data-v-2ce117d9]{width:48px;height:48px;display:flex;align-items:center;justify-content:center;background:#fef2f2;color:#dc2626;border-radius:50%;font-size:1.5rem;font-weight:700;margin-bottom:1rem}.dark-mode .error-icon[data-v-2ce117d9]{background:#450a0a}.error-message[data-v-2ce117d9]{color:#dc2626;font-weight:500;margin:.5rem 0}.error-details[data-v-2ce117d9]{margin-top:1.5rem;padding:1rem;background:#fff;border-radius:8px;font-size:.875rem}.dark-mode .error-details[data-v-2ce117d9]{background:#1f2937}.retry-btn[data-v-2ce117d9]{margin-top:1rem;padding:.5rem 1rem;background:#6366f1;color:#fff;border:none;border-radius:6px;font-weight:500;cursor:pointer;transition:background .15s}.retry-btn[data-v-2ce117d9]:hover{background:#4f46e5}.main-content[data-v-2ce117d9]{flex:1;display:flex;flex-direction:column;padding:1rem;gap:1rem}.tabs[data-v-2ce117d9]{display:flex;align-items:center;gap:.25rem;padding:.25rem;background:#fff;border-radius:8px;box-shadow:0 1px 2px #0000000d}.dark-mode .tabs[data-v-2ce117d9]{background:#1f2937}.tab[data-v-2ce117d9]{padding:.5rem 1rem;border:none;border-radius:6px;background:transparent;color:#6b7280;font-size:.875rem;font-weight:500;cursor:pointer;transition:all .15s}.tab[data-v-2ce117d9]:hover{color:#1f2937}.dark-mode .tab[data-v-2ce117d9]:hover{color:#e5e7eb}.tab.active[data-v-2ce117d9]{background:#6366f1;color:#fff}.tab-controls[data-v-2ce117d9]{margin-left:auto;display:flex;gap:.25rem}.control-btn[data-v-2ce117d9]{display:flex;align-items:center;justify-content:center;width:36px;height:32px;border:none;border-radius:6px;background:transparent;color:#9ca3af;cursor:pointer;transition:all .15s}.control-btn[data-v-2ce117d9]:hover{background:#f3f4f6;color:#4b5563}.dark-mode .control-btn[data-v-2ce117d9]:hover{background:#374151;color:#d1d5db}.control-btn.active[data-v-2ce117d9]{background:#ede9fe;color:#6366f1}.dark-mode .control-btn.active[data-v-2ce117d9]{background:#4c1d95;color:#c4b5fd}.tab-panels[data-v-2ce117d9]{flex:1;display:flex;flex-direction:column}.tab-panel[data-v-2ce117d9]{flex:1;background:#fff;border-radius:8px;box-shadow:0 1px 3px #0000000d;overflow:auto}.dark-mode .tab-panel[data-v-2ce117d9]{background:#1f2937}.player-panel[data-v-2ce117d9]{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:2rem;background:#111827}.player-panel.fullscreen[data-v-2ce117d9]{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1000;border-radius:0;padding:0}.player-container[data-v-2ce117d9]{width:100%;max-width:960px;transition:all .3s ease}.player-container.aspect-landscape[data-v-2ce117d9]{aspect-ratio:16 / 9}.player-container.aspect-portrait[data-v-2ce117d9]{aspect-ratio:9 / 16;max-width:400px}.fullscreen .player-container[data-v-2ce117d9]{max-width:none;width:100%;height:100%}.fullscreen .player-container.aspect-portrait[data-v-2ce117d9]{max-width:none;width:auto;height:100%}.player-frame[data-v-2ce117d9]{position:relative;width:100%;height:100%;background:#000;border-radius:4px;overflow:hidden}.player-frame[data-v-2ce117d9]>*{position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%}.fullscreen .player-frame[data-v-2ce117d9]{border-radius:0}.exit-fullscreen[data-v-2ce117d9]{position:fixed;top:1rem;right:1rem;padding:.5rem 1rem;background:#000000bf;color:#fff;border:none;border-radius:6px;font-size:.875rem;cursor:pointer;z-index:1001}.exit-fullscreen[data-v-2ce117d9]:hover{background:#000000e6}.player-controls[data-v-2ce117d9]{display:flex;align-items:center;justify-content:center;gap:1.5rem;margin-top:1rem;padding:.75rem 1rem;background:#ffffff1a;border-radius:8px}.fullscreen .player-controls[data-v-2ce117d9]{position:fixed;bottom:1rem;left:50%;transform:translate(-50%);background:#000000bf;z-index:1001}.controls-group[data-v-2ce117d9]{display:flex;gap:.5rem}.player-btn[data-v-2ce117d9]{display:flex;align-items:center;justify-content:center;width:40px;height:40px;border:none;border-radius:8px;background:#ffffff1a;color:#e5e7eb;cursor:pointer;transition:all .15s}.player-btn[data-v-2ce117d9]:hover{background:#fff3;color:#fff}.player-btn.active[data-v-2ce117d9]{background:#6366f1;color:#fff}.controls-info[data-v-2ce117d9]{display:flex;gap:.5rem}.state-badge[data-v-2ce117d9]{padding:.25rem .5rem;border-radius:4px;font-size:.75rem;font-weight:500;background:#22c55e33;color:#86efac}.state-badge.inactive[data-v-2ce117d9]{background:#ef444433;color:#fca5a5}.config-panel[data-v-2ce117d9]{padding:1.5rem;overflow-y:auto}.meta-panel[data-v-2ce117d9]{padding:1rem}.meta-header[data-v-2ce117d9]{display:flex;justify-content:space-between;align-items:center;margin-bottom:.75rem}.meta-header h3[data-v-2ce117d9]{margin:0;font-size:.875rem;font-weight:600;color:#6b7280}.copy-btn[data-v-2ce117d9]{padding:.25rem .5rem;background:#f3f4f6;border:none;border-radius:4px;font-size:.75rem;color:#4b5563;cursor:pointer}.dark-mode .copy-btn[data-v-2ce117d9]{background:#374151;color:#d1d5db}.copy-btn[data-v-2ce117d9]:hover{background:#e5e7eb}.dark-mode .copy-btn[data-v-2ce117d9]:hover{background:#4b5563}.meta-code[data-v-2ce117d9]{margin:0;padding:1rem;background:#f9fafb;border-radius:6px;font-family:SF Mono,Monaco,Courier New,monospace;font-size:.8125rem;line-height:1.6;overflow-x:auto;white-space:pre-wrap;word-break:break-word}.dark-mode .meta-code[data-v-2ce117d9]{background:#111827;color:#e5e7eb}.placeholder[data-v-2ce117d9]{display:flex;align-items:center;justify-content:center;height:100%;min-height:200px;color:#9ca3af;font-style:italic}@media (max-width: 640px){.header[data-v-2ce117d9]{padding:.5rem 1rem}.header h1[data-v-2ce117d9]{font-size:1rem}.app-info[data-v-2ce117d9]{display:none}.tabs[data-v-2ce117d9]{flex-wrap:wrap}.tab-controls[data-v-2ce117d9]{width:100%;justify-content:center;margin-top:.5rem;margin-left:0}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
[data-v-e190f6cf]{box-sizing:border-box}.simulator-layout[data-v-e190f6cf]{min-height:100vh;display:flex;flex-direction:column;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;background-color:#f8f9fa;color:#1a1a2e;transition:background-color .2s,color .2s}.simulator-layout.dark-mode[data-v-e190f6cf]{background-color:#1a1a2e;color:#e8e8e8}.header[data-v-e190f6cf]{display:flex;justify-content:space-between;align-items:center;padding:.75rem 1.5rem;background:linear-gradient(135deg,#6366f1,#8b5cf6);color:#fff}.header-left[data-v-e190f6cf]{display:flex;align-items:center;gap:1.5rem}.header h1[data-v-e190f6cf]{margin:0;font-size:1.125rem;font-weight:600;letter-spacing:-.02em}.app-info[data-v-e190f6cf]{display:flex;align-items:center;gap:.5rem;padding:.25rem .75rem;background:#ffffff26;border-radius:4px;font-size:.8125rem}.app-name[data-v-e190f6cf]{font-weight:500}.app-version[data-v-e190f6cf]{opacity:.8;font-size:.75rem}.header-right[data-v-e190f6cf]{display:flex;align-items:center;gap:.75rem}.status-badge[data-v-e190f6cf]{display:flex;align-items:center;gap:.375rem;padding:.25rem .625rem;border-radius:999px;font-size:.75rem;font-weight:500}.status-badge.live[data-v-e190f6cf]{background:#22c55e33;color:#86efac}.status-dot[data-v-e190f6cf]{width:6px;height:6px;border-radius:50%;background:#22c55e;animation:pulse-e190f6cf 2s infinite}@keyframes pulse-e190f6cf{0%,to{opacity:1}50%{opacity:.5}}.icon-btn[data-v-e190f6cf]{display:flex;align-items:center;justify-content:center;width:32px;height:32px;border:none;border-radius:6px;background:#ffffff1a;color:#fff;cursor:pointer;transition:background .15s}.icon-btn[data-v-e190f6cf]:hover{background:#fff3}.loading-state[data-v-e190f6cf],.error-state[data-v-e190f6cf]{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:3rem;text-align:center}.spinner[data-v-e190f6cf]{width:40px;height:40px;border:3px solid #e5e7eb;border-top-color:#6366f1;border-radius:50%;animation:spin-e190f6cf .8s linear infinite}.dark-mode .spinner[data-v-e190f6cf]{border-color:#374151;border-top-color:#8b5cf6}@keyframes spin-e190f6cf{to{transform:rotate(360deg)}}.url-info[data-v-e190f6cf]{margin-top:.75rem;font-size:.8125rem;color:#6b7280;font-family:SF Mono,Monaco,monospace}.error-icon[data-v-e190f6cf]{width:48px;height:48px;display:flex;align-items:center;justify-content:center;background:#fef2f2;color:#dc2626;border-radius:50%;font-size:1.5rem;font-weight:700;margin-bottom:1rem}.dark-mode .error-icon[data-v-e190f6cf]{background:#450a0a}.error-message[data-v-e190f6cf]{color:#dc2626;font-weight:500;margin:.5rem 0}.error-details[data-v-e190f6cf]{margin-top:1.5rem;padding:1rem;background:#fff;border-radius:8px;font-size:.875rem}.dark-mode .error-details[data-v-e190f6cf]{background:#1f2937}.retry-btn[data-v-e190f6cf]{margin-top:1rem;padding:.5rem 1rem;background:#6366f1;color:#fff;border:none;border-radius:6px;font-weight:500;cursor:pointer;transition:background .15s}.retry-btn[data-v-e190f6cf]:hover{background:#4f46e5}.main-content[data-v-e190f6cf]{flex:1;display:flex;flex-direction:column;padding:1rem;gap:1rem}.tabs[data-v-e190f6cf]{display:flex;align-items:center;gap:.25rem;padding:.25rem;background:#fff;border-radius:8px;box-shadow:0 1px 2px #0000000d}.dark-mode .tabs[data-v-e190f6cf]{background:#1f2937}.tab[data-v-e190f6cf]{padding:.5rem 1rem;border:none;border-radius:6px;background:transparent;color:#6b7280;font-size:.875rem;font-weight:500;cursor:pointer;transition:all .15s}.tab[data-v-e190f6cf]:hover{color:#1f2937}.dark-mode .tab[data-v-e190f6cf]:hover{color:#e5e7eb}.tab.active[data-v-e190f6cf]{background:#6366f1;color:#fff}.tab-controls[data-v-e190f6cf]{margin-left:auto;display:flex;gap:.25rem}.control-btn[data-v-e190f6cf]{display:flex;align-items:center;justify-content:center;width:36px;height:32px;border:none;border-radius:6px;background:transparent;color:#9ca3af;cursor:pointer;transition:all .15s}.control-btn[data-v-e190f6cf]:hover{background:#f3f4f6;color:#4b5563}.dark-mode .control-btn[data-v-e190f6cf]:hover{background:#374151;color:#d1d5db}.control-btn.active[data-v-e190f6cf]{background:#ede9fe;color:#6366f1}.dark-mode .control-btn.active[data-v-e190f6cf]{background:#4c1d95;color:#c4b5fd}.tab-panels[data-v-e190f6cf]{flex:1;display:flex;flex-direction:column}.tab-panel[data-v-e190f6cf]{flex:1;background:#fff;border-radius:8px;box-shadow:0 1px 3px #0000000d;overflow:auto}.dark-mode .tab-panel[data-v-e190f6cf]{background:#1f2937}.player-panel[data-v-e190f6cf]{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:2rem;background:#111827}.player-panel.fullscreen[data-v-e190f6cf]{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1000;border-radius:0;padding:0}.player-container[data-v-e190f6cf]{width:100%;max-width:960px;transition:all .3s ease}.player-container.aspect-landscape[data-v-e190f6cf]{aspect-ratio:16 / 9}.player-container.aspect-portrait[data-v-e190f6cf]{aspect-ratio:9 / 16;max-width:400px}.fullscreen .player-container[data-v-e190f6cf]{max-width:none;width:100%;height:100%}.fullscreen .player-container.aspect-portrait[data-v-e190f6cf]{max-width:none;width:auto;height:100%}.player-frame[data-v-e190f6cf]{width:100%;height:100%;background:#000;border-radius:4px;overflow:hidden}.fullscreen .player-frame[data-v-e190f6cf]{border-radius:0}.exit-fullscreen[data-v-e190f6cf]{position:fixed;top:1rem;right:1rem;padding:.5rem 1rem;background:#000000bf;color:#fff;border:none;border-radius:6px;font-size:.875rem;cursor:pointer;z-index:1001}.exit-fullscreen[data-v-e190f6cf]:hover{background:#000000e6}.config-panel[data-v-e190f6cf]{padding:1.5rem;overflow-y:auto}.meta-panel[data-v-e190f6cf]{padding:1rem}.meta-header[data-v-e190f6cf]{display:flex;justify-content:space-between;align-items:center;margin-bottom:.75rem}.meta-header h3[data-v-e190f6cf]{margin:0;font-size:.875rem;font-weight:600;color:#6b7280}.copy-btn[data-v-e190f6cf]{padding:.25rem .5rem;background:#f3f4f6;border:none;border-radius:4px;font-size:.75rem;color:#4b5563;cursor:pointer}.dark-mode .copy-btn[data-v-e190f6cf]{background:#374151;color:#d1d5db}.copy-btn[data-v-e190f6cf]:hover{background:#e5e7eb}.dark-mode .copy-btn[data-v-e190f6cf]:hover{background:#4b5563}.meta-code[data-v-e190f6cf]{margin:0;padding:1rem;background:#f9fafb;border-radius:6px;font-family:SF Mono,Monaco,Courier New,monospace;font-size:.8125rem;line-height:1.6;overflow-x:auto;white-space:pre-wrap;word-break:break-word}.dark-mode .meta-code[data-v-e190f6cf]{background:#111827;color:#e5e7eb}.placeholder[data-v-e190f6cf]{display:flex;align-items:center;justify-content:center;height:100%;min-height:200px;color:#9ca3af;font-style:italic}@media (max-width: 640px){.header[data-v-e190f6cf]{padding:.5rem 1rem}.header h1[data-v-e190f6cf]{font-size:1rem}.app-info[data-v-e190f6cf]{display:none}.tabs[data-v-e190f6cf]{flex-wrap:wrap}.tab-controls[data-v-e190f6cf]{width:100%;justify-content:center;margin-top:.5rem;margin-left:0}}
|