import type { JSX, ValidComponent } from "@solidjs/web";
import { dynamic } from "@solidjs/web";
import { createEffect, createSignal, 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 {
type ScrollAreaRootState,
useScrollAreaRootContext,
} from "../root/scroll-area-root-context.ts";
import { scrollAreaDataAttrs } from "../utils/state-attrs.ts";
import { useScrollAreaViewportContext } from "../viewport/scroll-area-viewport-context.ts";
export interface ScrollAreaContentState extends ScrollAreaRootState {}
export interface ScrollAreaContentProps
extends BaseUIComponentProps<"div", ScrollAreaContentState> {
/** Tag/component to render. Defaults to `"div"`. */
as?: ValidComponent;
}
/**
* Container for the scrollable content. Renders a `
` element (or `as`
* override). Runs a `ResizeObserver` on its own wrapper so size changes within
* the content re-trigger the viewport's thumb recompute.
*
* ยง1 wave 3: replaces `renderElement` with `dynamic(() => props.as ?? "div")`.
*/
export function ScrollAreaContent(props: ScrollAreaContentProps): JSX.Element {
const root = useScrollAreaRootContext();
const viewport = useScrollAreaViewportContext();
const [contentWrapper, setContentWrapper] =
createSignal(null, { ownedWrite: true });
createEffect(
() => contentWrapper(),
(el) => {
if (typeof ResizeObserver === "undefined" || !el) return;
let hasInitialized = false;
const ro = new ResizeObserver(() => {
// Skip the initial delivery to avoid double-counting the mount
// pass which the viewport already performed.
if (!hasInitialized) {
hasInitialized = true;
return;
}
viewport.computeThumbPosition();
});
ro.observe(el);
return () => {
ro.disconnect();
};
},
);
const userStyling = resolveClassStyle(props, () => root.viewportState());
const userProps = omit(props, "class", "style", "attrs", "as");
const localRef = (el: HTMLDivElement | null): void => {
setContentWrapper(el);
};
const internalSlot = {
role: "presentation" as const,
style: { "min-width": "fit-content" } as JSX.CSSProperties,
};
const styledUserProps = mergeRootProps(userStyling, userProps);
let merged: Record = mergeRootProps(
internalSlot,
scrollAreaDataAttrs(root.viewportState),
);
merged = mergeRootProps(merged, styledUserProps);
const Tag = dynamic(() => props.as ?? "div");
return ;
}