updatePosition(): void {
    this.x = (Graphics.width - this.bitmap!.width) / 2;
    this.y = 0;
  }


updateVisibility(): void {
    this.visible = $gameTimer.isWorking();
  }


(resolve) => {
      const request = get(APPIUM_SERVER_URL, () => {
        resolve(true);
      });
      request.on("error", () => {
        resolve(false);
      });
    }


() => {
        resolve(true);
      }


() => {
        resolve(false);
      }


/**
 * Appium health checker.
 */
export default class AppiumHealthChecker {
  /**
   * Whether Appium server is started or not.
   * @returns 'true': Appium server is started, 'false': Appium server is not started.
   */
  public static async appiumIsStarted(): Promise<boolean> {
    return new Promise<boolean>((resolve) => {
      const request = get(APPIUM_SERVER_URL, () => {
        resolve(true);
      });
      request.on("error", () => {
        resolve(false);
      });
    });
  }
}


/**
   * Whether Appium server is started or not.
   * @returns 'true': Appium server is started, 'false': Appium server is not started.
   */
public static async appiumIsStarted(): Promise<boolean> {
    return new Promise<boolean>((resolve) => {
      const request = get(APPIUM_SERVER_URL, () => {
        resolve(true);
      });
      request.on("error", () => {
        resolve(false);
      });
    });
  }


