Skip to content

Commit

Permalink
Simplify props types
Browse files Browse the repository at this point in the history
wip
  • Loading branch information
thecrypticace committed Jun 21, 2024
1 parent d60ed6a commit 1dca656
Show file tree
Hide file tree
Showing 10 changed files with 25 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1573,7 +1573,7 @@ export type ComboboxOptionsProps<TTag extends ElementType = typeof DEFAULT_OPTIO
TTag,
OptionsRenderPropArg,
OptionsPropsWeControl,
PropsForFeatures<typeof OptionsRenderFeatures> & {
PropsForFeatures<'all'> & {
hold?: boolean
anchor?: AnchorProps
portal?: boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ export type DialogProps<TTag extends ElementType = typeof DEFAULT_DIALOG_TAG> =
TTag,
DialogRenderPropArg,
DialogPropsWeControl,
PropsForFeatures<typeof DialogRenderFeatures> & {
PropsForFeatures<'all'> & {
open?: boolean
onClose(value: boolean): void
initialFocus?: MutableRefObject<HTMLElement | null>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,7 @@ export type DisclosurePanelProps<TTag extends ElementType = typeof DEFAULT_PANEL
TTag,
PanelRenderPropArg,
DisclosurePanelPropsWeControl,
{ transition?: boolean } & PropsForFeatures<typeof PanelRenderFeatures>
{ transition?: boolean } & PropsForFeatures<'all'>
>

function PanelFn<TTag extends ElementType = typeof DEFAULT_PANEL_TAG>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -890,7 +890,7 @@ export type ListboxOptionsProps<TTag extends ElementType = typeof DEFAULT_OPTION
portal?: boolean
modal?: boolean
transition?: boolean
} & PropsForFeatures<typeof OptionsRenderFeatures>
} & PropsForFeatures<'all'>
>

function OptionsFn<TTag extends ElementType = typeof DEFAULT_OPTIONS_TAG>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -741,7 +741,7 @@ export type PopoverBackdropProps<TTag extends ElementType = typeof DEFAULT_BACKD
TTag,
BackdropRenderPropArg,
BackdropPropsWeControl,
{ transition?: boolean } & PropsForFeatures<typeof BackdropRenderFeatures>
{ transition?: boolean } & PropsForFeatures<'all'>
>

export type PopoverOverlayProps<TTag extends ElementType = typeof DEFAULT_BACKDROP_TAG> =
Expand Down
2 changes: 1 addition & 1 deletion packages/@headlessui-react/src/components/tabs/tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -610,7 +610,7 @@ export type TabPanelProps<TTag extends ElementType = typeof DEFAULT_PANEL_TAG> =
TTag,
PanelRenderPropArg,
PanelPropsWeControl,
PropsForFeatures<typeof PanelRenderFeatures> & { id?: string; tabIndex?: number }
PropsForFeatures<'all'> & { id?: string; tabIndex?: number }
>

function PanelFn<TTag extends ElementType = typeof DEFAULT_PANEL_TAG>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,7 @@ export type TooltipPanelProps<TTag extends ElementType = typeof DEFAULT_PANEL_TA
TTag,
PanelRenderPropArg,
PanelPropsWeControl,
{ anchor?: AnchorProps } & PropsForFeatures<typeof PanelRenderFeatures>
{ anchor?: AnchorProps } & PropsForFeatures<'all'>
>

function PanelFn<TTag extends ElementType = typeof DEFAULT_PANEL_TAG>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ export type TransitionChildProps<TTag extends ReactTag> = Props<
TTag,
TransitionChildRenderPropArg,
TransitionChildPropsWeControl,
PropsForFeatures<typeof TransitionChildRenderFeatures> &
PropsForFeatures<'unmount'> &
TransitionClasses &
TransitionEvents & { transition?: boolean; appear?: boolean }
>
Expand Down Expand Up @@ -318,7 +318,6 @@ function TransitionChildFn<TTag extends ElementType = typeof DEFAULT_TRANSITION_
leaveFrom,
leaveTo,

// @ts-expect-error
...theirProps
} = props as typeof props
let container = useRef<HTMLElement | null>(null)
Expand Down Expand Up @@ -444,6 +443,8 @@ function TransitionChildFn<TTag extends ElementType = typeof DEFAULT_TRANSITION_
className:
classNames(
// Incoming classes if any
// @ts-expect-error: className may not exist because not
// all components accept className (but all HTML elements do)
theirProps.className,

// Apply these classes immediately
Expand Down Expand Up @@ -498,7 +499,6 @@ function TransitionRootFn<TTag extends ElementType = typeof DEFAULT_TRANSITION_C
props: TransitionRootProps<TTag>,
ref: Ref<HTMLElement>
) {
// @ts-expect-error
let { show, appear = false, unmount = true, ...theirProps } = props as typeof props
let internalTransitionRef = useRef<HTMLElement | null>(null)
let requiresRef = shouldForwardRef(props)
Expand Down Expand Up @@ -610,10 +610,8 @@ function ChildFn<TTag extends ElementType = typeof DEFAULT_TRANSITION_CHILD_TAG>
return (
<>
{!hasTransitionContext && hasOpenClosedContext ? (
// @ts-expect-error This is an object
<TransitionRoot ref={ref} {...props} />
) : (
// @ts-expect-error This is an object
<InternalTransitionChild ref={ref} {...props} />
)}
</>
Expand Down
6 changes: 3 additions & 3 deletions packages/@headlessui-react/src/utils/render.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ describe('Features.Static', () => {
let slot = {}
let EnabledFeatures = RenderFeatures.Static
function Dummy<TTag extends ElementType = 'div'>(
props: Expand<Props<TTag> & PropsForFeatures<typeof EnabledFeatures>> & { show: boolean }
props: Expand<Props<TTag> & PropsForFeatures<'static'>> & { show: boolean }
) {
let { show, ...rest } = props
return (
Expand Down Expand Up @@ -377,7 +377,7 @@ describe('Features.RenderStrategy', () => {
let slot = {}
let EnabledFeatures = RenderFeatures.RenderStrategy
function Dummy<TTag extends ElementType = 'div'>(
props: Expand<Props<TTag> & PropsForFeatures<typeof EnabledFeatures>> & { show: boolean }
props: Expand<Props<TTag> & PropsForFeatures<'unmount'>> & { show: boolean }
) {
let { show, ...rest } = props
return (
Expand Down Expand Up @@ -405,7 +405,7 @@ describe('Features.Static | Features.RenderStrategy', () => {
let slot = {}
let EnabledFeatures = RenderFeatures.Static | RenderFeatures.RenderStrategy
function Dummy<TTag extends ElementType = 'div'>(
props: Expand<Props<TTag> & PropsForFeatures<typeof EnabledFeatures>> & { show: boolean }
props: Expand<Props<TTag> & PropsForFeatures<'all'>> & { show: boolean }
) {
let { show, ...rest } = props
return (
Expand Down
27 changes: 12 additions & 15 deletions packages/@headlessui-react/src/utils/render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
type ReactElement,
type Ref,
} from 'react'
import type { Expand, Props, XOR, __ } from '../types'
import type { Expand, Props } from '../types'
import { classNames } from './class-names'
import { match } from './match'

Expand Down Expand Up @@ -40,18 +40,15 @@ export enum RenderStrategy {
Hidden,
}

type PropsForFeature<
TPassedInFeatures extends RenderFeatures,
TForFeature extends RenderFeatures,
TProps,
> = {
[P in TPassedInFeatures]: P extends TForFeature ? TProps : __
}[TPassedInFeatures]
type FeatureCollection = 'all' | 'static' | 'unmount'

export type PropsForFeatures<T extends RenderFeatures> = XOR<
PropsForFeature<T, RenderFeatures.Static, { static?: boolean }>,
PropsForFeature<T, RenderFeatures.RenderStrategy, { unmount?: boolean }>
>
export type PropsForFeatures<T extends FeatureCollection> = T extends 'all'
? { unmount?: boolean; static?: never } | { static?: boolean; unmount?: never }
: T extends 'static'
? { static?: boolean }
: T extends 'unmount'
? { unmount?: boolean }
: {}

export function render<TFeature extends RenderFeatures, TTag extends ElementType, TSlot>({
ourProps,
Expand All @@ -63,7 +60,7 @@ export function render<TFeature extends RenderFeatures, TTag extends ElementType
name,
mergeRefs,
}: {
ourProps: Expand<Props<TTag, TSlot, any> & PropsForFeatures<TFeature>> & {
ourProps: Expand<Props<TTag, TSlot, any> & PropsForFeatures<'all'>> & {
ref?: Ref<HTMLElement | ElementType>
}
theirProps: Expand<Props<TTag, TSlot, any>>
Expand All @@ -84,14 +81,14 @@ export function render<TFeature extends RenderFeatures, TTag extends ElementType
let featureFlags = features ?? RenderFeatures.None

if (featureFlags & RenderFeatures.Static) {
let { static: isStatic = false, ...rest } = props as PropsForFeatures<RenderFeatures.Static>
let { static: isStatic = false, ...rest } = props as PropsForFeatures<'static'>

// When the `static` prop is passed as `true`, then the user is in control, thus we don't care about anything else
if (isStatic) return _render(rest, slot, defaultTag, name, mergeRefs)
}

if (featureFlags & RenderFeatures.RenderStrategy) {
let { unmount = true, ...rest } = props as PropsForFeatures<RenderFeatures.RenderStrategy>
let { unmount = true, ...rest } = props as PropsForFeatures<'unmount'>
let strategy = unmount ? RenderStrategy.Unmount : RenderStrategy.Hidden

return match(strategy, {
Expand Down

0 comments on commit 1dca656

Please sign in to comment.