@bitmagic/cli 0.1.59-dev.11 → 0.1.59-dev.12

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 CHANGED
@@ -496,15 +496,15 @@ says what went wrong and offers to try again, instead of leaving you a black rec
496
496
 
497
497
  ### Where your game is published
498
498
 
499
- Once the project has been published, a **Published** pill appears in the top bar. It opens the
500
- game's address, the visibility it went out with, which publish this is and how long ago — and the
501
- same QR code the terminal draws, so the phone in your hand can reach the build without you typing
502
- anything.
499
+ Once the project has been published, **Published…** in the top bar's **⋯** menu opens the game's
500
+ address, the visibility it went out with, which publish this is and how long ago — and the same QR
501
+ code the terminal draws, so the phone in your hand can reach the build without you typing anything.
503
502
 
504
- The pill lights up on its own within a second or two of a publish finishing, with no reload: the
505
- page polls, and the publish it should show almost always happens in another terminal — often your
506
- agent's, which you never look at. Until the first publish the pill is there but dead, because a
507
- control that opens an empty dialog is worse than one that is plainly not ready.
503
+ A dot appears on the **⋯** button within a second or two of a publish finishing, with no reload:
504
+ the page polls, and the publish it should show almost always happens in another terminal — often
505
+ your agent's, which you never look at. Opening the menu clears the dot, so it means *new* rather
506
+ than *exists*. Until the first publish the row is there but dead, because a control that opens an
507
+ empty dialog is worse than one that is plainly not ready.
508
508
 
509
509
  It works even when the game will not boot, which is deliberate: that is the moment the link matters
510
510
  most, since the last good build is still live at that address.
@@ -518,14 +518,19 @@ two tabs over the same running game, so switching costs nothing and does not res
518
518
  Click an object to select it, then move, rotate, scale, snap it to the ground, edit its numbers in
519
519
  the inspector, delete it, or right-click to add one from the project's assets.
520
520
 
521
- **Screenshot** in the top bar copies the current frame to your clipboard, so you can paste it
522
- straight into your agent's chat — the fastest way to show it something that looks wrong. It captures
523
- whichever tab you are on, so you can grab gameplay or the editor view. If your browser refuses the
524
- clipboard write the image is saved to your downloads instead, and the status bar says so.
521
+ **Screenshot** in the top bar — or the **S** key — copies the current frame to your clipboard, so
522
+ you can paste it straight into your agent's chat — the fastest way to show it something that looks
523
+ wrong. It captures whichever tab you are on, so you can grab gameplay or the editor view. If your
524
+ browser refuses the clipboard write the image is saved to your downloads instead, and the status bar
525
+ says so.
525
526
 
526
- **Record** in the top bar holds the recording settings; the recording itself is a key. It appears
527
- only on the dev line — a build installed with `npm i -g @bitmagic/cli@dev` — while the feature is
528
- still settling; a release build has no Record pill and no sink. Press **F9**
527
+ **Reload** is the same, on **R**. Both keys are ignored while you are typing and while a dialog is
528
+ open, and they only reach the page when the chrome has focus: click into the game and the game gets
529
+ your keys, which is what you want — press F9 there and the recorder starts.
530
+
531
+ **Record gameplay…** in the **⋯** menu holds the recording settings; the recording itself is a key.
532
+ It appears only on the dev line — a build installed with `npm i -g @bitmagic/cli@dev` — while the
533
+ feature is still settling; a release build has no such row and no sink. Press **F9**
529
534
  in the game to start, play, press F9 again to stop. In the default frame-by-frame mode the engine
530
535
  renders every frame at the chosen resolution — 60 fps output regardless of how fast your machine
531
536
  renders — and streams them to `~/Downloads/gameplay_recording_*/` along with a `timeline.json` of
@@ -533,6 +538,19 @@ game events, sounds and HUD state, ready to be cut into a trailer. Video mode in
533
538
  real time and downloads a `.webm`. If the panel says your project's engine is too old for the disk
534
539
  streaming, run `bitmagic upgrade` and reload.
535
540
 
