import { ArrayExt } from '@lumino/algorithm' ; /**
 * The names of the supported HTML5 DOM element attributes.
 *
 * This list is not all-encompassing, rather it attempts to define the
 * attribute names which are relevant for use in a virtual DOM context.
 * If a standardized or widely supported name is missing, please open
 * an issue to have it added.
 *
 * The attribute names were collected from the following sources:
 *   - https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes
 *   - https://www.w3.org/TR/html5/index.html#attributes-1
 *   - https://html.spec.whatwg.org/multipage/indices.html#attributes-3
 */ export type ElementAttrNames = 'abbr' | 'accept' | 'accept-charset' | 'accesskey' | 'action' | 'allowfullscreen' | 'alt' | 'autocomplete' | 'autofocus' | 'autoplay' | 'autosave' | 'checked' | 'cite' | 'cols' | 'colspan' | 'contenteditable' | 'controls' | 'coords' | 'crossorigin' | 'data' | 'datetime' | 'default' | 'dir' | 'dirname' | 'disabled' | 'download' | 'draggable' | 'dropzone' | 'enctype' | 'form' | 'formaction' | 'formenctype' | 'formmethod' | 'formnovalidate' | 'formtarget' | 'headers' | 'height' | 'hidden' | 'high' | 'href' | 'hreflang' | 'id' | 'inputmode' | 'integrity' | 'ismap' | 'kind' | 'label' | 'lang' | 'list' | 'loop' | 'low' | 'max' | 'maxlength' | 'media' | 'mediagroup' | 'method' | 'min' | 'minlength' | 'multiple' | 'muted' | 'name' | 'novalidate' | 'optimum' | 'pattern' | 'placeholder' | 'poster' | 'preload' | 'readonly' | 'rel' | 'required' | 'reversed' | 'rows' | 'rowspan' | 'sandbox' | 'scope' | 'selected' | 'shape' | 'size' | 'sizes' | 'span' | 'spellcheck' | 'src' | 'srcdoc' | 'srclang' | 'srcset' | 'start' | 'step' | 'tabindex' | 'target' | 'title' | 'type' | 'typemustmatch' | 'usemap' | 'value' | 'width' | 'wrap' ; /**
 * The names of ARIA attributes for HTML elements.
 *
 * The attribute names are collected from
 * https://www.w3.org/TR/html5/infrastructure.html#element-attrdef-aria-role
 */ export type ARIAAttrNames = 'aria-activedescendant' | 'aria-atomic' | 'aria-autocomplete' | 'aria-busy' | 'aria-checked' | 'aria-colcount' | 'aria-colindex' | 'aria-colspan' | 'aria-controls' | 'aria-current' | 'aria-describedby' | 'aria-details' | 'aria-dialog' | 'aria-disabled' | 'aria-dropeffect' | 'aria-errormessage' | 'aria-expanded' | 'aria-flowto' | 'aria-grabbed' | 'aria-haspopup' | 'aria-hidden' | 'aria-invalid' | 'aria-keyshortcuts' | 'aria-label' | 'aria-labelledby' | 'aria-level' | 'aria-live' | 'aria-multiline' | 'aria-multiselectable' | 'aria-orientation' | 'aria-owns' | 'aria-placeholder' | 'aria-posinset' | 'aria-pressed' | 'aria-readonly' | 'aria-relevant' | 'aria-required' | 'aria-roledescription' | 'aria-rowcount' | 'aria-rowindex' | 'aria-rowspan' | 'aria-selected' | 'aria-setsize' | 'aria-sort' | 'aria-valuemax' | 'aria-valuemin' | 'aria-valuenow' | 'aria-valuetext' | 'role' ; /**
 * The names of the supported HTML5 CSS property names.
 *
 * If a standardized or widely supported name is missing, please open
 * an issue to have it added.
 *
 * The property names were collected from the following sources:
 *   - TypeScript's `lib.dom.d.ts` file
 */ export type CSSPropertyNames = 'alignContent' | 'alignItems' | 'alignSelf' | 'alignmentBaseline' | 'animation' | 'animationDelay' | 'animationDirection' | 'animationDuration' | 'animationFillMode' | 'animationIterationCount' | 'animationName' | 'animationPlayState' | 'animationTimingFunction' | 'backfaceVisibility' | 'background' | 'backgroundAttachment' | 'backgroundClip' | 'backgroundColor' | 'backgroundImage' | 'backgroundOrigin' | 'backgroundPosition' | 'backgroundPositionX' | 'backgroundPositionY' | 'backgroundRepeat' | 'backgroundSize' | 'baselineShift' | 'border' | 'borderBottom' | 'borderBottomColor' | 'borderBottomLeftRadius' | 'borderBottomRightRadius' | 'borderBottomStyle' | 'borderBottomWidth' | 'borderCollapse' | 'borderColor' | 'borderImage' | 'borderImageOutset' | 'borderImageRepeat' | 'borderImageSlice' | 'borderImageSource' | 'borderImageWidth' | 'borderLeft' | 'borderLeftColor' | 'borderLeftStyle' | 'borderLeftWidth' | 'borderRadius' | 'borderRight' | 'borderRightColor' | 'borderRightStyle' | 'borderRightWidth' | 'borderSpacing' | 'borderStyle' | 'borderTop' | 'borderTopColor' | 'borderTopLeftRadius' | 'borderTopRightRadius' | 'borderTopStyle' | 'borderTopWidth' | 'borderWidth' | 'bottom' | 'boxShadow' | 'boxSizing' | 'breakAfter' | 'breakBefore' | 'breakInside' | 'captionSide' | 'clear' | 'clip' | 'clipPath' | 'clipRule' | 'color' | 'colorInterpolationFilters' | 'columnCount' | 'columnFill' | 'columnGap' | 'columnRule' | 'columnRuleColor' | 'columnRuleStyle' | 'columnRuleWidth' | 'columnSpan' | 'columnWidth' | 'columns' | 'content' | 'counterIncrement' | 'counterReset' | 'cssFloat' | 'cssText' | 'cursor' | 'direction' | 'display' | 'dominantBaseline' | 'emptyCells' | 'enableBackground' | 'fill' | 'fillOpacity' | 'fillRule' | 'filter' | 'flex' | 'flexBasis' | 'flexDirection' | 'flexFlow' | 'flexGrow' | 'flexShrink' | 'flexWrap' | 'floodColor' | 'floodOpacity' | 'font' | 'fontFamily' | 'fontFeatureSettings' | 'fontSize' | 'fontSizeAdjust' | 'fontStretch' | 'fontStyle' | 'fontVariant' | 'fontWeight' | 'glyphOrientationHorizontal' | 'glyphOrientationVertical' | 'height' | 'imeMode' | 'justifyContent' | 'kerning' | 'left' | 'letterSpacing' | 'lightingColor' | 'lineHeight' | 'listStyle' | 'listStyleImage' | 'listStylePosition' | 'listStyleType' | 'margin' | 'marginBottom' | 'marginLeft' | 'marginRight' | 'marginTop' | 'marker' | 'markerEnd' | 'markerMid' | 'markerStart' | 'mask' | 'maxHeight' | 'maxWidth' | 'minHeight' | 'minWidth' | 'msContentZoomChaining' | 'msContentZoomLimit' | 'msContentZoomLimitMax' | 'msContentZoomLimitMin' | 'msContentZoomSnap' | 'msContentZoomSnapPoints' | 'msContentZoomSnapType' | 'msContentZooming' | 'msFlowFrom' | 'msFlowInto' | 'msFontFeatureSettings' | 'msGridColumn' | 'msGridColumnAlign' | 'msGridColumnSpan' | 'msGridColumns' | 'msGridRow' | 'msGridRowAlign' | 'msGridRowSpan' | 'msGridRows' | 'msHighContrastAdjust' | 'msHyphenateLimitChars' | 'msHyphenateLimitLines' | 'msHyphenateLimitZone' | 'msHyphens' | 'msImeAlign' | 'msOverflowStyle' | 'msScrollChaining' | 'msScrollLimit' | 'msScrollLimitXMax' | 'msScrollLimitXMin' | 'msScrollLimitYMax' | 'msScrollLimitYMin' | 'msScrollRails' | 'msScrollSnapPointsX' | 'msScrollSnapPointsY' | 'msScrollSnapType' | 'msScrollSnapX' | 'msScrollSnapY' | 'msScrollTranslation' | 'msTextCombineHorizontal' | 'msTextSizeAdjust' | 'msTouchAction' | 'msTouchSelect' | 'msUserSelect' | 'msWrapFlow' | 'msWrapMargin' | 'msWrapThrough' | 'opacity' | 'order' | 'orphans' | 'outline' | 'outlineColor' | 'outlineStyle' | 'outlineWidth' | 'overflow' | 'overflowX' | 'overflowY' | 'padding' | 'paddingBottom' | 'paddingLeft' | 'paddingRight' | 'paddingTop' | 'pageBreakAfter' | 'pageBreakBefore' | 'pageBreakInside' | 'perspective' | 'perspectiveOrigin' | 'pointerEvents' | 'position' | 'quotes' | 'resize' | 'right' | 'rubyAlign' | 'rubyOverhang' | 'rubyPosition' | 'stopColor' | 'stopOpacity' | 'stroke' | 'strokeDasharray' | 'strokeDashoffset' | 'strokeLinecap' | 'strokeLinejoin' | 'strokeMiterlimit' | 'strokeOpacity' | 'strokeWidth' | 'tableLayout' | 'textAlign' | 'textAlignLast' | 'textAnchor' | 'textDecoration' | 'textIndent' | 'textJustify' | 'textKashida' | 'textKashidaSpace' | 'textOverflow' | 'textShadow' | 'textTransform' | 'textUnderlinePosition' | 'top' | 'touchAction' | 'transform' | 'transformOrigin' | 'transformStyle' | 'transition' | 'transitionDelay' | 'transitionDuration' | 'transitionProperty' | 'transitionTimingFunction' | 'unicodeBidi' | 'verticalAlign' | 'visibility' | 'webkitAlignContent' | 'webkitAlignItems' | 'webkitAlignSelf' | 'webkitAnimation' | 'webkitAnimationDelay' | 'webkitAnimationDirection' | 'webkitAnimationDuration' | 'webkitAnimationFillMode' | 'webkitAnimationIterationCount' | 'webkitAnimationName' | 'webkitAnimationPlayState' | 'webkitAnimationTimingFunction' | 'webkitAppearance' | 'webkitBackfaceVisibility' | 'webkitBackgroundClip' | 'webkitBackgroundOrigin' | 'webkitBackgroundSize' | 'webkitBorderBottomLeftRadius' | 'webkitBorderBottomRightRadius' | 'webkitBorderImage' | 'webkitBorderRadius' | 'webkitBorderTopLeftRadius' | 'webkitBorderTopRightRadius' | 'webkitBoxAlign' | 'webkitBoxDirection' | 'webkitBoxFlex' | 'webkitBoxOrdinalGroup' | 'webkitBoxOrient' | 'webkitBoxPack' | 'webkitBoxSizing' | 'webkitColumnBreakAfter' | 'webkitColumnBreakBefore' | 'webkitColumnBreakInside' | 'webkitColumnCount' | 'webkitColumnGap' | 'webkitColumnRule' | 'webkitColumnRuleColor' | 'webkitColumnRuleStyle' | 'webkitColumnRuleWidth' | 'webkitColumnSpan' | 'webkitColumnWidth' | 'webkitColumns' | 'webkitFilter' | 'webkitFlex' | 'webkitFlexBasis' | 'webkitFlexDirection' | 'webkitFlexFlow' | 'webkitFlexGrow' | 'webkitFlexShrink' | 'webkitFlexWrap' | 'webkitJustifyContent' | 'webkitOrder' | 'webkitPerspective' | 'webkitPerspectiveOrigin' | 'webkitTapHighlightColor' | 'webkitTextFillColor' | 'webkitTextSizeAdjust' | 'webkitTransform' | 'webkitTransformOrigin' | 'webkitTransformStyle' | 'webkitTransition' | 'webkitTransitionDelay' | 'webkitTransitionDuration' | 'webkitTransitionProperty' | 'webkitTransitionTimingFunction' | 'webkitUserModify' | 'webkitUserSelect' | 'webkitWritingMode' | 'whiteSpace' | 'widows' | 'width' | 'wordBreak' | 'wordSpacing' | 'wordWrap' | 'writingMode' | 'zIndex' | 'zoom' ; /**
 * A mapping of inline event name to event object type.
 *
 * This mapping is used to create the event listener properties for
 * the virtual DOM element attributes object. If a standardized or
 * widely supported name is missing, please open an issue to have it
 * added.
 *
 * The event names were collected from the following sources:
 *   - TypeScript's `lib.dom.d.ts` file
 *   - https://www.w3.org/TR/html5/index.html#attributes-1
 *   - https://html.spec.whatwg.org/multipage/webappapis.html#idl-definitions
 */ export type ElementEventMap = { onabort : UIEvent ; onauxclick : MouseEvent ; onblur : FocusEvent ; oncanplay : Event ; oncanplaythrough : Event ; onchange : Event ; onclick : MouseEvent ; oncontextmenu : PointerEvent ; oncopy : ClipboardEvent ; oncuechange : Event ; oncut : ClipboardEvent ; ondblclick : MouseEvent ; ondrag : DragEvent ; ondragend : DragEvent ; ondragenter : DragEvent ; ondragexit : DragEvent ; ondragleave : DragEvent ; ondragover : DragEvent ; ondragstart : DragEvent ; ondrop : DragEvent ; ondurationchange : Event ; onemptied : Event ; onended : ErrorEvent ; onerror : ErrorEvent ; onfocus : FocusEvent ; oninput : Event ; oninvalid : Event ; onkeydown : KeyboardEvent ; onkeypress : KeyboardEvent ; onkeyup : KeyboardEvent ; onload : Event ; onloadeddata : Event ; onloadedmetadata : Event ; onloadend : Event ; onloadstart : Event ; onmousedown : MouseEvent ; onmouseenter : MouseEvent ; onmouseleave : MouseEvent ; onmousemove : MouseEvent ; onmouseout : MouseEvent ; onmouseover : MouseEvent ; onmouseup : MouseEvent ; onmousewheel : WheelEvent ; onpaste : ClipboardEvent ; onpause : Event ; onplay : Event ; onplaying : Event ; onpointercancel : PointerEvent ; onpointerdown : PointerEvent ; onpointerenter : PointerEvent ; onpointerleave : PointerEvent ; onpointermove : PointerEvent ; onpointerout : PointerEvent ; onpointerover : PointerEvent ; onpointerup : PointerEvent ; onprogress : ProgressEvent ; onratechange : Event ; onreset : Event ; onscroll : UIEvent ; onseeked : Event ; onseeking : Event ; onselect : UIEvent ; onselectstart : Event ; onstalled : Event ; onsubmit : Event ; onsuspend : Event ; ontimeupdate : Event ; onvolumechange : Event ; onwaiting : Event ; } ; /**
 * An object which represents a dataset for a virtual DOM element.
 *
 * The names of the dataset properties will be automatically prefixed
 * with `data-` before being added to the node, e.g. `{ thing: '12' }`
 * will be rendered as `data-thing='12'` in the DOM element.
 *
 * Dataset property names should not contain spaces.
 */ export type ElementDataset = { readonly [ name ] : string ; } ; /**
 * The inline style for for a virtual DOM element.
 *
 * Style attributes use the JS camel-cased property names instead of
 * the CSS hyphenated names for performance and security.
 */ export type ElementInlineStyle = { readonly [ T in CSSPropertyNames ] ? : string ; } ; /**
 * The ARIA attributes for a virtual element node.
 *
 * These are the attributes which are applied to a real DOM element via
 * `element.setAttribute()`. The supported attribute names are defined
 * by the `ARIAAttrNames` type.
 */ export type ElementARIAAttrs = { readonly [ T in ARIAAttrNames ] ? : string ; } ; /**
 * The base attributes for a virtual element node.
 *
 * These are the attributes which are applied to a real DOM element via
 * `element.setAttribute()`. The supported attribute names are defined
 * by the `ElementAttrNames` type.
 *
 * Node attributes are specified using the lower-case HTML name instead
 * of the camel-case JS name due to browser inconsistencies in handling
 * the JS versions.
 */ export type ElementBaseAttrs = { readonly [ T in ElementAttrNames ] ? : string ; } ; /**
 * The inline event listener attributes for a virtual element node.
 *
 * The supported listeners are defined by the `ElementEventMap` type.
 */ export type ElementEventAttrs = { readonly [ T in keyof ElementEventMap ] ? : ( this : HTMLElement , event : ElementEventMap [ T ] ) => any ; } ; /**
 * The special-cased attributes for a virtual element node.
 */ export type ElementSpecialAttrs = { /**
     * The key id for the virtual element node.
     *
     * If a node is given a key id, the generated DOM node will not be
     * recreated during a rendering update if it only moves among its
     * siblings in the render tree.
     *
     * In general, reordering child nodes will cause the nodes to be
     * completely re-rendered. Keys allow this to be optimized away.
     *
     * If a key is provided, it must be unique among sibling nodes.
     */ readonly key ? : string ; /**
     * The JS-safe name for the HTML `class` attribute.
     */ readonly className ? : string ; /**
     * The JS-safe name for the HTML `for` attribute.
     */ readonly htmlFor ? : string ; /**
     * The dataset for the rendered DOM element.
     */ readonly dataset ? : ElementDataset ; /**
     * The inline style for the rendered DOM element.
     */ readonly style ? : ElementInlineStyle ; } ; /**
 * The full set of attributes supported by a virtual element node.
 *
 * This is the combination of the base element attributes, the the ARIA attributes,
 * the inline element event listeners, and the special element attributes.
 */ export type ElementAttrs = ElementBaseAttrs & ElementARIAAttrs & ElementEventAttrs & ElementSpecialAttrs ; /**
 * A virtual node which represents plain text content.
 *
 * #### Notes
 * User code will not typically create a `VirtualText` node directly.
 * Instead, the `h()` function will be used to create an element tree.
 */ export class VirtualText { /**
     * The text content for the node.
     */ readonly content : string ; /**
     * The type of the node.
     *
     * This value can be used as a type guard for discriminating the
     * `VirtualNode` union type.
     */ readonly type : 'text' = 'text' ; param content constructor ( content ) { this . content = content ; } } /**
 * A virtual node which represents an HTML element.
 *
 * #### Notes
 * User code will not typically create a `VirtualElement` node directly.
 * Instead, the `h()` function will be used to create an element tree.
 */ export class VirtualElement { /**
     * The tag name for the element.
     */ readonly tag : string ; /**
     * The attributes for the element.
     */ readonly attrs : ElementAttrs ; /**
     * The children for the element.
     */ readonly children : ReadonlyArray < VirtualNode > ; /**
     * An optional custom renderer for the element's children. If set, on render
     * this element's DOM node and it's attrs will be created/updated as normal.
     * At that point the DOM node is handed off to the renderer.
     */ readonly renderer : VirtualElement . IRenderer | undefined ; /**
     * The type of the node.
     *
     * This value can be used as a type guard for discriminating the
     * `VirtualNode` union type.
     */ readonly type : 'element' = 'element' ; param tag param attrs param children param renderer constructor ( tag , attrs , children , renderer ? ) { this . tag = tag ; this . attrs = attrs ; this . children = children ; this . renderer = renderer ; } } export namespace VirtualElement { /**
     * A type describing a custom element renderer
     */ export type IRenderer = { param host param options render : ( host : HTMLElement , options ? : { attrs ? : ElementAttrs ; children ? : ReadonlyArray < VirtualNode > ; } ) => void ; param host param options unrender ? : ( host : HTMLElement , options ? : { attrs ? : ElementAttrs ; children ? : ReadonlyArray < VirtualNode > ; } ) => void ; } ; } /**
 * DEPRECATED - use VirtualElement with a defined renderer param instead.
 * This class is provided as a backwards compatibility shim
 *
 * A "pass thru" virtual node whose children are managed by a render and an
 * unrender callback. The intent of this flavor of virtual node is to make
 * it easy to blend other kinds of virtualdom (eg React) into Phosphor's
 * virtualdom.
 *
 * #### Notes
 * User code will not typically create a `VirtualElementPass` node directly.
 * Instead, the `hpass()` function will be used to create an element tree.
 */ export class VirtualElementPass extends VirtualElement { param tag param attrs param renderer constructor ( tag , attrs , renderer ) { super ( tag , attrs , [ ] , renderer || undefined ) ; } } export namespace VirtualElementPass { /**
     * DEPRECATED - use VirtualElement.IRenderer instead
     *
     * A type describing a custom element renderer
     */ export type IRenderer = VirtualElement . IRenderer ; } /**
 * A type alias for a general virtual node.
 */ export type VirtualNode = VirtualElement | VirtualText ; param tag param attrs param renderer param children returns export function h ( tag , ... children ) ; export function h ( tag , attrs , ... children ) ; export function h ( tag , renderer , ... children ) ; export function h ( tag , attrs , renderer , ... children ) ; export function h ( tag ) { let attrs = { } ; let renderer ; let children = [ ] ; for ( let i = 1 , n = arguments . length ; i < n ; ++ i ) { let arg = arguments [ i ] ; if ( typeof arg === 'string' ) { children . push ( new VirtualText ( arg ) ) ; } else if ( arg instanceof VirtualText ) { children . push ( arg ) ; } else if ( arg instanceof VirtualElement ) { children . push ( arg ) ; } else if ( arg instanceof Array ) { extend ( children , arg ) ; } else if ( ( i === 1 || i === 2 ) && arg && typeof arg === 'object' ) { if ( 'render' in arg ) { renderer = arg ; } else { attrs = arg ; } } } return new VirtualElement ( tag , attrs , children , renderer ) ; function extend ( array , values ) { for ( let child of values ) { if ( typeof child === 'string' ) { array . push ( new VirtualText ( child ) ) ; } else if ( child instanceof VirtualText ) { array . push ( child ) ; } else if ( child instanceof VirtualElement ) { array . push ( child ) ; } } } } /**
 * The namespace for the `h` function statics.
 */ export namespace h { /**
     * A type alias for the supported child argument types.
     */ export type Child = ( string | VirtualNode | null ) | Array < string | VirtualNode | null > ; /**
     * A bound factory function for a specific `h()` tag.
     */ export interface IFactory { ( ... children ) : VirtualElement ; ( attrs , ... children ) : VirtualElement ; ( renderer , ... children ) : VirtualElement ; ( attrs , renderer , ... children ) : VirtualElement ; } export const a = h . bind ( undefined , 'a' ) ; export const abbr = h . bind ( undefined , 'abbr' ) ; export const address = h . bind ( undefined , 'address' ) ; export const area = h . bind ( undefined , 'area' ) ; export const article = h . bind ( undefined , 'article' ) ; export const aside = h . bind ( undefined , 'aside' ) ; export const audio = h . bind ( undefined , 'audio' ) ; export const b = h . bind ( undefined , 'b' ) ; export const bdi = h . bind ( undefined , 'bdi' ) ; export const bdo = h . bind ( undefined , 'bdo' ) ; export const blockquote = h . bind ( undefined , 'blockquote' ) ; export const br = h . bind ( undefined , 'br' ) ; export const button = h . bind ( undefined , 'button' ) ; export const canvas = h . bind ( undefined , 'canvas' ) ; export const caption = h . bind ( undefined , 'caption' ) ; export const cite = h . bind ( undefined , 'cite' ) ; export const code = h . bind ( undefined , 'code' ) ; export const col = h . bind ( undefined , 'col' ) ; export const colgroup = h . bind ( undefined , 'colgroup' ) ; export const data = h . bind ( undefined , 'data' ) ; export const datalist = h . bind ( undefined , 'datalist' ) ; export const dd = h . bind ( undefined , 'dd' ) ; export const del = h . bind ( undefined , 'del' ) ; export const dfn = h . bind ( undefined , 'dfn' ) ; export const div = h . bind ( undefined , 'div' ) ; export const dl = h . bind ( undefined , 'dl' ) ; export const dt = h . bind ( undefined , 'dt' ) ; export const em = h . bind ( undefined , 'em' ) ; export const embed = h . bind ( undefined , 'embed' ) ; export const fieldset = h . bind ( undefined , 'fieldset' ) ; export const figcaption = h . bind ( undefined , 'figcaption' ) ; export const figure = h . bind ( undefined , 'figure' ) ; export const footer = h . bind ( undefined , 'footer' ) ; export const form = h . bind ( undefined , 'form' ) ; export const h1 = h . bind ( undefined , 'h1' ) ; export const h2 = h . bind ( undefined , 'h2' ) ; export const h3 = h . bind ( undefined , 'h3' ) ; export const h4 = h . bind ( undefined , 'h4' ) ; export const h5 = h . bind ( undefined , 'h5' ) ; export const h6 = h . bind ( undefined , 'h6' ) ; export const header = h . bind ( undefined , 'header' ) ; export const hr = h . bind ( undefined , 'hr' ) ; export const i = h . bind ( undefined , 'i' ) ; export const iframe = h . bind ( undefined , 'iframe' ) ; export const img = h . bind ( undefined , 'img' ) ; export const input = h . bind ( undefined , 'input' ) ; export const ins = h . bind ( undefined , 'ins' ) ; export const kbd = h . bind ( undefined , 'kbd' ) ; export const label = h . bind ( undefined , 'label' ) ; export const legend = h . bind ( undefined , 'legend' ) ; export const li = h . bind ( undefined , 'li' ) ; export const main = h . bind ( undefined , 'main' ) ; export const map = h . bind ( undefined , 'map' ) ; export const mark = h . bind ( undefined , 'mark' ) ; export const meter = h . bind ( undefined , 'meter' ) ; export const nav = h . bind ( undefined , 'nav' ) ; export const noscript = h . bind ( undefined , 'noscript' ) ; export const object = h . bind ( undefined , 'object' ) ; export const ol = h . bind ( undefined , 'ol' ) ; export const optgroup = h . bind ( undefined , 'optgroup' ) ; export const option = h . bind ( undefined , 'option' ) ; export const output = h . bind ( undefined , 'output' ) ; export const p = h . bind ( undefined , 'p' ) ; export const param = h . bind ( undefined , 'param' ) ; export const pre = h . bind ( undefined , 'pre' ) ; export const progress = h . bind ( undefined , 'progress' ) ; export const q = h . bind ( undefined , 'q' ) ; export const rp = h . bind ( undefined , 'rp' ) ; export const rt = h . bind ( undefined , 'rt' ) ; export const ruby = h . bind ( undefined , 'ruby' ) ; export const s = h . bind ( undefined , 's' ) ; export const samp = h . bind ( undefined , 'samp' ) ; export const section = h . bind ( undefined , 'section' ) ; export const select = h . bind ( undefined , 'select' ) ; export const small = h . bind ( undefined , 'small' ) ; export const source = h . bind ( undefined , 'source' ) ; export const span = h . bind ( undefined , 'span' ) ; export const strong = h . bind ( undefined , 'strong' ) ; export const sub = h . bind ( undefined , 'sub' ) ; export const summary = h . bind ( undefined , 'summary' ) ; export const sup = h . bind ( undefined , 'sup' ) ; export const table = h . bind ( undefined , 'table' ) ; export const tbody = h . bind ( undefined , 'tbody' ) ; export const td = h . bind ( undefined , 'td' ) ; export const textarea = h . bind ( undefined , 'textarea' ) ; export const tfoot = h . bind ( undefined , 'tfoot' ) ; export const th = h . bind ( undefined , 'th' ) ; export const thead = h . bind ( undefined , 'thead' ) ; export const time = h . bind ( undefined , 'time' ) ; export const title = h . bind ( undefined , 'title' ) ; export const tr = h . bind ( undefined , 'tr' ) ; export const track = h . bind ( undefined , 'track' ) ; export const u = h . bind ( undefined , 'u' ) ; export const ul = h . bind ( undefined , 'ul' ) ; export const var_ = h . bind ( undefined , 'var' ) ; export const video = h . bind ( undefined , 'video' ) ; export const wbr = h . bind ( undefined , 'wbr' ) ; } param tag param attrs param renderer returns export function hpass ( tag , renderer ? ) ; export function hpass ( tag , attrs , renderer ? ) ; export function hpass ( tag ) { let attrs = { } ; let renderer = null ; if ( arguments . length === 2 ) { const arg = arguments [ 1 ] ; if ( 'render' in arg ) { renderer = arg ; } else { attrs = arg ; } } else if ( arguments . length === 3 ) { attrs = arguments [ 1 ] ; renderer = arguments [ 2 ] ; } else if ( arguments . length > 3 ) { throw new Error ( 'hpass() should be called with 1, 2, or 3 arguments' ) ; } return new VirtualElementPass ( tag , attrs , renderer ) ; } /**
 * The namespace for the virtual DOM rendering functions.
 */ export namespace VirtualDOM { param node returns export function realize ( node ) ; export function realize ( node ) ; export function realize ( node ) { return Private . createDOMNode ( node ) ; } param content param host export function render ( content , host ) { let oldContent = Private . hostMap . get ( host ) || [ ] ; let newContent = Private . asContentArray ( content ) ; Private . hostMap . set ( host , newContent ) ; Private . updateContent ( host , oldContent , newContent ) ; } } /**
 * The namespace for the module implementation details.
 */ namespace Private { /**
     * A weak mapping of host element to virtual DOM content.
     */ export const hostMap = new WeakMap < HTMLElement , ReadonlyArray < VirtualNode > > ( ) ; /**
     * Cast a content value to a content array.
     */ export function asContentArray ( value ) { if ( ! value ) { return [ ] ; } if ( value instanceof Array ) { return value as ReadonlyArray < VirtualNode > ; } return [ value as VirtualNode ] ; } /**
     * Create a new DOM element for a virtual node.
     */ export function createDOMNode ( node ) ; export function createDOMNode ( node ) ; export function createDOMNode ( node ) ; export function createDOMNode ( node , host ) ; export function createDOMNode ( node , host , before ) ; export function createDOMNode ( node ) { let host = arguments [ 1 ] || null ; const before = arguments [ 2 ] || null ; if ( host ) { host . insertBefore ( createDOMNode ( node ) , before ) ; } else { if ( node . type === 'text' ) { return document . createTextNode ( node . content ) ; } host = document . createElement ( node . tag ) ; addAttrs ( host , node . attrs ) ; if ( node . renderer ) { node . renderer . render ( host , { attrs : node . attrs , children : node . children } ) ; return host ; } for ( let i = 0 , n = node . children . length ; i < n ; ++ i ) { createDOMNode ( node . children [ i ] , host ) ; } } return host ; } /**
     * Update a host element with the delta of the virtual content.
     *
     * This is the core "diff" algorithm. There is no explicit "patch"
     * phase. The host is patched at each step as the diff progresses.
     */ export function updateContent ( host , oldContent , newContent ) { if ( oldContent === newContent ) { return ; } let oldKeyed = collectKeys ( host , oldContent ) ; let oldCopy = oldContent . slice ( ) ; let currElem = host . firstChild ; let newCount = newContent . length ; for ( let i = 0 ; i < newCount ; ++ i ) { if ( i >= oldCopy . length ) { createDOMNode ( newContent [ i ] , host ) ; continue ; } let oldVNode = oldCopy [ i ] ; let newVNode = newContent [ i ] ; if ( oldVNode === newVNode ) { currElem = currElem ! . nextSibling ; continue ; } if ( oldVNode . type === 'text' && newVNode . type === 'text' ) { currElem ! . textContent = newVNode . content ; currElem = currElem ! . nextSibling ; continue ; } if ( oldVNode . type === 'text' || newVNode . type === 'text' ) { ArrayExt . insert ( oldCopy , i , newVNode ) ; createDOMNode ( newVNode , host , currElem ) ; continue ; } if ( ! oldVNode . renderer != ! newVNode . renderer ) { ArrayExt . insert ( oldCopy , i , newVNode ) ; createDOMNode ( newVNode , host , currElem ) ; continue ; } let newKey = newVNode . attrs . key ; if ( newKey && newKey in oldKeyed ) { let pair = oldKeyed [ newKey ] ; if ( pair . vNode !== oldVNode ) { ArrayExt . move ( oldCopy , oldCopy . indexOf ( pair . vNode , i + 1 ) , i ) ; host . insertBefore ( pair . element , currElem ) ; oldVNode = pair . vNode ; currElem = pair . element ; } } if ( oldVNode === newVNode ) { currElem = currElem ! . nextSibling ; continue ; } let oldKey = oldVNode . attrs . key ; if ( oldKey && oldKey !== newKey ) { ArrayExt . insert ( oldCopy , i , newVNode ) ; createDOMNode ( newVNode , host , currElem ) ; continue ; } if ( oldVNode . tag !== newVNode . tag ) { ArrayExt . insert ( oldCopy , i , newVNode ) ; createDOMNode ( newVNode , host , currElem ) ; continue ; } updateAttrs ( currElem as HTMLElement , oldVNode . attrs , newVNode . attrs ) ; if ( newVNode . renderer ) { newVNode . renderer . render ( currElem as HTMLElement , { attrs : newVNode . attrs , children : newVNode . children } ) ; } else { updateContent ( currElem as HTMLElement , oldVNode . children , newVNode . children ) ; } currElem = currElem ! . nextSibling ; } removeContent ( host , oldCopy , newCount , true ) ; } /**
     * Handle cleanup of stale vdom and its associated DOM. The host node is
     * traversed recursively (in depth-first order), and any explicit cleanup
     * required by a child node is carried out when it is visited (eg if a node
     * has a custom renderer, the renderer.unrender function will be called).
     * Once the subtree beneath each child of host has been completely visited,
     * that child will be removed via a call to host.removeChild.
     */ function removeContent ( host , oldContent , newCount , _sentinel ) { for ( let i = oldContent . length - 1 ; i >= newCount ; -- i ) { const oldNode = oldContent [ i ] ; const child = ( _sentinel ? host . lastChild : host . childNodes [ i ] ) as HTMLElement ; if ( oldNode . type === 'text' ) { } else if ( oldNode . renderer && oldNode . renderer . unrender ) { oldNode . renderer . unrender ( child ! , { attrs : oldNode . attrs , children : oldNode . children } ) ; } else { removeContent ( child ! , oldNode . children , 0 , false ) ; } if ( _sentinel ) { host . removeChild ( child ! ) ; } } } /**
     * A set of special-cased attribute names.
     */ const specialAttrs = { key : true , className : true , htmlFor : true , dataset : true , style : true } ; /**
     * Add element attributes to a newly created HTML element.
     */ function addAttrs ( element , attrs ) { for ( let name in attrs ) { if ( name in specialAttrs ) { continue ; } if ( name . substr ( 0 , 2 ) === 'on' ) { ( element as any ) [ name ] = ( attrs as any ) [ name ] ; } else { element . setAttribute ( name , ( attrs as any ) [ name ] ) ; } } if ( attrs . className !== undefined ) { element . setAttribute ( 'class' , attrs . className ) ; } if ( attrs . htmlFor !== undefined ) { element . setAttribute ( 'for' , attrs . htmlFor ) ; } if ( attrs . dataset ) { addDataset ( element , attrs . dataset ) ; } if ( attrs . style ) { addStyle ( element , attrs . style ) ; } } /**
     * Update the element attributes of an HTML element.
     */ function updateAttrs ( element , oldAttrs , newAttrs ) { if ( oldAttrs === newAttrs ) { return ; } let name ; for ( name in oldAttrs ) { if ( name in specialAttrs || name in newAttrs ) { continue ; } if ( name . substr ( 0 , 2 ) === 'on' ) { ( element as any ) [ name ] = null ; } else { element . removeAttribute ( name ) ; } } for ( name in newAttrs ) { if ( name in specialAttrs || oldAttrs [ name ] === newAttrs [ name ] ) { continue ; } if ( name . substr ( 0 , 2 ) === 'on' ) { ( element as any ) [ name ] = ( newAttrs as any ) [ name ] ; } else { element . setAttribute ( name , ( newAttrs as any ) [ name ] ) ; } } if ( oldAttrs . className !== newAttrs . className ) { if ( newAttrs . className !== undefined ) { element . setAttribute ( 'class' , newAttrs . className ) ; } else { element . removeAttribute ( 'class' ) ; } } if ( oldAttrs . htmlFor !== newAttrs . htmlFor ) { if ( newAttrs . htmlFor !== undefined ) { element . setAttribute ( 'for' , newAttrs . htmlFor ) ; } else { element . removeAttribute ( 'for' ) ; } } if ( oldAttrs . dataset !== newAttrs . dataset ) { updateDataset ( element , oldAttrs . dataset || { } , newAttrs . dataset || { } ) ; } if ( oldAttrs . style !== newAttrs . style ) { updateStyle ( element , oldAttrs . style || { } , newAttrs . style || { } ) ; } } /**
     * Add dataset values to a newly created HTML element.
     */ function addDataset ( element , dataset ) { for ( let name in dataset ) { element . setAttribute ( `data-${ name }` , dataset [ name ] ) ; } } /**
     * Update the dataset values of an HTML element.
     */ function updateDataset ( element , oldDataset , newDataset ) { for ( let name in oldDataset ) { if ( ! ( name in newDataset ) ) { element . removeAttribute ( `data-${ name }` ) ; } } for ( let name in newDataset ) { if ( oldDataset [ name ] !== newDataset [ name ] ) { element . setAttribute ( `data-${ name }` , newDataset [ name ] ) ; } } } /**
     * Add inline style values to a newly created HTML element.
     */ function addStyle ( element , style ) { let elemStyle = element . style ; let name ; for ( name in style ) { ( elemStyle as any ) [ name ] = style [ name ] ; } } /**
     * Update the inline style values of an HTML element.
     */ function updateStyle ( element , oldStyle , newStyle ) { let elemStyle = element . style ; let name ; for ( name in oldStyle ) { if ( ! ( name in newStyle ) ) { ( elemStyle as any ) [ name ] = '' ; } } for ( name in newStyle ) { if ( oldStyle [ name ] !== newStyle [ name ] ) { ( elemStyle as any ) [ name ] = newStyle [ name ] ; } } } /**
     * A mapping of string key to pair of element and rendered node.
     */ type KeyMap = { [ key ] : { vNode : VirtualElement ; element : HTMLElement ; } ; } ; /**
     * Collect a mapping of keyed elements for the host content.
     */ function collectKeys ( host , content ) { let node = host . firstChild ; let keyMap = Object . create ( null ) ; for ( let vNode of content ) { if ( vNode . type === 'element' && vNode . attrs . key ) { keyMap [ vNode . attrs . key ] = { vNode , element : node as HTMLElement } ; } node = node ! . nextSibling ; } return keyMap ; } }