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 ; }