pa_encoder 0.1.0 → 0.2.1

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.
@@ -0,0 +1,469 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>pa_encoder</title>
7
+ <style>
8
+ :root {
9
+ --panel-bg: rgba(16, 16, 18, 0.92);
10
+ --panel-border: rgba(255, 255, 255, 0.12);
11
+ --text: rgba(255, 255, 255, 0.92);
12
+ --muted: rgba(255, 255, 255, 0.62);
13
+
14
+ --surface: rgba(255, 255, 255, 0.06);
15
+ --surface-2: rgba(255, 255, 255, 0.1);
16
+ --border: rgba(255, 255, 255, 0.14);
17
+
18
+ --primary: #2f6df6;
19
+ --primary-hover: #3d7bff;
20
+
21
+ --danger: #e5484d;
22
+ --danger-hover: #ff5a60;
23
+
24
+ --shadow: 0 14px 42px rgba(0, 0, 0, 0.45);
25
+ --radius: 14px;
26
+ --ring: 0 0 0 3px rgba(47, 109, 246, 0.35);
27
+ }
28
+
29
+ html,
30
+ body {
31
+ margin: 0;
32
+ padding: 0;
33
+ background: transparent;
34
+ font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto,
35
+ Helvetica, Arial;
36
+ color: var(--text);
37
+ overflow: hidden; /* prevent any page-level horizontal scroll */
38
+ }
39
+
40
+ /* Preview fills the viewport */
41
+ #previewWrap {
42
+ position: fixed;
43
+ inset: 0;
44
+ z-index: 0;
45
+ }
46
+ #preview {
47
+ position: absolute;
48
+ inset: 0;
49
+ width: 100%;
50
+ height: 100%;
51
+ border: 0;
52
+ pointer-events: none; /* default: UI captures mouse */
53
+ }
54
+
55
+ /* UI overlay root */
56
+ #root {
57
+ position: fixed;
58
+ inset: 0;
59
+ z-index: 1;
60
+ pointer-events: none;
61
+ }
62
+
63
+ /* Panel */
64
+ #panel {
65
+ position: fixed;
66
+ pointer-events: auto;
67
+
68
+ width: clamp(320px, 34vw, 520px);
69
+ max-height: min(78vh, 720px);
70
+
71
+ background: var(--panel-bg);
72
+ border: 1px solid var(--panel-border);
73
+ border-radius: var(--radius);
74
+ box-shadow: var(--shadow);
75
+ backdrop-filter: blur(10px);
76
+
77
+ display: flex;
78
+ flex-direction: column;
79
+ overflow: hidden; /* scrolling happens in middle area */
80
+ }
81
+
82
+ /* Dock positions */
83
+ body.dock-br #panel {
84
+ right: 16px;
85
+ bottom: 16px;
86
+ }
87
+ body.dock-bl #panel {
88
+ left: 16px;
89
+ bottom: 16px;
90
+ }
91
+ body.dock-tr #panel {
92
+ right: 16px;
93
+ top: 16px;
94
+ }
95
+ body.dock-tl #panel {
96
+ left: 16px;
97
+ top: 16px;
98
+ }
99
+
100
+ /* Header */
101
+ .topbar {
102
+ display: flex;
103
+ align-items: center;
104
+ justify-content: space-between;
105
+ gap: 10px;
106
+ padding: 12px 12px 10px 12px;
107
+ border-bottom: 1px solid var(--border);
108
+ }
109
+ .title {
110
+ font-weight: 700;
111
+ font-size: 14px;
112
+ letter-spacing: 0.2px;
113
+ }
114
+ .topbtns {
115
+ display: flex;
116
+ gap: 8px;
117
+ align-items: center;
118
+ }
119
+
120
+ /* Controls area: scroll container */
121
+ .content {
122
+ flex: 1;
123
+ overflow-y: auto;
124
+ overflow-x: hidden; /* key: prevent horizontal scroll */
125
+ padding: 12px;
126
+ }
127
+
128
+ /* Footer log: fixed height */
129
+ .log {
130
+ border-top: 1px solid var(--border);
131
+ padding: 10px 12px;
132
+ height: 128px;
133
+ overflow: auto;
134
+
135
+ background: rgba(0, 0, 0, 0.28);
136
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
137
+ "Liberation Mono", "Courier New", monospace;
138
+ font-size: 12.5px;
139
+ white-space: pre-wrap;
140
+ word-break: break-word;
141
+ }
142
+
143
+ /* Inputs */
144
+ button,
145
+ input,
146
+ select {
147
+ border-radius: 10px;
148
+ border: 1px solid var(--border);
149
+ background: var(--surface);
150
+ color: var(--text);
151
+ padding: 10px 12px;
152
+ font-size: 14px;
153
+ outline: none;
154
+ box-sizing: border-box;
155
+
156
+ min-width: 0; /* key: allow shrinking inside grid */
157
+ width: 100%; /* key: fit grid cell */
158
+ }
159
+
160
+ input:focus,
161
+ select:focus,
162
+ button:focus {
163
+ box-shadow: var(--ring);
164
+ border-color: rgba(47, 109, 246, 0.55);
165
+ }
166
+
167
+ button {
168
+ cursor: pointer;
169
+ user-select: none;
170
+ background: var(--surface-2);
171
+ }
172
+ button:hover {
173
+ background: rgba(255, 255, 255, 0.12);
174
+ }
175
+ button:disabled {
176
+ opacity: 0.55;
177
+ cursor: not-allowed;
178
+ }
179
+
180
+ .btnSmall {
181
+ padding: 8px 10px;
182
+ font-size: 13px;
183
+ border-radius: 10px;
184
+ width: auto; /* small buttons shouldn't stretch */
185
+ min-width: 0;
186
+ }
187
+ .btnGhost {
188
+ background: transparent;
189
+ }
190
+ .btnGhost:hover {
191
+ background: rgba(255, 255, 255, 0.08);
192
+ }
193
+
194
+ .btnPrimary {
195
+ background: var(--primary);
196
+ border-color: rgba(47, 109, 246, 0.55);
197
+ }
198
+ .btnPrimary:hover {
199
+ background: var(--primary-hover);
200
+ }
201
+
202
+ .btnDanger {
203
+ background: var(--danger);
204
+ border-color: rgba(229, 72, 77, 0.65);
205
+ }
206
+ .btnDanger:hover {
207
+ background: var(--danger-hover);
208
+ }
209
+
210
+ /* Form rows */
211
+ .row {
212
+ display: grid;
213
+ grid-template-columns: 110px minmax(0, 1fr); /* key */
214
+ gap: 10px;
215
+ align-items: center;
216
+ margin: 10px 0;
217
+ }
218
+ .row2 {
219
+ display: grid;
220
+ grid-template-columns:
221
+ 110px minmax(0, 1fr)
222
+ 110px minmax(0, 1fr); /* key */
223
+ gap: 10px;
224
+ align-items: center;
225
+ margin: 10px 0;
226
+ }
227
+
228
+ label {
229
+ color: var(--muted);
230
+ font-size: 13px;
231
+ min-width: 0;
232
+ }
233
+
234
+ .btnRow {
235
+ display: grid;
236
+ grid-template-columns: 1fr 1fr 1fr;
237
+ gap: 10px;
238
+ margin-top: 12px;
239
+ }
240
+ .btnRow > button {
241
+ width: 100%;
242
+ }
243
+
244
+ /* Details sections */
245
+ details {
246
+ border: 1px solid rgba(255, 255, 255, 0.1);
247
+ border-radius: 12px;
248
+ padding: 10px 10px 6px 10px;
249
+ background: rgba(255, 255, 255, 0.03);
250
+ margin: 12px 0;
251
+ overflow: hidden; /* avoid inner horizontal overflow */
252
+ }
253
+ summary {
254
+ cursor: pointer;
255
+ list-style: none;
256
+ font-weight: 650;
257
+ font-size: 13px;
258
+ color: rgba(255, 255, 255, 0.82);
259
+ display: flex;
260
+ align-items: center;
261
+ justify-content: space-between;
262
+ gap: 10px;
263
+ user-select: none;
264
+ }
265
+ summary::-webkit-details-marker {
266
+ display: none;
267
+ }
268
+ .summaryHint {
269
+ color: var(--muted);
270
+ font-weight: 500;
271
+ font-size: 12px;
272
+ white-space: nowrap;
273
+ }
274
+
275
+ .hint {
276
+ color: var(--muted);
277
+ font-size: 12.5px;
278
+ line-height: 1.35;
279
+ margin-top: 10px;
280
+ }
281
+
282
+ /* States */
283
+ body.hidden #panel {
284
+ display: none;
285
+ }
286
+ body.compact .content details,
287
+ body.compact .content .advancedRow,
288
+ body.compact .content .hint {
289
+ display: none;
290
+ }
291
+ body.passthrough #preview {
292
+ pointer-events: auto;
293
+ }
294
+
295
+ /* Responsive */
296
+ @media (max-width: 520px) {
297
+ #panel {
298
+ width: calc(100vw - 32px);
299
+ }
300
+ .row,
301
+ .row2 {
302
+ grid-template-columns: minmax(0, 1fr);
303
+ }
304
+ .btnRow {
305
+ grid-template-columns: 1fr;
306
+ }
307
+ label {
308
+ margin-bottom: -6px;
309
+ }
310
+ }
311
+ </style>
312
+ </head>
313
+
314
+ <body class="dock-br">
315
+ <div id="previewWrap">
316
+ <iframe id="preview"></iframe>
317
+ </div>
318
+
319
+ <div id="root">
320
+ <div id="panel" role="dialog" aria-label="pa_encoder UI">
321
+ <div class="topbar">
322
+ <div class="title">pa_encoder</div>
323
+ <div class="topbtns">
324
+ <button id="btnDock" class="btnSmall btnGhost" title="Change dock">
325
+ Dock
326
+ </button>
327
+ <button
328
+ id="btnCompact"
329
+ class="btnSmall btnGhost"
330
+ title="Toggle compact mode"
331
+ >
332
+ Compact
333
+ </button>
334
+ <button id="btnHide" class="btnSmall btnGhost" title="Hide UI">
335
+ Hide
336
+ </button>
337
+ </div>
338
+ </div>
339
+
340
+ <div class="content">
341
+ <div
342
+ class="advancedRow"
343
+ style="
344
+ display: flex;
345
+ gap: 10px;
346
+ flex-wrap: wrap;
347
+ margin-bottom: 10px;
348
+ "
349
+ >
350
+ <button
351
+ id="btnPassthrough"
352
+ class="btnSmall btnGhost"
353
+ title="Toggle passthrough (mouse to sketch)"
354
+ >
355
+ Passthrough: Off
356
+ </button>
357
+ <button
358
+ id="btnFocus"
359
+ class="btnSmall btnGhost"
360
+ title="Focus sketch for keyboard input"
361
+ >
362
+ Focus Sketch
363
+ </button>
364
+ </div>
365
+
366
+ <div class="row">
367
+ <label>Entry</label>
368
+ <input id="entry" />
369
+ </div>
370
+
371
+ <div class="row">
372
+ <label>Mode</label>
373
+ <select id="mode">
374
+ <option value="live">Live (realtime)</option>
375
+ <option value="frame">Frame (deterministic)</option>
376
+ </select>
377
+ </div>
378
+
379
+ <div class="row">
380
+ <label>Canvas</label>
381
+ <select id="canvas"></select>
382
+ </div>
383
+
384
+ <div class="row2">
385
+ <label>FPS</label>
386
+ <input id="fps" type="number" min="1" step="1" value="60" />
387
+ <label>Exporter</label>
388
+ <select id="exporter">
389
+ <option value="zip">ZIP (download)</option>
390
+ <option value="fs">FS (directory)</option>
391
+ <option value="best">Best (auto)</option>
392
+ </select>
393
+ </div>
394
+
395
+ <details open id="detailsLive">
396
+ <summary>
397
+ <span>Live settings</span>
398
+ <span class="summaryHint">duration / queue</span>
399
+ </summary>
400
+
401
+ <div class="row2">
402
+ <label>Policy</label>
403
+ <select id="policy">
404
+ <option value="drop">drop</option>
405
+ <option value="block">block</option>
406
+ </select>
407
+ <label>Conc.</label>
408
+ <input
409
+ id="concurrency"
410
+ type="number"
411
+ min="1"
412
+ step="1"
413
+ value="2"
414
+ />
415
+ </div>
416
+
417
+ <div class="row2">
418
+ <label>MaxQueue</label>
419
+ <input id="maxQueue" type="number" min="0" step="1" value="8" />
420
+ <label>Duration</label>
421
+ <input id="duration" type="number" min="1" step="1" value="10" />
422
+ </div>
423
+ </details>
424
+
425
+ <details id="detailsFrame">
426
+ <summary>
427
+ <span>Frame settings</span>
428
+ <span class="summaryHint">frames / warmup</span>
429
+ </summary>
430
+
431
+ <div class="row2">
432
+ <label>Frames</label>
433
+ <input id="frames" type="number" min="1" step="1" value="300" />
434
+ <label>Warmup</label>
435
+ <input id="warmup" type="number" min="0" step="1" value="0" />
436
+ </div>
437
+ </details>
438
+
439
+ <div class="btnRow">
440
+ <button id="btnReload" class="btnGhost">Reload</button>
441
+ <button id="btnStart" class="btnPrimary">Start</button>
442
+ <button id="btnStop" class="btnDanger" disabled>Stop</button>
443
+ </div>
444
+
445
+ <div class="hint">
446
+ Hotkeys (only when not recording):
447
+ <br />
448
+ - H: hide UI
449
+ <br />
450
+ - P: toggle passthrough
451
+ <br />
452
+ - C: compact
453
+ <br />
454
+ - D: dock position
455
+ <br />
456
+ - Space: start
457
+ <br />
458
+ During recording, keyboard is not captured by the UI. Use Focus
459
+ Sketch if needed, then click the canvas to ensure focus.
460
+ </div>
461
+ </div>
462
+
463
+ <div id="log" class="log"></div>
464
+ </div>
465
+ </div>
466
+
467
+ <script type="module" src="/__pa_encoder__/ui/encoder.js"></script>
468
+ </body>
469
+ </html>