import type { JSX, ValidComponent } from "@solidjs/web"; import { dynamic } from "@solidjs/web"; import { createRenderEffect, omit, onCleanup, Show } 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"; // biome-ignore lint/complexity/noBannedTypes: matches Base UI React — corner exposes no state fields, but a named type lets consumers reference `ScrollArea.Corner.State`. export type ScrollAreaCornerState = {}; export interface ScrollAreaCornerProps extends BaseUIComponentProps<"div", ScrollAreaCornerState> { /** Tag/component to render. Defaults to `"div"`. */ as?: ValidComponent; } /** * Small square sitting at the intersection of the two scrollbars. Renders * a `
` element (or `as` override), or nothing when both scrollbars are * visible is false. * * §1 wave 3: replaces `renderElement` with `dynamic(() => props.as ?? "div")`. */ export function ScrollAreaCorner(props: ScrollAreaCornerProps): JSX.Element { const context = useScrollAreaRootContext(); const userStyling = resolveClassStyle(props, () => ({})); const userProps = omit(props, "class", "style", "attrs", "as"); const localRef = (el: HTMLDivElement | null): void => { context.cornerRef.current = el; }; // `` swaps its children by unmounting the old branch without firing // the ref callback with `null`, so the shared `cornerRef.current` would // dangle at a detached node. Ref callbacks run ownerless in Solid 2 // (`onCleanup` there is a no-op — `[NO_OWNER_CLEANUP]`), so the cleanup // lives in owned scopes instead: a render effect mirroring the `` // condition handles branch swaps, and onCleanup handles disposal. createRenderEffect( () => context.hiddenState().corner, (hidden) => { if (hidden) { context.cornerRef.current = null; } return undefined; }, ); onCleanup(() => { context.cornerRef.current = null; }); const internalSlot = { get style(): JSX.CSSProperties { const size = context.cornerSize(); return { position: "absolute", bottom: 0, "inset-inline-end": 0, width: `${size.width}px`, height: `${size.height}px`, }; }, }; const styledUserProps = mergeRootProps(userStyling, userProps); const merged = mergeRootProps(internalSlot, styledUserProps); const Tag = dynamic(() => props.as ?? "div"); return ( ); }