mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-03 04:38:33 +00:00
Fixes three of the adversarial findings from the third #2416 tip re-review: - Grade rollback was identity-scoped but not attempt-scoped: two edits on the SAME element (e.g. drag Exposure, then Contrast, before Exposure's persist settles) could have the earlier edit's late completion stamp confirmedGradingRef with its now-superseded value, or revert `grading` out from under the newer optimistic edit. Added a monotonic per-commit version via the existing bumpDomEditCommitVersion primitive (the same one the DOM-attribute commit runner uses for the identical race) — persistColorGradingValue now checks both identity AND "is this still the latest attempt for this element" before applying any effect. - The render-phase identity-reset block consumed shared mutable state (clearing the pending-persist timer, reading and nulling pendingPersistValueRef) directly during render. Adjusting STATE during render this way is React's documented pattern and safe to repeat, but consuming a ref this way is not: if React discarded/interrupted that specific render before it committed, the timer would already be cancelled and the pending value already nulled, with no corresponding effect ever running to compensate, silently losing the edit. Replaced with the idiomatic pattern for "clean up a per-identity resource when it changes" — a useEffect keyed on identityKey whose CLEANUP performs the cancellation/flush. A cleanup only ever runs for the effect instance that actually committed, closing the gap entirely. The render-phase block now only performs pure, idempotent state resets. - FlatSelectRow's Preset row passes label="" (the visible "Preset" text is a sibling span, to avoid rendering it twice) which left the underlying <select> with no accessible name at all. Added a dedicated `ariaLabel` prop, distinct from the visible `label`, so a caller can supply a name without a duplicate visible label. Also hardened FlatSlider's lostpointercapture handling: it now resyncs the draft directly from a latestValueRef immediately, instead of only clearing the dragging flag and waiting for the separate [value]-keyed effect to notice — closing a narrow ordering gap where a value change arriving while still dragging, followed by capture loss with no further render, could otherwise leave the knob stuck. propertyPanelFlatPrimitives.tsx crossed the 600-line file-size gate after these changes; extracted FlatToggle (and its tests) into their own files, matching the FlatMaskInsetRows precedent from an earlier commit in this stack. New/updated regression tests: same-element version race, Preset select's aria-label. Full studio suite still at the known pre-existing 55-failure baseline, zero regressions.