import type { HTMLProps } from 'react' import type { ElementProps } from './types' // merges prop getters from multiple interaction hooks. // event handlers are chained (all run), first non-undefined return value wins. // non-function props: user props override hook props. export function useInteractions(propsList: Array) { const filtered = propsList.filter(Boolean) as ElementProps[] // collect all event handlers by event name for each element type const referenceFns = new Map any>>() const floatingFns = new Map any>>() const itemFns = new Map any>>() const referenceStatic: Record = {} const floatingStatic: Record = {} for (const props of filtered) { if (props.reference) { collectProps(props.reference as any, referenceFns, referenceStatic) } if (props.floating) { collectProps(props.floating as any, floatingFns, floatingStatic) } if (props.item && typeof props.item === 'object') { collectProps(props.item as any, itemFns, {}) } } return { getReferenceProps(userProps?: HTMLProps) { return buildProps(referenceFns, referenceStatic, userProps) }, getFloatingProps(userProps?: HTMLProps) { return buildProps(floatingFns, floatingStatic, userProps) }, getItemProps(userProps?: HTMLProps) { return buildProps(itemFns, {}, userProps) }, } } function collectProps( props: Record, fnMap: Map any>>, staticMap: Record ) { for (const key of Object.keys(props)) { if (typeof props[key] === 'function') { let arr = fnMap.get(key) if (!arr) { arr = [] fnMap.set(key, arr) } arr.push(props[key]) } else { staticMap[key] = props[key] } } } function buildProps( fnMap: Map any>>, staticProps: Record, userProps?: Record ): Record { // hook static props first, then user props override const result: Record = { ...staticProps } // merge event handlers from hooks for (const [key, fns] of fnMap) { const hookHandler = (...args: any[]) => { for (const fn of fns) { const result = fn(...args) if (result !== undefined) return result } } result[key] = hookHandler } // user props override everything — but chain event handlers if (userProps) { for (const key of Object.keys(userProps)) { if (key === 'style') { result.style = { ...result.style, ...userProps.style } } else if (typeof userProps[key] === 'function' && result[key]) { const hookFn = result[key] const userFn = userProps[key] result[key] = (...args: any[]) => { userFn(...args) hookFn(...args) } } else { result[key] = userProps[key] } } } return result }