@vectoriox/iox-ui 5.76.1 → 5.77.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/fesm2022/vectoriox-iox-ui-media-core.mjs +11 -11
- package/fesm2022/vectoriox-iox-ui-media-core.mjs.map +1 -1
- package/fesm2022/vectoriox-iox-ui-scene-core.mjs +29 -1
- package/fesm2022/vectoriox-iox-ui-scene-core.mjs.map +1 -1
- package/media-core/index.d.ts +7 -5
- package/package.json +1 -1
- package/scene-core/index.d.ts +19 -2
- package/src/media-core/frames.ts +10 -11
- package/src/scene-core/scene-edit.ts +35 -0
package/media-core/index.d.ts
CHANGED
|
@@ -38,8 +38,12 @@ declare enum FrameExtension {
|
|
|
38
38
|
Webp = "webp",
|
|
39
39
|
Jpeg = "jpg"
|
|
40
40
|
}
|
|
41
|
-
/**
|
|
42
|
-
|
|
41
|
+
/**
|
|
42
|
+
* The most pictures one set may hold. A film's smoothness is its density, pictures per screen of scrolling: 210 over 18
|
|
43
|
+
* screens stepped on Doron's iPhone as a glide slowed, 1050 did not (2026-11-05). Memory is not what limits it: the player
|
|
44
|
+
* keeps the downloaded files (about 10 kB a phone picture) and only a window of them unpacked (`unpackedFrameCount`).
|
|
45
|
+
*/
|
|
46
|
+
declare const MAX_FRAMES = 1200;
|
|
43
47
|
/** The most one picture may weigh when uploaded. */
|
|
44
48
|
declare const MAX_FRAME_BYTES: number;
|
|
45
49
|
/** A sequence's name in storage: what the browser generates and what the server accepts in a key. */
|
|
@@ -109,8 +113,6 @@ declare function fittedFrameSize(width: number, height: number, longSide: number
|
|
|
109
113
|
declare function videoFrameCount(seconds: number): number;
|
|
110
114
|
/** Which of `sourceCount` pictures make a set of `count`, spread evenly, first and last always in. */
|
|
111
115
|
declare function sampledFrameIndexes(sourceCount: number, count: number): number[];
|
|
112
|
-
/** A phone plays half the pictures: it has less memory, and half is plenty on a small screen. */
|
|
113
|
-
declare function phoneFrameCount(wideCount: number): number;
|
|
114
116
|
/** Rendered frames in their real order: `frame2` before `frame10`. */
|
|
115
117
|
declare function sortFrameFiles<T extends {
|
|
116
118
|
name: string;
|
|
@@ -471,5 +473,5 @@ declare function attachVideos(container: ParentNode, options?: VideoRuntimeOptio
|
|
|
471
473
|
/** The runtime already running at `el`, if any. */
|
|
472
474
|
declare function videoRuntimeOf(el: Element | null | undefined): VideoRuntime | null;
|
|
473
475
|
|
|
474
|
-
export { CONSENT_GRANT_EVENT, CONSENT_PREFERENCES_EVENT, FRAMES_PHONE_MAX_WIDTH, FRAMES_SHOWING_ATTRIBUTE, FRAMES_UNPACKED_BYTES, FRAME_BLEND_STEPS, FRAME_SEQUENCE_ID, FrameExtension, FramePlayer, FrameSet, FramesClass, MAX_FRAMES, MAX_FRAME_BYTES, PHONE_LONG_SIDE, VIDEO_EMBED_ORIGINS, VIDEO_NODE_TYPE, VIDEO_PROVIDER_COMPANY, VIDEO_PROVIDER_LABEL, VIDEO_WORDS, VideoAttribute, VideoClass, VideoIcon, VideoKind, VideoMode, VideoRuntime, VideoSource, VideoTrait, WIDE_LONG_SIDE, attachVideoAt, attachVideos, documentConsentTransport, fittedFrameSize, frameBlendAt, frameFileName, frameIndexAt, frameLoadOrder, framePosition, frameSetFor, frameSummary, frameUrl, framesToHold, isThirdPartyPoster, nearestLoadedFrame, normalizeFrameSequence, parseVideoUrl,
|
|
476
|
+
export { CONSENT_GRANT_EVENT, CONSENT_PREFERENCES_EVENT, FRAMES_PHONE_MAX_WIDTH, FRAMES_SHOWING_ATTRIBUTE, FRAMES_UNPACKED_BYTES, FRAME_BLEND_STEPS, FRAME_SEQUENCE_ID, FrameExtension, FramePlayer, FrameSet, FramesClass, MAX_FRAMES, MAX_FRAME_BYTES, PHONE_LONG_SIDE, VIDEO_EMBED_ORIGINS, VIDEO_NODE_TYPE, VIDEO_PROVIDER_COMPANY, VIDEO_PROVIDER_LABEL, VIDEO_WORDS, VideoAttribute, VideoClass, VideoIcon, VideoKind, VideoMode, VideoRuntime, VideoSource, VideoTrait, WIDE_LONG_SIDE, attachVideoAt, attachVideos, documentConsentTransport, fittedFrameSize, frameBlendAt, frameFileName, frameIndexAt, frameLoadOrder, framePosition, frameSetFor, frameSummary, frameUrl, framesToHold, isThirdPartyPoster, nearestLoadedFrame, normalizeFrameSequence, parseVideoUrl, phoneFrameSrcset, planVideo, readConsentRecord, sampledFrameIndexes, serializeVideoAttributes, sortFrameFiles, unpackedFrameCount, videoConsentCategory, videoEmbedUrl, videoFrameCount, videoInnerHtml, videoPlayLabel, videoPosterFileName, videoProp, videoRefOf, videoRootAttributes, videoRuntimeOf, videoSourceOf, videoThumbnailRequest, videoWords };
|
|
475
477
|
export type { ConsentGrantDetail, ConsentTransport, FrameBlend, FramePlayerOptions, FrameSequence, FrameSetInfo, FrameSizes, VideoMarkupOptions, VideoNodeLike, VideoPlan, VideoRef, VideoRuntimeOptions, VideoThumbnailRequest, VideoWords };
|
package/package.json
CHANGED
package/scene-core/index.d.ts
CHANGED
|
@@ -218,6 +218,23 @@ declare const SCENE_MAX_SCREENS = 20;
|
|
|
218
218
|
*/
|
|
219
219
|
declare function sceneScreensOf(height: string | null | undefined): number | null;
|
|
220
220
|
declare function sceneHeightForScreens(screens: number): string;
|
|
221
|
+
/**
|
|
222
|
+
* Pictures per screen of scrolling at which a played film stays smooth as a glide slows to a stop. Measured on Doron's
|
|
223
|
+
* iPhone (2026-11-05): Studio Alma's film at about 11 a screen stepped, at about 55 it did not.
|
|
224
|
+
*/
|
|
225
|
+
declare const SCENE_FILM_SMOOTH = 40;
|
|
226
|
+
interface SceneFilmDensity {
|
|
227
|
+
/** Pictures per screen of scrolling over most of the play: half its scroll holds at least this many. */
|
|
228
|
+
perScreen: number;
|
|
229
|
+
/** The screens of scrolling the film plays over; where it holds still is not counted. */
|
|
230
|
+
screens: number;
|
|
231
|
+
smooth: boolean;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* How densely a film of `count` pictures plays on a Scene of `screens`, by its Play track; null when nothing plays. A
|
|
235
|
+
* film's smoothness is its density, never the drawing: spread thin, a slowing glide holds each picture for many refreshes.
|
|
236
|
+
*/
|
|
237
|
+
declare function sceneFilmDensity(tracks: ReadonlyArray<SceneTrack> | null | undefined, screens: number | null, count: number): SceneFilmDensity | null;
|
|
221
238
|
/** Motion v2 §3d's limits for scroll-linked work on one page. */
|
|
222
239
|
declare const SCENE_BUDGET: {
|
|
223
240
|
readonly heldSections: 1;
|
|
@@ -402,5 +419,5 @@ declare function revealStagger(groups: number, by: TextRevealBy): number;
|
|
|
402
419
|
*/
|
|
403
420
|
declare function playTextReveal(el: HTMLElement, by: TextRevealBy, timing: KeyframeAnimationOptions): Animation | null;
|
|
404
421
|
|
|
405
|
-
export { LIGHT_UP_PIECE_CAP, REVEAL_PIECE_CAP, SCENE_BUDGET, SCENE_DAMPING, SCENE_FLOW_RULES, SCENE_LENGTH, SCENE_MAX_SCREENS, SCENE_MIN_SCREENS, SCENE_PHONE_LENGTH, SCENE_PHONE_MAX_WIDTH, SCENE_REDUCED_MOTION_CSS, SCENE_REVEAL_DEFAULT, SCENE_STAGE_HEIGHT, SCENE_TRACK_DEFS, SCENE_WORDS, SCENE_WORD_DIM, SceneAttribute, SceneProp, SceneRevealFrom, ScrollDriver, TextRevealBy, applySceneFirstFrame, attachScenes, buildSceneRecipe, colourAt, dampToward, lineIndexes, movedSceneKey, normalizeTracks, playTextReveal, revealClipPath, revealStagger, sceneBudget, sceneColourKeyAt, sceneDisplayValue, sceneFirstFrame, sceneFrame, sceneFrameDeclarations, sceneHasKeyAt, sceneHeightForScreens, sceneKeyPosition, sceneLayersOf, sceneNodeAttributes, scenePlayed, sceneRevealFromOf, sceneRootOnPath, sceneScreensOf, sceneScrollState, sceneTrackDef, sceneTrackSpan, sceneWordOpacity, sceneWordsLit, scenesIn, splitText, syncSceneAttributes, textPieces, valueAt, withSceneKey, withScenePlayback, withSceneRevealFrom, withoutSceneKey, withoutScenePlayback };
|
|
406
|
-
export type { SceneBudget, SceneFrame, SceneFrameOptions, SceneFrameState, SceneKey, SceneLayerNode, SceneNodeSource, SceneTrack, SceneTrackDef, SceneTreeNode, SceneWords, ScrollDriverOptions, SplitText, SplitTextOptions, TextPiece };
|
|
422
|
+
export { LIGHT_UP_PIECE_CAP, REVEAL_PIECE_CAP, SCENE_BUDGET, SCENE_DAMPING, SCENE_FILM_SMOOTH, SCENE_FLOW_RULES, SCENE_LENGTH, SCENE_MAX_SCREENS, SCENE_MIN_SCREENS, SCENE_PHONE_LENGTH, SCENE_PHONE_MAX_WIDTH, SCENE_REDUCED_MOTION_CSS, SCENE_REVEAL_DEFAULT, SCENE_STAGE_HEIGHT, SCENE_TRACK_DEFS, SCENE_WORDS, SCENE_WORD_DIM, SceneAttribute, SceneProp, SceneRevealFrom, ScrollDriver, TextRevealBy, applySceneFirstFrame, attachScenes, buildSceneRecipe, colourAt, dampToward, lineIndexes, movedSceneKey, normalizeTracks, playTextReveal, revealClipPath, revealStagger, sceneBudget, sceneColourKeyAt, sceneDisplayValue, sceneFilmDensity, sceneFirstFrame, sceneFrame, sceneFrameDeclarations, sceneHasKeyAt, sceneHeightForScreens, sceneKeyPosition, sceneLayersOf, sceneNodeAttributes, scenePlayed, sceneRevealFromOf, sceneRootOnPath, sceneScreensOf, sceneScrollState, sceneTrackDef, sceneTrackSpan, sceneWordOpacity, sceneWordsLit, scenesIn, splitText, syncSceneAttributes, textPieces, valueAt, withSceneKey, withScenePlayback, withSceneRevealFrom, withoutSceneKey, withoutScenePlayback };
|
|
423
|
+
export type { SceneBudget, SceneFilmDensity, SceneFrame, SceneFrameOptions, SceneFrameState, SceneKey, SceneLayerNode, SceneNodeSource, SceneTrack, SceneTrackDef, SceneTreeNode, SceneWords, ScrollDriverOptions, SplitText, SplitTextOptions, TextPiece };
|
package/src/media-core/frames.ts
CHANGED
|
@@ -42,8 +42,12 @@ export enum FrameExtension {
|
|
|
42
42
|
Jpeg = 'jpg',
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
/**
|
|
46
|
-
|
|
45
|
+
/**
|
|
46
|
+
* The most pictures one set may hold. A film's smoothness is its density, pictures per screen of scrolling: 210 over 18
|
|
47
|
+
* screens stepped on Doron's iPhone as a glide slowed, 1050 did not (2026-11-05). Memory is not what limits it: the player
|
|
48
|
+
* keeps the downloaded files (about 10 kB a phone picture) and only a window of them unpacked (`unpackedFrameCount`).
|
|
49
|
+
*/
|
|
50
|
+
export const MAX_FRAMES = 1200;
|
|
47
51
|
/** The most one picture may weigh when uploaded. */
|
|
48
52
|
export const MAX_FRAME_BYTES = 3 * 1024 * 1024;
|
|
49
53
|
/** A sequence's name in storage: what the browser generates and what the server accepts in a key. */
|
|
@@ -206,10 +210,10 @@ export interface FrameSizes {
|
|
|
206
210
|
* tall stage by its height, so a picture sized to the phone's width would be enlarged five times. */
|
|
207
211
|
export const WIDE_LONG_SIDE = 1600;
|
|
208
212
|
export const PHONE_LONG_SIDE = 1100;
|
|
209
|
-
/** How many pictures a second of video becomes, before the cap. */
|
|
210
|
-
const VIDEO_FRAMES_PER_SECOND =
|
|
211
|
-
/** A video's cap:
|
|
212
|
-
const VIDEO_MAX_FRAMES =
|
|
213
|
+
/** How many pictures a second of video becomes, before the cap: what most recordings hold, so few are the same twice. */
|
|
214
|
+
const VIDEO_FRAMES_PER_SECOND = 30;
|
|
215
|
+
/** A video's cap: half a minute at that rate. A set of pictures is the author's own count, up to `MAX_FRAMES`. */
|
|
216
|
+
const VIDEO_MAX_FRAMES = 900;
|
|
213
217
|
|
|
214
218
|
/** `width`×`height` fitted inside `longSide`, never enlarged. */
|
|
215
219
|
export function fittedFrameSize(width: number, height: number, longSide: number): FrameSizes {
|
|
@@ -229,11 +233,6 @@ export function sampledFrameIndexes(sourceCount: number, count: number): number[
|
|
|
229
233
|
return Array.from({ length: count }, (_, i) => Math.round((i * (sourceCount - 1)) / (count - 1)));
|
|
230
234
|
}
|
|
231
235
|
|
|
232
|
-
/** A phone plays half the pictures: it has less memory, and half is plenty on a small screen. */
|
|
233
|
-
export function phoneFrameCount(wideCount: number): number {
|
|
234
|
-
return Math.max(2, Math.ceil(wideCount / 2));
|
|
235
|
-
}
|
|
236
|
-
|
|
237
236
|
const NATURAL = new Intl.Collator('en', { numeric: true, sensitivity: 'base' });
|
|
238
237
|
|
|
239
238
|
/** Rendered frames in their real order: `frame2` before `frame10`. */
|
|
@@ -238,6 +238,41 @@ export function sceneHeightForScreens(screens: number): string {
|
|
|
238
238
|
return `${roundTo((held + 1) * 100, 1)}vh`;
|
|
239
239
|
}
|
|
240
240
|
|
|
241
|
+
/**
|
|
242
|
+
* Pictures per screen of scrolling at which a played film stays smooth as a glide slows to a stop. Measured on Doron's
|
|
243
|
+
* iPhone (2026-11-05): Studio Alma's film at about 11 a screen stepped, at about 55 it did not.
|
|
244
|
+
*/
|
|
245
|
+
export const SCENE_FILM_SMOOTH = 40;
|
|
246
|
+
|
|
247
|
+
export interface SceneFilmDensity {
|
|
248
|
+
/** Pictures per screen of scrolling over most of the play: half its scroll holds at least this many. */
|
|
249
|
+
perScreen: number;
|
|
250
|
+
/** The screens of scrolling the film plays over; where it holds still is not counted. */
|
|
251
|
+
screens: number;
|
|
252
|
+
smooth: boolean;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* How densely a film of `count` pictures plays on a Scene of `screens`, by its Play track; null when nothing plays. A
|
|
257
|
+
* film's smoothness is its density, never the drawing: spread thin, a slowing glide holds each picture for many refreshes.
|
|
258
|
+
*/
|
|
259
|
+
export function sceneFilmDensity(tracks: ReadonlyArray<SceneTrack> | null | undefined, screens: number | null, count: number): SceneFilmDensity | null {
|
|
260
|
+
const keys = normalizeTracks(tracks).find(track => track.prop === SceneProp.Play)?.keys ?? [];
|
|
261
|
+
if (count < 2 || !screens || screens <= 0) return null;
|
|
262
|
+
const stretches: { perScreen: number; screens: number }[] = [];
|
|
263
|
+
for (let i = 1; i < keys.length; i++) {
|
|
264
|
+
const scrolled = (keys[i][0] - keys[i - 1][0]) * screens;
|
|
265
|
+
const played = Math.abs(Number(keys[i][1]) - Number(keys[i - 1][1]));
|
|
266
|
+
if (scrolled > 0 && played > 0) stretches.push({ perScreen: ((played / 100) * (count - 1)) / scrolled, screens: scrolled });
|
|
267
|
+
}
|
|
268
|
+
if (!stretches.length) return null;
|
|
269
|
+
stretches.sort((a, b) => a.perScreen - b.perScreen);
|
|
270
|
+
const total = stretches.reduce((sum, stretch) => sum + stretch.screens, 0);
|
|
271
|
+
let covered = 0;
|
|
272
|
+
const typical = stretches.find(stretch => (covered += stretch.screens) >= total / 2)!;
|
|
273
|
+
return { perScreen: Math.round(typical.perScreen), screens: roundTo(total, 1), smooth: typical.perScreen >= SCENE_FILM_SMOOTH };
|
|
274
|
+
}
|
|
275
|
+
|
|
241
276
|
/** Motion v2 §3d's limits for scroll-linked work on one page. */
|
|
242
277
|
export const SCENE_BUDGET = { heldSections: 1, movingLayers: 8 } as const;
|
|
243
278
|
|