UNPKG

@primer/react

Version:

An implementation of GitHub's Primer Design System using React

64 lines 2.91 kB
import React from 'react'; /** * useSlots - Extract slot components from children for SSR-compatible slot APIs. * * Given a list of children and a config mapping slot names to component types, * separates children into two groups: matched slots and the rest. * * Config: { leadingVisual: LeadingVisual, description: Description } * * Children: Matching: Output: * +----------------+ slots = { * | LeadingVisual | -> matches slot 0 --> leadingVisual: <LeadingVisual /> * | "Project name" | -> no match --> description: <Description /> * | Description | -> matches slot 1 --> } * | TrailingVisual | -> no match --> rest = ["Project name", <TrailingVisual />] * +----------------+ * * Performance-sensitive: called per item in lists (e.g. 100-item ActionList * calls this 101 times per render). * * Once all slots are filled, remaining children skip matching entirely in * production (single integer comparison). In dev, we still scan for duplicates * to emit a warning. * * Flow per child: * * child ──> isValidElement? ──no──> rest[] * | * yes * | * v * all slots filled? ──yes──> rest[] (prod) * | | * no [dev: check for * | duplicate warning] * v * match against unfilled slots * | * found match? ──no──> rest[] * | * yes * | * v * slots[key] = child, slotsFound++ * * Slot config supports two matcher styles: * 1. Component reference: { visual: LeadingVisual } * 2. Component + test fn: { block: [Description, props => props.variant === 'block'] } */ type Props = any; type ComponentMatcher = React.ElementType<Props>; type ComponentAndPropsMatcher = [ComponentMatcher, (props: Props) => boolean]; export type SlotConfig = Record<string, ComponentMatcher | ComponentAndPropsMatcher>; type SlotElements<Config extends SlotConfig> = { [Property in keyof Config]: SlotValue<Config, Property>; }; type SlotValue<Config, Property extends keyof Config> = Config[Property] extends React.ElementType ? React.ReactElement<React.ComponentPropsWithoutRef<Config[Property]>, Config[Property]> : Config[Property] extends readonly [ infer ElementType extends React.ElementType, infer _testFn ] ? React.ReactElement<React.ComponentPropsWithoutRef<ElementType>, ElementType> : never; /** Extract slot components from children. See file header for details. */ export declare function useSlots<Config extends SlotConfig>(children: React.ReactNode, config: Config): [Partial<SlotElements<Config>>, React.ReactNode[]]; export {}; //# sourceMappingURL=useSlots.d.ts.map