mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-03 04:38:33 +00:00
feat(studio): add centerTick and reset-slot to FlatSlider for bipolar grade rows
This commit is contained in:
@@ -229,6 +229,96 @@ describe("FlatSlider", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("FlatSlider — Grade extensions", () => {
|
||||
it("renders a center tick when centerTick is true, and omits it by default", () => {
|
||||
const { host: withTick, root: rootA } = renderInto(
|
||||
<FlatSlider
|
||||
label="Exposure"
|
||||
value={0}
|
||||
min={-100}
|
||||
max={100}
|
||||
tier="default"
|
||||
displayValue="+0.00"
|
||||
centerTick
|
||||
onCommit={vi.fn()}
|
||||
/>,
|
||||
);
|
||||
expect(withTick.querySelector('[data-flat-slider-center-tick="true"]')).not.toBeNull();
|
||||
act(() => rootA.unmount());
|
||||
|
||||
const { host: withoutTick, root: rootB } = renderInto(
|
||||
<FlatSlider
|
||||
label="Layer blur"
|
||||
value={0}
|
||||
min={0}
|
||||
max={100}
|
||||
tier="default"
|
||||
displayValue="0px"
|
||||
onCommit={vi.fn()}
|
||||
/>,
|
||||
);
|
||||
expect(withoutTick.querySelector('[data-flat-slider-center-tick="true"]')).toBeNull();
|
||||
act(() => rootB.unmount());
|
||||
});
|
||||
|
||||
it("always reserves a 14px reset slot, showing the icon only when set and onReset is provided", () => {
|
||||
const onReset = vi.fn();
|
||||
const { host, root } = renderInto(
|
||||
<FlatSlider
|
||||
label="Contrast"
|
||||
value={12}
|
||||
min={-100}
|
||||
max={100}
|
||||
tier="explicitCustom"
|
||||
displayValue="+12%"
|
||||
centerTick
|
||||
onReset={onReset}
|
||||
onCommit={vi.fn()}
|
||||
/>,
|
||||
);
|
||||
const slot = host.querySelector('[data-flat-slider-reset-slot="true"]');
|
||||
expect(slot).not.toBeNull();
|
||||
const resetButton = host.querySelector<HTMLButtonElement>('[data-flat-slider-reset="true"]');
|
||||
expect(resetButton).not.toBeNull();
|
||||
act(() => resetButton?.dispatchEvent(new MouseEvent("click", { bubbles: true })));
|
||||
expect(onReset).toHaveBeenCalledTimes(1);
|
||||
act(() => root.unmount());
|
||||
|
||||
const { host: unsetHost, root: rootB } = renderInto(
|
||||
<FlatSlider
|
||||
label="Contrast"
|
||||
value={0}
|
||||
min={-100}
|
||||
max={100}
|
||||
tier="default"
|
||||
displayValue="0%"
|
||||
centerTick
|
||||
onCommit={vi.fn()}
|
||||
/>,
|
||||
);
|
||||
expect(unsetHost.querySelector('[data-flat-slider-reset-slot="true"]')).not.toBeNull();
|
||||
expect(unsetHost.querySelector('[data-flat-slider-reset="true"]')).toBeNull();
|
||||
act(() => rootB.unmount());
|
||||
});
|
||||
|
||||
it("renders no reset slot at all when centerTick is omitted, matching existing Style/Media callers", () => {
|
||||
const { host, root } = renderInto(
|
||||
<FlatSlider
|
||||
label="Opacity"
|
||||
value={100}
|
||||
min={0}
|
||||
max={100}
|
||||
tier="explicitCustom"
|
||||
displayValue="100%"
|
||||
onCommit={vi.fn()}
|
||||
/>,
|
||||
);
|
||||
expect(host.querySelector('[data-flat-slider-reset-slot="true"]')).toBeNull();
|
||||
expect(host.querySelector('[data-flat-slider-reset="true"]')).toBeNull();
|
||||
act(() => root.unmount());
|
||||
});
|
||||
});
|
||||
|
||||
describe("FlatSelectRow", () => {
|
||||
it("renders the default tier with no reset button", () => {
|
||||
const { host, root } = renderInto(
|
||||
|
||||
@@ -247,6 +247,8 @@ export function FlatSlider({
|
||||
tier,
|
||||
displayValue,
|
||||
disabled,
|
||||
centerTick,
|
||||
onReset,
|
||||
onCommit,
|
||||
}: {
|
||||
label: string;
|
||||
@@ -257,6 +259,8 @@ export function FlatSlider({
|
||||
tier: "default" | "explicitCustom";
|
||||
displayValue: string;
|
||||
disabled?: boolean;
|
||||
centerTick?: boolean;
|
||||
onReset?: () => void;
|
||||
onCommit: (nextValue: number) => void;
|
||||
}) {
|
||||
const clampedPct = Math.max(0, Math.min(100, ((value - min) / Math.max(max - min, 1e-6)) * 100));
|
||||
@@ -285,6 +289,12 @@ export function FlatSlider({
|
||||
commitFromClientX(e.clientX, e.currentTarget.getBoundingClientRect());
|
||||
}}
|
||||
>
|
||||
{centerTick && (
|
||||
<div
|
||||
data-flat-slider-center-tick="true"
|
||||
className="absolute left-1/2 top-[-1px] h-1 w-px -translate-x-1/2 bg-panel-text-5"
|
||||
/>
|
||||
)}
|
||||
{tier === "explicitCustom" && (
|
||||
<div
|
||||
data-flat-slider-fill="true"
|
||||
@@ -308,6 +318,21 @@ export function FlatSlider({
|
||||
>
|
||||
{displayValue}
|
||||
</span>
|
||||
{centerTick && (
|
||||
<span data-flat-slider-reset-slot="true" className="w-3.5 flex-shrink-0">
|
||||
{tier === "explicitCustom" && onReset && (
|
||||
<button
|
||||
type="button"
|
||||
data-flat-slider-reset="true"
|
||||
title="Remove — fall back to default"
|
||||
onClick={onReset}
|
||||
className="text-panel-text-3 hover:text-panel-text-1"
|
||||
>
|
||||
<RotateCcw size={11} />
|
||||
</button>
|
||||
)}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user