Skip to content

Commit ea4d920

Browse files
committed
refactor(studio): split oversized files and raise line limit to 600
Split PlayerControls.tsx into focused sub-components (SeekBar, WorkAreaOverlay, MuteButton, LoopButton, FullscreenButton, ShortcutsPanel, SpeedMenu) and extracted seek bar drag/progress tracking into useSeekBarDrag hook. Split manualEditsDom.ts patch-builder functions into manualEditsDomPatches.ts with data-driven helpers to reduce duplication and complexity. Extracted per-type reapply helpers from reapplyPositionEditsAfterSeek and factored out identity-matrix check from stripGsapTranslateFromTransform. Raised file-size limit from 500 to 600 lines, removed .filesize-allowlist.
1 parent 06e4db8 commit ea4d920

10 files changed

Lines changed: 1166 additions & 1103 deletions

File tree

.filesize-allowlist

Lines changed: 0 additions & 13 deletions
This file was deleted.

.github/workflows/ci.yml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,7 @@ jobs:
469469
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
470470
with:
471471
fetch-depth: 0
472-
- name: Check file sizes (max 500 lines)
472+
- name: Check file sizes (max 600 lines)
473473
# Scoped to files THIS PR changed under packages/studio. Walking the
474474
# whole tree blamed every unrelated PR for pre-existing offenders.
475475
# Falls back to a full scan on push events (no base ref available)
@@ -494,10 +494,9 @@ jobs:
494494
for f in "${files[@]}"; do
495495
[ -z "$f" ] && continue
496496
[ -f "$f" ] || continue # skip files deleted in this PR
497-
if grep -qxF "$f" .filesize-allowlist 2>/dev/null; then continue; fi
498497
lines=$(wc -l < "$f")
499-
if [ "$lines" -gt 500 ]; then
500-
echo "::error file=$f::$f has $lines lines (max 500)"
498+
if [ "$lines" -gt 600 ]; then
499+
echo "::error file=$f::$f has $lines lines (max 600)"
501500
EXIT=1
502501
fi
503502
done

lefthook.yml

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,16 @@ pre-commit:
2121
glob: "packages/**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}"
2222
run: bunx fallow audit --base origin/main --fail-on-issues
2323
filesize:
24-
# Scoped to packages/studio — the 500 LOC limit is a studio architecture
24+
# Scoped to packages/studio — the 600 LOC limit is a studio architecture
2525
# standard enforced as part of the App.tsx decomposition work. Player and
2626
# other packages enforce size discipline via code review and convention.
27-
# Files temporarily over the limit are listed in .filesize-allowlist.
2827
glob: "packages/studio/**/*.{ts,tsx}"
2928
exclude: "(\\.test\\.(ts|tsx)$|\\.generated\\.)"
3029
run: |
3130
for f in {staged_files}; do
32-
if grep -qxF "$f" .filesize-allowlist 2>/dev/null; then continue; fi
3331
lines=$(wc -l < "$f")
34-
if [ "$lines" -gt 500 ]; then
35-
echo "ERROR: $f has $lines lines (max 500) — add to .filesize-allowlist if temporarily needed"
32+
if [ "$lines" -gt 600 ]; then
33+
echo "ERROR: $f has $lines lines (max 600)"
3634
exit 1
3735
fi
3836
done

packages/studio/src/components/editor/manualEditsDom.ts

