anentrypoint-design 1.0.11 → 1.0.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/package.json +1 -1
- package/src/kits/os/theme.css +62 -1
- package/src/kits/os/wm.js +41 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "anentrypoint-design",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.12",
|
|
4
4
|
"description": "247420 design system SDK — webjsx + modified ripple-ui, single-file ESM bundle for reproducible use of the AnEntrypoint design.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/247420.js",
|
package/src/kits/os/theme.css
CHANGED
|
@@ -368,7 +368,63 @@ html, body {
|
|
|
368
368
|
overflow: hidden;
|
|
369
369
|
display: flex;
|
|
370
370
|
flex-direction: column;
|
|
371
|
+
/* Open/maximize/restore transitions: transform+opacity are interpolable
|
|
372
|
+
* (unlike wm-min's `display:none`, which cannot transition at all — a
|
|
373
|
+
* real minimize/restore animation needs wm.js to defer the display swap
|
|
374
|
+
* until this transition ends, tracked as its own follow-up). A freshly
|
|
375
|
+
* mounted .wm-win starts from CSS-animation-in via @starting-style so it
|
|
376
|
+
* scales/fades into place instead of snapping to full size, and every
|
|
377
|
+
* maximize/restore toggle (a real geometry change, not a display swap)
|
|
378
|
+
* eases instead of jumping. */
|
|
379
|
+
transition: opacity 160ms ease, transform 160ms cubic-bezier(0.2, 0.8, 0.3, 1), box-shadow 160ms ease;
|
|
380
|
+
}
|
|
381
|
+
@supports (transition-behavior: allow-discrete) {
|
|
382
|
+
.ds-247420 .wm-win {
|
|
383
|
+
transition: opacity 160ms ease, transform 160ms cubic-bezier(0.2, 0.8, 0.3, 1), box-shadow 160ms ease;
|
|
384
|
+
@starting-style {
|
|
385
|
+
opacity: 0;
|
|
386
|
+
transform: scale(0.96);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
@media (prefers-reduced-motion: reduce) {
|
|
391
|
+
.ds-247420 .wm-win { transition: none; }
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/* Minimize/restore/close: wm.js's animateMinimize()/animateClose() (wm.js)
|
|
395
|
+
* apply these classes BEFORE the real wm-min toggle / el.remove(), holding
|
|
396
|
+
* them for exactly the duration below so the display:none / DOM-removal
|
|
397
|
+
* that neither CSS nor `transition` can animate happens only after the
|
|
398
|
+
* visual scale+fade has actually played out. Direction: minimize collapses
|
|
399
|
+
* toward the taskbar (down+shrink); close shrinks in place; restore is the
|
|
400
|
+
* minimize keyframe in reverse. Not scoped to .ds-247420 -- these classes
|
|
401
|
+
* are always renderWindow()-authored, own their state fully. */
|
|
402
|
+
.wm-win.wm-minimizing {
|
|
403
|
+
transition: opacity 200ms ease, transform 200ms cubic-bezier(0.4, 0, 1, 1);
|
|
404
|
+
opacity: 0;
|
|
405
|
+
transform: scale(0.85) translateY(24px);
|
|
406
|
+
pointer-events: none;
|
|
371
407
|
}
|
|
408
|
+
.wm-win.wm-restoring {
|
|
409
|
+
transition: opacity 200ms ease, transform 200ms cubic-bezier(0.2, 0.8, 0.3, 1);
|
|
410
|
+
animation: wm-restore-in 200ms cubic-bezier(0.2, 0.8, 0.3, 1);
|
|
411
|
+
}
|
|
412
|
+
@keyframes wm-restore-in {
|
|
413
|
+
from { opacity: 0; transform: scale(0.85) translateY(24px); }
|
|
414
|
+
to { opacity: 1; transform: scale(1) translateY(0); }
|
|
415
|
+
}
|
|
416
|
+
.wm-win.wm-closing {
|
|
417
|
+
transition: opacity 200ms ease, transform 200ms cubic-bezier(0.4, 0, 1, 1);
|
|
418
|
+
opacity: 0;
|
|
419
|
+
transform: scale(0.92);
|
|
420
|
+
pointer-events: none;
|
|
421
|
+
}
|
|
422
|
+
@media (prefers-reduced-motion: reduce) {
|
|
423
|
+
.wm-win.wm-minimizing, .wm-win.wm-restoring, .wm-win.wm-closing {
|
|
424
|
+
transition: none; animation: none; opacity: 1; transform: none;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
372
428
|
.ds-247420 .wm-win.wm-focused {
|
|
373
429
|
border-color: color-mix(in oklab, var(--os-fg) 28%, transparent);
|
|
374
430
|
box-shadow: inset var(--space-1) 0 0 var(--os-accent), var(--shadow-3);
|
|
@@ -396,7 +452,12 @@ html, body {
|
|
|
396
452
|
letter-spacing: 0.005em;
|
|
397
453
|
text-align: center;
|
|
398
454
|
font-weight: 600;
|
|
399
|
-
|
|
455
|
+
/* 0.72, not 0.65: measured live against the unfocused titlebar's actual
|
|
456
|
+
* background (rgb(77,77,82)) the opacity-blended effective contrast at
|
|
457
|
+
* 0.65 was 4.25:1 -- below WCAG AA's 4.5:1 floor for normal text. 0.72
|
|
458
|
+
* clears it with margin (~4.8:1) while staying visually dimmer than the
|
|
459
|
+
* focused window's full-opacity title. */
|
|
460
|
+
opacity: 0.72;
|
|
400
461
|
transition: opacity 120ms ease;
|
|
401
462
|
/* No text-transform here: the titlebar renders the window's own dynamic
|
|
402
463
|
* title (renderWindow({title}) / setTitle(t) in wm.js) — a user- or
|
package/src/kits/os/wm.js
CHANGED
|
@@ -226,11 +226,11 @@ export function renderWindow(opts = {}) {
|
|
|
226
226
|
},
|
|
227
227
|
setFocused(v) { applyFocused(el, v); },
|
|
228
228
|
setMaximized(v) { applyMaximized(el, v); },
|
|
229
|
-
setMinimized(v) {
|
|
229
|
+
setMinimized(v) { animateMinimize(el, v); },
|
|
230
230
|
setInstanceId(id) { if (id) el.dataset.instanceId = id; else delete el.dataset.instanceId; },
|
|
231
231
|
setZIndex(z) { el.style.zIndex = String(z); },
|
|
232
232
|
getBounds() { return { x: el.offsetLeft, y: el.offsetTop, w: el.offsetWidth, h: el.offsetHeight }; },
|
|
233
|
-
dispose() { if (closeArmTimer) clearTimeout(closeArmTimer); el
|
|
233
|
+
dispose() { if (closeArmTimer) clearTimeout(closeArmTimer); animateClose(el); },
|
|
234
234
|
};
|
|
235
235
|
}
|
|
236
236
|
|
|
@@ -252,3 +252,42 @@ function setBodyContent(host, body) {
|
|
|
252
252
|
function applyFocused(el, v) { el.classList.toggle('wm-focused', !!v); }
|
|
253
253
|
function applyMaximized(el, v) { el.classList.toggle('wm-max', !!v); }
|
|
254
254
|
function applyMinimized(el, v) { el.classList.toggle('wm-min', !!v); }
|
|
255
|
+
|
|
256
|
+
function reducedMotion() {
|
|
257
|
+
return typeof matchMedia === 'function' && matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// wm.css's `.wm-win.wm-min{display:none}` cannot be CSS-transitioned (display
|
|
261
|
+
// has no interpolable intermediate value), so a real minimize animation needs
|
|
262
|
+
// the display swap deferred until a scale+fade transition actually finishes.
|
|
263
|
+
// `.wm-minimizing`/`.wm-restoring` (theme.css) carry the transform+opacity
|
|
264
|
+
// keyframes; this only sequences when `wm-min` itself flips. 220ms fallback
|
|
265
|
+
// timer guards against a transitionend that never fires (element removed
|
|
266
|
+
// mid-transition, browser tab backgrounded and rAF/transitions paused, etc.)
|
|
267
|
+
// so a window can never get stuck invisible-but-not-display:none.
|
|
268
|
+
function animateMinimize(el, v) {
|
|
269
|
+
if (reducedMotion()) { applyMinimized(el, v); return; }
|
|
270
|
+
if (v) {
|
|
271
|
+
el.classList.add('wm-minimizing');
|
|
272
|
+
const done = () => { el.classList.remove('wm-minimizing'); applyMinimized(el, true); };
|
|
273
|
+
el.addEventListener('transitionend', done, { once: true });
|
|
274
|
+
setTimeout(done, 220);
|
|
275
|
+
} else {
|
|
276
|
+
applyMinimized(el, false);
|
|
277
|
+
el.classList.add('wm-restoring');
|
|
278
|
+
setTimeout(() => el.classList.remove('wm-restoring'), 220);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// Same display-can't-transition problem as minimize, but for the terminal
|
|
283
|
+
// close path: el.remove() used to happen synchronously, so a window vanished
|
|
284
|
+
// instantly with no close animation at all (the literal gap named in the
|
|
285
|
+
// "no animation on open/close" request). Fade+scale out, then remove.
|
|
286
|
+
function animateClose(el) {
|
|
287
|
+
if (!el.isConnected) return;
|
|
288
|
+
if (reducedMotion()) { el.remove(); return; }
|
|
289
|
+
el.classList.add('wm-closing');
|
|
290
|
+
const done = () => el.remove();
|
|
291
|
+
el.addEventListener('transitionend', done, { once: true });
|
|
292
|
+
setTimeout(done, 220);
|
|
293
|
+
}
|