@justai/cuts 0.155.0 → 0.157.0
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/Base.astro +11 -2
- package/src/Preroll.astro +16 -0
- package/src/Toolbar.astro +22 -5
- package/src/behaviour/preroll.ts +10 -2
package/package.json
CHANGED
package/src/Base.astro
CHANGED
|
@@ -82,6 +82,12 @@ interface Props {
|
|
|
82
82
|
* privacy/terms child personas use this: the surface that proves it collects nothing by running
|
|
83
83
|
* nothing. */
|
|
84
84
|
gaId?: string | null;
|
|
85
|
+
/** Sign-in, ON by default. Pass `false` for a persona with no accounts: the SSO token capture is
|
|
86
|
+
* then not rendered in the head, so nothing reads `#auth_token` or writes `justai_token`. It is
|
|
87
|
+
* the head half of the opt-out — pass the same `auth={false}` to Toolbar, which then renders no
|
|
88
|
+
* AuthMount and loads no sdk.js. Everything else in the head (language, theme, the service
|
|
89
|
+
* worker, analytics as `gaId` decides) is untouched. */
|
|
90
|
+
auth?: boolean;
|
|
85
91
|
/**
|
|
86
92
|
* queries: kind game · data-kind · my game persona has margins · the game does not fill the screen ·
|
|
87
93
|
* which storefront lists this persona · persona kind in the layout
|
|
@@ -135,6 +141,7 @@ const {
|
|
|
135
141
|
themeDark,
|
|
136
142
|
themeLight,
|
|
137
143
|
gaId = "G-13L3BP6XCW",
|
|
144
|
+
auth = true,
|
|
138
145
|
kind = "app",
|
|
139
146
|
page,
|
|
140
147
|
} = Astro.props;
|
|
@@ -210,8 +217,10 @@ const ogImage = page?.image
|
|
|
210
217
|
#auth_token before the deferred sdk.js can read it; and the language picker copies the
|
|
211
218
|
current hash onto the next locale's URL (LangPicker), which would PROPAGATE the raw token
|
|
212
219
|
into a new page and into history. Capturing first defeats both. Move this and sign-in breaks
|
|
213
|
-
silently — no error, the visitor simply lands back signed out.
|
|
214
|
-
|
|
220
|
+
silently — no error, the visitor simply lands back signed out.
|
|
221
|
+
A persona with no accounts (`auth={false}`) has no token to capture, so the script is not
|
|
222
|
+
rendered at all. */}
|
|
223
|
+
{auth && <script is:inline set:html={AUTH_CAPTURE_JS} />}
|
|
215
224
|
<script is:inline set:html={JS_CLASS_JS} />
|
|
216
225
|
{/* queries: design grid · x-ray · ?xray · safe area · debug overlay · see the layout ·
|
|
217
226
|
is my content inside the safe area · layout debugging
|
package/src/Preroll.astro
CHANGED
|
@@ -457,6 +457,22 @@ const primary = storeRows[0]?.url;
|
|
|
457
457
|
* container, and layout containment makes it the containing block for FIXED descendants too — a
|
|
458
458
|
* fixed overlay written inside it would be clipped to the frame it is meant to surround. */
|
|
459
459
|
html[data-stage="playing"] { overflow: hidden; }
|
|
460
|
+
/* queries: oyun başlayınca toolbar gitsin · the toolbar hides while playing · full screen game ·
|
|
461
|
+
* tam ekran oyun · ipad oyun ekranı · the hud is under the toolbar
|
|
462
|
+
*
|
|
463
|
+
* ── WHILE A GAME PLAYS, THE TOOLBAR STEPS OUT AND THE GAME TAKES THE WHOLE SCREEN ──────────────
|
|
464
|
+
*
|
|
465
|
+
* The founder, 2026-10-22, on an iPad and a phone: the game's own money, day and full-screen keys
|
|
466
|
+
* were crowded by the bar above them. So while the stage is `playing` the bar's sticky slot leaves
|
|
467
|
+
* the flow and the game kernel grows by exactly what it gave up — the whole painted screen. The
|
|
468
|
+
* moment the game announces `paused` (its own pause key, the tab hidden, leaving full screen) the
|
|
469
|
+
* attribute goes and the bar comes back with the page as it was. The protocol is unchanged: the
|
|
470
|
+
* game says what the player is doing, and this is only what the shell does with it. */
|
|
471
|
+
html[data-stage="playing"] .tb-slot { display: none; }
|
|
472
|
+
/* What the shell takes above the kernel is nothing, while it plays: the one number the game
|
|
473
|
+
* kernel's height law and its landing offset both read (@justai/ui base.css). `!important` because
|
|
474
|
+
* the shell measures the bar and writes the number inline on the root — and the bar is gone. */
|
|
475
|
+
html[data-stage="playing"] { --shell-top: 0px !important; }
|
|
460
476
|
/* queries: theater mode · where did the dim layer go · dark theme while playing
|
|
461
477
|
*
|
|
462
478
|
* ── THE THEATER IS THE PERSONA'S OWN DARK THEME, NOT A LAYER ────────────────────────────────
|
package/src/Toolbar.astro
CHANGED
|
@@ -54,9 +54,12 @@ interface Props {
|
|
|
54
54
|
// translated it yet gets a working, named control rather than an unlabelled icon.
|
|
55
55
|
files?: boolean;
|
|
56
56
|
filesLabel?: string;
|
|
57
|
-
// The home affordance points at
|
|
58
|
-
//
|
|
59
|
-
// the
|
|
57
|
+
// The home affordance points at the persona's apex (`apex` below), so EVERY apex suppresses it:
|
|
58
|
+
// app.zone, pin.games and cityinmotion.nl ARE that destination — told their own host, the row
|
|
59
|
+
// draws their mark as a link to the page it sits on, beside the profile icon that is the same
|
|
60
|
+
// face (cityinmotion.nl shipped exactly that until 2026-10-15) — and justai.pro is above them
|
|
61
|
+
// all (sending the parent "home" to a child platform is the wrong direction). Every other
|
|
62
|
+
// persona keeps it. The template passes `home={false}` for every apex it generates.
|
|
60
63
|
home?: boolean;
|
|
61
64
|
/**
|
|
62
65
|
* Which storefront the home affordance points at. Defaults to app.zone — see BackToZone, which owns
|
|
@@ -147,11 +150,25 @@ interface Props {
|
|
|
147
150
|
// `feed` already reads the host persona's avatar from the registry, and an absolute URL it was
|
|
148
151
|
// given beats a relative one it inferred.
|
|
149
152
|
parent?: { href?: string; label?: string; icon?: string };
|
|
153
|
+
|
|
154
|
+
// queries: accountless persona · no sign-in on this persona · turn auth off · auth={false} ·
|
|
155
|
+
// the toolbar loads sdk.js on a persona with no accounts · privacy-sensitive persona
|
|
156
|
+
//
|
|
157
|
+
// ── SIGN-IN, ON UNLESS A PERSONA SAYS IT HAS NO ACCOUNTS ─────────────────────────────────────
|
|
158
|
+
//
|
|
159
|
+
// ON by default, because every persona today is one place in one signed-in ecosystem. Pass
|
|
160
|
+
// `auth={false}` and the AuthMount is not RENDERED — no mount point, no sdk.js tag,
|
|
161
|
+
// so no request to auth.justai.pro is ever made. Hiding it would not be the same thing: a hidden
|
|
162
|
+
// mount still loads a third-party script into the persona's origin, which is the surface an
|
|
163
|
+
// accountless, privacy-sensitive persona is opting out of.
|
|
164
|
+
//
|
|
165
|
+
// Pass the same `auth={false}` to Base, which owns the other half (the token capture in the head).
|
|
166
|
+
auth?: boolean;
|
|
150
167
|
}
|
|
151
168
|
import BackToZone from "./BackToZone.astro";
|
|
152
169
|
const {
|
|
153
170
|
sectionsLabel, profileLabel, kernelLabel, postsLabel,
|
|
154
|
-
files = true, filesLabel = "Files", landOn, avatar = "/icon.svg", parent,
|
|
171
|
+
files = true, filesLabel = "Files", landOn, avatar = "/icon.svg", parent, auth = true,
|
|
155
172
|
} = Astro.props;
|
|
156
173
|
// A child's row answers UP to its parent, not out to the zone, and has no stream of its own — so
|
|
157
174
|
// both default off the moment `parent` is given, rather than each consumer remembering to say so.
|
|
@@ -274,7 +291,7 @@ import AuthMount from "./AuthMount.astro";
|
|
|
274
291
|
<div class="tb-right">
|
|
275
292
|
<slot name="toolbarRight" />
|
|
276
293
|
<slot name="langPicker" />
|
|
277
|
-
<AuthMount />
|
|
294
|
+
{auth && <AuthMount />}
|
|
278
295
|
</div>
|
|
279
296
|
</div>
|
|
280
297
|
</header>
|
package/src/behaviour/preroll.ts
CHANGED
|
@@ -180,8 +180,11 @@ if (root && root.dataset.door === "store") {
|
|
|
180
180
|
const el = document.getElementById(id);
|
|
181
181
|
if (el) el.toggleAttribute("inert", playing);
|
|
182
182
|
}
|
|
183
|
-
// The page is locked, so make sure what it is locked ON is the stage
|
|
184
|
-
|
|
183
|
+
// The page is locked, so make sure what it is locked ON is the stage — the whole of it, now
|
|
184
|
+
// that the toolbar has stepped out (see Preroll.astro). On pause the bar is back, and the
|
|
185
|
+
// kernel lands under it again by its own scroll-margin.
|
|
186
|
+
if (playing) (document.getElementById("kernel") ?? stage).scrollIntoView({ block: "start" });
|
|
187
|
+
else document.getElementById("kernel")?.scrollIntoView({ block: "start" });
|
|
185
188
|
// queries: space does nothing · keyboard not reaching the game · input bind · focus
|
|
186
189
|
//
|
|
187
190
|
// AND THE KEYBOARD GOES WITH THE STAGE. The play press happened in THIS document, so this
|
|
@@ -245,6 +248,11 @@ if (root && root.dataset.door === "store") {
|
|
|
245
248
|
document.addEventListener("justai:pause-request", () => askPause("chrome"));
|
|
246
249
|
document.addEventListener("justai:fullscreen-request", () =>
|
|
247
250
|
(stage as any).requestFullscreen?.().catch(() => {}));
|
|
251
|
+
// Leaving full screen is leaving the game for a moment: it pauses, and with the pause the
|
|
252
|
+
// toolbar comes back — the same way back as the game's own pause key.
|
|
253
|
+
document.addEventListener("fullscreenchange", () => {
|
|
254
|
+
if (!document.fullscreenElement && document.documentElement.dataset.stage === "playing") askPause("fullscreen");
|
|
255
|
+
});
|
|
248
256
|
document.addEventListener("visibilitychange", () => {
|
|
249
257
|
if (document.hidden && document.documentElement.dataset.stage === "playing") askPause("hidden");
|
|
250
258
|
});
|