diff --git a/packages/components/src/components/Dialog/components/DialogBody.tsx b/packages/components/src/components/Dialog/components/DialogBody.tsx index 0fb10d5b..327f8bd5 100644 --- a/packages/components/src/components/Dialog/components/DialogBody.tsx +++ b/packages/components/src/components/Dialog/components/DialogBody.tsx @@ -1,14 +1,12 @@ 'use client'; import type { ReactNode, ComponentRef } from 'react'; -import { forwardRef, useContext, createContext } from 'react'; +import { forwardRef, createContext } from 'react'; -import { - clsx, - type ExtendableComponentPropsWithRef, - mergeProps, - useMultiRef, -} from '@koobiq/react-core'; +import type { ExtendableComponentPropsWithRef } from '@koobiq/react-core'; +import { clsx } from '@koobiq/react-core'; +import type { ContextValue } from '@koobiq/react-primitives'; +import { useContextProps } from '@koobiq/react-primitives'; import { utilClasses } from '../../../styles/utility'; import s from '../Dialog.module.css'; @@ -27,16 +25,16 @@ export type DialogBodyProps = ExtendableComponentPropsWithRef< 'div' >; -export const DialogBodyContext = createContext({}); +export const DialogBodyContext = + createContext>(null); export const DialogBody = forwardRef( ({ children, className, ...other }, ref) => { - const defaultProps = useContext(DialogBodyContext); - const { ref: contextRef } = mergeProps(defaultProps, other); + const [, ctxRef] = useContextProps({}, ref, DialogBodyContext); return (
( (props, ref) => { - const commonProps = useSlottedContext(props, ButtonContext, props.slot); + const [ctxProps, ctxRef] = useContextProps(props, ref, ButtonContext); const { as, @@ -33,16 +32,16 @@ export const Button = polymorphicForwardRef<'button', ButtonBaseProps>( formMethod, formNoValidate, formTarget, - } = commonProps; + } = ctxProps; const Tag = as || 'button'; - const domRef = useDOMRef(ref); + const domRef = useDOMRef(ctxRef); const { isHovered, isPressed, isFocused, isFocusVisible, buttonProps } = useButton( { - ...commonProps, + ...ctxProps, ...((isLoading || isDisabled) && { onPress: undefined, onPressStart: undefined, @@ -96,8 +95,8 @@ export const Button = polymorphicForwardRef<'button', ButtonBaseProps>( data-loading={isLoading || undefined} data-disabled={isDisabled || undefined} data-focus-visible={isFocusVisible || undefined} - {...('tabIndex' in commonProps && { tabIndex })} - aria-hidden={commonProps['aria-hidden']} + {...('tabIndex' in ctxProps && { tabIndex })} + aria-hidden={ctxProps['aria-hidden']} aria-disabled={isLoading ? 'true' : buttonProps['aria-disabled']} aria-busy={isLoading} ref={domRef} diff --git a/packages/primitives/src/components/Button/ButtonContext.tsx b/packages/primitives/src/components/Button/ButtonContext.tsx index 90f3e080..c1ba8367 100644 --- a/packages/primitives/src/components/Button/ButtonContext.tsx +++ b/packages/primitives/src/components/Button/ButtonContext.tsx @@ -2,10 +2,10 @@ import { createContext } from 'react'; -import type { ButtonProps } from './index'; +import type { ContextValue } from '../../utils'; -export type ButtonContextProps = { - slots?: Record; -}; +import type { ButtonProps } from './index'; -export const ButtonContext = createContext({}); +export const ButtonContext = createContext< + ContextValue +>({}); diff --git a/packages/primitives/src/components/Label/Label.tsx b/packages/primitives/src/components/Label/Label.tsx index 3a20ec1d..d3d9bbf4 100644 --- a/packages/primitives/src/components/Label/Label.tsx +++ b/packages/primitives/src/components/Label/Label.tsx @@ -1,22 +1,22 @@ 'use client'; import type { ComponentPropsWithRef, ElementType } from 'react'; -import { useContext } from 'react'; -import { polymorphicForwardRef, mergeProps } from '@koobiq/react-core'; +import { polymorphicForwardRef } from '@koobiq/react-core'; + +import { useContextProps } from '../../utils'; import type { LabelBaseProps } from './index'; import { LabelContext } from './index'; export const Label = polymorphicForwardRef<'label', LabelBaseProps>( (props, ref) => { - const { as: Tag = 'label', children, ...other } = props; + const [ctxProps, ctxRef] = useContextProps(props, ref, LabelContext); - const defaultProps = useContext(LabelContext); - const commonProps = mergeProps(defaultProps, other); + const { as: Tag = 'label', children, ...other } = ctxProps; return ( - + {children} ); diff --git a/packages/primitives/src/components/Label/LabelContext.tsx b/packages/primitives/src/components/Label/LabelContext.tsx index 9fda962d..22ca2373 100644 --- a/packages/primitives/src/components/Label/LabelContext.tsx +++ b/packages/primitives/src/components/Label/LabelContext.tsx @@ -2,6 +2,9 @@ import { createContext } from 'react'; +import type { ContextValue } from '../../utils'; + import type { LabelProps } from './index'; -export const LabelContext = createContext({}); +export const LabelContext = + createContext>(null); diff --git a/packages/primitives/src/components/Text/Text.tsx b/packages/primitives/src/components/Text/Text.tsx index 09b04c01..7fff260a 100644 --- a/packages/primitives/src/components/Text/Text.tsx +++ b/packages/primitives/src/components/Text/Text.tsx @@ -4,17 +4,17 @@ import type { ComponentPropsWithRef, ComponentRef, ElementType } from 'react'; import { polymorphicForwardRef } from '@koobiq/react-core'; -import { useSlottedContext } from '../../utils/useSlottedContext'; +import { useContextProps } from '../../utils'; import { type TextBaseProps, TextContext } from './index'; export const Text = polymorphicForwardRef<'p', TextBaseProps>((props, ref) => { - const { as: Tag = 'p', children, slot, ...other } = props; + const [ctxProps, ctxRef] = useContextProps(props, ref, TextContext); - const commonProps = useSlottedContext(other, TextContext, slot); + const { as: Tag = 'p', children, ...other } = ctxProps; return ( - + {children} ); diff --git a/packages/primitives/src/components/Text/TextContext.tsx b/packages/primitives/src/components/Text/TextContext.tsx index e285612b..86537e55 100644 --- a/packages/primitives/src/components/Text/TextContext.tsx +++ b/packages/primitives/src/components/Text/TextContext.tsx @@ -2,10 +2,10 @@ import { createContext } from 'react'; -import type { TextProps } from './Text'; +import type { ContextValue } from '../../utils'; -export type TextContextProps = { - slots?: Record; -}; +import type { TextProps } from './Text'; -export const TextContext = createContext({}); +export const TextContext = createContext>( + {} +); diff --git a/packages/primitives/src/utils/index.tsx b/packages/primitives/src/utils/index.tsx index 43e752f2..209cccd7 100644 --- a/packages/primitives/src/utils/index.tsx +++ b/packages/primitives/src/utils/index.tsx @@ -12,7 +12,12 @@ import type { DOMProps as SharedDOMProps, RefObject, } from '@koobiq/react-core'; -import { mergeProps, mergeRefs, useObjectRef } from '@koobiq/react-core'; +import { + isNotNil, + mergeProps, + mergeRefs, + useObjectRef, +} from '@koobiq/react-core'; export const DEFAULT_SLOT = Symbol('default'); @@ -179,8 +184,7 @@ export function useSlottedContext( ): T | null | undefined { const ctx = useContext(context); - if (slot === null) { - // An explicit `null` slot means don't use context. + if (!isNotNil(slot)) { return null; } diff --git a/packages/primitives/src/utils/useSlottedContext.ts b/packages/primitives/src/utils/useSlottedContext.ts deleted file mode 100644 index c30d9ec7..00000000 --- a/packages/primitives/src/utils/useSlottedContext.ts +++ /dev/null @@ -1,18 +0,0 @@ -import type { Context } from 'react'; -import { useContext } from 'react'; - -import { mergeProps } from '@koobiq/react-core'; - -// TODO: remove this and switch to useContextProps. -export function useSlottedContext< - PROPS extends object, - CONTEXT extends Context<{ slots?: Record }>, ->(props: PROPS, context: CONTEXT, slot: string | undefined): PROPS { - const slotContext = useContext(context); - - if (!slot) return props; - - const propsContext = slotContext.slots?.[slot]; - - return mergeProps(propsContext, props); -}