import type { JSX, ValidComponent } from "@solidjs/web";
import { dynamic } from "@solidjs/web";
import { omit } from "solid-js";
import { composeRefs, userRef } from "../../internals/compose-refs";
import { mergeRootProps } from "../../internals/merge-root-props";
import { resolveClassStyle } from "../../internals/resolve-class-style";
import type { BaseUIComponentProps } from "../../internals/types";
import { useScrollAreaRootContext } from "../root/scroll-area-root-context.ts";
import { useScrollAreaScrollbarContext } from "../scrollbar/scroll-area-scrollbar-context.ts";
import { ScrollAreaScrollbarCssVars } from "../scrollbar/scroll-area-scrollbar-css-vars.ts";
import { ScrollAreaThumbDataAttributes } from "./scroll-area-thumb-data-attributes.ts";
export interface ScrollAreaThumbState {
/** The thumb's orientation. */
orientation?: "horizontal" | "vertical" | undefined;
}
export interface ScrollAreaThumbProps
extends BaseUIComponentProps<"div", ScrollAreaThumbState> {
/** Tag/component to render. Defaults to `"div"`. */
as?: ValidComponent;
}
/**
* The draggable thumb of the scrollbar. Renders a `
` element (or `as`
* override).
*
* ยง1 wave 3: replaces `renderElement` with `dynamic(() => props.as ?? "div")`.
* The legacy `stateAttributesMapping` (which projected `orientation`) is
* inlined as a reactive getter on the internal slot bag.
*/
export function ScrollAreaThumb(props: ScrollAreaThumbProps): JSX.Element {
const root = useScrollAreaRootContext();
const scrollbar = useScrollAreaScrollbarContext();
const userStyling = resolveClassStyle(props, () => ({
orientation: scrollbar.orientation,
}));
const userProps = omit(props, "class", "style", "attrs", "as");
const localRef = (el: HTMLDivElement | null): void => {
if (scrollbar.orientation === "vertical") {
root.thumbYRef.current = el;
} else {
root.thumbXRef.current = el;
}
};
const internalSlot = {
[ScrollAreaThumbDataAttributes.orientation]: scrollbar.orientation,
onPointerDown: (event: PointerEvent) => {
root.handlePointerDown(event);
},
onPointerMove: (event: PointerEvent) => {
root.handlePointerMove(event);
},
onPointerUp: (event: PointerEvent) => {
if (scrollbar.orientation === "vertical") {
root.setScrollingY(false);
} else {
root.setScrollingX(false);
}
root.handlePointerUp(event);
},
get style(): JSX.CSSProperties {
const base: JSX.CSSProperties = {};
if (!root.hasMeasuredScrollbar()) {
base.visibility = "hidden";
}
if (scrollbar.orientation === "vertical") {
base.height = `var(${ScrollAreaScrollbarCssVars.scrollAreaThumbHeight})`;
} else {
base.width = `var(${ScrollAreaScrollbarCssVars.scrollAreaThumbWidth})`;
}
return base;
},
};
const styledUserProps = mergeRootProps(userStyling, userProps);
const merged = mergeRootProps(internalSlot, styledUserProps);
const Tag = dynamic(() => props.as ?? "div");
return ;
}