import type {
FrontendHTMLTag,
FrontendStaticConfig,
} from '@tamagui/core/internal-runtime'
import type {
AriaAttributes,
ComponentPropsWithoutRef,
CSSProperties,
FunctionComponent,
HTMLAttributes,
ReactElement,
ReactNode,
Ref as ReactRef,
} from 'react'
import type {
PressableProps,
StyleProp,
TextInstance as ReactNativeText,
TextProps as ReactNativeTextProps,
TextStyle,
ViewInstance as ReactNativeView,
ViewProps as ReactNativeViewProps,
ViewStyle,
} from '@tamagui/react-native-types'
type WebEventProps = {
onMouseEnter?: HTMLAttributes['onMouseEnter']
onMouseLeave?: HTMLAttributes['onMouseLeave']
onMouseDown?: HTMLAttributes['onMouseDown']
onMouseUp?: HTMLAttributes['onMouseUp']
onMouseMove?: HTMLAttributes['onMouseMove']
onMouseOver?: HTMLAttributes['onMouseOver']
onMouseOut?: HTMLAttributes['onMouseOut']
onFocus?: HTMLAttributes['onFocus']
onBlur?: HTMLAttributes['onBlur']
onClick?: HTMLAttributes['onClick']
onDoubleClick?: HTMLAttributes['onDoubleClick']
onContextMenu?: HTMLAttributes['onContextMenu']
onWheel?: HTMLAttributes['onWheel']
onKeyDown?: HTMLAttributes['onKeyDown']
onKeyUp?: HTMLAttributes['onKeyUp']
onChange?: HTMLAttributes['onChange']
onInput?: HTMLAttributes['onInput']
onBeforeInput?: HTMLAttributes['onBeforeInput']
onScroll?: HTMLAttributes['onScroll']
onCopy?: HTMLAttributes['onCopy']
onCut?: HTMLAttributes['onCut']
onPaste?: HTMLAttributes['onPaste']
onDrag?: HTMLAttributes['onDrag']
onDragStart?: HTMLAttributes['onDragStart']
onDragEnd?: HTMLAttributes['onDragEnd']
onDragEnter?: HTMLAttributes['onDragEnter']
onDragLeave?: HTMLAttributes['onDragLeave']
onDragOver?: HTMLAttributes['onDragOver']
onDrop?: HTMLAttributes['onDrop']
onPointerDown?: HTMLAttributes['onPointerDown']
onPointerMove?: HTMLAttributes['onPointerMove']
onPointerUp?: HTMLAttributes['onPointerUp']
onPointerCancel?: HTMLAttributes['onPointerCancel']
}
type TailwindComponentState = {
unmounted: boolean | 'should-enter'
disabled?: boolean
hover?: boolean
press?: boolean
pressIn?: boolean
focus?: boolean
focusVisible?: boolean
focusWithin?: boolean
}
type TailwindCommonProps = AriaAttributes &
WebEventProps & {
target?: string
htmlFor?: string
asChild?: boolean | 'except-style' | 'except-style-web' | 'web'
dangerouslySetInnerHTML?: { __html: string }
children?: ReactNode
debug?: boolean | 'break' | 'verbose' | 'visualize' | 'profile'
disabled?: boolean
themeShallow?: boolean
id?: string
render?:
| keyof HTMLElementTagNameMap
| (string & {})
| ReactElement
| ((
props: Record & { ref?: ReactRef },
state: TailwindComponentState
) => ReactElement)
theme?: string | null
group?: string | boolean
container?: boolean | string
untilMeasured?: 'hide' | 'show'
name?: string
tabIndex?: string | number
role?: HTMLAttributes['role']
disableOptimization?: boolean
forceStyle?: 'hover' | 'press' | 'focus' | 'focusVisible' | 'focusWithin'
disableClassName?: boolean
hitSlop?:
| number
| { top?: number; left?: number; bottom?: number; right?: number }
| null
animatedBy?: string | null
onPress?: PressableProps['onPress']
onLongPress?: PressableProps['onLongPress']
onPressIn?: PressableProps['onPress']
onPressOut?: PressableProps['onPress']
}
type LooseCombinedObjects = A | B | (A & B)
export type TailwindViewNonStyleProps = Omit<
ReactNativeViewProps,
'children' | 'display' | 'hitSlop' | 'pointerEvents' | 'style' | keyof WebEventProps
> &
TailwindCommonProps & {
style?: StyleProp>
}
export type TailwindTextNonStyleProps = Omit<
ReactNativeTextProps,
'children' | 'style' | keyof WebEventProps
> &
TailwindCommonProps & {
style?: StyleProp>
}
type MeasureOnSuccessCallback = (
x: number,
y: number,
width: number,
height: number,
pageX: number,
pageY: number
) => void
export interface TailwindElementMethods {
measure(callback: MeasureOnSuccessCallback): void
measureInWindow(
callback: (x: number, y: number, width: number, height: number) => void
): void
measureLayout(
relativeToNativeNode: ReactNativeView | HTMLElement,
onSuccess: (left: number, top: number, width: number, height: number) => void,
onFail?: () => void
): void
focus(): void
blur(): void
}
export type TailwindViewElement = (HTMLElement & TailwindElementMethods) | ReactNativeView
export type TailwindTextElement = (HTMLElement & TailwindElementMethods) | ReactNativeText
/**
* The complete styling surface of a `@tamagui/tailwind` component.
*
* Everything else a component accepts is ordinary behavior: children, refs,
* accessibility, events, ids, and the raw platform `style` escape hatch, all
* inherited from the shared non-style prop types. Tamagui inline style props
* (`padding`, `bg`, shorthands, state/media clauses, theme style props) are
* deliberately absent — that authoring syntax belongs to `@tamagui/core`.
*/
export type TailwindStyleProps = {
className?: string
}
/** `true`/`false` matchers become a boolean prop; every other matcher is its own literal. */
type VariantAcceptedValue = Key extends 'true' | 'false' ? boolean : Key
/**
* Finite variant inference: one optional prop per variant, accepting exactly the
* matchers that variant declares. It never reaches core's style prop graph.
*/
export type TailwindVariantProps = Variants extends object
? {
[Key in keyof Variants]?: VariantAcceptedValue
}
: {}
/** Variant values are class strings — the same authoring syntax as `className`. */
export type TailwindVariantDefinitions = {
[variantName: string]: { [matcher: string]: string }
}
export type TailwindStyledOptions = {
displayName?: string
variants?: Variants
defaultVariants?: TailwindVariantProps
}
export interface TailwindComponent<
Ref = any,
NonStyleProps = {},
VariantProps = {},
> extends FunctionComponent<
NonStyleProps & TailwindStyleProps & VariantProps & { ref?: ReactRef[ }
> {
staticConfig: FrontendStaticConfig
/** phantom carrier so `styled()` can recover the parts of a parent component */
__tailwind?: { ref: Ref; props: NonStyleProps; variants: VariantProps }
}
export type GetTailwindRef =
Component extends TailwindComponent ? Ref : any
export type GetTailwindNonStyleProps =
Component extends TailwindComponent ? Props : {}
export type GetTailwindVariantProps =
Component extends TailwindComponent ? Variants : {}
export type TailwindView = TailwindComponent<
TailwindViewElement,
TailwindViewNonStyleProps
>
export type TailwindText = TailwindComponent<
TailwindTextElement,
TailwindTextNonStyleProps
>
export type TailwindViewProps = TailwindViewNonStyleProps & TailwindStyleProps
export type TailwindTextProps = TailwindTextNonStyleProps & TailwindStyleProps
/**
* One tag's props: the element's own DOM contract plus the shared Tamagui
* behavior props, with `className` the only styling input. Tamagui non-style
* props win where both name the same thing, matching the regular `html`.
*/
type TailwindHTMLProps = Omit<
ComponentPropsWithoutRef,
'className' | 'style' | keyof TailwindCommonProps
> &
TailwindCommonProps & {
style?: StyleProp>
}
/**
* The semantic elements, authored in Tailwind classes. Same tags and same
* element defaults as `html` from `tamagui`; only the styling syntax differs.
*/
export type TailwindHTML = {
[Tag in FrontendHTMLTag]: TailwindComponent<
HTMLElementTagNameMap[Tag],
TailwindHTMLProps
>
}
]