Lines changed: 38 additions & 359 deletions
Large diffs are not rendered by default.
Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
1+
import type { PatchOperation } from "../../utils/sourcePatcher";
2+
import {
3+
STUDIO_OFFSET_X_PROP,
4+
STUDIO_OFFSET_Y_PROP,
5+
STUDIO_WIDTH_PROP,
6+
STUDIO_HEIGHT_PROP,
7+
STUDIO_ROTATION_PROP,
8+
STUDIO_PATH_OFFSET_ATTR,
9+
STUDIO_BOX_SIZE_ATTR,
10+
STUDIO_ROTATION_ATTR,
11+
STUDIO_ROTATION_DRAFT_ATTR,
12+
STUDIO_ORIGINAL_TRANSLATE_ATTR,
13+
STUDIO_ORIGINAL_INLINE_TRANSLATE_ATTR,
14+
STUDIO_ORIGINAL_WIDTH_ATTR,
15+
STUDIO_ORIGINAL_HEIGHT_ATTR,
16+
STUDIO_ORIGINAL_MIN_WIDTH_ATTR,
17+
STUDIO_ORIGINAL_MIN_HEIGHT_ATTR,
18+
STUDIO_ORIGINAL_MAX_WIDTH_ATTR,
19+
STUDIO_ORIGINAL_MAX_HEIGHT_ATTR,
20+
STUDIO_ORIGINAL_FLEX_BASIS_ATTR,
21+
STUDIO_ORIGINAL_FLEX_GROW_ATTR,
22+
STUDIO_ORIGINAL_FLEX_SHRINK_ATTR,
23+
STUDIO_ORIGINAL_BOX_SIZING_ATTR,
24+
STUDIO_ORIGINAL_SCALE_ATTR,
25+
STUDIO_ORIGINAL_TRANSFORM_ORIGIN_ATTR,
26+
STUDIO_ORIGINAL_DISPLAY_ATTR,
27+
STUDIO_ORIGINAL_ROTATE_ATTR,
28+
STUDIO_ORIGINAL_INLINE_ROTATE_ATTR,
29+
STUDIO_ORIGINAL_ROTATION_TRANSFORM_ORIGIN_ATTR,
30+
STUDIO_ORIGINAL_TRANSFORM_DISPLAY_ATTR,
31+
} from "./manualEditsTypes";
32+
import {
33+
STUDIO_MOTION_ATTR,
34+
STUDIO_MOTION_ORIGINAL_TRANSFORM_ATTR,
35+
STUDIO_MOTION_ORIGINAL_OPACITY_ATTR,
36+
STUDIO_MOTION_ORIGINAL_VISIBILITY_ATTR,
37+
} from "./studioMotionTypes";
38+
39+
/* ── Shared helpers ──────────────────────────────────────────────── */
40+
41+
function collectInlineStyleOps(
42+
element: HTMLElement,
43+
properties: readonly string[],
44+
ops: PatchOperation[],
45+
): void {
46+
for (const prop of properties) {
47+
const val = element.style.getPropertyValue(prop);
48+
if (val) ops.push({ type: "inline-style", property: prop, value: val });
49+
}
50+
}
51+
52+
function collectAttributeOps(
53+
element: HTMLElement,
54+
attrNames: readonly string[],
55+
ops: PatchOperation[],
56+
): void {
57+
for (const attr of attrNames) {
58+
const val = element.getAttribute(attr);
59+
if (val !== null) ops.push({ type: "attribute", property: attr, value: val });
60+
}
61+
}
62+
63+
function appendTransformDisplayOps(element: HTMLElement, ops: PatchOperation[]): void {
64+
const val = element.getAttribute(STUDIO_ORIGINAL_TRANSFORM_DISPLAY_ATTR);
65+
if (val !== null) {
66+
ops.push({ type: "inline-style", property: "display", value: val || null });
67+
ops.push({ type: "attribute", property: STUDIO_ORIGINAL_TRANSFORM_DISPLAY_ATTR, value: null });
68+
}
69+
}
70+
71+
/* ── Path offset patches ─────────────────────────────────────────── */
72+
73+
export function buildPathOffsetPatches(element: HTMLElement): PatchOperation[] {
74+
const ops: PatchOperation[] = [];
75+
collectInlineStyleOps(element, [STUDIO_OFFSET_X_PROP, STUDIO_OFFSET_Y_PROP, "translate"], ops);
76+
ops.push({ type: "attribute", property: STUDIO_PATH_OFFSET_ATTR, value: "true" });
77+
collectAttributeOps(
78+
element,
79+
[STUDIO_ORIGINAL_TRANSLATE_ATTR, STUDIO_ORIGINAL_INLINE_TRANSLATE_ATTR],
80+
ops,
81+
);
82+
collectInlineStyleOps(element, ["display"], ops);
83+
collectAttributeOps(element, [STUDIO_ORIGINAL_TRANSFORM_DISPLAY_ATTR], ops);
84+
return ops;
85+
}
86+
87+
export function buildClearPathOffsetPatches(element: HTMLElement): PatchOperation[] {
88+
const originalInlineTranslate = element.getAttribute(STUDIO_ORIGINAL_INLINE_TRANSLATE_ATTR);
89+
const ops: PatchOperation[] = [
90+
{ type: "inline-style", property: STUDIO_OFFSET_X_PROP, value: null },
91+
{ type: "inline-style", property: STUDIO_OFFSET_Y_PROP, value: null },
92+
{ type: "inline-style", property: "translate", value: originalInlineTranslate || null },
93+
{ type: "attribute", property: STUDIO_PATH_OFFSET_ATTR, value: null },
94+
{ type: "attribute", property: STUDIO_ORIGINAL_TRANSLATE_ATTR, value: null },
95+
{ type: "attribute", property: STUDIO_ORIGINAL_INLINE_TRANSLATE_ATTR, value: null },
96+
];
97+
appendTransformDisplayOps(element, ops);
98+
return ops;
99+
}
100+
101+
/* ── Box size patches ────────────────────────────────────────────── */
102+
103+
const BOX_SIZE_STYLE_PROPS = [
104+
"width",
105+
"height",
106+
"min-width",
107+
"min-height",
108+
"max-width",
109+
"max-height",
110+
"flex-basis",
111+
"flex-grow",
112+
"flex-shrink",
113+
"box-sizing",
114+
"scale",
115+
"transform-origin",
116+
"display",
117+
] as const;
118+
119+
const BOX_SIZE_ORIG_ATTRS: ReadonlyArray<[string, string]> = [
120+
[STUDIO_ORIGINAL_WIDTH_ATTR, "width"],
121+
[STUDIO_ORIGINAL_HEIGHT_ATTR, "height"],
122+
[STUDIO_ORIGINAL_MIN_WIDTH_ATTR, "min-width"],
123+
[STUDIO_ORIGINAL_MIN_HEIGHT_ATTR, "min-height"],
124+
[STUDIO_ORIGINAL_MAX_WIDTH_ATTR, "max-width"],
125+
[STUDIO_ORIGINAL_MAX_HEIGHT_ATTR, "max-height"],
126+
[STUDIO_ORIGINAL_FLEX_BASIS_ATTR, "flex-basis"],
127+
[STUDIO_ORIGINAL_FLEX_GROW_ATTR, "flex-grow"],
128+
[STUDIO_ORIGINAL_FLEX_SHRINK_ATTR, "flex-shrink"],
129+
[STUDIO_ORIGINAL_BOX_SIZING_ATTR, "box-sizing"],
130+
[STUDIO_ORIGINAL_SCALE_ATTR, "scale"],
131+
[STUDIO_ORIGINAL_TRANSFORM_ORIGIN_ATTR, "transform-origin"],
132+
[STUDIO_ORIGINAL_DISPLAY_ATTR, "display"],
133+
[STUDIO_ORIGINAL_TRANSFORM_DISPLAY_ATTR, ""],
134+
];
135+
136+
export function buildBoxSizePatches(element: HTMLElement): PatchOperation[] {
137+
const ops: PatchOperation[] = [];
138+
collectInlineStyleOps(element, [STUDIO_WIDTH_PROP, STUDIO_HEIGHT_PROP], ops);
139+
collectInlineStyleOps(element, BOX_SIZE_STYLE_PROPS, ops);
140+
ops.push({ type: "attribute", property: STUDIO_BOX_SIZE_ATTR, value: "true" });
141+
collectAttributeOps(
142+
element,
143+
BOX_SIZE_ORIG_ATTRS.map(([attr]) => attr),
144+
ops,
145+
);
146+
return ops;
147+
}
148+
149+
export function buildClearBoxSizePatches(element: HTMLElement): PatchOperation[] {
150+
const ops: PatchOperation[] = [
151+
{ type: "inline-style", property: STUDIO_WIDTH_PROP, value: null },
152+
{ type: "inline-style", property: STUDIO_HEIGHT_PROP, value: null },
153+
{ type: "attribute", property: STUDIO_BOX_SIZE_ATTR, value: null },
154+
];
155+
for (const [attrName, styleProp] of BOX_SIZE_ORIG_ATTRS) {
156+
const origVal = element.getAttribute(attrName);
157+
if (origVal !== null && styleProp) {
158+
ops.push({ type: "inline-style", property: styleProp, value: origVal || null });
159+
}
160+
ops.push({ type: "attribute", property: attrName, value: null });
161+
}
162+
return ops;
163+
}
164+
165+
/* ── Rotation patches ────────────────────────────────────────────── */
166+
167+
const ROTATION_STYLE_PROPS = [
168+
STUDIO_ROTATION_PROP,
169+
"rotate",
170+
"transform-origin",
171+
"display",
172+
] as const;
173+
174+
const ROTATION_ORIG_ATTRS = [
175+
STUDIO_ORIGINAL_ROTATE_ATTR,
176+
STUDIO_ORIGINAL_INLINE_ROTATE_ATTR,
177+
STUDIO_ORIGINAL_ROTATION_TRANSFORM_ORIGIN_ATTR,
178+
STUDIO_ORIGINAL_TRANSFORM_DISPLAY_ATTR,
179+
] as const;
180+
181+
export function buildRotationPatches(element: HTMLElement): PatchOperation[] {
182+
const ops: PatchOperation[] = [];
183+
collectInlineStyleOps(element, ROTATION_STYLE_PROPS, ops);
184+
ops.push({ type: "attribute", property: STUDIO_ROTATION_ATTR, value: "true" });
185+
collectAttributeOps(element, ROTATION_ORIG_ATTRS, ops);
186+
return ops;
187+
}
188+
189+
export function buildClearRotationPatches(element: HTMLElement): PatchOperation[] {
190+
const origInlineRotate = element.getAttribute(STUDIO_ORIGINAL_INLINE_ROTATE_ATTR);
191+
const origRotationTransformOrigin = element.getAttribute(
192+
STUDIO_ORIGINAL_ROTATION_TRANSFORM_ORIGIN_ATTR,
193+
);
194+
const ops: PatchOperation[] = [
195+
{ type: "inline-style", property: STUDIO_ROTATION_PROP, value: null },
196+
{ type: "inline-style", property: "rotate", value: origInlineRotate || null },
197+
{
198+
type: "inline-style",
199+
property: "transform-origin",
200+
value: origRotationTransformOrigin !== null ? origRotationTransformOrigin || null : null,
201+
},
202+
{ type: "attribute", property: STUDIO_ROTATION_ATTR, value: null },
203+
{ type: "attribute", property: STUDIO_ROTATION_DRAFT_ATTR, value: null },
204+
{ type: "attribute", property: STUDIO_ORIGINAL_ROTATE_ATTR, value: null },
205+
{ type: "attribute", property: STUDIO_ORIGINAL_INLINE_ROTATE_ATTR, value: null },
206+
{ type: "attribute", property: STUDIO_ORIGINAL_ROTATION_TRANSFORM_ORIGIN_ATTR, value: null },
207+
];
208+
appendTransformDisplayOps(element, ops);
209+
return ops;
210+
}
211+
212+
/* ── Motion patches ──────────────────────────────────────────────── */
213+
214+
const MOTION_ORIG_ATTRS = [
215+
STUDIO_MOTION_ORIGINAL_TRANSFORM_ATTR,
216+
STUDIO_MOTION_ORIGINAL_OPACITY_ATTR,
217+
STUDIO_MOTION_ORIGINAL_VISIBILITY_ATTR,
218+
] as const;
219+
220+
export function buildMotionPatches(element: HTMLElement): PatchOperation[] {
221+
const motionJson = element.getAttribute(STUDIO_MOTION_ATTR);
222+
if (!motionJson) return [];
223+
const ops: PatchOperation[] = [
224+
{ type: "attribute", property: STUDIO_MOTION_ATTR, value: motionJson },
225+
];
226+
collectAttributeOps(element, MOTION_ORIG_ATTRS, ops);
227+
return ops;
228+
}
229+
230+
export function buildClearMotionPatches(_element: HTMLElement): PatchOperation[] {
231+
return [
232+
{ type: "attribute", property: STUDIO_MOTION_ATTR, value: null },
233+
{ type: "attribute", property: STUDIO_MOTION_ORIGINAL_TRANSFORM_ATTR, value: null },
234+
{ type: "attribute", property: STUDIO_MOTION_ORIGINAL_OPACITY_ATTR, value: null },
235+
{ type: "attribute", property: STUDIO_MOTION_ORIGINAL_VISIBILITY_ATTR, value: null },
236+
];
237+
}

0 commit comments

Comments
 (0)