UNPKG

@kitn.ai/ui

Version:

Framework-agnostic, Shadow-DOM web components for building AI chat interfaces — works in React, Vue, Angular, Svelte, or plain HTML. Authored in SolidJS.

80 lines (79 loc) 3.53 kB
import { Accessor, JSX } from 'solid-js'; import { Placement } from '@floating-ui/dom'; /** * Keep a node mounted through its CSS exit animation. * Open -> present=true, state='open' (enter animation via base classes) * Close -> state='closed' (data-closed triggers tw-animate-css animate-out), * then unmount on `animationend`. If no animation is defined * (e.g. jsdom), unmount on the next microtask. */ export declare function createPresence(show: Accessor<boolean>): { present: Accessor<boolean>; state: Accessor<"open" | "closed">; setRef: (el: Element) => void; }; export type AsTag = string | ((props: Record<string, any>) => JSX.Element); /** * Polymorphic element. `as` may be a tag name (default 'span') or a render * function that receives the forwarded props (render-prop style `as={fn}`). * Uses splitProps (NOT destructuring) so reactive forwarded props such as * aria-expanded stay reactive. All extra props (incl. `ref`, event handlers, * aria-*) are forwarded. `children` is left in `rest` so it forwards naturally. */ export declare function As(props: { as?: AsTag; children?: JSX.Element; [k: string]: any; }): JSX.Element; export interface UsePositionOptions { placement?: Placement; gutter?: number; arrowEl?: Accessor<HTMLElement | undefined>; /** * Fired ONCE when the reference (anchor) "goes away" — either removed from the * document OR hidden behind an `inert` ancestor (e.g. a modal/takeover that * inert-s the background while open). In both cases the anchor is no longer a * valid, interactive target, so the caller should close the overlay and unmount * its portal instead of leaving it orphaned (floating over an inert background or * anchored to a node that no longer exists). Anchored overlays portal OUT of the * trigger's subtree, so Solid's onCleanup does not catch an anchor that is * removed/inerted independently of the overlay component. Wire this to set the * overlay's open state to false. */ onDisconnect?: () => void; } /** * Position `floating` relative to `reference` using fixed strategy + autoUpdate, * so the element tracks the trigger on scroll/resize (fix DD-2). Writes * position into the returned `pos` signal; caller applies it as inline style. * * `options` (placement/gutter) are read at setup time — pass static values; * reactive option changes won't reposition until the next autoUpdate tick. */ export declare function usePosition(reference: Accessor<HTMLElement | undefined>, floating: Accessor<HTMLElement | undefined>, options?: UsePositionOptions): { pos: Accessor<{ x: number; y: number; placement: Placement; }>; arrowPos: Accessor<{ x?: number; y?: number; }>; hidden: Accessor<boolean>; }; export type DismissReason = 'escape' | 'outside'; export interface UseDismissOptions { enabled: Accessor<boolean>; onDismiss: (reason: DismissReason) => void; /** Elements considered "inside" (trigger + content). Pointerdown outside all of them dismisses. */ refs: () => (HTMLElement | undefined)[]; } /** * Escape key + outside-pointerdown dismissal. Does NOT lock page scroll (fix DD-1). * * `onDismiss` and `refs` are captured at call time (component setup), which is * fine in SolidJS since components don't re-run — ensure they close over mutable * variables, not stale values. */ export declare function useDismiss(opts: UseDismissOptions): void;