|
| 1 | +import * as React from 'react' |
| 2 | +import { StyledComponent } from '@emotion/styled' |
| 3 | +import { InterpolationWithTheme } from '@emotion/core' |
| 4 | +import { SpaceProps, ColorProps, MarginProps } from 'styled-system' |
| 5 | +import { ResponsiveStyleValue } from '@theme-ui/css' |
| 6 | + |
| 7 | +type Omit<T, K> = Pick<T, Exclude<keyof T, K>> |
| 8 | + |
| 9 | +type Assign<T, U> = { |
| 10 | + [P in keyof (T & U)]: P extends keyof T |
| 11 | + ? T[P] |
| 12 | + : P extends keyof U |
| 13 | + ? U[P] |
| 14 | + : never |
| 15 | +} |
| 16 | + |
| 17 | +type ForwardRef<T, P> = React.ForwardRefExoticComponent< |
| 18 | + React.PropsWithoutRef<P> & React.RefAttributes<T> |
| 19 | +> |
| 20 | + |
| 21 | +export interface BoxOwnProps extends SpaceProps, ColorProps { |
| 22 | + as?: React.ElementType |
| 23 | + variant?: string |
| 24 | + css?: InterpolationWithTheme<any> |
| 25 | +} |
| 26 | +export interface BoxProps |
| 27 | + extends Assign<React.ComponentProps<'div'>, BoxOwnProps> {} |
| 28 | +/** |
| 29 | + * Use the Box component as a layout primitive to add margin, padding, and colors to content. |
| 30 | + * @see https://theme-ui.com/components/box |
| 31 | + */ |
| 32 | +export const Box: StyledComponent<React.ComponentProps<'div'>, BoxOwnProps, {}> |
| 33 | + |
| 34 | +export type FlexStyleProps = BoxOwnProps |
| 35 | +export type FlexProps = BoxProps |
| 36 | +/** |
| 37 | + * Use the Flex component to create flexbox layouts. |
| 38 | + * @see https://theme-ui.com/components/flex |
| 39 | + */ |
| 40 | +export const Flex: StyledComponent< |
| 41 | + React.ComponentProps<'div'>, |
| 42 | + FlexStyleProps, |
| 43 | + {} |
| 44 | +> |
| 45 | + |
| 46 | +export interface GridProps extends BoxProps { |
| 47 | + /** |
| 48 | + * Minimum width of child elements |
| 49 | + */ |
| 50 | + width?: ResponsiveStyleValue<string | number> |
| 51 | + /** |
| 52 | + * Number of columns to use for the layout (cannot be used in conjunction with the width prop) |
| 53 | + */ |
| 54 | + columns?: ResponsiveStyleValue<string | number> |
| 55 | + /** |
| 56 | + * Space between child elements |
| 57 | + */ |
| 58 | + gap?: ResponsiveStyleValue<string | number> |
| 59 | +} |
| 60 | +/** |
| 61 | + * CSS grid layout component to arrange direct child elements in a tiled grid layout. |
| 62 | + * @see https://theme-ui.com/components/grid |
| 63 | + */ |
| 64 | +export const Grid: ForwardRef<HTMLDivElement, GridProps> |
| 65 | + |
| 66 | +export interface ButtonProps |
| 67 | + extends Assign<React.ComponentPropsWithRef<'button'>, BoxOwnProps> {} |
| 68 | +/** |
| 69 | + * Primitive button component with variants |
| 70 | + * @see https://theme-ui.com/components/button |
| 71 | + */ |
| 72 | +export const Button: ForwardRef<HTMLButtonElement, ButtonProps> |
| 73 | + |
| 74 | +export interface LinkProps |
| 75 | + extends Assign<React.ComponentPropsWithRef<'a'>, BoxOwnProps> {} |
| 76 | +/** |
| 77 | + * Link variants can be defined in the `theme.links` object. |
| 78 | + * By default the Link component will use styles defined in `theme.styles.a`. |
| 79 | + * @see https://theme-ui.com/components/link |
| 80 | + */ |
| 81 | +export const Link: ForwardRef<HTMLAnchorElement, LinkProps> |
| 82 | + |
| 83 | +export type TextProps = BoxProps |
| 84 | +/** |
| 85 | + * Primitive typographic component. |
| 86 | + * |
| 87 | + * Text style variants can be defined in the theme.text object. |
| 88 | + * @see https://theme-ui.com/components/text |
| 89 | + */ |
| 90 | +export const Text: ForwardRef<HTMLDivElement, BoxProps> |
| 91 | + |
| 92 | +export interface HeadingProps |
| 93 | + extends Assign<React.ComponentPropsWithRef<'h2'>, BoxOwnProps> {} |
| 94 | +/** |
| 95 | + * Primitive heading component, defaults to <h2>. |
| 96 | + * |
| 97 | + * Text style variants can be defined in the theme.text object. |
| 98 | + * The Heading component uses theme.text.heading as its default variant style. |
| 99 | + * @see https://theme-ui.com/components/heading |
| 100 | + */ |
| 101 | +export const Heading: ForwardRef<HTMLHeadingElement, HeadingProps> |
| 102 | + |
| 103 | +export interface ImageProps |
| 104 | + extends Assign<React.ComponentProps<'img'>, BoxOwnProps> {} |
| 105 | +/** |
| 106 | + * Image style variants can be defined in the theme.images object. |
| 107 | + * @see https://theme-ui.com/components/image/ |
| 108 | + */ |
| 109 | +export const Image: ForwardRef<HTMLImageElement, ImageProps> |
| 110 | + |
| 111 | +export type CardProps = BoxProps |
| 112 | +/** |
| 113 | + * Card style variants can be defined in the `theme.cards` object. |
| 114 | + * By default the Card component uses the `theme.cards.primary` variant. |
| 115 | + * @see https://theme-ui.com/components/card |
| 116 | + */ |
| 117 | +export const Card: ForwardRef<HTMLDivElement, CardProps> |
| 118 | + |
| 119 | +export interface LabelProps |
| 120 | + extends Assign<React.ComponentProps<'label'>, BoxOwnProps> {} |
| 121 | +/** |
| 122 | + * Label variants can be defined in `theme.forms` |
| 123 | + * and the component uses the `theme.forms.label` variant by default. |
| 124 | + * @see https://theme-ui.com/components/label/ |
| 125 | + */ |
| 126 | +export const Label: ForwardRef<HTMLLabelElement, LabelProps> |
| 127 | + |
| 128 | +export interface InputProps |
| 129 | + extends Assign<React.ComponentProps<'input'>, BoxOwnProps> {} |
| 130 | +/** |
| 131 | + * Input variants can be defined in `theme.forms` |
| 132 | + * and the component uses the `theme.forms.input` variant by default. |
| 133 | + * @see https://theme-ui.com/components/input/ |
| 134 | + */ |
| 135 | +export const Input: ForwardRef<HTMLInputElement, InputProps> |
| 136 | + |
| 137 | +export interface SelectProps |
| 138 | + extends Assign<React.ComponentProps<'select'>, BoxOwnProps> {} |
| 139 | +/** |
| 140 | + * Select variants can be defined in `theme.forms` |
| 141 | + * and the component uses the `theme.forms.select` variant by default. |
| 142 | + * @see https://theme-ui.com/components/select/ |
| 143 | + */ |
| 144 | +export const Select: ForwardRef<HTMLSelectElement, SelectProps> |
| 145 | + |
| 146 | +export interface TextareaProps |
| 147 | + extends Assign<React.ComponentProps<'textarea'>, BoxOwnProps> {} |
| 148 | +/** |
| 149 | + * Form textarea component |
| 150 | + * |
| 151 | + * Textarea variants can be defined in `theme.forms` |
| 152 | + * and the component uses the `theme.forms.textarea` variant by default. |
| 153 | + * @see https://theme-ui.com/components/textarea/ |
| 154 | + */ |
| 155 | +export const Textarea: ForwardRef<HTMLTextAreaElement, TextareaProps> |
| 156 | + |
| 157 | +export interface RadioProps |
| 158 | + extends Assign<React.ComponentProps<'input'>, BoxOwnProps> {} |
| 159 | +/** |
| 160 | + * Form radio input component |
| 161 | + * |
| 162 | + * Radio variants can be defined in `theme.forms` and the |
| 163 | + * component uses the `theme.forms.radio variant` by default. |
| 164 | + * @see https://theme-ui.com/components/radio/ |
| 165 | + */ |
| 166 | +export const Radio: ForwardRef<HTMLInputElement, RadioProps> |
| 167 | + |
| 168 | +export interface CheckboxProps |
| 169 | + extends Assign<React.ComponentProps<'input'>, BoxOwnProps> {} |
| 170 | +/** |
| 171 | + * Form checkbox input component |
| 172 | + * |
| 173 | + * Checkbox variants can be defined in `theme.forms` and the |
| 174 | + * component uses the `theme.forms.checkbox` variant by default. |
| 175 | + * @see https://theme-ui.com/components/checkbox/ |
| 176 | + */ |
| 177 | +export const Checkbox: ForwardRef<HTMLInputElement, CheckboxProps> |
| 178 | + |
| 179 | +export interface SliderProps |
| 180 | + extends Assign<React.ComponentProps<'input'>, BoxOwnProps> {} |
| 181 | +/** |
| 182 | + * Range input element |
| 183 | + * |
| 184 | + * Slider variants can be defined in the `theme.forms` object. |
| 185 | + * The Slider component uses `theme.forms.slider` as its default variant style. |
| 186 | + * @see https://theme-ui.com/components/slider/ |
| 187 | + */ |
| 188 | +export const Slider: ForwardRef<HTMLInputElement, SliderProps> |
| 189 | + |
| 190 | +export interface FieldOwnProps extends MarginProps { |
| 191 | + /** |
| 192 | + * Text for Label component |
| 193 | + */ |
| 194 | + label: string |
| 195 | + /** |
| 196 | + * Used for the for, id, and name attributes |
| 197 | + */ |
| 198 | + name: string |
| 199 | +} |
| 200 | +export type FieldProps<T extends React.ElementType> = FieldOwnProps & |
| 201 | + Omit<React.ComponentProps<T>, 'as' | keyof FieldOwnProps> & { |
| 202 | + /** |
| 203 | + * form control to render, default Input |
| 204 | + */ |
| 205 | + as?: T |
| 206 | + } |
| 207 | + |
| 208 | +// `T` is far from unnecessary. We derive component props from it. |
| 209 | +// tslint:disable-next-line no-unnecessary-generics |
| 210 | +export function Field< |
| 211 | + T extends React.ElementType = React.ElementType<InputProps> |
| 212 | +>(props: FieldProps<T>): JSX.Element |
| 213 | + |
| 214 | +export interface ProgressProps |
| 215 | + extends Assign<React.ComponentProps<'progress'>, BoxOwnProps> {} |
| 216 | +/** |
| 217 | + * @see https://theme-ui.com/components/progress/ |
| 218 | + */ |
| 219 | +export const Progress: ForwardRef<HTMLProgressElement, ProgressProps> |
| 220 | + |
| 221 | +export interface DonutProps |
| 222 | + extends Omit< |
| 223 | + React.SVGProps<SVGSVGElement>, |
| 224 | + 'opacity' | 'color' | 'css' | 'sx' | 'max' | 'min' |
| 225 | + >, |
| 226 | + BoxOwnProps { |
| 227 | + value: number |
| 228 | + min?: number |
| 229 | + max?: number |
| 230 | + title?: string |
| 231 | + size?: string | number |
| 232 | +} |
| 233 | +/** |
| 234 | + * Single value SVG donut chart |
| 235 | + * @see https://theme-ui.com/components/donut/ |
| 236 | + */ |
| 237 | +export const Donut: ForwardRef<SVGSVGElement, DonutProps> |
| 238 | + |
| 239 | +export interface SpinnerProps |
| 240 | + extends Omit< |
| 241 | + React.SVGProps<SVGSVGElement>, |
| 242 | + 'opacity' | 'color' | 'css' | 'sx' |
| 243 | + >, |
| 244 | + BoxOwnProps { |
| 245 | + size?: number | string |
| 246 | +} |
| 247 | +export const Spinner: ForwardRef<SVGSVGElement, SpinnerProps> |
| 248 | + |
| 249 | +export interface AvatarProps extends ImageProps { |
| 250 | + size?: number | string |
| 251 | +} |
| 252 | +export const Avatar: ForwardRef<HTMLImageElement, AvatarProps> |
| 253 | + |
| 254 | +export type BadgeProps = BoxProps |
| 255 | +export const Badge: ForwardRef<HTMLDivElement, BadgeProps> |
| 256 | + |
| 257 | +interface CloseProps extends Omit<IconButtonProps, 'children'> {} |
| 258 | +/** |
| 259 | + * Button with close (×) icon. |
| 260 | + * |
| 261 | + * The Close component renders as a <button> element by default. |
| 262 | + * Pass any button attributes as props to the component. |
| 263 | + * |
| 264 | + * Close component variants can be defined in the theme.buttons object. |
| 265 | + * The Close component uses theme.buttons.close as its default variant style. |
| 266 | + */ |
| 267 | +export const Close: ForwardRef<HTMLButtonElement, CloseProps> |
| 268 | + |
| 269 | +export type AlertProps = BoxProps |
| 270 | +/** |
| 271 | + * Component for displaying messages, notifications, or other application state. |
| 272 | + * |
| 273 | + * Alert variants can be defined in `theme.alerts`. |
| 274 | + * The Alert component uses `theme.alerts.primary` as its default variant. |
| 275 | + */ |
| 276 | +export const Alert: ForwardRef<HTMLDivElement, AlertProps> |
| 277 | + |
| 278 | +export type DividerProps = BoxProps |
| 279 | +/** |
| 280 | + * The Divider component reuses styles from `theme.styles.hr` as its default variant. |
| 281 | + */ |
| 282 | +export const Divider: ForwardRef<HTMLDivElement, DividerProps> |
| 283 | + |
| 284 | +export interface EmbedProps extends BoxProps { |
| 285 | + ratio?: number |
| 286 | + src?: React.IframeHTMLAttributes<any>['src'] |
| 287 | + frameBorder?: React.IframeHTMLAttributes<any>['frameBorder'] |
| 288 | + allowFullScreen?: React.IframeHTMLAttributes<any>['allowFullScreen'] |
| 289 | + allow?: React.IframeHTMLAttributes<any>['allow'] |
| 290 | +} |
| 291 | +/** |
| 292 | + * Responsive iframe for video embeds. |
| 293 | + * |
| 294 | + * Embed variants can be defined anywhere in the theme object. |
| 295 | + * |
| 296 | + * @see https://theme-ui.com/components/embed |
| 297 | + */ |
| 298 | +export const Embed: ForwardRef<HTMLIFrameElement, EmbedProps> |
| 299 | + |
| 300 | +export interface AspectRatioProps extends BoxProps { |
| 301 | + ratio?: number |
| 302 | +} |
| 303 | +/** |
| 304 | + * Component for maintaining a fluid-width aspect ratio |
| 305 | + * @see https://theme-ui.com/components/aspect-ratio |
| 306 | + */ |
| 307 | +export const AspectRatio: ForwardRef<HTMLDivElement, AspectRatioProps> |
| 308 | + |
| 309 | +export interface AspectImageProps extends ImageProps { |
| 310 | + ratio?: number |
| 311 | +} |
| 312 | +/** |
| 313 | + * Image component constrained by as aspect ratio. |
| 314 | + * @see https://theme-ui.com/components/aspect-image |
| 315 | + */ |
| 316 | +export const AspectImage: ForwardRef<HTMLImageElement, AspectImageProps> |
| 317 | + |
| 318 | +export type ContainerProps = BoxProps |
| 319 | +/** |
| 320 | + * Centered, max-width layout component |
| 321 | + * |
| 322 | + * Container variants can be defined in the `theme.layout` object. |
| 323 | + * The Container component uses `theme.layout.container` as its default variant style. |
| 324 | + * @see https://theme-ui.com/components/container |
| 325 | + */ |
| 326 | +export const Container: ForwardRef<HTMLDivElement, ContainerProps> |
| 327 | + |
| 328 | +export type NavLinkProps = LinkProps |
| 329 | +/** |
| 330 | + * Link component for use in navigation |
| 331 | + * |
| 332 | + * NavLink variants can be defined in the `theme.links` object. |
| 333 | + * By default the NavLink component will use styles defined in `theme.links.nav`. |
| 334 | + * @see https://theme-ui.com/components/nav-link |
| 335 | + */ |
| 336 | +export const NavLink: ForwardRef<HTMLAnchorElement, NavLinkProps> |
| 337 | + |
| 338 | +export type MessageProps = BoxProps |
| 339 | +/** |
| 340 | + * Styled Box component for callouts and inline messages |
| 341 | + * |
| 342 | + * Message variants can be defined in the theme.messages object. |
| 343 | + * @see https://theme-ui.com/components/message |
| 344 | + */ |
| 345 | +export const Message: ForwardRef<HTMLDivElement, MessageProps> |
| 346 | + |
| 347 | +export interface IconButtonProps |
| 348 | + extends Assign<React.ComponentPropsWithRef<'button'>, BoxOwnProps> {} |
| 349 | +/** |
| 350 | + * Transparent button for SVG icons |
| 351 | + * |
| 352 | + * IconButton variants can be defined in the `theme.buttons` object. |
| 353 | + * By default the IconButton component will use styles defined in `theme.buttons.icon`. |
| 354 | + * |
| 355 | + * @see https://theme-ui.com/components/icon-button |
| 356 | + */ |
| 357 | +export const IconButton: ForwardRef<HTMLButtonElement, IconButtonProps> |
| 358 | + |
| 359 | +export type MenuButtonProps = IconButtonProps |
| 360 | +/** |
| 361 | + * MenuButton variants can be defined in the `theme.buttons` object. |
| 362 | + * By default the MenuButton component will use styles defined in `theme.buttons.menu`. |
| 363 | + * |
| 364 | + * @see https://theme-ui.com/components/menu-button |
| 365 | + */ |
| 366 | +export const MenuButton: ForwardRef<HTMLButtonElement, MenuButtonProps> |
0 commit comments