@justai/cuts 0.129.3 → 0.129.5
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/package.json +1 -1
- package/src/Preroll.astro +9 -0
- package/src/Toolbar.astro +40 -47
package/package.json
CHANGED
package/src/Preroll.astro
CHANGED
|
@@ -505,6 +505,15 @@ const safeId = "game-" + (id.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/
|
|
|
505
505
|
}
|
|
506
506
|
// The page is locked, so make sure what it is locked ON is the stage.
|
|
507
507
|
if (playing) stage.scrollIntoView({ block: "nearest" });
|
|
508
|
+
// queries: space does nothing · keyboard not reaching the game · input bind · focus
|
|
509
|
+
//
|
|
510
|
+
// AND THE KEYBOARD GOES WITH THE STAGE. The play press happened in THIS document, so this
|
|
511
|
+
// document holds the focus — and every key the player presses lands in the shell while
|
|
512
|
+
// the game hears nothing. The founder, on the space bar: *"bu haldeyken klavyeden space
|
|
513
|
+
// tusunu bile almiyor. tum input game frame'e bind olmali."* Granting the stage IS the
|
|
514
|
+
// input handover, so the frame is focused with it — and again on pause's reversal, so a
|
|
515
|
+
// resumed game does not come back deaf.
|
|
516
|
+
if (playing) frame.focus();
|
|
508
517
|
// The toolbar swaps its icons for the handle on this event — it owns its own row.
|
|
509
518
|
document.dispatchEvent(new CustomEvent("justai:stage", { detail: { mode } }));
|
|
510
519
|
};
|
package/src/Toolbar.astro
CHANGED
|
@@ -156,8 +156,6 @@ import BackToZone from "./BackToZone.astro";
|
|
|
156
156
|
const {
|
|
157
157
|
sectionsLabel, profileLabel, kernelLabel, postsLabel,
|
|
158
158
|
files = true, filesLabel = "Files", kernelTitle, postsTitle, avatar = "/icon.svg", parent,
|
|
159
|
-
pauseLabel = "Pause",
|
|
160
|
-
fullscreenLabel = "Fullscreen",
|
|
161
159
|
} = Astro.props;
|
|
162
160
|
// A child's row answers UP to its parent, not out to the zone, and has no stream of its own — so
|
|
163
161
|
// both default off the moment `parent` is given, rather than each consumer remembering to say so.
|
|
@@ -263,29 +261,19 @@ import AuthMount from "./AuthMount.astro";
|
|
|
263
261
|
page (justai.pro carries app.zone's mark here). Keeping it out of <nav aria-label=sections>
|
|
264
262
|
is the a11y half of the reason it is its own slot. -->
|
|
265
263
|
<slot name="leftExtra" />
|
|
266
|
-
<!--
|
|
267
|
-
|
|
268
|
-
|
|
264
|
+
<!-- queries: where did the pause button go · toolbar controls while playing · tb-stage
|
|
265
|
+
THE ROW CARRIES NO GAME CONTROLS, and it did for one version. Pause and fullscreen were
|
|
266
|
+
drawn HERE first — the "withdraw to a single handle" design — and the founder struck it:
|
|
267
|
+
*"pause ve fullscreen ux bilesenleri oyun icerisinde olmali degil mi? bizim game persona
|
|
268
|
+
toolbari ile de isimiz yok ki."* He is right twice. The player's eyes and thumbs are in
|
|
269
|
+
the frame, and a control in chrome faded to 16% is a control where nobody is looking; and
|
|
270
|
+
while a game plays, this row is furniture — furniture does not sprout transport controls.
|
|
269
271
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
The buttons only DISPATCH. The Preroll owns the bus, so it listens and asks the game;
|
|
277
|
-
the chrome is restored when the GAME announces paused, never optimistically — state has
|
|
278
|
-
one source and it is the game. Fullscreen is feature-detected in the script below:
|
|
279
|
-
absent rather than dead where the platform does not implement it, which is every
|
|
280
|
-
iPhone. -->
|
|
281
|
-
<span class="tb-stage" id="tbStage">
|
|
282
|
-
<button class="tb-nav tb-pausebtn" id="tbPause" type="button" aria-label={pauseLabel} title={pauseLabel}>
|
|
283
|
-
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M9 3v18M15 3v18"/></svg>
|
|
284
|
-
</button>
|
|
285
|
-
<button class="tb-nav tb-fsbtn" id="tbFullscreen" type="button" aria-label={fullscreenLabel} title={fullscreenLabel} hidden>
|
|
286
|
-
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M8 3H5a2 2 0 0 0-2 2v3M16 3h3a2 2 0 0 1 2 2v3M8 21H5a2 2 0 0 1-2-2v-3M16 21h3a2 2 0 0 0 2-2v-3"/></svg>
|
|
287
|
-
</button>
|
|
288
|
-
</span>
|
|
272
|
+
So the GAME draws pause and fullscreen in its own HUD language, and announces state over
|
|
273
|
+
the protocol. The escape from a broken game is not a shell button either: the shell asks
|
|
274
|
+
the game to pause whenever the tab hides, so leaving and returning restores the chrome —
|
|
275
|
+
the browser's own gesture, which no game can fail to have. The row's whole part while
|
|
276
|
+
playing is to fade, go inert, and come back when the game says paused. -->
|
|
289
277
|
</div>
|
|
290
278
|
<div class="tb-right">
|
|
291
279
|
<slot name="toolbarRight" />
|
|
@@ -469,12 +457,14 @@ import AuthMount from "./AuthMount.astro";
|
|
|
469
457
|
* Opacity and pointer-events here; the INERT that takes them out of the tab order is set in the
|
|
470
458
|
* script, because CSS cannot. The transition matters more than it looks: chrome that snaps away
|
|
471
459
|
* reads as breaking, chrome that withdraws reads as dimming the house lights. */
|
|
472
|
-
.
|
|
473
|
-
|
|
460
|
+
/* QUIET, NOT DEAD. The first version faded the row to 16% and made it inert - a locked door.
|
|
461
|
+
* The founder's better idea: leave everything enabled, and USING any of it pauses the game -
|
|
462
|
+
* *"gitti chats'e tikladi. game state playing ise otomatik oyunu pause eder. daha smooth bir
|
|
463
|
+
* deneyim."* One tap instead of pause-then-tap, and the whole row becomes the way back. */
|
|
474
464
|
:global(html[data-stage="playing"]) .tb-nav-group,
|
|
475
465
|
:global(html[data-stage="playing"]) .tb-right,
|
|
476
466
|
:global(html[data-stage="playing"]) .tb-title {
|
|
477
|
-
opacity: 0.
|
|
467
|
+
opacity: 0.5;
|
|
478
468
|
transition: opacity 0.4s var(--ease-out);
|
|
479
469
|
}
|
|
480
470
|
/* icon-only section nav — current cut highlighted */
|
|
@@ -642,26 +632,29 @@ import AuthMount from "./AuthMount.astro";
|
|
|
642
632
|
// Both or neither — see the props above. When both are set the strip names the SECTIONS; core's
|
|
643
633
|
// default, which names the persona and its handle, is left entirely alone otherwise. Nothing here
|
|
644
634
|
// reproduces that default, which is the point: `.pname` and `.handle` stay core's business.
|
|
645
|
-
// ── the stage
|
|
646
|
-
// queries:
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
document.
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
635
|
+
// ── the stage: the row stays LIVE, and using it pauses the game ───────────────────────────
|
|
636
|
+
// queries: toolbar during a game · tapping posts while playing · auto pause · data-stage-silent
|
|
637
|
+
//
|
|
638
|
+
// The row went inert for one version and the founder unlocked it: every control stays enabled,
|
|
639
|
+
// and touching ANY of them while a game is playing asks the game to pause first — so a player who
|
|
640
|
+
// reaches for the posts mid-flight gets a paused gull and the feed, in one tap. The event is not
|
|
641
|
+
// blocked: the action proceeds naturally while the pause lands beside it (a locked page still
|
|
642
|
+
// scrolls programmatically, so even the hash navigation works before the unlock).
|
|
643
|
+
//
|
|
644
|
+
// Declarative seam, as asked: an element that must NOT pause the game opts out by carrying
|
|
645
|
+
// `data-stage-silent` — on itself or any ancestor. Everything else pauses by default, because a
|
|
646
|
+
// rule with a default and an opt-out survives a fleet; a per-element opt-in is the third copy
|
|
647
|
+
// that forgets.
|
|
648
|
+
document.querySelector(".toolbar")?.addEventListener(
|
|
649
|
+
"click",
|
|
650
|
+
(e) => {
|
|
651
|
+
if (document.documentElement.dataset.stage !== "playing") return;
|
|
652
|
+
const hit = (e.target as Element | null)?.closest?.("a, button, select, [role=button]");
|
|
653
|
+
if (!hit || hit.closest("[data-stage-silent]")) return;
|
|
654
|
+
document.dispatchEvent(new CustomEvent("justai:pause-request"));
|
|
655
|
+
},
|
|
656
|
+
true,
|
|
657
|
+
);
|
|
665
658
|
|
|
666
659
|
const bar = document.querySelector(".toolbar") as HTMLElement | null;
|
|
667
660
|
const kt = bar?.dataset.kernelTitle;
|