diff --git a/src/runtime/html.ts b/src/runtime/html.ts
new file mode 100644
index 0000000000..83c69a0905
--- /dev/null
+++ b/src/runtime/html.ts
@@ -0,0 +1,1585 @@
+// Type definitions for Svelte HTML, based on JSX React 18 typings
+// Original Project/Authors:
+// Type definitions for React 18.0
+// Project: http://facebook.github.io/react/
+// Definitions by: Asana
+// AssureSign
+// Microsoft
+// John Reilly
+// Benoit Benezech
+// Patricio Zavolinsky
+// Eric Anderson
+// Dovydas Navickas
+// Josh Rutherford
+// Guilherme Hübner
+// Ferdy Budhidharma
+// Johann Rakotoharisoa
+// Olivier Pascal
+// Martin Hochel
+// Frank Li
+// Jessica Franco
+// Saransh Kataria
+// Kanitkorn Sujautra
+// Sebastian Silbermann
+// Kyle Scully
+// Cong Zhang
+// Dimitri Mitropoulos
+// JongChan Choi
+// Victor Magalhães
+// Dale Tan
+// Priyanshu Rav
+// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
+// TypeScript Version: 2.8
+
+// Note: We also allow `null` as a valid value because Svelte treats this the same as `undefined`
+
+type Booleanish = boolean | 'true' | 'false';
+
+//
+// Event Handler Types
+// ----------------------------------------------------------------------
+
+type EventHandler =
+(event: E & { currentTarget: EventTarget & T}) => any;
+
+export type ClipboardEventHandler = EventHandler;
+export type CompositionEventHandler = EventHandler;
+export type DragEventHandler = EventHandler;
+export type FocusEventHandler = EventHandler;
+export type FormEventHandler = EventHandler;
+export type ChangeEventHandler = EventHandler;
+export type KeyboardEventHandler = EventHandler;
+export type MouseEventHandler = EventHandler;
+export type TouchEventHandler = EventHandler;
+export type PointerEventHandler = EventHandler;
+export type UIEventHandler = EventHandler;
+export type WheelEventHandler = EventHandler;
+export type AnimationEventHandler = EventHandler;
+export type TransitionEventHandler = EventHandler;
+export type MessageEventHandler = EventHandler;
+
+//
+// DOM Attributes
+// ----------------------------------------------------------------------
+
+export interface DOMAttributes {
+ // Clipboard Events
+ oncopy?: ClipboardEventHandler | undefined | null;
+ oncut?: ClipboardEventHandler | undefined | null;
+ onpaste?: ClipboardEventHandler | undefined | null;
+
+ // Composition Events
+ oncompositionend?: CompositionEventHandler | undefined | null;
+ oncompositionstart?: CompositionEventHandler | undefined | null;
+ oncompositionupdate?: CompositionEventHandler | undefined | null;
+
+ // Focus Events
+ onfocus?: FocusEventHandler | undefined | null;
+ onfocusin?: FocusEventHandler | undefined | null;
+ onfocusout?: FocusEventHandler | undefined | null;
+ onblur?: FocusEventHandler | undefined | null;
+
+ // Form Events
+ onchange?: FormEventHandler | undefined | null;
+ onbeforeinput?: EventHandler | undefined | null;
+ oninput?: FormEventHandler | undefined | null;
+ onreset?: FormEventHandler | undefined | null;
+ onsubmit?: EventHandler | undefined | null;
+ oninvalid?: EventHandler | undefined | null;
+
+
+ // Image Events
+ onload?: EventHandler | undefined | null;
+ onerror?: EventHandler | undefined | null; // also a Media Event
+
+ // Detail Events
+ ontoggle?: EventHandler | undefined | null;
+
+ // Keyboard Events
+ onkeydown?: KeyboardEventHandler | undefined | null;
+ onkeypress?: KeyboardEventHandler | undefined | null;
+ onkeyup?: KeyboardEventHandler | undefined | null;
+
+ // Media Events
+ onabort?: EventHandler | undefined | null;
+ oncanplay?: EventHandler | undefined | null;
+ oncanplaythrough?: EventHandler | undefined | null;
+ oncuechange?: EventHandler | undefined | null;
+ ondurationchange?: EventHandler | undefined | null;
+ onemptied?: EventHandler | undefined | null;
+ onencrypted?: EventHandler | undefined | null;
+ onended?: EventHandler | undefined | null;
+ onloadeddata?: EventHandler | undefined | null;
+ onloadedmetadata?: EventHandler | undefined | null;
+ onloadstart?: EventHandler | undefined | null;
+ onpause?: EventHandler | undefined | null;
+ onplay?: EventHandler | undefined | null;
+ onplaying?: EventHandler | undefined | null;
+ onprogress?: EventHandler | undefined | null;
+ onratechange?: EventHandler | undefined | null;
+ onseeked?: EventHandler | undefined | null;
+ onseeking?: EventHandler | undefined | null;
+ onstalled?: EventHandler | undefined | null;
+ onsuspend?: EventHandler | undefined | null;
+ ontimeupdate?: EventHandler | undefined | null;
+ onvolumechange?: EventHandler | undefined | null;
+ onwaiting?: EventHandler | undefined | null;
+
+ // MouseEvents
+ onauxclick?: MouseEventHandler | undefined | null;
+ onclick?: MouseEventHandler | undefined | null;
+ oncontextmenu?: MouseEventHandler | undefined | null;
+ ondblclick?: MouseEventHandler | undefined | null;
+ ondrag?: DragEventHandler | undefined | null;
+ ondragend?: DragEventHandler | undefined | null;
+ ondragenter?: DragEventHandler | undefined | null;
+ ondragexit?: DragEventHandler | undefined | null;
+ ondragleave?: DragEventHandler | undefined | null;
+ ondragover?: DragEventHandler | undefined | null;
+ ondragstart?: DragEventHandler | undefined | null;
+ ondrop?: DragEventHandler | undefined | null;
+ onmousedown?: MouseEventHandler | undefined | null;
+ onmouseenter?: MouseEventHandler | undefined | null;
+ onmouseleave?: MouseEventHandler | undefined | null;
+ onmousemove?: MouseEventHandler | undefined | null;
+ onmouseout?: MouseEventHandler | undefined | null;
+ onmouseover?: MouseEventHandler | undefined | null;
+ onmouseup?: MouseEventHandler | undefined | null;
+
+ // Selection Events
+ onselect?: EventHandler | undefined | null;
+ onselectionchange?: EventHandler | undefined | null;
+ onselectstart?: EventHandler | undefined | null;
+
+ // Touch Events
+ ontouchcancel?: TouchEventHandler | undefined | null;
+ ontouchend?: TouchEventHandler | undefined | null;
+ ontouchmove?: TouchEventHandler | undefined | null;
+ ontouchstart?: TouchEventHandler | undefined | null;
+
+ // Pointer Events
+ ongotpointercapture?: PointerEventHandler | undefined | null;
+ onpointercancel?: PointerEventHandler | undefined | null;
+ onpointerdown?: PointerEventHandler | undefined | null;
+ onpointerenter?: PointerEventHandler | undefined | null;
+ onpointerleave?: PointerEventHandler | undefined | null;
+ onpointermove?: PointerEventHandler | undefined | null;
+ onpointerout?: PointerEventHandler | undefined | null;
+ onpointerover?: PointerEventHandler | undefined | null;
+ onpointerup?: PointerEventHandler | undefined | null;
+ onlostpointercapture?: PointerEventHandler | undefined | null;
+
+ // UI Events
+ onscroll?: UIEventHandler | undefined | null;
+ onresize?: UIEventHandler | undefined | null;
+
+ // Wheel Events
+ onwheel?: WheelEventHandler | undefined | null;
+
+ // Animation Events
+ onanimationstart?: AnimationEventHandler | undefined | null;
+ onanimationend?: AnimationEventHandler | undefined | null;
+ onanimationiteration?: AnimationEventHandler | undefined | null;
+
+ // Transition Events
+ ontransitionstart?: TransitionEventHandler | undefined | null;
+ ontransitionrun?: TransitionEventHandler | undefined | null;
+ ontransitionend?: TransitionEventHandler | undefined | null;
+ ontransitioncancel?: TransitionEventHandler | undefined | null;
+
+ // Svelte Transition Events
+ onoutrostart?: EventHandler, T> | undefined | null;
+ onoutroend?: EventHandler, T> | undefined | null;
+ onintrostart?: EventHandler, T> | undefined | null;
+ onintroend?: EventHandler, T> | undefined | null;
+
+ // Message Events
+ onmessage?: MessageEventHandler | undefined | null;
+ onmessageerror?: MessageEventHandler | undefined | null;
+
+ // Global Events
+ oncancel?: EventHandler | undefined | null;
+ onclose?: EventHandler | undefined | null;
+ onfullscreenchange?: EventHandler | undefined | null;
+ onfullscreenerror?: EventHandler | undefined | null;
+}
+
+// All the WAI-ARIA 1.1 attributes from https://www.w3.org/TR/wai-aria-1.1/
+export interface AriaAttributes {
+ /** Identifies the currently active element when DOM focus is on a composite widget, textbox, group, or application. */
+ 'aria-activedescendant'?: string | undefined | null;
+ /** 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 | null;
+ /**
+ * 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 | null;
+ /** 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 | null;
+ /**
+ * Indicates the current "checked" state of checkboxes, radio buttons, and other widgets.
+ * @see aria-pressed @see aria-selected.
+ */
+ 'aria-checked'?: boolean | 'false' | 'mixed' | 'true' | undefined | null;
+ /**
+ * Defines the total number of columns in a table, grid, or treegrid.
+ * @see aria-colindex.
+ */
+ 'aria-colcount'?: number | undefined | null;
+ /**
+ * 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 | null;
+ /**
+ * 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 | null;
+ /**
+ * Identifies the element (or elements) whose contents or presence are controlled by the current element.
+ * @see aria-owns.
+ */
+ 'aria-controls'?: string | undefined | null;
+ /** Indicates the element that represents the current item within a container or set of related elements. */
+ 'aria-current'?: boolean | 'false' | 'true' | 'page' | 'step' | 'location' | 'date' | 'time' | undefined | null;
+ /**
+ * Identifies the element (or elements) that describes the object.
+ * @see aria-labelledby
+ */
+ 'aria-describedby'?: string | undefined | null;
+ /**
+ * Identifies the element that provides a detailed, extended description for the object.
+ * @see aria-describedby.
+ */
+ 'aria-details'?: string | undefined | null;
+ /**
+ * 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 | null;
+ /**
+ * Indicates what functions can be performed when a dragged object is released on the drop target.
+ * @deprecated in ARIA 1.1
+ */
+ 'aria-dropeffect'?: 'none' | 'copy' | 'execute' | 'link' | 'move' | 'popup' | undefined | null;
+ /**
+ * Identifies the element that provides an error message for the object.
+ * @see aria-invalid @see aria-describedby.
+ */
+ 'aria-errormessage'?: string | undefined | null;
+ /** Indicates whether the element, or another grouping element it controls, is currently expanded or collapsed. */
+ 'aria-expanded'?: Booleanish | undefined | null;
+ /**
+ * 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 | null;
+ /**
+ * Indicates an element's "grabbed" state in a drag-and-drop operation.
+ * @deprecated in ARIA 1.1
+ */
+ 'aria-grabbed'?: Booleanish | undefined | null;
+ /** Indicates the availability and type of interactive popup element, such as menu or dialog, that can be triggered by an element. */
+ 'aria-haspopup'?: boolean | 'false' | 'true' | 'menu' | 'listbox' | 'tree' | 'grid' | 'dialog' | undefined | null;
+ /**
+ * Indicates whether the element is exposed to an accessibility API.
+ * @see aria-disabled.
+ */
+ 'aria-hidden'?: Booleanish | undefined | null;
+ /**
+ * Indicates the entered value does not conform to the format expected by the application.
+ * @see aria-errormessage.
+ */
+ 'aria-invalid'?: boolean | 'false' | 'true' | 'grammar' | 'spelling' | undefined | null;
+ /** Indicates keyboard shortcuts that an author has implemented to activate or give focus to an element. */
+ 'aria-keyshortcuts'?: string | undefined | null;
+ /**
+ * Defines a string value that labels the current element.
+ * @see aria-labelledby.
+ */
+ 'aria-label'?: string | undefined | null;
+ /**
+ * Identifies the element (or elements) that labels the current element.
+ * @see aria-describedby.
+ */
+ 'aria-labelledby'?: string | undefined | null;
+ /** Defines the hierarchical level of an element within a structure. */
+ 'aria-level'?: number | undefined | null;
+ /** 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 | null;
+ /** Indicates whether an element is modal when displayed. */
+ 'aria-modal'?: Booleanish | undefined | null;
+ /** Indicates whether a text box accepts multiple lines of input or only a single line. */
+ 'aria-multiline'?: Booleanish | undefined | null;
+ /** Indicates that the user may select more than one item from the current selectable descendants. */
+ 'aria-multiselectable'?: Booleanish | undefined | null;
+ /** Indicates whether the element's orientation is horizontal, vertical, or unknown/ambiguous. */
+ 'aria-orientation'?: 'horizontal' | 'vertical' | undefined | null;
+ /**
+ * 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 | null;
+ /**
+ * 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 | null;
+ /**
+ * 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 | null;
+ /**
+ * Indicates the current "pressed" state of toggle buttons.
+ * @see aria-checked @see aria-selected.
+ */
+ 'aria-pressed'?: boolean | 'false' | 'mixed' | 'true' | undefined | null;
+ /**
+ * Indicates that the element is not editable, but is otherwise operable.
+ * @see aria-disabled.
+ */
+ 'aria-readonly'?: Booleanish | undefined | null;
+ /**
+ * 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 | null;
+ /** Indicates that user input is required on the element before a form may be submitted. */
+ 'aria-required'?: Booleanish | undefined | null;
+ /** Defines a human-readable, author-localized description for the role of an element. */
+ 'aria-roledescription'?: string | undefined | null;
+ /**
+ * Defines the total number of rows in a table, grid, or treegrid.
+ * @see aria-rowindex.
+ */
+ 'aria-rowcount'?: number | undefined | null;
+ /**
+ * 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 | null;
+ /**
+ * 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 | null;
+ /**
+ * Indicates the current "selected" state of various widgets.
+ * @see aria-checked @see aria-pressed.
+ */
+ 'aria-selected'?: Booleanish | undefined | null;
+ /**
+ * 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 | null;
+ /** Indicates if items in a table or grid are sorted in ascending or descending order. */
+ 'aria-sort'?: 'none' | 'ascending' | 'descending' | 'other' | undefined | null;
+ /** Defines the maximum allowed value for a range widget. */
+ 'aria-valuemax'?: number | undefined | null;
+ /** Defines the minimum allowed value for a range widget. */
+ 'aria-valuemin'?: number | undefined | null;
+ /**
+ * Defines the current value for a range widget.
+ * @see aria-valuetext.
+ */
+ 'aria-valuenow'?: number | undefined | null;
+ /** Defines the human readable text alternative of aria-valuenow for a range widget. */
+ 'aria-valuetext'?: string | undefined | null;
+}
+
+// All the WAI-ARIA 1.1 role attribute values from https://www.w3.org/TR/wai-aria-1.1/#role_definitions
+export type AriaRole =
+ | 'alert'
+ | 'alertdialog'
+ | 'application'
+ | 'article'
+ | 'banner'
+ | 'button'
+ | 'cell'
+ | 'checkbox'
+ | 'columnheader'
+ | 'combobox'
+ | 'complementary'
+ | 'contentinfo'
+ | 'definition'
+ | 'dialog'
+ | 'directory'
+ | 'document'
+ | 'feed'
+ | 'figure'
+ | 'form'
+ | 'grid'
+ | 'gridcell'
+ | 'group'
+ | 'heading'
+ | 'img'
+ | 'link'
+ | 'list'
+ | 'listbox'
+ | 'listitem'
+ | 'log'
+ | 'main'
+ | 'marquee'
+ | 'math'
+ | 'menu'
+ | 'menubar'
+ | 'menuitem'
+ | 'menuitemcheckbox'
+ | 'menuitemradio'
+ | 'navigation'
+ | 'none'
+ | 'note'
+ | 'option'
+ | 'presentation'
+ | 'progressbar'
+ | 'radio'
+ | 'radiogroup'
+ | 'region'
+ | 'row'
+ | 'rowgroup'
+ | 'rowheader'
+ | 'scrollbar'
+ | 'search'
+ | 'searchbox'
+ | 'separator'
+ | 'slider'
+ | 'spinbutton'
+ | 'status'
+ | 'switch'
+ | 'tab'
+ | 'table'
+ | 'tablist'
+ | 'tabpanel'
+ | 'term'
+ | 'textbox'
+ | 'timer'
+ | 'toolbar'
+ | 'tooltip'
+ | 'tree'
+ | 'treegrid'
+ | 'treeitem'
+ | (string & {});
+
+export interface HTMLAttributes extends AriaAttributes, DOMAttributes {
+ // Standard HTML Attributes
+ accesskey?: string | undefined | null;
+ class?: string | undefined | null;
+ contenteditable?: Booleanish | "inherit" | undefined | null;
+ contextmenu?: string | undefined | null;
+ dir?: string | undefined | null;
+ draggable?: Booleanish | undefined | null;
+ hidden?: boolean | undefined | null;
+ id?: string | undefined | null;
+ lang?: string | undefined | null;
+ placeholder?: string | undefined | null;
+ slot?: string | undefined | null;
+ spellcheck?: Booleanish | undefined | null;
+ style?: string | undefined | null;
+ tabindex?: number | undefined | null;
+ title?: string | undefined | null;
+ translate?: "yes" | "no" | "" | undefined | null;
+
+ // Unknown
+ radiogroup?: string | undefined | null; // ,