import { Slot } from "@radix-ui/react-slot"; import { useLayoutEffect } from "@radix-ui/react-use-layout-effect"; import { createContext, forwardRef, useCallback, useContext, useMemo, useRef } from "react"; import type { UnwrapResponsive } from "../../types/responsive"; import { handleColor, handleDimension, type StyleProps } from "../../utils/styled"; export interface PrefixIconProps { svg: React.ReactNode; } export const PrefixIcon = forwardRef( ({ svg, ...otherProps }, ref) => { return ( } aria-hidden className="seed-prefix-icon" {...otherProps} > {svg} ); }, ); export interface SuffixIconProps { svg: React.ReactNode; } export const SuffixIcon = forwardRef( ({ svg, ...otherProps }, ref) => { return ( } aria-hidden className="seed-suffix-icon" {...otherProps} > {svg} ); }, ); const IconContext = createContext<{ register: () => void; unregister: () => void } | null>(null); export const IconRequired = ({ children, enabled, }: { children: React.ReactNode; enabled: boolean; }) => { const registeredRef = useRef(false); const parentContext = useContext(IconContext); const register = useCallback(() => { // @ts-ignore if (process.env.NODE_ENV !== "production") { if (registeredRef.current) { throw new Error( "Icon-only Component must render only one under children. Check if you are rendering multiple .", ); } } registeredRef.current = true; }, []); const unregister = useCallback(() => { registeredRef.current = false; }, []); useLayoutEffect(() => { if (!enabled) { return; } // @ts-ignore if (process.env.NODE_ENV !== "production") { if (parentContext) { throw new Error( "Icon-only Component must not be nested within another Icon-Only. Check if you are using Icon-Only inside another Icon-Only.", ); } if (!registeredRef.current) { throw new Error( "Icon-only Component must render as a child. Check if you are using raw svg icon instead of .", ); } } }, [parentContext, enabled]); const providerValue = useMemo(() => { if (!enabled) { // If not enabled, return parent context if exists if (parentContext) { return parentContext; } // If not enabled and no parent context, return null return null; } // If enabled, return register and unregister functions to detect count return { register, unregister }; }, [enabled, parentContext, register, unregister]); return {children}; }; export interface IconProps { svg: React.ReactNode; size?: UnwrapResponsive; color?: StyleProps["color"]; } export const Icon = forwardRef( ({ svg, size, color, ...otherProps }, ref) => { const context = useContext(IconContext); useLayoutEffect(() => { context?.register(); return () => { context?.unregister(); }; }, [context]); const sizeValue = handleDimension(size); const colorValue = handleColor(color); return ( } aria-hidden className="seed-icon" style={ { "--seed-icon-size": sizeValue, "--seed-icon-color": colorValue, } as React.CSSProperties } {...otherProps} > {svg} ); }, ); export function withIconRequired

( Component: React.ComponentType

>, enabledPredicate: (props: React.PropsWithoutRef

) => boolean, ) { const Node = forwardRef((props, ref) => { const enabled = enabledPredicate(props); return ( {/* @ts-ignore */} ); }); Node.displayName = Component.displayName || Component.name; return Node; }