Fixes issues raised in the Deepwork re-review of #2120-#2190 that weren't
covered by #2225's earlier fix pass:
- useColorGradingController: reset grading/compare/mediaMetadata state (and
cancel pending persist/status timers) when selection changes to a
different element — this hook is called unconditionally on every render
(unlike legacy ColorGradingSection, remounted via a selectionIdentityKey
React key), so switching selection reused the previous element's state.
- useColorGradingController: stop permanently caching a non-OK
/media/metadata response as null — a transient server error poisoned the
HDR banner for that asset for the whole page lifetime.
- FlatSelectRow: preserve a valid authored value outside the preset list
(e.g. mix-blend-mode: difference, an arbitrary object-position) instead of
silently misrepresenting it as the first preset — touching the control
would overwrite real persisted state.
- FlatSlider: the throttled trailing commit now reads onCommit through a
ref updated every render instead of closing over it at schedule time — a
caller whose onCommit spreads other current state (Grade's per-detail
commits) could otherwise have a delayed commit revert whatever the user
changed on a different control in the same 40ms window.
- FlatSlider: flush a still-queued trailing commit on unmount instead of
dropping it, and disable the reset button when the slider itself is
disabled.
- FlatSlider: add touch-action: none to the track so touch drags don't
compete with page scroll.
- FlatColorGradingAccessory: clean up the compare-hold's window listeners
on unmount, not only on release — switching selection mid-hold used to
leak them.
- Align (flat Text): re-clicking the option already visually active for a
logical start/end value no longer rewrites it to the physical left/right,
preserving RTL semantics.
- FlatSegmentedRow: give every option an accessible name and aria-pressed
state — two visually-identical glyph buttons (upright/italic "A") had no
way to be told apart by assistive tech.
- PropertyPanelFlat: the panel body falls back to its own scroll when the
collapsed group headers alone exceed the available height, so groups
can't become permanently unreachable in a short pane.
New regression tests for all of the above; full studio suite at the known
pre-existing baseline (55 failures unrelated to this stack).
FlatTextSection's multi-field branch (textFields.length > 1) now renders
FlatTextLayerList (Task 5) + the existing single-field FlatTextFieldEditor
for the active field, tracked via new local activeFieldKey state that
resyncs (useEffect) when the active field disappears from props. This
retires the legacy TextSection delegation entirely for that case; the
TextSection import is removed from propertyPanelFlatTextSection.tsx since
nothing else in the file referenced it.
Also updates propertyPanelSections.test.tsx and PropertyPanel.test.tsx,
which exercised/documented the old multi-field-falls-back-to-legacy-
TextSection behavior in comments and test titles — reworded to describe
the new flat path (assertions were already compatible and still pass).
Flag for reviewer: hideOwnHeading on the legacy TextSection component
(propertyPanelSections.tsx) was added in an earlier plan specifically for
this now-removed call site. It has no remaining consumer after this task
lands (PropertyPanel.tsx's legacy caller doesn't pass it). Left in place
per brief instruction — not deleting unilaterally, since that's a scope
decision for whoever reviews this task.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Review proved the existing test didn't catch a broken stopPropagation
by temporarily removing it and confirming the suite still passed.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>