@ffsm/html-factory
Version:
A lightweight utility for creating React HTML factory components with TypeScript support, ref forwarding, and className merging.
85 lines (84 loc) • 4.13 kB
TypeScript
import { ComponentPropsWithRef, DetailedHTMLProps, HTMLAttributes, JSX, PropsWithChildren, Ref } from 'react';
/**
* A utility type that represents detailed HTML props for a specific element type.
* This combines HTML attributes with the element type to create proper typing.
*
* @template El - The HTML element instance type (e.g., HTMLDivElement, HTMLButtonElement)
* @type {DetailedHTMLProps<HTMLAttributes<El>, El>}
*/
export type HTMLFactoryInfer<El> = DetailedHTMLProps<HTMLAttributes<El>, El>;
/**
* A utility type that extracts the props type for a specific JSX intrinsic element.
* This provides direct access to the props type defined in JSX.IntrinsicElements.
*
* @template El - The HTML element tag that extends keyof JSX.IntrinsicElements (e.g., 'div', 'button')
* @type {JSX.IntrinsicElements[El]}
*
* @example
* // Type will be the props type for a div element
* type DivProps = HTMLElementProps<'div'>;
*
* // Usage in a component
* function CustomDiv(props: HTMLElementProps<'div'>) {
* return <div {...props} />;
* }
*/
export type HTMLElementProps<El extends keyof JSX.IntrinsicElements> = JSX.IntrinsicElements[El];
/**
* A type utility that extracts the underlying HTML element instance type from a JSX intrinsic element.
* Uses conditional type inference to determine the actual DOM element type that corresponds to
* a given JSX element tag.
*
* @template El - The HTML element tag that extends keyof JSX.IntrinsicElements (e.g., 'div', 'button')
* @returns If the element can be inferred using HTMLFactoryInfer, returns the inferred instance type;
* otherwise falls back to HTMLElement
*
* @example
* // Type will be HTMLButtonElement
* type ButtonElement = HTMLFactory<'button'>;
*
* // Type will be HTMLDivElement
* type DivElement = HTMLFactory<'div'>;
*
* // Usage with useRef
* const buttonRef = useRef<HTMLFactory<'button'>>(null);
*
* @example
* // Using with the factory function
* const Button = factory('button', 'Button');
* function Component() {
* const ref = useRef<HTMLFactory<'button'>>(null);
* return <Button ref={ref}>Click me</Button>;
* }
*/
export type HTMLFactory<El extends keyof JSX.IntrinsicElements> = JSX.IntrinsicElements[El] extends HTMLFactoryInfer<infer InstanceType> ? InstanceType : HTMLElement;
/**
* Type for HTML factory component props
* @template El The HTML element type, defaults to HTMLElement
*/
export type HTMlFactoryProps<El extends keyof JSX.IntrinsicElements> = PropsWithChildren<HTMLElementProps<El>>;
/**
* Processes and merges HTML props with special handling for className
* @template El The HTML element type
* @param {HTMLElementProps<El>} overideProps - Props to override initial props with
* @param {Ref<El>} [ref] - Optional ref to forward
* @param {HTMLElementProps<El>} [initialProps] - Optional initial props
* @returns {HTMLElementProps<El>} Merged props with className handling
*/
export declare function propsHTML<El extends keyof JSX.IntrinsicElements>(overideProps: HTMlFactoryProps<El>, ref?: Ref<HTMLFactory<El>>, initialProps?: HTMLElementProps<El>): ComponentPropsWithRef<El>;
/**
* Creates a factory component for the specified HTML tag
* @template El The HTML element type that extends keyof JSX.IntrinsicElements
* @param {El} tag - The HTML tag to create a factory for
* @param {string} displayName - The display name for the component
* @param {HTMlFactoryProps<El>} [initialProps] - Optional initial props for the component
* @returns {ForwardRefExoticComponent<PropsWithoutRef<HTMlFactoryProps<El>> & RefAttributes<El>>} A React component
*
* @example
* // Create a custom paragraph component
* const P = factory('p', 'Paragraph', { className: 'text-base' });
*
* // Use in your component
* <P className="text-red-500">This will have both classes</P>
*/
export declare function factory<El extends keyof JSX.IntrinsicElements>(Tag: El, displayName: string, initialProps?: HTMlFactoryProps<El>): import("react").ForwardRefExoticComponent<import("react").PropsWithoutRef<HTMlFactoryProps<El>> & import("react").RefAttributes<HTMLFactory<El>>>;