0.28.1 — vendor @joan/procedural-glyph-engine for portable SPA builds (fixes deploy)
The procedural-glyph-engine dep pointed at a non-portable file:/private/tmp/orby-pkg
path, breaking npm ci in Docker and every main deploy since v0.20.0 (the build
cache masked it until it busted ~Aug 5). Vendor Orby v5.0.0 into web/vendor/,
switch the dep to file:../vendor, and use npm install in the web Dockerfile
(file: deps need install, not ci). Cherry-picked from 3cd4cf9.
This commit is contained in:
82
web/vendor/src/preview-thumbnails.js
vendored
Normal file
82
web/vendor/src/preview-thumbnails.js
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
const DEFAULT_PREVIEW_PROGRESS = 0.48;
|
||||
|
||||
function clamp01(value) {
|
||||
return Math.min(1, Math.max(0, Number(value) || 0));
|
||||
}
|
||||
|
||||
function representativeTime(recipe) {
|
||||
const phase = clamp01(recipe?.reducedMotion?.phase ?? 0.25);
|
||||
const cycleMs =
|
||||
Number(recipe?.timeline?.macroCycleMs) ||
|
||||
Number(recipe?.timeline?.durationMs) ||
|
||||
4000;
|
||||
return (Math.max(1, cycleMs) / 1000) * phase;
|
||||
}
|
||||
|
||||
/**
|
||||
* One-shot recipes may advance to a different state while their card is active.
|
||||
* Atlas previews retain the requested recipe so their identity and resting frame
|
||||
* always match the card label.
|
||||
*/
|
||||
export function createThumbnailRecipe(recipe) {
|
||||
if (!recipe?.timeline?.next) return recipe;
|
||||
return {
|
||||
...recipe,
|
||||
timeline: {
|
||||
...recipe.timeline,
|
||||
next: null,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function shouldAnimateThumbnail(
|
||||
id,
|
||||
{
|
||||
selectedId = null,
|
||||
mainRunning = false,
|
||||
hoveredIds = new Set(),
|
||||
focusedIds = new Set(),
|
||||
} = {},
|
||||
) {
|
||||
return (
|
||||
(id === selectedId && mainRunning) ||
|
||||
hoveredIds.has(id) ||
|
||||
focusedIds.has(id)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a deterministic, authored representative phase without leaving the
|
||||
* preview in reduced-motion mode. JoanGlyphEngine maps time zero to each
|
||||
* recipe's reducedMotion.phase while reduced motion is enabled.
|
||||
*/
|
||||
export function renderThumbnailRestFrame(
|
||||
preview,
|
||||
{ progress = DEFAULT_PREVIEW_PROGRESS } = {},
|
||||
) {
|
||||
if (!preview || preview.destroyed) return null;
|
||||
|
||||
const nextProgress = clamp01(progress);
|
||||
if (Math.abs(preview.progress - nextProgress) > 1e-6) {
|
||||
preview.setProgress(nextProgress);
|
||||
}
|
||||
|
||||
// Neighbor-propagation previews otherwise retain their previous gate buffer,
|
||||
// making the supposedly static pose depend on how long the card was hovered.
|
||||
preview.stateElapsed = representativeTime(preview.currentRecipe);
|
||||
preview.gates?.fill(0);
|
||||
preview.neighborBuffer?.fill(0);
|
||||
preview.dwell?.fill(0);
|
||||
|
||||
const previousReducedMotion = preview.reducedMotion;
|
||||
preview.reducedMotion = true;
|
||||
let stats;
|
||||
try {
|
||||
stats = preview.renderOnce(0);
|
||||
} finally {
|
||||
preview.reducedMotion = previousReducedMotion;
|
||||
}
|
||||
|
||||
if (preview.canvas?.dataset) preview.canvas.dataset.previewState = "ready";
|
||||
return stats;
|
||||
}
|
||||
Reference in New Issue
Block a user