@hyperframes/core 0.8.206 → 0.8.208

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.
@@ -312,6 +312,7 @@ export function wrapScopedCompositionScript(source, compositionId, errorLabel =
312
312
  const authoredRootIdLiteral = jsonScriptLiteral(authoredRootId?.trim() || null);
313
313
  const scopeSelectorLiteral = jsonScriptLiteral(scopeSelectorOverride ?? null);
314
314
  const rootSelectorPatternLiteral = jsonScriptLiteral(String.raw `\[\s*data-composition-id\s*=\s*(?:"${escapedCompositionId}"|'${escapedCompositionId}')\s*\]`);
315
+ const timelineRootSelectorPatternLiteral = jsonScriptLiteral(String.raw `\[\s*data-composition-id\s*=\s*(?:"${escapeRegExp(timelineCompositionId)}"|'${escapeRegExp(timelineCompositionId)}')\s*\]`);
315
316
  const timingSelectorPatternLiteral = jsonScriptLiteral(String.raw `\s*\[\s*data-(?:start|duration)\s*=\s*(?:"[^"]*"|'[^']*')\s*\]`);
316
317
  const aliasInstallerOutsideAuthoredStrictness = `(function(){ ${getSvgSelectorAliasesScript()} })();`;
317
318
  return `(function(){
@@ -330,6 +331,7 @@ export function wrapScopedCompositionScript(source, compositionId, errorLabel =
330
331
  : "");
331
332
  var __hfRoot = null;
332
333
  var __hfRootSelectorPattern = ${rootSelectorPatternLiteral};
334
+ var __hfTimelineRootSelectorPattern = ${timelineRootSelectorPatternLiteral};
333
335
  var __hfTimingSelectorPattern = ${timingSelectorPatternLiteral};
334
336
  var __hfAuthoredRootSelector = __hfAuthoredRootId
335
337
  ? "[" + __hfAuthoredRootAttr + '="' + __hfEscapeAttr(__hfAuthoredRootId) + '"]'
@@ -341,7 +343,11 @@ export function wrapScopedCompositionScript(source, compositionId, errorLabel =
341
343
  if (!__hfCompId || typeof selector !== "string") return selector;
342
344
  var normalized = selector
343
345
  .replace(new RegExp(__hfRootSelectorPattern + '(?:' + __hfTimingSelectorPattern + ')+', 'g'), __hfRootSelector)
344
- .replace(new RegExp('(?:' + __hfTimingSelectorPattern + ')+' + __hfRootSelectorPattern, 'g'), __hfRootSelector);
346
+ .replace(new RegExp('(?:' + __hfTimingSelectorPattern + ')+' + __hfRootSelectorPattern, 'g'), __hfRootSelector)
347
+ .replace(new RegExp(__hfRootSelectorPattern, 'g'), __hfRootSelector);
348
+ if (__hfTimelineCompId !== __hfCompId) {
349
+ normalized = normalized.replace(new RegExp(__hfTimelineRootSelectorPattern, 'g'), __hfRootSelector);
350
+ }
345
351
  return window.__hfSvgSelectorAliases.rewrite(normalized, __hfAuthoredRootEntries);
346
352
  };
347
353
  var __hfFindRoot = function() {
@@ -62,7 +62,7 @@ export declare function parseAttributeSelector(predicate: string): {
62
62
  name: string;
63
63
  rawName: string;
64
64
  namespace: AttributeNamespace;
65
- operator: "=" | "~=" | "|=" | "^=" | "$=" | "*=";
65
+ operator: "=" | "*=" | "|=" | "^=" | "~=" | "$=";
66
66
  value: string;
67
67
  flag: string | undefined;
68
68
  } | null;
@@ -1,70 +1,6 @@
1
1
  export type ExecutionMode = "planning" | "design" | "execution" | null;
2
- /**
3
- * Frame rate as an exact rational. Carrying `{num, den}` end-to-end (rather
4
- * than collapsing to `29.97`) lets us pass NTSC / drop-frame rates straight
5
- * through to FFmpeg via `-r 30000/1001` without any decimal round-trip.
6
- *
7
- * Integer fps is represented with `den: 1` (e.g. `{ num: 30, den: 1 }`).
8
- *
9
- * Use {@link fpsToNumber} when arithmetic forces a decimal (e.g. `setTimeout`
10
- * intervals) and {@link fpsToFfmpegArg} when emitting FFmpeg `-r` /
11
- * `-framerate` strings.
12
- */
13
- export interface Fps {
14
- num: number;
15
- den: number;
16
- }
17
- export type FpsInput = number | Fps;
18
- export declare function toFps(input: FpsInput): Fps;
19
- /**
20
- * Decimal value of an {@link Fps} rational. Used at sites that need a
21
- * `number` for arithmetic (frame-index → time, frame intervals, telemetry
22
- * payloads) where the small precision loss of the decimal is acceptable.
23
- */
24
- export declare function fpsToNumber(fps: Fps): number;
25
- /**
26
- * FFmpeg-style fps argument. Returns `"30"` for integer fps and `"30000/1001"`
27
- * for rationals — both forms are accepted verbatim by FFmpeg's `-r` and
28
- * `-framerate` flags. We keep integer fps as a bare integer so existing
29
- * snapshot tests / log output don't churn for the common case.
30
- */
31
- export declare function fpsToFfmpegArg(fps: Fps): string;
32
- /**
33
- * Discriminated parse result for {@link parseFps}. Lets the CLI / route
34
- * validation own its own error UX without losing the structured failure
35
- * reason.
36
- */
37
- export type FpsParseResult = {
38
- ok: true;
39
- value: Fps;
40
- } | {
41
- ok: false;
42
- reason: "empty" | "not-a-number" | "non-positive" | "out-of-range" | "invalid-fraction" | "ambiguous-decimal";
43
- };
44
- /**
45
- * Parse a user-supplied fps spec into an {@link Fps} rational.
46
- *
47
- * Accepted forms:
48
- * - integer string `"30"` → `{ num: 30, den: 1 }`
49
- * - integer number `30` → `{ num: 30, den: 1 }`
50
- * - rational string `"30000/1001"` → `{ num: 30000, den: 1001 }` (exact NTSC)
51
- *
52
- * Rejected:
53
- * - empty / non-numeric input
54
- * - decimals like `"29.97"` — callers must spell rationals with `/` so the
55
- * exact denominator is unambiguous (FFmpeg treats `29.97` as a slightly
56
- * different framerate than `30000/1001`).
57
- * - division by zero, negative or zero numerator
58
- * - decimal value outside `[1, 240]` — defensive bounds for "human" fps
59
- * ranges (24, 25, 30, 50, 60, 120, 240, plus the NTSC trio).
60
- */
61
- export declare function parseFps(input: string | number): FpsParseResult;
62
- /**
63
- * Convenience wrapper around {@link parseFps} for callsites that want the
64
- * default-30-fps fallback when input is `undefined`. Does NOT swallow parse
65
- * errors — those still surface via the discriminated result.
66
- */
67
- export declare function parseFpsWithDefault(input: string | number | undefined): FpsParseResult;
2
+ export type { Fps, FpsInput, FpsParseResult } from "./fps.js";
3
+ export { toFps, fpsToNumber, fpsToFfmpegArg, parseFps, parseFpsWithDefault } from "./fps.js";
68
4
  /** Video orientation / aspect ratio. */
69
5
  export type Orientation = "16:9" | "9:16";
70
6
  export type { Asset, TimelineElementType, MediaElementType, TimelineElementBase, TimelineMediaElement, WaveformData, TimelineTextElement, TimelineCompositionElement, CompositionVariableType, CompositionVariableBase, StringVariable, NumberVariable, ColorVariable, BooleanVariable, EnumVariable, CompositionVariable, CompositionSpec, TimelineElement, MediaFile, CanvasResolution, CompositionAPI, PlayerAPI, AddElementData, ValidationResult, CompositionAsset, Keyframe, KeyframeProperties, ElementKeyframes, StageZoom, StageZoomKeyframe, } from "@hyperframes/parsers";
@@ -1,104 +1,3 @@
1
1
  // ── Shared cross-package types ──────────────────────────────────────────────
2
- export function toFps(input) {
3
- if (typeof input === "number") {
4
- return { num: input, den: 1 };
5
- }
6
- return input;
7
- }
8
- /**
9
- * Decimal value of an {@link Fps} rational. Used at sites that need a
10
- * `number` for arithmetic (frame-index → time, frame intervals, telemetry
11
- * payloads) where the small precision loss of the decimal is acceptable.
12
- */
13
- export function fpsToNumber(fps) {
14
- return fps.num / fps.den;
15
- }
16
- /**
17
- * FFmpeg-style fps argument. Returns `"30"` for integer fps and `"30000/1001"`
18
- * for rationals — both forms are accepted verbatim by FFmpeg's `-r` and
19
- * `-framerate` flags. We keep integer fps as a bare integer so existing
20
- * snapshot tests / log output don't churn for the common case.
21
- */
22
- export function fpsToFfmpegArg(fps) {
23
- return fps.den === 1 ? String(fps.num) : `${fps.num}/${fps.den}`;
24
- }
25
- /**
26
- * Parse a user-supplied fps spec into an {@link Fps} rational.
27
- *
28
- * Accepted forms:
29
- * - integer string `"30"` → `{ num: 30, den: 1 }`
30
- * - integer number `30` → `{ num: 30, den: 1 }`
31
- * - rational string `"30000/1001"` → `{ num: 30000, den: 1001 }` (exact NTSC)
32
- *
33
- * Rejected:
34
- * - empty / non-numeric input
35
- * - decimals like `"29.97"` — callers must spell rationals with `/` so the
36
- * exact denominator is unambiguous (FFmpeg treats `29.97` as a slightly
37
- * different framerate than `30000/1001`).
38
- * - division by zero, negative or zero numerator
39
- * - decimal value outside `[1, 240]` — defensive bounds for "human" fps
40
- * ranges (24, 25, 30, 50, 60, 120, 240, plus the NTSC trio).
41
- */
42
- export function parseFps(input) {
43
- if (typeof input === "number") {
44
- if (!Number.isFinite(input))
45
- return { ok: false, reason: "not-a-number" };
46
- if (!Number.isInteger(input))
47
- return { ok: false, reason: "ambiguous-decimal" };
48
- if (input <= 0)
49
- return { ok: false, reason: "non-positive" };
50
- if (input > 240)
51
- return { ok: false, reason: "out-of-range" };
52
- return { ok: true, value: { num: input, den: 1 } };
53
- }
54
- const raw = input.trim();
55
- if (raw === "")
56
- return { ok: false, reason: "empty" };
57
- if (raw.includes("/")) {
58
- const parts = raw.split("/");
59
- if (parts.length !== 2)
60
- return { ok: false, reason: "invalid-fraction" };
61
- const num = Number(parts[0]);
62
- const den = Number(parts[1]);
63
- if (!Number.isFinite(num) || !Number.isFinite(den)) {
64
- return { ok: false, reason: "not-a-number" };
65
- }
66
- if (!Number.isInteger(num) || !Number.isInteger(den)) {
67
- return { ok: false, reason: "invalid-fraction" };
68
- }
69
- if (den <= 0)
70
- return { ok: false, reason: "invalid-fraction" };
71
- if (num <= 0)
72
- return { ok: false, reason: "non-positive" };
73
- const decimal = num / den;
74
- if (decimal < 1 || decimal > 240)
75
- return { ok: false, reason: "out-of-range" };
76
- return { ok: true, value: { num, den } };
77
- }
78
- // Integer-only path — reject `"29.97"` so users are explicit about the
79
- // exact rational they want.
80
- if (!/^-?\d+$/.test(raw)) {
81
- // Allow caller to differentiate "29.97" from "abc" if they want; both
82
- // are user errors but the message can be friendlier for decimals.
83
- if (/^-?\d*\.\d+$/.test(raw))
84
- return { ok: false, reason: "ambiguous-decimal" };
85
- return { ok: false, reason: "not-a-number" };
86
- }
87
- const n = Number(raw);
88
- if (n <= 0)
89
- return { ok: false, reason: "non-positive" };
90
- if (n > 240)
91
- return { ok: false, reason: "out-of-range" };
92
- return { ok: true, value: { num: n, den: 1 } };
93
- }
94
- /**
95
- * Convenience wrapper around {@link parseFps} for callsites that want the
96
- * default-30-fps fallback when input is `undefined`. Does NOT swallow parse
97
- * errors — those still surface via the discriminated result.
98
- */
99
- export function parseFpsWithDefault(input) {
100
- if (input === undefined || input === "")
101
- return { ok: true, value: { num: 30, den: 1 } };
102
- return parseFps(input);
103
- }
2
+ export { toFps, fpsToNumber, fpsToFfmpegArg, parseFps, parseFpsWithDefault } from "./fps.js";
104
3
  export { CANVAS_DIMENSIONS, VALID_CANVAS_RESOLUTIONS, normalizeResolutionFlag, isAspectAgnosticResolutionAlias, resolveResolutionFlagPair, checkOutputResolutionCompatibility, outputResolutionForSize, suggestMatchingPreset, COMPOSITION_VARIABLE_TYPES, TIMELINE_COLORS, DEFAULT_DURATIONS, getDefaultStageZoom, isTextElement, isMediaElement, isCompositionElement, } from "@hyperframes/parsers";
package/dist/fps.d.ts ADDED
@@ -0,0 +1,17 @@
1
+ export interface Fps {
2
+ num: number;
3
+ den: number;
4
+ }
5
+ export type FpsInput = number | Fps;
6
+ export declare function toFps(input: FpsInput): Fps;
7
+ export declare function fpsToNumber(fps: Fps): number;
8
+ export declare function fpsToFfmpegArg(fps: Fps): string;
9
+ export type FpsParseResult = {
10
+ ok: true;
11
+ value: Fps;
12
+ } | {
13
+ ok: false;
14
+ reason: "empty" | "not-a-number" | "non-positive" | "out-of-range" | "invalid-fraction" | "ambiguous-decimal";
15
+ };
16
+ export declare function parseFps(input: string | number): FpsParseResult;
17
+ export declare function parseFpsWithDefault(input: string | number | undefined): FpsParseResult;
package/dist/fps.js ADDED
@@ -0,0 +1,58 @@
1
+ export function toFps(input) {
2
+ if (typeof input === "number") {
3
+ return { num: input, den: 1 };
4
+ }
5
+ return input;
6
+ }
7
+ export function fpsToNumber(fps) {
8
+ return fps.num / fps.den;
9
+ }
10
+ export function fpsToFfmpegArg(fps) {
11
+ return fps.den === 1 ? String(fps.num) : `${fps.num}/${fps.den}`;
12
+ }
13
+ const fail = (reason) => ({ ok: false, reason });
14
+ function rangedFps(num, den) {
15
+ if (num <= 0)
16
+ return fail("non-positive");
17
+ const decimal = num / den;
18
+ if (decimal < 1 || decimal > 240)
19
+ return fail("out-of-range");
20
+ return { ok: true, value: { num, den } };
21
+ }
22
+ function numericFps(input) {
23
+ if (!Number.isFinite(input))
24
+ return fail("not-a-number");
25
+ if (!Number.isInteger(input))
26
+ return fail("ambiguous-decimal");
27
+ return rangedFps(input, 1);
28
+ }
29
+ function fractionFps(raw) {
30
+ const parts = raw.split("/");
31
+ if (parts.length !== 2)
32
+ return fail("invalid-fraction");
33
+ const num = Number(parts[0]);
34
+ const den = Number(parts[1]);
35
+ if (!Number.isFinite(num) || !Number.isFinite(den))
36
+ return fail("not-a-number");
37
+ if (!Number.isInteger(num) || !Number.isInteger(den) || den <= 0)
38
+ return fail("invalid-fraction");
39
+ return rangedFps(num, den);
40
+ }
41
+ // Decimals like "29.97" are rejected: FFmpeg reads them as a different rate than 30000/1001.
42
+ export function parseFps(input) {
43
+ if (typeof input === "number")
44
+ return numericFps(input);
45
+ const raw = input.trim();
46
+ if (raw === "")
47
+ return fail("empty");
48
+ if (raw.includes("/"))
49
+ return fractionFps(raw);
50
+ if (/^-?\d+$/.test(raw))
51
+ return rangedFps(Number(raw), 1);
52
+ return fail(/^-?\d*\.\d+$/.test(raw) ? "ambiguous-decimal" : "not-a-number");
53
+ }
54
+ export function parseFpsWithDefault(input) {
55
+ if (input === undefined || input === "")
56
+ return { ok: true, value: { num: 30, den: 1 } };
57
+ return parseFps(input);
58
+ }