541
+ **Record motion…** in the same menu makes an animation out of you. It records two to sixty seconds
542
+ from your webcam — or takes a video file you already have — sends it to be turned into a motion
543
+ clip, and drops the result into the project's assets, ready to play on a character. There is a
544
+ 3-2-1 countdown before the webcam rolls, and the walk-to-the-camera frames at the start are trimmed
545
+ off for you.
546
+
547
+ ### The top bar
548
+
549
+ What you reach for all session sits in the bar: the **Game / Editor** tabs, **Auto-reload**, the
550
+ status light, **Assets** (which shows whether the panel is open), **Screenshot** and **Reload**.
551
+ Everything that opens a dialog and is wanted once a week — Published, and the two recorders — lives
552
+ behind **⋯**, so the bar stops growing a button every time the CLI grows a feature.
553
+
536
554
  3010 still serves the game on its own, for a second window or a bookmark.
537
555
 
538
556
  ### On a real phone
@@ -147,6 +147,76 @@ export const BITMAGIC_CONTROLS_CSS = `
147
147
  .bm-pill--ghost { background: transparent; border-color: var(--bm-text-dim); color: var(--bm-text-muted); }
148
148
  .bm-pill--ghost:hover:not(:disabled) { background: transparent; border-color: var(--bm-text); color: var(--bm-text); }
149
149
 
150
+ /* Pressed — a toggle whose panel is open. Deliberately NOT Aquamarine: the accent is already
151
+ spent on the active tab, and DESIGN.md does not stack accents. The pill reads as pushed in. */
152
+ .bm-pill--pressed { background: var(--bm-surface-card); border-color: var(--bm-text-dim); }
153
+
154
+ /* === Circular icon button =================================================================
155
+ DESIGN.md's "Toolbar / header icon controls". Filled rather than transparent, because in the
156
+ dev view it sits among filled pills rather than on the engine's own panel. */
157
+ .bm-icon-btn {
158
+ background: var(--bm-surface-alt);
159
+ color: var(--bm-text);
160
+ border: 1px solid var(--bm-border);
161
+ border-radius: 50%;
162
+ width: 26px;
163
+ height: 26px;
164
+ padding: 0;
165
+ display: flex;
166
+ align-items: center;
167
+ justify-content: center;
168
+ font-family: var(--bm-font);
169
+ font-size: 15px;
170
+ line-height: 1;
171
+ cursor: pointer;
172
+ transition: background .15s ease, border-color .15s ease, color .15s ease;
173
+ }
174
+ .bm-icon-btn:hover:not(:disabled) { background: var(--bm-surface-card); border-color: var(--bm-text-dim); }
175
+ .bm-icon-btn:focus-visible { outline: none; box-shadow: 0 0 0 2px rgba(160, 218, 185, .45); }
176
+
177
+ /* === Vertical separator (toolbar) ========================================================= */
178
+ .bm-separator-v { width: 1px; align-self: stretch; margin: 12px 4px; background: var(--bm-border); }
179
+
180
+ /* === Dropdown menu ========================================================================
181
+ The overflow behind a toolbar's rare actions, so the bar stops growing a pill per feature.
182
+ Elevated (2) in DESIGN.md's depth scale — shadow-card is the dropdown one, shadow-dialog
183
+ belongs to modals. Rows are sentence-case Regular: this is content voice, not label voice,
184
+ which is why they are the one control here that is not uppercase. */
185
+ .bm-menu-wrap { position: relative; display: flex; align-items: center; }
186
+ .bm-menu {
187
+ display: none;
188
+ position: absolute;
189
+ top: 100%;
190
+ right: 0;
191
+ margin-top: 8px;
192
+ z-index: 20;
193
+ min-width: 200px;
194
+ padding: 6px;
195
+ background: var(--bm-surface);
196
+ border: 1px solid var(--bm-border-muted);
197
+ border-radius: 8px;
198
+ box-shadow: var(--bm-shadow-card);
199
+ }
200
+ .bm-menu.show { display: flex; flex-direction: column; }
201
+ .bm-menu-item {
202
+ background: transparent;
203
+ color: var(--bm-text);
204
+ border: none;
205
+ border-radius: 4px;
206
+ padding: 10px 12px;
207
+ font-family: var(--bm-font);
208
+ font-size: 14px;
209
+ font-weight: 400;
210
+ text-align: left;
211
+ white-space: nowrap;
212
+ cursor: pointer;
213
+ transition: background .15s ease;
214
+ }
215
+ .bm-menu-item:hover:not(:disabled) { background: var(--bm-border-muted); }
216
+ .bm-menu-item:focus-visible { outline: none; background: var(--bm-border-muted);
217
+ box-shadow: 0 0 0 2px rgba(160, 218, 185, .45); }
218
+ .bm-menu-item:disabled { opacity: .5; cursor: default; }
219
+
150
220
  /* === Input ================================================================================ */
151
221
  .bm-input {
152
222
  background: var(--bm-surface-alt);
@@ -1 +1 @@
1
- {"version":3,"file":"design.js","sourceRoot":"","sources":["../../src/editor/design.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,4FAA4F;AAC5F,MAAM,CAAC,MAAM,EAAE,GAAG;IAChB,EAAE,EAAE,SAAS;IACb,OAAO,EAAE,SAAS;IAClB,UAAU,EAAE,SAAS;IACrB,WAAW,EAAE,SAAS;IAEtB,WAAW,EAAE,SAAS;IACtB,SAAS,EAAE,SAAS;IACpB,OAAO,EAAE,SAAS;IAClB,YAAY,EAAE,SAAS;IAEvB,MAAM,EAAE,SAAS;IACjB,WAAW,EAAE,SAAS;IAEtB,IAAI,EAAE,SAAS;IACf,SAAS,EAAE,SAAS;IACpB,WAAW,EAAE,SAAS;IACtB,IAAI,EAAE,SAAS;IACf,SAAS,EAAE,SAAS;IACpB,WAAW,EAAE,SAAS;IACtB,OAAO,EAAE,SAAS;IAClB,MAAM,EAAE,SAAS;IAEjB,YAAY,EAAE,+BAA+B;IAC7C,UAAU,EAAE,8BAA8B;IAC1C,QAAQ,EAAE,oCAAoC;IAC9C,QAAQ,EAAE,kCAAkC;IAC5C,cAAc,EAAE,yBAAyB;IACzC,gBAAgB,EAAE,8DAA8D;IAEhF,IAAI,EAAE,8EAA8E;IACpF,QAAQ,EAAE,gDAAgD;CAClD,CAAC;AAEX;;;;;GAKG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG;;0HAEwF,CAAC;AAE3H,uFAAuF;AACvF,MAAM,CAAC,MAAM,mBAAmB,GAAG;;;eAGpB,EAAE,CAAC,EAAE;oBACA,EAAE,CAAC,OAAO;wBACN,EAAE,CAAC,UAAU;yBACZ,EAAE,CAAC,WAAW;iBACtB,EAAE,CAAC,WAAW;uBACR,EAAE,CAAC,SAAS;qBACd,EAAE,CAAC,OAAO;mBACZ,EAAE,CAAC,MAAM;yBACH,EAAE,CAAC,WAAW;iBACtB,EAAE,CAAC,IAAI;uBACD,EAAE,CAAC,SAAS;iBAClB,EAAE,CAAC,IAAI;uBACD,EAAE,CAAC,SAAS;oBACf,EAAE,CAAC,OAAO;mBACX,EAAE,CAAC,MAAM;;;;;;;0BAOF,EAAE,CAAC,YAAY;wBACjB,EAAE,CAAC,UAAU;sBACf,EAAE,CAAC,QAAQ;sBACX,EAAE,CAAC,QAAQ;iBAChB,EAAE,CAAC,IAAI;sBACF,EAAE,CAAC,QAAQ;;CAEhC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBA+DnB,EAAE,CAAC,cAAc;;;;;;;kCAOD,EAAE,CAAC,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsDpD,CAAC"}
1
+ {"version":3,"file":"design.js","sourceRoot":"","sources":["../../src/editor/design.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,4FAA4F;AAC5F,MAAM,CAAC,MAAM,EAAE,GAAG;IAChB,EAAE,EAAE,SAAS;IACb,OAAO,EAAE,SAAS;IAClB,UAAU,EAAE,SAAS;IACrB,WAAW,EAAE,SAAS;IAEtB,WAAW,EAAE,SAAS;IACtB,SAAS,EAAE,SAAS;IACpB,OAAO,EAAE,SAAS;IAClB,YAAY,EAAE,SAAS;IAEvB,MAAM,EAAE,SAAS;IACjB,WAAW,EAAE,SAAS;IAEtB,IAAI,EAAE,SAAS;IACf,SAAS,EAAE,SAAS;IACpB,WAAW,EAAE,SAAS;IACtB,IAAI,EAAE,SAAS;IACf,SAAS,EAAE,SAAS;IACpB,WAAW,EAAE,SAAS;IACtB,OAAO,EAAE,SAAS;IAClB,MAAM,EAAE,SAAS;IAEjB,YAAY,EAAE,+BAA+B;IAC7C,UAAU,EAAE,8BAA8B;IAC1C,QAAQ,EAAE,oCAAoC;IAC9C,QAAQ,EAAE,kCAAkC;IAC5C,cAAc,EAAE,yBAAyB;IACzC,gBAAgB,EAAE,8DAA8D;IAEhF,IAAI,EAAE,8EAA8E;IACpF,QAAQ,EAAE,gDAAgD;CAClD,CAAC;AAEX;;;;;GAKG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG;;0HAEwF,CAAC;AAE3H,uFAAuF;AACvF,MAAM,CAAC,MAAM,mBAAmB,GAAG;;;eAGpB,EAAE,CAAC,EAAE;oBACA,EAAE,CAAC,OAAO;wBACN,EAAE,CAAC,UAAU;yBACZ,EAAE,CAAC,WAAW;iBACtB,EAAE,CAAC,WAAW;uBACR,EAAE,CAAC,SAAS;qBACd,EAAE,CAAC,OAAO;mBACZ,EAAE,CAAC,MAAM;yBACH,EAAE,CAAC,WAAW;iBACtB,EAAE,CAAC,IAAI;uBACD,EAAE,CAAC,SAAS;iBAClB,EAAE,CAAC,IAAI;uBACD,EAAE,CAAC,SAAS;oBACf,EAAE,CAAC,OAAO;mBACX,EAAE,CAAC,MAAM;;;;;;;0BAOF,EAAE,CAAC,YAAY;wBACjB,EAAE,CAAC,UAAU;sBACf,EAAE,CAAC,QAAQ;sBACX,EAAE,CAAC,QAAQ;iBAChB,EAAE,CAAC,IAAI;sBACF,EAAE,CAAC,QAAQ;;CAEhC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAqInB,EAAE,CAAC,cAAc;;;;;;;kCAOD,EAAE,CAAC,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsDpD,CAAC"}
@@ -146,6 +146,13 @@ ${BITMAGIC_CONTROLS_CSS}
146
146
  #auto { display: flex; align-items: center; gap: 6px; font-size: 12px;
147
147
  color: var(--bm-text-muted); cursor: pointer; }
148
148
  #auto input { margin: 0; accent-color: var(--bm-aqua); }
149
+ /* The Published pill used to un-dim itself when a publish landed, which is how a creator learnt
150
+ it had finished. Behind a menu that signal would be invisible, so the trigger carries it:
151
+ Aquamarine, the same "something landed" this page already uses for a fresh asset row. */
152
+ #more { position: relative; }
153
+ #more.news::after { content: ''; position: absolute; top: -1px; right: -1px;
154
+ width: 6px; height: 6px; border-radius: 50%;
155
+ background: var(--bm-aqua); border: 1px solid var(--bm-surface); }
149
156
  .banner { display: none; align-items: center; gap: 12px; flex: none; padding: 10px 16px;
150
157
  background: var(--bm-tint-warning); border-bottom: 1px solid var(--bm-pumpkin);
151
158
  color: var(--bm-text); }
@@ -251,11 +258,18 @@ ${BOOT_LOADER_CSS}
251
258
  <input id="auto-toggle" type="checkbox" checked> Auto-reload
252
259
  </label>
253
260
  <span id="status"><span id="dot"></span><span id="status-text">Loading…</span></span>
254
- <button id="publish-toggle" class="bm-pill" type="button" title="Where this game is published" disabled>Published</button>
255
- <button id="assets-toggle" class="bm-pill" type="button" title="Show the assets in this project and what is being made">Assets</button>
256
- <button id="shot" class="bm-pill" type="button" title="Copy the current frame to the clipboard">Screenshot</button>
257
- <button id="motion" class="bm-pill" type="button" title="Record a motion on camera and turn it into an animation">Record motion</button>
258
- ${recording ? ' <button id="record" class="bm-pill" type="button" title="Record gameplay — press F9 in the game to start and stop">Record</button>\n' : ''} <button id="reload" class="bm-pill" type="button">Reload</button>
261
+ <span class="bm-separator-v"></span>
262
+ <button id="assets-toggle" class="bm-pill" type="button" aria-pressed="true" title="Show the assets in this project and what is being made">Assets</button>
263
+ <span class="bm-separator-v"></span>
264
+ <button id="shot" class="bm-pill" type="button" title="Copy the current frame to the clipboard (S)">Screenshot</button>
265
+ <button id="reload" class="bm-pill" type="button" title="Reload the game (R)">Reload</button>
266
+ <div class="bm-menu-wrap">
267
+ <button id="more" class="bm-icon-btn" type="button" aria-haspopup="true" aria-expanded="false" aria-label="More actions" title="More actions">⋯</button>
268
+ <div id="more-menu" class="bm-menu">
269
+ <button id="publish-toggle" class="bm-menu-item" type="button" disabled>Published…</button>
270
+ ${recording ? ' <button id="record" class="bm-menu-item" type="button">Record gameplay…</button>\n' : ''} <button id="motion" class="bm-menu-item" type="button">Record motion…</button>
271
+ </div>
272
+ </div>
259
273
  </div>
260
274
  <div id="build-banner" class="banner">
261
275
  <span id="build-message"></span>
@@ -318,6 +332,8 @@ ${ASSET_DETAIL_HTML}
318
332
  var TAB_KEY = 'bitmagic.dev.tab';
319
333
  var AUTO_KEY = 'bitmagic.dev.autoReload';
320
334
  var ASSETS_KEY = 'bitmagic.dev.assets';
335
+ // The publish the creator has already been shown, so the trigger's dot means NEW, not "exists".
336
+ var SEEN_PUBLISH_KEY = 'bitmagic.dev.seenPublish';
321
337
  // Dev line only — see recordingAvailable() in recording-sink.ts. On a release build the pill and
322
338
  // the panel are not in the document at all, so this also guards the lookups below finding null.
323
339
  var RECORDING_ENABLED = ${recording ? 'true' : 'false'};
@@ -330,6 +346,8 @@ ${ASSET_DETAIL_HTML}
330
346
  var statusText = document.getElementById('status-text');
331
347
  var banner = document.getElementById('banner');
332
348
  var publishToggle = document.getElementById('publish-toggle');
349
+ var moreButton = document.getElementById('more');
350
+ var moreMenu = document.getElementById('more-menu');
333
351
  var publishOverlay = document.getElementById('publish-overlay');
334
352
  var publishUrl = document.getElementById('publish-url');
335
353
  var publishVisibility = document.getElementById('publish-visibility');
@@ -1121,6 +1139,9 @@ ${ASSET_DETAIL_HTML}
1121
1139
  publishToggle.title = lastPublish
1122
1140
  ? 'Where this game is published'
1123
1141
  : 'Publish the game to get a link and a QR code';
1142
+ // The pill used to carry this by un-dimming in the bar. Inside a menu nobody would see it, so
1143
+ // the trigger wears a dot until the creator has opened the menu on this particular publish.
1144
+ moreButton.classList.toggle('news', !!lastPublish && readPref(SEEN_PUBLISH_KEY, '') !== lastPublish.at);
1124
1145
  if (!lastPublish && publishOverlay.classList.contains('show')) closePublish();
1125
1146
  }
1126
1147
 
@@ -1148,7 +1169,9 @@ ${ASSET_DETAIL_HTML}
1148
1169
  publishOverlay.classList.remove('show');
1149
1170
  // Drop the image so a session that publishes repeatedly does not keep every code it drew.
1150
1171
  publishQr.removeAttribute('src');
1151
- publishToggle.focus();
1172
+ // Not publishToggle: it lives inside the menu, which is closed by now, and focusing a hidden
1173
+ // element drops focus to the body. The trigger is the thing that is still on screen.
1174
+ moreButton.focus();
1152
1175
  }
1153
1176
 
1154
1177
  /**
@@ -2046,11 +2069,35 @@ ${ASSET_DETAIL_HTML}
2046
2069
  // The page had no keyboard handling at all before this, so #hq-overlay gains Escape with it.
2047
2070
  document.addEventListener('keydown', function (event) {
2048
2071
  if (event.key !== 'Escape') return;
2072
+ // Innermost first. The motion and publish dialogs were missing from this chain entirely —
2073
+ // they only closed on their own button or the backdrop.
2074
+ if (closeMore()) return;
2049
2075
  if (closeAssetDetail()) return;
2050
2076
  if (closeRecordingPanel()) return;
2077
+ if (closeMotionPanel()) return;
2078
+ if (publishOverlay.classList.contains('show')) { closePublish(); return; }
2051
2079
  hqOverlay.classList.remove('show');
2052
2080
  });
2053
2081
 
2082
+ /**
2083
+ * Reload and Screenshot are the two things pressed all session, so they get a key each.
2084
+ *
2085
+ * Bare letters, because every modifier combination worth having is the browser's (Cmd+R, Cmd+S).
2086
+ * That means guarding the cases where a letter is text rather than a command: a field, or a
2087
+ * dialog that is up. Note the game iframe is a different origin, so once the creator clicks into
2088
+ * the game these stop firing until they click the chrome again — nothing here can see those keys,
2089
+ * which is exactly why the recorder's own F9 is bound inside the engine instead.
2090
+ */
2091
+ document.addEventListener('keydown', function (event) {
2092
+ if (event.metaKey || event.ctrlKey || event.altKey || event.shiftKey) return;
2093
+ var target = event.target;
2094
+ if (target && (target.isContentEditable || /^(?:INPUT|TEXTAREA|SELECT)$/.test(target.tagName))) return;
2095
+ if (document.querySelector('.bm-overlay.show')) return;
2096
+ var key = event.key.toLowerCase();
2097
+ if (key === 'r') { event.preventDefault(); reloadUnlessSculpting(); }
2098
+ else if (key === 's') { event.preventDefault(); takeScreenshot(); }
2099
+ });
2100
+
2054
2101
  /**
2055
2102
  * Lend the cached thumbnails to the engine's own asset palette.
2056
2103
  *
@@ -2098,10 +2145,36 @@ ${ASSET_DETAIL_HTML}
2098
2145
  function setAssetsOpen(open) {
2099
2146
  assetsOpen = open;
2100
2147
  document.body.classList.toggle('assets-closed', !open);
2148
+ // A toggle that looks identical in both states is a button that lies about what it did.
2149
+ assetsToggle.classList.toggle('bm-pill--pressed', open);
2150
+ assetsToggle.setAttribute('aria-pressed', open ? 'true' : 'false');
2101
2151
  writePref(ASSETS_KEY, open ? '1' : '0');
2102
2152
  if (open) void refreshAssets();
2103
2153
  }
2104
2154
 
2155
+ /**
2156
+ * The overflow menu.
2157
+ *
2158
+ * The bar had grown a pill per feature, and two of them were called Record. What is left in the
2159
+ * bar is what a creator touches in a normal session; what opens a dialog and is reached once a
2160
+ * week lives here, so the next feature adds a row rather than a seventh pill.
2161
+ */
2162
+ function openMore() {
2163
+ moreMenu.classList.add('show');
2164
+ moreButton.setAttribute('aria-expanded', 'true');
2165
+ // Opening the menu IS seeing the publish, so the dot has done its job.
2166
+ if (lastPublish) writePref(SEEN_PUBLISH_KEY, lastPublish.at);
2167
+ moreButton.classList.remove('news');
2168
+ }
2169
+
2170
+ /** Returns whether it was open — the Escape chain's contract, like closeRecordingPanel. */
2171
+ function closeMore() {
2172
+ if (!moreMenu.classList.contains('show')) return false;
2173
+ moreMenu.classList.remove('show');
2174
+ moreButton.setAttribute('aria-expanded', 'false');
2175
+ return true;
2176
+ }
2177
+
2105
2178
  /**
2106
2179
  * Screenshot → clipboard.
2107
2180
  *
@@ -2307,6 +2380,19 @@ ${ASSET_DETAIL_HTML}
2307
2380
  if (autoReload) banner.classList.remove('show');
2308
2381
  });
2309
2382
 
2383
+ moreButton.addEventListener('click', function () {
2384
+ if (!closeMore()) openMore();
2385
+ });
2386
+ // One delegate for every row, present and future: a click that lands on a row's button closes
2387
+ // the menu, and the row's own handler opens whatever it opens.
2388
+ moreMenu.addEventListener('click', function (event) {
2389
+ if (event.target.tagName === 'BUTTON' && !event.target.disabled) closeMore();
2390
+ });
2391
+ // Anywhere outside the trigger and the menu dismisses it, the way a dropdown is expected to.
2392
+ document.addEventListener('click', function (event) {
2393
+ if (!event.target.closest || !event.target.closest('.bm-menu-wrap')) closeMore();
2394
+ });
2395
+
2310
2396
  publishToggle.addEventListener('click', openPublish);
2311
2397
  publishClose.addEventListener('click', closePublish);
2312
2398
  // Click the backdrop to dismiss, like every other dialog on this page.
@@ -1 +1 @@
1
- {"version":3,"file":"shell-page.js","sourceRoot":"","sources":["../../src/editor/shell-page.ts"],"names":[],"mappings":"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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAy8DtD,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqChB,CAAC;AACF,CAAC"}
1
+ {"version":3,"file":"shell-page.js","sourceRoot":"","sources":["../../src/editor/shell-page.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AAEH,OAAO,EACL,qBAAqB,EAAE,kBAAkB,GAC1C,MAAM,qDAAqD,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,+CAA+C,CAAC;AAClF,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC9E,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC3E,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AACjF,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzF,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACrE,OAAO,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAE7F,oGAAoG;AACpG,MAAM,gBAAgB,GAAG,GAAG,CAAC;AAE7B;;;;;;GAMG;AACH,MAAM,gBAAgB,GAAG,GAAG,CAAC;AAE7B;;;;;;;;;;;;GAYG;AACH,SAAS,sBAAsB;IAC7B,OAAO;QACL,6BAA6B,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAAC,GAAG;QACjE,iCAAiC,qBAAqB,CAAC,QAAQ,EAAE,GAAG;QACpE,8BAA8B,kBAAkB,CAAC,QAAQ,EAAE,GAAG;KAC/D,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AACjB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,qBAAqB,GAAG,IAAI,CAAC;AAEnC,kGAAkG;AAClG,SAAS,UAAU,CAAC,KAAa;IAC/B,OAAO,KAAK;SACT,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC;SACvB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAC3B,CAAC;AAiBD,MAAM,UAAU,iBAAiB,CAAC,OAA2B;IAC3D,MAAM,OAAO,GAAG,oBAAoB,OAAO,CAAC,QAAQ,2BAA2B,kBAAkB,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;IACpH,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;IACpC,OAAO;;;;wBAIe,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC;EAChD,kBAAkB;;EAElB,mBAAmB;EACnB,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA6HrB,gBAAgB;EAChB,iBAAiB;EACjB,SAAS,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,EAAE;EACpC,gBAAgB;EAChB,eAAe;;;;;;uBAMM,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC;;;;;;;;;;;;;;;;;;;EAmB/C,SAAS,CAAC,CAAC,CAAC,4FAA4F,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;EAwB7G,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;EAyBhB,kBAAkB;EAClB,SAAS,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,EAAE;EACrC,iBAAiB;EACjB,iBAAiB;;;;mBAIA,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;kBACxB,gBAAgB;yBACT,qBAAqB;2BACnB,gBAAgB;;IAEvC,sBAAsB,EAAE;;;;;;;;4BAQA,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+gEtD,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqChB,CAAC;AACF,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bitmagic/cli",
3
- "version": "0.1.59-dev.11",
3
+ "version": "0.1.59-dev.12",
4
4
  "description": "Build Bitmagic games from your own agent tool",
5
5
  "license": "SEE LICENSE IN LICENSE.md",
6
6
  "author": "Bitmagic Oy",
@@ -23,9 +23,9 @@
23
23
  "fflate": "^0.8.2",
24
24
  "playwright-core": "^1.59.1",
25
25
  "tar": "^7.4.3",
26
- "@bitmagic/animation-forger": "0.1.14-dev.11",
27
- "@bitmagic/world-forger": "0.1.19-dev.11",
28
- "@bitmagic/asset-core": "0.2.14-dev.11"
26
+ "@bitmagic/animation-forger": "0.1.14-dev.12",
27
+ "@bitmagic/world-forger": "0.1.19-dev.12",
28
+ "@bitmagic/asset-core": "0.2.14-dev.12"
29
29
  },
30
30
  "devDependencies": {
31
31
  "@eslint/js": "^9.38.0",