mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-03 04:38:33 +00:00
feat(studio): add flat Opacity slider, completing the Style group
This commit is contained in:
@@ -316,7 +316,8 @@ describe("FlatStyleSection — blur sliders", () => {
|
|||||||
expect(host.textContent).toContain("Backdrop");
|
expect(host.textContent).toContain("Backdrop");
|
||||||
expect(host.textContent).toContain("6px");
|
expect(host.textContent).toContain("6px");
|
||||||
const tracks = host.querySelectorAll('[data-flat-slider-track="true"]');
|
const tracks = host.querySelectorAll('[data-flat-slider-track="true"]');
|
||||||
const backdropTrack = tracks[tracks.length - 1];
|
// Track order is Layer blur, Backdrop, Opacity — Backdrop is the second track.
|
||||||
|
const backdropTrack = tracks[1];
|
||||||
Object.defineProperty(backdropTrack, "getBoundingClientRect", {
|
Object.defineProperty(backdropTrack, "getBoundingClientRect", {
|
||||||
value: () => ({ left: 0, width: 100, top: 0, height: 2, right: 100, bottom: 2 }),
|
value: () => ({ left: 0, width: 100, top: 0, height: 2, right: 100, bottom: 2 }),
|
||||||
});
|
});
|
||||||
@@ -330,7 +331,13 @@ describe("FlatStyleSection — blur sliders", () => {
|
|||||||
|
|
||||||
it("does not render a fill/knob highlight for a zero-value blur (default tier)", () => {
|
it("does not render a fill/knob highlight for a zero-value blur (default tier)", () => {
|
||||||
const { host, root } = renderSection({});
|
const { host, root } = renderSection({});
|
||||||
expect(host.querySelectorAll('[data-flat-slider-fill="true"]')).toHaveLength(0);
|
const tracks = host.querySelectorAll('[data-flat-slider-track="true"]');
|
||||||
|
// Only the first two tracks are the blur sliders (Layer blur, Backdrop); Opacity
|
||||||
|
// (the third track) always renders a fill by design, so it's excluded here.
|
||||||
|
const blurTracks = Array.from(tracks).slice(0, 2);
|
||||||
|
for (const track of blurTracks) {
|
||||||
|
expect(track.querySelectorAll('[data-flat-slider-fill="true"]')).toHaveLength(0);
|
||||||
|
}
|
||||||
act(() => root.unmount());
|
act(() => root.unmount());
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -466,3 +473,36 @@ describe("FlatStyleSection — Overflow and Mask", () => {
|
|||||||
act(() => root.unmount());
|
act(() => root.unmount());
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("FlatStyleSection — Opacity", () => {
|
||||||
|
it("renders the Opacity slider at 100% by default and commits a change through onSetStyle", () => {
|
||||||
|
const onSetStyle = vi.fn();
|
||||||
|
const host = document.createElement("div");
|
||||||
|
document.body.append(host);
|
||||||
|
const root = createRoot(host);
|
||||||
|
act(() => {
|
||||||
|
root.render(
|
||||||
|
<FlatStyleSection
|
||||||
|
projectId="proj-1"
|
||||||
|
element={makeElement()}
|
||||||
|
styles={{}}
|
||||||
|
assets={[]}
|
||||||
|
onSetStyle={onSetStyle}
|
||||||
|
gsapBorderRadius={null}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
expect(host.textContent).toContain("Opacity");
|
||||||
|
expect(host.textContent).toContain("100%");
|
||||||
|
const tracks = host.querySelectorAll('[data-flat-slider-track="true"]');
|
||||||
|
const opacityTrack = tracks[tracks.length - 1];
|
||||||
|
Object.defineProperty(opacityTrack, "getBoundingClientRect", {
|
||||||
|
value: () => ({ left: 0, width: 100, top: 0, height: 2, right: 100, bottom: 2 }),
|
||||||
|
});
|
||||||
|
act(() => {
|
||||||
|
opacityTrack.dispatchEvent(new MouseEvent("pointerdown", { bubbles: true, clientX: 50 }));
|
||||||
|
});
|
||||||
|
expect(onSetStyle).toHaveBeenCalledWith("opacity", "0.5");
|
||||||
|
act(() => root.unmount());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -477,6 +477,35 @@ function FlatOverflowMaskRows({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
/* Flat Opacity slider */
|
||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
function FlatOpacitySlider({
|
||||||
|
styles,
|
||||||
|
disabled,
|
||||||
|
onSetStyle,
|
||||||
|
}: {
|
||||||
|
styles: Record<string, string>;
|
||||||
|
disabled: boolean;
|
||||||
|
onSetStyle: (prop: string, value: string) => void | Promise<void>;
|
||||||
|
}) {
|
||||||
|
const opacityValue = Math.round((parseNumericValue(styles.opacity) ?? 1) * 100);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FlatSlider
|
||||||
|
label="Opacity"
|
||||||
|
value={opacityValue}
|
||||||
|
min={0}
|
||||||
|
max={100}
|
||||||
|
tier="explicitCustom"
|
||||||
|
displayValue={`${opacityValue}%`}
|
||||||
|
disabled={disabled}
|
||||||
|
onCommit={(next) => void onSetStyle("opacity", formatNumericValue(next / 100))}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function FlatStyleSection({
|
export function FlatStyleSection({
|
||||||
projectId,
|
projectId,
|
||||||
element,
|
element,
|
||||||
@@ -523,6 +552,7 @@ export function FlatStyleSection({
|
|||||||
disabled={styleEditingDisabled}
|
disabled={styleEditingDisabled}
|
||||||
onSetStyle={onSetStyle}
|
onSetStyle={onSetStyle}
|
||||||
/>
|
/>
|
||||||
|
<FlatOpacitySlider styles={styles} disabled={styleEditingDisabled} onSetStyle={onSetStyle} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user