({ onSubmit, onCancel, type, token, maxAmount = 0 }) => {
    const [value, setValue] = useState<string>(``);
    const isValid = amountRegex.test(value)

    const handleSubmit = (evt) => {
        evt.preventDefault();
        onSubmit(decomposeAsset(makeAssetString(value, token.symbol)));
    };

    const handleMaxClick = () => {
        setValue(formatAsset({ amount: maxAmount, symbol: token.symbol }, { withSymbol: false }));
    };

    const renderTitle = () => {
        switch (type) {
            case `DEPOSIT`:
                return <FormattedMessage id="modalDepositTitle" defaultMessage="Deposit {symbol}" values={{ symbol: token.symbol.code }} />


(evt) => {
        evt.preventDefault();
        onSubmit(decomposeAsset(makeAssetString(value, token.symbol)));
    }


() => {
        setValue(formatAsset({ amount: maxAmount, symbol: token.symbol }, { withSymbol: false }));
    }


() => {
        switch (type) {
            case `DEPOSIT`:
                return <FormattedMessage id="modalDepositTitle" defaultMessage="Deposit {symbol}" values={{ symbol: token.symbol.code }} />


() => {
        switch (type) {
            case `DEPOSIT`:
                return <FormattedMessage id="modalDepositButton" defaultMessage="Deposit" />
            case `WITHDRAW`:
                return <FormattedMessage id="modalWithdrawButton" defaultMessage="Withdraw" />
            case `BORROW`:
                return <FormattedMessage id="modalBorrowButton" defaultMessage="Borrow" />
            case `PAYOFFDEBT`:
                return <FormattedMessage id="modalPayoffDebtButton" defaultMessage="Payoff Debt" />
        }
    }


type Props = {
    onSubmit: (data: TAsset) => void;
    onCancel: () => void;
    type: TokenModalTypes,
    token: TExtendedSymbol;
    maxAmount?: number
};


renderTitle()


renderButtonText()


export default function serveFile(req: IncomingMessage, res: ServerResponse) {
  const fileExtension = path.extname(req?.url || '')
  const output = fs.createReadStream(`${process.cwd()}/build/${req.url}`)
  res.setHeader('Vary', 'Accept-Encoding')
  let acceptEncoding = req.headers['accept-encoding']
  if (!acceptEncoding) {
    acceptEncoding = ''
  }
  const onError = (err: NodeJS.ErrnoException | null) => {
    if (err) {
      res.end()
      console.error('An error occurred:', err)
    }
  }
  res.setHeader('Content-Type', setContentType(fileExtension))
  if (/\bbr\b/.test(acceptEncoding as string)) {
    res.writeHead(200, { 'Content-Encoding': 'br' })
    stream.pipeline(output, zlib.createBrotliCompress(), res, onError)
  } else if (/\bgzip\b/.test(acceptEncoding as string)) {
    res.writeHead(200, { 'Content-Encoding': 'gzip' })
    stream.pipeline(output, zlib.createGzip(), res, onError)
  } else if (/\bdeflate\b/.test(acceptEncoding as string)) {
    res.writeHead(200, { 'Content-Encoding': 'deflate' })
    stream.pipeline(output, zlib.createDeflate(), res, onError)
  } else {
    res.writeHead(200, {})
    stream.pipeline(output, res, onError)
  }
}


(extension: string) => {
  return supported[extension as keyof typeof supported] || 'text/plain'
}


(err: NodeJS.ErrnoException | null) => {
    if (err) {
      res.end()
      console.error('An error occurred:', err)
    }
  }


/**
 * Returns a function which can access individual cell data in a DataFrame.
 *
 * The returned function has the form:
 *
 * cellContentsGetter(columnIndex: int, rowIndex: int) -> {
 *    classes: str - a css class string
 *    styles: {property1: value1, ...} - css styles to apply to the cell
 *    contents: str - the cell's formatted display string
 * }
 *
 * element              - a DataFrame
 * headerRows           - the number of frozen rows
 * headerCols           - the number of frozen columns
 * sortedDataRowIndices - (optional) an array containing an ordering for row indices
 */
export function getCellContentsGetter({
  element,
  headerRows,
  sortedDataRowIndices,
}: CellContentsGetterProps): CellContentsGetter {
  return (columnIndex: number, rowIndex: number): CellContents => {
    if (sortedDataRowIndices != null && rowIndex >= headerRows) {
      // If we have a sortedDataRowIndices Array, it contains a mapping of row indices for
      // all *data* (non-header) rows.
      const sortIdx = rowIndex - headerRows
      if (sortIdx >= 0 && sortIdx < sortedDataRowIndices.length) {
        rowIndex = sortedDataRowIndices[sortIdx]
        rowIndex += headerRows
      } else {
        logWarning(
          `Bad sortedDataRowIndices (` +
            `rowIndex=${rowIndex}, ` +
            `headerRows=${headerRows}, ` +
            `sortedDataRowIndices.length=${sortedDataRowIndices.length}`
        )
      }
    }

    const { contents, styles, type } = dataFrameGet(
      element,
      columnIndex,
      rowIndex
    )

    // All table elements have class 'dataframe'.
    const Component = typeToStyledComponent[type]

    // Format floating point numbers nicely.
    const fsContents = toFormattedString(contents)

    // Put it all together
    return { Component, styles, contents: fsContents }
  }
}


/**
 * Computes various dimensions for the table.
 *
 * First of all we create an array containing all the calculated column widths,
 * if the difference between the total of columns and the container width is negative
 * we put a width limit, if not, we divide the remaining space by each exceeding width
 */
export function getWidths(
  cols: number,
  rows: number,
  headerCols: number,
  headerRows: number,
  containerWidth: number,
  cellContentsGetter: CellContentsGetter
): ComputedWidths {
  const minWidth = MIN_CELL_WIDTH_PX
  const maxWidth =
    cols > 2 // 2 because 1 column is the index.
      ? MAX_CELL_WIDTH_PX
      : MAX_LONELY_CELL_WIDTH_PX

  // Calculate column width based on character count alone.
  const calculateColumnWidth = ({ index }: { index: number }): number => {
    const colIndex = index
    const fontSize = 10
    const charWidth = (fontSize * 8) / 10
    const padding = 14 + SORT_ICON_WIDTH_PX // 14 for whitespace; an extra 10 for the optional sort arrow icon

    // Set the colWidth to the maximum width of a column.
    const maxRows = 100
    let colWidth = minWidth
    for (let i = 0; i < Math.min(rows, maxRows); i++) {
      let rowIndex = -1
      if (i < headerRows) {
        // Always measure all the header rows.
        rowIndex = i
      } else if (rows > maxRows) {
        // If there are a lot of rows, then pick some at random.
        rowIndex = Math.floor(Math.random() * rows)
      } else {
        // Otherwise, just measure every row.
        rowIndex = i
      }
      const { contents } = cellContentsGetter(colIndex, rowIndex)
      const nChars = contents ? contents.length : 0
      const cellWidth = nChars * charWidth + padding

      if (cellWidth > colWidth) {
        colWidth = cellWidth
      }
    }
    return colWidth
  }

  let distributedTable: Array<number> = []
  const tableColumnWidth: Array<number> = Array.from(Array(cols), (_, index) =>
    calculateColumnWidth({ index })
  )
  const totalTableWidth = tableColumnWidth.reduce((a, b) => a + b, 0)
  const remainingSpace = containerWidth - totalTableWidth
  const getColumnsThatExceedMaxWidth = (
    columns: Array<number>
  ): Array<number> => columns.filter(width => width > maxWidth)

  if (remainingSpace < 0) {
    distributedTable = tableColumnWidth.map(width =>
      width > maxWidth ? maxWidth : width
    )
  } else {
    const columnsThatExceed = getColumnsThatExceedMaxWidth(tableColumnWidth)
    const remainingSpaceByColumn = remainingSpace / columnsThatExceed.length

    distributedTable = tableColumnWidth.map((width, id) => {
      if (id in columnsThatExceed.keys()) {
        return width + remainingSpaceByColumn
      }

      return width
    })
  }

  let distributedTableTotal = distributedTable.reduce((a, b) => a + b, 0)
  if (
    distributedTableTotal > containerWidth * (2 / 3) &&
    distributedTableTotal < containerWidth
  ) {
    const remainingSpace = (containerWidth - distributedTableTotal) / cols
    distributedTable = distributedTable.map(width => width + remainingSpace)
    distributedTableTotal = distributedTable.reduce((a, b) => a + b, 0)
  }

  const elementWidth = Math.min(distributedTableTotal, containerWidth)
  const needsHorizontalScrollbar = distributedTableTotal > containerWidth
  const columnWidth = ({ index }: { index: number }): number =>
    distributedTable[index]

  const headerWidth = distributedTable
    .slice(0, headerCols)
    .reduce((prev, curr) => prev + curr)

  return {
    elementWidth,
    columnWidth,
    headerWidth,
    needsHorizontalScrollbar,
  }
}


(
  height: number | undefined,
  width: number,
  element: ImmutableMap<string, any>,
  cellContentsGetter: CellContentsGetter
): Dimensions => {
  const {
    headerRows,
    headerCols,
    dataRows,
    cols,
    rows,
  } = dataFrameGetDimensions(element)

  // Rendering constants.
  const rowHeight = 25
  const headerHeight = rowHeight * headerRows
  const border = 2

  // Reserve enough space to render the dataframe border as well as a vertical
  // scrollbar if necessary.
  const availableWidth = width - border - scrollbarSize()
  const widths = getWidths(
    cols,
    rows,
    headerCols,
    headerRows,
    availableWidth,
    cellContentsGetter
  )

  let { elementWidth, columnWidth, headerWidth } = widths
  const { needsHorizontalScrollbar } = widths

  // Add space for the "empty" text when the table is empty.
  const EMPTY_WIDTH = 60 // px
  if (dataRows === 0 && elementWidth < EMPTY_WIDTH) {
    elementWidth = EMPTY_WIDTH
    headerWidth = EMPTY_WIDTH
    let totalWidth = 0
    for (let i = 0; i < cols; i++) {
      totalWidth += columnWidth({ index: i })
    }
    if (totalWidth < EMPTY_WIDTH) {
      columnWidth = () => EMPTY_WIDTH / cols
    }
  }

  // Allocate extra space for horizontal and vertical scrollbars, if needed.
  const totalHeight = rows * rowHeight
  const maxHeight = height || DEFAULT_HEIGHT

  const horizScrollbarHeight = needsHorizontalScrollbar ? scrollbarSize() : 0
  height = Math.min(totalHeight + horizScrollbarHeight, maxHeight)

  const needsVerticalScrollbar = totalHeight > maxHeight
  elementWidth += needsVerticalScrollbar ? scrollbarSize() : 0

  return {
    rowHeight,
    headerHeight,
    border,
    columnWidth,
    headerWidth,
    elementWidth,
    height,
  }
}


() => EMPTY_WIDTH / cols


(columnIndex: number, rowIndex: number): CellContents => {
    if (sortedDataRowIndices != null && rowIndex >= headerRows) {
      // If we have a sortedDataRowIndices Array, it contains a mapping of row indices for
      // all *data* (non-header) rows.
      const sortIdx = rowIndex - headerRows
      if (sortIdx >= 0 && sortIdx < sortedDataRowIndices.length) {
        rowIndex = sortedDataRowIndices[sortIdx]
        rowIndex += headerRows
      } else {
        logWarning(
          `Bad sortedDataRowIndices (` +
            `rowIndex=${rowIndex}, ` +
            `headerRows=${headerRows}, ` +
            `sortedDataRowIndices.length=${sortedDataRowIndices.length}`
        )
      }
    }

    const { contents, styles, type } = dataFrameGet(
      element,
      columnIndex,
      rowIndex
    )

    // All table elements have class 'dataframe'.
    const Component = typeToStyledComponent[type]

    // Format floating point numbers nicely.
    const fsContents = toFormattedString(contents)

    // Put it all together
    return { Component, styles, contents: fsContents }
  }


({ index }: { index: number }): number => {
    const colIndex = index
    const fontSize = 10
    const charWidth = (fontSize * 8) / 10
    const padding = 14 + SORT_ICON_WIDTH_PX // 14 for whitespace; an extra 10 for the optional sort arrow icon

    // Set the colWidth to the maximum width of a column.
    const maxRows = 100
    let colWidth = minWidth
    for (let i = 0; i < Math.min(rows, maxRows); i++) {
      let rowIndex = -1
      if (i < headerRows) {
        // Always measure all the header rows.
        rowIndex = i
      } else if (rows > maxRows) {
        // If there are a lot of rows, then pick some at random.
        rowIndex = Math.floor(Math.random() * rows)
      } else {
        // Otherwise, just measure every row.
        rowIndex = i
      }
      const { contents } = cellContentsGetter(colIndex, rowIndex)
      const nChars = contents ? contents.length : 0
      const cellWidth = nChars * charWidth + padding

      if (cellWidth > colWidth) {
        colWidth = cellWidth
      }
    }
    return colWidth
  }


(_, index) =>
    calculateColumnWidth({ index })


(
    columns: Array<number>
  ): Array<number> => columns.filter(width => width > maxWidth)


width => width > maxWidth


width =>
      width > maxWidth ? maxWidth : width


(width, id) => {
      if (id in columnsThatExceed.keys()) {
        return width + remainingSpaceByColumn
      }

      return width
    }


width => width + remainingSpace


({ index }: { index: number }): number =>
    distributedTable[index]


(prev, curr) => prev + curr


export interface CellContents {
  Component: ComponentType
  styles: Record<string, unknown>
  contents: string
}


export interface CellContentsGetter {
  (columnIndex: number, rowIndex: number): CellContents
}


export interface CellContentsGetterProps {
  element: ImmutableMap<string, any>
  headerRows: number
  sortedDataRowIndices?: number[]
}


export interface CellRendererInput {
  columnIndex: number
  key: string
  rowIndex: number
  style: React.CSSProperties
}


export interface CellRenderer {
  (input: CellRendererInput): ReactElement
}


interface Dimensions {
  rowHeight: number
  headerHeight: number
  border: number
  height: number
  elementWidth: number
  columnWidth: ({ index }: { index: number }) => number
  headerWidth: number
}


interface ComputedWidths {
  elementWidth: number
  columnWidth: ({ index }: { index: number }) => number
  headerWidth: number
  needsHorizontalScrollbar: boolean
}


/**
 * @description Initialize the TrunkList
 *
 * @param version - Version of the resource
 */
declare function TrunkList(version: V1): TrunkListInstance;


declare class TrunkContext {
  /**
   * Initialize the TrunkContext
   *
   * @property originationUrls - originationUrls resource
   * @property credentialsLists - credentialsLists resource
   * @property ipAccessControlLists - ipAccessControlLists resource
   * @property phoneNumbers - phoneNumbers resource
   *
   * @param version - Version of the resource
   * @param sid - A 34 character string that uniquely identifies the SIP Trunk in Twilio.
   */
  constructor(version: V1, sid: string);

  credentialsLists: CredentialListListInstance;
  /**
   * fetch a TrunkInstance
   *
   * @param callback - Callback to handle processed record
   */
  fetch(callback?: (error: Error | null, items: TrunkInstance) => any): Promise<TrunkInstance>;
  ipAccessControlLists: IpAccessControlListListInstance;
  originationUrls: OriginationUrlListInstance;
  phoneNumbers: PhoneNumberListInstance;
  /**
   * remove a TrunkInstance
   *
   * @param callback - Callback to handle processed record
   */
  remove(callback?: (error: Error | null, items: TrunkInstance) => any): void;
  /**
   * Provide a user-friendly representation
   */
  toJSON(): any;
  /**
   * update a TrunkInstance
   *
   * @param opts - Options for request
   * @param callback - Callback to handle processed record
   */
  update(opts?: TrunkInstanceUpdateOptions, callback?: (error: Error | null, items: TrunkInstance) => any): Promise<TrunkInstance>;
}


declare class TrunkInstance extends SerializableClass {
  /**
   * Initialize the TrunkContext
   *
   * @property accountSid - The unique ID of the Account that owns this Trunk.
   * @property domainName - The unique address you reserve on Twilio to which you route your SIP traffic.
   * @property disasterRecoveryMethod - The HTTP method Twilio will use when requesting the DisasterRecoveryUrl.
   * @property disasterRecoveryUrl - The HTTP URL that Twilio will request if an error occurs while sending SIP traffic towards your configured Origination URL.
   * @property friendlyName - A human-readable name for the Trunk.
   * @property secure - The Secure Trunking  settings for this trunk.
   * @property recording - The recording settings for this trunk.
   * @property cnamLookupEnabled - The Caller ID Name (CNAM) lookup setting for this trunk.
   * @property authType - The types of authentication you have mapped to your domain.
   * @property authTypeSet - The auth_type_set
   * @property dateCreated - The date this Activity was created.
   * @property dateUpdated - The date this Activity was updated.
   * @property sid - A 34 character string that uniquely identifies the SIP Trunk in Twilio.
   * @property url - The URL for this resource, relative to https://trunking.
   * @property links - The links
   *
   * @param version - Version of the resource
   * @param payload - The instance payload
   * @param sid - A 34 character string that uniquely identifies the SIP Trunk in Twilio.
   */
  constructor(version: V1, payload: TrunkPayload, sid: string);

  private _proxy: TrunkContext;
  accountSid: string;
  authType: string;
  authTypeSet: string;
  cnamLookupEnabled: boolean;
  /**
   * Access the credentialsLists
   */
  credentialsLists(): CredentialListListInstance;
  dateCreated: Date;
  dateUpdated: Date;
  disasterRecoveryMethod: string;
  disasterRecoveryUrl: string;
  domainName: string;
  /**
   * fetch a TrunkInstance
   *
   * @param callback - Callback to handle processed record
   */
  fetch(callback?: (error: Error | null, items: TrunkInstance) => any): void;
  friendlyName: string;
  /**
   * Access the ipAccessControlLists
   */
  ipAccessControlLists(): IpAccessControlListListInstance;
  links: string;
  /**
   * Access the originationUrls
   */
  originationUrls(): OriginationUrlListInstance;
  /**
   * Access the phoneNumbers
   */
  phoneNumbers(): PhoneNumberListInstance;
  recording: string;
  /**
   * remove a TrunkInstance
   *
   * @param callback - Callback to handle processed record
   */
  remove(callback?: (error: Error | null, items: TrunkInstance) => any): void;
  secure: boolean;
  sid: string;
  /**
   * Provide a user-friendly representation
   */
  toJSON(): any;
  /**
   * update a TrunkInstance
   *
   * @param opts - Options for request
   * @param callback - Callback to handle processed record
   */
  update(opts?: TrunkInstanceUpdateOptions, callback?: (error: Error | null, items: TrunkInstance) => any): void;
  url: string;
}


declare class TrunkPage extends Page<V1, TrunkPayload, TrunkResource, TrunkInstance> {
  /**
   * Initialize the TrunkPage
   *
   * @param version - Version of the resource
   * @param response - Response from the API
   * @param solution - Path solution
   */
  constructor(version: V1, response: Response<string>, solution: TrunkSolution);

  /**
   * Build an instance of TrunkInstance
   *
   * @param payload - Payload response from the API
   */
  getInstance(payload: TrunkPayload): TrunkInstance;
  /**
   * Provide a user-friendly representation
   */
  toJSON(): any;
}


/**
 * Options to pass to update
 *
 * @property cnamLookupEnabled - The Caller ID Name (CNAM) lookup setting for this trunk.
 * @property disasterRecoveryMethod - The HTTP method Twilio will use when requesting the DisasterRecoveryUrl.
 * @property disasterRecoveryUrl - The HTTP URL that Twilio will request if an error occurs while sending SIP traffic towards your configured Origination URL.
 * @property domainName - The unique address you reserve on Twilio to which you route your SIP traffic.
 * @property friendlyName - A human-readable name for the Trunk.
 * @property recording - The recording settings for this trunk.
 * @property secure - The Secure Trunking  settings for this trunk.
 */
interface TrunkInstanceUpdateOptions {
  cnamLookupEnabled?: boolean;
  disasterRecoveryMethod?: string;
  disasterRecoveryUrl?: string;
  domainName?: string;
  friendlyName?: string;
  recording?: TrunkRecordingSetting;
  secure?: boolean;
}


interface TrunkListInstance {
  /**
   * @param sid - sid of instance
   */
  (sid: string): TrunkContext;
  /**
   * create a TrunkInstance
   *
   * @param opts - Options for request
   * @param callback - Callback to handle processed record
   */
  create(opts?: TrunkListInstanceCreateOptions, callback?: (error: Error | null, item: TrunkInstance) => any): Promise<TrunkInstance>;
  /**
   * Streams TrunkInstance records from the API.
   *
   * This operation lazily loads records as efficiently as possible until the limit
   * is reached.
   *
   * The results are passed into the callback function, so this operation is memory efficient.
   *
   * If a function is passed as the first argument, it will be used as the callback function.
   *
   * @param opts - Options for request
   * @param callback - Function to process each record
   */
  each(opts?: TrunkListInstanceEachOptions, callback?: (item: TrunkInstance, done: (err?: Error) => void) => void): void;
  /**
   * Constructs a trunk
   *
   * @param sid - A 34 character string that uniquely identifies the SIP Trunk in Twilio.
   */
  get(sid: string): TrunkContext;
  /**
   * Retrieve a single target page of TrunkInstance records from the API.
   * Request is executed immediately
   *
   * If a function is passed as the first argument, it will be used as the callback function.
   *
   * @param targetUrl - API-generated URL for the requested results page
   * @param callback - Callback to handle list of records
   */
  getPage(targetUrl?: string, callback?: (error: Error | null, items: TrunkPage) => any): Promise<TrunkPage>;
  /**
   * Lists TrunkInstance records from the API as a list.
   *
   * If a function is passed as the first argument, it will be used as the callback function.
   *
   * @param opts - Options for request
   * @param callback - Callback to handle list of records
   */
  list(opts?: TrunkListInstanceOptions, callback?: (error: Error | null, items: TrunkInstance[]) => any): Promise<TrunkInstance[]>;
  /**
   * Retrieve a single page of TrunkInstance records from the API.
   * Request is executed immediately
   *
   * If a function is passed as the first argument, it will be used as the callback function.
   *
   * @param opts - Options for request
   * @param callback - Callback to handle list of records
   */
  page(opts?: TrunkListInstancePageOptions, callback?: (error: Error | null, items: TrunkPage) => any): Promise<TrunkPage>;
  /**
   * Provide a user-friendly representation
   */
  toJSON(): any;
}


/**
 * Options to pass to create
 *
 * @property cnamLookupEnabled - The Caller ID Name (CNAM) lookup setting for this trunk.
 * @property disasterRecoveryMethod - The HTTP method Twilio will use when requesting the DisasterRecoveryUrl.
 * @property disasterRecoveryUrl - The HTTP URL that Twilio will request if an error occurs while sending SIP traffic towards your configured Origination URL.
 * @property domainName - The unique address you reserve on Twilio to which you route your SIP traffic.
 * @property friendlyName - A human-readable name for the Trunk.
 * @property recording - The recording settings for this trunk.
 * @property secure - The Secure Trunking  settings for this trunk.
 */
interface TrunkListInstanceCreateOptions {
  cnamLookupEnabled?: boolean;
  disasterRecoveryMethod?: string;
  disasterRecoveryUrl?: string;
  domainName?: string;
  friendlyName?: string;
  recording?: TrunkRecordingSetting;
  secure?: boolean;
}


/**
 * Options to pass to each
 *
 * @property callback -
 *                         Function to process each record. If this and a positional
 *                         callback are passed, this one will be used
 * @property done - Function to be called upon completion of streaming
 * @property limit -
 *                         Upper limit for the number of records to return.
 *                         each() guarantees never to return more than limit.
 *                         Default is no limit
 * @property pageSize -
 *                         Number of records to fetch per request,
 *                         when not set will use the default value of 50 records.
 *                         If no pageSize is defined but a limit is defined,
 *                         each() will attempt to read the limit with the most efficient
 *                         page size, i.e. min(limit, 1000)
 */
interface TrunkListInstanceEachOptions {
  callback?: (item: TrunkInstance, done: (err?: Error) => void) => void;
  done?: Function;
  limit?: number;
  pageSize?: number;
}


/**
 * Options to pass to list
 *
 * @property limit -
 *                         Upper limit for the number of records to return.
 *                         list() guarantees never to return more than limit.
 *                         Default is no limit
 * @property pageSize -
 *                         Number of records to fetch per request,
 *                         when not set will use the default value of 50 records.
 *                         If no page_size is defined but a limit is defined,
 *                         list() will attempt to read the limit with the most
 *                         efficient page size, i.e. min(limit, 1000)
 */
interface TrunkListInstanceOptions {
  limit?: number;
  pageSize?: number;
}


/**
 * Options to pass to page
 *
 * @property pageNumber - Page Number, this value is simply for client state
 * @property pageSize - Number of records to return, defaults to 50
 * @property pageToken - PageToken provided by the API
 */
interface TrunkListInstancePageOptions {
  pageNumber?: number;
  pageSize?: number;
  pageToken?: string;
}


interface TrunkPayload extends TrunkResource, Page.TwilioResponsePayload {
}


interface TrunkResource {
  account_sid: string;
  auth_type: string;
  auth_type_set: string;
  cnam_lookup_enabled: boolean;
  date_created: Date;
  date_updated: Date;
  disaster_recovery_method: string;
  disaster_recovery_url: string;
  domain_name: string;
  friendly_name: string;
  links: string;
  recording: string;
  secure: boolean;
  sid: string;
  url: string;
}


interface TrunkSolution {
}


type TrunkRecordingSetting = 'do-not-record'|'record-from-ringing'|'record-from-answer';


/**
   * fetch a TrunkInstance
   *
   * @param callback - Callback to handle processed record
   */
fetch(callback?: (error: Error | null, items: TrunkInstance) => any): Promise<TrunkInstance>;


/**
   * remove a TrunkInstance
   *
   * @param callback - Callback to handle processed record
   */
remove(callback?: (error: Error | null, items: TrunkInstance) => any): void;


/**
   * Provide a user-friendly representation
   */
toJSON(): any;


/**
   * update a TrunkInstance
   *
   * @param opts - Options for request
   * @param callback - Callback to handle processed record
   */
update(opts?: TrunkInstanceUpdateOptions, callback?: (error: Error | null, items: TrunkInstance) => any): Promise<TrunkInstance>;


/**
   * Access the credentialsLists
   */
credentialsLists(): CredentialListListInstance;


/**
   * fetch a TrunkInstance
   *
   * @param callback - Callback to handle processed record
   */
fetch(callback?: (error: Error | null, items: TrunkInstance) => any): void;


/**
   * Access the ipAccessControlLists
   */
ipAccessControlLists(): IpAccessControlListListInstance;


/**
   * Access the originationUrls
   */
originationUrls(): OriginationUrlListInstance;


/**
   * Access the phoneNumbers
   */
phoneNumbers(): PhoneNumberListInstance;


/**
   * update a TrunkInstance
   *
   * @param opts - Options for request
   * @param callback - Callback to handle processed record
   */
update(opts?: TrunkInstanceUpdateOptions, callback?: (error: Error | null, items: TrunkInstance) => any): void;


/**
   * Build an instance of TrunkInstance
   *
   * @param payload - Payload response from the API
   */
getInstance(payload: TrunkPayload): TrunkInstance;


(data) => {
      this.carregando = false;
      this.semconteudo = data.length <= 0;
      this.data = data;
      this.dataSource = new MatTableDataSource(this.data);
      this.dataSource.sort = this.sort;
      this.dataSource.paginator = this.paginator;

      this.dataSource.sortingDataAccessor = (item, property) => {
        console.log(item)
        switch (property) {
          case 'data_entrega': {
            let d : firebase.firestore.Timestamp;
            d  = item.data as unknown as firebase.firestore.Timestamp;
            return new Date(d.toDate());
          }
          default: return item[property];
        }
      };

    }


(item, property) => {
        console.log(item)
        switch (property) {
          case 'data_entrega': {
            let d : firebase.firestore.Timestamp;
            d  = item.data as unknown as firebase.firestore.Timestamp;
            return new Date(d.toDate());
          }
          default: return item[property];
        }
      }


(dialogResult) => {
      if (dialogResult == true) {
        this.excluir(m);
      }
    }


() => {
        this.toastr.success("Pedido excluído com sucesso", "Atenção!", {
          closeButton: true,
          progressAnimation: "decreasing",
          progressBar: true,
        });
        this.pedidosService.listar().then((data) => {
          this.data = data;
          this.dataSource = new MatTableDataSource(this.data);
          this.dataSource.sort = this.sort;
          this.dataSource.paginator = this.paginator;
        });
      }


(data) => {
          this.data = data;
          this.dataSource = new MatTableDataSource(this.data);
          this.dataSource.sort = this.sort;
          this.dataSource.paginator = this.paginator;
        }


@Component({
  selector: 'lista-historico-pedidos',
  templateUrl: './lista-historico-pedidos.component.html',
  styleUrls: ['./lista-historico-pedidos.component.css']
})
export class ListaHistoricoPedidosComponent implements AfterViewInit, OnInit {
  @ViewChild(MatPaginator) paginator: MatPaginator;
  @ViewChild(MatSort, { static: false }) sort: MatSort;

  dataSource: MatTableDataSource<Pedido>;

  data:Pedido[] ;

  constructor(
    private pedidosService: PedidosHistoricoService,
    private router: Router,
    private activatedRoute: ActivatedRoute,
    private toastr: ToastrService,
    public dialog: MatDialog,
  ) {}

  order:boolean = false;

  carregando = true;
  semconteudo = false;

  /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */
  displayedColumns = ["_id","numero_celular", "data_entrega","acoes"];

  async ngOnInit() {
     await  this.carregarDados();
  }

  ngAfterViewInit() {

  }

  async carregarDados() {
    this.carregando = true;
    await this.pedidosService.listar().then((data) => {
      this.carregando = false;
      this.semconteudo = data.length <= 0;
      this.data = data;
      this.dataSource = new MatTableDataSource(this.data);
      this.dataSource.sort = this.sort;
      this.dataSource.paginator = this.paginator;

      this.dataSource.sortingDataAccessor = (item, property) => {
        console.log(item)
        switch (property) {
          case 'data_entrega': {
            let d : firebase.firestore.Timestamp;
            d  = item.data as unknown as firebase.firestore.Timestamp;
            return new Date(d.toDate());
          }
          default: return item[property];
        }
      };

    });
  }

  sortDataSource(id: string){
    this.order = !this.order;
    let ord = 'desc';
    if(this.order){
      ord = 'asc'
    }
    this.dataSource.sort.sort(<MatSortable>({id: id, start: ord}));
  }

  adicionar() {
    this.router.navigate(["../cadastro-pedidos", ""], {
      relativeTo: this.activatedRoute,
    });
  }

  editar(id) {
    this.router.navigate(["../historico", id], {
      relativeTo: this.activatedRoute,
    });
  }

  confirmDialog(m): void {
    const message = `Deseja excluir o pedido?`;

    const dialogData = new ConfirmDialogModel("Confirmar", message);

    const dialogRef = this.dialog.open(ConfirmDialogComponent, {
      maxWidth: "400px",
      data: dialogData,
    });

    dialogRef.afterClosed().subscribe((dialogResult) => {
      if (dialogResult == true) {
        this.excluir(m);
      }
    });
  }

  excluir(m: Pedido) {
    if (m._id) {
      this.pedidosService.delete(m._id).then(() => {
        this.toastr.success("Pedido excluído com sucesso", "Atenção!", {
          closeButton: true,
          progressAnimation: "decreasing",
          progressBar: true,
        });
        this.pedidosService.listar().then((data) => {
          this.data = data;
          this.dataSource = new MatTableDataSource(this.data);
          this.dataSource.sort = this.sort;
          this.dataSource.paginator = this.paginator;
        });
      });
    }
  }

  applyFilter(filterValue: string) {
    filterValue = filterValue.trim(); // Remove whitespace
    filterValue = filterValue.toLowerCase(); // Datasource defaults to lowercase matches
    this.dataSource.filter = filterValue;
  }
}


async ngOnInit() {
     await  this.carregarDados();
  }


ngAfterViewInit() {

  }


async carregarDados() {
    this.carregando = true;
    await this.pedidosService.listar().then((data) => {
      this.carregando = false;
      this.semconteudo = data.length <= 0;
      this.data = data;
      this.dataSource = new MatTableDataSource(this.data);
      this.dataSource.sort = this.sort;
      this.dataSource.paginator = this.paginator;

      this.dataSource.sortingDataAccessor = (item, property) => {
        console.log(item)
        switch (property) {
          case 'data_entrega': {
            let d : firebase.firestore.Timestamp;
            d  = item.data as unknown as firebase.firestore.Timestamp;
            return new Date(d.toDate());
          }
          default: return item[property];
        }
      };

    });
  }


sortDataSource(id: string){
    this.order = !this.order;
    let ord = 'desc';
    if(this.order){
      ord = 'asc'
    }
    this.dataSource.sort.sort(<MatSortable>({id: id, start: ord}));
  }


adicionar() {
    this.router.navigate(["../cadastro-pedidos", ""], {
      relativeTo: this.activatedRoute,
    });
  }


editar(id) {
    this.router.navigate(["../historico", id], {
      relativeTo: this.activatedRoute,
    });
  }


confirmDialog(m): void {
    const message = `Deseja excluir o pedido?`;

    const dialogData = new ConfirmDialogModel("Confirmar", message);

    const dialogRef = this.dialog.open(ConfirmDialogComponent, {
      maxWidth: "400px",
      data: dialogData,
    });

    dialogRef.afterClosed().subscribe((dialogResult) => {
      if (dialogResult == true) {
        this.excluir(m);
      }
    });
  }


excluir(m: Pedido) {
    if (m._id) {
      this.pedidosService.delete(m._id).then(() => {
        this.toastr.success("Pedido excluído com sucesso", "Atenção!", {
          closeButton: true,
          progressAnimation: "decreasing",
          progressBar: true,
        });
        this.pedidosService.listar().then((data) => {
          this.data = data;
          this.dataSource = new MatTableDataSource(this.data);
          this.dataSource.sort = this.sort;
          this.dataSource.paginator = this.paginator;
        });
      });
    }
  }


applyFilter(filterValue: string) {
    filterValue = filterValue.trim(); // Remove whitespace
    filterValue = filterValue.toLowerCase(); // Datasource defaults to lowercase matches
    this.dataSource.filter = filterValue;
  }


export function useUpdateAppAndSecretConfigMutation(
  appID: string
): {
  updateAppAndSecretConfig: (
    appConfig: PortalAPIAppConfig,
    secretConfig: PortalAPISecretConfig
  ) => Promise<PortalAPIApp | null>;
  loading: boolean;
  error: unknown;
} {
  const [mutationFunction, { error, loading }] = useMutation<
    UpdateAppAndSecretConfigMutation,
    UpdateAppAndSecretConfigMutationVariables
  >(updateAppAndSecretConfigMutation, { client });
  const updateAppAndSecretConfig = React.useCallback(
    async (
      appConfig: PortalAPIAppConfig,
      secretConfig: PortalAPISecretConfig
    ) => {
      const appConfigYaml = yaml.safeDump(appConfig);
      const secretConfigYaml = yaml.safeDump(secretConfig);

      const result = await mutationFunction({
        variables: {
          appID,
          updates: [
            { path: APP_CONFIG_PATH, data: btoa(appConfigYaml) },
            { path: SECRET_CONFIG_PATH, data: btoa(secretConfigYaml) },
          ],
        },
      });
      return result.data?.updateAppResources.app ?? null;
    },
    [appID, mutationFunction]
  );
  return { updateAppAndSecretConfig, error, loading };
}


async (
      appConfig: PortalAPIAppConfig,
      secretConfig: PortalAPISecretConfig
    ) => {
      const appConfigYaml = yaml.safeDump(appConfig);
      const secretConfigYaml = yaml.safeDump(secretConfig);

      const result = await mutationFunction({
        variables: {
          appID,
          updates: [
            { path: APP_CONFIG_PATH, data: btoa(appConfigYaml) },
            { path: SECRET_CONFIG_PATH, data: btoa(secretConfigYaml) },
          ],
        },
      });
      return result.data?.updateAppResources.app ?? null;
    }


export interface InterfaceSecretManagerPlugin {
  initSecret(name: string): Promise<void>;
  getSecretString(name: string): Promise<string | null>;
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  getSecretJson(name: string): Promise<any>;
}


(props) => {

  const {
    vertical,
    className
  } = props;

  return(
    <div
      className={classes(
        styles.separator,
        vertical ? styles.vertical : styles.horizontal,
        className


classes(
        styles


(p) => p.theme.editorColours.text


(res) => (
              <TracingRow
                key={res.path.join('.')}


class ResponseTracing extends React.PureComponent<ReduxProps & Props> {
  render() {
    const { tracing, tracingSupported, startTime, endTime, open } = this.props
    const requestMs =
      tracing && startTime
        ? Math.abs(new Date(tracing.startTime).getTime() - startTime.getTime())
        : 0
    const responseMs =
      tracing && endTime
        ? Math.abs(endTime.getTime() - new Date(tracing.endTime).getTime())
        : 0
    const requestDuration = 1000 * 1000 * requestMs

    return (
      <TracingWrapper>
        {tracing && open ? (
          <TracingRows>
            <TracingRow
              path={['Request']}
              startOffset={0}
              duration={requestDuration}
            />
            {tracing.execution.resolvers.map((res) => (
              <TracingRow
                key={res.path.join('.')}
                path={res.path}
                startOffset={res.startOffset + requestDuration}
                duration={res.duration}
              />
            ))}
            <TracingRow
              path={['Response']}
              startOffset={tracing.duration + requestDuration}
              duration={1000 * 1000 * responseMs}
            />
          </TracingRows>
        ) : tracingSupported ? (
          <ReRun>
            {this.props.queryRunning
              ? 'Running query ...'
              : 'Please re-run the query to show tracing results.'}
          </ReRun>
        ) : (
          <NotSupported>
            This GraphQL server doesn’t support tracing. See the following page
            for instructions:
            <br />
            https://github.com/apollographql/apollo-tracing
          </NotSupported>
        )}


export interface TracingFormat {
  version: 1
  startTime: string
  endTime: string
  duration: number
  execution: {
    resolvers: Array<{
      path: Array<string | number>
      parentType: string
      fieldName: string
      returnType: string
      startOffset: number
      duration: number
    }>
  }
}


export interface ReduxProps {
  tracing?: TracingFormat
  tracingSupported?: boolean
  startTime?: Date
  endTime?: Date
  queryRunning: boolean
}


interface Props {
  open: boolean
}


render() {
    const { tracing, tracingSupported, startTime, endTime, open } = this.props
    const requestMs =
      tracing && startTime
        ? Math.abs(new Date(tracing.startTime).getTime() - startTime.getTime())
        : 0
    const responseMs =
      tracing && endTime
        ? Math.abs(endTime.getTime() - new Date(tracing.endTime).getTime())
        : 0
    const requestDuration = 1000 * 1000 * requestMs

    return (
      <TracingWrapper>
        {tracing && open ? (
          <TracingRows>
            <TracingRow
              path={['Request']}
              startOffset={0}
              duration={requestDuration}
            />
            {tracing.execution.resolvers.map((res) => (
              <TracingRow
                key={res.path.join('.')}
                path={res.path}
                startOffset={res.startOffset + requestDuration}
                duration={res.duration}
              />
            ))}
            <TracingRow
              path={['Response']}
              startOffset={tracing.duration + requestDuration}
              duration={1000 * 1000 * responseMs}
            />
          </TracingRows>
        ) : tracingSupported ? (
          <ReRun>
            {this.props.queryRunning
              ? 'Running query ...'
              : 'Please re-run the query to show tracing results.'}
          </ReRun>
        ) : (
          <NotSupported>
            This GraphQL server doesn’t support tracing. See the following page
            for instructions:
            <br />
            https://github.com/apollographql/apollo-tracing
          </NotSupported>
        )}


(props) => {
  const {data, loading} = useQuery<
    PartitionRunListForStepQuery,
    PartitionRunListForStepQueryVariables
  >(PARTITION_RUN_LIST_FOR_STEP_QUERY, {
    variables: {
      filter: {
        pipelineName: props.pipelineName,
        tags: [{key: DagsterTag.Partition, value: props.partitionName}],
      },
    },
  });

  if (loading || !data) {
    return <Spinner purpose="section" />;
  }

  if (data.pipelineRunsOrError.__typename !== 'Runs') {
    return (
      <NonIdealState
        icon="error"
        title="Query Error"
        description={data.pipelineRunsOrError.message}
      />


interface StepStats {
  startTime: number | null;
  endTime: number | null;
  status: StepEventStatus | null;
  materializations: Record<string, unknown>[];
  expectationResults: {success: boolean}[];
}


interface PartitionRunListForStepProps {
  pipelineName: string;
  partitionName: string;
  stepName: string;
  stepStatsByRunId: {
    [runId: string]: StepStats;
  };
}


/* eslint-disable no-console */
export function handleError(err: Error | AppError | any) {
  console.error(err);
  if (err instanceof AxiosError) {
    console.log(JSON.stringify(err.toJSON(), null, 2));
  }
  process.exit(1);
}


() => {
  const { params } = useRouteMatch<RepositoryParams>();

  const [repository, setRepository] = useState<Repository | null>(null);
  const [issues, setIssues] = useState<Issue[]>([]);

  useEffect(() => {
    api.get(`repos/${params.repository}`).then(response => {
      setRepository(response.data);
    });

    api.get(`repos/${params.repository}/issues`).then(response => {
      setIssues(response.data);
    });
  }, [params.repository]);

  return (
    <>

        <Logo src={logo} alt="Github Explorer" />
        <Link to="/">
          <FiChevronLeft size={20} />
          Voltar
        </Link>

      {repository && (
        <RepositoryInfo>

              {repository.full_name}

{repository.description}

              {repository.stargazers_count}
              Stars

              {repository.forks_count}
              Forks

              {repository.open_issues_count}
              Issues abertas

        </RepositoryInfo>


() => {
    api.get(`repos/${params.repository}`).then(response => {
      setRepository(response.data);
    });

    api.get(`repos/${params.repository}/issues`).then(response => {
      setIssues(response.data);
    });
  }


response => {
      setRepository(response.data);
    }


response => {
      setIssues(response.data);
    }


issue => (
          <a href={issue.html_url}


interface RepositoryParams {
  repository: string;
}


interface Repository {
  full_name: string;
  description: string;
  stargazers_count: number;
  forks_count: number;
  open_issues_count: number;
  owner: {
    login: string;
    avatar_url: string;
  };
}


interface Issue {
  title: string;
  html_url: string;
  id: number;
  user: {
    login: string;
  };
}


export declare class FullscreenOverlayContainer extends OverlayContainer implements OnDestroy {
    private _fullScreenEventName;
    private _fullScreenListener;
    constructor(_document: any,
    /**
     * @deprecated `platform` parameter to become required.
     * @breaking-change 10.0.0
     */
    platform?: Platform);
    ngOnDestroy(): void;
    protected _createContainer(): void;
    private _adjustParentForFullscreenChange;
    private _addFullscreenChangeListener;
    private _getEventName;
    /**
     * When the page is put into fullscreen mode, a specific element is specified.
     * Only that element and its children are visible when in fullscreen mode.
     */
    getFullscreenElement(): Element;
    static ɵfac: ɵngcc0.ɵɵFactoryDef<FullscreenOverlayContainer, never>;
}


protected _createContainer(): void;


/**
     * When the page is put into fullscreen mode, a specific element is specified.
     * Only that element and its children are visible when in fullscreen mode.
     */
getFullscreenElement(): Element;


declare function moment(inp?: moment.MomentInput, format?: moment.MomentFormatSpecification, strict?: boolean): moment.Moment;


declare function moment(inp?: moment.MomentInput, format?: moment.MomentFormatSpecification, language?: string, strict?: boolean): moment.Moment;


// NOTE(constructor): Same as moment constructor
export function utc(inp?: MomentInput, format?: MomentFormatSpecification, strict?: boolean): Moment;


export function utc(inp?: MomentInput, format?: MomentFormatSpecification, language?: string, strict?: boolean): Moment;


export function unix(timestamp: number): Moment;


export function invalid(flags?: MomentParsingFlagsOpt): Moment;


export function isMoment(m: any): m is Moment;


export function isDate(m: any): m is Date;


export function isDuration(d: any): d is Duration;


/**
   * @deprecated in 2.8.0
   */
export function lang(language?: string): string;


/**
   * @deprecated in 2.8.0
   */
export function lang(language?: string, definition?: Locale): string;


export function locale(language?: string): string;


export function locale(language?: string[]): string;


export function locale(language?: string, definition?: LocaleSpecification | void): string;


export function localeData(key?: string | string[]): Locale;


export function duration(inp?: DurationInputArg1, unit?: DurationInputArg2): Duration;


// NOTE(constructor): Same as moment constructor
export function parseZone(inp?: MomentInput, format?: MomentFormatSpecification, strict?: boolean): Moment;


export function parseZone(inp?: MomentInput, format?: MomentFormatSpecification, language?: string, strict?: boolean): Moment;


export function months(): string[];


export function months(index: number): string;


export function months(format: string): string[];


export function months(format: string, index: number): string;


export function monthsShort(): string[];


export function monthsShort(index: number): string;


export function monthsShort(format: string): string[];


export function monthsShort(format: string, index: number): string;


export function jWeekOfYear(mom: Moment, firstDayOfWeek: number, firstDayOfWeekOfYear: number): MomentInput;


export function jDaysInMonth(jMear: number, jMonth: number): number;


export function jIsLeapYear(jYear: number): boolean;


export function useJalaliSystemPrimarily(): void;


export function useJalaliSystemSecondary(): void;


export function from (date: string, locale: string, format?: string): Moment;


export function weekdays(): string[];


export function weekdays(index: number): string;


export function weekdays(format: string): string[];


export function weekdays(format: string, index: number): string;


export function weekdays(localeSorted: boolean): string[];


export function weekdays(localeSorted: boolean, index: number): string;


export function weekdays(localeSorted: boolean, format: string): string[];


export function weekdays(localeSorted: boolean, format: string, index: number): string;


export function weekdaysShort(): string[];


export function weekdaysShort(index: number): string;


export function weekdaysShort(format: string): string[];


export function weekdaysShort(format: string, index: number): string;


export function weekdaysShort(localeSorted: boolean): string[];


export function weekdaysShort(localeSorted: boolean, index: number): string;


export function weekdaysShort(localeSorted: boolean, format: string): string[];


export function weekdaysShort(localeSorted: boolean, format: string, index: number): string;


export function weekdaysMin(): string[];


export function weekdaysMin(index: number): string;


export function weekdaysMin(format: string): string[];


export function weekdaysMin(format: string, index: number): string;


export function weekdaysMin(localeSorted: boolean): string[];


export function weekdaysMin(localeSorted: boolean, index: number): string;


export function weekdaysMin(localeSorted: boolean, format: string): string[];


export function weekdaysMin(localeSorted: boolean, format: string, index: number): string;


export function min(...moments: MomentInput[]): Moment;


export function max(...moments: MomentInput[]): Moment;


/**
   * Returns unix time in milliseconds. Overwrite for profit.
   */
export function now(): number;


export function defineLocale(language: string, localeSpec: LocaleSpecification | void): Locale;


export function updateLocale(language: string, localeSpec: LocaleSpecification | void): Locale;


export function locales(): string[];


export function normalizeUnits(unit: unitOfTime.All): string;


export function relativeTimeThreshold(threshold: string): number | boolean;


export function relativeTimeThreshold(threshold: string, limit: number): boolean;


export function relativeTimeRounding(fn: (num: number) => number): boolean;


export function relativeTimeRounding(): (num: number) => number;


export function calendarFormat(m: Moment, now: Moment): string;


interface Locale {
    calendar(key?: CalendarKey, m?: Moment, now?: Moment): string;

    longDateFormat(key: LongDateFormatKey): string;
    invalidDate(): string;
    ordinal(n: number): string;

    preparse(inp: string): string;
    postformat(inp: string): string;
    relativeTime(n: number, withoutSuffix: boolean,
                 key: RelativeTimeKey, isFuture: boolean): string;
    pastFuture(diff: number, absRelTime: string): string;
    set(config: Object): void;

    months(): string[];
    jMonths(): string[];

    months(m: Moment, format?: string): string;
    jMonths(m: Moment): string;
    monthsShort(): string[];
    jMonthsShort():string[];
    monthsShort(m: Moment, format?: string): string;
    jMonthsParse(monthName: string): number;
    monthsParse(monthName: string, format: string, strict: boolean): number;
    monthsRegex(strict: boolean): RegExp;
    monthsShortRegex(strict: boolean): RegExp;

    week(m: Moment): number;
    firstDayOfYear(): number;
    firstDayOfWeek(): number;

    weekdays(): string[];
    weekdays(m: Moment, format?: string): string;
    weekdaysMin(): string[];
    weekdaysMin(m: Moment): string;
    weekdaysShort(): string[];
    weekdaysShort(m: Moment): string;
    weekdaysParse(weekdayName: string, format: string, strict: boolean): number;
    weekdaysRegex(strict: boolean): RegExp;
    weekdaysShortRegex(strict: boolean): RegExp;
    weekdaysMinRegex(strict: boolean): RegExp;

    isPM(input: string): boolean;
    meridiem(hour: number, minute: number, isLower: boolean): string;
  }


interface StandaloneFormatSpec {
    format: string[];
    standalone: string[];
    isFormat?: RegExp;
  }


interface WeekSpec {
    dow: number;
    doy: number;
  }


interface CalendarSpec {
    sameDay?: CalendarSpecVal;
    nextDay?: CalendarSpecVal;
    lastDay?: CalendarSpecVal;
    nextWeek?: CalendarSpecVal;
    lastWeek?: CalendarSpecVal;
    sameElse?: CalendarSpecVal;

    // any additional properties might be used with moment.calendarFormat
    [x: string]: CalendarSpecVal | void; // undefined
  }


interface RelativeTimeSpec {
    future: RelativeTimeFuturePastVal;
    past: RelativeTimeFuturePastVal;
    s: RelativeTimeSpecVal;
    m: RelativeTimeSpecVal;
    mm: RelativeTimeSpecVal;
    h: RelativeTimeSpecVal;
    hh: RelativeTimeSpecVal;
    d: RelativeTimeSpecVal;
    dd: RelativeTimeSpecVal;
    M: RelativeTimeSpecVal;
    MM: RelativeTimeSpecVal;
    y: RelativeTimeSpecVal;
    yy: RelativeTimeSpecVal;
  }


interface LongDateFormatSpec {
    LTS: string;
    LT: string;
    L: string;
    LL: string;
    LLL: string;
    LLLL: string;

    // lets forget for a sec that any upper/lower permutation will also work
    lts?: string;
    lt?: string;
    l?: string;
    ll?: string;
    lll?: string;
    llll?: string;
  }


interface LocaleSpecification {
    useGregorianParser?: boolean;
    months?: string[] | StandaloneFormatSpec | MonthWeekdayFn;
    monthsShort?: string[] | StandaloneFormatSpec | MonthWeekdayFn;

    weekdays?: string[] | StandaloneFormatSpec | MonthWeekdayFn;
    weekdaysShort?: string[] | StandaloneFormatSpec | WeekdaySimpleFn;
    weekdaysMin?: string[] | StandaloneFormatSpec | WeekdaySimpleFn;

    meridiemParse?: RegExp;
    meridiem?: (hour: number, minute: number, isLower: boolean) => string;

    isPM?: (input: string) => boolean;

    longDateFormat?: LongDateFormatSpec;
    calendar?: CalendarSpec;
    relativeTime?: RelativeTimeSpec;
    invalidDate?: string;
    ordinal?: (n: number) => string;
    ordinalParse?: RegExp;

    week?: WeekSpec;

    // Allow anything: in general any property that is passed as locale spec is
    // put in the locale object so it can be used by locale functions
    [x: string]: any;
  }


interface MomentObjectOutput {
    years: number;
    /* One digit */
    months: number;
    /* Day of the month */
    date: number;
    hours: number;
    minutes: number;
    seconds: number;
    milliseconds: number;
  }


interface Duration {
    humanize(withSuffix?: boolean): string;

    abs(): Duration;

    as(units: unitOfTime.Base): number;
    get(units: unitOfTime.Base): number;

    milliseconds(): number;
    asMilliseconds(): number;

    seconds(): number;
    asSeconds(): number;

    minutes(): number;
    asMinutes(): number;

    hours(): number;
    asHours(): number;

    days(): number;
    asDays(): number;

    weeks(): number;
    asWeeks(): number;

    months(): number;
    asMonths(): number;

    years(): number;
    asYears(): number;

    add(inp?: DurationInputArg1, unit?: DurationInputArg2): Duration;
    subtract(inp?: DurationInputArg1, unit?: DurationInputArg2): Duration;

    locale(): string;
    locale(locale: LocaleSpecifier): Duration;
    localeData(): Locale;

    toISOString(): string;
    toJSON(): string;

    /**
     * @deprecated since version 2.8.0
     */
    lang(locale: LocaleSpecifier): Moment;
    /**
     * @deprecated since version 2.8.0
     */
    lang(): Locale;
    /**
     * @deprecated
     */
    toIsoString(): string;
  }


interface MomentRelativeTime {
    future: any;
    past: any;
    s: any;
    m: any;
    mm: any;
    h: any;
    hh: any;
    d: any;
    dd: any;
    M: any;
    MM: any;
    y: any;
    yy: any;
  }


interface MomentLongDateFormat {
    L: string;
    LL: string;
    LLL: string;
    LLLL: string;
    LT: string;
    LTS: string;

    l?: string;
    ll?: string;
    lll?: string;
    llll?: string;
    lt?: string;
    lts?: string;
  }


interface MomentParsingFlags {
    empty: boolean;
    unusedTokens: string[];
    unusedInput: string[];
    overflow: number;
    charsLeftOver: number;
    nullInput: boolean;
    invalidMonth: string | void; // null
    invalidFormat: boolean;
    userInvalidated: boolean;
    iso: boolean;
    parsedDateParts: any[];
    meridiem: string | void; // null
  }


interface MomentParsingFlagsOpt {
    empty?: boolean;
    unusedTokens?: string[];
    unusedInput?: string[];
    overflow?: number;
    charsLeftOver?: number;
    nullInput?: boolean;
    invalidMonth?: string;
    invalidFormat?: boolean;
    userInvalidated?: boolean;
    iso?: boolean;
    parsedDateParts?: any[];
    meridiem?: string;
  }


interface MomentBuiltinFormat {
    __momentBuiltinFormatBrand: any;
  }


interface MomentInputObject {
    years?: number;
    year?: number;
    y?: number;

    months?: number;
    month?: number;
    M?: number;

    days?: number;
    day?: number;
    d?: number;

    dates?: number;
    date?: number;
    D?: number;

    hours?: number;
    hour?: number;
    h?: number;

    minutes?: number;
    minute?: number;
    m?: number;

    seconds?: number;
    second?: number;
    s?: number;

    milliseconds?: number;
    millisecond?: number;
    ms?: number;
  }


interface DurationInputObject extends MomentInputObject {
    quarters?: number;
    quarter?: number;
    Q?: number;

    weeks?: number;
    week?: number;
    w?: number;
  }


interface MomentSetObject extends MomentInputObject {
    weekYears?: number;
    weekYear?: number;
    gg?: number;

    isoWeekYears?: number;
    isoWeekYear?: number;
    GG?: number;

    quarters?: number;
    quarter?: number;
    Q?: number;

    weeks?: number;
    week?: number;
    w?: number;

    isoWeeks?: number;
    isoWeek?: number;
    W?: number;

    dayOfYears?: number;
    dayOfYear?: number;
    DDD?: number;

    weekdays?: number;
    weekday?: number;
    e?: number;

    isoWeekdays?: number;
    isoWeekday?: number;
    E?: number;
  }


interface FromTo {
    from: MomentInput;
    to: MomentInput;
  }


interface MomentCreationData {
    input: MomentInput;
    format?: MomentFormatSpecification;
    locale: Locale;
    isUTC: boolean;
    strict?: boolean;
  }


interface Moment extends Object{
    format(format?: string): string;

    startOf(unitOfTime: unitOfTime.StartOf): Moment;
    endOf(unitOfTime: unitOfTime.StartOf): Moment;

    add(amount?: DurationInputArg1, unit?: DurationInputArg2): Moment;
    /**
     * @deprecated reverse syntax
     */
    add(unit: unitOfTime.DurationConstructor, amount: number|string): Moment;

    subtract(amount?: DurationInputArg1, unit?: DurationInputArg2): Moment;
    /**
     * @deprecated reverse syntax
     */
    subtract(unit: unitOfTime.DurationConstructor, amount: number|string): Moment;

    calendar(time?: MomentInput, formats?: CalendarSpec): string;

    clone(): Moment;

    /**
     * @return Unix timestamp in milliseconds
     */
    valueOf(): number;

    // current date/time in local mode
    local(keepLocalTime?: boolean): Moment;
    isLocal(): boolean;

    // current date/time in UTC mode
    utc(keepLocalTime?: boolean): Moment;
    isUTC(): boolean;
    /**
     * @deprecated use isUTC
     */
    isUtc(): boolean;

    parseZone(): Moment;
    isValid(): boolean;
    invalidAt(): number;

    hasAlignedHourOffset(other?: MomentInput): boolean;

    creationData(): MomentCreationData;
    parsingFlags(): MomentParsingFlags;

    year(y: number): Moment;
    year(): number;
    jYear(y: number): Moment;
    jYear():number;
    /**
     * @deprecated use year(y)
     */
    years(y: number): Moment;
    /**
     * @deprecated use year()
     */
    years(): number;
    quarter(): number;
    quarter(q: number): Moment;
    quarters(): number;
    quarters(q: number): Moment;
    month(M: number|string): Moment;
    jMonth(M: number|string): Moment;
    month(): number;
    jMonth(): number;
    /**
     * @deprecated use month(M)
     */
    months(M: number|string): Moment;
    /**
     * @deprecated use month()
     */
    months(): number;
    day(d: number|string): Moment;
    day(): number;
    jDay(d: number|string): Moment;
    jDay(): number;
    days(d: number|string): Moment;
    days(): number;
    date(d: number): Moment;
    jDate(d: number): Moment;
    date(): number;
    jDate(): number;
    /**
     * @deprecated use date(d)
     */
    dates(d: number): Moment;
    /**
     * @deprecated use jDate(d)
     */
    jDates(d: number): Moment;
    /**
     * @deprecated use date()
     */
    dates(): number;
    /**
     * @deprecated use jDate()
     */
    jDates():number;

    hour(h: number): Moment;
    hour(): number;
    hours(h: number): Moment;
    hours(): number;
    minute(m: number): Moment;
    minute(): number;
    minutes(m: number): Moment;
    minutes(): number;
    second(s: number): Moment;
    second(): number;
    seconds(s: number): Moment;
    seconds(): number;
    millisecond(ms: number): Moment;
    millisecond(): number;
    milliseconds(ms: number): Moment;
    milliseconds(): number;
    weekday(): number;
    //TODO:jweekday
    weekday(d: number): Moment;
    isoWeekday(): number;
    isoWeekday(d: number|string): Moment;
    weekYear(): number;
    jWeekYear(): number;
    weekYear(d: number): Moment;
    jWeekYear(d: number): Moment;
    isoWeekYear(): number;
    isoWeekYear(d: number): Moment;
    week(): number;
    jWeek(): number;
    week(d: number): Moment;
    jWeek(d: number): Moment;
    weeks(): number;
    jWeeks(): number;//TODO:check it
    weeks(d: number): Moment;
    isoWeek(): number;
    isoWeek(d: number): Moment;
    isoWeeks(): number;
    isoWeeks(d: number): Moment;
    weeksInYear(): number;
    //TODO : jWeeksInYear
    isoWeeksInYear(): number;
    dayOfYear(): number;
    jDayOfYear(): number;
    dayOfYear(d: number): Moment;
    jDayOfYear(d: number): Moment;

    from(inp: MomentInput, suffix?: boolean): string;
    to(inp: MomentInput, suffix?: boolean): string;
    fromNow(withoutSuffix?: boolean): string;
    toNow(withoutPrefix?: boolean): string;

    diff(b: MomentInput, unitOfTime?: unitOfTime.Diff, precise?: boolean): number;

    toArray(): number[];
    toDate(): Date;
    toISOString(): string;
    inspect(): string;
    toJSON(): string;
    unix(): number;

    isLeapYear(): boolean;
    jIsLeapYear(): boolean;
    /**
     * @deprecated in favor of utcOffset
     */
    zone(): number;
    zone(b: number|string): Moment;
    utcOffset(): number;
    utcOffset(b: number|string, keepLocalTime?: boolean): Moment;
    isUtcOffset(): boolean;
    daysInMonth(): number;
    jDaysInMonth(): number;
    isDST(): boolean;

    zoneAbbr(): string;
    zoneName(): string;

    isBefore(inp?: MomentInput, granularity?: unitOfTime.StartOf): boolean;
    isAfter(inp?: MomentInput, granularity?: unitOfTime.StartOf): boolean;
    isSame(inp?: MomentInput, granularity?: unitOfTime.StartOf): boolean;
    isSameOrAfter(inp?: MomentInput, granularity?: unitOfTime.StartOf): boolean;
    isSameOrBefore(inp?: MomentInput, granularity?: unitOfTime.StartOf): boolean;
    isBetween(a: MomentInput, b: MomentInput, granularity?: unitOfTime.StartOf, inclusivity?: "()" | "[)" | "(]" | "[]"): boolean;

    doAsGregorian(): Moment;

    /**
     * @deprecated as of 2.8.0, use locale
     */
    lang(language: LocaleSpecifier): Moment;
    /**
     * @deprecated as of 2.8.0, use locale
     */
    lang(): Locale;

    locale(): string;
    locale(locale: LocaleSpecifier): Moment;

    localeData(): Locale;

    /**
     * @deprecated no reliable implementation
     */
    isDSTShifted(): boolean;

    // NOTE(constructor): Same as moment constructor
    /**
     * @deprecated as of 2.7.0, use moment.min/max
     */
    max(inp?: MomentInput, format?: MomentFormatSpecification, strict?: boolean): Moment;
    /**
     * @deprecated as of 2.7.0, use moment.min/max
     */
    max(inp?: MomentInput, format?: MomentFormatSpecification, language?: string, strict?: boolean): Moment;

    // NOTE(constructor): Same as moment constructor
    /**
     * @deprecated as of 2.7.0, use moment.min/max
     */
    min(inp?: MomentInput, format?: MomentFormatSpecification, strict?: boolean): Moment;
    /**
     * @deprecated as of 2.7.0, use moment.min/max
     */
    min(inp?: MomentInput, format?: MomentFormatSpecification, language?: string, strict?: boolean): Moment;

    get(unit: unitOfTime.All): number;
    set(unit: unitOfTime.All, value: number): Moment;
    set(objectLiteral: MomentSetObject): Moment;

    toObject(): MomentObjectOutput;
  }


type RelativeTimeKey = 's' | 'm' | 'mm' | 'h' | 'hh' | 'd' | 'dd' | 'M' | 'MM' | 'y' | 'yy';


type CalendarKey = 'sameDay' | 'nextDay' | 'lastDay' | 'nextWeek' | 'lastWeek' | 'sameElse' | string;


type LongDateFormatKey = 'LTS' | 'LT' | 'L' | 'LL' | 'LLL' | 'LLLL' | 'lts' | 'lt' | 'l' | 'll' | 'lll' | 'llll';


type CalendarSpecVal = string | ((m?: MomentInput, now?: Moment) => string);


type RelativeTimeSpecVal = (
      string |
          ((n: number, withoutSuffix: boolean,
            key: RelativeTimeKey, isFuture: boolean) => string)
      );


type RelativeTimeFuturePastVal = string | ((relTime: string) => string);


type MonthWeekdayFn = (momentToFormat: Moment, format?: string) => string;


type WeekdaySimpleFn = (momentToFormat: Moment) => string;


type MomentFormatSpecification = string | MomentBuiltinFormat | (string | MomentBuiltinFormat)[];


type Base = (
        "year" | "years" | "y" | "jYear" |
            "month" | "months" | "M" | "jMonth" | "jmonth" |
            "week" | "weeks" | "w" | "jw" |
            "day" | "days" | "d" | "jDay" | "jD" |
            "hour" | "hours" | "h" |
            "minute" | "minutes" | "m" |
            "second" | "seconds" | "s" |
            "millisecond" | "milliseconds" | "ms"
        );


type _quarter = "quarter" | "quarters" | "Q";


type _isoWeek = "isoWeek" | "isoWeeks" | "W";


type _date = "date" | "dates" | "D";


type DurationConstructor = Base | _quarter;


type DurationAs = Base;


type StartOf = Base | _quarter | _isoWeek | _date;


type Diff = Base | _quarter;


type MomentConstructor = Base | _date;


type All = Base | _quarter | _isoWeek | _date |
        "weekYear" | "weekYears" | "gg" |
        "isoWeekYear" | "isoWeekYears" | "GG" |
        "dayOfYear" | "dayOfYears" | "DDD" |
        "weekday" | "weekdays" | "e" |
        "isoWeekday" | "isoWeekdays" | "E";


type MomentInput = Moment | Date | string | number | (number | string)[] | MomentInputObject | void;


type DurationInputArg1 = Duration | number | string | FromTo | DurationInputObject | void;


type DurationInputArg2 = unitOfTime.DurationConstructor;


type LocaleSpecifier = string | Moment | Duration | string[] | boolean;


export class CommentConverter {
    private lines: string[];
    private lineIndex: number;
    private newLines: string[] = [];

    /**
     * The main function of the converter
     * @param lines lines of code
     * @returns generated lines
     */
    convertComment(lines: string[]): string[] {
        this.lines = lines;
        this.lineIndex = 0;
        this.newLines = [];

        for (this.lineIndex = 0; this.lineIndex < lines.length; this.lineIndex++) {
            const line = lines[this.lineIndex];

            // one line comment, '//' or '///<'
            const m = line.match(/(\s*)([^\s].*?)\/\/(\/<)?([^\/].*)$/);
            if (m != undefined) {
                const indent = m[1];
                const code = m[2].trimRight();
                let comment = m[4];
                if (comment.startsWith(' ')) {
                    comment = comment.slice(1);
                }
                comment = comment.trimRight();
                // skip annotations like '@Expose()'
                const insertPosition = this.lookBackForAnnotation(indent);
                this.newLines.splice(insertPosition, 0, `${indent}/** ${comment.trim()} */`);
                this.newLines.push(indent + code);
            } else if (this.handleMultilineComment()) {
            } else {
                this.newLines.push(line);
            }
        }

        return this.newLines;
    }

    /**
     * Look back into newly generated lines and find well aligned TypeScript annotation
     * @param indent a string contains spaces
     * @returns the line index of the first annotation
     */
    private lookBackForAnnotation(indent: string): number {
        let i;
        for (i = this.newLines.length - 1; i != -1; i--) {
            const line = this.newLines[i];
            // same indent and starts with @
            if (line.length > indent.length + 2
                && line.slice(0, indent.length) === indent
                && line[indent.length] == '@') {
                // it must be an annotation
                continue;
            }
            break;
        }

        return i + 1;
    }

    /**
     * Try to consume lines and generate new lines for multi line comments.
     *
     * Like this one:
     *
     * ```ts
     * // This is a multi-line
     * // comment.
     * runCommand();
     * ```
     *
     * @returns true if one or more lines are successfully consumed.
     */
    private handleMultilineComment(): boolean {
        const startIndex = this.lineIndex;
        const comments = [];
        const lines = this.lines;
        let indent = -1;
        for (let i = startIndex; i < lines.length; i++) {
            const line = lines[i];
            const m = line.match(/(\s*)\/\/(.*)/);

            // for none-pure-comment line
            if (m == undefined) {
                if (comments.length != 0) {
                    const firstCodeLineIndent = line.length - line.trimLeft().length;
                    if (firstCodeLineIndent === indent) {
                        // found well aligned comments
                        const leadingIndent = ' '.repeat(indent);
                        if (comments.length == 1) {
                            this.newLines.push(`${leadingIndent}/** ${comments[0]} */`);
                        } else {
                            this.newLines.push(leadingIndent + `/**`);
                            for (const comment of comments) {
                                this.newLines.push(leadingIndent + ` * ${comment}`);
                            }
                            this.newLines.push(leadingIndent + ` */`);
                        }
                        this.newLines.push(line);
                        this.lineIndex = i;
                        return true;
                    }
                }

                this.lineIndex = startIndex;
                return false;
            } else {
                // pure comment line

                // save indent
                const newIndent = m[1].length;
                if (indent == -1) {
                    indent = newIndent;
                }

                // save comments
                if (m[2].startsWith(' ')) {
                    comments.push(m[2].slice(1).trimRight());
                } else {
                    comments.push(m[2].trimRight());
                }

                // found mis-aligned comment, failed
                if (newIndent !== indent) {
                    this.lineIndex = startIndex;
                    return false;
                }
            }
        }
    }
}


/**
     * The main function of the converter
     * @param lines lines of code
     * @returns generated lines
     */
convertComment(lines: string[]): string[] {
        this.lines = lines;
        this.lineIndex = 0;
        this.newLines = [];

        for (this.lineIndex = 0; this.lineIndex < lines.length; this.lineIndex++) {
            const line = lines[this.lineIndex];

            // one line comment, '//' or '///<'
            const m = line.match(/(\s*)([^\s].*?)\/\/(\/<)?([^\/].*)$/);
            if (m != undefined) {
                const indent = m[1];
                const code = m[2].trimRight();
                let comment = m[4];
                if (comment.startsWith(' ')) {
                    comment = comment.slice(1);
                }
                comment = comment.trimRight();
                // skip annotations like '@Expose()'
                const insertPosition = this.lookBackForAnnotation(indent);
                this.newLines.splice(insertPosition, 0, `${indent}/** ${comment.trim()} */`);
                this.newLines.push(indent + code);
            } else if (this.handleMultilineComment()) {
            } else {
                this.newLines.push(line);
            }
        }

        return this.newLines;
    }


/**
     * Look back into newly generated lines and find well aligned TypeScript annotation
     * @param indent a string contains spaces
     * @returns the line index of the first annotation
     */
private lookBackForAnnotation(indent: string): number {
        let i;
        for (i = this.newLines.length - 1; i != -1; i--) {
            const line = this.newLines[i];
            // same indent and starts with @
            if (line.length > indent.length + 2
                && line.slice(0, indent.length) === indent
                && line[indent.length] == '@') {
                // it must be an annotation
                continue;
            }
            break;
        }

        return i + 1;
    }


/**
     * Try to consume lines and generate new lines for multi line comments.
     *
     * Like this one:
     *
     * ```ts
     * // This is a multi-line
     * // comment.
     * runCommand();
     * ```
     *
     * @returns true if one or more lines are successfully consumed.
     */
private handleMultilineComment(): boolean {
        const startIndex = this.lineIndex;
        const comments = [];
        const lines = this.lines;
        let indent = -1;
        for (let i = startIndex; i < lines.length; i++) {
            const line = lines[i];
            const m = line.match(/(\s*)\/\/(.*)/);

            // for none-pure-comment line
            if (m == undefined) {
                if (comments.length != 0) {
                    const firstCodeLineIndent = line.length - line.trimLeft().length;
                    if (firstCodeLineIndent === indent) {
                        // found well aligned comments
                        const leadingIndent = ' '.repeat(indent);
                        if (comments.length == 1) {
                            this.newLines.push(`${leadingIndent}/** ${comments[0]} */`);
                        } else {
                            this.newLines.push(leadingIndent + `/**`);
                            for (const comment of comments) {
                                this.newLines.push(leadingIndent + ` * ${comment}`);
                            }
                            this.newLines.push(leadingIndent + ` */`);
                        }
                        this.newLines.push(line);
                        this.lineIndex = i;
                        return true;
                    }
                }

                this.lineIndex = startIndex;
                return false;
            } else {
                // pure comment line

                // save indent
                const newIndent = m[1].length;
                if (indent == -1) {
                    indent = newIndent;
                }

                // save comments
                if (m[2].startsWith(' ')) {
                    comments.push(m[2].slice(1).trimRight());
                } else {
                    comments.push(m[2].trimRight());
                }

                // found mis-aligned comment, failed
                if (newIndent !== indent) {
                    this.lineIndex = startIndex;
                    return false;
                }
            }
        }
    }


() => {
  it('should render', async () => {
    const page = await newSpecPage({
      components: [Backdrop],
      template: () => <cho-backdrop />,
    });

    expect(page.root).toBeTruthy();
  });

  describe('visible', () => {
    it('should render container and children', async () => {
      const page = await newSpecPage({
        components: [Backdrop],
        template: () => (
          <cho-backdrop visible>
            Test
          </cho-backdrop>
        ),
      });

      expect(page.root.shadowRoot.querySelector('slot')).toBeTruthy();
    });

    it('should not render container and children', async () => {
      const page = await newSpecPage({
        components: [Backdrop],
        template: () => (
          <cho-backdrop visible={false}>
            Test
          </cho-backdrop>
        ),
      });

      expect(page.root.shadowRoot.querySelector('slot')).toBeFalsy();
    }


async () => {
    const page = await newSpecPage({
      components: [Backdrop],
      template: () => <cho-backdrop />,
    });

    expect(page.root).toBeTruthy();
  }


() => <cho-backdrop />


() => {
    it('should render container and children', async () => {
      const page = await newSpecPage({
        components: [Backdrop],
        template: () => (
          <cho-backdrop visible>
            Test
          </cho-backdrop>
        ),
      });

      expect(page.root.shadowRoot.querySelector('slot')).toBeTruthy();
    }


async () => {
      const page = await newSpecPage({
        components: [Backdrop],
        template: () => (
          <cho-backdrop visible>
            Test
          </cho-backdrop>
        ),
      }


() => (
          <cho-backdrop


async () => {
      const page = await newSpecPage({
        components: [Backdrop],
        template: () => (
          <cho-backdrop visible={false}>
            Test
          </cho-backdrop>
        ),
      }


() => this._scrollIntoView()


(item, index) => ({ ...item, index: index })


(shouldOpenOnFocus?: boolean, useFocusAsync?: boolean): void => {
    if (this._autofill.current) {
      if (useFocusAsync) {
        focusAsync(this._autofill.current);
      } else {
        this._autofill.current.focus();
      }

      if (shouldOpenOnFocus) {
        this.setState({
          isOpen: true
        });
      }
    }
  }


(): void => {
    const { isOpen } = this.state;
    isOpen && this.setState({ isOpen: false });
  }


(): string | null => {
    const comboBox = this._autofill.current;

    if (!comboBox) {
      return null;
    }

    if (comboBox.value === null || comboBox.value === undefined) {
      return null;
    }

    const visibleValue = this._normalizeToString(this._currentVisibleValue);
    if (comboBox.value !== visibleValue) {
      // If visibleValue is empty, make it a zero width space.
      // If we did not do that, the empty string would not get used
      // potentially resulting in an unexpected value being used
      return visibleValue || '';
    }

    return comboBox.value;
  }


(): boolean => {
    return this._currentVisibleValue === this.state.suggestedDisplayValue;
  }


(): string | undefined => {
    const { text, allowFreeform, autoComplete } = this.props;
    const {
      selectedIndices,
      currentPendingValueValidIndex,
      currentOptions,
      currentPendingValue,
      suggestedDisplayValue,
      isOpen,
      focused
    } = this.state;

    const currentPendingIndexValid = this._indexWithinBounds(currentOptions, currentPendingValueValidIndex);

    // If the user passed is a value prop, use that
    // unless we are open and have a valid current pending index
    if (!(isOpen && currentPendingIndexValid) && (text && (currentPendingValue === null || currentPendingValue === undefined))) {
      return text;
    }

    // Values to display in the BaseAutoFill area
    const displayValues = [];

    if (this.props.multiSelect) {
      // Multi-select
      if (focused) {
        let index = -1;
        if (autoComplete === 'on' && currentPendingIndexValid) {
          index = currentPendingValueValidIndex;
        }
        displayValues.push(
          currentPendingValue !== null && currentPendingValue !== undefined
            ? currentPendingValue
            : this._indexWithinBounds(currentOptions, index)
            ? currentOptions[index].text
            : ''
        );
      } else {
        for (let idx = 0; selectedIndices && idx < selectedIndices.length; idx++) {
          const index: number = selectedIndices[idx];
          displayValues.push(
            this._indexWithinBounds(currentOptions, index) ? currentOptions[index].text : this._normalizeToString(suggestedDisplayValue)
          );
        }
      }
    } else {
      // Single-select
      let index: number = this._getFirstSelectedIndex();
      if (allowFreeform) {
        // If we are allowing freeform and autocomplete is also true
        // and we've got a pending value that matches an option, remember
        // the matched option's index
        if (autoComplete === 'on' && currentPendingIndexValid) {
          index = currentPendingValueValidIndex;
        }

        // Since we are allowing freeform, if there is currently a pending value, use that
        // otherwise use the index determined above (falling back to '' if we did not get a valid index)
        displayValues.push(
          currentPendingValue !== null && currentPendingValue !== undefined
            ? currentPendingValue
            : this._indexWithinBounds(currentOptions, index)
            ? currentOptions[index].text
            : ''
        );
      } else {
        // If we are not allowing freeform and have a
        // valid index that matches the pending value,
        // we know we will need some version of the pending value
        if (currentPendingIndexValid && autoComplete === 'on') {
          // If autoComplete is on, return the
          // raw pending value, otherwise remember
          // the matched option's index
          index = currentPendingValueValidIndex;
          displayValues.push(this._normalizeToString(currentPendingValue));
        } else {
          displayValues.push(
            this._indexWithinBounds(currentOptions, index) ? currentOptions[index].text : this._normalizeToString(suggestedDisplayValue)
          );
        }
      }
    }

    // If we have a valid index then return the text value of that option,
    // otherwise return the suggestedDisplayValue
    let displayString = '';
    for (let idx = 0; idx < displayValues.length; idx++) {
      if (idx > 0) {
        displayString += ', ';
      }
      displayString += displayValues[idx];
    }
    return displayString;
  }


(updatedValue: string): void => {
    if (this.props.disabled) {
      this._handleInputWhenDisabled(null /* event */);
      return;
    }

    this.props.allowFreeform ? this._processInputChangeWithFreeform(updatedValue) : this._processInputChangeWithoutFreeform(updatedValue);
  }


(item, index) => {
          return { ...item, index };
        }


option => option.itemType !== SelectableOptionMenuItemType.Header && option.itemType !== SelectableOptionMenuItemType.Divider


option => this._getPreviewText(option) === updatedValue


option =>
            this._getPreviewText(option)
              .toLocaleLowerCase()
              .indexOf(updatedValue) === 0


option => this._getPreviewText(option).toLocaleLowerCase() === updatedValue


(item, i) => {
            return { ...item, index: i };
          }


option => option.text.toLocaleLowerCase().indexOf(updatedValue) === 0


() => {
          this._lastReadOnlyAutoCompleteChangeTimeoutId = undefined;
        }


(value: number) => value !== index


() => {
          // If ComboBox value is changed, revert preview first
          if (this._hasPendingValue && onPendingValueChanged) {
            onPendingValueChanged();
            this._hasPendingValue = false;
          }

          if (onChange) {
            onChange(submitPendingValueEvent, option, index, undefined);
          }
        }


(): void => {
    if (this._autofill.current && this._autofill.current.inputElement) {
      this._autofill.current.inputElement.select();
    }

    if (!this.state.focused) {
      const state: Pick<IComboBoxState, 'focused'> | Pick<IComboBoxState, 'focused' | 'isOpen'> = { focused: true };

      if (this.props.openOnKeyboardFocus && !this.state.isOpen && !this.props.disabled) {
        (state as Pick<IComboBoxState, 'focused' | 'isOpen'>).isOpen = true;
      }
      this.setState(state);
    }
  }


(): void => {
    if (this.props.onResolveOptions) {
      // get the options
      const newOptions = this.props.onResolveOptions([...this.state.currentOptions]);

      // Check to see if the returned value is an array, if it is update the state
      // If the returned value is not an array then check to see if it's a promise or PromiseLike. If it is then resolve it asynchronously.
      if (Array.isArray(newOptions)) {
        this.setState({
          currentOptions: newOptions
        });
      } else if (newOptions && newOptions.then) {
        // Ensure that the promise will only use the callback if it was the most recent one
        // and update the state when the promise returns
        const promise: PromiseLike<IComboBoxOption[]> = (this._currentPromise = newOptions);
        promise.then((newOptionsFromPromise: IComboBoxOption[]) => {
          if (promise === this._currentPromise) {
            this.setState({
              currentOptions: newOptionsFromPromise
            });
          }
        });
      }
    }
  }


(newOptionsFromPromise: IComboBoxOption[]) => {
          if (promise === this._currentPromise) {
            this.setState({
              currentOptions: newOptionsFromPromise
            });
          }
        }


(
    event: React.FocusEvent<HTMLInputElement | Autofill | HTMLAnchorElement | HTMLButtonElement | HTMLDivElement | BaseButton | Button>
  ): void => {
    // Do nothing if the blur is coming from something
    // inside the comboBox root or the comboBox menu since
    // it we are not really bluring from the whole comboBox
    let relatedTarget = event.relatedTarget;
    if (event.relatedTarget === null) {
      // In IE11, due to lack of support, event.relatedTarget is always
      // null making every onBlur call to be "outside" of the ComboBox
      // even when it's not. Using document.activeElement is another way
      // for us to be able to get what the relatedTarget without relying
      // on the event
      relatedTarget = document.activeElement as Element;
    }
    if (
      relatedTarget &&
      // when event coming from withing the comboBox title
      ((this._root.current && this._root.current.contains(relatedTarget as HTMLElement)) ||
        // when event coming from within the comboBox list menu
        (this._comboBoxMenu.current &&
          (this._comboBoxMenu.current.contains(relatedTarget as HTMLElement) ||
            // when event coming from the callout containing the comboBox list menu (ex: when scrollBar of the Callout clicked)
            // checks if the relatedTarget is a parent of _comboBoxMenu
            findElementRecursive(this._comboBoxMenu.current, element => element === relatedTarget))))
    ) {
      event.preventDefault();
      event.stopPropagation();
      return;
    }

    if (this.state.focused) {
      this.setState({ focused: false });
      if (!this.props.multiSelect || this.props.allowFreeform) {
        this._submitPendingValue(event);
      }
    }
  }


element => element === relatedTarget


(props: IComboBoxProps): JSX.Element => {
    const {
      onRenderList,
      calloutProps,
      dropdownWidth,
      dropdownMaxWidth,
      onRenderLowerContent = this._onRenderLowerContent,
      useComboBoxAsMenuWidth,
      persistMenu,
      shouldRestoreFocus = true
    } = props;

    const { isOpen } = this.state;

    const comboBoxMenuWidth =
      useComboBoxAsMenuWidth && this._comboBoxWrapper.current ? this._comboBoxWrapper.current.clientWidth + 2 : undefined;

    return (
      <Callout
        isBeakVisible={false}
        gapSpace={0}
        doNotLayer={false}
        directionalHint={DirectionalHint.bottomLeftEdge}
        directionalHintFixed={false}
        {...calloutProps}
        onLayerMounted={this._onLayerMounted}
        className={css(this._classNames.callout, calloutProps ? calloutProps.className : undefined)}
        target={this._comboBoxWrapper.current}
        onDismiss={this._onDismiss}
        onScroll={this._onScroll}
        setInitialFocus={false}
        calloutWidth={useComboBoxAsMenuWidth && this._comboBoxWrapper.current ? comboBoxMenuWidth && comboBoxMenuWidth : dropdownWidth}


() => {
    this._onCalloutLayerMounted();

    if (this.props.calloutProps && this.props.calloutProps.onLayerMounted) {
      this.props.calloutProps.onLayerMounted();
    }
  }


(props: IComboBoxProps): JSX.Element => {
    const { onRenderItem, options } = props;

    const id = this._id;
    return (
      <div id={id + '-list'}


item => (onRenderItem as any)(item, this._onRenderItem)


(item: IComboBoxOption): JSX.Element | null => {
    switch (item.itemType) {
      case SelectableOptionMenuItemType.Divider:
        return this._renderSeparator(item);
      case SelectableOptionMenuItemType.Header:
        return this._renderHeader(item);
      default:
        return this._renderOption(item);
    }
  }


(): null => {
    return null;
  }


(item: IComboBoxOption): JSX.Element => {
    const { onRenderOption = this._onRenderOptionContent } = this.props;
    const id = this._id;
    const isSelected: boolean = this._isOptionSelected(item.index);
    const optionStyles = this._getCurrentOptionStyles(item);
    const optionClassNames = getComboBoxOptionClassNames(this._getCurrentOptionStyles(item));
    const checkboxStyles = () => {
      return optionStyles;
    };
    const title = this._getPreviewText(item);

    const getOptionComponent = () => {
      return !this.props.multiSelect ? (
        <CommandButton
          id={id + '-list' + item.index}
          key={item.key}
          data-index={item.index}
          styles={this._getCurrentOptionStyles(item)}
          checked={isSelected}
          className={'ms-ComboBox-option'}
          onClick={this._onItemClick(item)}
          onMouseEnter={this._onOptionMouseEnter.bind(this, item.index)}
          onMouseMove={this._onOptionMouseMove.bind(this, item.index)}
          onMouseLeave={this._onOptionMouseLeave}
          role="option"
          aria-selected={isSelected ? 'true' : 'false'}
          ariaLabel={this._getPreviewText(item)}
          disabled={item.disabled}
          title={title}
        >
          {' '}
          {
            <span className={optionClassNames.optionTextWrapper} ref={isSelected ? this._selectedElement : undefined}>
              {onRenderOption(item, this._onRenderOptionContent)}
            </span>
          }
        </CommandButton>
      ) : (
        <Checkbox
          id={id + '-list' + item.index}


() => {
      return optionStyles;
    }


() => {
      return !this.props.multiSelect ? (
        <CommandButton
          id={id + '-list' + item.index}


() => {
    if (!this._isScrollIdle && this._scrollIdleTimeoutId !== undefined) {
      this._async.clearTimeout(this._scrollIdleTimeoutId);
      this._scrollIdleTimeoutId = undefined;
    } else {
      this._isScrollIdle = false;
    }

    this._scrollIdleTimeoutId = this._async.setTimeout(() => {
      this._isScrollIdle = true;
    }, ScrollIdleDelay);
  }


() => {
      this._isScrollIdle = true;
    }


(item: IComboBoxOption): JSX.Element => {
    const optionClassNames = getComboBoxOptionClassNames(this._getCurrentOptionStyles(item));
    return {item.text};
  }


(ev: any) => void {
    const { onItemClick } = this.props;
    const { index } = item;

    return (ev: any): void =>


(): void => {
    const { onMenuDismiss } = this.props;
    if (onMenuDismiss) {
      onMenuDismiss();
    }

    // In persistMode we need to simulate callout layer mount
    // since that only happens once. We do it on dismiss since
    // it works either way.
    if (this.props.persistMenu) {
      this._onCalloutLayerMounted();
    }

    // close the menu
    this._setOpenStateAndFocusOnClose(false /* isOpen */, false /* focusInputAfterClose */);

    // reset the selected index
    // to the last value state
    this._resetSelectedIndex();
  }


(option: IComboBoxOption, index: number) => {
      if (option.selected) {
        selectedIndices[index] = true;
      }
    }


option => option.key === selectedKey


() => {
    this._processingClearPendingInfo = false;
  }


(ev: React.KeyboardEvent<HTMLElement | Autofill>): void => {
    const { disabled, allowFreeform, autoComplete } = this.props;
    const { isOpen, currentOptions, currentPendingValueValidIndexOnHover } = this.state;

    // Take note if we are processing an alt (option) or meta (command) keydown.
    // See comment in _onInputKeyUp for reasoning.
    this._lastKeyDownWasAltOrMeta = this._isAltOrMeta(ev);

    if (disabled) {
      this._handleInputWhenDisabled(ev);
      return;
    }

    let index = this._getPendingSelectedIndex(false /* includeCurrentPendingValue */);

    switch (ev.which) {
      case KeyCodes.enter:
        if (this._autofill.current && this._autofill.current.inputElement) {
          this._autofill.current.inputElement.select();
        }

        this._submitPendingValue(ev);
        if (this.props.multiSelect && isOpen) {
          this.setState({
            currentPendingValueValidIndex: index
          });
        } else {
          // On enter submit the pending value
          if (
            isOpen ||
            ((!allowFreeform ||
              this.state.currentPendingValue === undefined ||
              this.state.currentPendingValue === null ||
              this.state.currentPendingValue.length <= 0) &&
              this.state.currentPendingValueValidIndex < 0)
          ) {
            // if we are open or
            // if we are not allowing freeform or
            // our we have no pending value
            // and no valid pending index
            // flip the open state
            this.setState({
              isOpen: !isOpen
            });
          }
        }
        break;

      case KeyCodes.tab:
        // On enter submit the pending value
        if (!this.props.multiSelect) {
          this._submitPendingValue(ev);
        }

        // If we are not allowing freeform
        // or the comboBox is open, flip the open state
        if (isOpen) {
          this._setOpenStateAndFocusOnClose(!isOpen, false /* focusInputAfterClose */);
        }

        // Allow TAB to propigate
        return;

      case KeyCodes.escape:
        // reset the selected index
        this._resetSelectedIndex();

        // Close the menu if opened
        if (isOpen) {
          this.setState({
            isOpen: false
          });
        } else {
          return;
        }
        break;

      case KeyCodes.up:
        // if we are in clearAll state (e.g. the user as hovering
        // and has since mousedOut of the menu items),
        // go to the last index
        if (currentPendingValueValidIndexOnHover === HoverStatus.clearAll) {
          index = this.state.currentOptions.length;
        }

        if (ev.altKey || ev.metaKey) {
          // Close the menu if it is open and break so
          // that the event get stopPropagation and prevent default.
          // Otherwise, we need to let the event continue to propagate
          if (isOpen) {
            this._setOpenStateAndFocusOnClose(!isOpen, true /* focusInputAfterClose */);
            break;
          }

          return;
        }

        // Go to the previous option
        this._setPendingInfoFromIndexAndDirection(index, SearchDirection.backward);
        break;

      case KeyCodes.down:
        // Expand the comboBox on ALT + DownArrow
        if (ev.altKey || ev.metaKey) {
          this._setOpenStateAndFocusOnClose(true /* isOpen */, true /* focusInputAfterClose */);
        } else {
          // if we are in clearAll state (e.g. the user as hovering
          // and has since mousedOut of the menu items),
          // go to the first index
          if (currentPendingValueValidIndexOnHover === HoverStatus.clearAll) {
            index = -1;
          }

          // Got to the next option
          this._setPendingInfoFromIndexAndDirection(index, SearchDirection.forward);
        }
        break;

      case KeyCodes.home:
      case KeyCodes.end:
        if (allowFreeform) {
          return;
        }

        // Set the initial values to respond to HOME
        // which goes to the first selectable option
        index = -1;
        let directionToSearch = SearchDirection.forward;

        // If end, update the values to respond to END
        // which goes to the last selectable option
        if (ev.which === KeyCodes.end) {
          index = currentOptions.length;
          directionToSearch = SearchDirection.backward;
        }

        this._setPendingInfoFromIndexAndDirection(index, directionToSearch);
        break;

      case KeyCodes.space:
        // event handled in _onComboBoxKeyUp
        if (!allowFreeform && autoComplete === 'off') {
          break;
        }

      default:
        // are we processing a function key? if so bail out
        if (ev.which >= 112 /* F1 */ && ev.which <= 123 /* F12 */) {
          return;
        }

        // If we get here and we got either and ALT key
        // or meta key, let the event propagate
        if (ev.keyCode === KeyCodes.alt || ev.key === 'Meta' /* && isOpen */) {
          return;
        }

        // If we are not allowing freeform and
        // allowing autoComplete, handle the input here
        // since we have marked the input as readonly
        if (!allowFreeform && autoComplete === 'on') {
          this._onInputChange(String.fromCharCode(ev.which));
          break;
        }

        // allow the key to propagate by default
        return;
    }

    ev.stopPropagation();
    ev.preventDefault();
  }