import { type Cartesian2D, type Polar2D } from "./Coordinates.js"; import { type Override } from "./Types.js"; /** * credit goes to puppeteer types */ export declare namespace Selector { type CombinatorTokens = [" ", ">", "+", "~", "|", "|"]; type BeginSubclassSelectorTokens = [".", "#", "[", ":"]; type FlatmapSplitWithDelemiters = Inputs extends [infer FirstInput, ...infer RestInputs] ? FirstInput extends string ? RestInputs extends readonly string[] ? FlatmapSplitWithDelemiters ]> : Acc : Acc : Acc; type Split = Input extends `${infer Prefix}${Delimiter}${infer Suffix}` ? Split : [...Acc, Input]; type SplitWithDelemiters = Delemiters extends [infer FirstDelemiter, ...infer RestDelemiters] ? FirstDelemiter extends string ? RestDelemiters extends readonly string[] ? FlatmapSplitWithDelemiters, RestDelemiters> : never : never : [Input]; type Drop = Arr extends [infer Head, ...infer Tail] ? Head extends Remove ? Drop : Drop : Acc; type CompoundSelectorsOfComplexSelector = SplitWithDelemiters extends infer IntermediateTokens ? IntermediateTokens extends readonly string[] ? Drop : never : never; type NonEmptyReadonlyArray = [T, ...(readonly T[])]; type Last> = Arr extends [ infer Head, ...infer Tail ] ? Tail extends NonEmptyReadonlyArray ? Last : Head : never; type TypeSelectorOfCompoundSelector = SplitWithDelemiters extends infer CompoundSelectorTokens ? CompoundSelectorTokens extends [infer TypeSelector, ...any[]] ? TypeSelector extends "" ? unknown : TypeSelector : never : never; type TypeSelectorOfComplexSelector = CompoundSelectorsOfComplexSelector extends infer CompoundSelectors ? CompoundSelectors extends NonEmptyReadonlyArray ? Last extends infer LastCompoundSelector ? LastCompoundSelector extends string ? TypeSelectorOfCompoundSelector : never : never : unknown : never; export type ElementFor = TagName extends keyof HTMLElementTagNameMap ? HTMLElementTagNameMap[TagName] : TagName extends keyof SVGElementTagNameMap ? SVGElementTagNameMap[TagName] : never; export type NodeFor = TypeSelectorOfComplexSelector extends infer TypeSelector ? TypeSelector extends keyof HTMLElementTagNameMap | keyof SVGElementTagNameMap ? ElementFor : Element : never; export {}; } /** * select all matches of the given css selector. optionally check for visibility as well. */ export declare const selectAll: (container: Element, selector: Selector, opts?: { /** * whether or not the element must be visible * @default false */ visible?: boolean; }) => Selector.NodeFor[]; /** * return the first match of the given css selector. If no match is found an error is thrown */ export declare const select: (container: Element, selector: Selector, opts?: { /** * whether or not the element must be visible * @default false */ visible?: boolean; } | undefined) => Selector.NodeFor; /** * return all ancestors of a node until the root node */ export declare const getAncestors: (from: Element) => Element[]; /** * aggregate all previous siblings */ export declare const allPreviousSiblings: (from: Element) => Element[]; /** * return the node that matches the given css selector in backward scanning direction. * If no such node is found returns undefined */ export declare const previous: (selector: Selector, from: Node, opts?: { boundary?: Node; }) => Selector.NodeFor | undefined; /** * return the node that matches the given css selector in forward scanning direction. * If no such node is found returns undefined */ export declare const next: (selector: Selector, from: Node, opts?: { boundary?: Node; }) => Selector.NodeFor | undefined; /** * performs a forward scan of the given nodes children and returns all nodes * that match the given predicate */ export declare const filterChildren: (predicate: (node: Node) => node is Filtered, ofElement: Node) => Filtered[]; /** * create a new dom element. * * This works similarly to jsx under the hood, so you can rather easily * declare elements instead of imperatively manipulating them yourself. */ export declare const create: (tagname: K, attributes?: Partial; part: string; }> & { [key: `data-${string}`]: string | boolean | null | undefined; }>, children?: Iterable) => HTMLElementTagNameMap[K]; /** * create a new text node */ export declare const text: (text: string | number) => Text; /** * get the closest attribute to a from a given element on upwards. * Can optionally be bounded to another element to prevent scanning * up to root */ export declare function getClosestAttribute(attribute: string, from: HTMLElement, root?: null | HTMLElement): string | null; /** * get the closest parent that matches a given selector. * * This is different from `HTMLElement.closest` in that it never matches the element itself. */ export declare function getClosestParent(selector: Selector, from: HTMLElement): Selector.NodeFor | null; /** * create a new event from _at least_ a given type string. * * If the passed argument already is an event it is returned * unchanged. This is because cloning events has some pitfalls, * chief among which is that you can't clone trusted events and * re-dispatching trusted events as untrusted events will often * lead to the browser ignoring those events. */ export declare const createEvent: (event: { type: Type; } & ((Type extends keyof HTMLElementEventMap ? HTMLElementEventMap[Type] : CustomEvent) extends infer Event ? Event extends CustomEvent ? (unknown extends Detail ? {} : { detail: Detail; }) & EventInit : EventInit : never)) => Type extends keyof HTMLElementEventMap ? HTMLElementEventMap[Type] : typeof event & CustomEvent; /** * dispatch a new custom event */ export declare const dispatch: (on: EventTarget, event: Parameters>[0]) => boolean; /** * all native events */ export declare const allEvents: string[]; export type ForwardEventListenerOptions = AddEventListenerOptions & { /** * you can override the composed path of the forwarded event * to give consumers a way to identify the original target */ keepComposedPath?: boolean; /** * check whether an event should be forwarded or not. */ predicate?: (e: Event) => boolean; }; export type ForwardEventOptions = AddEventListenerOptions & ForwardEventListenerOptions & { eventNames?: string[]; } & ({ source: EventTarget; target: EventTarget; } | { source?: EventTarget; target: EventTarget; predicate: NonNullable; }); /** * sometimes you want to capture events before they reach their intended * target and re-dispatch them as if they had fired on something else */ export declare function forwardEvents(options: ForwardEventOptions): void; /** * @deprecated please pass ForwardOptions instead */ export declare function forwardEvents(from: EventTarget, to: EventTarget, eventNames?: string[], eventListenerOptions?: ForwardEventListenerOptions): void; /** * returns a nodes index in its parents children */ export declare const indexInParent: (element: Element) => number; /** * swap child elements by index. * * Does not perform any sanity checks; you are responsible for making sure there are elements at the given indices. */ export declare const swapIndices: (inElement: Element, a: number, b: number) => void; /** * watches the attribute on *the closest parent that has it set at the time of * calling this function* * * Exercise caution when using this function as the element that has the attribute * you're interested in might change. */ export declare const watchClosestAttribute: (attribute: string, from: Element, callback: (current: string | null) => void, opts?: { /** * specify an AbortSignal to disconnect the observer */ signal?: AbortSignal; /** * an optional "boundary" to prevent watching attributes * that exist "too high up" in the tree */ root?: Element; }) => Disposable; /** * build a string from classnames. * * This is pretty much the same as the npm package classnames, but I got tired of installing that * and in the sense of this being the "prelude to web dev" I've written my own here.. */ export declare const classNames: (...classes: Array | string | undefined>) => string; /** * returns polar coordinates of where the given event happened * in relation to the center of the given element. * * This is useful e.g. to determine whether an event happened * in the upper or lower half and such. */ export declare const getPolarCoordinatesFromCenter: (event: MouseEvent, element: HTMLElement) => Polar2D; /** * extended information sourced from {@MDN getBoundingClientRect} */ export declare const getClientRect: (element: HTMLElement) => { left: number; right: number; top: number; bottom: number; center: Cartesian2D; }; /** * returns a cartesian delta of an event position relative to an elements center */ export declare const getEventOffsetFromCenter: (event: MouseEvent, target: HTMLElement) => Cartesian2D; export declare const isEventInLeftHalf: (event: MouseEvent, target: HTMLElement) => boolean; export declare const isEventInRightHalf: (event: MouseEvent, target: HTMLElement) => boolean; export declare const isEventInTopHalf: (event: MouseEvent, target: HTMLElement) => boolean; export declare const isEventInBottomHalf: (event: MouseEvent, target: HTMLElement) => boolean; /** * removes existing selection ranges and creates a new range that spans * the given char-index range in the given element. This is focused on * the text content of the given element, so it will skip/span child element * boundaries. */ export declare const selectText: (on: Node, from?: number, to?: number) => void; /** * create a way to attach event listeners and pre-bind common options. * * This is useful to avoid passing the same parameters over and over again. * * @example * ```ts * const on = createEventRegistrar(someInput, someAbortController); * on("change", handleChange) * on(["focusin", "focusout"], handleFocusChange) * ``` */ export declare const createEventRegistrar: (on: HTMLElement, options: Parameters[2]) => (eventName: EventName | EventName[], handler: Parameters extends keyof HTMLElementEventMap ? typeof on.addEventListener : typeof on.addEventListener>[1], overrideOptions?: typeof options) => void; /** * little helper to create an "enum" like structure that exposes * event names regarding changes to the attributes of the given type. * * Keep in mind that this does not yet attach any event * listener or such. You still have to use the resulting * strings to do that yourself. * * @deprecated usage of this functionality is implicitly coupled to simple-custom-elements library and bears no functionality on its own. Have a look at {@link createKeyNameProxy} for an alternative in combination with simple-custom-elements * * @example * * ```ts * @customElement({tagname: "my-ce"}) * class MyCe extends HTMLElement { * @attribute() * foo = ""; * } * const Events = createEventNameProxy();` * someDiv.addEventListener( * Events.fooChanged, // event name is created on usage * someEventListener, * ); * * someDiv.dispatchEvent(new Event(Events.clear)); * ``` */ export declare const createEventNameProxy: () => { [k in keyof Element as `${k & string}Changed`]-?: `${k & string}Changed`; } & { [k_1 in AdditionalEventNames[number]]: k_1; }; /** * create a proxy object that saves the passed keys. * * Think of it as making a typescript union of strings * accessible at runtime without using reflection. * * @example * ``` * type Events = { * foo: CustomEvent; * bar: CustomEvent; * } * const events = createKeyNameProxy(); * * declare global { * // merge your custom events into the global event map * // this way they're integrating nicely with `addEventListener` * interface HTMLElementEventMap extends Events {} * } * ``` */ export declare const createKeyNameProxy: >() => { [k in keyof Keys]: k; }; /** * creates a virtual text cursor relative to the given element. * * With this you can get and set a cursors position without * consideration for child elements - only the user visible * text counts. */ export declare const createCursor: (relativeTo: HTMLElement) => { getPosition: () => { x: number; y: number; } | undefined; setPosition: (cursor: { x: number; y: number; }) => void; };