/**
* HTML Props for JSX Elements
*
* Based on standard HTML props but excludes event handlers since
* we use the `on` prop with the @/events package for event handling.
*/
import type { EventDescriptor } from '@remix-run/events'
import type { StyleProperties, EnhancedStyleProperties } from '@remix-run/style'
import type { Remix } from './component.ts'
declare module './component.ts' {
namespace Remix {
/**
* Get the props for a specific element type with normalized `on` prop.
*
* @example
* interface MyButtonProps extends Props<"button"> {
* size: "sm" | "md" | "lg"
* }
*
* @example
* function Button({ on = [], ...rest }: Props<"button">) {
* // on is always EventDescriptor[] here
* return
* }
*/
export type Props =
HTMLElements[T] extends HTMLProps
? NormalizeOnProp
: never
}
}
type NormalizeOnProp
= P extends { on?: any }
? { [K in keyof P as K extends 'on' ? never : K]: P[K] } & {
on?: EventDescriptor[] | undefined
}
: P
export type Booleanish = boolean | 'true' | 'false'
// WAI-ARIA 1.1 props
export interface AriaProps {
/** Identifies the currently active element when DOM focus is on a composite widget, textbox, group, or application. */
'aria-activedescendant'?: string | undefined
/** Indicates whether assistive technologies will present all, or only parts of, the changed region based on the change notifications defined by the aria-relevant attribute. */
'aria-atomic'?: Booleanish | undefined
/**
* Indicates whether inputting text could trigger display of one or more predictions of the user's intended value for an input and specifies how predictions would be
* presented if they are made.
*/
'aria-autocomplete'?: 'none' | 'inline' | 'list' | 'both' | undefined
/** Indicates an element is being modified and that assistive technologies MAY want to wait until the modifications are complete before exposing them to the user. */
'aria-busy'?: Booleanish | undefined
/**
* Indicates the current "checked" state of checkboxes, radio buttons, and other widgets.
* @see aria-pressed
* @see aria-selected
*/
'aria-checked'?: Booleanish | 'mixed' | undefined
/**
* Defines the total number of columns in a table, grid, or treegrid.
* @see aria-colindex
*/
'aria-colcount'?: number | undefined
/**
* Defines an element's column index or position with respect to the total number of columns within a table, grid, or treegrid.
* @see aria-colcount
* @see aria-colspan
*/
'aria-colindex'?: number | undefined
/**
* Defines the number of columns spanned by a cell or gridcell within a table, grid, or treegrid.
* @see aria-colindex
* @see aria-rowspan
*/
'aria-colspan'?: number | undefined
/**
* Identifies the element (or elements) whose contents or presence are controlled by the current element.
* @see aria-owns
*/
'aria-controls'?: string | undefined
/** Indicates the element that represents the current item within a container or set of related elements. */
'aria-current'?: Booleanish | 'page' | 'step' | 'location' | 'date' | 'time' | undefined
/**
* Identifies the element (or elements) that describes the object.
* @see aria-labelledby
*/
'aria-describedby'?: string | undefined
/**
* Identifies the element that provides a detailed, extended description for the object.
* @see aria-describedby
*/
'aria-details'?: string | undefined
/**
* Indicates that the element is perceivable but disabled, so it is not editable or otherwise operable.
* @see aria-hidden
* @see aria-readonly
*/
'aria-disabled'?: Booleanish | undefined
/**
* Identifies the element that provides an error message for the object.
* @see aria-invalid
* @see aria-describedby
*/
'aria-errormessage'?: string | undefined
/** Indicates whether the element, or another grouping element it controls, is currently expanded or collapsed. */
'aria-expanded'?: Booleanish | undefined
/**
* Identifies the next element (or elements) in an alternate reading order of content which, at the user's discretion,
* allows assistive technology to override the general default of reading in document source order.
*/
'aria-flowto'?: string | undefined
/** Indicates the availability and type of interactive popup element, such as menu or dialog, that can be triggered by an element. */
'aria-haspopup'?: Booleanish | 'menu' | 'listbox' | 'tree' | 'grid' | 'dialog' | undefined
/**
* Indicates whether the element is exposed to an accessibility API.
* @see aria-disabled
*/
'aria-hidden'?: Booleanish | undefined
/**
* Indicates the entered value does not conform to the format expected by the application.
* @see aria-errormessage
*/
'aria-invalid'?: Booleanish | 'grammar' | 'spelling' | undefined
/** Indicates keyboard shortcuts that an author has implemented to activate or give focus to an element. */
'aria-keyshortcuts'?: string | undefined
/**
* Defines a string value that labels the current element.
* @see aria-labelledby
*/
'aria-label'?: string | undefined
/**
* Identifies the element (or elements) that labels the current element.
* @see aria-describedby
*/
'aria-labelledby'?: string | undefined
/** Defines the hierarchical level of an element within a structure. */
'aria-level'?: number | undefined
/** Indicates that an element will be updated, and describes the types of updates the user agents, assistive technologies, and user can expect from the live region. */
'aria-live'?: 'off' | 'assertive' | 'polite' | undefined
/** Indicates whether an element is modal when displayed. */
'aria-modal'?: Booleanish | undefined
/** Indicates whether a text box accepts multiple lines of input or only a single line. */
'aria-multiline'?: Booleanish | undefined
/** Indicates that the user may select more than one item from the current selectable descendants. */
'aria-multiselectable'?: Booleanish | undefined
/** Indicates whether the element's orientation is horizontal, vertical, or unknown/ambiguous. */
'aria-orientation'?: 'horizontal' | 'vertical' | undefined
/**
* Identifies an element (or elements) in order to define a visual, functional, or contextual parent/child relationship
* between DOM elements where the DOM hierarchy cannot be used to represent the relationship.
* @see aria-controls
*/
'aria-owns'?: string | undefined
/**
* Defines a short hint (a word or short phrase) intended to aid the user with data entry when the control has no value.
* A hint could be a sample value or a brief description of the expected format.
*/
'aria-placeholder'?: string | undefined
/**
* Defines an element's number or position in the current set of listitems or treeitems. Not required if all elements in the set are present in the DOM.
* @see aria-setsize
*/
'aria-posinset'?: number | undefined
/**
* Indicates the current "pressed" state of toggle buttons.
* @see aria-checked
* @see aria-selected
*/
'aria-pressed'?: Booleanish | 'mixed' | undefined
/**
* Indicates that the element is not editable, but is otherwise operable.
* @see aria-disabled
*/
'aria-readonly'?: Booleanish | undefined
/**
* Indicates what notifications the user agent will trigger when the accessibility tree within a live region is modified.
* @see aria-atomic
*/
'aria-relevant'?:
| 'additions'
| 'additions removals'
| 'additions text'
| 'all'
| 'removals'
| 'removals additions'
| 'removals text'
| 'text'
| 'text additions'
| 'text removals'
| undefined
/** Indicates that user input is required on the element before a form may be submitted. */
'aria-required'?: Booleanish | undefined
/** Defines a human-readable, author-localized description for the role of an element. */
'aria-roledescription'?: string | undefined
/**
* Defines the total number of rows in a table, grid, or treegrid.
* @see aria-rowindex
*/
'aria-rowcount'?: number | undefined
/**
* Defines an element's row index or position with respect to the total number of rows within a table, grid, or treegrid.
* @see aria-rowcount
* @see aria-rowspan
*/
'aria-rowindex'?: number | undefined
/**
* Defines the number of rows spanned by a cell or gridcell within a table, grid, or treegrid.
* @see aria-rowindex
* @see aria-colspan
*/
'aria-rowspan'?: number | undefined
/**
* Indicates the current "selected" state of various widgets.
* @see aria-checked
* @see aria-pressed
*/
'aria-selected'?: Booleanish | undefined
/**
* Defines the number of items in the current set of listitems or treeitems. Not required if all elements in the set are present in the DOM.
* @see aria-posinset
*/
'aria-setsize'?: number | undefined
/** Indicates if items in a table or grid are sorted in ascending or descending order. */
'aria-sort'?: 'none' | 'ascending' | 'descending' | 'other' | undefined
/** Defines the maximum allowed value for a range widget. */
'aria-valuemax'?: number | undefined
/** Defines the minimum allowed value for a range widget. */
'aria-valuemin'?: number | undefined
/**
* Defines the current value for a range widget.
* @see aria-valuetext
*/
'aria-valuenow'?: number | undefined
/** Defines the human readable text alternative of aria-valuenow for a range widget. */
'aria-valuetext'?: string | undefined
}
// WAI-ARIA 1.2 role prop values
export type AriaRole =
| 'alert'
| 'alertdialog'
| 'application'
| 'article'
| 'banner'
| 'blockquote'
| 'button'
| 'caption'
| 'cell'
| 'checkbox'
| 'code'
| 'columnheader'
| 'combobox'
| 'command'
| 'complementary'
| 'composite'
| 'contentinfo'
| 'definition'
| 'deletion'
| 'dialog'
| 'directory'
| 'document'
| 'emphasis'
| 'feed'
| 'figure'
| 'form'
| 'grid'
| 'gridcell'
| 'group'
| 'heading'
| 'img'
| 'input'
| 'insertion'
| 'landmark'
| 'link'
| 'list'
| 'listbox'
| 'listitem'
| 'log'
| 'main'
| 'marquee'
| 'math'
| 'meter'
| 'menu'
| 'menubar'
| 'menuitem'
| 'menuitemcheckbox'
| 'menuitemradio'
| 'navigation'
| 'none'
| 'note'
| 'option'
| 'paragraph'
| 'presentation'
| 'progressbar'
| 'radio'
| 'radiogroup'
| 'range'
| 'region'
| 'roletype'
| 'row'
| 'rowgroup'
| 'rowheader'
| 'scrollbar'
| 'search'
| 'searchbox'
| 'section'
| 'sectionhead'
| 'select'
| 'separator'
| 'slider'
| 'spinbutton'
| 'status'
| 'strong'
| 'structure'
| 'subscript'
| 'superscript'
| 'switch'
| 'tab'
| 'table'
| 'tablist'
| 'tabpanel'
| 'term'
| 'textbox'
| 'time'
| 'timer'
| 'toolbar'
| 'tooltip'
| 'tree'
| 'treegrid'
| 'treeitem'
| 'widget'
| 'window'
| 'none presentation'
/**
* Base props that all HTML elements have
*/
export interface HTMLProps extends AriaProps {
key?: Remix.Key | undefined
accessKey?: string | undefined
children?: Remix.RemixNode | Remix.RemixNode[] | undefined
autoCapitalize?: 'off' | 'none' | 'on' | 'sentences' | 'words' | 'characters' | undefined
class?: string | undefined
autoCorrect?: string | undefined
for?: string | undefined
autoFocus?: boolean | undefined
className?: string | undefined
contentEditable?: Booleanish | '' | 'plaintext-only' | 'inherit' | undefined
dir?: 'auto' | 'rtl' | 'ltr' | undefined
draggable?: boolean | undefined
enterKeyHint?: 'enter' | 'done' | 'go' | 'next' | 'previous' | 'search' | 'send' | undefined
hidden?: boolean | 'hidden' | 'until-found' | 'true' | 'false' | string | undefined
id?: string | undefined
inert?: boolean | undefined
innerHTML?: string | undefined
inputMode?: string | undefined
lang?: string | undefined
nonce?: string | undefined
ref?: ((node: Target) => void) | undefined
role?: AriaRole | undefined
spellCheck?: boolean | undefined
// Inline style: directly applied to DOM element via el.style.* or as a string attribute
style?:
| StyleProperties
| string
| {
[key: string]: string | number | boolean | (string | number)[] | null | undefined
[key: `--${string}`]: string | number | null | undefined
}
| undefined
// Class-based CSS-in-JS: processed to rmx-* class names and style tags
css?: EnhancedStyleProperties | undefined
tabIndex?: number | string | undefined
title?: string | undefined
translate?: boolean | undefined
on?: EventDescriptor | EventDescriptor[] | undefined
popover?: 'auto' | 'manual' | boolean | undefined
popovertarget?: string | undefined
// Data attributes
[key: `data-${string}`]: string | number | boolean | undefined
}
/**
* Props for elements
*/
export interface HTMLAnchorProps
extends HTMLProps {
download?: any
href?: string | undefined
hrefLang?: string | undefined
media?: string | undefined
ping?: string | undefined
rel?: string | undefined
target?: '_self' | '_blank' | '_parent' | '_top' | (string & {}) | undefined
type?: string | undefined
referrerPolicy?:
| 'no-referrer'
| 'no-referrer-when-downgrade'
| 'origin'
| 'origin-when-cross-origin'
| 'same-origin'
| 'strict-origin'
| 'strict-origin-when-cross-origin'
| 'unsafe-url'
| undefined
}
/**
* Props for elements
*/
export interface HTMLAreaProps
extends HTMLProps {
alt?: string | undefined
coords?: string | undefined
download?: any
href?: string | undefined
hrefLang?: string | undefined
media?: string | undefined
referrerPolicy?:
| 'no-referrer'
| 'no-referrer-when-downgrade'
| 'origin'
| 'origin-when-cross-origin'
| 'same-origin'
| 'strict-origin'
| 'strict-origin-when-cross-origin'
| 'unsafe-url'
| undefined
rel?: string | undefined
shape?: string | undefined
target?: '_self' | '_blank' | '_parent' | '_top' | (string & {}) | undefined
}
/**
* Props for