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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "anentrypoint-design",
3
- "version": "1.0.11",
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",
@@ -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
- opacity: 0.65;
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) { applyMinimized(el, 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.remove(); },
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
+ }