react-cmp-selector
Version:
A powerful and extensible utility for filtering and selecting React components based on specified attributes and values.
107 lines (106 loc) • 4.06 kB
TypeScript
import React, { ReactElement, ReactNode } from 'react';
/**
* Configuration options for finding and modifying React components
* @template P - Props type of the target component
*/
export interface ComponentFinderProps<P = unknown> {
/** React children to search through */
children: ReactNode;
/** HTML attribute name to search for (default: 'data-slot') */
attribute?: string;
/** Attribute value to match */
value?: string;
/** Props to merge into the found component */
props?: Partial<P>;
/** Enable debug logging */
debug?: boolean;
/** Find all matching components */
findAll?: boolean;
/** Callback triggered when component is found */
onFound?: (component: ReactElement) => void;
/** Merge strategy for function props */
functionPropMerge?: 'combine' | 'override';
}
/**
* Custom React hook for finding components by attribute with enhanced capabilities
*
* @remarks
* This hook provides advanced component searching with prop merging, debug capabilities,
* and support for complex React trees. It's ideal for component injection patterns.
*
* @template P - Props type of the target component
* @param options - Configuration options for the finder
* @returns Found component(s) or null
*
* @example
* // Find and modify a header component
* const header = getCmpByAttr({
* value: 'header',
* props: { className: 'sticky-header' }
* });
*
* @example
* // Find all matching buttons with combined click handlers
* const buttons = getCmpByAttr({
* attribute: 'data-role',
* value: 'action-button',
* findAll: true,
* functionPropMerge: 'combine'
* });
*/
export declare function getCmpByAttr<P = unknown>({ children, attribute, value, props, debug, findAll, onFound, functionPropMerge }: ComponentFinderProps<P>): ReactNode | ReactNode[] | null;
/**
* Props for the Slot component
* @template P - Props type of the slotted component
*/
export interface SlotProps<P = unknown> extends Omit<ComponentFinderProps<P>, 'value' | 'findAll' | 'onFound'> {
/** Slot identifier to search for */
name: string;
/** Fallback content when no slot is found */
fallback?: ReactNode;
}
/**
* Declarative component version of getCmpByAttr
*
* @remarks
* Provides a React component interface for the slot finding functionality
* with additional validation and fallback capabilities.
*
* @example
* <Slot name="header" fallback={<DefaultHeader />}>
* {children}
* </Slot>
*/
export declare function Slot<P = unknown>({ children, name, attribute, props, debug, fallback, functionPropMerge }: SlotProps<P>): string | number | bigint | boolean | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | Promise<string | number | bigint | boolean | React.ReactPortal | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | null | undefined> | null;
/**
* Utility functions for working with slots
*/
export declare const SlotUtils: {
/**
* Creates a slot marker component for type-safe slot declaration
*
* @param name - Slot identifier
* @param attribute - Attribute name to use (default: 'data-slot')
* @returns Slot marker component
*
* @example
* const HeaderSlot = SlotUtils.createMarker('header');
* <HeaderSlot>...</HeaderSlot>
*/
createMarker: (name: string, attribute?: string) => ({ children, ...props }: {
children?: ReactNode;
} & Record<string, unknown>) => React.DetailedReactHTMLElement<{
[x: string]: unknown;
style: {
display: "contents";
};
}, HTMLElement>;
/**
* Validates required slots in development environment
*
* @param children - Component children to validate
* @param requiredSlots - Array of required slot names
* @param attribute - Attribute name to check (default: 'data-slot')
*/
validate: (children: ReactNode, requiredSlots: string[], attribute?: string) => void;
};