[
  {
    "path": ".editorconfig",
    "content": "# EditorConfig is awesome: http://EditorConfig.org\n\nroot = true\n\n[*]\nindent_size = 2\ncharset = utf-8\nend_of_line = lf\nindent_style = space\ninsert_final_newline = true\ntrim_trailing_whitespace = true\n\n[*.md]\ntrim_trailing_whitespace = false\n"
  },
  {
    "path": ".eslintrc",
    "content": "{\n  \"env\": {\n    \"browser\": true,\n    \"jest/globals\": true\n  },\n  \"parser\": \"babel-eslint\",\n  \"extends\": [\"standard\", \"prettier\"],\n  \"plugins\": [\"flowtype\", \"jest\"],\n  \"rules\": {\n    \"comma-dangle\": [\"error\", \"always-multiline\"],\n    \"semi\": [\"error\", \"always\"],\n    \"flowtype/define-flow-type\": 1\n  }\n}\n"
  },
  {
    "path": ".flowconfig",
    "content": "[ignore]\n\n[include]\n\n[libs]\n\n[lints]\n\n[options]\n\n[strict]\n"
  },
  {
    "path": ".gitignore",
    "content": "node_modules\n.cache\ndist\nlib\n*.log\nreference\n.DS_Store\n\n# editor specific files\n.vscode\n.package-lock.json\n"
  },
  {
    "path": ".npmignore",
    "content": "# Ignore source and reference files\nsrc\nnode_modules\nreference\n\n# Ignore config files\n.eslintrc\n.gitignore\nwebpack.config.js\n\n# Ignore doc and example file\ndocs\nexample\nexample_old\n\n"
  },
  {
    "path": ".prettierrc",
    "content": "{\n  \"printWidth\": 100,\n  \"arrowParens\": \"always\",\n  \"singleQuote\": true,\n  \"tabWidth\": 2,\n  \"useTabs\": false,\n  \"semi\": true,\n  \"bracketSpacing\": true,\n  \"jsxBracketSameLine\": false,\n  \"requirePragma\": false,\n  \"proseWrap\": \"preserve\",\n  \"trailingComma\": \"all\"\n}\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: node_js\nnode_js:\n  - \"8\"\nscript:\n  - echo 'Starting Build!'\n  - echo 'Installing Deps!'\n  - yarn\n  - echo 'Testing!'\n  - yarn test\n  - echo 'Checking Bundle Size!'\n  - yarn test:bundlesize\ndeploy:\n  on:\n    tags: true\n  provider: npm\n  email: \"$EMAIL_ADDRESS\"\n  api_key: \"$AUTH_TOKEN\"\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "v11.0\n  - Support new jsx transform.\n  - Children APIs\n  - 3rd Party React library support (Tested React-router, redux, mobx, react-query, zustand, recharts)\n  - Added couple of unit test for the library.\n\nv10.0\n  - Concurrent mode API support\n  - Suspense for data fetch, Suspense.\n  - React Memo\n\nv9.0\n  - Rewrote library with Fiber architecture.\n\nv8.0\n  - SVG support\n  - Portals\n  - Context API "
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, we as\ncontributors and maintainers pledge to making participation in our project and\nour community a harassment-free experience for everyone, regardless of age, body\nsize, disability, ethnicity, sex characteristics, gender identity and expression,\nlevel of experience, education, socio-economic status, nationality, personal\nappearance, race, religion, or sexual identity and orientation.\n\n## Our Standards\n\nExamples of behavior that contributes to creating a positive environment\ninclude:\n\n* Using welcoming and inclusive language\n* Being respectful of differing viewpoints and experiences\n* Gracefully accepting constructive criticism\n* Focusing on what is best for the community\n* Showing empathy towards other community members\n\nExamples of unacceptable behavior by participants include:\n\n* The use of sexualized language or imagery and unwelcome sexual attention or\n advances\n* Trolling, insulting/derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or electronic\n address, without explicit permission\n* Other conduct which could reasonably be considered inappropriate in a\n professional setting\n\n## Our Responsibilities\n\nProject maintainers are responsible for clarifying the standards of acceptable\nbehavior and are expected to take appropriate and fair corrective action in\nresponse to any instances of unacceptable behavior.\n\nProject maintainers have the right and responsibility to remove, edit, or\nreject comments, commits, code, wiki edits, issues, and other contributions\nthat are not aligned to this Code of Conduct, or to ban temporarily or\npermanently any contributor for other behaviors that they deem inappropriate,\nthreatening, offensive, or harmful.\n\n## Scope\n\nThis Code of Conduct applies both within project spaces and in public spaces\nwhen an individual is representing the project or its community. Examples of\nrepresenting a project or community include using an official project e-mail\naddress, posting via an official social media account, or acting as an appointed\nrepresentative at an online or offline event. Representation of a project may be\nfurther defined and clarified by project maintainers.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported by contacting the project team at sudhanshuyadav2@gmail.com. All\ncomplaints will be reviewed and investigated and will result in a response that\nis deemed necessary and appropriate to the circumstances. The project team is\nobligated to maintain confidentiality with regard to the reporter of an incident.\nFurther details of specific enforcement policies may be posted separately.\n\nProject maintainers who do not follow or enforce the Code of Conduct in good\nfaith may face temporary or permanent repercussions as determined by other\nmembers of the project's leadership.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,\navailable at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html\n\n[homepage]: https://www.contributor-covenant.org\n\nFor answers to common questions about this code of conduct, see\nhttps://www.contributor-covenant.org/faq\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2019 Sudhanshu Yadav\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "<p align=\"center\">\n  <img src=\"https://unpkg.com/brahmos@0.5.0/brahmos.svg\" alt=\"Brahmos.js\" width=\"250\">\n</p>\n\n# Brahmos\n\nSupercharged JavaScript library to build user interfaces with modern React API and native templates.\n\nBrahmos supports all the APIs of React including the upcoming concurrent mode APIs and the existing ones. It has its own custom fiber architecture and concurrent mode implementation to support the concurrent UI patterns.\n\n## Features\n\n- Lightweight and Fast.\n- Exact same React's Declarative APIs with JSX.\n- Fast alternative to Virtual DOM. (JSX without VDOM).\n- Smaller transpiled footprint of your source code, than traditional JSX.\n\n## Installation\n### Create Brahmos App\nUse [Create a New Brahmos App](https://www.npmjs.com/package/create-brahmos-app) if you're looking for a powerful JavaScript toolchain.\n\n### Manual installation\n\nAdd `brahmos` as dependency. And `babel-plugin-brahmos` as dev dependency.\n```\nnpm install brahmos\nnpm install babel-plugin-brahmos --save-dev\n```\n\nAdd brahmos in your babel config.\n```\n{\n  presets: ['@babel/preset-env'],\n  plugins: [\n    //...\n    'brahmos'\n  ]\n}\n```\n**Note:** You will have to remove react preset from babel if you trying brahmos on existing project.\n\n## Usage\nThe API is exact same as React so build how you build application with React, but instead of importing from `react` or `react-dom` import from `brahmos`;\n\n```js\nimport {useState, useEffect} from 'brahmos';\n\nexport default function App(props) {\n  const [state, setState] = useState(0);\n\n  return (\n    <div>\n      ...\n    </div>\n  )\n}\n```\n\n\n### Using React 3rd party libraries\n\nJust alias react and react-dom with brahmos. And you are good to go using 3rd party react libraries.\n\nYou need to add following aliases.\n```js\nalias: {\n  react: 'brahmos',\n  'react-dom': 'brahmos',\n  'react/jsx-runtime': 'brahmos'\n},\n```\n\n-  **webpack** ([https://webpack.js.org/configuration/resolve/#resolvealias](https://webpack.js.org/configuration/resolve/#resolvealias))\n- **parcel** ([https://parceljs.org/module_resolution.html#aliases](https://parceljs.org/module_resolution.html#aliases))\n- **rollup** ([https://www.npmjs.com/package/@rollup/plugin-alias](https://www.npmjs.com/package/@rollup/plugin-alias))\n- **babel** ([https://www.npmjs.com/package/babel-plugin-module-resolver](https://www.npmjs.com/package/babel-plugin-module-resolver))\n\n\n## Idea\n\nIt is inspired by the rendering patterns used on hyperHTML and lit-html.\n\nIt has the same declarative API like React, but instead of working with VDOM, it uses tagged template literals and HTML's template tag for faster rendering and updates.\nIt divides the HTML to be rendered into static and dynamic parts, and in next render, it has to compare the values of only dynamic parts and apply the changes optimally to the connected DOM.\nIt's unlike the VDOM which compares the whole last rendered VDOM to the new VDOM (which has both static and dynamic parts) to derive the optimal changes that are required on the actual DOM.\n\nEven though tagged template literals are the key to static and dynamic part separation, the developer has to code on well adopted JSX.\n\nUsing the babel-plugin-brahmos it transforms JSX into tagged template literals which are optimized for render/updates and the output size.\n\nConsider this example,\n\n```jsx\nclass TodoList extends Component {\n  state = { todos: [], text: '' };\n  setText = (e) => {\n    this.setState({ text: e.target.value });\n  };\n  addTodo = () => {\n    let { todos, text } = this.state;\n    this.setState({\n      todos: todos.concat(text),\n      text: '',\n    });\n  };\n  render() {\n    const { todos, text } = this.state;\n    return (\n      <form className=\"todo-form\" onSubmit={this.addTodo} action=\"javascript:\">\n        <input value={text} onChange={this.setText} />\n        <button type=\"submit\">Add</button>\n        <ul className=\"todo-list\">\n          {todos.map((todo) => (\n            <li className=\"todo-item\">{todo}</li>\n          ))}\n        </ul>\n      </form>\n    );\n  }\n}\n```\n\nIt will be transformed to\n\n```js\nclass TodoList extends Component {\n  state = { todos: [], text: '' };\n  setText = (e) => {\n    this.setState({ text: e.target.value });\n  };\n  addTodo = () => {\n    let { todos, text } = this.state;\n    this.setState({\n      todos: todos.concat(text),\n      text: '',\n    });\n  };\n  render() {\n    const { todos, text } = this.state;\n    return html`\n      <form class=\"todo-form\" ${{ onSubmit: this.addTodo }} action=\"javascript:\">\n        <input ${{ value: text }} ${{ onChange: this.setText }} />\n        <button type=\"submit\">Add</button>\n        <ul class=\"todo-list\">\n          ${todos.map((todo) =>\n            html`\n              <li class=\"todo-item\">${todo}</li>\n            `(),\n          )}\n        </ul>\n      </form>\n    `(\"0|0|1,0|1|0,1|3|\");\n  }\n}\n```\n\nWith the tagged template literal we get a clear separating of the static and dynamic part. And on updates it needs to apply changes only on the changed dynamic parts.\n\nTagged template literals also have a unique property where the reference of the literal part (array of static strings) remain the same for every call of that tag with a given template.\nTaking advantage of this behavior Brahmos uses literal parts as a cache key to keep the intermediate states to avoid the work done to process a template literal again.\n\nTagged template is natively supported by the browser, unlike the React's JSX which has to be transformed to React.createElement calls. So the output generated to run Brahmos has a smaller footprint than the output generated for the react.\nFor the above example, the Brahmos output is 685 bytes, compared to 824 bytes from the React output. More the static part of an HTML, greater the difference will be.\n\n## Demo\n\nThe following demo demonstrates the support of all the APIs coming in future version of React like Concurrent mode, suspense list, suspense for data fetch, and also for the existing APIs like states, hooks, context api, refs etc.\n\n[https://codesandbox.io/s/brahmos-demo-3t8r6](https://codesandbox.io/s/brahmos-demo-3t8r6)\n\n\n## Talk on the Idea of Brahmos\n\n<a href=\"https://www.youtube.com/watch?v=oYdVhIzPBr8&feature=youtu.be&ab_channel=BristolJS\" target=\"_blank\" rel=\"noopener\">\n  <img src=\"https://unpkg.com/brahmos@0.10.0-alpha4/brahmos_talk.jpg\" alt=\"Brahmos.js: React without VDOM\"\n\ttitle=\"Brahmos.js: React without VDOM\" width=\"410px\" />\n</a>\n\n## Slack Channel\n\nhttps://join.slack.com/t/brahmoscommunity/shared_invite/enQtODM5NDMwODgwMzQyLTc4YjJlZjY3Mzk1ODJkNTRkODljYjhmM2NhMGIxNzFjMjZjODk0MmVjZTVkNmE5Y2MwYzZkMzk5NTUxYmI5OWE\n\n## Progress\n\n- [x] Babel Plugin to transpile JSX to tagged template\n- [x] Class components with all life cycle methods (Except deprecated methods)\n- [x] Functional Component\n- [x] List and Keyed list\n- [x] Synthetic input events - onChange support\n- [x] Hooks\n- [x] Context API\n- [x] Refs Api, createRef, ref as callback, forwardRef\n- [x] SVG Support\n- [x] Suspense, Lazy, Suspense for data fetch, Suspense List\n- [x] Concurrent Mode\n- [x] 3rd Party React library support (Tested React-router, redux, mobx, react-query, zustand, recharts)\n- [x] React Utilities and Methods\n- [ ] Handle server rendering\n- [ ] Performance improvement\n- [ ] Bug fixes\n- [ ] Test Cases\n\n"
  },
  {
    "path": "babel.config.js",
    "content": "module.exports = {\n  presets: [['@babel/preset-env']],\n  plugins: [\n    '@babel/plugin-transform-flow-strip-types',\n    '@babel/plugin-transform-runtime',\n    '@babel/plugin-proposal-class-properties',\n    ['@babel/plugin-proposal-object-rest-spread', {}, 'rest-spread'],\n    'brahmos',\n  ],\n};\n"
  },
  {
    "path": "bundlesize.config.json",
    "content": "{\n    \"files\": [\n      {\n        \"path\": \"./dist/brahmos.js\",\n        \"maxSize\": \"20 kB\"\n      },\n      {\n        \"path\": \"./dist/brahmos.min.js\",\n        \"maxSize\": \"7 kB\"\n      }\n    ]\n  }\n"
  },
  {
    "path": "docs/HOW_IT_WORKS.md",
    "content": "<h2> ⚠️ Warning: This document is stale, a lot has been changed since this doc was published. This need's to be updated. </h2>\n\nThis document is to explain how Brahmos work, its concept, internals and taxonomies. This is a good place for the contributors and people who want to understand the inner working of the Brahmos.\n\nThis doc tries to cover the different parts of Brahmos and explains what they do. Links to the source files are also added so you can dive deep through code and comments as well.\n\nThis doc tries to be as much as descriptive so that you can understand the internals of Brahmos. But if things are unclear and you have some ideas to improve it, please raise an issue or submit a PR.\n\n- [Concept](#concept)\n- [Brahmos Transformation (with babel-plugin-brahmos)](#brahmos-transformation-with-babel-plugin-brahmos)\n    - [Basic html with dynamic value](#basic-html-with-dynamic-value)\n    - [Html with Custom Component](#html-with-custom-component)\n    - [More complex transformation](#more-complex-transformation)\n- [Tag function `html`](#tag-function-html)\n- [createElement](#createelement)\n- [Brahmos Nodes](#brahmos-nodes)\n    - [Brahmos Tag Node](#brahmos-tag-node)\n    - [Brahmos Component Node](#brahmos-component-node)\n    - [Brahmos Element Node](#brahmos-element-node)\n    - [Brahmos String Node](#brahmos-string-node)\n    - [Brahmos Array Node](#brahmos-array-node)\n- [Brahmos node tree](#brahmos-node-tree)\n- [TemplateTag](#templatetag)\n- [TemplateNode](#templatenode)\n- [Class Component](#class-component)\n- [Functional Component](#functional-component)\n- [Associating instance](#associating-instance)\n- [Updater](#updater)\n  - [Attribute updater](#attribute-updater)\n  - [Node updater](#node-updater)\n    - [Non renderable node](#non-renderable-node)\n    - [Component node](#component-node)\n    - [Tag node & Element node](#tag-node--element-node)\n    - [Array nodes](#array-nodes)\n    - [Text nodes](#text-nodes)\n- [Tear down](#tear-down)\n\n## Concept\n\nBrahmos is a lightweight implementation of React without VDOM. It has the same declarative API like React, but instead of working with VDOM, it uses tagged template literals and HTML's template tag for faster rendering and updates. It divides the HTML to be rendered into static and dynamic parts, and in next render, it has to compare the values of only dynamic parts and apply the changes optimally to the connected DOM. It's unlike the VDOM which compares the whole last rendered VDOM (which has both static and dynamic parts) with the new VDOM to derive the optimal changes that are required on the actual DOM.\n\nIt has the exact same API as React but the Brahmos compiler and the renderer makes this library different. Let's see how it works.\n\n## Brahmos Transformation (with babel-plugin-brahmos)\n\nA developer writes code in JSX and the babel-plugin-brahmos transform code to templateLiteral.\n\nHere are example of few transformation.\n\n#### Basic html with dynamic value\n\n```jsx\n<div className=\"greet\">\n  Hello <span className=\"name\">{name}</span> !!\n</div>\n```\n\nIn Brahmos this will be transformed to.\n\n```js\nhtml`\n  <div class=\"greet\">Hello <span class=\"name\">${name}</span> !!</div>\n`;\n```\n\nCompared to React\n\n```js\nReact.createElement(\n  'div',\n  {\n    className: 'greet',\n  },\n  'Hello ',\n  React.createElement(\n    'span',\n    {\n      className: 'name',\n    },\n    name,\n  ),\n  ' !!',\n);\n```\n\nWith the string literal, you can see there is a clear separation between static and dynamic part.\n\n#### Html with Custom Component\n\n```jsx\n<div className=\"greet\">\n  Hello <Name value={name} /> !!\n</div>\n```\n\nBrahmos:\n\n```js\nhtml`\n  <div class=\"greet\">\n    Hello ${createElement(Name, { value: 'name' })} !!\n  </div>\n`;\n```\n\nReact:\n\n```js\nReact.createElement(\n  'div',\n  {\n    className: 'greet',\n  },\n  'Hello ',\n  React.createElement(Name, {\n    value: name,\n  }),\n  ' !!',\n);\n```\n\n- For Custom component it uses the syntax createElement similar to React as they cannot be converted to the template tag. With the first argument being a Component reference, the 2nd argument being props followed by children.\n- The output of createElement of Brahmos is slightly different than the React.\n- This also enables support for third-party React component to be used along with Brahmos.\n\n#### More complex transformation\n\n```jsx\n<div className=\"items\">\n  <Item>\n    <img className=\"item-img\" src={itemImg} alt={itemShortDesc} />\n    <p>{itemDesc}</p>\n    <button className=\"add-item\" onClick={this.addItem}>\n      Add\n    </button>\n  </Item>\n</div>\n```\n\nBrahmos:\n\n```js\nhtml`\n  <div class=\"items\">\n    ${createElement(\n      Item,\n      {},\n      html`\n        <img class=\"item-img\" ${{ src: itemImg, alt: itemShortDesc }} />\n        <p>${itemDesc}</p>\n        <button className=\"add-item\" ${{ onClick: this.addItem }}>\n          Add\n        </button>\n      `,\n    )}\n  </div>\n`;\n```\n\nReact:\n\n```js\nReact.createElement(\n  'div',\n  {\n    className: 'items',\n  },\n  React.createElement(\n    Item,\n    null,\n    React.createElement('img', {\n      className: 'item-img',\n      src: itemImg,\n      alt: itemShortDesc,\n    }),\n    React.createElement('p', null, itemDesc),\n    React.createElement(\n      'button',\n      {\n        className: 'add-item',\n        onClick: (void 0).addItem,\n      },\n      'Add',\n    ),\n  ),\n);\n```\n\n- Dynamic attributes are transformed into key-value pairs while also maintaining the node reference of that dynamic attributes.\n- A tagged template literal can be passed as children of createElement call. Children can be string, tagged component literal, another custom component or array of all this.\n- We can also see how the overall footprint of Brahmos output is smaller than the JSX output. And bigger the static part bigger the difference will be more.\n\n## Tag function `html`\n\nSource: [https://github.com/s-yadav/brahmos/blob/master/src/tags.js](https://github.com/s-yadav/brahmos/blob/master/src/tags.js)\n\nOn the code transformed by Brahmos, we see the ES6 template literal with a tag.\nTags are nothing but a function which receives an array of the literal part (static part) followed by all expressions (values).\n\n```js\nfunction html(strings, ...values) {\n  // string ['<div class=\"greeting\">\\nHello <span class=\"name\">', '</span> !!\\n</div>']\n  // values = [name]\n}\n```\n\nA tag function doesn't have to return only the string, it can return anything. The html tag function returns an object (Brahmos Tag Node) which contains TemplateTag instance (which we will see later) and an array of dynamic expressions.\n\nBrahmos Tag Node\n\n```js\n{\n  template: templateTagInstance,\n  values: [name],\n}\n```\n\nAlso on a tag function, the reference of string array remains the same for a given template. We use this behaviour to cache the templateTagInstance for a given literal (static) part and reuse it for next calls.\n\n## createElement\n\nSource: https://github.com/s-yadav/brahmos/blob/master/src/createElement.js\n\ncreateElement API is similar to react where the first argument is an element (component reference or a string), the second argument is for props followed by children.\n\nIt returns the Brahmos element node if a string is passed as the first argument and returns the Brahmos component node if component reference is passed.\n\nBrahmos Element Node\n\n```js\n{\n  element: 'div',\n  values: [attributes, children]\n}\n```\n\nBrahmos Component Node\n\n```js\n{\n  type: BrahmosComponent,\n  props: {\n    ...allPassedProps,\n    children,\n  }\n  key,\n  ref,\n}\n```\n\nSimilar to React children are passed as a prop. key and ref are reserved props and are not passed to the component.\n\n## Brahmos Nodes\n\nBrahmos has different types of nodes which are handled and updated differently on first render or updates.\n\n#### Brahmos Tag Node\n\nThis is returned by tagged template, which looks like\n\n```js\n{\n  template: templateTagInstance,\n  values: [...dynamicExpressions],\n  __$isBrahmosTag$__: true,\n}\n```\n\n#### Brahmos Component Node\n\n- Brahmos component node is further divided into `Class Component Node` and `Functional Component Node`.\n- Component nodes are returned by the createElement call with custom component.\n\n```js\n{\n  type: BrahmosComponent,\n  props: {\n    ...allPassedProps,\n    children,\n  }\n  key,\n  ref,\n  __$isBrahmosComponent$__: true,\n  __$isBrahmosClassComponent$__: true | false,\n  __$isBrahmosFunctionalComponent$__: true | false,\n}\n```\n\n#### Brahmos Element Node\n\n- This is returned by the createElement call with HTML elements tagName instead of custom component.\n\n```js\n{\n  element: 'div',\n  values: [attributes, children],\n  __$isBrahmosTag$__: true,\n  __$isBrahmosTagElement$__: true,\n}\n```\n\n#### Brahmos String Node\n\n- This is a simple string and is rendered as a text node.\n\n#### Brahmos Array Node\n\n- This is an array of the above types of nodes.\n\n## Brahmos node tree\n\nBased on the different types of nodes Brahmos forms a node tree. Unlike the VDOM which is a tree representation of the actual dom, Brahmos maintains a tree of Brahmos nodes. So the depth of the Brahmos node is much smaller than VDOM.\n\nFor the following JSX\n\n```jsx\n<div className=\"items\">\n  <Item>\n    <img className=\"item-img\" src={itemImg} alt={itemShortDesc} />\n    <p>{itemDesc}</p>\n    <button className=\"add-item\" onClick={addItem}>\n      Add\n    </button>\n  </Item>\n</div>\n```\n\nBrahmos tree will look like\n\n```js\n{\n  template: templateTagInstance, // for the outer div\n  values: [{\n    type: Item,\n    props: {\n      children: {\n        template: templateTagInstance, // for the Item content\n        values: [itemImg, itemShortDesc, itemDesc, addItem]\n      }\n    },\n    __$isBrahmosComponent$__: true,\n  }]\n  __$isBrahmosTag$__: true,\n}\n```\n\nCompared to React VDOM tree which looks like\n\n```js\n{\n  type: 'div',\n  props: {\n    className: 'items',\n    children: [{\n      type: 'item',\n      props: {\n        children: [{\n          type: 'img' ,\n          props: {\n            className: 'item-img',\n            src: itemImg,\n            alt: itemShortDesc,\n          }\n        }, {\n          type: 'p',\n          props: {\n            children: [itemDesc]\n          },\n        }, {\n          type: 'button',\n          props: {\n            className: 'add-item',\n            onClick: addItem,\n            children: ['Add']\n          }\n        }]\n      }\n    }]\n  }\n}\n```\n\nThe Brahmos tree is then recursively analyzed to associate proper node instances and to render.\n\n## TemplateTag\n\nSource: https://github.com/s-yadav/brahmos/blob/master/src/TemplateTag.js\n\nTemplateTag class has two responsibilities.\n\n1. Create a template tag (HTML tag) for a given literal part (static part).\n2. Create basic parts metadata.\n\nFor a given template\n\n```js\nhtml`\n  <div class=\"greeting\" {{onClick: handleClick}}>Hello <span class=\"name\">${name}</span> !!</div>\n`();\n```\n\nTemplateTag Class will create a template tag which will look like\n\n```html\n<template>\n  <div class=\"greeting\" data-brahmos-attr>\n    Hello <span class=\"name\"><!--{{brahmos}}--></span> !!\n  </div>\n</template>\n```\n\nIt adds placeholder for attribute part and node part so parts can be processed easily later.\n\nIt will also create dynamic part metadata. For the above template this will look like\n\n```js\n[\n  {\n    tagAttrs: ['class'], //this are all other attributes other than dynamic attributes.\n    attrIndex: 1, // store the location of dynamic attribute part\n    isAttribute: true,\n  },\n  {\n    isNode: true,\n  },\n];\n```\n\n- For the tag attribute, we store the index (location) of dynamic attribute so attribute can be applied in order without overriding attributes which it shouldn't.\n\nFor example\n\n```js\nhtml`<div id=\"someId\" {{id: 'someOtherId'}}></div>\n```\n\nThis should have `someOtherId` as id. While\n\n```js\nhtml`<div {{id: 'someOtherId'}} id=\"someId\"></div>\n```\n\nThis should have `someId` as id.\n\nattrIndex helps to figure out which one to apply in such cases.\n\ncreating a template tag and part metadata is deferred until the first render of that component. This is required as some information is available during the render time only like whether a template is part of an SVG or the normal HTML.\n\n## TemplateNode\n\nSource: https://github.com/s-yadav/brahmos/blob/master/src/TemplateNode.js\n\nTemplateNode class do two things\n\n1. Create DOM nodes from the template tag removing the placeholders.\n2. Create part information using placeholder location and parts metadata from the templateTagInstance.\n\nEach of Brahmos tag node has different TemplateNode instance, but it remains the same for all consecutive renders till it has same TemplateTag instance.\n\nIf TemplateTag instance does not have template tag and part metadata created, TemplateNode initializes that on TemplateTag Instance.\n\nTemplateNode then clones the template tag and remove place holders and creates the part information which has actual DOM references of dynamic locations.\n\nNode which is appended to dom\n\n```html\n<div class=\"greeting\">Hello <span class=\"name\"></span> !!</div>\n```\n\nPart information\n\n```js\n[{\n  tagAttrs: ['class'],\n  attrIndex: 1,\n  isAttribute: true,\n  node: Element, //div.greeting\n}, {\n  isNode: true,\n  parentNode: Element //span.name\n  previousSibling: null, //null because there is no previousSibling of the dynamic part\n  nextSibling: null, // null because there is no nextSibling of the the dynamic part\n}]\n```\n\nNow with this part information, dynamic parts can be updated directly as now we know the actual DOM locations for those dynamic parts.\n\nOn creation of TemplateNode instance, it attaches this instance to Brahmos tag node so it can be used later.\n\n```js\n{\n  template: templateTagInstance,\n  values: [...dynamicExpressions],\n  templateNode: templateNodeInstance,\n  __$isBrahmosTag$__: true,\n}\n```\n\n## Class Component\n\nSource: https://github.com/s-yadav/brahmos/blob/master/src/Component.js\n\nClass Component API is exactly the same as the React. There are few implementation changes though from the React.\n\n- The deprecated life cycle methods are not supported. Even unsafe life cycle methods are not supported.\n- setState calls batch all the state change and are always asynchronous.\n\nClass Component keeps the last rendered node information so on next render it can associate proper instance to each of Brahmos Node.\n\nDuring the render, the updater creates ComponentInstance and attaches it to the Brahmos component node.\n\n```js\n{\n  type: Component,\n  props: {...}\n  componentInstance: classComponentInstance,\n}\n```\n\n## Functional Component\n\nSource: https://github.com/s-yadav/brahmos/blob/master/src/functionalComponentInstance.js\n\nFunctional Component is written the same way as React,\nWhile rendering Brahmos creates an instance of a functional component and associate the instance to Brahmos Component node.\n\n```js\n{\n  type: Component,\n  props: {...}\n  componentInstance: functionalComponentInstance,\n}\n```\n\n## Associating instance\n\nSource: https://github.com/s-yadav/brahmos/blob/master/src/associateInstance.js\n\nThis is key to making optimal updates. On rerender of a Brahmos node, the associateInstance method associate already created templateNodeInstance, or componentInstance to the new node, so it gets the reference of dynamic parts on the actual dom node.\n\nIf a node does not get an associated instance it means it is a new node and old node needs to be removed and the new one should get added.\n\nThe instance association to the new node happens with following rules.\n\n- If the new node and old node at a specific tree path are different types, then return without associating anything.\n- If the new node is a Brahmos tag node, and the templateTag instance of new node and old node is same then associate the templateNode instance to the new node. (If the literal part of a template is same, the templateTag instance will always remain same)\n- If the new node is a Brahmos component node and the node.type matches with oldNode.type then it associates component instance form the old node to the new node.\n- If the new node is Brahmos element node, and the element tagName matches with the oldNode's tagName then it associates templateNode instance to the new node.\n- If the new node is an array, each of the nodes in that array is matched with the item in the old node having the same index or the same key. And if they match based on the above condition instance are associated with the node.\n\n## Updater\n\nSource: https://github.com/s-yadav/brahmos/blob/master/src/updater.js\n\nAn updater is a place where all rendering or updates happens. It recursively updates all the Brahmos node on the tree. There are three main arguments of an updater.\n\n- parts, which is an array of dynamic part and have information about DOM location and type of part (attribute or node).\n- values, which is an array of dynamic values.\n- oldValues, an array of old values against which the updater can compare and only if there is a change in value apply the changes to the DOM.\n\nThere are different types of updates with two categories.\n\n- Attribute updater\n- Node updater\n\nApart from calling proper updater it takes care of two more thing\n\n- Merge all dynamic attribute for a dom node, so it can be effectively updated.\n- Set proper ref if ref prop is passed to an element.\n\n### Attribute updater\n\nSource: https://github.com/s-yadav/brahmos/blob/master/src/updateAttribute.js\n\n- Attribute updater takes care of updating the attribute of a given node based on the index of that attribute. This information comes from the part object.\n- It handles dom node property and attributes differently.\n- For event properties, it takes care of removing old event listeners (if the eventListener is changed) and add new event listeners.\n- To be React compatible it has synthetic events only for inputs. It has the same onChange API as react. https://github.com/s-yadav/brahmos/blob/master/src/reactEvents.js\n- For inputs, it takes care of controlled and uncontrolled input similar to React. https://github.com/s-yadav/brahmos/blob/master/src/reactEvents.js\n\n### Node updater\n\nSource: https://github.com/s-yadav/brahmos/blob/master/src/updateNode.js\n\nNode updater handles rendering and updates of different type of Brahmos node.\n\n#### Non renderable node\n\nFor non-renderable values like `null`, `undefined`, `false`, it bails out and\nremove the existing old node if present on that location.\n\n#### Component node\n\nSource: https://github.com/s-yadav/brahmos/blob/master/src/updateComponentNode.js\n`updateComponentNode` handles updating a component node. It creates a component instance and associates the instance to the component node if it's not already created.\n\nFor class components\n\n- it calls all the applicable life cycle methods if provided and renders with the error boundaries.\n- It applies and flushes all the uncommitted state if present for that component.\n- It also takes care or providing proper context to a component and merge contextValue provided by the ContextProvider for the component nodes down the tree.\n- It sets a proper component reference to ref prop.\n\nFor functional component\n\n- It takes care of calling effects after the render and clean the effects before the next render.\n\n#### Tag node & Element node\n\nSource: https://github.com/s-yadav/brahmos/blob/master/src/updateNode.js#L135\n\n- It creates a TemplateNode instance and associates it with Brahmos tag node if it's not already created.\n- For the element node, it creates an object similar to templateNode (if not created already) and associates it to the node. https://github.com/s-yadav/brahmos/blob/master/src/TagNode.js\n- For the first render, it adds everything on a document fragment and adds it to DOM at the end to avoid multiple reflows.\n\n#### Array nodes\n\nSource: https://github.com/s-yadav/brahmos/blob/master/src/updateNode.js#L91\n\n- Array's are optimally updated based on provided keys. It reuses the same DOM element even if the order changes (if proper keys are provided).\n- It takes care of optimally removing unused old nodes, reordering of nodes and adding new nodes.\n\n#### Text nodes\n\nSource: https://github.com/s-yadav/brahmos/blob/master/src/updateNode.js#L23\n\n- For text nodes, it finds the existing text node at the DOM tree path and only updates the text value avoiding creating new text node.\n\n## Tear down\n\nSource: https://github.com/s-yadav/brahmos/blob/master/src/tearDown.js\nTear down is a way to recursively delete a path from a given node on the Brahmos tree. It takes care of the following things.\n\n- Unmount the components and call life cycle methods for the class component.\n- Clean the effects on a functional component.\n- Unset the refs.\n- Delete the dom nodes.\n"
  },
  {
    "path": "example/App.js",
    "content": "import { useState, useEffect, useMemo } from 'brahmos';\n\nimport { Switch, Route, NavLink, useLocation } from 'react-router-dom';\n\nimport { BrahmosLogo, GithubLogo } from './Logos';\nimport TodoList from './todo-list';\nimport ConcurrentModeDemo from './concurrent-mode';\nimport SuspenseListDemo from './suspense-list';\nimport UseDeferredValueDemo from './use-deferred-value';\nimport UseDeferredValueSuspenseDemo from './use-deferred-value-suspense';\nimport LazyComponentDemo from './lazy-component';\nimport PortalDemo from './portals';\nimport ErrorBoundariesDemo from './error-boundaries';\nimport SVGDemo from './svg-chart';\nimport HooksDemo from './hooks';\nimport ContextDemo from './context-api';\nimport RechartExample from './third-party-component';\nimport ReduxExample from './food-app/redux';\nimport MobxExample from './food-app/mobx';\nimport ReactQueryExample from './food-app/react-query';\n\nimport './App.scss';\n\nconst examples = [\n  {\n    title: 'TODO List',\n    id: 'todo-list',\n    Component: TodoList,\n  },\n  {\n    title: 'Context API',\n    id: 'context-api',\n    Component: ContextDemo,\n  },\n  {\n    title: 'Hooks Demo',\n    id: 'hooks',\n    Component: HooksDemo,\n  },\n  {\n    title: 'Error Boundaries Demo',\n    id: 'error-boundaries',\n    Component: ErrorBoundariesDemo,\n  },\n  {\n    title: 'SVG Support Demo',\n    id: 'svg-support',\n    Component: SVGDemo,\n  },\n  {\n    title: 'Portal Demo',\n    id: 'portals',\n    Component: PortalDemo,\n  },\n  {\n    title: 'Concurrent Mode Demo',\n    id: 'concurrent-mode',\n    Component: ConcurrentModeDemo,\n  },\n  {\n    title: 'Suspense List Demo',\n    id: 'suspense-list',\n    Component: SuspenseListDemo,\n  },\n  {\n    title: 'Suspense with useDeferredValue',\n    id: 'use-deferred-value-suspense',\n    Component: UseDeferredValueSuspenseDemo,\n  },\n  {\n    title: 'Time slicing with useDeferredValue',\n    id: 'use-deferred-value',\n    Component: UseDeferredValueDemo,\n  },\n  {\n    title: 'Lazy Component Demo',\n    id: 'lazy-component',\n    Component: LazyComponentDemo,\n  },\n  {\n    title: 'Third Party React Component',\n    id: 'third-party-component',\n    Component: RechartExample,\n  },\n  {\n    title: 'Redux Demo',\n    id: 'redux',\n    Component: ReduxExample,\n  },\n  {\n    title: 'Mobx Demo',\n    id: 'mobx',\n    Component: MobxExample,\n  },\n  {\n    title: 'React Query and Zustand Demo',\n    id: 'rq-zustand',\n    Component: ReactQueryExample,\n  },\n];\n\nexport default function App() {\n  const { pathname } = useLocation();\n\n  const title = useMemo(() => {\n    const pathWithoutHash = pathname.substr(1);\n    const currentSelected = examples.find((obj) => obj.id === pathWithoutHash);\n    return currentSelected ? currentSelected.title : examples[0].title;\n  }, [pathname]);\n\n  return (\n    <div className=\"app-container\">\n      <header class=\"hero is-primary\">\n        <div class=\"hero-body\">\n          <a href=\"https://github.com/brahmosjs/brahmos\" target=\"_blank\" rel=\"noopener\">\n            <div className=\"logo\">\n              <BrahmosLogo class=\"brahmos-logo\" />\n              <GithubLogo class=\"github-logo\" />\n            </div>\n          </a>\n\n          <div>\n            <h1 class=\"title\">\n              Brahmos Demo{' '}\n              <iframe\n                src=\"https://ghbtns.com/github-btn.html?user=brahmosjs&repo=brahmos&type=fork&count=false&size=large\"\n                frameborder=\"0\"\n                scrolling=\"0\"\n                width=\"170\"\n                height=\"30\"\n                className=\"star-btn\"\n                title=\"GitHub\"\n              ></iframe>\n            </h1>\n            <h2 class=\"subtitle\">\n              Brahmos is a Super charged UI library with exact same declarative APIs of React which\n              uses native templates to separate static and dynamic parts of an application for\n              faster updates.\n            </h2>\n          </div>\n        </div>\n      </header>\n      <div className=\"body row\">\n        <aside className=\"menu has-background-light column is-one-quarter\">\n          <nav className=\"menu-list\">\n            <ul>\n              {examples.map((example) => {\n                const { title, id } = example;\n                return (\n                  <li className=\"menu-list-item\" key={id}>\n                    <NavLink to={`/${id}`} activeClassName=\"is-active\">\n                      {title}\n                    </NavLink>\n                  </li>\n                );\n              })}\n            </ul>\n          </nav>\n        </aside>\n        <div className=\"example-container content column\">\n          <h2>{title}</h2>\n          <Switch>\n            <Route key={'/'} exact path={`/`} component={examples[0].Component} />\n            {examples.map(({ id, Component }) => {\n              return (\n                <Route key={id} path={`/${id}`}>\n                  <Component />\n                </Route>\n              );\n            })}\n          </Switch>\n        </div>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "example/App.scss",
    "content": "@import url('https://fonts.googleapis.com/css?family=Nunito:400,700');\n\n/** Colors **/\n$brahmos-color-1: #efdc4f;\n$brahmos-color-2: #323330;\n\n$primary: $brahmos-color-2;\n// $primary-invert: #efdc4f;\n$primary-light: white;\n$text: $brahmos-color-2;\n$link: #2060c3;\n$menu-item-active-background-color: $brahmos-color-1;\n$menu-item-active-color: $brahmos-color-2;\n$family-sans-serif: 'Nunito', sans-serif;\n// $background: #02030e;\n\n@import '../node_modules/bulma/bulma.sass';\n\n.app-container {\n  min-height: 100vh;\n\n  display: flex;\n  flex-direction: column;\n\n  .hero-body {\n    display: flex;\n    align-items: center;\n    padding: 1.5rem;\n  }\n\n  .star-btn {\n    vertical-align: middle;\n    margin-left: 2rem;\n  }\n\n  .brahmos-logo,\n  .github-logo {\n    transition: all ease 400ms;\n  }\n\n  .brahmos-logo {\n    width: 100px;\n    height: 100px;\n    top: 0;\n    left: 0;\n    position: absolute;\n  }\n\n  .github-logo {\n    width: 60px;\n    height: 60px;\n    left: 50%;\n    top: 150%;\n    transform: translate(-50%, -50%);\n    position: absolute;\n  }\n\n  .logo {\n    margin-right: 1rem;\n    min-width: 100px;\n    height: 100px;\n    border-radius: 50%;\n    background: $brahmos-color-1;\n    overflow: hidden;\n    position: relative;\n    cursor: pointer;\n\n    &:hover {\n      .brahmos-logo {\n        top: -100%;\n      }\n      .github-logo {\n        top: 50%;\n      }\n    }\n  }\n\n  .body {\n    display: flex;\n    flex: 1;\n  }\n\n  .menu-list a:not(.is-active) {\n    border-bottom: 1px solid $border;\n  }\n\n  .small-width {\n    width: 300px;\n  }\n\n  .control-wrap {\n    display: flex;\n    align-items: center;\n  }\n\n  .example-container {\n    padding-bottom: 100px;\n    position: relative;\n  }\n\n  .react-credit {\n    background: white;\n    position: fixed;\n    padding: 1rem 0.75rem;\n    border-top: 1px solid $border;\n    bottom: 0;\n    left: 25%;\n    width: 75%;\n  }\n}\n"
  },
  {
    "path": "example/Logos.js",
    "content": "import Brahmos from 'brahmos';\n\nexport function GithubLogo(props) {\n  return (\n    <svg viewBox=\"0 0 478.613 478.613\" {...props}>\n      <path\n        fill=\"#323330\"\n        d=\"M427.501 200.695c1.776-11.238 2.884-23.56 3.163-37.377-.107-59.246-28.468-80.21-33.925-90.038 8.037-44.89-1.331-65.309-5.688-72.299-16.07-5.704-55.91 14.722-77.678 29.101-35.491-10.389-110.494-9.375-138.621 2.689C122.856-4.389 95.408 1.277 95.408 1.277s-17.745 31.82-4.691 78.371c-17.075 21.759-29.802 37.143-29.802 77.949 0 9.773.607 19.008 1.637 27.893 14.705 77.318 75.97 110.674 136.15 116.426-9.056 6.881-19.928 19.903-21.432 34.992-11.379 7.357-34.268 9.789-52.067 4.193-24.939-7.88-34.486-57.266-71.833-50.221-8.081 1.512-6.475 6.842.523 11.386 11.378 7.38 22.094 16.554 30.354 36.185 6.344 15.072 19.687 41.982 61.873 41.982 16.747 0 28.477-1.979 28.477-1.979s.319 38.406.319 53.385c0 17.238-23.264 22.078-23.264 30.348 0 3.289 7.7 3.601 13.888 3.601 12.229 0 37.673-10.186 37.673-28.103 0-14.237.227-62.081.227-70.46 0-18.307 9.811-24.136 9.811-24.136s1.201 97.727-2.361 110.829c-4.177 15.408-11.744 13.219-11.744 20.076 0 10.233 30.589 2.502 40.735-19.897 7.849-17.495 4.334-113.331 4.334-113.331l8.183-.178s.094 43.892-.188 63.944c-.295 20.769-2.438 47.025 9.898 59.417 8.097 8.15 32.903 22.451 32.903 9.382 0-7.574-17.371-13.833-17.371-34.353V344.45c10.553 0 12.734 31.072 12.734 31.072l3.804 57.727s-2.526 21.065 22.756 29.856c8.925 3.126 28.018 3.976 28.913-1.271.897-5.26-22.99-13.038-23.217-29.342-.123-9.93.445-15.742.445-58.934 0-43.168-5.799-59.137-26.007-71.863 58.601-6.014 119.468-32.185 130.433-101z\"\n      />\n    </svg>\n  );\n}\n\nexport function BrahmosLogo(props) {\n  return (\n    <svg viewBox=\"0 0 640 640\" {...props}>\n      <defs>\n        <path\n          d=\"M622.35 318.15c0 165.58-134.42 300-300 300-165.57 0-300-134.42-300-300 0-165.57 134.43-300 300-300 165.58 0 300 134.43 300 300z\"\n          id=\"prefix__a\"\n        />\n        <path d=\"M286.24 574.54v-79.68\" id=\"prefix__b\" />\n        <path\n          d=\"M384.88 166.01L322.4 61.77l-62.57 104.24V339.4l-62.48 77.11v125.26l62.48-62.63h125.05l62.47 62.63V416.51l-62.47-77.11V166.01z\"\n          id=\"prefix__c\"\n        />\n        <path d=\"M358.46 574.54v-79.68\" id=\"prefix__d\" />\n        <path d=\"M322.35 562.82v-70.34\" id=\"prefix__e\" />\n      </defs>\n      <use xlinkHref=\"#prefix__a\" fill=\"#f0da51\" />\n      <use xlinkHref=\"#prefix__b\" fill=\"#323330\" />\n      <use xlinkHref=\"#prefix__b\" fillOpacity={0} stroke=\"#323330\" strokeWidth={6} />\n      <use xlinkHref=\"#prefix__c\" fill=\"#323330\" />\n      <use xlinkHref=\"#prefix__c\" fillOpacity={0} stroke=\"#323330\" />\n      <use xlinkHref=\"#prefix__d\" fill=\"#323330\" />\n      <use xlinkHref=\"#prefix__d\" fillOpacity={0} stroke=\"#323330\" strokeWidth={6} />\n      <g>\n        <use xlinkHref=\"#prefix__e\" fill=\"#323330\" />\n        <use xlinkHref=\"#prefix__e\" fillOpacity={0} stroke=\"#323330\" strokeWidth={6} />\n      </g>\n    </svg>\n  );\n}\n"
  },
  {
    "path": "example/common/ReactCredit.js",
    "content": "export default function ReactCredit({ name, link }) {\n  return (\n    <p className=\"react-credit\">\n      This demo is forked from {name} demo of React:\n      <br />\n      <strong>Source: </strong>\n      <a href={link} target=\"_blank\" rel=\"noopener\">\n        {link}\n      </a>\n    </p>\n  );\n}\n"
  },
  {
    "path": "example/concurrent-mode/fakeApi.js",
    "content": "export function fetchProfileData(userId) {\n  const userPromise = fetchUser(userId);\n  const postsPromise = fetchPosts(userId);\n  return {\n    userId,\n    user: wrapPromise(userPromise),\n    posts: wrapPromise(postsPromise),\n  };\n}\n\n// Suspense integrations like Relay implement\n// a contract like this to integrate with React.\n// Real implementations can be significantly more complex.\n// Don't copy-paste this into your project!\nfunction wrapPromise(promise) {\n  let status = 'pending';\n  let result;\n  const suspender = promise.then(\n    (r) => {\n      status = 'success';\n      result = r;\n    },\n    (e) => {\n      status = 'error';\n      result = e;\n    },\n  );\n  return {\n    read() {\n      if (status === 'pending') {\n        throw suspender;\n      } else if (status === 'error') {\n        throw result;\n      } else if (status === 'success') {\n        return result;\n      }\n    },\n  };\n}\n\nexport function fetchUser(userId) {\n  console.log('fetch user ' + userId + '...');\n  return new Promise((resolve) => {\n    setTimeout(() => {\n      console.log('fetched user ' + userId);\n      switch (userId) {\n        case 0:\n          resolve({\n            name: 'Ringo Starr',\n          });\n          break;\n        case 1:\n          resolve({\n            name: 'George Harrison',\n          });\n          break;\n        case 2:\n          resolve({\n            name: 'John Lennon',\n          });\n          break;\n        case 3:\n          resolve({\n            name: 'Paul McCartney',\n          });\n          break;\n        default:\n          throw Error('Unknown user.');\n      }\n    }, 1000 * Math.random());\n  });\n}\n\nexport function fetchPosts(userId) {\n  console.log('fetch posts for ' + userId + '...');\n  return new Promise((resolve) => {\n    setTimeout(() => {\n      console.log('fetched posts for ' + userId);\n      switch (userId) {\n        case 0:\n          resolve([\n            {\n              id: 0,\n              text: 'I get by with a little help from my friends',\n            },\n            {\n              id: 1,\n              text: \"I'd like to be under the sea in an octupus's garden\",\n            },\n            {\n              id: 2,\n              text: 'You got that sand all over your feet',\n            },\n          ]);\n          break;\n        case 1:\n          resolve([\n            {\n              id: 0,\n              text: 'Turn off your mind, relax, and float downstream',\n            },\n            {\n              id: 1,\n              text: 'All things must pass',\n            },\n            {\n              id: 2,\n              text: \"I look at the world and I notice it's turning\",\n            },\n          ]);\n          break;\n        case 2:\n          resolve([\n            {\n              id: 0,\n              text: 'Living is easy with eyes closed',\n            },\n            {\n              id: 1,\n              text: \"Nothing's gonna change my world\",\n            },\n            {\n              id: 2,\n              text: 'I am the walrus',\n            },\n          ]);\n          break;\n        case 3:\n          resolve([\n            {\n              id: 0,\n              text: 'Woke up, fell out of bed',\n            },\n            {\n              id: 1,\n              text: 'Here, there, and everywhere',\n            },\n            {\n              id: 2,\n              text: 'Two of us sending postcards, writing letters',\n            },\n          ]);\n          break;\n        default:\n          throw Error('Unknown user.');\n      }\n    }, 2000 * Math.random());\n  });\n}\n"
  },
  {
    "path": "example/concurrent-mode/index.js",
    "content": "/**\n * Forked from: https://codesandbox.io/s/jovial-lalande-26yep?file=/src/index.js:0-1646\n */\nimport Brahmos, { useState, useTransition, Suspense } from 'brahmos';\nimport ReactCredit from '../common/ReactCredit';\n\nimport { fetchProfileData } from './fakeApi';\n\nfunction getNextId(id) {\n  return id === 3 ? 0 : id + 1;\n}\n\nconst initialResource = fetchProfileData(0);\n\nfunction ProfileDetails({ resource }) {\n  const user = resource.user.read();\n  return <h1>{user.name}</h1>;\n}\n\nfunction ProfileTimeline({ resource }) {\n  const posts = resource.posts.read();\n  return (\n    <ul>\n      {posts.map((post) => (\n        <li key={post.id}>{post.text}</li>\n      ))}\n    </ul>\n  );\n}\n\nfunction ProfilePageWithoutTransition() {\n  const [resource, setResource] = useState(initialResource);\n\n  return (\n    <div>\n      <hr />\n      <h3>Example of suspense for data fetching.</h3>\n      <p>\n        As soon as we click the button the view will go on receded state (shows loader), and as soon\n        as partial data (skeleton or required data) is available it will starts showing partial\n        data, and then show the complete data lazily.\n        <br />\n        <strong>Click Next to see the behaviour</strong>\n      </p>\n      <div style={{ minHeight: 210 }}>\n        <div className=\"control-wrap\">\n          <button\n            className=\"button is-primary\"\n            onClick={() => {\n              const nextUserId = getNextId(resource.userId);\n              setResource(fetchProfileData(nextUserId));\n            }}\n          >\n            Next\n          </button>\n        </div>\n        <Suspense fallback={<h1>Loading profile...</h1>}>\n          <ProfileDetails resource={resource} />\n          <Suspense fallback={<h1>Loading posts...</h1>}>\n            <ProfileTimeline resource={resource} />\n          </Suspense>\n        </Suspense>\n      </div>\n    </div>\n  );\n}\n\nfunction ProfilePageWithTransition() {\n  const [resource, setResource] = useState(initialResource);\n  const [startTransition, isPending] = useTransition({\n    timeoutMs: 3000,\n  });\n\n  return (\n    <div>\n      <hr />\n      <h3>Example of transition.</h3>\n      <p>\n        Preferably, we should remain on the same screen with pending state until we have partial\n        data (skeleton or required data).\n        <br />\n        <strong>Click Next to see the behaviour</strong>\n      </p>\n      <div style={{ minHeight: 210 }}>\n        <div className=\"control-wrap\">\n          <button\n            className=\"button is-primary\"\n            disabled={isPending}\n            onClick={() => {\n              startTransition(() => {\n                const nextUserId = getNextId(resource.userId);\n                setResource(fetchProfileData(nextUserId));\n              });\n            }}\n          >\n            Next\n          </button>\n          {isPending ? ' Loading...' : null}\n        </div>\n        <Suspense fallback={<h1>Loading profile...</h1>}>\n          <ProfileDetails resource={resource} />\n          <Suspense fallback={<h1>Loading posts...</h1>}>\n            <ProfileTimeline resource={resource} />\n          </Suspense>\n        </Suspense>\n      </div>\n    </div>\n  );\n}\n\nfunction ProfilePageWithTransitionPreferred() {\n  const [resource, setResource] = useState(initialResource);\n  const [startTransition, isPending] = useTransition({\n    timeoutMs: 3000,\n  });\n\n  return (\n    <div>\n      <hr />\n      <h3>Another example of transition.</h3>\n      <p>\n        We can also wait in pending state until complete data is available for next page.\n        <br />\n        <strong>Click Next to see the behaviour</strong>\n      </p>\n      <div style={{ minHeight: 210 }}>\n        <div className=\"control-wrap\">\n          <button\n            className=\"button is-primary\"\n            disabled={isPending}\n            onClick={() => {\n              startTransition(() => {\n                const nextUserId = getNextId(resource.userId);\n                setResource(fetchProfileData(nextUserId));\n              });\n            }}\n          >\n            Next\n          </button>\n          {isPending ? ' Loading...' : null}\n        </div>\n        <Suspense fallback={<h1>Loading profile...</h1>}>\n          <ProfileDetails resource={resource} />\n        </Suspense>\n        <Suspense fallback={<h1>Loading posts...</h1>}>\n          <ProfileTimeline resource={resource} />\n        </Suspense>\n      </div>\n    </div>\n  );\n}\n\nexport default function App() {\n  return (\n    <>\n      <p>\n        This demo demonstrates concurrent mode patterns in Brahmos.\n        <br />\n        It demonstrates Suspense for data fetch (Render as you fetch), Transitions and preferred\n        rendering approach (Pending -> Skeleton -> Complete). Read more about it in official React\n        Docs.\n        <a\n          href=\"https://reactjs.org/docs/concurrent-mode-patterns.html\"\n          target=\"_blank\"\n          rel=\"noopener\"\n        >\n          https://reactjs.org/docs/concurrent-mode-patterns.html\n        </a>\n        <br />\n        <br />\n        On this demo APIs are mocked. Profile detail API responds between 0 - 1000ms and Post API\n        responds between 0 - 2000ms\n      </p>\n      <ProfilePageWithoutTransition />\n      <ProfilePageWithTransition />\n      <ProfilePageWithTransitionPreferred />\n      <ReactCredit name=\"Concurrent Mode\" link=\"https://codesandbox.io/s/jovial-lalande-26yep\" />\n    </>\n  );\n}\n"
  },
  {
    "path": "example/context-api/index.js",
    "content": "import Brahmos, { Component, createContext, useContext, useState } from 'brahmos';\n\nconst BrahmosContext = createContext('Brahmos');\n\n// context as static property\nclass ContextStaticProperty extends Component {\n  render() {\n    const name = this.context;\n    return <div>Hello {name}</div>;\n  }\n}\nContextStaticProperty.contextType = BrahmosContext;\n\nfunction ContextConsumer() {\n  return <BrahmosContext.Consumer>{(name) => <div>Hello {name}</div>}</BrahmosContext.Consumer>;\n}\n\nfunction UseContext() {\n  const name = useContext(BrahmosContext);\n\n  return <div>Hello {name}</div>;\n}\n\nexport default function ContextExample() {\n  const [name, setName] = useState();\n\n  return (\n    <div>\n      <p> This demo demonstrates usage of Context API in different way</p>\n      <input className=\"input small-width\" value={name} onChange={(e) => setName(e.target.value)} />\n      <BrahmosContext.Provider value={name}>\n        <h3>ContextConsumer</h3>\n        <ContextConsumer />\n\n        <h3>Context Static Property</h3>\n        <ContextStaticProperty />\n\n        <h3>useContext Hook</h3>\n        <UseContext />\n      </BrahmosContext.Provider>\n      <>\n        <h3>ContextConsumer without Provider</h3>\n        <ContextConsumer />\n        <h3>useContext without Provider</h3>\n        <UseContext />\n      </>\n    </div>\n  );\n}\n"
  },
  {
    "path": "example/error-boundaries/index.js",
    "content": "import Brahmos, { Component } from 'brahmos';\nimport ReactCredit from '../common/ReactCredit';\n\n// Forked from: https://codepen.io/gaearon/pen/wqvxGa\n\nclass ErrorBoundary extends Component {\n  constructor(props) {\n    super(props);\n    this.state = { error: null, errorInfo: null };\n  }\n\n  static getDerivedStateFromError(error) {\n    return { error };\n  }\n\n  // eslint-disable-next-line handle-callback-err\n  componentDidCatch(error, errorInfo) {\n    // Catch errors in any components below and re-render with error message\n    this.setState({\n      errorInfo: errorInfo,\n    });\n    // You can also log error messages to an error reporting service here\n  }\n\n  render() {\n    if (this.state.error) {\n      // Error path\n      return (\n        <div>\n          <h2>Something went wrong.</h2>\n          <details style={{ whiteSpace: 'pre-wrap' }}>\n            {this.state.error && this.state.error.toString()}\n            <br />\n            {this.state.errorInfo && this.state.errorInfo.componentStack}\n          </details>\n        </div>\n      );\n    }\n    // Normally, just render children\n    return this.props.children;\n  }\n}\n\nclass BuggyCounter extends Brahmos.Component {\n  constructor(props) {\n    super(props);\n    this.state = { counter: 0 };\n    this.handleClick = this.handleClick.bind(this);\n  }\n\n  handleClick() {\n    this.setState(({ counter }) => ({\n      counter: counter + 1,\n    }));\n  }\n\n  render() {\n    if (this.state.counter === 5) {\n      // Simulate a JS error\n      throw new Error('I crashed!');\n    }\n    return (\n      <div>\n        <button className=\"button\" onClick={this.handleClick}>\n          {this.state.counter}\n        </button>\n        <br />\n        <br />\n      </div>\n    );\n  }\n}\n\nexport default function ErrorBoundaryExample() {\n  return (\n    <div>\n      <p>\n        <b>\n          Click on the numbers to increase the counters.\n          <br />\n          The counter is programmed to throw when it reaches 5. This simulates a JavaScript error in\n          a component.\n        </b>\n      </p>\n      <hr />\n      <ErrorBoundary>\n        <p>\n          These two counters are inside the same error boundary. If one crashes, the error boundary\n          will replace both of them.\n        </p>\n        <BuggyCounter />\n        <BuggyCounter />\n      </ErrorBoundary>\n      <hr />\n      <p>\n        These two counters are each inside of their own error boundary. So if one crashes, the other\n        is not affected.\n      </p>\n      <ErrorBoundary>\n        <BuggyCounter />\n      </ErrorBoundary>\n      <ErrorBoundary>\n        <BuggyCounter />\n      </ErrorBoundary>\n\n      <ReactCredit name=\"Error boundaries\" link=\"https://codepen.io/gaearon/pen/wqvxGa\" />\n    </div>\n  );\n}\n"
  },
  {
    "path": "example/food-app/food-app.css",
    "content": ".food-app {\n  position: relative;\n  display: flex;\n  flex-direction: column;\n  gap: 40px;\n  text-align: center;\n  padding-top: 20px;\n  padding-bottom: 120px;\n  width: 600px;\n  min-height: 400px;\n  background-color: #fffaf0;\n}\n\n.food-app > header {\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  padding: 0 20px;\n}\n\n.food-app > footer {\n  position: absolute;\n  bottom: 0;\n  padding: 30px 20px;\n  width: 100%;\n}\n\n.veg-filter {\n  margin-right: 5px;\n}\n\n.menu-list {\n  display: flex;\n  flex-direction: column;\n  gap: 20px;\n}\n\n.menu-item {\n  display: flex;\n  gap: 10px;\n  justify-content: space-between;\n  align-items: center;\n  padding: 0 20px;\n  text-align: left;\n}\n\n.menu-item-title {\n  display: flex;\n  gap: 5px;\n}\n\n.menu-item-description {\n  color: #555;\n  font-size: 14px;\n  margin-top: 5px;\n}\n\n.menu-btn-add {\n  display: flex;\n  align-items: center;\n  gap: 5px;\n  white-space: nowrap;\n  background-color: transparent;\n  border: 1px solid #cbd5e0;\n  border-radius: 4px;\n  padding: 5px 15px;\n  font-size: 14px;\n}\n\n.menu-btn-group {\n  display: flex;\n  border: 1px solid #718096;\n  border-radius: 4px;\n}\n\n.menu-btn-item {\n  background-color: transparent;\n  border: none;\n  font-size: 14px;\n}\n\n.menu-item-qty {\n  font-size: 14px;\n  display: flex;\n  align-items: center;\n  padding: 5px 0;\n  user-select: none;\n}\n\n.food-app-pay-btn {\n  display: block;\n  text-decoration: none;\n  width: 100%;\n  font-size: 20px;\n  border: none;\n  background-color: #ecc94b;\n  color: #2d3748;\n  padding: 20px 0;\n  border-radius: 6px;\n  font-weight: medium;\n}\n\n.icon-plus,\n.icon-minus {\n  display: block;\n}\n"
  },
  {
    "path": "example/food-app/food-menu.json",
    "content": "[\n  {\n    \"id\": \"SN\",\n    \"label\": \"Schezwan Noodles\",\n    \"diet\": \"veg\",\n    \"description\": \"Spicy Noodles soaked in Schezwan sauce and topped with exotic herbs\",\n    \"price\": 8\n  },\n  {\n    \"id\": \"SM\",\n    \"label\": \"Sausage McMuffin\",\n    \"description\": \"Lightly seasoned sausage patty and cheese slice on a hot toasted English muffin.\",\n    \"price\": 12\n  },\n  {\n    \"id\": \"MP\",\n    \"label\": \"Mushroom Pizza\",\n    \"diet\": \"veg\",\n    \"description\": \"Loaded with 2 types of cheese and garlic herb sautéed mushrooms!! \",\n    \"price\": 20\n  },\n  {\n    \"id\": \"CF\",\n    \"label\": \"Chicken Foldover Spicy\",\n    \"description\": \"Two succulent chicken patties, add some crisp lettuce.\",\n    \"price\": 10\n  },\n  {\n    \"id\": \"FF\",\n    \"label\": \"French Fries\",\n    \"diet\": \"veg\",\n    \"description\": \"Crispy golden fries with a pinch of salt.\",\n    \"price\": 6\n  },\n  {\n    \"id\": \"BQ\",\n    \"label\": \"BBQ Double Burger\",\n    \"description\": \"Beef patties with a slice of cheese, shredded lettuce, tomato and onions\",\n    \"price\": 16\n  }\n]\n"
  },
  {
    "path": "example/food-app/mobx/App.js",
    "content": "import { Fragment, useEffect, useState } from 'brahmos';\nimport { observer } from 'mobx-react-lite';\n\nimport { useRootStore } from './mobx';\nimport { MenuList, Message, PaymentFooter } from './Comps';\nimport { loadFoodData } from '../utils';\n\nconst App = observer(function App() {\n  const rootStore = useRootStore();\n  const stateAPIStatus = useLoadFoodData();\n\n  function handleVegToggle() {\n    rootStore.changeDiet();\n  }\n\n  return (\n    <div className=\"food-app\">\n      <header>\n        <h1>Ordux</h1>\n        <label>\n          <input\n            type=\"checkbox\"\n            className=\"veg-filter\"\n            name=\"veg-checkbox\"\n            value={rootStore.diet}\n            checked={rootStore.diet === 'veg'}\n            onChange={handleVegToggle}\n          />\n          Veg Only\n        </label>\n      </header>\n      <Message status={stateAPIStatus} />\n      {stateAPIStatus === 'success' && (\n        <Fragment>\n          <main>\n            <MenuList />\n          </main>\n          <PaymentFooter />\n        </Fragment>\n      )}\n    </div>\n  );\n});\n\nfunction useLoadFoodData() {\n  const [stateAPIStatus, setAPIStatus] = useState('idle');\n  const rootStore = useRootStore();\n\n  useEffect(() => {\n    setAPIStatus('loading');\n    loadFoodData()\n      .then((data) => {\n        rootStore.loadMenu(data);\n        setAPIStatus('success');\n      })\n      .catch((error) => {\n        setAPIStatus('error');\n      });\n  }, [rootStore]);\n\n  return stateAPIStatus;\n}\n\nexport default App;\n"
  },
  {
    "path": "example/food-app/mobx/Comps.js",
    "content": "import { observer } from 'mobx-react-lite';\n\nimport { useRootStore } from './mobx';\n\nexport const MenuItem = observer(function MenuItem(props) {\n  const { item } = props;\n  const { quantity } = item;\n  const rootStore = useRootStore();\n\n  function handleIncrement() {\n    rootStore.addToCart(item);\n  }\n\n  function handleDecrement() {\n    rootStore.removeFromCart(item);\n  }\n\n  const addBtn = (\n    <button\n      aria-label={`Add ${item.label} to cart`}\n      className=\"menu-btn-add\"\n      onClick={handleIncrement}\n    >\n      Add <IconPlus />\n    </button>\n  );\n\n  const increaseBtn = (\n    <button\n      aria-label={`Add ${item.label} to cart`}\n      className=\"menu-btn-item\"\n      onClick={handleIncrement}\n    >\n      <IconPlus />\n    </button>\n  );\n\n  const decreaseBtn = (\n    <button\n      aria-label={`Remove ${item.label} from cart`}\n      className=\"menu-btn-item\"\n      onClick={handleDecrement}\n    >\n      <IconMinus />\n    </button>\n  );\n\n  const qtyIndicator = (\n    <div className=\"menu-item-qty\" role=\"status\" aria-live=\"polite\">\n      {quantity}\n    </div>\n  );\n\n  return (\n    <li className=\"menu-item\">\n      <div>\n        <div className=\"menu-item-title\">\n          <h4>{item.label}</h4>\n          <span>(${item.price})</span>\n        </div>\n        <p className=\"menu-item-description\">{item.description}</p>\n      </div>\n      {quantity === 0 ? (\n        addBtn\n      ) : (\n        <div className=\"menu-btn-group\">\n          {decreaseBtn}\n          {qtyIndicator}\n          {increaseBtn}\n        </div>\n      )}\n    </li>\n  );\n});\n\nexport const MenuList = observer(function MenuList() {\n  const rootStore = useRootStore();\n  const { menuList } = rootStore;\n\n  return (\n    <ul className=\"menu-list\">\n      {menuList.map((item) => (\n        <MenuItem key={item.id} item={item} />\n      ))}\n    </ul>\n  );\n});\n\nexport function Message(props) {\n  const { status } = props;\n\n  const messages = {\n    loading: 'Loading...',\n    error: (\n      <>\n        Menu failed to load.\n        <br />\n        Please try again...\n      </>\n    ),\n  };\n\n  const messageText = messages[status];\n\n  if (!messageText) {\n    return null;\n  }\n\n  return (\n    <div\n      className={`message-${status}`}\n      role={status === 'error' ? 'alert' : 'status'}\n      aria-live=\"polite\"\n      aria-busy={status === 'loading'}\n    >\n      {messageText}\n    </div>\n  );\n}\n\nexport const PaymentFooter = observer(function PaymentFooter() {\n  const rootStore = useRootStore();\n  const { cartPrice } = rootStore;\n\n  return (\n    <footer>\n      {cartPrice > 0 && (\n        <a\n          href=\"#payment\"\n          onClick={(e) => e.preventDefault()}\n          className=\"food-app-pay-btn\"\n          aria-live=\"polite\"\n        >\n          Pay for food (${cartPrice})\n        </a>\n      )}\n    </footer>\n  );\n});\n\n// source- https://feathericons.com/\nexport function IconPlus() {\n  return (\n    <svg\n      className=\"icon-plus\"\n      viewBox=\"0 0 24 24\"\n      width=\"1em\"\n      height=\"1em\"\n      stroke=\"currentColor\"\n      strokeWidth=\"2\"\n      fill=\"none\"\n      strokeLinecap=\"round\"\n      strokeLinejoin=\"round\"\n      aria-hidden=\"true\"\n      focusable=\"false\"\n    >\n      <line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\"></line>\n      <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"></line>\n    </svg>\n  );\n}\n\n// source- https://feathericons.com/\nexport function IconMinus() {\n  return (\n    <svg\n      className=\"icon-minus\"\n      viewBox=\"0 0 24 24\"\n      width=\"1em\"\n      height=\"1em\"\n      stroke=\"currentColor\"\n      strokeWidth=\"2\"\n      fill=\"none\"\n      strokeLinecap=\"round\"\n      strokeLinejoin=\"round\"\n      aria-hidden=\"true\"\n      focusable=\"false\"\n    >\n      <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"></line>\n    </svg>\n  );\n}\n"
  },
  {
    "path": "example/food-app/mobx/index.js",
    "content": "import { StrictMode } from 'brahmos';\n\nimport App from './App';\nimport { RootStore, RootStoreProvider } from './mobx';\n\nimport '../food-app.css';\n\nexport default function ReduxExample() {\n  return (\n    <StrictMode>\n      <p>\n        This demo demonstrates Brahmos compatibility with Mobx.\n        <br />\n        The example is forked from{' '}\n        <a\n          href=\"https://github.com/itaditya/redux-hooks-for-food-delivery/tree/aditya-redux-to-mobx\"\n          target=\"_blank\"\n        >\n          https://github.com/itaditya/redux-hooks-for-food-delivery/tree/aditya-redux-to-mobx\n        </a>\n      </p>\n      <RootStoreProvider value={new RootStore()}>\n        <App />\n      </RootStoreProvider>\n    </StrictMode>\n  );\n}\n"
  },
  {
    "path": "example/food-app/mobx/mobx.js",
    "content": "import { createContext, useContext, useEffect } from 'brahmos';\nimport { makeAutoObservable, toJS } from 'mobx';\n\nexport class RootStore {\n  diet = 'all';\n  menu = [];\n\n  constructor() {\n    makeAutoObservable(this);\n  }\n\n  changeDiet() {\n    const newDiet = this.diet === 'veg' ? 'all' : 'veg';\n    this.diet = newDiet;\n  }\n\n  loadMenu(menuList) {\n    const menu = menuList.map((item) => {\n      return {\n        ...item,\n        quantity: 0,\n      };\n    });\n    this.menu = menu;\n  }\n\n  addToCart(item) {\n    item.quantity += 1;\n  }\n\n  removeFromCart(item) {\n    if (item.quantity !== 0) {\n      item.quantity -= 1;\n    }\n  }\n\n  get menuList() {\n    if (this.diet === 'all') {\n      return this.menu;\n    }\n\n    return this.menu.filter((item) => item.diet === this.diet);\n  }\n\n  get cartPrice() {\n    let total = 0;\n    this.menuList.forEach((item) => {\n      total += item.price * item.quantity;\n    });\n    return total;\n  }\n}\n\nconst RootStoreContext = createContext();\n\nexport const RootStoreProvider = RootStoreContext.Provider;\nexport const RootStoreConsumer = RootStoreContext.Consumer;\n\nexport function useRootStore() {\n  const rootStore = useContext(RootStoreContext);\n\n  if (rootStore === undefined) {\n    throw new Error('useRootStore must be used within a RootStoreProvider');\n  }\n\n  useEffect(() => {\n    if (process.env.NODE_ENV === 'development' && !window.mobx) {\n      window.mobx = {\n        rootStore,\n        toJS,\n      };\n    }\n  }, [rootStore]);\n\n  return rootStore;\n}\n"
  },
  {
    "path": "example/food-app/react-query/App.js",
    "content": "import { Fragment } from 'brahmos';\n\nimport { useDietStore } from './zustand';\nimport { MenuList, Message, PaymentFooter } from './Comps';\nimport { useLoadFoodQuery, useMenuList } from './hooks';\n\nexport default function App() {\n  const { diet, changeDiet } = useDietStore();\n  const menuQuery = useLoadFoodQuery();\n  const menuList = useMenuList();\n\n  const stateAPIStatus = menuQuery.status;\n\n  function handleVegToggle() {\n    changeDiet();\n  }\n\n  return (\n    <div className=\"food-app\">\n      <header>\n        <h1>Ordux</h1>\n        <label>\n          <input\n            type=\"checkbox\"\n            className=\"veg-filter\"\n            name=\"veg-checkbox\"\n            value={diet}\n            checked={diet === 'veg'}\n            onChange={handleVegToggle}\n          />\n          Veg Only\n        </label>\n      </header>\n      <Message status={stateAPIStatus} />\n      {stateAPIStatus === 'success' && (\n        <Fragment>\n          <main>\n            <MenuList menuList={menuList} />\n          </main>\n          <PaymentFooter />\n        </Fragment>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "example/food-app/react-query/Comps.js",
    "content": "import Brahmos from 'brahmos';\n\nimport { useCartStore } from './zustand';\nimport { useCartPrice } from './hooks';\n\nexport function MenuItem(props) {\n  const { item } = props;\n  const { cartByIds, addToCart, removeFromCart } = useCartStore();\n\n  const quantity = cartByIds[item.id]?.quantity ?? 0;\n\n  function handleIncrement() {\n    addToCart(item.id);\n  }\n\n  function handleDecrement() {\n    removeFromCart(item.id);\n  }\n\n  const addBtn = (\n    <button\n      aria-label={`Add ${item.label} to cart`}\n      className=\"menu-btn-add\"\n      onClick={handleIncrement}\n    >\n      Add <IconPlus />\n    </button>\n  );\n\n  const increaseBtn = (\n    <button\n      aria-label={`Add ${item.label} to cart`}\n      className=\"menu-btn-item\"\n      onClick={handleIncrement}\n    >\n      <IconPlus />\n    </button>\n  );\n\n  const decreaseBtn = (\n    <button\n      aria-label={`Remove ${item.label} from cart`}\n      className=\"menu-btn-item\"\n      onClick={handleDecrement}\n    >\n      <IconMinus />\n    </button>\n  );\n\n  const qtyIndicator = (\n    <div className=\"menu-item-qty\" role=\"status\" aria-live=\"polite\">\n      {quantity}\n    </div>\n  );\n\n  return (\n    <li className=\"menu-item\">\n      <div>\n        <div className=\"menu-item-title\">\n          <h4>{item.label}</h4>\n          <span>(${item.price})</span>\n        </div>\n        <p className=\"menu-item-description\">{item.description}</p>\n      </div>\n      {quantity === 0 ? (\n        addBtn\n      ) : (\n        <div className=\"menu-btn-group\">\n          {decreaseBtn}\n          {qtyIndicator}\n          {increaseBtn}\n        </div>\n      )}\n    </li>\n  );\n}\n\nfunction PureMenuList(props) {\n  console.log('MenuList Re-Render');\n  const { menuList } = props;\n  return (\n    <ul className=\"menu-list\">\n      {menuList.map((item) => (\n        <MenuItem key={item.id} item={item} />\n      ))}\n    </ul>\n  );\n}\n\nexport const MenuList = Brahmos.memo(PureMenuList);\n\nexport function Message(props) {\n  const { status } = props;\n\n  const messages = {\n    loading: 'Loading...',\n    error: (\n      <>\n        Menu failed to load.\n        <br />\n        Please try again...\n      </>\n    ),\n  };\n\n  const messageText = messages[status];\n\n  if (!messageText) {\n    return null;\n  }\n\n  return (\n    <div\n      className={`message-${status}`}\n      role={status === 'error' ? 'alert' : 'status'}\n      aria-live=\"polite\"\n      aria-busy={status === 'loading'}\n    >\n      {messageText}\n    </div>\n  );\n}\n\nexport function PaymentFooter() {\n  const cartPrice = useCartPrice();\n\n  return (\n    <footer>\n      {cartPrice > 0 && (\n        <a\n          href=\"#payment\"\n          onClick={(e) => e.preventDefault()}\n          className=\"food-app-pay-btn\"\n          aria-live=\"polite\"\n        >\n          Pay for food (${cartPrice})\n        </a>\n      )}\n    </footer>\n  );\n}\n\n// source- https://feathericons.com/\nexport function IconPlus() {\n  return (\n    <svg\n      className=\"icon-plus\"\n      viewBox=\"0 0 24 24\"\n      width=\"1em\"\n      height=\"1em\"\n      stroke=\"currentColor\"\n      strokeWidth=\"2\"\n      fill=\"none\"\n      strokeLinecap=\"round\"\n      strokeLinejoin=\"round\"\n      aria-hidden=\"true\"\n      focusable=\"false\"\n    >\n      <line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\"></line>\n      <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"></line>\n    </svg>\n  );\n}\n\n// source- https://feathericons.com/\nexport function IconMinus() {\n  return (\n    <svg\n      className=\"icon-minus\"\n      viewBox=\"0 0 24 24\"\n      width=\"1em\"\n      height=\"1em\"\n      stroke=\"currentColor\"\n      strokeWidth=\"2\"\n      fill=\"none\"\n      strokeLinecap=\"round\"\n      strokeLinejoin=\"round\"\n      aria-hidden=\"true\"\n      focusable=\"false\"\n    >\n      <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"></line>\n    </svg>\n  );\n}\n"
  },
  {
    "path": "example/food-app/react-query/hooks.js",
    "content": "import { useMemo } from 'brahmos';\nimport { useQuery } from 'react-query';\n\nimport { useDietStore, useCartStore } from './zustand';\nimport { loadFoodData } from '../utils';\n\nexport function useLoadFoodQuery() {\n  const menuQuery = useQuery('menu', loadFoodData);\n  return menuQuery;\n}\n\nexport function useMenuList() {\n  const diet = useDietStore((state) => state.diet);\n  const menuQuery = useLoadFoodQuery();\n  const data = menuQuery.data || [];\n\n  const menuList = useMemo(() => {\n    const computeMenuList = data.filter((item) => {\n      if (diet === 'all') {\n        return item;\n      }\n\n      return item.diet === diet;\n    });\n\n    return computeMenuList;\n  }, [diet, data]);\n\n  return menuList;\n}\n\nexport function useCartPrice() {\n  const cartByIds = useCartStore((state) => state.cartByIds);\n  const menuList = useMenuList();\n\n  const cartPrice = useMemo(() => {\n    let cartPrice = 0;\n    menuList.forEach((item) => {\n      const cartItem = cartByIds[item.id] || { quantity: 0 };\n      cartPrice += item.price * cartItem.quantity;\n    });\n\n    return cartPrice;\n  }, [cartByIds, menuList]);\n\n  return cartPrice;\n}\n"
  },
  {
    "path": "example/food-app/react-query/index.js",
    "content": "import { StrictMode } from 'brahmos';\nimport { QueryCache, ReactQueryCacheProvider } from 'react-query';\n\nimport App from './App';\n\nimport '../food-app.css';\n\nconst queryCache = new QueryCache({\n  defaultConfig: {\n    queries: {\n      staleTime: 300000, // 5 minutes\n    },\n  },\n});\n\nexport default function ReduxExample() {\n  return (\n    <StrictMode>\n      <p>\n        This demo demonstrates Brahmos compatibility with React Query and Zustand.\n        <br />\n        The example is forked from{' '}\n        <a\n          href=\"https://github.com/itaditya/redux-hooks-for-food-delivery/tree/aditya-redux-to-rq-zustand\"\n          target=\"_blank\"\n        >\n          https://github.com/itaditya/redux-hooks-for-food-delivery/tree/aditya-redux-to-rq-zustand\n        </a>\n      </p>\n      <ReactQueryCacheProvider queryCache={queryCache}>\n        <App />\n      </ReactQueryCacheProvider>\n    </StrictMode>\n  );\n}\n"
  },
  {
    "path": "example/food-app/react-query/zustand.js",
    "content": "import create from 'zustand';\n\nexport const useDietStore = create((set) => ({\n  diet: 'all',\n  changeDiet: () => set((state) => ({ diet: state.diet === 'veg' ? 'all' : 'veg' })),\n}));\n\nexport const useCartStore = create((set, get) => ({\n  cartByIds: {},\n  addToCart(itemId) {\n    const { cartByIds } = get();\n\n    const cartItem = cartByIds[itemId] || {\n      quantity: 0,\n    };\n\n    cartItem.quantity += 1;\n\n    const newCart = {\n      ...cartByIds,\n      [itemId]: cartItem,\n    };\n\n    set({\n      cartByIds: newCart,\n    });\n  },\n  removeFromCart(itemId) {\n    const { cartByIds } = get();\n\n    const cartItem = cartByIds[itemId];\n\n    if (!cartItem) {\n      return;\n    }\n\n    cartItem.quantity -= 1;\n\n    const newCart = {\n      ...cartByIds,\n      [itemId]: cartItem,\n    };\n\n    set({\n      cartByIds: newCart,\n    });\n  },\n}));\n"
  },
  {
    "path": "example/food-app/redux/App.js",
    "content": "import { Fragment, useEffect, useState } from 'brahmos';\nimport { shallowEqual, useSelector, useDispatch } from 'react-redux';\n\nimport { ACTIONS } from './redux';\nimport { MenuList, Message, PaymentFooter } from './Comps';\nimport { loadFoodData } from '../utils';\n\nexport default function App() {\n  const diet = useSelector((state) => state.diet);\n  const dispatch = useDispatch();\n\n  const stateAPIStatus = useLoadFoodData();\n  const menuList = useSelector(selectorMenu, shallowEqual);\n\n  useEffect(() => {\n    console.log('SERVER_EVENT: menu list changed');\n  }, [menuList]);\n\n  function handleVegToggle() {\n    dispatch({\n      type: ACTIONS.CHANGE_DIET,\n    });\n  }\n\n  return (\n    <div className=\"food-app\">\n      <header>\n        <h1>Ordux</h1>\n        <label>\n          <input\n            type=\"checkbox\"\n            className=\"veg-filter\"\n            name=\"veg-checkbox\"\n            value={diet}\n            checked={diet === 'veg'}\n            onChange={handleVegToggle}\n          />\n          Veg Only\n        </label>\n      </header>\n      <Message status={stateAPIStatus} />\n      {stateAPIStatus === 'success' && (\n        <Fragment>\n          <main>\n            <MenuList menuList={menuList} />\n          </main>\n          <PaymentFooter />\n        </Fragment>\n      )}\n    </div>\n  );\n}\n\nfunction useLoadFoodData() {\n  const [stateAPIStatus, setAPIStatus] = useState('idle');\n  const dispatch = useDispatch();\n\n  useEffect(() => {\n    setAPIStatus('loading');\n    loadFoodData()\n      .then((data) => {\n        dispatch({\n          type: ACTIONS.LOAD_MENU,\n          payload: {\n            menu: data,\n          },\n        });\n        setAPIStatus('success');\n      })\n      .catch((error) => {\n        setAPIStatus('error');\n      });\n  }, [dispatch]);\n\n  return stateAPIStatus;\n}\n\nfunction selectorMenu(state) {\n  const { diet, menuIdList, menuById } = state;\n  const menuId = menuIdList[diet];\n  const menuList = [];\n\n  menuId.forEach((id) => {\n    menuList.push(menuById[id]);\n  });\n\n  return menuList;\n}\n"
  },
  {
    "path": "example/food-app/redux/Comps.js",
    "content": "import Brahmos from 'brahmos';\n\nimport { useSelector, useDispatch } from 'react-redux';\n\nimport { ACTIONS } from './redux';\n\nexport function MenuItem(props) {\n  const { item } = props;\n\n  const cartByIds = useSelector((state) => state.cartByIds);\n  const dispatch = useDispatch();\n\n  const quantity = cartByIds[item.id]?.quantity ?? 0;\n\n  function handleIncrement() {\n    dispatch({\n      type: ACTIONS.ADD_TO_CART,\n      payload: {\n        itemId: item.id,\n      },\n    });\n  }\n\n  function handleDecrement() {\n    dispatch({\n      type: ACTIONS.REMOVE_FROM_CART,\n      payload: {\n        itemId: item.id,\n      },\n    });\n  }\n\n  const addBtn = (\n    <button\n      aria-label={`Add ${item.label} to cart`}\n      className=\"menu-btn-add\"\n      onClick={handleIncrement}\n    >\n      Add <IconPlus />\n    </button>\n  );\n\n  const increaseBtn = (\n    <button\n      aria-label={`Add ${item.label} to cart`}\n      className=\"menu-btn-item\"\n      onClick={handleIncrement}\n    >\n      <IconPlus />\n    </button>\n  );\n\n  const decreaseBtn = (\n    <button\n      aria-label={`Remove ${item.label} from cart`}\n      className=\"menu-btn-item\"\n      onClick={handleDecrement}\n    >\n      <IconMinus />\n    </button>\n  );\n\n  const qtyIndicator = (\n    <div className=\"menu-item-qty\" role=\"status\" aria-live=\"polite\">\n      {quantity}\n    </div>\n  );\n\n  return (\n    <li className=\"menu-item\">\n      <div>\n        <div className=\"menu-item-title\">\n          <h4>{item.label}</h4>\n          <span>(${item.price})</span>\n        </div>\n        <p className=\"menu-item-description\">{item.description}</p>\n      </div>\n      {quantity === 0 ? (\n        addBtn\n      ) : (\n        <div className=\"menu-btn-group\">\n          {decreaseBtn}\n          {qtyIndicator}\n          {increaseBtn}\n        </div>\n      )}\n    </li>\n  );\n}\n\nfunction PureMenuList(props) {\n  console.log('MenuList Re-Render');\n  const { menuList } = props;\n  return (\n    <ul className=\"menu-list\">\n      {menuList.map((item) => (\n        <MenuItem key={item.id} item={item} />\n      ))}\n    </ul>\n  );\n}\n\nexport const MenuList = Brahmos.memo(PureMenuList);\n\nexport function Message(props) {\n  const { status } = props;\n\n  const messages = {\n    loading: 'Loading...',\n    error: (\n      <>\n        Menu failed to load.\n        <br />\n        Please try again...\n      </>\n    ),\n  };\n\n  const messageText = messages[status];\n\n  if (!messageText) {\n    return null;\n  }\n\n  return (\n    <div\n      className={`message-${status}`}\n      role={status === 'error' ? 'alert' : 'status'}\n      aria-live=\"polite\"\n      aria-busy={status === 'loading'}\n    >\n      {messageText}\n    </div>\n  );\n}\n\nfunction selectorCartPrice(state) {\n  const { cartByIds, menuById } = state;\n  let cartPrice = 0;\n\n  const cartKeys = Object.keys(cartByIds);\n  cartKeys.forEach((id) => {\n    const item = menuById[id];\n    const cartItem = cartByIds[id];\n\n    const price = cartItem.quantity * item.price;\n    cartPrice += price;\n  });\n\n  return cartPrice;\n}\n\nexport function PaymentFooter() {\n  const cartPrice = useSelector(selectorCartPrice);\n\n  return (\n    <footer>\n      {cartPrice > 0 && (\n        <a\n          href=\"#payment\"\n          onClick={(e) => e.preventDefault()}\n          className=\"food-app-pay-btn\"\n          aria-live=\"polite\"\n        >\n          Pay for food (${cartPrice})\n        </a>\n      )}\n    </footer>\n  );\n}\n\n// source- https://feathericons.com/\nexport function IconPlus() {\n  return (\n    <svg\n      className=\"icon-plus\"\n      viewBox=\"0 0 24 24\"\n      width=\"1em\"\n      height=\"1em\"\n      stroke=\"currentColor\"\n      strokeWidth=\"2\"\n      fill=\"none\"\n      strokeLinecap=\"round\"\n      strokeLinejoin=\"round\"\n      aria-hidden=\"true\"\n      focusable=\"false\"\n    >\n      <line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\"></line>\n      <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"></line>\n    </svg>\n  );\n}\n\n// source- https://feathericons.com/\nexport function IconMinus() {\n  return (\n    <svg\n      className=\"icon-minus\"\n      viewBox=\"0 0 24 24\"\n      width=\"1em\"\n      height=\"1em\"\n      stroke=\"currentColor\"\n      strokeWidth=\"2\"\n      fill=\"none\"\n      strokeLinecap=\"round\"\n      strokeLinejoin=\"round\"\n      aria-hidden=\"true\"\n      focusable=\"false\"\n    >\n      <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"></line>\n    </svg>\n  );\n}\n"
  },
  {
    "path": "example/food-app/redux/index.js",
    "content": "import { StrictMode } from 'brahmos';\nimport { Provider } from 'react-redux';\n\nimport App from './App';\nimport { createReduxStore } from './redux';\n\nimport '../food-app.css';\n\nexport default function ReduxExample() {\n  return (\n    <StrictMode>\n      <p>\n        This demo demonstrates Brahmos compatibility with Redux.\n        <br />\n        The example is forked from{' '}\n        <a href=\"https://github.com/itaditya/redux-hooks-for-food-delivery/\" target=\"_blank\">\n          https://github.com/itaditya/redux-hooks-for-food-delivery/\n        </a>\n      </p>\n      <Provider store={createReduxStore()}>\n        <App />\n      </Provider>\n    </StrictMode>\n  );\n}\n"
  },
  {
    "path": "example/food-app/redux/redux.js",
    "content": "import { createStore } from 'redux';\n\nexport const ACTIONS = {\n  CHANGE_DIET: 'CHANGE_DIET',\n  LOAD_MENU: 'LOAD_MENU',\n  ADD_TO_CART: 'ADD_TO_CART',\n  REMOVE_FROM_CART: 'REMOVE_FROM_CART',\n};\n\nconst initialState = {\n  diet: 'all',\n  menuById: {},\n  menuIdList: {\n    all: [],\n    veg: [],\n  },\n  cartByIds: {},\n};\n\nfunction foodReducer(state = initialState, action) {\n  switch (action.type) {\n    case ACTIONS.CHANGE_DIET: {\n      const { diet } = state;\n      const newDiet = diet === 'veg' ? 'all' : 'veg';\n\n      return {\n        ...state,\n        diet: newDiet,\n        cartByIds: {},\n      };\n    }\n    case ACTIONS.LOAD_MENU: {\n      const { menu } = action.payload;\n\n      const menuById = {};\n      menu.forEach((item) => {\n        menuById[item.id] = item;\n      });\n      const allMenuId = menu.map((item) => item.id);\n      const vegMenuId = menu.filter((item) => item.diet === 'veg').map((item) => item.id);\n\n      return {\n        ...state,\n        menuById,\n        menuIdList: {\n          all: allMenuId,\n          veg: vegMenuId,\n        },\n      };\n    }\n    case ACTIONS.ADD_TO_CART: {\n      const { itemId } = action.payload;\n      const { cartByIds } = state;\n\n      const cartItem = cartByIds[itemId] || {\n        quantity: 0,\n      };\n\n      cartItem.quantity += 1;\n\n      const newCart = {\n        ...cartByIds,\n        [itemId]: cartItem,\n      };\n\n      return {\n        ...state,\n        cartByIds: newCart,\n      };\n    }\n    case ACTIONS.REMOVE_FROM_CART: {\n      const { itemId } = action.payload;\n      const { cartByIds } = state;\n\n      const cartItem = cartByIds[itemId];\n\n      if (!cartItem) {\n        return state;\n      }\n\n      cartItem.quantity -= 1;\n\n      const newCart = {\n        ...cartByIds,\n        [itemId]: cartItem,\n      };\n\n      return {\n        ...state,\n        cartByIds: newCart,\n      };\n    }\n    default:\n      return state;\n  }\n}\n\nconst enableReduxDevTools = window.__REDUX_DEVTOOLS_EXTENSION__?.();\n\nexport function createReduxStore() {\n  const store = createStore(foodReducer, enableReduxDevTools);\n  return store;\n}\n"
  },
  {
    "path": "example/food-app/utils.js",
    "content": "import foodMenu from './food-menu.json';\n\nexport async function loadFoodData() {\n  return foodMenu;\n}\n"
  },
  {
    "path": "example/hooks/index.js",
    "content": "import Brahmos, { useState, useEffect, useRef } from 'brahmos';\nimport ReactCredit from '../common/ReactCredit';\n\nfunction useInterval(callback, delay) {\n  const savedCallback = useRef();\n\n  // Remember the latest function.\n  useEffect(() => {\n    savedCallback.current = callback;\n  }, [callback]);\n\n  // Set up the interval.\n  useEffect(() => {\n    function tick() {\n      savedCallback.current();\n    }\n    if (delay !== null) {\n      const id = setInterval(tick, delay);\n      return () => clearInterval(id);\n    }\n  }, [delay]);\n}\n\nexport default function Counter() {\n  const [count, setCount] = useState(0);\n  const [delay, setDelay] = useState(1000);\n  const [isRunning, setIsRunning] = useState(true);\n\n  useInterval(\n    () => {\n      // Your custom logic here\n      setCount(count + 1);\n    },\n    isRunning ? delay : null,\n  );\n\n  function handleDelayChange(e) {\n    setDelay(Number(e.target.value));\n  }\n\n  function handleIsRunningChange(e) {\n    setIsRunning(e.target.checked);\n  }\n\n  return (\n    <>\n      <p>\n        This demo demonstrates usage of hooks in Brahmos. The example here uses useState, useRef and\n        useEffect hooks to make setInterval declarative.\n      </p>\n      <h1>{count}</h1>\n      <input type=\"checkbox\" checked={isRunning} onChange={handleIsRunningChange} /> Running\n      <br />\n      <input type=\"number\" value={delay} onChange={handleDelayChange} />\n      <ReactCredit\n        name=\"declarative setInterval with hooks\"\n        link=\"https://overreacted.io/making-setinterval-declarative-with-react-hooks/\"\n      />\n    </>\n  );\n}\n"
  },
  {
    "path": "example/index.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>Brahmos Demo</title>\n    <meta charset=\"UTF-8\" />\n  </head>\n\n  <body>\n    <div id=\"app\"></div>\n    <div id=\"portal-container\"></div>\n  </body>\n</html>\n"
  },
  {
    "path": "example/index.js",
    "content": "import { render } from 'brahmos';\nimport { HashRouter as Router } from 'react-router-dom';\n\nimport App from './App.js';\n\nfunction RootApp() {\n  return (\n    <Router>\n      <App />\n    </Router>\n  );\n}\n\nrender(<RootApp />, document.getElementById('app'));\n"
  },
  {
    "path": "example/lazy-component/index.js",
    "content": "import Brahmos, { Suspense, lazy } from 'brahmos';\n\nconst LazyTodoList = lazy(() => {\n  return new Promise((resolve) => {\n    setTimeout(() => {\n      resolve(import('../todo-list/index'));\n    }, 1500);\n  });\n});\n\nexport default function LazyExample() {\n  return (\n    <Suspense fallback={<h2>Loading TodoList !!!</h2>}>\n      <h2> This Todo list is loaded lazily. </h2>\n      <LazyTodoList showDescription={false} />\n    </Suspense>\n  );\n}\n"
  },
  {
    "path": "example/portals/index.js",
    "content": "import Brahmos, { createPortal, useState } from 'brahmos';\n\nfunction Modal({ onClose }) {\n  return (\n    <div className=\"modal is-active\">\n      <div className=\"modal-background\"></div>\n      <div className=\"modal-card content\">\n        <header className=\"modal-card-head\">\n          <p className=\"modal-card-title\">Modal title</p>\n          <button className=\"delete\" aria-label=\"close\" onClick={onClose}></button>\n        </header>\n        <section className=\"modal-card-body\">\n          <h1>Hello World</h1>\n          <p>\n            Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla accumsan, metus ultrices\n            eleifend gravida, nulla nunc varius lectus, nec rutrum justo nibh eu lectus. Ut\n            vulputate semper dui. Fusce erat odio, sollicitudin vel erat vel, interdum mattis neque.\n          </p>\n        </section>\n        <footer className=\"modal-card-foot\">\n          <button className=\"button is-primary\" onClick={onClose}>\n            Save changes\n          </button>\n          <button className=\"button\" onClick={onClose}>\n            Cancel\n          </button>\n        </footer>\n      </div>\n    </div>\n  );\n}\n\nexport default function CreatePortalExample() {\n  const [display, setDisplay] = useState(false);\n  return (\n    <div>\n      {display &&\n        createPortal(\n          <Modal onClose={() => setDisplay(false)} />,\n          document.querySelector('#portal-container'),\n        )}\n      <p>\n        <strong>Click button to open modal.</strong> The modal will open in another root element.\n      </p>\n      <button\n        className=\"button is-primary\"\n        onClick={() => {\n          setDisplay(true);\n        }}\n      >\n        Open Modal\n      </button>\n    </div>\n  );\n}\n"
  },
  {
    "path": "example/sierpinski-triangle/index.js",
    "content": "import { Component, unstable_deferredUpdates, unstable_syncUpdates } from 'brahmos';\n\n/**\n * Source: https://github.com/facebook/react/blob/master/fixtures/fiber-triangle/index.html\n */\nconst dotStyle = {\n  position: 'absolute',\n  background: '#61dafb',\n  font: 'normal 15px sans-serif',\n  textAlign: 'center',\n  cursor: 'pointer',\n};\n\nconst containerStyle = {\n  position: 'absolute',\n  transformOrigin: '0 0',\n  left: '50%',\n  top: '50%',\n  width: '10px',\n  height: '10px',\n  background: '#eee',\n};\n\nvar targetSize = 25;\n\nclass Dot extends Component {\n  constructor() {\n    super();\n    this.state = { hover: false };\n  }\n\n  enter() {\n    this.setState({\n      hover: true,\n    });\n  }\n\n  leave() {\n    this.setState({\n      hover: false,\n    });\n  }\n\n  render() {\n    var props = this.props;\n    var s = props.size * 1.3;\n    var style = {\n      ...dotStyle,\n      width: s + 'px',\n      height: s + 'px',\n      left: props.x + 'px',\n      top: props.y + 'px',\n      borderRadius: s / 2 + 'px',\n      lineHeight: s + 'px',\n      background: this.state.hover ? '#ff0' : dotStyle.background,\n    };\n    return (\n      <div style={style} onMouseEnter={() => this.enter()} onMouseLeave={() => this.leave()}>\n        {this.state.hover ? '*' + props.text + '*' : props.text}\n      </div>\n    );\n  }\n}\n\nclass SierpinskiTriangle extends Component {\n  shouldComponentUpdate(nextProps) {\n    var o = this.props;\n    var n = nextProps;\n    return !(o.x === n.x && o.y === n.y && o.s === n.s && o.children === n.children);\n  }\n\n  render() {\n    let { x, y, s, children } = this.props;\n\n    if (s <= targetSize) {\n      return (\n        <Dot x={x - targetSize / 2} y={y - targetSize / 2} size={targetSize} text={children} />\n      );\n      return r;\n    }\n    var newSize = s / 2;\n    var slowDown = true;\n    if (slowDown) {\n      var e = performance.now() + 0.8;\n      while (performance.now() < e) {\n        // Artificially long execution time.\n      }\n    }\n\n    s /= 2;\n\n    return [\n      <SierpinskiTriangle x={x} y={y - s / 2} s={s}>\n        {children}\n      </SierpinskiTriangle>,\n      <SierpinskiTriangle x={x - s} y={y + s / 2} s={s}>\n        {children}\n      </SierpinskiTriangle>,\n      <SierpinskiTriangle x={x + s} y={y + s / 2} s={s}>\n        {children}\n      </SierpinskiTriangle>,\n    ];\n  }\n}\n\nclass Toggle extends Component {\n  constructor(props) {\n    super();\n    this.onChange = this.onChange.bind(this);\n  }\n\n  onChange(event) {\n    this.props.onChange(event.target.value === 'on');\n  }\n\n  render() {\n    const value = this.props.value;\n    return (\n      <label className=\"control\" onChange={this.onChange}>\n        <label className=\"radio\">\n          <input type=\"radio\" name=\"value\" value=\"on\" checked={value} />\n          {this.props.onLabel}\n        </label>\n        <label className=\"radio\">\n          <input type=\"radio\" name=\"value\" value=\"off\" checked={!value} />\n          {this.props.offLabel}\n        </label>\n      </label>\n    );\n  }\n}\n\nclass SierpinskiWrapper extends Component {\n  constructor() {\n    super();\n    this.state = {\n      seconds: 0,\n      useTimeSlicing: true,\n    };\n    this.tick = this.tick.bind(this);\n    this.onTimeSlicingChange = this.onTimeSlicingChange.bind(this);\n  }\n\n  componentDidMount() {\n    this.intervalID = setInterval(this.tick, 1000);\n  }\n\n  tick() {\n    if (this.state.useTimeSlicing) {\n      // Update is time-sliced.\n      unstable_deferredUpdates(() => {\n        this.setState({ seconds: (this.state.seconds % 10) + 1 });\n      });\n    } else {\n      // Update is not time-sliced. Causes demo to stutter.\n      this.setState({ seconds: (this.state.seconds % 10) + 1 });\n    }\n  }\n\n  onTimeSlicingChange(value) {\n    this.setState(() => ({ useTimeSlicing: value }));\n  }\n\n  componentWillUnmount() {\n    clearInterval(this.intervalID);\n  }\n\n  render() {\n    const seconds = this.state.seconds;\n    const elapsed = this.props.elapsed;\n    const t = (elapsed / 1000) % 10;\n    const scale = 1 + (t > 5 ? 10 - t : t) / 10;\n    const transform = 'scaleX(' + scale / 2.1 + ') scaleY(0.7) translateZ(0.1px)';\n    return (\n      <div>\n        <div>\n          <h3>Time-slicing</h3>\n          <p>Toggle this and observe the effect</p>\n          <Toggle\n            onLabel=\"On\"\n            offLabel=\"Off\"\n            onChange={this.onTimeSlicingChange}\n            value={this.state.useTimeSlicing}\n          />\n        </div>\n        <div style={{ ...containerStyle, transform }}>\n          <div className=\"dot-container\">\n            <SierpinskiTriangle x={0} y={0} s={1000}>\n              {seconds}\n            </SierpinskiTriangle>\n          </div>\n        </div>\n      </div>\n    );\n  }\n}\n\nexport default class DemoApp extends Component {\n  constructor() {\n    super();\n    this.start = Date.now();\n    this.state = {\n      elapsed: this.start,\n    };\n  }\n\n  componentDidMount() {\n    this.updateElapsed();\n  }\n\n  componentWillUnmount() {\n    cancelAnimationFrame(this.animationFrameId);\n  }\n\n  updateElapsed() {\n    this.animationFrameId = requestAnimationFrame(() => {\n      unstable_syncUpdates(() => {\n        this.setState({\n          elapsed: Date.now() - this.start,\n        });\n      });\n\n      this.updateElapsed();\n    });\n  }\n\n  render() {\n    const { elapsed } = this.state;\n    return <SierpinskiWrapper elapsed={elapsed} />;\n  }\n}\n"
  },
  {
    "path": "example/suspense-list/fakeApi.js",
    "content": "export function fetchProfileData() {\n  const userPromise = fetchUser();\n  const postsPromise = fetchPosts();\n  const triviaPromise = fetchTrivia();\n  return {\n    user: wrapPromise(userPromise),\n    posts: wrapPromise(postsPromise),\n    trivia: wrapPromise(triviaPromise),\n  };\n}\n\n// Suspense integrations like Relay implement\n// a contract like this to integrate with React.\n// Real implementations can be significantly more complex.\n// Don't copy-paste this into your project!\nfunction wrapPromise(promise) {\n  let status = 'pending';\n  let result;\n  const suspender = promise.then(\n    (r) => {\n      status = 'success';\n      result = r;\n    },\n    (e) => {\n      status = 'error';\n      result = e;\n    },\n  );\n  return {\n    read() {\n      if (status === 'pending') {\n        throw suspender;\n      } else if (status === 'error') {\n        throw result;\n      } else if (status === 'success') {\n        return result;\n      }\n    },\n  };\n}\n\nfunction fetchUser() {\n  console.log('fetch user...');\n  return new Promise((resolve) => {\n    setTimeout(() => {\n      console.log('fetched user');\n      resolve({\n        name: 'Ringo Starr',\n      });\n    }, 500);\n  });\n}\n\nconst ringoPosts = [\n  {\n    id: 0,\n    text: 'I get by with a little help from my friends',\n  },\n  {\n    id: 1,\n    text: \"I'd like to be under the sea in an octupus's garden\",\n  },\n  {\n    id: 2,\n    text: 'You got that sand all over your feet',\n  },\n];\n\nfunction fetchPosts() {\n  const ringoPostsAtTheTime = ringoPosts;\n  console.log('fetch posts...');\n  return new Promise((resolve) => {\n    setTimeout(() => {\n      console.log('fetched posts');\n      resolve(ringoPostsAtTheTime);\n    }, 3000 * Math.random());\n  });\n}\n\nfunction fetchTrivia() {\n  return new Promise((resolve) => {\n    setTimeout(() => {\n      resolve([\n        {\n          id: 1,\n          text: 'The nickname \"Ringo\" came from his habit of wearing numerous rings.',\n        },\n        {\n          id: 2,\n          text: 'Plays the drums left-handed with a right-handed drum set.',\n        },\n        {\n          id: 3,\n          text: 'Nominated for one Daytime Emmy Award, but did not win',\n        },\n      ]);\n    }, 3000 * Math.random());\n  });\n}\n"
  },
  {
    "path": "example/suspense-list/index.js",
    "content": "/**\n * Forked from: https://codesandbox.io/s/black-wind-byilt\n */\n\nimport Brahmos, { SuspenseList, Suspense, useEffect, useState } from 'brahmos';\nimport ReactCredit from '../common/ReactCredit';\n\nimport { fetchProfileData } from './fakeApi';\n\nfunction ProfileDetails({ resource }) {\n  const user = resource.user.read();\n  return <h1>{user.name}</h1>;\n}\n\nfunction ProfileTimeline({ resource }) {\n  const posts = resource.posts.read();\n  return (\n    <ul>\n      {posts.map((post) => (\n        <li key={post.id}>{post.text}</li>\n      ))}\n    </ul>\n  );\n}\n\nfunction ProfileTrivia({ resource }) {\n  const trivia = resource.trivia.read();\n  return (\n    <>\n      <h2>Fun Facts</h2>\n      <ul>\n        {trivia.map((fact) => (\n          <li key={fact.id}>{fact.text}</li>\n        ))}\n      </ul>\n    </>\n  );\n}\n\nfunction ProfilePage({ revealOrder = 'forwards', tail }) {\n  const [resource, setResource] = useState();\n  return (\n    <div style={{ minHeight: resource ? 250 : 0 }}>\n      <Suspense fallback={<h1>Loading...</h1>}>\n        <button\n          className=\"button is-primary\"\n          onClick={() => {\n            setResource(fetchProfileData(0));\n          }}\n        >\n          Load/Reload\n        </button>\n        {resource && (\n          <>\n            <ProfileDetails resource={resource} />\n            <SuspenseList revealOrder={revealOrder} tail={tail}>\n              <Suspense fallback={<h2>Loading posts...</h2>}>\n                <ProfileTimeline resource={resource} />\n              </Suspense>\n              <Suspense fallback={<h2>Loading fun facts...</h2>}>\n                <ProfileTrivia resource={resource} />\n              </Suspense>\n            </SuspenseList>\n          </>\n        )}\n      </Suspense>\n    </div>\n  );\n}\n\nfunction App() {\n  return (\n    <>\n      <p>\n        This demo demonstrates Suspense List Implementation on Brahmos.\n        <br />\n        The APIs are mocked to respond in between 0-3000ms.\n      </p>\n      <div>\n        <hr />\n        <h3>Suspense list with forwards reveal order.</h3>\n        <p>\n          Though api response time can defer, in forwards reveal order, it guarantees the second\n          suspense will not reveal before the first suspense. In this example fun facts will never\n          be revealed before the post.\n          <br />\n          <strong>Click on button multiple times to see the effect.</strong>\n        </p>\n        <ProfilePage revealOrder=\"forwards\" />\n      </div>\n      <div>\n        <hr />\n        <h3>Suspense list with backwards reveal order.</h3>\n        <p>\n          In backwards reveal order, it guarantees the suspense are revealed from last to first. In\n          this example post will never be revealed before the fun fact.\n          <br />\n          <strong>Click on button multiple times to see the effect.</strong>\n        </p>\n        <ProfilePage revealOrder=\"backwards\" />\n      </div>\n      <div>\n        <hr />\n        <h3>Suspense list with together reveal order.</h3>\n        <p>In together reveal order, all the suspense are revealed together.</p>\n        <ProfilePage revealOrder=\"together\" />\n      </div>\n      <div>\n        <hr />\n        <h3>Suspense list with collapsed loading state.</h3>\n        <p>Only one loading will be shown inside the SuspenseList at a time.</p>\n        <ProfilePage tail=\"collapsed\" />\n      </div>\n      <div>\n        <hr />\n        <h3>Suspense list with no loading state.</h3>\n        <p>No loading will be shown inside the SuspenseList when tail prop is set to hidden.</p>\n        <ProfilePage tail=\"hidden\" />\n      </div>\n      <ReactCredit name=\"Suspense List\" link=\"https://codesandbox.io/s/black-wind-byilt\" />\n    </>\n  );\n}\n\nexport default App;\n"
  },
  {
    "path": "example/svg-chart/index.js",
    "content": "import Brahmos, { Component } from 'brahmos';\n\nfunction Rect({ height, index }) {\n  return (\n    <rect\n      width=\"40\"\n      y={120 - height}\n      x=\"50\"\n      height={height}\n      style=\"transition: all ease .3s;\"\n      transform={`translate(${43 * index},0)`}\n    />\n  );\n}\n\nfunction Chart({ data }) {\n  return (\n    <svg width=\"420\" height=\"120\">\n      {data.map((height, index) => (\n        <Rect key={index} height={height} index={index} />\n      ))}\n    </svg>\n  );\n}\n\nclass SVGExample extends Component {\n  state = {\n    data: [99, 44, 11, 55, 33, 115, 4],\n  };\n\n  _shuffuleArray(array) {\n    var j, temp, i;\n    for (i = array.length; i; i--) {\n      j = Math.floor(Math.random() * i);\n      temp = array[i - 1];\n      array[i - 1] = array[j];\n      array[j] = temp;\n    }\n    return array;\n  }\n\n  shuffule = () => this.setState({ data: this._shuffuleArray(this.state.data) });\n\n  render() {\n    const { data } = this.state;\n    return (\n      <div>\n        <p>This demo demonstrate usage of dynamic svg in Brahmos.</p>\n        <Chart data={data} />\n        <button className=\"button is-primary\" onClick={this.shuffule}>\n          Suffule\n        </button>\n      </div>\n    );\n  }\n}\n\nexport default SVGExample;\n"
  },
  {
    "path": "example/third-party-component/index.js",
    "content": "import { PureComponent } from 'brahmos';\nimport { BarChart, Bar, Cell, XAxis, YAxis, CartesianGrid, Tooltip, Legend } from 'recharts';\n\nconst data = [\n  {\n    name: 'Page A',\n    uv: 4000,\n    pv: 2400,\n    amt: 2400,\n  },\n  {\n    name: 'Page B',\n    uv: 3000,\n    pv: 1398,\n    amt: 2210,\n  },\n  {\n    name: 'Page C',\n    uv: 2000,\n    pv: 9800,\n    amt: 2290,\n  },\n  {\n    name: 'Page D',\n    uv: 2780,\n    pv: 3908,\n    amt: 2000,\n  },\n  {\n    name: 'Page E',\n    uv: 1890,\n    pv: 4800,\n    amt: 2181,\n  },\n  {\n    name: 'Page F',\n    uv: 2390,\n    pv: 3800,\n    amt: 2500,\n  },\n  {\n    name: 'Page G',\n    uv: 3490,\n    pv: 4300,\n    amt: 2100,\n  },\n];\n\nexport default class RechartExample extends PureComponent {\n  render() {\n    return (\n      <div>\n        <p>\n          This demo demonstrate usage of third party react component in Brahmos. In this example we\n          are using{' '}\n          <a href=\"https://recharts.org/en-US/\" target=\"_blank\">\n            recharts\n          </a>\n          for rendering chart which internally uses{' '}\n          <a href=\"https://github.com/recharts/react-smooth\" target=\"_blank\">\n            react-smooth\n          </a>\n          . Both of them are react based libraries.\n        </p>\n        <BarChart\n          width={500}\n          height={300}\n          data={data}\n          margin={{\n            top: 5,\n            right: 30,\n            left: 20,\n            bottom: 5,\n          }}\n        >\n          <CartesianGrid strokeDasharray=\"3 3\" />\n          <XAxis dataKey=\"name\" />\n          <YAxis />\n          <Tooltip />\n          <Legend />\n          <Bar dataKey=\"pv\" fill=\"#8884d8\" />\n          <Bar dataKey=\"uv\" fill=\"#82ca9d\" />\n        </BarChart>\n      </div>\n    );\n  }\n}\n"
  },
  {
    "path": "example/time-slicing/Chart.js",
    "content": "import Brahmos, { PureComponent } from 'brahmos';\nimport {\n  VictoryArea,\n  VictoryAxis,\n  VictoryChart,\n  VictoryBar,\n  VictoryTheme,\n  VictoryScatter,\n  VictoryStack,\n} from 'victory';\n\nconst colors = ['#fff489', '#fa57c1', '#b166cc', '#7572ff', '#69a6f9'];\n\nexport default class Charts extends PureComponent {\n  render() {\n    const streamData = this.props.data;\n    return (\n      <div>\n        <div style={{ display: 'flex' }}>\n          <VictoryChart\n            theme={VictoryTheme.material}\n            width={400}\n            height={400}\n            style={{\n              parent: {\n                backgroundColor: '#222',\n              },\n            }}\n          >\n            <VictoryAxis\n              style={{\n                axis: { stroke: 'white' },\n                tickLabels: { fill: 'white' },\n              }}\n            />\n            <VictoryAxis\n              style={{\n                axis: { stroke: 'white' },\n                tickLabels: { fill: 'white' },\n              }}\n              dependentAxis\n            />\n            <VictoryScatter\n              data={streamData[0]}\n              size={6}\n              style={{\n                data: {\n                  fill: (d) => colors[d.x % 5],\n                },\n              }}\n            />\n          </VictoryChart>\n\n          <VictoryChart\n            theme={VictoryTheme.material}\n            width={400}\n            height={400}\n            style={{\n              parent: {\n                backgroundColor: '#222',\n              },\n            }}\n            domainPadding={[20, 20]}\n          >\n            <VictoryAxis\n              style={{\n                axis: { stroke: 'white' },\n                tickLabels: { fill: 'white' },\n              }}\n            />\n            <VictoryAxis\n              style={{\n                axis: { stroke: 'white' },\n                tickLabels: { fill: 'white' },\n              }}\n              dependentAxis\n            />\n            <VictoryBar\n              data={streamData[0]}\n              style={{\n                data: {\n                  fill: (d) => colors[d.x % 5],\n                  stroke: 'none',\n                  padding: 5,\n                },\n              }}\n            />\n          </VictoryChart>\n        </div>\n        <div\n          style={{\n            display: 'flex',\n            position: 'relative',\n            top: '-50px',\n          }}\n        >\n          <VictoryChart\n            theme={VictoryTheme.material}\n            width={800}\n            height={350}\n            style={{\n              parent: {\n                backgroundColor: '#222',\n              },\n            }}\n          >\n            <VictoryAxis\n              style={{\n                axis: { stroke: 'white' },\n                tickLabels: { fill: 'white' },\n              }}\n            />\n            <VictoryAxis\n              style={{\n                axis: { stroke: 'white' },\n                tickLabels: { fill: 'white' },\n              }}\n              dependentAxis\n            />\n            <VictoryStack>\n              {streamData.map((data, i) => (\n                <VictoryArea key={i} data={data} colorScale={colors} />\n              ))}\n            </VictoryStack>\n          </VictoryChart>\n        </div>\n      </div>\n    );\n  }\n}\n"
  },
  {
    "path": "example/time-slicing/Clock.js",
    "content": "import Brahmos, { createRef, PureComponent } from 'brahmos';\n\nconst SPEED = 0.003 / Math.PI;\nconst FRAMES = 10;\n\nexport default class Clock extends PureComponent {\n  faceRef = createRef();\n\n  arcGroupRef = createRef();\n\n  clockHandRef = createRef();\n\n  frame = null;\n\n  hitCounter = 0;\n\n  rotation = 0;\n\n  t0 = Date.now();\n\n  arcs = [];\n\n  animate = () => {\n    const now = Date.now();\n    const td = now - this.t0;\n    this.rotation = (this.rotation + SPEED * td) % (2 * Math.PI);\n    this.t0 = now;\n\n    this.arcs.push({ rotation: this.rotation, td });\n\n    let lx, ly, tx, ty;\n    if (this.arcs.length > FRAMES) {\n      this.arcs.forEach(({ rotation, td }, i) => {\n        lx = tx;\n        ly = ty;\n        const r = 145;\n        tx = 155 + r * Math.cos(rotation);\n        ty = 155 + r * Math.sin(rotation);\n        const bigArc = SPEED * td < Math.PI ? '0' : '1';\n        const path = `M${tx} ${ty}A${r} ${r} 0 ${bigArc} 0 ${lx} ${ly}L155 155`;\n        const hue = 120 - Math.min(120, td / 4);\n        const colour = `hsl(${hue}, 100%, ${60 - i * (30 / FRAMES)}%)`;\n        if (i !== 0) {\n          const arcEl = this.arcGroupRef.current.children[i - 1];\n          arcEl.setAttribute('d', path);\n          arcEl.setAttribute('fill', colour);\n        }\n      });\n      this.clockHandRef.current.setAttribute('d', `M155 155L${tx} ${ty}`);\n      this.arcs.shift();\n    }\n\n    if (this.hitCounter > 0) {\n      this.faceRef.current.setAttribute('fill', `hsla(0, 0%, ${this.hitCounter}%, 0.95)`);\n      this.hitCounter -= 1;\n    } else {\n      this.hitCounter = 0;\n      this.faceRef.current.setAttribute('fill', 'hsla(0, 0%, 5%, 0.95)');\n    }\n\n    this.frame = requestAnimationFrame(this.animate);\n  };\n\n  componentDidMount() {\n    this.frame = requestAnimationFrame(this.animate);\n    if (this.faceRef.current) {\n      this.faceRef.current.addEventListener('click', this.handleClick);\n    }\n  }\n\n  componentDidUpdate() {\n    console.log('componentDidUpdate()', this.faceRef.current);\n  }\n\n  componentWillUnmount() {\n    this.faceRef.current.removeEventListener('click', this.handleClick);\n    if (this.frame) {\n      cancelAnimationFrame(this.frame);\n    }\n  }\n\n  handleClick = (e) => {\n    e.stopPropagation();\n    this.hitCounter = 50;\n  };\n\n  render() {\n    const paths = new Array(FRAMES);\n    for (let i = 0; i < FRAMES; i++) {\n      paths.push(<path className=\"arcHand\" key={i} />);\n    }\n    return (\n      <div className=\"stutterer\">\n        <svg height=\"310\" width=\"310\">\n          <circle\n            className=\"clockFace\"\n            onClick={this.handleClick}\n            cx={155}\n            cy={155}\n            r={150}\n            ref={this.faceRef}\n          />\n          <g ref={this.arcGroupRef}>{paths}</g>\n          <path className=\"clockHand\" ref={this.clockHandRef} />\n        </svg>\n      </div>\n    );\n  }\n}\n"
  },
  {
    "path": "example/time-slicing/index.js",
    "content": "import Brahmos, { PureComponent } from 'brahmos';\nimport { flushSync } from 'react-dom';\nimport Scheduler from 'scheduler';\nimport _ from 'lodash';\nimport Charts from './Charts';\nimport Clock from './Clock';\n// import './index.css';\n\nconst cachedData = new Map();\n\nclass App extends PureComponent {\n  state = {\n    value: '',\n    strategy: 'sync',\n    showDemo: true,\n    showClock: false,\n  };\n\n  // Random data for the chart\n  getStreamData(input) {\n    if (cachedData.has(input)) {\n      return cachedData.get(input);\n    }\n    const multiplier = input.length !== 0 ? input.length : 1;\n    const complexity = (parseInt(window.location.search.substring(1), 10) / 100) * 25 || 25;\n    const data = _.range(5).map((t) =>\n      _.range(complexity * multiplier).map((j, i) => {\n        return {\n          x: j,\n          y: (t + 1) * _.random(0, 255),\n        };\n      }),\n    );\n    cachedData.set(input, data);\n    return data;\n  }\n\n  componentDidMount() {\n    window.addEventListener('keydown', (e) => {\n      if (e.key.toLowerCase() === '?') {\n        e.preventDefault();\n        this.setState((state) => ({\n          showClock: !state.showClock,\n        }));\n      }\n    });\n  }\n\n  handleChartClick = (e) => {\n    if (this.state.showDemo) {\n      if (e.shiftKey) {\n        this.setState({ showDemo: false });\n      }\n      return;\n    }\n    if (this.state.strategy !== 'async') {\n      flushSync(() => {\n        this.setState((state) => ({\n          showDemo: !state.showDemo,\n        }));\n      });\n      return;\n    }\n    if (this._ignoreClick) {\n      return;\n    }\n    this._ignoreClick = true;\n\n    Scheduler.unstable_next(() => {\n      this.setState({ showDemo: true }, () => {\n        this._ignoreClick = false;\n      });\n    });\n  };\n\n  debouncedHandleChange = _.debounce((value) => {\n    if (this.state.strategy === 'debounced') {\n      flushSync(() => {\n        this.setState({ value: value });\n      });\n    }\n  }, 1000);\n\n  renderOption(strategy, label) {\n    const { strategy: currentStrategy } = this.state;\n    return (\n      <label className={strategy === currentStrategy ? 'selected' : null}>\n        <input\n          type=\"radio\"\n          checked={strategy === currentStrategy}\n          onChange={() => this.setState({ strategy })}\n        />\n        {label}\n      </label>\n    );\n  }\n\n  handleChange = (e) => {\n    const value = e.target.value;\n    const { strategy } = this.state;\n    switch (strategy) {\n      case 'sync':\n        this.setState({ value });\n        break;\n      case 'debounced':\n        this.debouncedHandleChange(value);\n        break;\n      case 'async':\n        // TODO: useTransition hook instead.\n        setTimeout(() => {\n          this.setState({ value });\n        }, 0);\n        break;\n      default:\n        break;\n    }\n  };\n\n  render() {\n    const { showClock } = this.state;\n    const data = this.getStreamData(this.state.value);\n    return (\n      <div className=\"container\">\n        <div className=\"rendering\">\n          {this.renderOption('sync', 'Synchronous')}\n          {this.renderOption('debounced', 'Debounced')}\n          {this.renderOption('async', 'Concurrent')}\n        </div>\n        <input\n          className={'input ' + this.state.strategy}\n          placeholder=\"longer input → more components and DOM nodes\"\n          defaultValue={this.state.input}\n          onChange={this.handleChange}\n        />\n        <div className=\"demo\" onClick={this.handleChartClick}>\n          {this.state.showDemo && <Charts data={data} onClick={this.handleChartClick} />}\n          <div style={{ display: showClock ? 'block' : 'none' }}>\n            <Clock />\n          </div>\n        </div>\n      </div>\n    );\n  }\n}\n"
  },
  {
    "path": "example/todo-list/index.js",
    "content": "import Brahmos, { Component } from 'brahmos';\n\n// Source: https://stackoverflow.com/a/12646864\nfunction shuffleArray(array) {\n  for (let i = array.length - 1; i > 0; i--) {\n    const j = Math.floor(Math.random() * (i + 1));\n    [array[i], array[j]] = [array[j], array[i]];\n  }\n  return array;\n}\n\n// Source: https://stackoverflow.com/a/25821830\nfunction randomColor() {\n  return `#${Math.floor(Math.random() * 16777215)\n    .toString(16)\n    .padStart(6, '0')}`;\n}\n\nexport default class TodoList extends Component {\n  static defaultProps = {\n    maxCount: 5,\n    showDescription: true,\n  };\n\n  state = { todos: [], text: '' };\n\n  componentDidUpdate(prevProps, prevState) {\n    /**\n     * Imperatively updating background on first color-code item,\n     * to demonstrate element are persisted on shuffle\n     */\n    if (prevState.todos.length !== this.state.todos.length) {\n      document.querySelector('.color-code').style.background = randomColor();\n    }\n  }\n\n  setText = (e) => {\n    this.setState({ text: e.target.value });\n  };\n\n  addTodo = () => {\n    const { todos, text } = this.state;\n    const { maxCount } = this.props;\n    if (!text || maxCount === todos.length) {\n      return;\n    }\n    const todo = {\n      text,\n      id: todos.length,\n    };\n    this.setState({ todos: [todo, ...todos], text: '' });\n  };\n\n  shuffle = () => {\n    const { todos } = this.state;\n    this.setState({ todos: shuffleArray(todos) });\n  };\n\n  render() {\n    const { todos, text } = this.state;\n    const { maxCount, showDescription } = this.props;\n    return (\n      <>\n        {showDescription && (\n          <p>\n            This demo demonstrates states, list and keyed list in Brahmos. A color code is also\n            added imperatively through DOM APIs to demonstrate keyed list are persisted (just\n            rearranged) on addition or shuffle.\n          </p>\n        )}\n\n        <form onSubmit={this.addTodo} action=\"javascript:\">\n          <div className=\"field has-addons\">\n            <div className=\"control\">\n              <input className=\"input small-width\" value={text} onChange={this.setText} />\n            </div>\n            <div className=\"control\">\n              <button className=\"button is-dark\" type=\"submit\">\n                Add\n              </button>\n            </div>\n          </div>\n        </form>\n        <br />\n        <p>Latest todo item is added on top. Add 3 items or more to shuffle the list</p>\n        <ul>\n          {todos.map((todo) => (\n            <li key={todo.id}>\n              <span\n                style={{\n                  width: '20px',\n                  height: '20px',\n                  display: 'inline-block',\n                  verticalAlign: 'middle',\n                }}\n                className=\"color-code\"\n              ></span>{' '}\n              {todo.text}\n            </li>\n          ))}\n        </ul>\n        <div className=\"control-wrap\">\n          {!!todos.length && maxCount > todos.length && (\n            <span>You can add {maxCount - todos.length} items to this list &nbsp;</span>\n          )}\n          {maxCount === todos.length && <span>List is Full &nbsp;</span>}\n          {todos.length > 2 && (\n            <button className=\"button is-dark\" type=\"button\" onClick={this.shuffle}>\n              Shuffle\n            </button>\n          )}\n        </div>\n      </>\n    );\n  }\n}\n"
  },
  {
    "path": "example/use-deferred-value/MySlowList.js",
    "content": "import Brahmos, { PureComponent } from 'brahmos';\n\n// Note: this file is exactly the same in both examples.\n\nfunction ListItem({ children }) {\n  const now = performance.now();\n  while (performance.now() - now < 1.5) {\n    // Note: this is an INTENTIONALLY EMPTY loop that\n    // DOES NOTHING for 1.5 milliseconds for EACH ITEM.\n    //\n    // It's meant to emulate what happens in a deep\n    // component tree with calculations and other\n    // work performed inside components that can't\n    // trivially be optimized or removed.\n  }\n  return <div className=\"ListItem\">{children}</div>;\n}\n\nexport default class MySlowList extends PureComponent {\n  render() {\n    const { text } = this.props;\n    const items = [];\n    const ln = text.length * 5;\n    for (let i = 0; i < ln; i++) {\n      items.push(\n        <ListItem key={i}>\n          Result #{i} for \"{text}\"\n        </ListItem>,\n      );\n    }\n    return (\n      <>\n        <p>\n          <b>Results for \"{text}\":</b>\n        </p>\n        <ul className=\"List\">{items}</ul>\n      </>\n    );\n  }\n}\n"
  },
  {
    "path": "example/use-deferred-value/index.js",
    "content": "import Brahmos, { useDeferredValue, useState, useEffect } from 'brahmos';\nimport MySlowList from './MySlowList';\nimport ReactCredit from '../common/ReactCredit';\n\n/**\n * Forked from:\n * https://codesandbox.io/s/infallible-dewdney-9fkv9\n */\n\nfunction Toggle({ concurrentMode, setConcurrentMode }) {\n  return (\n    <div className=\"control-wrap\">\n      <strong>Concurrent Mode: &nbsp;</strong>\n      <label className=\"radio\">\n        <input type=\"radio\" checked={concurrentMode} onClick={() => setConcurrentMode(true)} />\n        &nbsp;On\n      </label>\n      <label className=\"radio\">\n        <input type=\"radio\" checked={!concurrentMode} onClick={() => setConcurrentMode(false)} />\n        &nbsp;Off\n      </label>\n    </div>\n  );\n}\n\nexport default function App() {\n  const [text, setText] = useState('');\n  const [concurrentMode, setConcurrentMode] = useState(true);\n\n  // This is a new feature in Concurrent Mode.\n  // This value is allowed to \"lag behind\" the text input:\n  const deferredText = useDeferredValue(text, {\n    timeoutMs: 5000,\n  });\n\n  function handleChange(e) {\n    setText(e.target.value);\n  }\n\n  return (\n    <div className=\"App\">\n      <p>Toggle concurrentMode and see the effect in input</p>\n      <Toggle concurrentMode={concurrentMode} setConcurrentMode={setConcurrentMode} />\n      <br />\n      <label className=\"control-wrap\">\n        <span>Type into the input: </span>\n        <input className=\"input small-width\" value={text} onChange={handleChange} />\n      </label>\n      <p>\n        Here we create 5 list item for each character in text box. Plus each of the list item\n        completely blocks the main thread for 1.5 milliseconds.\n        <br />\n        <br />\n        On concurrent mode we can see the app is able to stay responsive even the number of list\n        increases and only delays displaying the list. While in normal mode the input starts getting\n        janky as soon as the size of list grows.\n      </p>\n      <hr />\n      {/* Pass the \"lagging\" value to the list */}\n      <MySlowList text={concurrentMode ? deferredText : text} />\n      <ReactCredit\n        name=\"useDeferredValue hook\"\n        link=\"https://codesandbox.io/s/infallible-dewdney-9fkv9\"\n      />\n    </div>\n  );\n}\n"
  },
  {
    "path": "example/use-deferred-value-suspense/fakeApi.js",
    "content": "export function fetchProfileData(userId) {\n  const userPromise = fetchUser(userId);\n  const postsPromise = fetchPosts(userId);\n  return {\n    userId,\n    user: wrapPromise(userPromise),\n    posts: wrapPromise(postsPromise),\n  };\n}\n\n// Suspense integrations like Relay implement\n// a contract like this to integrate with React.\n// Real implementations can be significantly more complex.\n// Don't copy-paste this into your project!\nfunction wrapPromise(promise) {\n  let status = 'pending';\n  let result;\n  const suspender = promise.then(\n    (r) => {\n      status = 'success';\n      result = r;\n    },\n    (e) => {\n      status = 'error';\n      result = e;\n    },\n  );\n  return {\n    read() {\n      if (status === 'pending') {\n        throw suspender;\n      } else if (status === 'error') {\n        throw result;\n      } else if (status === 'success') {\n        return result;\n      }\n    },\n  };\n}\n\nexport function fetchUser(userId) {\n  console.log('fetch user ' + userId + '...');\n  return new Promise((resolve) => {\n    setTimeout(() => {\n      console.log('fetched user ' + userId);\n      switch (userId) {\n        case 0:\n          resolve({\n            name: 'Ringo Starr',\n          });\n          break;\n        case 1:\n          resolve({\n            name: 'George Harrison',\n          });\n          break;\n        case 2:\n          resolve({\n            name: 'John Lennon',\n          });\n          break;\n        case 3:\n          resolve({\n            name: 'Paul McCartney',\n          });\n          break;\n        default:\n          throw Error('Unknown user.');\n      }\n    }, 300);\n  });\n}\n\nexport function fetchPosts(userId) {\n  console.log('fetch posts for ' + userId + '...');\n  return new Promise((resolve) => {\n    setTimeout(() => {\n      console.log('fetched posts for ' + userId);\n      switch (userId) {\n        case 0:\n          resolve([\n            {\n              id: 0,\n              text: 'I get by with a little help from my friends',\n            },\n            {\n              id: 1,\n              text: \"I'd like to be under the sea in an octupus's garden\",\n            },\n            {\n              id: 2,\n              text: 'You got that sand all over your feet',\n            },\n          ]);\n          break;\n        case 1:\n          resolve([\n            {\n              id: 0,\n              text: 'Turn off your mind, relax, and float downstream',\n            },\n            {\n              id: 1,\n              text: 'All things must pass',\n            },\n            {\n              id: 2,\n              text: \"I look at the world and I notice it's turning\",\n            },\n          ]);\n          break;\n        case 2:\n          resolve([\n            {\n              id: 0,\n              text: 'Living is easy with eyes closed',\n            },\n            {\n              id: 1,\n              text: \"Nothing's gonna change my world\",\n            },\n            {\n              id: 2,\n              text: 'I am the walrus',\n            },\n          ]);\n          break;\n        case 3:\n          resolve([\n            {\n              id: 0,\n              text: 'Woke up, fell out of bed',\n            },\n            {\n              id: 1,\n              text: 'Here, there, and everywhere',\n            },\n            {\n              id: 2,\n              text: 'Two of us sending postcards, writing letters',\n            },\n          ]);\n          break;\n        default:\n          throw Error('Unknown user.');\n      }\n    }, 1500);\n  });\n}\n"
  },
  {
    "path": "example/use-deferred-value-suspense/index.js",
    "content": "/**\n * Forked from: https://codesandbox.io/s/vigorous-keller-3ed2b\n */\n\nimport Brahmos, { useDeferredValue, useState, useTransition, Suspense } from 'brahmos';\nimport ReactCredit from '../common/ReactCredit';\n\nimport { fetchProfileData } from './fakeApi';\n\nfunction getNextId(id) {\n  return id === 3 ? 0 : id + 1;\n}\n\nconst initialResource = fetchProfileData(0);\n\nfunction App() {\n  const [resource, setResource] = useState(initialResource);\n  const [startTransition, isPending] = useTransition({\n    timeoutMs: 3000,\n  });\n  return (\n    <>\n      <p>\n        This demo demonstrates how we can use useDeferredValue to prevent loading state on non\n        important data.\n        <br />\n        Read more about it in official React Docs.\n        <a\n          href=\"https://reactjs.org/docs/concurrent-mode-patterns.html#deferring-a-value\"\n          target=\"_blank\"\n          rel=\"noopener\"\n        >\n          https://reactjs.org/docs/concurrent-mode-patterns.html#deferring-a-value\n        </a>\n        <br />\n        <br />\n        Here the profile detail API is mocked to respond in 300ms and post API is mocked to respond\n        in 1500ms. The app will keep showing stale content for post data until its loaded or for max\n        5 seconds if you keep pressing next before a post gets a chance to load.\n      </p>\n      <div className=\"control-wrap\">\n        <button\n          className=\"button is-primary\"\n          disabled={isPending}\n          onClick={() => {\n            startTransition(() => {\n              const nextUserId = getNextId(resource.userId);\n              setResource(fetchProfileData(nextUserId));\n            });\n          }}\n        >\n          Next\n        </button>\n        {isPending ? ' Loading...' : null}\n      </div>\n      <ProfilePage resource={resource} />\n      <ReactCredit name=\"useDeferredValue\" link=\"https://codesandbox.io/s/vigorous-keller-3ed2b\" />\n    </>\n  );\n}\n\nfunction ProfilePage({ resource }) {\n  const deferredResource = useDeferredValue(resource, {\n    timeoutMs: 5000,\n  });\n  return (\n    <Suspense fallback={<h1>Loading profile...</h1>}>\n      <ProfileDetails resource={resource} />\n      <Suspense fallback={<h1>Loading posts...</h1>}>\n        <ProfileTimeline resource={deferredResource} isStale={deferredResource !== resource} />\n      </Suspense>\n    </Suspense>\n  );\n}\n\nfunction ProfileDetails({ resource }) {\n  const user = resource.user.read();\n  return <h1>{user.name}</h1>;\n}\n\nfunction ProfileTimeline({ isStale, resource }) {\n  const posts = resource.posts.read();\n  return (\n    <ul style={{ opacity: isStale ? 0.7 : 1 }}>\n      {posts.map((post) => (\n        <li key={post.id}>{post.text}</li>\n      ))}\n    </ul>\n  );\n}\n\nexport default App;\n"
  },
  {
    "path": "example_old/App.js",
    "content": "import Brahmos, { Suspense, lazy, Component } from '../src';\n\nimport TodoList from './TodoList';\nimport UseStateExample from './UseStateExample';\nimport ContextExample from './context';\nimport RefsExample from './RefsExample';\nimport CreatePortalExample from './createPortalExample';\nimport SVGExample from './SVGExample';\nimport LazySuspenseExample from './lazySuspenseExample';\nimport ErrorBoundaryExample from './ErrorBoundaryExample';\n\nfunction shuffle(array) {\n  array = [...array];\n  var currentIndex = array.length;\n  var temporaryValue;\n  var randomIndex;\n\n  // While there remain elements to shuffle...\n  while (currentIndex !== 0) {\n    // Pick a remaining element...\n    randomIndex = Math.floor(Math.random() * currentIndex);\n    currentIndex -= 1;\n\n    // And swap it with the current element.\n    temporaryValue = array[currentIndex];\n    array[currentIndex] = array[randomIndex];\n    array[randomIndex] = temporaryValue;\n  }\n\n  return array;\n}\n\nexport function OldApp() {\n  return (\n    <div>\n      {/* <div className=\"wrapper\">\n        <h2>Todo List</h2>\n        <TodoList />\n      </div>\n      <div className=\"wrapper\">\n        <h2>useState hook example</h2>\n        <UseStateExample />\n      </div> */}\n      {/* <div className=\"wrapper\">\n        <h2>Context api example</h2>\n        <ContextExample />\n      </div> */}\n      {/* <div className=\"wrapper\">\n        <h2>Refs example</h2>\n        <RefsExample />\n      </div> */}\n      {/* <div className=\"wrapper\">\n        <h2>SVG Example</h2>\n        <SVGExample />\n      </div> */}\n      {/* <div className=\"wrapper\">\n        <h2>Lazy and Suspense Example</h2>\n        <LazySuspenseExample />\n      </div> */}\n      {/* <div className=\"wrapper\">\n        <h2>Error Boundary Example</h2>\n        <ErrorBoundaryExample />\n      </div> */}\n      {/** Keep the portal example on last */}\n      <div className=\"wrapper\">\n        <h2>CreatePortal Example</h2>\n        <CreatePortalExample />\n      </div>\n    </div>\n  );\n}\n\nfunction Div() {\n  return <div>askjdkajsdks</div>;\n}\n\nfunction Div2({ length, list }) {\n  return (\n    <ul>\n      {list.slice(0, length).map((val, idx) => (\n        <li key={val}>{val}</li>\n      ))}\n    </ul>\n  );\n}\n\nexport class AppBase extends Component {\n  state = {\n    name: '',\n    list: [1, 2, 3, 4],\n  };\n\n  render() {\n    const { name, list } = this.state;\n    return (\n      <div>\n        <input\n          type=\"text\"\n          value={name}\n          onChange={(e) => {\n            this.setState({ name: e.target.value.slice(0, 10) });\n\n            Brahmos.unstable_deferredUpdates(() => {\n              this.setState({ list: shuffle(list) }, null);\n            });\n            // this.deferredSetState({ list: shuffle(list) }, null);\n          }}\n        />\n        <p>Hello {name}</p> {'Hello World'}\n        <Div2 length={name.length} list={list} />\n        {name && <Div />}\n      </div>\n    );\n  }\n}\n\nexport default function App() {\n  return (\n    <div>\n      <OldApp />\n    </div>\n  );\n}\n"
  },
  {
    "path": "example_old/ErrorBoundaryExample.js",
    "content": "import Brahmos from '../src';\n\nclass ErrorBoundary extends Brahmos.Component {\n  constructor(props) {\n    super(props);\n    this.state = { error: null, errorInfo: null };\n  }\n\n  static getDerivedStateFromError(error) {\n    return { error };\n  }\n\n  componentDidCatch(error, errorInfo) {\n    // Catch errors in any components below and re-render with error message\n    this.setState({\n      error: error,\n      errorInfo: errorInfo,\n    });\n    // You can also log error messages to an error reporting service here\n  }\n\n  render() {\n    if (this.state.error) {\n      // Error path\n      return (\n        <div>\n          <h2>Something went wrong.</h2>\n          <details style={{ whiteSpace: 'pre-wrap' }}>\n            {this.state.error && this.state.error.toString()}\n            <br />\n            {this.state.errorInfo && this.state.errorInfo.componentStack}\n          </details>\n        </div>\n      );\n    }\n    // Normally, just render children\n    return this.props.children;\n  }\n}\n\nclass BuggyCounter extends Brahmos.Component {\n  constructor(props) {\n    super(props);\n    this.state = { counter: 0 };\n    this.handleClick = this.handleClick.bind(this);\n  }\n\n  handleClick() {\n    this.setState(({ counter }) => ({\n      counter: counter + 1,\n    }));\n  }\n\n  render() {\n    if (this.state.counter === 5) {\n      // Simulate a JS error\n      throw new Error('I crashed!');\n    }\n    return <h1 onClick={this.handleClick}>{this.state.counter}</h1>;\n  }\n}\n\nexport default function ErrorBoundaryExample() {\n  return (\n    <div>\n      <p>\n        <b>\n          This is an example of error boundaries in React 16.\n          <br />\n          <br />\n          Click on the numbers to increase the counters.\n          <br />\n          The counter is programmed to throw when it reaches 5. This simulates a JavaScript error in\n          a component.\n        </b>\n      </p>\n      <hr />\n      <ErrorBoundary>\n        <p>\n          These two counters are inside the same error boundary. If one crashes, the error boundary\n          will replace both of them.\n        </p>\n        <BuggyCounter />\n        <BuggyCounter />\n      </ErrorBoundary>\n      <hr />\n      <p>\n        These two counters are each inside of their own error boundary. So if one crashes, the other\n        is not affected.\n      </p>\n      <ErrorBoundary>\n        <BuggyCounter />\n      </ErrorBoundary>\n      <ErrorBoundary>\n        <BuggyCounter />\n      </ErrorBoundary>\n    </div>\n  );\n}\n"
  },
  {
    "path": "example_old/RefsExample.js",
    "content": "import Brahmos, { Component, createRef, forwardRef } from '../src';\n\nclass Child extends Component {\n  logSomething() {\n    // console.log('something');\n  }\n\n  render() {\n    return <div>Hello World!!</div>;\n  }\n}\n\nconst ChildWithForwardedRef = forwardRef((props, ref) => {\n  return <div ref={ref}>Forwarded Ref</div>;\n});\n\nexport default class RefsExample extends Component {\n  constructor() {\n    super();\n    this.childCreateRef = createRef();\n    this.domCreateRef = createRef();\n    this.forwardedRef = createRef();\n  }\n\n  logRefs = () => {\n    console.log(this.childCreateRef);\n    console.log(this.childCallbackRef);\n    console.log(this.domCreateRef);\n    console.log(this.domCbRef);\n    console.log(this.forwardedRef);\n  };\n\n  render() {\n    return (\n      <div>\n        <Child ref={this.childCreateRef} />\n        <Child\n          ref={(instance) => {\n            this.childCallbackRef = instance;\n          }}\n        />\n        <div ref={this.domCreateRef}>Dom create ref</div>\n        <div\n          ref={(elm) => {\n            this.domCbRef = elm;\n          }}\n        >\n          Dom callback ref\n        </div>\n        <ChildWithForwardedRef ref={this.forwardedRef} />\n        <button onClick={this.logRefs}>Log refs</button>\n      </div>\n    );\n  }\n}\n"
  },
  {
    "path": "example_old/SVGExample.js",
    "content": "import Brahmos, { Component } from '../src';\n\nfunction Path() {\n  return (\n    <path\n      fill=\"#703E03\"\n      d=\"M29.203 45.82c1.69-.807 2.947-2.117 4.708-2.838 1.607-.658 3.201-1.199 4.833-1.834 1.597-.621 3.242-.886 4.83-1.362 1.673-.502 3.236-.53 4.937-.953 1.737-.431 3.513-1.197 5.333-1.667 1.412-.365 2.669-1.173 4.1-1.389 2.5-.378 4.977.133 7.4.723 1.939.472 3.729 1.028 5.667 1.333 1.651.26 2.876.773 4.5 1.167 1.959.475 4.125 1.768 6.1 2.28 1.979.514 4.2.655 6.067 1.554 3.612 1.739 7.296 2.528 10.721 4.448 3.489 1.956 5.612 4.218 7.009 8.829 1.659 5.478 2.217 13.509 1.604 19.056-.16 1.446-.494 3.428-.833 4.833-.397 1.653-.967 3.458-1.334 5.167-.561 2.605-1.511 4.076-3.067 6.319-1.573 2.268-3.493 4.336-5.037 6.634-1.276 1.901-2.764 3.523-4.345 5.158-2.773 2.867-5.986 5.034-9.654 6.366-1.673.607-3.126 1.624-4.729 2.355-1.852.843-3.623 1.234-5.775 1.448-4.083.406-8.257-.108-12.199-.676-1.575-.227-4.594-.044-5.444-1.467 3.956-1.482 8.64-.723 12.827-1.323 3.803-.546 6.978-2.452 10.142-4.46 1.951-1.237 4.331-2.173 6.021-3.749 1.562-1.456 2.935-3.242 4.524-4.629 2.886-2.518 5.756-5.546 7.175-9.199.799-2.058 1.604-4.157 2.005-6.343.375-2.045.383-4.43.938-6.433-1.547-.019-1.213 3.997-8.046 4.497 3.166-2.167 8.166-9.453 8.166-11.834 0-3.333.088-5.217-1.166-8.333-.651-1.618-.942-3.283-2.167-4.5-1.729-1.716-3.293-4.038-5.449-4.86-4.349-1.659-8.537-3.441-13.143-4.029-4.493-.574-8.646-2.018-13.129-2.407-5.001-.434-10.206-.379-15.091.449-1.575.267-3.17.636-4.752.796-1.8.182-3.32-.131-5.04.612-1.65.714-2.971 1.943-4.793 2.351-1.8.403-3.505.673-5.208 1.529-1.437.723-2.78 1.875-4.157 2.753-1.905 1.214-4.284 1.733-2.436-1.195 1.644-2.604 4.715-3.903 7.387-5.177z\"\n      opacity=\"0.44\"\n    />\n  );\n}\n\nfunction Image() {\n  return (\n    <svg\n      x=\"0\"\n      y=\"0\"\n      width=\"100\"\n      height=\"100\"\n      version=\"1.1\"\n      viewBox=\"0 0 123.61 125.76\"\n      xmlSpace=\"preserve\"\n    >\n      <path\n        fill=\"none\"\n        stroke=\"#FFF\"\n        strokeLinecap=\"round\"\n        strokeLinejoin=\"round\"\n        strokeWidth=\"0\"\n        d=\"M.011.72v125.04h123.6V0H.251c-.28.041-.261.379-.24.72z\"\n      />\n      <path\n        fill=\"#050000\"\n        stroke=\"#000\"\n        strokeLinecap=\"round\"\n        strokeLinejoin=\"round\"\n        strokeWidth=\"0\"\n        d=\"M3.851 56.88c1.875 3.062 6.286 4.794 10.32 5.52-3.6 21.854 5.785 38.208 17.28 47.52 9.626 7.797 24.468 13.2 40.32 10.32 13.498-2.452 24.493-10.479 31.44-20.641 6.735-9.851 11.13-25.374 6.479-41.76 4.692-.748 9.717-1.163 12.24-4.08.052-9.999-4.273-15.911-9.84-21.36-6.505-6.367-13.335-10.312-21.84-14.64-7.029-3.576-14.632-6.652-23.28-7.92-.736-1.941-.329-4.134-.72-6-2.249-.137-5.195.203-6.72 0-.284.117-.544.256-.72.48-.067 2.467.547 4.253.48 6.72-9.243 1.915-16.295 5.3-24.48 9.36-9.875 4.898-17.957 10.942-24.72 18.96C5.735 44.523-.715 49.42 3.851 56.88z\"\n      />\n      <path\n        fill=\"#F9BA06\"\n        stroke=\"#FFF\"\n        strokeLinecap=\"round\"\n        strokeLinejoin=\"round\"\n        strokeWidth=\"0\"\n        d=\"M24.491 97.44c7.703 11.266 22.038 20.568 39.36 19.92 17.409-.652 30.38-10.228 37.44-21.601 7.217-11.626 9.833-32.751.72-46.56-5.724-3.712-13.155-5.204-20.4-7.92-7.037-2.639-15.007-5.472-23.04-5.52-.079 0-.162-.006-.24 0-3.503.292-7.329 2.729-11.04 3.6-5.467 1.284-10.551 2.881-14.88 4.8-4.286 1.9-8.381 3.702-10.56 6.96-8.976 13.424-4.837 35.385 2.64 46.321z\"\n      />\n      <path\n        fill=\"#020000\"\n        stroke=\"#000\"\n        strokeLinecap=\"round\"\n        strokeLinejoin=\"round\"\n        strokeWidth=\"0\"\n        d=\"M25.931 65.04c.156 19.995 30.532 19.669 30.48-.24-.023-8.815-7.445-15.833-16.8-14.88-7.844.799-13.742 7.203-13.68 15.12zM83.051 80.64c7.981-.146 14.55-6.614 14.88-14.399.426-10.062-7.827-16.826-16.8-15.84-8.55.939-14.171 7.654-13.68 16.081.454 7.797 6.885 14.319 15.6 14.158z\"\n      />\n      <path\n        fill=\"#FFF\"\n        stroke=\"#FFF\"\n        strokeLinecap=\"round\"\n        strokeLinejoin=\"round\"\n        strokeWidth=\"0\"\n        d=\"M29.771 67.2c1.94 12.828 20.939 11.152 22.8.24 1.567-9.189-5.502-15.075-13.68-13.681-5.996 1.024-10.167 6.521-9.12 13.441zM71.291 67.68c1.939 12.828 20.938 11.152 22.8.24 1.567-9.188-5.503-15.075-13.68-13.68-5.996 1.023-10.167 6.52-9.12 13.44z\"\n      />\n      <path\n        fill=\"#050000\"\n        stroke=\"#000\"\n        strokeLinecap=\"round\"\n        strokeLinejoin=\"round\"\n        strokeWidth=\"0\"\n        d=\"M53.771 78.48c-.206 1.394-1.983 1.216-2.16 2.64 3.445 5.921 15.521 5.449 19.68.479-.063-1.536-.285-2.915-1.44-3.359-2.749 4.479-13.187 4.846-16.08.24z\"\n      />\n      <path\n        fill=\"#050000\"\n        d=\"M36.011 94.08c8.396 6.568 26.5 11.277 40.32 6.72 1.326-.438 2.738-1.567 3.84-2.64-.583-5.279-3.393-2.688-6.96-1.68-2.283.645-6.163 1.229-8.16 1.439-8.81.932-14.93-1.887-20.16-4.32-2.641-1.229-4.706-2.354-6.24-3.6-1.957-1.589-2.51-4.383-4.56-5.04-.547-.176-2.935.736-3.12 2.4-.374 3.352 4.412 4.362 5.04 6.721z\"\n      />\n      <Path />\n      <path\n        fill=\"#703E03\"\n        d=\"M62.178 85.5c-1.299.069-2.554.292-3.833.009-1.331-.294-2.541-1.274-3.974-1.15-.102 1.731 3.847 3.931 5.187 4.675 2.28 1.268 5.146 2.301 7.787 1.812 1.651-.306 3.156-1.4 4.135-2.741.764-1.047 2.148-4.111.522-5.095-1.138-.688-2.841.876-3.844 1.316-1.897.835-3.929 1.066-5.98 1.174z\"\n        opacity=\"0.46\"\n      />\n    </svg>\n  );\n}\n\nfunction Chart({ data }) {\n  return (\n    <svg width=\"420\" height=\"120\">\n      {data.map((item, i) => (\n        <rect\n          width=\"40\"\n          y={120 - item}\n          x=\"50\"\n          height={item}\n          style=\"transition: all ease .3s;\"\n          transform={`translate(${43 * i},0)`}\n        />\n      ))}\n    </svg>\n  );\n}\n\nclass SVGExample extends Component {\n  state = {\n    data: [99, 44, 11, 55, 33, 115, 4],\n  };\n\n  _shuffuleArray(array) {\n    var j, temp, i;\n    for (i = array.length; i; i--) {\n      j = Math.floor(Math.random() * i);\n      temp = array[i - 1];\n      array[i - 1] = array[j];\n      array[j] = temp;\n    }\n    return array;\n  }\n\n  shuffule = () => this.setState({ data: this._shuffuleArray(this.state.data) });\n\n  render() {\n    const { data } = this.state;\n    return (\n      <div>\n        <Image />\n        <Chart data={data} />\n        <button onClick={this.shuffule}>Suffule</button>\n      </div>\n    );\n  }\n}\n\nexport default SVGExample;\n"
  },
  {
    "path": "example_old/TodoList.js",
    "content": "import Brahmos, { Component } from '../src';\n\nexport default class TodoList extends Component {\n  static defaultProps = {\n    maxCount: 5,\n  };\n\n  state = { todos: [], text: '' };\n\n  setText = (e) => {\n    this.setState({ text: e.target.value });\n  };\n\n  addTodo = () => {\n    let { todos, text } = this.state;\n    const { maxCount } = this.props;\n    if (!text || maxCount === todos.length) {\n      return;\n    }\n    todos = todos.concat(text);\n    this.setState({ todos, text: '' });\n  };\n\n  componentDidMount() {\n    // console.log('TODO List mounted');\n  }\n\n  render() {\n    const { todos, text } = this.state;\n    const { maxCount } = this.props;\n    return (\n      <form onSubmit={this.addTodo} action=\"javascript:\">\n        <input value={text} onInput={this.setText} />\n        <button type=\"submit\">Add</button>\n        <ul>\n          {todos.map((todo, idx) => (\n            <li key={idx}>{todo}</li>\n          ))}\n        </ul>\n        {maxCount > todos.length && (\n          <span>You can add {maxCount - todos.length} items to this list</span>\n        )}\n        {maxCount === todos.length && <span>List is Full</span>}\n      </form>\n    );\n  }\n}\n"
  },
  {
    "path": "example_old/UnMountAtNode.js",
    "content": "import Brahmos, { Component, unmountComponentAtNode } from '../src';\n\nexport default class UnMountAtNode extends Component {\n  removeNode = () => {\n    setTimeout(() => {\n      unmountComponentAtNode(document.getElementById('unmount-node'));\n    }, 1000);\n  };\n\n  componentWillUnmount() {\n    // console.log('component will unmount life cycle called!!');\n  }\n\n  render() {\n    return (\n      <div>\n        <p>\n          {' '}\n          Remove a mounted Brahmos component from the DOM and clean up its event handlers and state.\n          If no component was mounted in the container, calling this function does nothing. Returns\n          true if a component was unmounted and false if there was no component to unmount.{' '}\n        </p>\n        <div>\n          <button onClick={this.removeNode}> Remove node</button>\n        </div>\n      </div>\n    );\n  }\n}\n"
  },
  {
    "path": "example_old/UseStateExample.js",
    "content": "import Brahmos, { useState } from '../src';\nimport friends from './friends.json';\n\nexport default function UseStateExample() {\n  const [filterStr, setFilter] = useState('');\n  const filteredLower = filterStr.toLowerCase();\n  const filteredFriend = friends.filter(({ name }) => {\n    return name.toLowerCase().startsWith(filteredLower);\n  });\n\n  return (\n    <div>\n      <input value={filterStr} onChange={(e) => setFilter(e.target.value)} />\n      <ul>\n        {filteredFriend.map(({ _id, name }) => {\n          return <li key={_id}>{name}</li>;\n        })}\n      </ul>\n    </div>\n  );\n}\n"
  },
  {
    "path": "example_old/concurrentApp.js",
    "content": "import _Brahmos from '../src';\nimport data from './data.json';\n\n// Doing this to check performance\nconst Brahmos = _Brahmos;\nconst { Component, PureComponent } = Brahmos;\n\nfunction shuffle(array) {\n  array = [...array];\n  var currentIndex = array.length;\n  var temporaryValue;\n  var randomIndex;\n\n  // While there remain elements to shuffle...\n  while (currentIndex !== 0) {\n    // Pick a remaining element...\n    randomIndex = Math.floor(Math.random() * currentIndex);\n    currentIndex -= 1;\n\n    // And swap it with the current element.\n    temporaryValue = array[currentIndex];\n    array[currentIndex] = array[randomIndex];\n    array[randomIndex] = temporaryValue;\n  }\n\n  return array;\n}\n\nfunction duplicateData(data, count) {\n  const newData = [];\n  const ln = data.length;\n  for (let i = 0; i < count; i++) {\n    newData.push({ ...data[i % ln], id: i });\n  }\n\n  return newData;\n}\n\nclass Result extends PureComponent {\n  render() {\n    const { result } = this.props;\n    return (\n      <div className=\"result\">\n        <div>\n          <a href={result.html_url} target=\"_blank\">\n            {result.full_name}\n          </a>\n          <button>OK</button>\n          🌟<strong>{result.stargazers_count}</strong>\n        </div>\n        <p>{result.description}</p>\n      </div>\n    );\n  }\n}\n\n// function Result(props) {\n//   const { result } = props;\n//   return (\n//     <div className=\"result\">\n//       <div>\n//         <a href={result.html_url} target=\"_blank\">\n//           {result.full_name}\n//         </a>\n//         <button>OK</button>\n//         🌟<strong>{result.stargazers_count}</strong>\n//       </div>\n//       <p>{result.description}</p>\n//     </div>\n//   );\n// }\n\n// export const Result = ({ result }) => {\n//   // let i = 0;\n\n//   // while (i < 100000000) i++;\n\n//   return (\n//     <div className=\"result\">\n//       <div>\n//         <a href={result.html_url} target=\"_blank\">\n//           {result.full_name}\n//         </a>\n//         <button>OK</button>\n//         🌟<strong>{result.stargazers_count}</strong>\n//       </div>\n//       <p>{result.description}</p>\n//     </div>\n//   );\n// };\n\nconst initialTime = performance.now();\n\nexport default class App extends Component {\n  state = { results: [] };\n\n  stateUpdateTime = initialTime;\n\n  componentDidMount() {\n    this.setState({\n      results: duplicateData(data.items, 1000),\n    });\n    // setInterval(() => {\n    //   this.shuffle();\n    // }, 10000);\n\n    // document.querySelector('#shuffle-btn').addEventListener('click', this.shuffle);\n  }\n\n  componentDidUpdate() {\n    console.log(performance.now() - this.stateUpdateTime);\n  }\n\n  shuffle = () => {\n    // console.log('State update');\n    this.stateUpdateTime = performance.now();\n    // this.state.results.reverse();\n\n    // this.forceUpdate();\n\n    this.setState({ results: shuffle(this.state.results) });\n  };\n\n  clear = () => {\n    this.stateUpdateTime = performance.now();\n\n    this.setState({ results: [] });\n  };\n\n  render(props) {\n    const { results, value = '' } = this.state || {};\n    // let i = 0;\n\n    // while (i < 10000000) i++;\n\n    return (\n      <div>\n        <h1>Examples</h1>\n        <input\n          value={value}\n          onChange={(e) => {\n            // console.log('Event update');\n\n            this.stateUpdateTime = performance.now();\n            this.setState({ value: e.target.value.slice(0, 10) });\n          }}\n        />\n        <button id=\"shuffle-btn\" onClick={this.shuffle}>\n          Shuffle\n        </button>\n        <button onClick={this.clear}>Clear</button>\n        <div className=\"list\">\n          {results.map((result) => (\n            <Result key={result.id} result={result} />\n          ))}\n        </div>\n      </div>\n    );\n  }\n}\n"
  },
  {
    "path": "example_old/context.js",
    "content": "import Brahmos, { Component, createContext, useContext, useState } from '../src';\n\nconst BrahmosContext = createContext('Brahmos');\n\n// context as static property\nclass ContextStaticProperty extends Component {\n  render() {\n    const name = this.context;\n    return <div>Hello {name}</div>;\n  }\n}\nContextStaticProperty.contextType = BrahmosContext;\n\nfunction ContextConsumer() {\n  return <BrahmosContext.Consumer>{(name) => <div>Hello {name}</div>}</BrahmosContext.Consumer>;\n}\n\nfunction UseContext() {\n  const name = useContext(BrahmosContext);\n\n  return <div>Hello {name}</div>;\n}\n\nexport default function ContextExample() {\n  const [name, setName] = useState();\n\n  return (\n    <div>\n      <input value={name} onChange={(e) => setName(e.target.value)} />\n      <BrahmosContext.Provider value={name}>\n        <h3>ContextConsumer</h3>\n        <ContextConsumer />\n\n        <h3>ContextStaticProperty</h3>\n        <ContextStaticProperty />\n\n        <h3>useContext Hook</h3>\n        <UseContext />\n      </BrahmosContext.Provider>\n\n      <div>\n        <h3>ContextConsumer without Provider</h3>\n        <ContextConsumer />\n        <h3>useContext without Provider</h3>\n        <UseContext />\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "example_old/createPortalExample.js",
    "content": "import Brahmos, { Component, createPortal, useState } from '../src';\n\nclass Child extends Component {\n  componentWillUnmount() {\n    // console.log('unmounted');\n  }\n\n  render() {\n    return <div>Hello New Root!</div>;\n  }\n}\n\nfunction CreatePortalExample() {\n  const [display, setDisplay] = useState(true);\n  return (\n    <div>\n      {display && createPortal(<Child />, document.querySelector('#another-root'))}\n      <button\n        onClick={() => {\n          setDisplay(!display);\n        }}\n      >\n        Toggle\n      </button>\n    </div>\n  );\n}\n\nexport default CreatePortalExample;\n"
  },
  {
    "path": "example_old/data.json",
    "content": "{\n  \"total_count\": 3782,\n  \"incomplete_results\": false,\n  \"items\": [\n    {\n      \"id\": 42283287,\n      \"node_id\": \"MDEwOlJlcG9zaXRvcnk0MjI4MzI4Nw==\",\n      \"name\": \"preact\",\n      \"full_name\": \"preactjs/preact\",\n      \"private\": false,\n      \"owner\": {\n        \"login\": \"preactjs\",\n        \"id\": 26872990,\n        \"node_id\": \"MDEyOk9yZ2FuaXphdGlvbjI2ODcyOTkw\",\n        \"avatar_url\": \"https://avatars3.githubusercontent.com/u/26872990?v=4\",\n        \"gravatar_id\": \"\",\n        \"url\": \"https://api.github.com/users/preactjs\",\n        \"html_url\": \"https://github.com/preactjs\",\n        \"followers_url\": \"https://api.github.com/users/preactjs/followers\",\n        \"following_url\": \"https://api.github.com/users/preactjs/following{/other_user}\",\n        \"gists_url\": \"https://api.github.com/users/preactjs/gists{/gist_id}\",\n        \"starred_url\": \"https://api.github.com/users/preactjs/starred{/owner}{/repo}\",\n        \"subscriptions_url\": \"https://api.github.com/users/preactjs/subscriptions\",\n        \"organizations_url\": \"https://api.github.com/users/preactjs/orgs\",\n        \"repos_url\": \"https://api.github.com/users/preactjs/repos\",\n        \"events_url\": \"https://api.github.com/users/preactjs/events{/privacy}\",\n        \"received_events_url\": \"https://api.github.com/users/preactjs/received_events\",\n        \"type\": \"Organization\",\n        \"site_admin\": false\n      },\n      \"html_url\": \"https://github.com/preactjs/preact\",\n      \"description\": \"⚛️ Fast 3kB React alternative with the same modern API. Components & Virtual DOM.\",\n      \"fork\": false,\n      \"url\": \"https://api.github.com/repos/preactjs/preact\",\n      \"forks_url\": \"https://api.github.com/repos/preactjs/preact/forks\",\n      \"keys_url\": \"https://api.github.com/repos/preactjs/preact/keys{/key_id}\",\n      \"collaborators_url\": \"https://api.github.com/repos/preactjs/preact/collaborators{/collaborator}\",\n      \"teams_url\": \"https://api.github.com/repos/preactjs/preact/teams\",\n      \"hooks_url\": \"https://api.github.com/repos/preactjs/preact/hooks\",\n      \"issue_events_url\": \"https://api.github.com/repos/preactjs/preact/issues/events{/number}\",\n      \"events_url\": \"https://api.github.com/repos/preactjs/preact/events\",\n      \"assignees_url\": \"https://api.github.com/repos/preactjs/preact/assignees{/user}\",\n      \"branches_url\": \"https://api.github.com/repos/preactjs/preact/branches{/branch}\",\n      \"tags_url\": \"https://api.github.com/repos/preactjs/preact/tags\",\n      \"blobs_url\": \"https://api.github.com/repos/preactjs/preact/git/blobs{/sha}\",\n      \"git_tags_url\": \"https://api.github.com/repos/preactjs/preact/git/tags{/sha}\",\n      \"git_refs_url\": \"https://api.github.com/repos/preactjs/preact/git/refs{/sha}\",\n      \"trees_url\": \"https://api.github.com/repos/preactjs/preact/git/trees{/sha}\",\n      \"statuses_url\": \"https://api.github.com/repos/preactjs/preact/statuses/{sha}\",\n      \"languages_url\": \"https://api.github.com/repos/preactjs/preact/languages\",\n      \"stargazers_url\": \"https://api.github.com/repos/preactjs/preact/stargazers\",\n      \"contributors_url\": \"https://api.github.com/repos/preactjs/preact/contributors\",\n      \"subscribers_url\": \"https://api.github.com/repos/preactjs/preact/subscribers\",\n      \"subscription_url\": \"https://api.github.com/repos/preactjs/preact/subscription\",\n      \"commits_url\": \"https://api.github.com/repos/preactjs/preact/commits{/sha}\",\n      \"git_commits_url\": \"https://api.github.com/repos/preactjs/preact/git/commits{/sha}\",\n      \"comments_url\": \"https://api.github.com/repos/preactjs/preact/comments{/number}\",\n      \"issue_comment_url\": \"https://api.github.com/repos/preactjs/preact/issues/comments{/number}\",\n      \"contents_url\": \"https://api.github.com/repos/preactjs/preact/contents/{+path}\",\n      \"compare_url\": \"https://api.github.com/repos/preactjs/preact/compare/{base}...{head}\",\n      \"merges_url\": \"https://api.github.com/repos/preactjs/preact/merges\",\n      \"archive_url\": \"https://api.github.com/repos/preactjs/preact/{archive_format}{/ref}\",\n      \"downloads_url\": \"https://api.github.com/repos/preactjs/preact/downloads\",\n      \"issues_url\": \"https://api.github.com/repos/preactjs/preact/issues{/number}\",\n      \"pulls_url\": \"https://api.github.com/repos/preactjs/preact/pulls{/number}\",\n      \"milestones_url\": \"https://api.github.com/repos/preactjs/preact/milestones{/number}\",\n      \"notifications_url\": \"https://api.github.com/repos/preactjs/preact/notifications{?since,all,participating}\",\n      \"labels_url\": \"https://api.github.com/repos/preactjs/preact/labels{/name}\",\n      \"releases_url\": \"https://api.github.com/repos/preactjs/preact/releases{/id}\",\n      \"deployments_url\": \"https://api.github.com/repos/preactjs/preact/deployments\",\n      \"created_at\": \"2015-09-11T02:40:18Z\",\n      \"updated_at\": \"2020-05-15T04:34:56Z\",\n      \"pushed_at\": \"2020-05-14T02:58:48Z\",\n      \"git_url\": \"git://github.com/preactjs/preact.git\",\n      \"ssh_url\": \"git@github.com:preactjs/preact.git\",\n      \"clone_url\": \"https://github.com/preactjs/preact.git\",\n      \"svn_url\": \"https://github.com/preactjs/preact\",\n      \"homepage\": \"https://preactjs.com\",\n      \"size\": 6574,\n      \"stargazers_count\": 26215,\n      \"watchers_count\": 26215,\n      \"language\": \"JavaScript\",\n      \"has_issues\": true,\n      \"has_projects\": true,\n      \"has_downloads\": true,\n      \"has_wiki\": true,\n      \"has_pages\": true,\n      \"forks_count\": 1428,\n      \"mirror_url\": null,\n      \"archived\": false,\n      \"disabled\": false,\n      \"open_issues_count\": 162,\n      \"license\": {\n        \"key\": \"mit\",\n        \"name\": \"MIT License\",\n        \"spdx_id\": \"MIT\",\n        \"url\": \"https://api.github.com/licenses/mit\",\n        \"node_id\": \"MDc6TGljZW5zZTEz\"\n      },\n      \"forks\": 1428,\n      \"open_issues\": 162,\n      \"watchers\": 26215,\n      \"default_branch\": \"master\",\n      \"score\": 1.0\n    },\n    {\n      \"id\": 91839306,\n      \"node_id\": \"MDEwOlJlcG9zaXRvcnk5MTgzOTMwNg==\",\n      \"name\": \"preact-cli\",\n      \"full_name\": \"preactjs/preact-cli\",\n      \"private\": false,\n      \"owner\": {\n        \"login\": \"preactjs\",\n        \"id\": 26872990,\n        \"node_id\": \"MDEyOk9yZ2FuaXphdGlvbjI2ODcyOTkw\",\n        \"avatar_url\": \"https://avatars3.githubusercontent.com/u/26872990?v=4\",\n        \"gravatar_id\": \"\",\n        \"url\": \"https://api.github.com/users/preactjs\",\n        \"html_url\": \"https://github.com/preactjs\",\n        \"followers_url\": \"https://api.github.com/users/preactjs/followers\",\n        \"following_url\": \"https://api.github.com/users/preactjs/following{/other_user}\",\n        \"gists_url\": \"https://api.github.com/users/preactjs/gists{/gist_id}\",\n        \"starred_url\": \"https://api.github.com/users/preactjs/starred{/owner}{/repo}\",\n        \"subscriptions_url\": \"https://api.github.com/users/preactjs/subscriptions\",\n        \"organizations_url\": \"https://api.github.com/users/preactjs/orgs\",\n        \"repos_url\": \"https://api.github.com/users/preactjs/repos\",\n        \"events_url\": \"https://api.github.com/users/preactjs/events{/privacy}\",\n        \"received_events_url\": \"https://api.github.com/users/preactjs/received_events\",\n        \"type\": \"Organization\",\n        \"site_admin\": false\n      },\n      \"html_url\": \"https://github.com/preactjs/preact-cli\",\n      \"description\": \"😺 Your next Preact PWA starts in 30 seconds.\",\n      \"fork\": false,\n      \"url\": \"https://api.github.com/repos/preactjs/preact-cli\",\n      \"forks_url\": \"https://api.github.com/repos/preactjs/preact-cli/forks\",\n      \"keys_url\": \"https://api.github.com/repos/preactjs/preact-cli/keys{/key_id}\",\n      \"collaborators_url\": \"https://api.github.com/repos/preactjs/preact-cli/collaborators{/collaborator}\",\n      \"teams_url\": \"https://api.github.com/repos/preactjs/preact-cli/teams\",\n      \"hooks_url\": \"https://api.github.com/repos/preactjs/preact-cli/hooks\",\n      \"issue_events_url\": \"https://api.github.com/repos/preactjs/preact-cli/issues/events{/number}\",\n      \"events_url\": \"https://api.github.com/repos/preactjs/preact-cli/events\",\n      \"assignees_url\": \"https://api.github.com/repos/preactjs/preact-cli/assignees{/user}\",\n      \"branches_url\": \"https://api.github.com/repos/preactjs/preact-cli/branches{/branch}\",\n      \"tags_url\": \"https://api.github.com/repos/preactjs/preact-cli/tags\",\n      \"blobs_url\": \"https://api.github.com/repos/preactjs/preact-cli/git/blobs{/sha}\",\n      \"git_tags_url\": \"https://api.github.com/repos/preactjs/preact-cli/git/tags{/sha}\",\n      \"git_refs_url\": \"https://api.github.com/repos/preactjs/preact-cli/git/refs{/sha}\",\n      \"trees_url\": \"https://api.github.com/repos/preactjs/preact-cli/git/trees{/sha}\",\n      \"statuses_url\": \"https://api.github.com/repos/preactjs/preact-cli/statuses/{sha}\",\n      \"languages_url\": \"https://api.github.com/repos/preactjs/preact-cli/languages\",\n      \"stargazers_url\": \"https://api.github.com/repos/preactjs/preact-cli/stargazers\",\n      \"contributors_url\": \"https://api.github.com/repos/preactjs/preact-cli/contributors\",\n      \"subscribers_url\": \"https://api.github.com/repos/preactjs/preact-cli/subscribers\",\n      \"subscription_url\": \"https://api.github.com/repos/preactjs/preact-cli/subscription\",\n      \"commits_url\": \"https://api.github.com/repos/preactjs/preact-cli/commits{/sha}\",\n      \"git_commits_url\": \"https://api.github.com/repos/preactjs/preact-cli/git/commits{/sha}\",\n      \"comments_url\": \"https://api.github.com/repos/preactjs/preact-cli/comments{/number}\",\n      \"issue_comment_url\": \"https://api.github.com/repos/preactjs/preact-cli/issues/comments{/number}\",\n      \"contents_url\": \"https://api.github.com/repos/preactjs/preact-cli/contents/{+path}\",\n      \"compare_url\": \"https://api.github.com/repos/preactjs/preact-cli/compare/{base}...{head}\",\n      \"merges_url\": \"https://api.github.com/repos/preactjs/preact-cli/merges\",\n      \"archive_url\": \"https://api.github.com/repos/preactjs/preact-cli/{archive_format}{/ref}\",\n      \"downloads_url\": \"https://api.github.com/repos/preactjs/preact-cli/downloads\",\n      \"issues_url\": \"https://api.github.com/repos/preactjs/preact-cli/issues{/number}\",\n      \"pulls_url\": \"https://api.github.com/repos/preactjs/preact-cli/pulls{/number}\",\n      \"milestones_url\": \"https://api.github.com/repos/preactjs/preact-cli/milestones{/number}\",\n      \"notifications_url\": \"https://api.github.com/repos/preactjs/preact-cli/notifications{?since,all,participating}\",\n      \"labels_url\": \"https://api.github.com/repos/preactjs/preact-cli/labels{/name}\",\n      \"releases_url\": \"https://api.github.com/repos/preactjs/preact-cli/releases{/id}\",\n      \"deployments_url\": \"https://api.github.com/repos/preactjs/preact-cli/deployments\",\n      \"created_at\": \"2017-05-19T19:34:36Z\",\n      \"updated_at\": \"2020-05-14T16:27:47Z\",\n      \"pushed_at\": \"2020-05-14T15:23:10Z\",\n      \"git_url\": \"git://github.com/preactjs/preact-cli.git\",\n      \"ssh_url\": \"git@github.com:preactjs/preact-cli.git\",\n      \"clone_url\": \"https://github.com/preactjs/preact-cli.git\",\n      \"svn_url\": \"https://github.com/preactjs/preact-cli\",\n      \"homepage\": \"https://cli-demo-next.preactjs.com\",\n      \"size\": 6479,\n      \"stargazers_count\": 4143,\n      \"watchers_count\": 4143,\n      \"language\": \"JavaScript\",\n      \"has_issues\": true,\n      \"has_projects\": true,\n      \"has_downloads\": true,\n      \"has_wiki\": true,\n      \"has_pages\": false,\n      \"forks_count\": 344,\n      \"mirror_url\": null,\n      \"archived\": false,\n      \"disabled\": false,\n      \"open_issues_count\": 112,\n      \"license\": {\n        \"key\": \"mit\",\n        \"name\": \"MIT License\",\n        \"spdx_id\": \"MIT\",\n        \"url\": \"https://api.github.com/licenses/mit\",\n        \"node_id\": \"MDc6TGljZW5zZTEz\"\n      },\n      \"forks\": 344,\n      \"open_issues\": 112,\n      \"watchers\": 4143,\n      \"default_branch\": \"master\",\n      \"score\": 1.0\n    },\n    {\n      \"id\": 55373335,\n      \"node_id\": \"MDEwOlJlcG9zaXRvcnk1NTM3MzMzNQ==\",\n      \"name\": \"preact-www\",\n      \"full_name\": \"preactjs/preact-www\",\n      \"private\": false,\n      \"owner\": {\n        \"login\": \"preactjs\",\n        \"id\": 26872990,\n        \"node_id\": \"MDEyOk9yZ2FuaXphdGlvbjI2ODcyOTkw\",\n        \"avatar_url\": \"https://avatars3.githubusercontent.com/u/26872990?v=4\",\n        \"gravatar_id\": \"\",\n        \"url\": \"https://api.github.com/users/preactjs\",\n        \"html_url\": \"https://github.com/preactjs\",\n        \"followers_url\": \"https://api.github.com/users/preactjs/followers\",\n        \"following_url\": \"https://api.github.com/users/preactjs/following{/other_user}\",\n        \"gists_url\": \"https://api.github.com/users/preactjs/gists{/gist_id}\",\n        \"starred_url\": \"https://api.github.com/users/preactjs/starred{/owner}{/repo}\",\n        \"subscriptions_url\": \"https://api.github.com/users/preactjs/subscriptions\",\n        \"organizations_url\": \"https://api.github.com/users/preactjs/orgs\",\n        \"repos_url\": \"https://api.github.com/users/preactjs/repos\",\n        \"events_url\": \"https://api.github.com/users/preactjs/events{/privacy}\",\n        \"received_events_url\": \"https://api.github.com/users/preactjs/received_events\",\n        \"type\": \"Organization\",\n        \"site_admin\": false\n      },\n      \"html_url\": \"https://github.com/preactjs/preact-www\",\n      \"description\": \":book: Preact documentation website.\",\n      \"fork\": false,\n      \"url\": \"https://api.github.com/repos/preactjs/preact-www\",\n      \"forks_url\": \"https://api.github.com/repos/preactjs/preact-www/forks\",\n      \"keys_url\": \"https://api.github.com/repos/preactjs/preact-www/keys{/key_id}\",\n      \"collaborators_url\": \"https://api.github.com/repos/preactjs/preact-www/collaborators{/collaborator}\",\n      \"teams_url\": \"https://api.github.com/repos/preactjs/preact-www/teams\",\n      \"hooks_url\": \"https://api.github.com/repos/preactjs/preact-www/hooks\",\n      \"issue_events_url\": \"https://api.github.com/repos/preactjs/preact-www/issues/events{/number}\",\n      \"events_url\": \"https://api.github.com/repos/preactjs/preact-www/events\",\n      \"assignees_url\": \"https://api.github.com/repos/preactjs/preact-www/assignees{/user}\",\n      \"branches_url\": \"https://api.github.com/repos/preactjs/preact-www/branches{/branch}\",\n      \"tags_url\": \"https://api.github.com/repos/preactjs/preact-www/tags\",\n      \"blobs_url\": \"https://api.github.com/repos/preactjs/preact-www/git/blobs{/sha}\",\n      \"git_tags_url\": \"https://api.github.com/repos/preactjs/preact-www/git/tags{/sha}\",\n      \"git_refs_url\": \"https://api.github.com/repos/preactjs/preact-www/git/refs{/sha}\",\n      \"trees_url\": \"https://api.github.com/repos/preactjs/preact-www/git/trees{/sha}\",\n      \"statuses_url\": \"https://api.github.com/repos/preactjs/preact-www/statuses/{sha}\",\n      \"languages_url\": \"https://api.github.com/repos/preactjs/preact-www/languages\",\n      \"stargazers_url\": \"https://api.github.com/repos/preactjs/preact-www/stargazers\",\n      \"contributors_url\": \"https://api.github.com/repos/preactjs/preact-www/contributors\",\n      \"subscribers_url\": \"https://api.github.com/repos/preactjs/preact-www/subscribers\",\n      \"subscription_url\": \"https://api.github.com/repos/preactjs/preact-www/subscription\",\n      \"commits_url\": \"https://api.github.com/repos/preactjs/preact-www/commits{/sha}\",\n      \"git_commits_url\": \"https://api.github.com/repos/preactjs/preact-www/git/commits{/sha}\",\n      \"comments_url\": \"https://api.github.com/repos/preactjs/preact-www/comments{/number}\",\n      \"issue_comment_url\": \"https://api.github.com/repos/preactjs/preact-www/issues/comments{/number}\",\n      \"contents_url\": \"https://api.github.com/repos/preactjs/preact-www/contents/{+path}\",\n      \"compare_url\": \"https://api.github.com/repos/preactjs/preact-www/compare/{base}...{head}\",\n      \"merges_url\": \"https://api.github.com/repos/preactjs/preact-www/merges\",\n      \"archive_url\": \"https://api.github.com/repos/preactjs/preact-www/{archive_format}{/ref}\",\n      \"downloads_url\": \"https://api.github.com/repos/preactjs/preact-www/downloads\",\n      \"issues_url\": \"https://api.github.com/repos/preactjs/preact-www/issues{/number}\",\n      \"pulls_url\": \"https://api.github.com/repos/preactjs/preact-www/pulls{/number}\",\n      \"milestones_url\": \"https://api.github.com/repos/preactjs/preact-www/milestones{/number}\",\n      \"notifications_url\": \"https://api.github.com/repos/preactjs/preact-www/notifications{?since,all,participating}\",\n      \"labels_url\": \"https://api.github.com/repos/preactjs/preact-www/labels{/name}\",\n      \"releases_url\": \"https://api.github.com/repos/preactjs/preact-www/releases{/id}\",\n      \"deployments_url\": \"https://api.github.com/repos/preactjs/preact-www/deployments\",\n      \"created_at\": \"2016-04-03T23:00:51Z\",\n      \"updated_at\": \"2020-05-14T21:10:20Z\",\n      \"pushed_at\": \"2020-05-14T23:37:26Z\",\n      \"git_url\": \"git://github.com/preactjs/preact-www.git\",\n      \"ssh_url\": \"git@github.com:preactjs/preact-www.git\",\n      \"clone_url\": \"https://github.com/preactjs/preact-www.git\",\n      \"svn_url\": \"https://github.com/preactjs/preact-www\",\n      \"homepage\": \"https://preactjs.com\",\n      \"size\": 4959,\n      \"stargazers_count\": 247,\n      \"watchers_count\": 247,\n      \"language\": \"JavaScript\",\n      \"has_issues\": true,\n      \"has_projects\": true,\n      \"has_downloads\": true,\n      \"has_wiki\": false,\n      \"has_pages\": false,\n      \"forks_count\": 342,\n      \"mirror_url\": null,\n      \"archived\": false,\n      \"disabled\": false,\n      \"open_issues_count\": 44,\n      \"license\": {\n        \"key\": \"mit\",\n        \"name\": \"MIT License\",\n        \"spdx_id\": \"MIT\",\n        \"url\": \"https://api.github.com/licenses/mit\",\n        \"node_id\": \"MDc6TGljZW5zZTEz\"\n      },\n      \"forks\": 342,\n      \"open_issues\": 44,\n      \"watchers\": 247,\n      \"default_branch\": \"master\",\n      \"score\": 1.0\n    },\n    {\n      \"id\": 49995432,\n      \"node_id\": \"MDEwOlJlcG9zaXRvcnk0OTk5NTQzMg==\",\n      \"name\": \"preact-boilerplate\",\n      \"full_name\": \"developit/preact-boilerplate\",\n      \"private\": false,\n      \"owner\": {\n        \"login\": \"developit\",\n        \"id\": 105127,\n        \"node_id\": \"MDQ6VXNlcjEwNTEyNw==\",\n        \"avatar_url\": \"https://avatars2.githubusercontent.com/u/105127?v=4\",\n        \"gravatar_id\": \"\",\n        \"url\": \"https://api.github.com/users/developit\",\n        \"html_url\": \"https://github.com/developit\",\n        \"followers_url\": \"https://api.github.com/users/developit/followers\",\n        \"following_url\": \"https://api.github.com/users/developit/following{/other_user}\",\n        \"gists_url\": \"https://api.github.com/users/developit/gists{/gist_id}\",\n        \"starred_url\": \"https://api.github.com/users/developit/starred{/owner}{/repo}\",\n        \"subscriptions_url\": \"https://api.github.com/users/developit/subscriptions\",\n        \"organizations_url\": \"https://api.github.com/users/developit/orgs\",\n        \"repos_url\": \"https://api.github.com/users/developit/repos\",\n        \"events_url\": \"https://api.github.com/users/developit/events{/privacy}\",\n        \"received_events_url\": \"https://api.github.com/users/developit/received_events\",\n        \"type\": \"User\",\n        \"site_admin\": false\n      },\n      \"html_url\": \"https://github.com/developit/preact-boilerplate\",\n      \"description\": \":guitar: Ready-to-rock Preact starter project, powered by Webpack.\",\n      \"fork\": false,\n      \"url\": \"https://api.github.com/repos/developit/preact-boilerplate\",\n      \"forks_url\": \"https://api.github.com/repos/developit/preact-boilerplate/forks\",\n      \"keys_url\": \"https://api.github.com/repos/developit/preact-boilerplate/keys{/key_id}\",\n      \"collaborators_url\": \"https://api.github.com/repos/developit/preact-boilerplate/collaborators{/collaborator}\",\n      \"teams_url\": \"https://api.github.com/repos/developit/preact-boilerplate/teams\",\n      \"hooks_url\": \"https://api.github.com/repos/developit/preact-boilerplate/hooks\",\n      \"issue_events_url\": \"https://api.github.com/repos/developit/preact-boilerplate/issues/events{/number}\",\n      \"events_url\": \"https://api.github.com/repos/developit/preact-boilerplate/events\",\n      \"assignees_url\": \"https://api.github.com/repos/developit/preact-boilerplate/assignees{/user}\",\n      \"branches_url\": \"https://api.github.com/repos/developit/preact-boilerplate/branches{/branch}\",\n      \"tags_url\": \"https://api.github.com/repos/developit/preact-boilerplate/tags\",\n      \"blobs_url\": \"https://api.github.com/repos/developit/preact-boilerplate/git/blobs{/sha}\",\n      \"git_tags_url\": \"https://api.github.com/repos/developit/preact-boilerplate/git/tags{/sha}\",\n      \"git_refs_url\": \"https://api.github.com/repos/developit/preact-boilerplate/git/refs{/sha}\",\n      \"trees_url\": \"https://api.github.com/repos/developit/preact-boilerplate/git/trees{/sha}\",\n      \"statuses_url\": \"https://api.github.com/repos/developit/preact-boilerplate/statuses/{sha}\",\n      \"languages_url\": \"https://api.github.com/repos/developit/preact-boilerplate/languages\",\n      \"stargazers_url\": \"https://api.github.com/repos/developit/preact-boilerplate/stargazers\",\n      \"contributors_url\": \"https://api.github.com/repos/developit/preact-boilerplate/contributors\",\n      \"subscribers_url\": \"https://api.github.com/repos/developit/preact-boilerplate/subscribers\",\n      \"subscription_url\": \"https://api.github.com/repos/developit/preact-boilerplate/subscription\",\n      \"commits_url\": \"https://api.github.com/repos/developit/preact-boilerplate/commits{/sha}\",\n      \"git_commits_url\": \"https://api.github.com/repos/developit/preact-boilerplate/git/commits{/sha}\",\n      \"comments_url\": \"https://api.github.com/repos/developit/preact-boilerplate/comments{/number}\",\n      \"issue_comment_url\": \"https://api.github.com/repos/developit/preact-boilerplate/issues/comments{/number}\",\n      \"contents_url\": \"https://api.github.com/repos/developit/preact-boilerplate/contents/{+path}\",\n      \"compare_url\": \"https://api.github.com/repos/developit/preact-boilerplate/compare/{base}...{head}\",\n      \"merges_url\": \"https://api.github.com/repos/developit/preact-boilerplate/merges\",\n      \"archive_url\": \"https://api.github.com/repos/developit/preact-boilerplate/{archive_format}{/ref}\",\n      \"downloads_url\": \"https://api.github.com/repos/developit/preact-boilerplate/downloads\",\n      \"issues_url\": \"https://api.github.com/repos/developit/preact-boilerplate/issues{/number}\",\n      \"pulls_url\": \"https://api.github.com/repos/developit/preact-boilerplate/pulls{/number}\",\n      \"milestones_url\": \"https://api.github.com/repos/developit/preact-boilerplate/milestones{/number}\",\n      \"notifications_url\": \"https://api.github.com/repos/developit/preact-boilerplate/notifications{?since,all,participating}\",\n      \"labels_url\": \"https://api.github.com/repos/developit/preact-boilerplate/labels{/name}\",\n      \"releases_url\": \"https://api.github.com/repos/developit/preact-boilerplate/releases{/id}\",\n      \"deployments_url\": \"https://api.github.com/repos/developit/preact-boilerplate/deployments\",\n      \"created_at\": \"2016-01-20T01:27:33Z\",\n      \"updated_at\": \"2020-05-10T04:15:21Z\",\n      \"pushed_at\": \"2020-05-13T04:01:56Z\",\n      \"git_url\": \"git://github.com/developit/preact-boilerplate.git\",\n      \"ssh_url\": \"git@github.com:developit/preact-boilerplate.git\",\n      \"clone_url\": \"https://github.com/developit/preact-boilerplate.git\",\n      \"svn_url\": \"https://github.com/developit/preact-boilerplate\",\n      \"homepage\": \"https://preact-boilerplate.surge.sh\",\n      \"size\": 472,\n      \"stargazers_count\": 941,\n      \"watchers_count\": 941,\n      \"language\": \"JavaScript\",\n      \"has_issues\": true,\n      \"has_projects\": true,\n      \"has_downloads\": true,\n      \"has_wiki\": true,\n      \"has_pages\": false,\n      \"forks_count\": 193,\n      \"mirror_url\": null,\n      \"archived\": false,\n      \"disabled\": false,\n      \"open_issues_count\": 34,\n      \"license\": null,\n      \"forks\": 193,\n      \"open_issues\": 34,\n      \"watchers\": 941,\n      \"default_branch\": \"master\",\n      \"score\": 1.0\n    },\n    {\n      \"id\": 45793760,\n      \"node_id\": \"MDEwOlJlcG9zaXRvcnk0NTc5Mzc2MA==\",\n      \"name\": \"preact-compat\",\n      \"full_name\": \"preactjs/preact-compat\",\n      \"private\": false,\n      \"owner\": {\n        \"login\": \"preactjs\",\n        \"id\": 26872990,\n        \"node_id\": \"MDEyOk9yZ2FuaXphdGlvbjI2ODcyOTkw\",\n        \"avatar_url\": \"https://avatars3.githubusercontent.com/u/26872990?v=4\",\n        \"gravatar_id\": \"\",\n        \"url\": \"https://api.github.com/users/preactjs\",\n        \"html_url\": \"https://github.com/preactjs\",\n        \"followers_url\": \"https://api.github.com/users/preactjs/followers\",\n        \"following_url\": \"https://api.github.com/users/preactjs/following{/other_user}\",\n        \"gists_url\": \"https://api.github.com/users/preactjs/gists{/gist_id}\",\n        \"starred_url\": \"https://api.github.com/users/preactjs/starred{/owner}{/repo}\",\n        \"subscriptions_url\": \"https://api.github.com/users/preactjs/subscriptions\",\n        \"organizations_url\": \"https://api.github.com/users/preactjs/orgs\",\n        \"repos_url\": \"https://api.github.com/users/preactjs/repos\",\n        \"events_url\": \"https://api.github.com/users/preactjs/events{/privacy}\",\n        \"received_events_url\": \"https://api.github.com/users/preactjs/received_events\",\n        \"type\": \"Organization\",\n        \"site_admin\": false\n      },\n      \"html_url\": \"https://github.com/preactjs/preact-compat\",\n      \"description\": \":raised_hands: React compatibility layer for Preact.\",\n      \"fork\": false,\n      \"url\": \"https://api.github.com/repos/preactjs/preact-compat\",\n      \"forks_url\": \"https://api.github.com/repos/preactjs/preact-compat/forks\",\n      \"keys_url\": \"https://api.github.com/repos/preactjs/preact-compat/keys{/key_id}\",\n      \"collaborators_url\": \"https://api.github.com/repos/preactjs/preact-compat/collaborators{/collaborator}\",\n      \"teams_url\": \"https://api.github.com/repos/preactjs/preact-compat/teams\",\n      \"hooks_url\": \"https://api.github.com/repos/preactjs/preact-compat/hooks\",\n      \"issue_events_url\": \"https://api.github.com/repos/preactjs/preact-compat/issues/events{/number}\",\n      \"events_url\": \"https://api.github.com/repos/preactjs/preact-compat/events\",\n      \"assignees_url\": \"https://api.github.com/repos/preactjs/preact-compat/assignees{/user}\",\n      \"branches_url\": \"https://api.github.com/repos/preactjs/preact-compat/branches{/branch}\",\n      \"tags_url\": \"https://api.github.com/repos/preactjs/preact-compat/tags\",\n      \"blobs_url\": \"https://api.github.com/repos/preactjs/preact-compat/git/blobs{/sha}\",\n      \"git_tags_url\": \"https://api.github.com/repos/preactjs/preact-compat/git/tags{/sha}\",\n      \"git_refs_url\": \"https://api.github.com/repos/preactjs/preact-compat/git/refs{/sha}\",\n      \"trees_url\": \"https://api.github.com/repos/preactjs/preact-compat/git/trees{/sha}\",\n      \"statuses_url\": \"https://api.github.com/repos/preactjs/preact-compat/statuses/{sha}\",\n      \"languages_url\": \"https://api.github.com/repos/preactjs/preact-compat/languages\",\n      \"stargazers_url\": \"https://api.github.com/repos/preactjs/preact-compat/stargazers\",\n      \"contributors_url\": \"https://api.github.com/repos/preactjs/preact-compat/contributors\",\n      \"subscribers_url\": \"https://api.github.com/repos/preactjs/preact-compat/subscribers\",\n      \"subscription_url\": \"https://api.github.com/repos/preactjs/preact-compat/subscription\",\n      \"commits_url\": \"https://api.github.com/repos/preactjs/preact-compat/commits{/sha}\",\n      \"git_commits_url\": \"https://api.github.com/repos/preactjs/preact-compat/git/commits{/sha}\",\n      \"comments_url\": \"https://api.github.com/repos/preactjs/preact-compat/comments{/number}\",\n      \"issue_comment_url\": \"https://api.github.com/repos/preactjs/preact-compat/issues/comments{/number}\",\n      \"contents_url\": \"https://api.github.com/repos/preactjs/preact-compat/contents/{+path}\",\n      \"compare_url\": \"https://api.github.com/repos/preactjs/preact-compat/compare/{base}...{head}\",\n      \"merges_url\": \"https://api.github.com/repos/preactjs/preact-compat/merges\",\n      \"archive_url\": \"https://api.github.com/repos/preactjs/preact-compat/{archive_format}{/ref}\",\n      \"downloads_url\": \"https://api.github.com/repos/preactjs/preact-compat/downloads\",\n      \"issues_url\": \"https://api.github.com/repos/preactjs/preact-compat/issues{/number}\",\n      \"pulls_url\": \"https://api.github.com/repos/preactjs/preact-compat/pulls{/number}\",\n      \"milestones_url\": \"https://api.github.com/repos/preactjs/preact-compat/milestones{/number}\",\n      \"notifications_url\": \"https://api.github.com/repos/preactjs/preact-compat/notifications{?since,all,participating}\",\n      \"labels_url\": \"https://api.github.com/repos/preactjs/preact-compat/labels{/name}\",\n      \"releases_url\": \"https://api.github.com/repos/preactjs/preact-compat/releases{/id}\",\n      \"deployments_url\": \"https://api.github.com/repos/preactjs/preact-compat/deployments\",\n      \"created_at\": \"2015-11-08T18:47:28Z\",\n      \"updated_at\": \"2020-05-10T15:45:50Z\",\n      \"pushed_at\": \"2020-03-06T12:28:17Z\",\n      \"git_url\": \"git://github.com/preactjs/preact-compat.git\",\n      \"ssh_url\": \"git@github.com:preactjs/preact-compat.git\",\n      \"clone_url\": \"https://github.com/preactjs/preact-compat.git\",\n      \"svn_url\": \"https://github.com/preactjs/preact-compat\",\n      \"homepage\": \"http://npm.im/preact-compat\",\n      \"size\": 283,\n      \"stargazers_count\": 875,\n      \"watchers_count\": 875,\n      \"language\": \"JavaScript\",\n      \"has_issues\": true,\n      \"has_projects\": true,\n      \"has_downloads\": true,\n      \"has_wiki\": true,\n      \"has_pages\": false,\n      \"forks_count\": 139,\n      \"mirror_url\": null,\n      \"archived\": false,\n      \"disabled\": false,\n      \"open_issues_count\": 47,\n      \"license\": {\n        \"key\": \"mit\",\n        \"name\": \"MIT License\",\n        \"spdx_id\": \"MIT\",\n        \"url\": \"https://api.github.com/licenses/mit\",\n        \"node_id\": \"MDc6TGljZW5zZTEz\"\n      },\n      \"forks\": 139,\n      \"open_issues\": 47,\n      \"watchers\": 875,\n      \"default_branch\": \"master\",\n      \"score\": 1.0\n    },\n    {\n      \"id\": 46458028,\n      \"node_id\": \"MDEwOlJlcG9zaXRvcnk0NjQ1ODAyOA==\",\n      \"name\": \"preact-router\",\n      \"full_name\": \"preactjs/preact-router\",\n      \"private\": false,\n      \"owner\": {\n        \"login\": \"preactjs\",\n        \"id\": 26872990,\n        \"node_id\": \"MDEyOk9yZ2FuaXphdGlvbjI2ODcyOTkw\",\n        \"avatar_url\": \"https://avatars3.githubusercontent.com/u/26872990?v=4\",\n        \"gravatar_id\": \"\",\n        \"url\": \"https://api.github.com/users/preactjs\",\n        \"html_url\": \"https://github.com/preactjs\",\n        \"followers_url\": \"https://api.github.com/users/preactjs/followers\",\n        \"following_url\": \"https://api.github.com/users/preactjs/following{/other_user}\",\n        \"gists_url\": \"https://api.github.com/users/preactjs/gists{/gist_id}\",\n        \"starred_url\": \"https://api.github.com/users/preactjs/starred{/owner}{/repo}\",\n        \"subscriptions_url\": \"https://api.github.com/users/preactjs/subscriptions\",\n        \"organizations_url\": \"https://api.github.com/users/preactjs/orgs\",\n        \"repos_url\": \"https://api.github.com/users/preactjs/repos\",\n        \"events_url\": \"https://api.github.com/users/preactjs/events{/privacy}\",\n        \"received_events_url\": \"https://api.github.com/users/preactjs/received_events\",\n        \"type\": \"Organization\",\n        \"site_admin\": false\n      },\n      \"html_url\": \"https://github.com/preactjs/preact-router\",\n      \"description\": \":earth_americas: URL router for Preact.\",\n      \"fork\": false,\n      \"url\": \"https://api.github.com/repos/preactjs/preact-router\",\n      \"forks_url\": \"https://api.github.com/repos/preactjs/preact-router/forks\",\n      \"keys_url\": \"https://api.github.com/repos/preactjs/preact-router/keys{/key_id}\",\n      \"collaborators_url\": \"https://api.github.com/repos/preactjs/preact-router/collaborators{/collaborator}\",\n      \"teams_url\": \"https://api.github.com/repos/preactjs/preact-router/teams\",\n      \"hooks_url\": \"https://api.github.com/repos/preactjs/preact-router/hooks\",\n      \"issue_events_url\": \"https://api.github.com/repos/preactjs/preact-router/issues/events{/number}\",\n      \"events_url\": \"https://api.github.com/repos/preactjs/preact-router/events\",\n      \"assignees_url\": \"https://api.github.com/repos/preactjs/preact-router/assignees{/user}\",\n      \"branches_url\": \"https://api.github.com/repos/preactjs/preact-router/branches{/branch}\",\n      \"tags_url\": \"https://api.github.com/repos/preactjs/preact-router/tags\",\n      \"blobs_url\": \"https://api.github.com/repos/preactjs/preact-router/git/blobs{/sha}\",\n      \"git_tags_url\": \"https://api.github.com/repos/preactjs/preact-router/git/tags{/sha}\",\n      \"git_refs_url\": \"https://api.github.com/repos/preactjs/preact-router/git/refs{/sha}\",\n      \"trees_url\": \"https://api.github.com/repos/preactjs/preact-router/git/trees{/sha}\",\n      \"statuses_url\": \"https://api.github.com/repos/preactjs/preact-router/statuses/{sha}\",\n      \"languages_url\": \"https://api.github.com/repos/preactjs/preact-router/languages\",\n      \"stargazers_url\": \"https://api.github.com/repos/preactjs/preact-router/stargazers\",\n      \"contributors_url\": \"https://api.github.com/repos/preactjs/preact-router/contributors\",\n      \"subscribers_url\": \"https://api.github.com/repos/preactjs/preact-router/subscribers\",\n      \"subscription_url\": \"https://api.github.com/repos/preactjs/preact-router/subscription\",\n      \"commits_url\": \"https://api.github.com/repos/preactjs/preact-router/commits{/sha}\",\n      \"git_commits_url\": \"https://api.github.com/repos/preactjs/preact-router/git/commits{/sha}\",\n      \"comments_url\": \"https://api.github.com/repos/preactjs/preact-router/comments{/number}\",\n      \"issue_comment_url\": \"https://api.github.com/repos/preactjs/preact-router/issues/comments{/number}\",\n      \"contents_url\": \"https://api.github.com/repos/preactjs/preact-router/contents/{+path}\",\n      \"compare_url\": \"https://api.github.com/repos/preactjs/preact-router/compare/{base}...{head}\",\n      \"merges_url\": \"https://api.github.com/repos/preactjs/preact-router/merges\",\n      \"archive_url\": \"https://api.github.com/repos/preactjs/preact-router/{archive_format}{/ref}\",\n      \"downloads_url\": \"https://api.github.com/repos/preactjs/preact-router/downloads\",\n      \"issues_url\": \"https://api.github.com/repos/preactjs/preact-router/issues{/number}\",\n      \"pulls_url\": \"https://api.github.com/repos/preactjs/preact-router/pulls{/number}\",\n      \"milestones_url\": \"https://api.github.com/repos/preactjs/preact-router/milestones{/number}\",\n      \"notifications_url\": \"https://api.github.com/repos/preactjs/preact-router/notifications{?since,all,participating}\",\n      \"labels_url\": \"https://api.github.com/repos/preactjs/preact-router/labels{/name}\",\n      \"releases_url\": \"https://api.github.com/repos/preactjs/preact-router/releases{/id}\",\n      \"deployments_url\": \"https://api.github.com/repos/preactjs/preact-router/deployments\",\n      \"created_at\": \"2015-11-19T01:04:24Z\",\n      \"updated_at\": \"2020-05-14T17:03:55Z\",\n      \"pushed_at\": \"2020-04-08T06:49:53Z\",\n      \"git_url\": \"git://github.com/preactjs/preact-router.git\",\n      \"ssh_url\": \"git@github.com:preactjs/preact-router.git\",\n      \"clone_url\": \"https://github.com/preactjs/preact-router.git\",\n      \"svn_url\": \"https://github.com/preactjs/preact-router\",\n      \"homepage\": \"http://npm.im/preact-router\",\n      \"size\": 626,\n      \"stargazers_count\": 691,\n      \"watchers_count\": 691,\n      \"language\": \"JavaScript\",\n      \"has_issues\": true,\n      \"has_projects\": false,\n      \"has_downloads\": true,\n      \"has_wiki\": false,\n      \"has_pages\": false,\n      \"forks_count\": 131,\n      \"mirror_url\": null,\n      \"archived\": false,\n      \"disabled\": false,\n      \"open_issues_count\": 69,\n      \"license\": {\n        \"key\": \"mit\",\n        \"name\": \"MIT License\",\n        \"spdx_id\": \"MIT\",\n        \"url\": \"https://api.github.com/licenses/mit\",\n        \"node_id\": \"MDc6TGljZW5zZTEz\"\n      },\n      \"forks\": 131,\n      \"open_issues\": 69,\n      \"watchers\": 691,\n      \"default_branch\": \"master\",\n      \"score\": 1.0\n    },\n    {\n      \"id\": 82581631,\n      \"node_id\": \"MDEwOlJlcG9zaXRvcnk4MjU4MTYzMQ==\",\n      \"name\": \"preact-material-components\",\n      \"full_name\": \"prateekbh/preact-material-components\",\n      \"private\": false,\n      \"owner\": {\n        \"login\": \"prateekbh\",\n        \"id\": 5960497,\n        \"node_id\": \"MDQ6VXNlcjU5NjA0OTc=\",\n        \"avatar_url\": \"https://avatars2.githubusercontent.com/u/5960497?v=4\",\n        \"gravatar_id\": \"\",\n        \"url\": \"https://api.github.com/users/prateekbh\",\n        \"html_url\": \"https://github.com/prateekbh\",\n        \"followers_url\": \"https://api.github.com/users/prateekbh/followers\",\n        \"following_url\": \"https://api.github.com/users/prateekbh/following{/other_user}\",\n        \"gists_url\": \"https://api.github.com/users/prateekbh/gists{/gist_id}\",\n        \"starred_url\": \"https://api.github.com/users/prateekbh/starred{/owner}{/repo}\",\n        \"subscriptions_url\": \"https://api.github.com/users/prateekbh/subscriptions\",\n        \"organizations_url\": \"https://api.github.com/users/prateekbh/orgs\",\n        \"repos_url\": \"https://api.github.com/users/prateekbh/repos\",\n        \"events_url\": \"https://api.github.com/users/prateekbh/events{/privacy}\",\n        \"received_events_url\": \"https://api.github.com/users/prateekbh/received_events\",\n        \"type\": \"User\",\n        \"site_admin\": false\n      },\n      \"html_url\": \"https://github.com/prateekbh/preact-material-components\",\n      \"description\": \"preact wrapper for \\\"Material Components for the web\\\"\",\n      \"fork\": false,\n      \"url\": \"https://api.github.com/repos/prateekbh/preact-material-components\",\n      \"forks_url\": \"https://api.github.com/repos/prateekbh/preact-material-components/forks\",\n      \"keys_url\": \"https://api.github.com/repos/prateekbh/preact-material-components/keys{/key_id}\",\n      \"collaborators_url\": \"https://api.github.com/repos/prateekbh/preact-material-components/collaborators{/collaborator}\",\n      \"teams_url\": \"https://api.github.com/repos/prateekbh/preact-material-components/teams\",\n      \"hooks_url\": \"https://api.github.com/repos/prateekbh/preact-material-components/hooks\",\n      \"issue_events_url\": \"https://api.github.com/repos/prateekbh/preact-material-components/issues/events{/number}\",\n      \"events_url\": \"https://api.github.com/repos/prateekbh/preact-material-components/events\",\n      \"assignees_url\": \"https://api.github.com/repos/prateekbh/preact-material-components/assignees{/user}\",\n      \"branches_url\": \"https://api.github.com/repos/prateekbh/preact-material-components/branches{/branch}\",\n      \"tags_url\": \"https://api.github.com/repos/prateekbh/preact-material-components/tags\",\n      \"blobs_url\": \"https://api.github.com/repos/prateekbh/preact-material-components/git/blobs{/sha}\",\n      \"git_tags_url\": \"https://api.github.com/repos/prateekbh/preact-material-components/git/tags{/sha}\",\n      \"git_refs_url\": \"https://api.github.com/repos/prateekbh/preact-material-components/git/refs{/sha}\",\n      \"trees_url\": \"https://api.github.com/repos/prateekbh/preact-material-components/git/trees{/sha}\",\n      \"statuses_url\": \"https://api.github.com/repos/prateekbh/preact-material-components/statuses/{sha}\",\n      \"languages_url\": \"https://api.github.com/repos/prateekbh/preact-material-components/languages\",\n      \"stargazers_url\": \"https://api.github.com/repos/prateekbh/preact-material-components/stargazers\",\n      \"contributors_url\": \"https://api.github.com/repos/prateekbh/preact-material-components/contributors\",\n      \"subscribers_url\": \"https://api.github.com/repos/prateekbh/preact-material-components/subscribers\",\n      \"subscription_url\": \"https://api.github.com/repos/prateekbh/preact-material-components/subscription\",\n      \"commits_url\": \"https://api.github.com/repos/prateekbh/preact-material-components/commits{/sha}\",\n      \"git_commits_url\": \"https://api.github.com/repos/prateekbh/preact-material-components/git/commits{/sha}\",\n      \"comments_url\": \"https://api.github.com/repos/prateekbh/preact-material-components/comments{/number}\",\n      \"issue_comment_url\": \"https://api.github.com/repos/prateekbh/preact-material-components/issues/comments{/number}\",\n      \"contents_url\": \"https://api.github.com/repos/prateekbh/preact-material-components/contents/{+path}\",\n      \"compare_url\": \"https://api.github.com/repos/prateekbh/preact-material-components/compare/{base}...{head}\",\n      \"merges_url\": \"https://api.github.com/repos/prateekbh/preact-material-components/merges\",\n      \"archive_url\": \"https://api.github.com/repos/prateekbh/preact-material-components/{archive_format}{/ref}\",\n      \"downloads_url\": \"https://api.github.com/repos/prateekbh/preact-material-components/downloads\",\n      \"issues_url\": \"https://api.github.com/repos/prateekbh/preact-material-components/issues{/number}\",\n      \"pulls_url\": \"https://api.github.com/repos/prateekbh/preact-material-components/pulls{/number}\",\n      \"milestones_url\": \"https://api.github.com/repos/prateekbh/preact-material-components/milestones{/number}\",\n      \"notifications_url\": \"https://api.github.com/repos/prateekbh/preact-material-components/notifications{?since,all,participating}\",\n      \"labels_url\": \"https://api.github.com/repos/prateekbh/preact-material-components/labels{/name}\",\n      \"releases_url\": \"https://api.github.com/repos/prateekbh/preact-material-components/releases{/id}\",\n      \"deployments_url\": \"https://api.github.com/repos/prateekbh/preact-material-components/deployments\",\n      \"created_at\": \"2017-02-20T17:01:45Z\",\n      \"updated_at\": \"2020-05-05T18:50:59Z\",\n      \"pushed_at\": \"2020-04-16T05:07:32Z\",\n      \"git_url\": \"git://github.com/prateekbh/preact-material-components.git\",\n      \"ssh_url\": \"git@github.com:prateekbh/preact-material-components.git\",\n      \"clone_url\": \"https://github.com/prateekbh/preact-material-components.git\",\n      \"svn_url\": \"https://github.com/prateekbh/preact-material-components\",\n      \"homepage\": \"https://material.preactjs.com\",\n      \"size\": 95695,\n      \"stargazers_count\": 509,\n      \"watchers_count\": 509,\n      \"language\": \"TypeScript\",\n      \"has_issues\": true,\n      \"has_projects\": true,\n      \"has_downloads\": true,\n      \"has_wiki\": true,\n      \"has_pages\": false,\n      \"forks_count\": 85,\n      \"mirror_url\": null,\n      \"archived\": false,\n      \"disabled\": false,\n      \"open_issues_count\": 47,\n      \"license\": {\n        \"key\": \"mit\",\n        \"name\": \"MIT License\",\n        \"spdx_id\": \"MIT\",\n        \"url\": \"https://api.github.com/licenses/mit\",\n        \"node_id\": \"MDc6TGljZW5zZTEz\"\n      },\n      \"forks\": 85,\n      \"open_issues\": 47,\n      \"watchers\": 509,\n      \"default_branch\": \"master\",\n      \"score\": 1.0\n    },\n    {\n      \"id\": 34381195,\n      \"node_id\": \"MDEwOlJlcG9zaXRvcnkzNDM4MTE5NQ==\",\n      \"name\": \"jsxstyle\",\n      \"full_name\": \"jsxstyle/jsxstyle\",\n      \"private\": false,\n      \"owner\": {\n        \"login\": \"jsxstyle\",\n        \"id\": 29987079,\n        \"node_id\": \"MDEyOk9yZ2FuaXphdGlvbjI5OTg3MDc5\",\n        \"avatar_url\": \"https://avatars0.githubusercontent.com/u/29987079?v=4\",\n        \"gravatar_id\": \"\",\n        \"url\": \"https://api.github.com/users/jsxstyle\",\n        \"html_url\": \"https://github.com/jsxstyle\",\n        \"followers_url\": \"https://api.github.com/users/jsxstyle/followers\",\n        \"following_url\": \"https://api.github.com/users/jsxstyle/following{/other_user}\",\n        \"gists_url\": \"https://api.github.com/users/jsxstyle/gists{/gist_id}\",\n        \"starred_url\": \"https://api.github.com/users/jsxstyle/starred{/owner}{/repo}\",\n        \"subscriptions_url\": \"https://api.github.com/users/jsxstyle/subscriptions\",\n        \"organizations_url\": \"https://api.github.com/users/jsxstyle/orgs\",\n        \"repos_url\": \"https://api.github.com/users/jsxstyle/repos\",\n        \"events_url\": \"https://api.github.com/users/jsxstyle/events{/privacy}\",\n        \"received_events_url\": \"https://api.github.com/users/jsxstyle/received_events\",\n        \"type\": \"Organization\",\n        \"site_admin\": false\n      },\n      \"html_url\": \"https://github.com/jsxstyle/jsxstyle\",\n      \"description\": \"Inline style system for React and Preact\",\n      \"fork\": false,\n      \"url\": \"https://api.github.com/repos/jsxstyle/jsxstyle\",\n      \"forks_url\": \"https://api.github.com/repos/jsxstyle/jsxstyle/forks\",\n      \"keys_url\": \"https://api.github.com/repos/jsxstyle/jsxstyle/keys{/key_id}\",\n      \"collaborators_url\": \"https://api.github.com/repos/jsxstyle/jsxstyle/collaborators{/collaborator}\",\n      \"teams_url\": \"https://api.github.com/repos/jsxstyle/jsxstyle/teams\",\n      \"hooks_url\": \"https://api.github.com/repos/jsxstyle/jsxstyle/hooks\",\n      \"issue_events_url\": \"https://api.github.com/repos/jsxstyle/jsxstyle/issues/events{/number}\",\n      \"events_url\": \"https://api.github.com/repos/jsxstyle/jsxstyle/events\",\n      \"assignees_url\": \"https://api.github.com/repos/jsxstyle/jsxstyle/assignees{/user}\",\n      \"branches_url\": \"https://api.github.com/repos/jsxstyle/jsxstyle/branches{/branch}\",\n      \"tags_url\": \"https://api.github.com/repos/jsxstyle/jsxstyle/tags\",\n      \"blobs_url\": \"https://api.github.com/repos/jsxstyle/jsxstyle/git/blobs{/sha}\",\n      \"git_tags_url\": \"https://api.github.com/repos/jsxstyle/jsxstyle/git/tags{/sha}\",\n      \"git_refs_url\": \"https://api.github.com/repos/jsxstyle/jsxstyle/git/refs{/sha}\",\n      \"trees_url\": \"https://api.github.com/repos/jsxstyle/jsxstyle/git/trees{/sha}\",\n      \"statuses_url\": \"https://api.github.com/repos/jsxstyle/jsxstyle/statuses/{sha}\",\n      \"languages_url\": \"https://api.github.com/repos/jsxstyle/jsxstyle/languages\",\n      \"stargazers_url\": \"https://api.github.com/repos/jsxstyle/jsxstyle/stargazers\",\n      \"contributors_url\": \"https://api.github.com/repos/jsxstyle/jsxstyle/contributors\",\n      \"subscribers_url\": \"https://api.github.com/repos/jsxstyle/jsxstyle/subscribers\",\n      \"subscription_url\": \"https://api.github.com/repos/jsxstyle/jsxstyle/subscription\",\n      \"commits_url\": \"https://api.github.com/repos/jsxstyle/jsxstyle/commits{/sha}\",\n      \"git_commits_url\": \"https://api.github.com/repos/jsxstyle/jsxstyle/git/commits{/sha}\",\n      \"comments_url\": \"https://api.github.com/repos/jsxstyle/jsxstyle/comments{/number}\",\n      \"issue_comment_url\": \"https://api.github.com/repos/jsxstyle/jsxstyle/issues/comments{/number}\",\n      \"contents_url\": \"https://api.github.com/repos/jsxstyle/jsxstyle/contents/{+path}\",\n      \"compare_url\": \"https://api.github.com/repos/jsxstyle/jsxstyle/compare/{base}...{head}\",\n      \"merges_url\": \"https://api.github.com/repos/jsxstyle/jsxstyle/merges\",\n      \"archive_url\": \"https://api.github.com/repos/jsxstyle/jsxstyle/{archive_format}{/ref}\",\n      \"downloads_url\": \"https://api.github.com/repos/jsxstyle/jsxstyle/downloads\",\n      \"issues_url\": \"https://api.github.com/repos/jsxstyle/jsxstyle/issues{/number}\",\n      \"pulls_url\": \"https://api.github.com/repos/jsxstyle/jsxstyle/pulls{/number}\",\n      \"milestones_url\": \"https://api.github.com/repos/jsxstyle/jsxstyle/milestones{/number}\",\n      \"notifications_url\": \"https://api.github.com/repos/jsxstyle/jsxstyle/notifications{?since,all,participating}\",\n      \"labels_url\": \"https://api.github.com/repos/jsxstyle/jsxstyle/labels{/name}\",\n      \"releases_url\": \"https://api.github.com/repos/jsxstyle/jsxstyle/releases{/id}\",\n      \"deployments_url\": \"https://api.github.com/repos/jsxstyle/jsxstyle/deployments\",\n      \"created_at\": \"2015-04-22T09:22:48Z\",\n      \"updated_at\": \"2020-05-05T04:33:24Z\",\n      \"pushed_at\": \"2020-05-01T07:17:07Z\",\n      \"git_url\": \"git://github.com/jsxstyle/jsxstyle.git\",\n      \"ssh_url\": \"git@github.com:jsxstyle/jsxstyle.git\",\n      \"clone_url\": \"https://github.com/jsxstyle/jsxstyle.git\",\n      \"svn_url\": \"https://github.com/jsxstyle/jsxstyle\",\n      \"homepage\": \"\",\n      \"size\": 2481,\n      \"stargazers_count\": 1920,\n      \"watchers_count\": 1920,\n      \"language\": \"TypeScript\",\n      \"has_issues\": true,\n      \"has_projects\": true,\n      \"has_downloads\": true,\n      \"has_wiki\": true,\n      \"has_pages\": true,\n      \"forks_count\": 59,\n      \"mirror_url\": null,\n      \"archived\": false,\n      \"disabled\": false,\n      \"open_issues_count\": 7,\n      \"license\": {\n        \"key\": \"other\",\n        \"name\": \"Other\",\n        \"spdx_id\": \"NOASSERTION\",\n        \"url\": null,\n        \"node_id\": \"MDc6TGljZW5zZTA=\"\n      },\n      \"forks\": 59,\n      \"open_issues\": 7,\n      \"watchers\": 1920,\n      \"default_branch\": \"master\",\n      \"score\": 1.0\n    },\n    {\n      \"id\": 113351554,\n      \"node_id\": \"MDEwOlJlcG9zaXRvcnkxMTMzNTE1NTQ=\",\n      \"name\": \"unistore\",\n      \"full_name\": \"developit/unistore\",\n      \"private\": false,\n      \"owner\": {\n        \"login\": \"developit\",\n        \"id\": 105127,\n        \"node_id\": \"MDQ6VXNlcjEwNTEyNw==\",\n        \"avatar_url\": \"https://avatars2.githubusercontent.com/u/105127?v=4\",\n        \"gravatar_id\": \"\",\n        \"url\": \"https://api.github.com/users/developit\",\n        \"html_url\": \"https://github.com/developit\",\n        \"followers_url\": \"https://api.github.com/users/developit/followers\",\n        \"following_url\": \"https://api.github.com/users/developit/following{/other_user}\",\n        \"gists_url\": \"https://api.github.com/users/developit/gists{/gist_id}\",\n        \"starred_url\": \"https://api.github.com/users/developit/starred{/owner}{/repo}\",\n        \"subscriptions_url\": \"https://api.github.com/users/developit/subscriptions\",\n        \"organizations_url\": \"https://api.github.com/users/developit/orgs\",\n        \"repos_url\": \"https://api.github.com/users/developit/repos\",\n        \"events_url\": \"https://api.github.com/users/developit/events{/privacy}\",\n        \"received_events_url\": \"https://api.github.com/users/developit/received_events\",\n        \"type\": \"User\",\n        \"site_admin\": false\n      },\n      \"html_url\": \"https://github.com/developit/unistore\",\n      \"description\": \"🌶 350b / 650b state container with component actions for Preact & React\",\n      \"fork\": false,\n      \"url\": \"https://api.github.com/repos/developit/unistore\",\n      \"forks_url\": \"https://api.github.com/repos/developit/unistore/forks\",\n      \"keys_url\": \"https://api.github.com/repos/developit/unistore/keys{/key_id}\",\n      \"collaborators_url\": \"https://api.github.com/repos/developit/unistore/collaborators{/collaborator}\",\n      \"teams_url\": \"https://api.github.com/repos/developit/unistore/teams\",\n      \"hooks_url\": \"https://api.github.com/repos/developit/unistore/hooks\",\n      \"issue_events_url\": \"https://api.github.com/repos/developit/unistore/issues/events{/number}\",\n      \"events_url\": \"https://api.github.com/repos/developit/unistore/events\",\n      \"assignees_url\": \"https://api.github.com/repos/developit/unistore/assignees{/user}\",\n      \"branches_url\": \"https://api.github.com/repos/developit/unistore/branches{/branch}\",\n      \"tags_url\": \"https://api.github.com/repos/developit/unistore/tags\",\n      \"blobs_url\": \"https://api.github.com/repos/developit/unistore/git/blobs{/sha}\",\n      \"git_tags_url\": \"https://api.github.com/repos/developit/unistore/git/tags{/sha}\",\n      \"git_refs_url\": \"https://api.github.com/repos/developit/unistore/git/refs{/sha}\",\n      \"trees_url\": \"https://api.github.com/repos/developit/unistore/git/trees{/sha}\",\n      \"statuses_url\": \"https://api.github.com/repos/developit/unistore/statuses/{sha}\",\n      \"languages_url\": \"https://api.github.com/repos/developit/unistore/languages\",\n      \"stargazers_url\": \"https://api.github.com/repos/developit/unistore/stargazers\",\n      \"contributors_url\": \"https://api.github.com/repos/developit/unistore/contributors\",\n      \"subscribers_url\": \"https://api.github.com/repos/developit/unistore/subscribers\",\n      \"subscription_url\": \"https://api.github.com/repos/developit/unistore/subscription\",\n      \"commits_url\": \"https://api.github.com/repos/developit/unistore/commits{/sha}\",\n      \"git_commits_url\": \"https://api.github.com/repos/developit/unistore/git/commits{/sha}\",\n      \"comments_url\": \"https://api.github.com/repos/developit/unistore/comments{/number}\",\n      \"issue_comment_url\": \"https://api.github.com/repos/developit/unistore/issues/comments{/number}\",\n      \"contents_url\": \"https://api.github.com/repos/developit/unistore/contents/{+path}\",\n      \"compare_url\": \"https://api.github.com/repos/developit/unistore/compare/{base}...{head}\",\n      \"merges_url\": \"https://api.github.com/repos/developit/unistore/merges\",\n      \"archive_url\": \"https://api.github.com/repos/developit/unistore/{archive_format}{/ref}\",\n      \"downloads_url\": \"https://api.github.com/repos/developit/unistore/downloads\",\n      \"issues_url\": \"https://api.github.com/repos/developit/unistore/issues{/number}\",\n      \"pulls_url\": \"https://api.github.com/repos/developit/unistore/pulls{/number}\",\n      \"milestones_url\": \"https://api.github.com/repos/developit/unistore/milestones{/number}\",\n      \"notifications_url\": \"https://api.github.com/repos/developit/unistore/notifications{?since,all,participating}\",\n      \"labels_url\": \"https://api.github.com/repos/developit/unistore/labels{/name}\",\n      \"releases_url\": \"https://api.github.com/repos/developit/unistore/releases{/id}\",\n      \"deployments_url\": \"https://api.github.com/repos/developit/unistore/deployments\",\n      \"created_at\": \"2017-12-06T18:15:34Z\",\n      \"updated_at\": \"2020-05-14T22:07:57Z\",\n      \"pushed_at\": \"2020-04-16T16:22:33Z\",\n      \"git_url\": \"git://github.com/developit/unistore.git\",\n      \"ssh_url\": \"git@github.com:developit/unistore.git\",\n      \"clone_url\": \"https://github.com/developit/unistore.git\",\n      \"svn_url\": \"https://github.com/developit/unistore\",\n      \"homepage\": \"https://npm.im/unistore\",\n      \"size\": 178,\n      \"stargazers_count\": 2687,\n      \"watchers_count\": 2687,\n      \"language\": \"JavaScript\",\n      \"has_issues\": true,\n      \"has_projects\": true,\n      \"has_downloads\": true,\n      \"has_wiki\": true,\n      \"has_pages\": false,\n      \"forks_count\": 161,\n      \"mirror_url\": null,\n      \"archived\": false,\n      \"disabled\": false,\n      \"open_issues_count\": 49,\n      \"license\": null,\n      \"forks\": 161,\n      \"open_issues\": 49,\n      \"watchers\": 2687,\n      \"default_branch\": \"master\",\n      \"score\": 1.0\n    },\n    {\n      \"id\": 77597037,\n      \"node_id\": \"MDEwOlJlcG9zaXRvcnk3NzU5NzAzNw==\",\n      \"name\": \"preact-pwa\",\n      \"full_name\": \"ezekielchentnik/preact-pwa\",\n      \"private\": false,\n      \"owner\": {\n        \"login\": \"ezekielchentnik\",\n        \"id\": 3333017,\n        \"node_id\": \"MDQ6VXNlcjMzMzMwMTc=\",\n        \"avatar_url\": \"https://avatars2.githubusercontent.com/u/3333017?v=4\",\n        \"gravatar_id\": \"\",\n        \"url\": \"https://api.github.com/users/ezekielchentnik\",\n        \"html_url\": \"https://github.com/ezekielchentnik\",\n        \"followers_url\": \"https://api.github.com/users/ezekielchentnik/followers\",\n        \"following_url\": \"https://api.github.com/users/ezekielchentnik/following{/other_user}\",\n        \"gists_url\": \"https://api.github.com/users/ezekielchentnik/gists{/gist_id}\",\n        \"starred_url\": \"https://api.github.com/users/ezekielchentnik/starred{/owner}{/repo}\",\n        \"subscriptions_url\": \"https://api.github.com/users/ezekielchentnik/subscriptions\",\n        \"organizations_url\": \"https://api.github.com/users/ezekielchentnik/orgs\",\n        \"repos_url\": \"https://api.github.com/users/ezekielchentnik/repos\",\n        \"events_url\": \"https://api.github.com/users/ezekielchentnik/events{/privacy}\",\n        \"received_events_url\": \"https://api.github.com/users/ezekielchentnik/received_events\",\n        \"type\": \"User\",\n        \"site_admin\": false\n      },\n      \"html_url\": \"https://github.com/ezekielchentnik/preact-pwa\",\n      \"description\": \"Super fast progressive web app with small footprint & minimal dependancies\",\n      \"fork\": false,\n      \"url\": \"https://api.github.com/repos/ezekielchentnik/preact-pwa\",\n      \"forks_url\": \"https://api.github.com/repos/ezekielchentnik/preact-pwa/forks\",\n      \"keys_url\": \"https://api.github.com/repos/ezekielchentnik/preact-pwa/keys{/key_id}\",\n      \"collaborators_url\": \"https://api.github.com/repos/ezekielchentnik/preact-pwa/collaborators{/collaborator}\",\n      \"teams_url\": \"https://api.github.com/repos/ezekielchentnik/preact-pwa/teams\",\n      \"hooks_url\": \"https://api.github.com/repos/ezekielchentnik/preact-pwa/hooks\",\n      \"issue_events_url\": \"https://api.github.com/repos/ezekielchentnik/preact-pwa/issues/events{/number}\",\n      \"events_url\": \"https://api.github.com/repos/ezekielchentnik/preact-pwa/events\",\n      \"assignees_url\": \"https://api.github.com/repos/ezekielchentnik/preact-pwa/assignees{/user}\",\n      \"branches_url\": \"https://api.github.com/repos/ezekielchentnik/preact-pwa/branches{/branch}\",\n      \"tags_url\": \"https://api.github.com/repos/ezekielchentnik/preact-pwa/tags\",\n      \"blobs_url\": \"https://api.github.com/repos/ezekielchentnik/preact-pwa/git/blobs{/sha}\",\n      \"git_tags_url\": \"https://api.github.com/repos/ezekielchentnik/preact-pwa/git/tags{/sha}\",\n      \"git_refs_url\": \"https://api.github.com/repos/ezekielchentnik/preact-pwa/git/refs{/sha}\",\n      \"trees_url\": \"https://api.github.com/repos/ezekielchentnik/preact-pwa/git/trees{/sha}\",\n      \"statuses_url\": \"https://api.github.com/repos/ezekielchentnik/preact-pwa/statuses/{sha}\",\n      \"languages_url\": \"https://api.github.com/repos/ezekielchentnik/preact-pwa/languages\",\n      \"stargazers_url\": \"https://api.github.com/repos/ezekielchentnik/preact-pwa/stargazers\",\n      \"contributors_url\": \"https://api.github.com/repos/ezekielchentnik/preact-pwa/contributors\",\n      \"subscribers_url\": \"https://api.github.com/repos/ezekielchentnik/preact-pwa/subscribers\",\n      \"subscription_url\": \"https://api.github.com/repos/ezekielchentnik/preact-pwa/subscription\",\n      \"commits_url\": \"https://api.github.com/repos/ezekielchentnik/preact-pwa/commits{/sha}\",\n      \"git_commits_url\": \"https://api.github.com/repos/ezekielchentnik/preact-pwa/git/commits{/sha}\",\n      \"comments_url\": \"https://api.github.com/repos/ezekielchentnik/preact-pwa/comments{/number}\",\n      \"issue_comment_url\": \"https://api.github.com/repos/ezekielchentnik/preact-pwa/issues/comments{/number}\",\n      \"contents_url\": \"https://api.github.com/repos/ezekielchentnik/preact-pwa/contents/{+path}\",\n      \"compare_url\": \"https://api.github.com/repos/ezekielchentnik/preact-pwa/compare/{base}...{head}\",\n      \"merges_url\": \"https://api.github.com/repos/ezekielchentnik/preact-pwa/merges\",\n      \"archive_url\": \"https://api.github.com/repos/ezekielchentnik/preact-pwa/{archive_format}{/ref}\",\n      \"downloads_url\": \"https://api.github.com/repos/ezekielchentnik/preact-pwa/downloads\",\n      \"issues_url\": \"https://api.github.com/repos/ezekielchentnik/preact-pwa/issues{/number}\",\n      \"pulls_url\": \"https://api.github.com/repos/ezekielchentnik/preact-pwa/pulls{/number}\",\n      \"milestones_url\": \"https://api.github.com/repos/ezekielchentnik/preact-pwa/milestones{/number}\",\n      \"notifications_url\": \"https://api.github.com/repos/ezekielchentnik/preact-pwa/notifications{?since,all,participating}\",\n      \"labels_url\": \"https://api.github.com/repos/ezekielchentnik/preact-pwa/labels{/name}\",\n      \"releases_url\": \"https://api.github.com/repos/ezekielchentnik/preact-pwa/releases{/id}\",\n      \"deployments_url\": \"https://api.github.com/repos/ezekielchentnik/preact-pwa/deployments\",\n      \"created_at\": \"2016-12-29T08:35:40Z\",\n      \"updated_at\": \"2020-03-21T13:39:11Z\",\n      \"pushed_at\": \"2017-08-12T02:48:39Z\",\n      \"git_url\": \"git://github.com/ezekielchentnik/preact-pwa.git\",\n      \"ssh_url\": \"git@github.com:ezekielchentnik/preact-pwa.git\",\n      \"clone_url\": \"https://github.com/ezekielchentnik/preact-pwa.git\",\n      \"svn_url\": \"https://github.com/ezekielchentnik/preact-pwa\",\n      \"homepage\": \"https://preact-pwa-yfxiijbzit.now.sh/\",\n      \"size\": 822,\n      \"stargazers_count\": 507,\n      \"watchers_count\": 507,\n      \"language\": \"JavaScript\",\n      \"has_issues\": true,\n      \"has_projects\": true,\n      \"has_downloads\": true,\n      \"has_wiki\": true,\n      \"has_pages\": false,\n      \"forks_count\": 48,\n      \"mirror_url\": null,\n      \"archived\": false,\n      \"disabled\": false,\n      \"open_issues_count\": 7,\n      \"license\": {\n        \"key\": \"mit\",\n        \"name\": \"MIT License\",\n        \"spdx_id\": \"MIT\",\n        \"url\": \"https://api.github.com/licenses/mit\",\n        \"node_id\": \"MDc6TGljZW5zZTEz\"\n      },\n      \"forks\": 48,\n      \"open_issues\": 7,\n      \"watchers\": 507,\n      \"default_branch\": \"master\",\n      \"score\": 1.0\n    },\n    {\n      \"id\": 44454813,\n      \"node_id\": \"MDEwOlJlcG9zaXRvcnk0NDQ1NDgxMw==\",\n      \"name\": \"preact-render-to-string\",\n      \"full_name\": \"preactjs/preact-render-to-string\",\n      \"private\": false,\n      \"owner\": {\n        \"login\": \"preactjs\",\n        \"id\": 26872990,\n        \"node_id\": \"MDEyOk9yZ2FuaXphdGlvbjI2ODcyOTkw\",\n        \"avatar_url\": \"https://avatars3.githubusercontent.com/u/26872990?v=4\",\n        \"gravatar_id\": \"\",\n        \"url\": \"https://api.github.com/users/preactjs\",\n        \"html_url\": \"https://github.com/preactjs\",\n        \"followers_url\": \"https://api.github.com/users/preactjs/followers\",\n        \"following_url\": \"https://api.github.com/users/preactjs/following{/other_user}\",\n        \"gists_url\": \"https://api.github.com/users/preactjs/gists{/gist_id}\",\n        \"starred_url\": \"https://api.github.com/users/preactjs/starred{/owner}{/repo}\",\n        \"subscriptions_url\": \"https://api.github.com/users/preactjs/subscriptions\",\n        \"organizations_url\": \"https://api.github.com/users/preactjs/orgs\",\n        \"repos_url\": \"https://api.github.com/users/preactjs/repos\",\n        \"events_url\": \"https://api.github.com/users/preactjs/events{/privacy}\",\n        \"received_events_url\": \"https://api.github.com/users/preactjs/received_events\",\n        \"type\": \"Organization\",\n        \"site_admin\": false\n      },\n      \"html_url\": \"https://github.com/preactjs/preact-render-to-string\",\n      \"description\": \":page_facing_up: Universal rendering for Preact: render JSX and Preact components to HTML.\",\n      \"fork\": false,\n      \"url\": \"https://api.github.com/repos/preactjs/preact-render-to-string\",\n      \"forks_url\": \"https://api.github.com/repos/preactjs/preact-render-to-string/forks\",\n      \"keys_url\": \"https://api.github.com/repos/preactjs/preact-render-to-string/keys{/key_id}\",\n      \"collaborators_url\": \"https://api.github.com/repos/preactjs/preact-render-to-string/collaborators{/collaborator}\",\n      \"teams_url\": \"https://api.github.com/repos/preactjs/preact-render-to-string/teams\",\n      \"hooks_url\": \"https://api.github.com/repos/preactjs/preact-render-to-string/hooks\",\n      \"issue_events_url\": \"https://api.github.com/repos/preactjs/preact-render-to-string/issues/events{/number}\",\n      \"events_url\": \"https://api.github.com/repos/preactjs/preact-render-to-string/events\",\n      \"assignees_url\": \"https://api.github.com/repos/preactjs/preact-render-to-string/assignees{/user}\",\n      \"branches_url\": \"https://api.github.com/repos/preactjs/preact-render-to-string/branches{/branch}\",\n      \"tags_url\": \"https://api.github.com/repos/preactjs/preact-render-to-string/tags\",\n      \"blobs_url\": \"https://api.github.com/repos/preactjs/preact-render-to-string/git/blobs{/sha}\",\n      \"git_tags_url\": \"https://api.github.com/repos/preactjs/preact-render-to-string/git/tags{/sha}\",\n      \"git_refs_url\": \"https://api.github.com/repos/preactjs/preact-render-to-string/git/refs{/sha}\",\n      \"trees_url\": \"https://api.github.com/repos/preactjs/preact-render-to-string/git/trees{/sha}\",\n      \"statuses_url\": \"https://api.github.com/repos/preactjs/preact-render-to-string/statuses/{sha}\",\n      \"languages_url\": \"https://api.github.com/repos/preactjs/preact-render-to-string/languages\",\n      \"stargazers_url\": \"https://api.github.com/repos/preactjs/preact-render-to-string/stargazers\",\n      \"contributors_url\": \"https://api.github.com/repos/preactjs/preact-render-to-string/contributors\",\n      \"subscribers_url\": \"https://api.github.com/repos/preactjs/preact-render-to-string/subscribers\",\n      \"subscription_url\": \"https://api.github.com/repos/preactjs/preact-render-to-string/subscription\",\n      \"commits_url\": \"https://api.github.com/repos/preactjs/preact-render-to-string/commits{/sha}\",\n      \"git_commits_url\": \"https://api.github.com/repos/preactjs/preact-render-to-string/git/commits{/sha}\",\n      \"comments_url\": \"https://api.github.com/repos/preactjs/preact-render-to-string/comments{/number}\",\n      \"issue_comment_url\": \"https://api.github.com/repos/preactjs/preact-render-to-string/issues/comments{/number}\",\n      \"contents_url\": \"https://api.github.com/repos/preactjs/preact-render-to-string/contents/{+path}\",\n      \"compare_url\": \"https://api.github.com/repos/preactjs/preact-render-to-string/compare/{base}...{head}\",\n      \"merges_url\": \"https://api.github.com/repos/preactjs/preact-render-to-string/merges\",\n      \"archive_url\": \"https://api.github.com/repos/preactjs/preact-render-to-string/{archive_format}{/ref}\",\n      \"downloads_url\": \"https://api.github.com/repos/preactjs/preact-render-to-string/downloads\",\n      \"issues_url\": \"https://api.github.com/repos/preactjs/preact-render-to-string/issues{/number}\",\n      \"pulls_url\": \"https://api.github.com/repos/preactjs/preact-render-to-string/pulls{/number}\",\n      \"milestones_url\": \"https://api.github.com/repos/preactjs/preact-render-to-string/milestones{/number}\",\n      \"notifications_url\": \"https://api.github.com/repos/preactjs/preact-render-to-string/notifications{?since,all,participating}\",\n      \"labels_url\": \"https://api.github.com/repos/preactjs/preact-render-to-string/labels{/name}\",\n      \"releases_url\": \"https://api.github.com/repos/preactjs/preact-render-to-string/releases{/id}\",\n      \"deployments_url\": \"https://api.github.com/repos/preactjs/preact-render-to-string/deployments\",\n      \"created_at\": \"2015-10-17T21:12:30Z\",\n      \"updated_at\": \"2020-05-14T11:07:51Z\",\n      \"pushed_at\": \"2020-05-08T12:19:47Z\",\n      \"git_url\": \"git://github.com/preactjs/preact-render-to-string.git\",\n      \"ssh_url\": \"git@github.com:preactjs/preact-render-to-string.git\",\n      \"clone_url\": \"https://github.com/preactjs/preact-render-to-string.git\",\n      \"svn_url\": \"https://github.com/preactjs/preact-render-to-string\",\n      \"homepage\": \"http://npm.im/preact-render-to-string\",\n      \"size\": 289,\n      \"stargazers_count\": 350,\n      \"watchers_count\": 350,\n      \"language\": \"JavaScript\",\n      \"has_issues\": true,\n      \"has_projects\": true,\n      \"has_downloads\": true,\n      \"has_wiki\": true,\n      \"has_pages\": false,\n      \"forks_count\": 68,\n      \"mirror_url\": null,\n      \"archived\": false,\n      \"disabled\": false,\n      \"open_issues_count\": 24,\n      \"license\": {\n        \"key\": \"mit\",\n        \"name\": \"MIT License\",\n        \"spdx_id\": \"MIT\",\n        \"url\": \"https://api.github.com/licenses/mit\",\n        \"node_id\": \"MDc6TGljZW5zZTEz\"\n      },\n      \"forks\": 68,\n      \"open_issues\": 24,\n      \"watchers\": 350,\n      \"default_branch\": \"master\",\n      \"score\": 1.0\n    },\n    {\n      \"id\": 51235098,\n      \"node_id\": \"MDEwOlJlcG9zaXRvcnk1MTIzNTA5OA==\",\n      \"name\": \"preact-redux-example\",\n      \"full_name\": \"developit/preact-redux-example\",\n      \"private\": false,\n      \"owner\": {\n        \"login\": \"developit\",\n        \"id\": 105127,\n        \"node_id\": \"MDQ6VXNlcjEwNTEyNw==\",\n        \"avatar_url\": \"https://avatars2.githubusercontent.com/u/105127?v=4\",\n        \"gravatar_id\": \"\",\n        \"url\": \"https://api.github.com/users/developit\",\n        \"html_url\": \"https://github.com/developit\",\n        \"followers_url\": \"https://api.github.com/users/developit/followers\",\n        \"following_url\": \"https://api.github.com/users/developit/following{/other_user}\",\n        \"gists_url\": \"https://api.github.com/users/developit/gists{/gist_id}\",\n        \"starred_url\": \"https://api.github.com/users/developit/starred{/owner}{/repo}\",\n        \"subscriptions_url\": \"https://api.github.com/users/developit/subscriptions\",\n        \"organizations_url\": \"https://api.github.com/users/developit/orgs\",\n        \"repos_url\": \"https://api.github.com/users/developit/repos\",\n        \"events_url\": \"https://api.github.com/users/developit/events{/privacy}\",\n        \"received_events_url\": \"https://api.github.com/users/developit/received_events\",\n        \"type\": \"User\",\n        \"site_admin\": false\n      },\n      \"html_url\": \"https://github.com/developit/preact-redux-example\",\n      \"description\": \":repeat: Preact + Redux Example Project\",\n      \"fork\": false,\n      \"url\": \"https://api.github.com/repos/developit/preact-redux-example\",\n      \"forks_url\": \"https://api.github.com/repos/developit/preact-redux-example/forks\",\n      \"keys_url\": \"https://api.github.com/repos/developit/preact-redux-example/keys{/key_id}\",\n      \"collaborators_url\": \"https://api.github.com/repos/developit/preact-redux-example/collaborators{/collaborator}\",\n      \"teams_url\": \"https://api.github.com/repos/developit/preact-redux-example/teams\",\n      \"hooks_url\": \"https://api.github.com/repos/developit/preact-redux-example/hooks\",\n      \"issue_events_url\": \"https://api.github.com/repos/developit/preact-redux-example/issues/events{/number}\",\n      \"events_url\": \"https://api.github.com/repos/developit/preact-redux-example/events\",\n      \"assignees_url\": \"https://api.github.com/repos/developit/preact-redux-example/assignees{/user}\",\n      \"branches_url\": \"https://api.github.com/repos/developit/preact-redux-example/branches{/branch}\",\n      \"tags_url\": \"https://api.github.com/repos/developit/preact-redux-example/tags\",\n      \"blobs_url\": \"https://api.github.com/repos/developit/preact-redux-example/git/blobs{/sha}\",\n      \"git_tags_url\": \"https://api.github.com/repos/developit/preact-redux-example/git/tags{/sha}\",\n      \"git_refs_url\": \"https://api.github.com/repos/developit/preact-redux-example/git/refs{/sha}\",\n      \"trees_url\": \"https://api.github.com/repos/developit/preact-redux-example/git/trees{/sha}\",\n      \"statuses_url\": \"https://api.github.com/repos/developit/preact-redux-example/statuses/{sha}\",\n      \"languages_url\": \"https://api.github.com/repos/developit/preact-redux-example/languages\",\n      \"stargazers_url\": \"https://api.github.com/repos/developit/preact-redux-example/stargazers\",\n      \"contributors_url\": \"https://api.github.com/repos/developit/preact-redux-example/contributors\",\n      \"subscribers_url\": \"https://api.github.com/repos/developit/preact-redux-example/subscribers\",\n      \"subscription_url\": \"https://api.github.com/repos/developit/preact-redux-example/subscription\",\n      \"commits_url\": \"https://api.github.com/repos/developit/preact-redux-example/commits{/sha}\",\n      \"git_commits_url\": \"https://api.github.com/repos/developit/preact-redux-example/git/commits{/sha}\",\n      \"comments_url\": \"https://api.github.com/repos/developit/preact-redux-example/comments{/number}\",\n      \"issue_comment_url\": \"https://api.github.com/repos/developit/preact-redux-example/issues/comments{/number}\",\n      \"contents_url\": \"https://api.github.com/repos/developit/preact-redux-example/contents/{+path}\",\n      \"compare_url\": \"https://api.github.com/repos/developit/preact-redux-example/compare/{base}...{head}\",\n      \"merges_url\": \"https://api.github.com/repos/developit/preact-redux-example/merges\",\n      \"archive_url\": \"https://api.github.com/repos/developit/preact-redux-example/{archive_format}{/ref}\",\n      \"downloads_url\": \"https://api.github.com/repos/developit/preact-redux-example/downloads\",\n      \"issues_url\": \"https://api.github.com/repos/developit/preact-redux-example/issues{/number}\",\n      \"pulls_url\": \"https://api.github.com/repos/developit/preact-redux-example/pulls{/number}\",\n      \"milestones_url\": \"https://api.github.com/repos/developit/preact-redux-example/milestones{/number}\",\n      \"notifications_url\": \"https://api.github.com/repos/developit/preact-redux-example/notifications{?since,all,participating}\",\n      \"labels_url\": \"https://api.github.com/repos/developit/preact-redux-example/labels{/name}\",\n      \"releases_url\": \"https://api.github.com/repos/developit/preact-redux-example/releases{/id}\",\n      \"deployments_url\": \"https://api.github.com/repos/developit/preact-redux-example/deployments\",\n      \"created_at\": \"2016-02-07T04:19:06Z\",\n      \"updated_at\": \"2020-05-06T07:30:08Z\",\n      \"pushed_at\": \"2019-05-21T04:49:58Z\",\n      \"git_url\": \"git://github.com/developit/preact-redux-example.git\",\n      \"ssh_url\": \"git@github.com:developit/preact-redux-example.git\",\n      \"clone_url\": \"https://github.com/developit/preact-redux-example.git\",\n      \"svn_url\": \"https://github.com/developit/preact-redux-example\",\n      \"homepage\": \"https://preact-redux-example.surge.sh\",\n      \"size\": 24,\n      \"stargazers_count\": 198,\n      \"watchers_count\": 198,\n      \"language\": \"JavaScript\",\n      \"has_issues\": true,\n      \"has_projects\": true,\n      \"has_downloads\": true,\n      \"has_wiki\": true,\n      \"has_pages\": false,\n      \"forks_count\": 56,\n      \"mirror_url\": null,\n      \"archived\": false,\n      \"disabled\": false,\n      \"open_issues_count\": 6,\n      \"license\": null,\n      \"forks\": 56,\n      \"open_issues\": 6,\n      \"watchers\": 198,\n      \"default_branch\": \"master\",\n      \"score\": 1.0\n    },\n    {\n      \"id\": 79582090,\n      \"node_id\": \"MDEwOlJlcG9zaXRvcnk3OTU4MjA5MA==\",\n      \"name\": \"awesome-preact\",\n      \"full_name\": \"preactjs/awesome-preact\",\n      \"private\": false,\n      \"owner\": {\n        \"login\": \"preactjs\",\n        \"id\": 26872990,\n        \"node_id\": \"MDEyOk9yZ2FuaXphdGlvbjI2ODcyOTkw\",\n        \"avatar_url\": \"https://avatars3.githubusercontent.com/u/26872990?v=4\",\n        \"gravatar_id\": \"\",\n        \"url\": \"https://api.github.com/users/preactjs\",\n        \"html_url\": \"https://github.com/preactjs\",\n        \"followers_url\": \"https://api.github.com/users/preactjs/followers\",\n        \"following_url\": \"https://api.github.com/users/preactjs/following{/other_user}\",\n        \"gists_url\": \"https://api.github.com/users/preactjs/gists{/gist_id}\",\n        \"starred_url\": \"https://api.github.com/users/preactjs/starred{/owner}{/repo}\",\n        \"subscriptions_url\": \"https://api.github.com/users/preactjs/subscriptions\",\n        \"organizations_url\": \"https://api.github.com/users/preactjs/orgs\",\n        \"repos_url\": \"https://api.github.com/users/preactjs/repos\",\n        \"events_url\": \"https://api.github.com/users/preactjs/events{/privacy}\",\n        \"received_events_url\": \"https://api.github.com/users/preactjs/received_events\",\n        \"type\": \"Organization\",\n        \"site_admin\": false\n      },\n      \"html_url\": \"https://github.com/preactjs/awesome-preact\",\n      \"description\": \"A curated list of amazingly awesome things regarding Preact ecosystem :star2:\",\n      \"fork\": false,\n      \"url\": \"https://api.github.com/repos/preactjs/awesome-preact\",\n      \"forks_url\": \"https://api.github.com/repos/preactjs/awesome-preact/forks\",\n      \"keys_url\": \"https://api.github.com/repos/preactjs/awesome-preact/keys{/key_id}\",\n      \"collaborators_url\": \"https://api.github.com/repos/preactjs/awesome-preact/collaborators{/collaborator}\",\n      \"teams_url\": \"https://api.github.com/repos/preactjs/awesome-preact/teams\",\n      \"hooks_url\": \"https://api.github.com/repos/preactjs/awesome-preact/hooks\",\n      \"issue_events_url\": \"https://api.github.com/repos/preactjs/awesome-preact/issues/events{/number}\",\n      \"events_url\": \"https://api.github.com/repos/preactjs/awesome-preact/events\",\n      \"assignees_url\": \"https://api.github.com/repos/preactjs/awesome-preact/assignees{/user}\",\n      \"branches_url\": \"https://api.github.com/repos/preactjs/awesome-preact/branches{/branch}\",\n      \"tags_url\": \"https://api.github.com/repos/preactjs/awesome-preact/tags\",\n      \"blobs_url\": \"https://api.github.com/repos/preactjs/awesome-preact/git/blobs{/sha}\",\n      \"git_tags_url\": \"https://api.github.com/repos/preactjs/awesome-preact/git/tags{/sha}\",\n      \"git_refs_url\": \"https://api.github.com/repos/preactjs/awesome-preact/git/refs{/sha}\",\n      \"trees_url\": \"https://api.github.com/repos/preactjs/awesome-preact/git/trees{/sha}\",\n      \"statuses_url\": \"https://api.github.com/repos/preactjs/awesome-preact/statuses/{sha}\",\n      \"languages_url\": \"https://api.github.com/repos/preactjs/awesome-preact/languages\",\n      \"stargazers_url\": \"https://api.github.com/repos/preactjs/awesome-preact/stargazers\",\n      \"contributors_url\": \"https://api.github.com/repos/preactjs/awesome-preact/contributors\",\n      \"subscribers_url\": \"https://api.github.com/repos/preactjs/awesome-preact/subscribers\",\n      \"subscription_url\": \"https://api.github.com/repos/preactjs/awesome-preact/subscription\",\n      \"commits_url\": \"https://api.github.com/repos/preactjs/awesome-preact/commits{/sha}\",\n      \"git_commits_url\": \"https://api.github.com/repos/preactjs/awesome-preact/git/commits{/sha}\",\n      \"comments_url\": \"https://api.github.com/repos/preactjs/awesome-preact/comments{/number}\",\n      \"issue_comment_url\": \"https://api.github.com/repos/preactjs/awesome-preact/issues/comments{/number}\",\n      \"contents_url\": \"https://api.github.com/repos/preactjs/awesome-preact/contents/{+path}\",\n      \"compare_url\": \"https://api.github.com/repos/preactjs/awesome-preact/compare/{base}...{head}\",\n      \"merges_url\": \"https://api.github.com/repos/preactjs/awesome-preact/merges\",\n      \"archive_url\": \"https://api.github.com/repos/preactjs/awesome-preact/{archive_format}{/ref}\",\n      \"downloads_url\": \"https://api.github.com/repos/preactjs/awesome-preact/downloads\",\n      \"issues_url\": \"https://api.github.com/repos/preactjs/awesome-preact/issues{/number}\",\n      \"pulls_url\": \"https://api.github.com/repos/preactjs/awesome-preact/pulls{/number}\",\n      \"milestones_url\": \"https://api.github.com/repos/preactjs/awesome-preact/milestones{/number}\",\n      \"notifications_url\": \"https://api.github.com/repos/preactjs/awesome-preact/notifications{?since,all,participating}\",\n      \"labels_url\": \"https://api.github.com/repos/preactjs/awesome-preact/labels{/name}\",\n      \"releases_url\": \"https://api.github.com/repos/preactjs/awesome-preact/releases{/id}\",\n      \"deployments_url\": \"https://api.github.com/repos/preactjs/awesome-preact/deployments\",\n      \"created_at\": \"2017-01-20T17:44:25Z\",\n      \"updated_at\": \"2020-05-14T15:55:40Z\",\n      \"pushed_at\": \"2020-05-11T19:18:22Z\",\n      \"git_url\": \"git://github.com/preactjs/awesome-preact.git\",\n      \"ssh_url\": \"git@github.com:preactjs/awesome-preact.git\",\n      \"clone_url\": \"https://github.com/preactjs/awesome-preact.git\",\n      \"svn_url\": \"https://github.com/preactjs/awesome-preact\",\n      \"homepage\": null,\n      \"size\": 107,\n      \"stargazers_count\": 415,\n      \"watchers_count\": 415,\n      \"language\": null,\n      \"has_issues\": true,\n      \"has_projects\": true,\n      \"has_downloads\": true,\n      \"has_wiki\": true,\n      \"has_pages\": false,\n      \"forks_count\": 36,\n      \"mirror_url\": null,\n      \"archived\": false,\n      \"disabled\": false,\n      \"open_issues_count\": 1,\n      \"license\": null,\n      \"forks\": 36,\n      \"open_issues\": 1,\n      \"watchers\": 415,\n      \"default_branch\": \"master\",\n      \"score\": 1.0\n    },\n    {\n      \"id\": 78304781,\n      \"node_id\": \"MDEwOlJlcG9zaXRvcnk3ODMwNDc4MQ==\",\n      \"name\": \"preact-starter\",\n      \"full_name\": \"lukeed/preact-starter\",\n      \"private\": false,\n      \"owner\": {\n        \"login\": \"lukeed\",\n        \"id\": 5855893,\n        \"node_id\": \"MDQ6VXNlcjU4NTU4OTM=\",\n        \"avatar_url\": \"https://avatars1.githubusercontent.com/u/5855893?v=4\",\n        \"gravatar_id\": \"\",\n        \"url\": \"https://api.github.com/users/lukeed\",\n        \"html_url\": \"https://github.com/lukeed\",\n        \"followers_url\": \"https://api.github.com/users/lukeed/followers\",\n        \"following_url\": \"https://api.github.com/users/lukeed/following{/other_user}\",\n        \"gists_url\": \"https://api.github.com/users/lukeed/gists{/gist_id}\",\n        \"starred_url\": \"https://api.github.com/users/lukeed/starred{/owner}{/repo}\",\n        \"subscriptions_url\": \"https://api.github.com/users/lukeed/subscriptions\",\n        \"organizations_url\": \"https://api.github.com/users/lukeed/orgs\",\n        \"repos_url\": \"https://api.github.com/users/lukeed/repos\",\n        \"events_url\": \"https://api.github.com/users/lukeed/events{/privacy}\",\n        \"received_events_url\": \"https://api.github.com/users/lukeed/received_events\",\n        \"type\": \"User\",\n        \"site_admin\": false\n      },\n      \"html_url\": \"https://github.com/lukeed/preact-starter\",\n      \"description\": \"Webpack3 boilerplate for building SPA / PWA / offline front-end apps with Preact\",\n      \"fork\": false,\n      \"url\": \"https://api.github.com/repos/lukeed/preact-starter\",\n      \"forks_url\": \"https://api.github.com/repos/lukeed/preact-starter/forks\",\n      \"keys_url\": \"https://api.github.com/repos/lukeed/preact-starter/keys{/key_id}\",\n      \"collaborators_url\": \"https://api.github.com/repos/lukeed/preact-starter/collaborators{/collaborator}\",\n      \"teams_url\": \"https://api.github.com/repos/lukeed/preact-starter/teams\",\n      \"hooks_url\": \"https://api.github.com/repos/lukeed/preact-starter/hooks\",\n      \"issue_events_url\": \"https://api.github.com/repos/lukeed/preact-starter/issues/events{/number}\",\n      \"events_url\": \"https://api.github.com/repos/lukeed/preact-starter/events\",\n      \"assignees_url\": \"https://api.github.com/repos/lukeed/preact-starter/assignees{/user}\",\n      \"branches_url\": \"https://api.github.com/repos/lukeed/preact-starter/branches{/branch}\",\n      \"tags_url\": \"https://api.github.com/repos/lukeed/preact-starter/tags\",\n      \"blobs_url\": \"https://api.github.com/repos/lukeed/preact-starter/git/blobs{/sha}\",\n      \"git_tags_url\": \"https://api.github.com/repos/lukeed/preact-starter/git/tags{/sha}\",\n      \"git_refs_url\": \"https://api.github.com/repos/lukeed/preact-starter/git/refs{/sha}\",\n      \"trees_url\": \"https://api.github.com/repos/lukeed/preact-starter/git/trees{/sha}\",\n      \"statuses_url\": \"https://api.github.com/repos/lukeed/preact-starter/statuses/{sha}\",\n      \"languages_url\": \"https://api.github.com/repos/lukeed/preact-starter/languages\",\n      \"stargazers_url\": \"https://api.github.com/repos/lukeed/preact-starter/stargazers\",\n      \"contributors_url\": \"https://api.github.com/repos/lukeed/preact-starter/contributors\",\n      \"subscribers_url\": \"https://api.github.com/repos/lukeed/preact-starter/subscribers\",\n      \"subscription_url\": \"https://api.github.com/repos/lukeed/preact-starter/subscription\",\n      \"commits_url\": \"https://api.github.com/repos/lukeed/preact-starter/commits{/sha}\",\n      \"git_commits_url\": \"https://api.github.com/repos/lukeed/preact-starter/git/commits{/sha}\",\n      \"comments_url\": \"https://api.github.com/repos/lukeed/preact-starter/comments{/number}\",\n      \"issue_comment_url\": \"https://api.github.com/repos/lukeed/preact-starter/issues/comments{/number}\",\n      \"contents_url\": \"https://api.github.com/repos/lukeed/preact-starter/contents/{+path}\",\n      \"compare_url\": \"https://api.github.com/repos/lukeed/preact-starter/compare/{base}...{head}\",\n      \"merges_url\": \"https://api.github.com/repos/lukeed/preact-starter/merges\",\n      \"archive_url\": \"https://api.github.com/repos/lukeed/preact-starter/{archive_format}{/ref}\",\n      \"downloads_url\": \"https://api.github.com/repos/lukeed/preact-starter/downloads\",\n      \"issues_url\": \"https://api.github.com/repos/lukeed/preact-starter/issues{/number}\",\n      \"pulls_url\": \"https://api.github.com/repos/lukeed/preact-starter/pulls{/number}\",\n      \"milestones_url\": \"https://api.github.com/repos/lukeed/preact-starter/milestones{/number}\",\n      \"notifications_url\": \"https://api.github.com/repos/lukeed/preact-starter/notifications{?since,all,participating}\",\n      \"labels_url\": \"https://api.github.com/repos/lukeed/preact-starter/labels{/name}\",\n      \"releases_url\": \"https://api.github.com/repos/lukeed/preact-starter/releases{/id}\",\n      \"deployments_url\": \"https://api.github.com/repos/lukeed/preact-starter/deployments\",\n      \"created_at\": \"2017-01-07T21:28:51Z\",\n      \"updated_at\": \"2020-05-04T11:01:01Z\",\n      \"pushed_at\": \"2018-11-23T18:48:47Z\",\n      \"git_url\": \"git://github.com/lukeed/preact-starter.git\",\n      \"ssh_url\": \"git@github.com:lukeed/preact-starter.git\",\n      \"clone_url\": \"https://github.com/lukeed/preact-starter.git\",\n      \"svn_url\": \"https://github.com/lukeed/preact-starter\",\n      \"homepage\": \"https://preact-starter.now.sh/\",\n      \"size\": 698,\n      \"stargazers_count\": 382,\n      \"watchers_count\": 382,\n      \"language\": \"JavaScript\",\n      \"has_issues\": true,\n      \"has_projects\": false,\n      \"has_downloads\": true,\n      \"has_wiki\": false,\n      \"has_pages\": false,\n      \"forks_count\": 34,\n      \"mirror_url\": null,\n      \"archived\": false,\n      \"disabled\": false,\n      \"open_issues_count\": 2,\n      \"license\": {\n        \"key\": \"mit\",\n        \"name\": \"MIT License\",\n        \"spdx_id\": \"MIT\",\n        \"url\": \"https://api.github.com/licenses/mit\",\n        \"node_id\": \"MDc6TGljZW5zZTEz\"\n      },\n      \"forks\": 34,\n      \"open_issues\": 2,\n      \"watchers\": 382,\n      \"default_branch\": \"master\",\n      \"score\": 1.0\n    },\n    {\n      \"id\": 79223894,\n      \"node_id\": \"MDEwOlJlcG9zaXRvcnk3OTIyMzg5NA==\",\n      \"name\": \"preact-habitat\",\n      \"full_name\": \"zouhir/preact-habitat\",\n      \"private\": false,\n      \"owner\": {\n        \"login\": \"zouhir\",\n        \"id\": 5052316,\n        \"node_id\": \"MDQ6VXNlcjUwNTIzMTY=\",\n        \"avatar_url\": \"https://avatars3.githubusercontent.com/u/5052316?v=4\",\n        \"gravatar_id\": \"\",\n        \"url\": \"https://api.github.com/users/zouhir\",\n        \"html_url\": \"https://github.com/zouhir\",\n        \"followers_url\": \"https://api.github.com/users/zouhir/followers\",\n        \"following_url\": \"https://api.github.com/users/zouhir/following{/other_user}\",\n        \"gists_url\": \"https://api.github.com/users/zouhir/gists{/gist_id}\",\n        \"starred_url\": \"https://api.github.com/users/zouhir/starred{/owner}{/repo}\",\n        \"subscriptions_url\": \"https://api.github.com/users/zouhir/subscriptions\",\n        \"organizations_url\": \"https://api.github.com/users/zouhir/orgs\",\n        \"repos_url\": \"https://api.github.com/users/zouhir/repos\",\n        \"events_url\": \"https://api.github.com/users/zouhir/events{/privacy}\",\n        \"received_events_url\": \"https://api.github.com/users/zouhir/received_events\",\n        \"type\": \"User\",\n        \"site_admin\": false\n      },\n      \"html_url\": \"https://github.com/zouhir/preact-habitat\",\n      \"description\": \"Zero configuration Preact widgets renderer in any host DOM\",\n      \"fork\": false,\n      \"url\": \"https://api.github.com/repos/zouhir/preact-habitat\",\n      \"forks_url\": \"https://api.github.com/repos/zouhir/preact-habitat/forks\",\n      \"keys_url\": \"https://api.github.com/repos/zouhir/preact-habitat/keys{/key_id}\",\n      \"collaborators_url\": \"https://api.github.com/repos/zouhir/preact-habitat/collaborators{/collaborator}\",\n      \"teams_url\": \"https://api.github.com/repos/zouhir/preact-habitat/teams\",\n      \"hooks_url\": \"https://api.github.com/repos/zouhir/preact-habitat/hooks\",\n      \"issue_events_url\": \"https://api.github.com/repos/zouhir/preact-habitat/issues/events{/number}\",\n      \"events_url\": \"https://api.github.com/repos/zouhir/preact-habitat/events\",\n      \"assignees_url\": \"https://api.github.com/repos/zouhir/preact-habitat/assignees{/user}\",\n      \"branches_url\": \"https://api.github.com/repos/zouhir/preact-habitat/branches{/branch}\",\n      \"tags_url\": \"https://api.github.com/repos/zouhir/preact-habitat/tags\",\n      \"blobs_url\": \"https://api.github.com/repos/zouhir/preact-habitat/git/blobs{/sha}\",\n      \"git_tags_url\": \"https://api.github.com/repos/zouhir/preact-habitat/git/tags{/sha}\",\n      \"git_refs_url\": \"https://api.github.com/repos/zouhir/preact-habitat/git/refs{/sha}\",\n      \"trees_url\": \"https://api.github.com/repos/zouhir/preact-habitat/git/trees{/sha}\",\n      \"statuses_url\": \"https://api.github.com/repos/zouhir/preact-habitat/statuses/{sha}\",\n      \"languages_url\": \"https://api.github.com/repos/zouhir/preact-habitat/languages\",\n      \"stargazers_url\": \"https://api.github.com/repos/zouhir/preact-habitat/stargazers\",\n      \"contributors_url\": \"https://api.github.com/repos/zouhir/preact-habitat/contributors\",\n      \"subscribers_url\": \"https://api.github.com/repos/zouhir/preact-habitat/subscribers\",\n      \"subscription_url\": \"https://api.github.com/repos/zouhir/preact-habitat/subscription\",\n      \"commits_url\": \"https://api.github.com/repos/zouhir/preact-habitat/commits{/sha}\",\n      \"git_commits_url\": \"https://api.github.com/repos/zouhir/preact-habitat/git/commits{/sha}\",\n      \"comments_url\": \"https://api.github.com/repos/zouhir/preact-habitat/comments{/number}\",\n      \"issue_comment_url\": \"https://api.github.com/repos/zouhir/preact-habitat/issues/comments{/number}\",\n      \"contents_url\": \"https://api.github.com/repos/zouhir/preact-habitat/contents/{+path}\",\n      \"compare_url\": \"https://api.github.com/repos/zouhir/preact-habitat/compare/{base}...{head}\",\n      \"merges_url\": \"https://api.github.com/repos/zouhir/preact-habitat/merges\",\n      \"archive_url\": \"https://api.github.com/repos/zouhir/preact-habitat/{archive_format}{/ref}\",\n      \"downloads_url\": \"https://api.github.com/repos/zouhir/preact-habitat/downloads\",\n      \"issues_url\": \"https://api.github.com/repos/zouhir/preact-habitat/issues{/number}\",\n      \"pulls_url\": \"https://api.github.com/repos/zouhir/preact-habitat/pulls{/number}\",\n      \"milestones_url\": \"https://api.github.com/repos/zouhir/preact-habitat/milestones{/number}\",\n      \"notifications_url\": \"https://api.github.com/repos/zouhir/preact-habitat/notifications{?since,all,participating}\",\n      \"labels_url\": \"https://api.github.com/repos/zouhir/preact-habitat/labels{/name}\",\n      \"releases_url\": \"https://api.github.com/repos/zouhir/preact-habitat/releases{/id}\",\n      \"deployments_url\": \"https://api.github.com/repos/zouhir/preact-habitat/deployments\",\n      \"created_at\": \"2017-01-17T12:08:35Z\",\n      \"updated_at\": \"2020-05-11T05:49:46Z\",\n      \"pushed_at\": \"2019-08-09T15:22:17Z\",\n      \"git_url\": \"git://github.com/zouhir/preact-habitat.git\",\n      \"ssh_url\": \"git@github.com:zouhir/preact-habitat.git\",\n      \"clone_url\": \"https://github.com/zouhir/preact-habitat.git\",\n      \"svn_url\": \"https://github.com/zouhir/preact-habitat\",\n      \"homepage\": \"\",\n      \"size\": 1467,\n      \"stargazers_count\": 399,\n      \"watchers_count\": 399,\n      \"language\": \"JavaScript\",\n      \"has_issues\": true,\n      \"has_projects\": false,\n      \"has_downloads\": true,\n      \"has_wiki\": false,\n      \"has_pages\": false,\n      \"forks_count\": 31,\n      \"mirror_url\": null,\n      \"archived\": false,\n      \"disabled\": false,\n      \"open_issues_count\": 11,\n      \"license\": {\n        \"key\": \"mit\",\n        \"name\": \"MIT License\",\n        \"spdx_id\": \"MIT\",\n        \"url\": \"https://api.github.com/licenses/mit\",\n        \"node_id\": \"MDc6TGljZW5zZTEz\"\n      },\n      \"forks\": 31,\n      \"open_issues\": 11,\n      \"watchers\": 399,\n      \"default_branch\": \"master\",\n      \"score\": 1.0\n    },\n    {\n      \"id\": 97216102,\n      \"node_id\": \"MDEwOlJlcG9zaXRvcnk5NzIxNjEwMg==\",\n      \"name\": \"gitalk\",\n      \"full_name\": \"gitalk/gitalk\",\n      \"private\": false,\n      \"owner\": {\n        \"login\": \"gitalk\",\n        \"id\": 29697133,\n        \"node_id\": \"MDEyOk9yZ2FuaXphdGlvbjI5Njk3MTMz\",\n        \"avatar_url\": \"https://avatars1.githubusercontent.com/u/29697133?v=4\",\n        \"gravatar_id\": \"\",\n        \"url\": \"https://api.github.com/users/gitalk\",\n        \"html_url\": \"https://github.com/gitalk\",\n        \"followers_url\": \"https://api.github.com/users/gitalk/followers\",\n        \"following_url\": \"https://api.github.com/users/gitalk/following{/other_user}\",\n        \"gists_url\": \"https://api.github.com/users/gitalk/gists{/gist_id}\",\n        \"starred_url\": \"https://api.github.com/users/gitalk/starred{/owner}{/repo}\",\n        \"subscriptions_url\": \"https://api.github.com/users/gitalk/subscriptions\",\n        \"organizations_url\": \"https://api.github.com/users/gitalk/orgs\",\n        \"repos_url\": \"https://api.github.com/users/gitalk/repos\",\n        \"events_url\": \"https://api.github.com/users/gitalk/events{/privacy}\",\n        \"received_events_url\": \"https://api.github.com/users/gitalk/received_events\",\n        \"type\": \"Organization\",\n        \"site_admin\": false\n      },\n      \"html_url\": \"https://github.com/gitalk/gitalk\",\n      \"description\": \"Gitalk is a modern comment component based on Github Issue and Preact.\",\n      \"fork\": false,\n      \"url\": \"https://api.github.com/repos/gitalk/gitalk\",\n      \"forks_url\": \"https://api.github.com/repos/gitalk/gitalk/forks\",\n      \"keys_url\": \"https://api.github.com/repos/gitalk/gitalk/keys{/key_id}\",\n      \"collaborators_url\": \"https://api.github.com/repos/gitalk/gitalk/collaborators{/collaborator}\",\n      \"teams_url\": \"https://api.github.com/repos/gitalk/gitalk/teams\",\n      \"hooks_url\": \"https://api.github.com/repos/gitalk/gitalk/hooks\",\n      \"issue_events_url\": \"https://api.github.com/repos/gitalk/gitalk/issues/events{/number}\",\n      \"events_url\": \"https://api.github.com/repos/gitalk/gitalk/events\",\n      \"assignees_url\": \"https://api.github.com/repos/gitalk/gitalk/assignees{/user}\",\n      \"branches_url\": \"https://api.github.com/repos/gitalk/gitalk/branches{/branch}\",\n      \"tags_url\": \"https://api.github.com/repos/gitalk/gitalk/tags\",\n      \"blobs_url\": \"https://api.github.com/repos/gitalk/gitalk/git/blobs{/sha}\",\n      \"git_tags_url\": \"https://api.github.com/repos/gitalk/gitalk/git/tags{/sha}\",\n      \"git_refs_url\": \"https://api.github.com/repos/gitalk/gitalk/git/refs{/sha}\",\n      \"trees_url\": \"https://api.github.com/repos/gitalk/gitalk/git/trees{/sha}\",\n      \"statuses_url\": \"https://api.github.com/repos/gitalk/gitalk/statuses/{sha}\",\n      \"languages_url\": \"https://api.github.com/repos/gitalk/gitalk/languages\",\n      \"stargazers_url\": \"https://api.github.com/repos/gitalk/gitalk/stargazers\",\n      \"contributors_url\": \"https://api.github.com/repos/gitalk/gitalk/contributors\",\n      \"subscribers_url\": \"https://api.github.com/repos/gitalk/gitalk/subscribers\",\n      \"subscription_url\": \"https://api.github.com/repos/gitalk/gitalk/subscription\",\n      \"commits_url\": \"https://api.github.com/repos/gitalk/gitalk/commits{/sha}\",\n      \"git_commits_url\": \"https://api.github.com/repos/gitalk/gitalk/git/commits{/sha}\",\n      \"comments_url\": \"https://api.github.com/repos/gitalk/gitalk/comments{/number}\",\n      \"issue_comment_url\": \"https://api.github.com/repos/gitalk/gitalk/issues/comments{/number}\",\n      \"contents_url\": \"https://api.github.com/repos/gitalk/gitalk/contents/{+path}\",\n      \"compare_url\": \"https://api.github.com/repos/gitalk/gitalk/compare/{base}...{head}\",\n      \"merges_url\": \"https://api.github.com/repos/gitalk/gitalk/merges\",\n      \"archive_url\": \"https://api.github.com/repos/gitalk/gitalk/{archive_format}{/ref}\",\n      \"downloads_url\": \"https://api.github.com/repos/gitalk/gitalk/downloads\",\n      \"issues_url\": \"https://api.github.com/repos/gitalk/gitalk/issues{/number}\",\n      \"pulls_url\": \"https://api.github.com/repos/gitalk/gitalk/pulls{/number}\",\n      \"milestones_url\": \"https://api.github.com/repos/gitalk/gitalk/milestones{/number}\",\n      \"notifications_url\": \"https://api.github.com/repos/gitalk/gitalk/notifications{?since,all,participating}\",\n      \"labels_url\": \"https://api.github.com/repos/gitalk/gitalk/labels{/name}\",\n      \"releases_url\": \"https://api.github.com/repos/gitalk/gitalk/releases{/id}\",\n      \"deployments_url\": \"https://api.github.com/repos/gitalk/gitalk/deployments\",\n      \"created_at\": \"2017-07-14T09:16:22Z\",\n      \"updated_at\": \"2020-05-15T01:23:42Z\",\n      \"pushed_at\": \"2020-05-13T13:38:00Z\",\n      \"git_url\": \"git://github.com/gitalk/gitalk.git\",\n      \"ssh_url\": \"git@github.com:gitalk/gitalk.git\",\n      \"clone_url\": \"https://github.com/gitalk/gitalk.git\",\n      \"svn_url\": \"https://github.com/gitalk/gitalk\",\n      \"homepage\": \"https://gitalk.github.io\",\n      \"size\": 3109,\n      \"stargazers_count\": 4356,\n      \"watchers_count\": 4356,\n      \"language\": \"JavaScript\",\n      \"has_issues\": true,\n      \"has_projects\": true,\n      \"has_downloads\": true,\n      \"has_wiki\": true,\n      \"has_pages\": false,\n      \"forks_count\": 434,\n      \"mirror_url\": null,\n      \"archived\": false,\n      \"disabled\": false,\n      \"open_issues_count\": 80,\n      \"license\": {\n        \"key\": \"mit\",\n        \"name\": \"MIT License\",\n        \"spdx_id\": \"MIT\",\n        \"url\": \"https://api.github.com/licenses/mit\",\n        \"node_id\": \"MDc6TGljZW5zZTEz\"\n      },\n      \"forks\": 434,\n      \"open_issues\": 80,\n      \"watchers\": 4356,\n      \"default_branch\": \"master\",\n      \"score\": 1.0\n    },\n    {\n      \"id\": 74236755,\n      \"node_id\": \"MDEwOlJlcG9zaXRvcnk3NDIzNjc1NQ==\",\n      \"name\": \"fathom\",\n      \"full_name\": \"usefathom/fathom\",\n      \"private\": false,\n      \"owner\": {\n        \"login\": \"usefathom\",\n        \"id\": 38684088,\n        \"node_id\": \"MDEyOk9yZ2FuaXphdGlvbjM4Njg0MDg4\",\n        \"avatar_url\": \"https://avatars0.githubusercontent.com/u/38684088?v=4\",\n        \"gravatar_id\": \"\",\n        \"url\": \"https://api.github.com/users/usefathom\",\n        \"html_url\": \"https://github.com/usefathom\",\n        \"followers_url\": \"https://api.github.com/users/usefathom/followers\",\n        \"following_url\": \"https://api.github.com/users/usefathom/following{/other_user}\",\n        \"gists_url\": \"https://api.github.com/users/usefathom/gists{/gist_id}\",\n        \"starred_url\": \"https://api.github.com/users/usefathom/starred{/owner}{/repo}\",\n        \"subscriptions_url\": \"https://api.github.com/users/usefathom/subscriptions\",\n        \"organizations_url\": \"https://api.github.com/users/usefathom/orgs\",\n        \"repos_url\": \"https://api.github.com/users/usefathom/repos\",\n        \"events_url\": \"https://api.github.com/users/usefathom/events{/privacy}\",\n        \"received_events_url\": \"https://api.github.com/users/usefathom/received_events\",\n        \"type\": \"Organization\",\n        \"site_admin\": false\n      },\n      \"html_url\": \"https://github.com/usefathom/fathom\",\n      \"description\": \"Fathom Lite. Simple, privacy-focused website analytics. Built with Golang & Preact.\",\n      \"fork\": false,\n      \"url\": \"https://api.github.com/repos/usefathom/fathom\",\n      \"forks_url\": \"https://api.github.com/repos/usefathom/fathom/forks\",\n      \"keys_url\": \"https://api.github.com/repos/usefathom/fathom/keys{/key_id}\",\n      \"collaborators_url\": \"https://api.github.com/repos/usefathom/fathom/collaborators{/collaborator}\",\n      \"teams_url\": \"https://api.github.com/repos/usefathom/fathom/teams\",\n      \"hooks_url\": \"https://api.github.com/repos/usefathom/fathom/hooks\",\n      \"issue_events_url\": \"https://api.github.com/repos/usefathom/fathom/issues/events{/number}\",\n      \"events_url\": \"https://api.github.com/repos/usefathom/fathom/events\",\n      \"assignees_url\": \"https://api.github.com/repos/usefathom/fathom/assignees{/user}\",\n      \"branches_url\": \"https://api.github.com/repos/usefathom/fathom/branches{/branch}\",\n      \"tags_url\": \"https://api.github.com/repos/usefathom/fathom/tags\",\n      \"blobs_url\": \"https://api.github.com/repos/usefathom/fathom/git/blobs{/sha}\",\n      \"git_tags_url\": \"https://api.github.com/repos/usefathom/fathom/git/tags{/sha}\",\n      \"git_refs_url\": \"https://api.github.com/repos/usefathom/fathom/git/refs{/sha}\",\n      \"trees_url\": \"https://api.github.com/repos/usefathom/fathom/git/trees{/sha}\",\n      \"statuses_url\": \"https://api.github.com/repos/usefathom/fathom/statuses/{sha}\",\n      \"languages_url\": \"https://api.github.com/repos/usefathom/fathom/languages\",\n      \"stargazers_url\": \"https://api.github.com/repos/usefathom/fathom/stargazers\",\n      \"contributors_url\": \"https://api.github.com/repos/usefathom/fathom/contributors\",\n      \"subscribers_url\": \"https://api.github.com/repos/usefathom/fathom/subscribers\",\n      \"subscription_url\": \"https://api.github.com/repos/usefathom/fathom/subscription\",\n      \"commits_url\": \"https://api.github.com/repos/usefathom/fathom/commits{/sha}\",\n      \"git_commits_url\": \"https://api.github.com/repos/usefathom/fathom/git/commits{/sha}\",\n      \"comments_url\": \"https://api.github.com/repos/usefathom/fathom/comments{/number}\",\n      \"issue_comment_url\": \"https://api.github.com/repos/usefathom/fathom/issues/comments{/number}\",\n      \"contents_url\": \"https://api.github.com/repos/usefathom/fathom/contents/{+path}\",\n      \"compare_url\": \"https://api.github.com/repos/usefathom/fathom/compare/{base}...{head}\",\n      \"merges_url\": \"https://api.github.com/repos/usefathom/fathom/merges\",\n      \"archive_url\": \"https://api.github.com/repos/usefathom/fathom/{archive_format}{/ref}\",\n      \"downloads_url\": \"https://api.github.com/repos/usefathom/fathom/downloads\",\n      \"issues_url\": \"https://api.github.com/repos/usefathom/fathom/issues{/number}\",\n      \"pulls_url\": \"https://api.github.com/repos/usefathom/fathom/pulls{/number}\",\n      \"milestones_url\": \"https://api.github.com/repos/usefathom/fathom/milestones{/number}\",\n      \"notifications_url\": \"https://api.github.com/repos/usefathom/fathom/notifications{?since,all,participating}\",\n      \"labels_url\": \"https://api.github.com/repos/usefathom/fathom/labels{/name}\",\n      \"releases_url\": \"https://api.github.com/repos/usefathom/fathom/releases{/id}\",\n      \"deployments_url\": \"https://api.github.com/repos/usefathom/fathom/deployments\",\n      \"created_at\": \"2016-11-19T21:34:03Z\",\n      \"updated_at\": \"2020-05-14T20:00:22Z\",\n      \"pushed_at\": \"2020-05-08T05:38:09Z\",\n      \"git_url\": \"git://github.com/usefathom/fathom.git\",\n      \"ssh_url\": \"git@github.com:usefathom/fathom.git\",\n      \"clone_url\": \"https://github.com/usefathom/fathom.git\",\n      \"svn_url\": \"https://github.com/usefathom/fathom\",\n      \"homepage\": \"https://usefathom.com/\",\n      \"size\": 14212,\n      \"stargazers_count\": 6461,\n      \"watchers_count\": 6461,\n      \"language\": \"Go\",\n      \"has_issues\": true,\n      \"has_projects\": false,\n      \"has_downloads\": true,\n      \"has_wiki\": false,\n      \"has_pages\": false,\n      \"forks_count\": 283,\n      \"mirror_url\": null,\n      \"archived\": false,\n      \"disabled\": false,\n      \"open_issues_count\": 40,\n      \"license\": {\n        \"key\": \"mit\",\n        \"name\": \"MIT License\",\n        \"spdx_id\": \"MIT\",\n        \"url\": \"https://api.github.com/licenses/mit\",\n        \"node_id\": \"MDc6TGljZW5zZTEz\"\n      },\n      \"forks\": 283,\n      \"open_issues\": 40,\n      \"watchers\": 6461,\n      \"default_branch\": \"master\",\n      \"score\": 1.0\n    },\n    {\n      \"id\": 84757332,\n      \"node_id\": \"MDEwOlJlcG9zaXRvcnk4NDc1NzMzMg==\",\n      \"name\": \"preact-hn\",\n      \"full_name\": \"kristoferbaxter/preact-hn\",\n      \"private\": false,\n      \"owner\": {\n        \"login\": \"kristoferbaxter\",\n        \"id\": 61764,\n        \"node_id\": \"MDQ6VXNlcjYxNzY0\",\n        \"avatar_url\": \"https://avatars1.githubusercontent.com/u/61764?v=4\",\n        \"gravatar_id\": \"\",\n        \"url\": \"https://api.github.com/users/kristoferbaxter\",\n        \"html_url\": \"https://github.com/kristoferbaxter\",\n        \"followers_url\": \"https://api.github.com/users/kristoferbaxter/followers\",\n        \"following_url\": \"https://api.github.com/users/kristoferbaxter/following{/other_user}\",\n        \"gists_url\": \"https://api.github.com/users/kristoferbaxter/gists{/gist_id}\",\n        \"starred_url\": \"https://api.github.com/users/kristoferbaxter/starred{/owner}{/repo}\",\n        \"subscriptions_url\": \"https://api.github.com/users/kristoferbaxter/subscriptions\",\n        \"organizations_url\": \"https://api.github.com/users/kristoferbaxter/orgs\",\n        \"repos_url\": \"https://api.github.com/users/kristoferbaxter/repos\",\n        \"events_url\": \"https://api.github.com/users/kristoferbaxter/events{/privacy}\",\n        \"received_events_url\": \"https://api.github.com/users/kristoferbaxter/received_events\",\n        \"type\": \"User\",\n        \"site_admin\": false\n      },\n      \"html_url\": \"https://github.com/kristoferbaxter/preact-hn\",\n      \"description\": \"Demonstration of Preact used to build Hacker News as a PWA.\",\n      \"fork\": false,\n      \"url\": \"https://api.github.com/repos/kristoferbaxter/preact-hn\",\n      \"forks_url\": \"https://api.github.com/repos/kristoferbaxter/preact-hn/forks\",\n      \"keys_url\": \"https://api.github.com/repos/kristoferbaxter/preact-hn/keys{/key_id}\",\n      \"collaborators_url\": \"https://api.github.com/repos/kristoferbaxter/preact-hn/collaborators{/collaborator}\",\n      \"teams_url\": \"https://api.github.com/repos/kristoferbaxter/preact-hn/teams\",\n      \"hooks_url\": \"https://api.github.com/repos/kristoferbaxter/preact-hn/hooks\",\n      \"issue_events_url\": \"https://api.github.com/repos/kristoferbaxter/preact-hn/issues/events{/number}\",\n      \"events_url\": \"https://api.github.com/repos/kristoferbaxter/preact-hn/events\",\n      \"assignees_url\": \"https://api.github.com/repos/kristoferbaxter/preact-hn/assignees{/user}\",\n      \"branches_url\": \"https://api.github.com/repos/kristoferbaxter/preact-hn/branches{/branch}\",\n      \"tags_url\": \"https://api.github.com/repos/kristoferbaxter/preact-hn/tags\",\n      \"blobs_url\": \"https://api.github.com/repos/kristoferbaxter/preact-hn/git/blobs{/sha}\",\n      \"git_tags_url\": \"https://api.github.com/repos/kristoferbaxter/preact-hn/git/tags{/sha}\",\n      \"git_refs_url\": \"https://api.github.com/repos/kristoferbaxter/preact-hn/git/refs{/sha}\",\n      \"trees_url\": \"https://api.github.com/repos/kristoferbaxter/preact-hn/git/trees{/sha}\",\n      \"statuses_url\": \"https://api.github.com/repos/kristoferbaxter/preact-hn/statuses/{sha}\",\n      \"languages_url\": \"https://api.github.com/repos/kristoferbaxter/preact-hn/languages\",\n      \"stargazers_url\": \"https://api.github.com/repos/kristoferbaxter/preact-hn/stargazers\",\n      \"contributors_url\": \"https://api.github.com/repos/kristoferbaxter/preact-hn/contributors\",\n      \"subscribers_url\": \"https://api.github.com/repos/kristoferbaxter/preact-hn/subscribers\",\n      \"subscription_url\": \"https://api.github.com/repos/kristoferbaxter/preact-hn/subscription\",\n      \"commits_url\": \"https://api.github.com/repos/kristoferbaxter/preact-hn/commits{/sha}\",\n      \"git_commits_url\": \"https://api.github.com/repos/kristoferbaxter/preact-hn/git/commits{/sha}\",\n      \"comments_url\": \"https://api.github.com/repos/kristoferbaxter/preact-hn/comments{/number}\",\n      \"issue_comment_url\": \"https://api.github.com/repos/kristoferbaxter/preact-hn/issues/comments{/number}\",\n      \"contents_url\": \"https://api.github.com/repos/kristoferbaxter/preact-hn/contents/{+path}\",\n      \"compare_url\": \"https://api.github.com/repos/kristoferbaxter/preact-hn/compare/{base}...{head}\",\n      \"merges_url\": \"https://api.github.com/repos/kristoferbaxter/preact-hn/merges\",\n      \"archive_url\": \"https://api.github.com/repos/kristoferbaxter/preact-hn/{archive_format}{/ref}\",\n      \"downloads_url\": \"https://api.github.com/repos/kristoferbaxter/preact-hn/downloads\",\n      \"issues_url\": \"https://api.github.com/repos/kristoferbaxter/preact-hn/issues{/number}\",\n      \"pulls_url\": \"https://api.github.com/repos/kristoferbaxter/preact-hn/pulls{/number}\",\n      \"milestones_url\": \"https://api.github.com/repos/kristoferbaxter/preact-hn/milestones{/number}\",\n      \"notifications_url\": \"https://api.github.com/repos/kristoferbaxter/preact-hn/notifications{?since,all,participating}\",\n      \"labels_url\": \"https://api.github.com/repos/kristoferbaxter/preact-hn/labels{/name}\",\n      \"releases_url\": \"https://api.github.com/repos/kristoferbaxter/preact-hn/releases{/id}\",\n      \"deployments_url\": \"https://api.github.com/repos/kristoferbaxter/preact-hn/deployments\",\n      \"created_at\": \"2017-03-12T21:05:15Z\",\n      \"updated_at\": \"2020-05-13T13:37:50Z\",\n      \"pushed_at\": \"2018-04-16T16:48:15Z\",\n      \"git_url\": \"git://github.com/kristoferbaxter/preact-hn.git\",\n      \"ssh_url\": \"git@github.com:kristoferbaxter/preact-hn.git\",\n      \"clone_url\": \"https://github.com/kristoferbaxter/preact-hn.git\",\n      \"svn_url\": \"https://github.com/kristoferbaxter/preact-hn\",\n      \"homepage\": null,\n      \"size\": 399,\n      \"stargazers_count\": 301,\n      \"watchers_count\": 301,\n      \"language\": \"TypeScript\",\n      \"has_issues\": true,\n      \"has_projects\": false,\n      \"has_downloads\": true,\n      \"has_wiki\": false,\n      \"has_pages\": false,\n      \"forks_count\": 30,\n      \"mirror_url\": null,\n      \"archived\": false,\n      \"disabled\": false,\n      \"open_issues_count\": 10,\n      \"license\": {\n        \"key\": \"mit\",\n        \"name\": \"MIT License\",\n        \"spdx_id\": \"MIT\",\n        \"url\": \"https://api.github.com/licenses/mit\",\n        \"node_id\": \"MDc6TGljZW5zZTEz\"\n      },\n      \"forks\": 30,\n      \"open_issues\": 10,\n      \"watchers\": 301,\n      \"default_branch\": \"master\",\n      \"score\": 1.0\n    },\n    {\n      \"id\": 60229688,\n      \"node_id\": \"MDEwOlJlcG9zaXRvcnk2MDIyOTY4OA==\",\n      \"name\": \"preact-redux\",\n      \"full_name\": \"developit/preact-redux\",\n      \"private\": false,\n      \"owner\": {\n        \"login\": \"developit\",\n        \"id\": 105127,\n        \"node_id\": \"MDQ6VXNlcjEwNTEyNw==\",\n        \"avatar_url\": \"https://avatars2.githubusercontent.com/u/105127?v=4\",\n        \"gravatar_id\": \"\",\n        \"url\": \"https://api.github.com/users/developit\",\n        \"html_url\": \"https://github.com/developit\",\n        \"followers_url\": \"https://api.github.com/users/developit/followers\",\n        \"following_url\": \"https://api.github.com/users/developit/following{/other_user}\",\n        \"gists_url\": \"https://api.github.com/users/developit/gists{/gist_id}\",\n        \"starred_url\": \"https://api.github.com/users/developit/starred{/owner}{/repo}\",\n        \"subscriptions_url\": \"https://api.github.com/users/developit/subscriptions\",\n        \"organizations_url\": \"https://api.github.com/users/developit/orgs\",\n        \"repos_url\": \"https://api.github.com/users/developit/repos\",\n        \"events_url\": \"https://api.github.com/users/developit/events{/privacy}\",\n        \"received_events_url\": \"https://api.github.com/users/developit/received_events\",\n        \"type\": \"User\",\n        \"site_admin\": false\n      },\n      \"html_url\": \"https://github.com/developit/preact-redux\",\n      \"description\": \":loop: Preact integration for Redux (no shim needed!)\",\n      \"fork\": false,\n      \"url\": \"https://api.github.com/repos/developit/preact-redux\",\n      \"forks_url\": \"https://api.github.com/repos/developit/preact-redux/forks\",\n      \"keys_url\": \"https://api.github.com/repos/developit/preact-redux/keys{/key_id}\",\n      \"collaborators_url\": \"https://api.github.com/repos/developit/preact-redux/collaborators{/collaborator}\",\n      \"teams_url\": \"https://api.github.com/repos/developit/preact-redux/teams\",\n      \"hooks_url\": \"https://api.github.com/repos/developit/preact-redux/hooks\",\n      \"issue_events_url\": \"https://api.github.com/repos/developit/preact-redux/issues/events{/number}\",\n      \"events_url\": \"https://api.github.com/repos/developit/preact-redux/events\",\n      \"assignees_url\": \"https://api.github.com/repos/developit/preact-redux/assignees{/user}\",\n      \"branches_url\": \"https://api.github.com/repos/developit/preact-redux/branches{/branch}\",\n      \"tags_url\": \"https://api.github.com/repos/developit/preact-redux/tags\",\n      \"blobs_url\": \"https://api.github.com/repos/developit/preact-redux/git/blobs{/sha}\",\n      \"git_tags_url\": \"https://api.github.com/repos/developit/preact-redux/git/tags{/sha}\",\n      \"git_refs_url\": \"https://api.github.com/repos/developit/preact-redux/git/refs{/sha}\",\n      \"trees_url\": \"https://api.github.com/repos/developit/preact-redux/git/trees{/sha}\",\n      \"statuses_url\": \"https://api.github.com/repos/developit/preact-redux/statuses/{sha}\",\n      \"languages_url\": \"https://api.github.com/repos/developit/preact-redux/languages\",\n      \"stargazers_url\": \"https://api.github.com/repos/developit/preact-redux/stargazers\",\n      \"contributors_url\": \"https://api.github.com/repos/developit/preact-redux/contributors\",\n      \"subscribers_url\": \"https://api.github.com/repos/developit/preact-redux/subscribers\",\n      \"subscription_url\": \"https://api.github.com/repos/developit/preact-redux/subscription\",\n      \"commits_url\": \"https://api.github.com/repos/developit/preact-redux/commits{/sha}\",\n      \"git_commits_url\": \"https://api.github.com/repos/developit/preact-redux/git/commits{/sha}\",\n      \"comments_url\": \"https://api.github.com/repos/developit/preact-redux/comments{/number}\",\n      \"issue_comment_url\": \"https://api.github.com/repos/developit/preact-redux/issues/comments{/number}\",\n      \"contents_url\": \"https://api.github.com/repos/developit/preact-redux/contents/{+path}\",\n      \"compare_url\": \"https://api.github.com/repos/developit/preact-redux/compare/{base}...{head}\",\n      \"merges_url\": \"https://api.github.com/repos/developit/preact-redux/merges\",\n      \"archive_url\": \"https://api.github.com/repos/developit/preact-redux/{archive_format}{/ref}\",\n      \"downloads_url\": \"https://api.github.com/repos/developit/preact-redux/downloads\",\n      \"issues_url\": \"https://api.github.com/repos/developit/preact-redux/issues{/number}\",\n      \"pulls_url\": \"https://api.github.com/repos/developit/preact-redux/pulls{/number}\",\n      \"milestones_url\": \"https://api.github.com/repos/developit/preact-redux/milestones{/number}\",\n      \"notifications_url\": \"https://api.github.com/repos/developit/preact-redux/notifications{?since,all,participating}\",\n      \"labels_url\": \"https://api.github.com/repos/developit/preact-redux/labels{/name}\",\n      \"releases_url\": \"https://api.github.com/repos/developit/preact-redux/releases{/id}\",\n      \"deployments_url\": \"https://api.github.com/repos/developit/preact-redux/deployments\",\n      \"created_at\": \"2016-06-02T03:28:15Z\",\n      \"updated_at\": \"2020-05-02T14:21:42Z\",\n      \"pushed_at\": \"2020-01-21T20:57:08Z\",\n      \"git_url\": \"git://github.com/developit/preact-redux.git\",\n      \"ssh_url\": \"git@github.com:developit/preact-redux.git\",\n      \"clone_url\": \"https://github.com/developit/preact-redux.git\",\n      \"svn_url\": \"https://github.com/developit/preact-redux\",\n      \"homepage\": \"https://npm.im/preact-redux\",\n      \"size\": 292,\n      \"stargazers_count\": 275,\n      \"watchers_count\": 275,\n      \"language\": \"JavaScript\",\n      \"has_issues\": true,\n      \"has_projects\": true,\n      \"has_downloads\": true,\n      \"has_wiki\": true,\n      \"has_pages\": false,\n      \"forks_count\": 29,\n      \"mirror_url\": null,\n      \"archived\": false,\n      \"disabled\": false,\n      \"open_issues_count\": 16,\n      \"license\": {\n        \"key\": \"mit\",\n        \"name\": \"MIT License\",\n        \"spdx_id\": \"MIT\",\n        \"url\": \"https://api.github.com/licenses/mit\",\n        \"node_id\": \"MDc6TGljZW5zZTEz\"\n      },\n      \"forks\": 29,\n      \"open_issues\": 16,\n      \"watchers\": 275,\n      \"default_branch\": \"master\",\n      \"score\": 1.0\n    },\n    {\n      \"id\": 144045551,\n      \"node_id\": \"MDEwOlJlcG9zaXRvcnkxNDQwNDU1NTE=\",\n      \"name\": \"Rocket.Chat.Livechat\",\n      \"full_name\": \"RocketChat/Rocket.Chat.Livechat\",\n      \"private\": false,\n      \"owner\": {\n        \"login\": \"RocketChat\",\n        \"id\": 12508788,\n        \"node_id\": \"MDEyOk9yZ2FuaXphdGlvbjEyNTA4Nzg4\",\n        \"avatar_url\": \"https://avatars1.githubusercontent.com/u/12508788?v=4\",\n        \"gravatar_id\": \"\",\n        \"url\": \"https://api.github.com/users/RocketChat\",\n        \"html_url\": \"https://github.com/RocketChat\",\n        \"followers_url\": \"https://api.github.com/users/RocketChat/followers\",\n        \"following_url\": \"https://api.github.com/users/RocketChat/following{/other_user}\",\n        \"gists_url\": \"https://api.github.com/users/RocketChat/gists{/gist_id}\",\n        \"starred_url\": \"https://api.github.com/users/RocketChat/starred{/owner}{/repo}\",\n        \"subscriptions_url\": \"https://api.github.com/users/RocketChat/subscriptions\",\n        \"organizations_url\": \"https://api.github.com/users/RocketChat/orgs\",\n        \"repos_url\": \"https://api.github.com/users/RocketChat/repos\",\n        \"events_url\": \"https://api.github.com/users/RocketChat/events{/privacy}\",\n        \"received_events_url\": \"https://api.github.com/users/RocketChat/received_events\",\n        \"type\": \"Organization\",\n        \"site_admin\": false\n      },\n      \"html_url\": \"https://github.com/RocketChat/Rocket.Chat.Livechat\",\n      \"description\": \"New Livechat client written in Preact\",\n      \"fork\": false,\n      \"url\": \"https://api.github.com/repos/RocketChat/Rocket.Chat.Livechat\",\n      \"forks_url\": \"https://api.github.com/repos/RocketChat/Rocket.Chat.Livechat/forks\",\n      \"keys_url\": \"https://api.github.com/repos/RocketChat/Rocket.Chat.Livechat/keys{/key_id}\",\n      \"collaborators_url\": \"https://api.github.com/repos/RocketChat/Rocket.Chat.Livechat/collaborators{/collaborator}\",\n      \"teams_url\": \"https://api.github.com/repos/RocketChat/Rocket.Chat.Livechat/teams\",\n      \"hooks_url\": \"https://api.github.com/repos/RocketChat/Rocket.Chat.Livechat/hooks\",\n      \"issue_events_url\": \"https://api.github.com/repos/RocketChat/Rocket.Chat.Livechat/issues/events{/number}\",\n      \"events_url\": \"https://api.github.com/repos/RocketChat/Rocket.Chat.Livechat/events\",\n      \"assignees_url\": \"https://api.github.com/repos/RocketChat/Rocket.Chat.Livechat/assignees{/user}\",\n      \"branches_url\": \"https://api.github.com/repos/RocketChat/Rocket.Chat.Livechat/branches{/branch}\",\n      \"tags_url\": \"https://api.github.com/repos/RocketChat/Rocket.Chat.Livechat/tags\",\n      \"blobs_url\": \"https://api.github.com/repos/RocketChat/Rocket.Chat.Livechat/git/blobs{/sha}\",\n      \"git_tags_url\": \"https://api.github.com/repos/RocketChat/Rocket.Chat.Livechat/git/tags{/sha}\",\n      \"git_refs_url\": \"https://api.github.com/repos/RocketChat/Rocket.Chat.Livechat/git/refs{/sha}\",\n      \"trees_url\": \"https://api.github.com/repos/RocketChat/Rocket.Chat.Livechat/git/trees{/sha}\",\n      \"statuses_url\": \"https://api.github.com/repos/RocketChat/Rocket.Chat.Livechat/statuses/{sha}\",\n      \"languages_url\": \"https://api.github.com/repos/RocketChat/Rocket.Chat.Livechat/languages\",\n      \"stargazers_url\": \"https://api.github.com/repos/RocketChat/Rocket.Chat.Livechat/stargazers\",\n      \"contributors_url\": \"https://api.github.com/repos/RocketChat/Rocket.Chat.Livechat/contributors\",\n      \"subscribers_url\": \"https://api.github.com/repos/RocketChat/Rocket.Chat.Livechat/subscribers\",\n      \"subscription_url\": \"https://api.github.com/repos/RocketChat/Rocket.Chat.Livechat/subscription\",\n      \"commits_url\": \"https://api.github.com/repos/RocketChat/Rocket.Chat.Livechat/commits{/sha}\",\n      \"git_commits_url\": \"https://api.github.com/repos/RocketChat/Rocket.Chat.Livechat/git/commits{/sha}\",\n      \"comments_url\": \"https://api.github.com/repos/RocketChat/Rocket.Chat.Livechat/comments{/number}\",\n      \"issue_comment_url\": \"https://api.github.com/repos/RocketChat/Rocket.Chat.Livechat/issues/comments{/number}\",\n      \"contents_url\": \"https://api.github.com/repos/RocketChat/Rocket.Chat.Livechat/contents/{+path}\",\n      \"compare_url\": \"https://api.github.com/repos/RocketChat/Rocket.Chat.Livechat/compare/{base}...{head}\",\n      \"merges_url\": \"https://api.github.com/repos/RocketChat/Rocket.Chat.Livechat/merges\",\n      \"archive_url\": \"https://api.github.com/repos/RocketChat/Rocket.Chat.Livechat/{archive_format}{/ref}\",\n      \"downloads_url\": \"https://api.github.com/repos/RocketChat/Rocket.Chat.Livechat/downloads\",\n      \"issues_url\": \"https://api.github.com/repos/RocketChat/Rocket.Chat.Livechat/issues{/number}\",\n      \"pulls_url\": \"https://api.github.com/repos/RocketChat/Rocket.Chat.Livechat/pulls{/number}\",\n      \"milestones_url\": \"https://api.github.com/repos/RocketChat/Rocket.Chat.Livechat/milestones{/number}\",\n      \"notifications_url\": \"https://api.github.com/repos/RocketChat/Rocket.Chat.Livechat/notifications{?since,all,participating}\",\n      \"labels_url\": \"https://api.github.com/repos/RocketChat/Rocket.Chat.Livechat/labels{/name}\",\n      \"releases_url\": \"https://api.github.com/repos/RocketChat/Rocket.Chat.Livechat/releases{/id}\",\n      \"deployments_url\": \"https://api.github.com/repos/RocketChat/Rocket.Chat.Livechat/deployments\",\n      \"created_at\": \"2018-08-08T17:18:37Z\",\n      \"updated_at\": \"2020-05-12T16:10:17Z\",\n      \"pushed_at\": \"2020-05-15T01:18:25Z\",\n      \"git_url\": \"git://github.com/RocketChat/Rocket.Chat.Livechat.git\",\n      \"ssh_url\": \"git@github.com:RocketChat/Rocket.Chat.Livechat.git\",\n      \"clone_url\": \"https://github.com/RocketChat/Rocket.Chat.Livechat.git\",\n      \"svn_url\": \"https://github.com/RocketChat/Rocket.Chat.Livechat\",\n      \"homepage\": \"https://rocket.chat/Rocket.Chat.Livechat\",\n      \"size\": 98221,\n      \"stargazers_count\": 113,\n      \"watchers_count\": 113,\n      \"language\": \"JavaScript\",\n      \"has_issues\": true,\n      \"has_projects\": true,\n      \"has_downloads\": true,\n      \"has_wiki\": true,\n      \"has_pages\": true,\n      \"forks_count\": 77,\n      \"mirror_url\": null,\n      \"archived\": false,\n      \"disabled\": false,\n      \"open_issues_count\": 100,\n      \"license\": {\n        \"key\": \"mit\",\n        \"name\": \"MIT License\",\n        \"spdx_id\": \"MIT\",\n        \"url\": \"https://api.github.com/licenses/mit\",\n        \"node_id\": \"MDc6TGljZW5zZTEz\"\n      },\n      \"forks\": 77,\n      \"open_issues\": 100,\n      \"watchers\": 113,\n      \"default_branch\": \"develop\",\n      \"score\": 1.0\n    },\n    {\n      \"id\": 93886655,\n      \"node_id\": \"MDEwOlJlcG9zaXRvcnk5Mzg4NjY1NQ==\",\n      \"name\": \"preact-i18n\",\n      \"full_name\": \"synacor/preact-i18n\",\n      \"private\": false,\n      \"owner\": {\n        \"login\": \"synacor\",\n        \"id\": 5131423,\n        \"node_id\": \"MDEyOk9yZ2FuaXphdGlvbjUxMzE0MjM=\",\n        \"avatar_url\": \"https://avatars0.githubusercontent.com/u/5131423?v=4\",\n        \"gravatar_id\": \"\",\n        \"url\": \"https://api.github.com/users/synacor\",\n        \"html_url\": \"https://github.com/synacor\",\n        \"followers_url\": \"https://api.github.com/users/synacor/followers\",\n        \"following_url\": \"https://api.github.com/users/synacor/following{/other_user}\",\n        \"gists_url\": \"https://api.github.com/users/synacor/gists{/gist_id}\",\n        \"starred_url\": \"https://api.github.com/users/synacor/starred{/owner}{/repo}\",\n        \"subscriptions_url\": \"https://api.github.com/users/synacor/subscriptions\",\n        \"organizations_url\": \"https://api.github.com/users/synacor/orgs\",\n        \"repos_url\": \"https://api.github.com/users/synacor/repos\",\n        \"events_url\": \"https://api.github.com/users/synacor/events{/privacy}\",\n        \"received_events_url\": \"https://api.github.com/users/synacor/received_events\",\n        \"type\": \"Organization\",\n        \"site_admin\": false\n      },\n      \"html_url\": \"https://github.com/synacor/preact-i18n\",\n      \"description\": \"Simple localization for Preact.\",\n      \"fork\": false,\n      \"url\": \"https://api.github.com/repos/synacor/preact-i18n\",\n      \"forks_url\": \"https://api.github.com/repos/synacor/preact-i18n/forks\",\n      \"keys_url\": \"https://api.github.com/repos/synacor/preact-i18n/keys{/key_id}\",\n      \"collaborators_url\": \"https://api.github.com/repos/synacor/preact-i18n/collaborators{/collaborator}\",\n      \"teams_url\": \"https://api.github.com/repos/synacor/preact-i18n/teams\",\n      \"hooks_url\": \"https://api.github.com/repos/synacor/preact-i18n/hooks\",\n      \"issue_events_url\": \"https://api.github.com/repos/synacor/preact-i18n/issues/events{/number}\",\n      \"events_url\": \"https://api.github.com/repos/synacor/preact-i18n/events\",\n      \"assignees_url\": \"https://api.github.com/repos/synacor/preact-i18n/assignees{/user}\",\n      \"branches_url\": \"https://api.github.com/repos/synacor/preact-i18n/branches{/branch}\",\n      \"tags_url\": \"https://api.github.com/repos/synacor/preact-i18n/tags\",\n      \"blobs_url\": \"https://api.github.com/repos/synacor/preact-i18n/git/blobs{/sha}\",\n      \"git_tags_url\": \"https://api.github.com/repos/synacor/preact-i18n/git/tags{/sha}\",\n      \"git_refs_url\": \"https://api.github.com/repos/synacor/preact-i18n/git/refs{/sha}\",\n      \"trees_url\": \"https://api.github.com/repos/synacor/preact-i18n/git/trees{/sha}\",\n      \"statuses_url\": \"https://api.github.com/repos/synacor/preact-i18n/statuses/{sha}\",\n      \"languages_url\": \"https://api.github.com/repos/synacor/preact-i18n/languages\",\n      \"stargazers_url\": \"https://api.github.com/repos/synacor/preact-i18n/stargazers\",\n      \"contributors_url\": \"https://api.github.com/repos/synacor/preact-i18n/contributors\",\n      \"subscribers_url\": \"https://api.github.com/repos/synacor/preact-i18n/subscribers\",\n      \"subscription_url\": \"https://api.github.com/repos/synacor/preact-i18n/subscription\",\n      \"commits_url\": \"https://api.github.com/repos/synacor/preact-i18n/commits{/sha}\",\n      \"git_commits_url\": \"https://api.github.com/repos/synacor/preact-i18n/git/commits{/sha}\",\n      \"comments_url\": \"https://api.github.com/repos/synacor/preact-i18n/comments{/number}\",\n      \"issue_comment_url\": \"https://api.github.com/repos/synacor/preact-i18n/issues/comments{/number}\",\n      \"contents_url\": \"https://api.github.com/repos/synacor/preact-i18n/contents/{+path}\",\n      \"compare_url\": \"https://api.github.com/repos/synacor/preact-i18n/compare/{base}...{head}\",\n      \"merges_url\": \"https://api.github.com/repos/synacor/preact-i18n/merges\",\n      \"archive_url\": \"https://api.github.com/repos/synacor/preact-i18n/{archive_format}{/ref}\",\n      \"downloads_url\": \"https://api.github.com/repos/synacor/preact-i18n/downloads\",\n      \"issues_url\": \"https://api.github.com/repos/synacor/preact-i18n/issues{/number}\",\n      \"pulls_url\": \"https://api.github.com/repos/synacor/preact-i18n/pulls{/number}\",\n      \"milestones_url\": \"https://api.github.com/repos/synacor/preact-i18n/milestones{/number}\",\n      \"notifications_url\": \"https://api.github.com/repos/synacor/preact-i18n/notifications{?since,all,participating}\",\n      \"labels_url\": \"https://api.github.com/repos/synacor/preact-i18n/labels{/name}\",\n      \"releases_url\": \"https://api.github.com/repos/synacor/preact-i18n/releases{/id}\",\n      \"deployments_url\": \"https://api.github.com/repos/synacor/preact-i18n/deployments\",\n      \"created_at\": \"2017-06-09T18:32:11Z\",\n      \"updated_at\": \"2020-04-29T13:20:54Z\",\n      \"pushed_at\": \"2020-05-05T21:14:41Z\",\n      \"git_url\": \"git://github.com/synacor/preact-i18n.git\",\n      \"ssh_url\": \"git@github.com:synacor/preact-i18n.git\",\n      \"clone_url\": \"https://github.com/synacor/preact-i18n.git\",\n      \"svn_url\": \"https://github.com/synacor/preact-i18n\",\n      \"homepage\": null,\n      \"size\": 233,\n      \"stargazers_count\": 168,\n      \"watchers_count\": 168,\n      \"language\": \"JavaScript\",\n      \"has_issues\": true,\n      \"has_projects\": false,\n      \"has_downloads\": true,\n      \"has_wiki\": true,\n      \"has_pages\": false,\n      \"forks_count\": 22,\n      \"mirror_url\": null,\n      \"archived\": false,\n      \"disabled\": false,\n      \"open_issues_count\": 7,\n      \"license\": {\n        \"key\": \"bsd-3-clause\",\n        \"name\": \"BSD 3-Clause \\\"New\\\" or \\\"Revised\\\" License\",\n        \"spdx_id\": \"BSD-3-Clause\",\n        \"url\": \"https://api.github.com/licenses/bsd-3-clause\",\n        \"node_id\": \"MDc6TGljZW5zZTU=\"\n      },\n      \"forks\": 22,\n      \"open_issues\": 7,\n      \"watchers\": 168,\n      \"default_branch\": \"master\",\n      \"score\": 1.0\n    },\n    {\n      \"id\": 16177735,\n      \"node_id\": \"MDEwOlJlcG9zaXRvcnkxNjE3NzczNQ==\",\n      \"name\": \"redux-websocket-example\",\n      \"full_name\": \"maxnachlinger/redux-websocket-example\",\n      \"private\": false,\n      \"owner\": {\n        \"login\": \"maxnachlinger\",\n        \"id\": 1207210,\n        \"node_id\": \"MDQ6VXNlcjEyMDcyMTA=\",\n        \"avatar_url\": \"https://avatars3.githubusercontent.com/u/1207210?v=4\",\n        \"gravatar_id\": \"\",\n        \"url\": \"https://api.github.com/users/maxnachlinger\",\n        \"html_url\": \"https://github.com/maxnachlinger\",\n        \"followers_url\": \"https://api.github.com/users/maxnachlinger/followers\",\n        \"following_url\": \"https://api.github.com/users/maxnachlinger/following{/other_user}\",\n        \"gists_url\": \"https://api.github.com/users/maxnachlinger/gists{/gist_id}\",\n        \"starred_url\": \"https://api.github.com/users/maxnachlinger/starred{/owner}{/repo}\",\n        \"subscriptions_url\": \"https://api.github.com/users/maxnachlinger/subscriptions\",\n        \"organizations_url\": \"https://api.github.com/users/maxnachlinger/orgs\",\n        \"repos_url\": \"https://api.github.com/users/maxnachlinger/repos\",\n        \"events_url\": \"https://api.github.com/users/maxnachlinger/events{/privacy}\",\n        \"received_events_url\": \"https://api.github.com/users/maxnachlinger/received_events\",\n        \"type\": \"User\",\n        \"site_admin\": false\n      },\n      \"html_url\": \"https://github.com/maxnachlinger/redux-websocket-example\",\n      \"description\": \"Preact/Redux + Websocket Example: For Fun\",\n      \"fork\": false,\n      \"url\": \"https://api.github.com/repos/maxnachlinger/redux-websocket-example\",\n      \"forks_url\": \"https://api.github.com/repos/maxnachlinger/redux-websocket-example/forks\",\n      \"keys_url\": \"https://api.github.com/repos/maxnachlinger/redux-websocket-example/keys{/key_id}\",\n      \"collaborators_url\": \"https://api.github.com/repos/maxnachlinger/redux-websocket-example/collaborators{/collaborator}\",\n      \"teams_url\": \"https://api.github.com/repos/maxnachlinger/redux-websocket-example/teams\",\n      \"hooks_url\": \"https://api.github.com/repos/maxnachlinger/redux-websocket-example/hooks\",\n      \"issue_events_url\": \"https://api.github.com/repos/maxnachlinger/redux-websocket-example/issues/events{/number}\",\n      \"events_url\": \"https://api.github.com/repos/maxnachlinger/redux-websocket-example/events\",\n      \"assignees_url\": \"https://api.github.com/repos/maxnachlinger/redux-websocket-example/assignees{/user}\",\n      \"branches_url\": \"https://api.github.com/repos/maxnachlinger/redux-websocket-example/branches{/branch}\",\n      \"tags_url\": \"https://api.github.com/repos/maxnachlinger/redux-websocket-example/tags\",\n      \"blobs_url\": \"https://api.github.com/repos/maxnachlinger/redux-websocket-example/git/blobs{/sha}\",\n      \"git_tags_url\": \"https://api.github.com/repos/maxnachlinger/redux-websocket-example/git/tags{/sha}\",\n      \"git_refs_url\": \"https://api.github.com/repos/maxnachlinger/redux-websocket-example/git/refs{/sha}\",\n      \"trees_url\": \"https://api.github.com/repos/maxnachlinger/redux-websocket-example/git/trees{/sha}\",\n      \"statuses_url\": \"https://api.github.com/repos/maxnachlinger/redux-websocket-example/statuses/{sha}\",\n      \"languages_url\": \"https://api.github.com/repos/maxnachlinger/redux-websocket-example/languages\",\n      \"stargazers_url\": \"https://api.github.com/repos/maxnachlinger/redux-websocket-example/stargazers\",\n      \"contributors_url\": \"https://api.github.com/repos/maxnachlinger/redux-websocket-example/contributors\",\n      \"subscribers_url\": \"https://api.github.com/repos/maxnachlinger/redux-websocket-example/subscribers\",\n      \"subscription_url\": \"https://api.github.com/repos/maxnachlinger/redux-websocket-example/subscription\",\n      \"commits_url\": \"https://api.github.com/repos/maxnachlinger/redux-websocket-example/commits{/sha}\",\n      \"git_commits_url\": \"https://api.github.com/repos/maxnachlinger/redux-websocket-example/git/commits{/sha}\",\n      \"comments_url\": \"https://api.github.com/repos/maxnachlinger/redux-websocket-example/comments{/number}\",\n      \"issue_comment_url\": \"https://api.github.com/repos/maxnachlinger/redux-websocket-example/issues/comments{/number}\",\n      \"contents_url\": \"https://api.github.com/repos/maxnachlinger/redux-websocket-example/contents/{+path}\",\n      \"compare_url\": \"https://api.github.com/repos/maxnachlinger/redux-websocket-example/compare/{base}...{head}\",\n      \"merges_url\": \"https://api.github.com/repos/maxnachlinger/redux-websocket-example/merges\",\n      \"archive_url\": \"https://api.github.com/repos/maxnachlinger/redux-websocket-example/{archive_format}{/ref}\",\n      \"downloads_url\": \"https://api.github.com/repos/maxnachlinger/redux-websocket-example/downloads\",\n      \"issues_url\": \"https://api.github.com/repos/maxnachlinger/redux-websocket-example/issues{/number}\",\n      \"pulls_url\": \"https://api.github.com/repos/maxnachlinger/redux-websocket-example/pulls{/number}\",\n      \"milestones_url\": \"https://api.github.com/repos/maxnachlinger/redux-websocket-example/milestones{/number}\",\n      \"notifications_url\": \"https://api.github.com/repos/maxnachlinger/redux-websocket-example/notifications{?since,all,participating}\",\n      \"labels_url\": \"https://api.github.com/repos/maxnachlinger/redux-websocket-example/labels{/name}\",\n      \"releases_url\": \"https://api.github.com/repos/maxnachlinger/redux-websocket-example/releases{/id}\",\n      \"deployments_url\": \"https://api.github.com/repos/maxnachlinger/redux-websocket-example/deployments\",\n      \"created_at\": \"2014-01-23T16:18:34Z\",\n      \"updated_at\": \"2020-04-20T12:29:23Z\",\n      \"pushed_at\": \"2020-01-29T18:47:25Z\",\n      \"git_url\": \"git://github.com/maxnachlinger/redux-websocket-example.git\",\n      \"ssh_url\": \"git@github.com:maxnachlinger/redux-websocket-example.git\",\n      \"clone_url\": \"https://github.com/maxnachlinger/redux-websocket-example.git\",\n      \"svn_url\": \"https://github.com/maxnachlinger/redux-websocket-example\",\n      \"homepage\": \"\",\n      \"size\": 682,\n      \"stargazers_count\": 255,\n      \"watchers_count\": 255,\n      \"language\": \"JavaScript\",\n      \"has_issues\": true,\n      \"has_projects\": true,\n      \"has_downloads\": true,\n      \"has_wiki\": true,\n      \"has_pages\": false,\n      \"forks_count\": 44,\n      \"mirror_url\": null,\n      \"archived\": false,\n      \"disabled\": false,\n      \"open_issues_count\": 0,\n      \"license\": null,\n      \"forks\": 44,\n      \"open_issues\": 0,\n      \"watchers\": 255,\n      \"default_branch\": \"master\",\n      \"score\": 1.0\n    },\n    {\n      \"id\": 50541843,\n      \"node_id\": \"MDEwOlJlcG9zaXRvcnk1MDU0MTg0Mw==\",\n      \"name\": \"preact-mdl\",\n      \"full_name\": \"developit/preact-mdl\",\n      \"private\": false,\n      \"owner\": {\n        \"login\": \"developit\",\n        \"id\": 105127,\n        \"node_id\": \"MDQ6VXNlcjEwNTEyNw==\",\n        \"avatar_url\": \"https://avatars2.githubusercontent.com/u/105127?v=4\",\n        \"gravatar_id\": \"\",\n        \"url\": \"https://api.github.com/users/developit\",\n        \"html_url\": \"https://github.com/developit\",\n        \"followers_url\": \"https://api.github.com/users/developit/followers\",\n        \"following_url\": \"https://api.github.com/users/developit/following{/other_user}\",\n        \"gists_url\": \"https://api.github.com/users/developit/gists{/gist_id}\",\n        \"starred_url\": \"https://api.github.com/users/developit/starred{/owner}{/repo}\",\n        \"subscriptions_url\": \"https://api.github.com/users/developit/subscriptions\",\n        \"organizations_url\": \"https://api.github.com/users/developit/orgs\",\n        \"repos_url\": \"https://api.github.com/users/developit/repos\",\n        \"events_url\": \"https://api.github.com/users/developit/events{/privacy}\",\n        \"received_events_url\": \"https://api.github.com/users/developit/received_events\",\n        \"type\": \"User\",\n        \"site_admin\": false\n      },\n      \"html_url\": \"https://github.com/developit/preact-mdl\",\n      \"description\": \":boom: A collection of Preact Components that encapsulate Google's Material Design Lite.\",\n      \"fork\": false,\n      \"url\": \"https://api.github.com/repos/developit/preact-mdl\",\n      \"forks_url\": \"https://api.github.com/repos/developit/preact-mdl/forks\",\n      \"keys_url\": \"https://api.github.com/repos/developit/preact-mdl/keys{/key_id}\",\n      \"collaborators_url\": \"https://api.github.com/repos/developit/preact-mdl/collaborators{/collaborator}\",\n      \"teams_url\": \"https://api.github.com/repos/developit/preact-mdl/teams\",\n      \"hooks_url\": \"https://api.github.com/repos/developit/preact-mdl/hooks\",\n      \"issue_events_url\": \"https://api.github.com/repos/developit/preact-mdl/issues/events{/number}\",\n      \"events_url\": \"https://api.github.com/repos/developit/preact-mdl/events\",\n      \"assignees_url\": \"https://api.github.com/repos/developit/preact-mdl/assignees{/user}\",\n      \"branches_url\": \"https://api.github.com/repos/developit/preact-mdl/branches{/branch}\",\n      \"tags_url\": \"https://api.github.com/repos/developit/preact-mdl/tags\",\n      \"blobs_url\": \"https://api.github.com/repos/developit/preact-mdl/git/blobs{/sha}\",\n      \"git_tags_url\": \"https://api.github.com/repos/developit/preact-mdl/git/tags{/sha}\",\n      \"git_refs_url\": \"https://api.github.com/repos/developit/preact-mdl/git/refs{/sha}\",\n      \"trees_url\": \"https://api.github.com/repos/developit/preact-mdl/git/trees{/sha}\",\n      \"statuses_url\": \"https://api.github.com/repos/developit/preact-mdl/statuses/{sha}\",\n      \"languages_url\": \"https://api.github.com/repos/developit/preact-mdl/languages\",\n      \"stargazers_url\": \"https://api.github.com/repos/developit/preact-mdl/stargazers\",\n      \"contributors_url\": \"https://api.github.com/repos/developit/preact-mdl/contributors\",\n      \"subscribers_url\": \"https://api.github.com/repos/developit/preact-mdl/subscribers\",\n      \"subscription_url\": \"https://api.github.com/repos/developit/preact-mdl/subscription\",\n      \"commits_url\": \"https://api.github.com/repos/developit/preact-mdl/commits{/sha}\",\n      \"git_commits_url\": \"https://api.github.com/repos/developit/preact-mdl/git/commits{/sha}\",\n      \"comments_url\": \"https://api.github.com/repos/developit/preact-mdl/comments{/number}\",\n      \"issue_comment_url\": \"https://api.github.com/repos/developit/preact-mdl/issues/comments{/number}\",\n      \"contents_url\": \"https://api.github.com/repos/developit/preact-mdl/contents/{+path}\",\n      \"compare_url\": \"https://api.github.com/repos/developit/preact-mdl/compare/{base}...{head}\",\n      \"merges_url\": \"https://api.github.com/repos/developit/preact-mdl/merges\",\n      \"archive_url\": \"https://api.github.com/repos/developit/preact-mdl/{archive_format}{/ref}\",\n      \"downloads_url\": \"https://api.github.com/repos/developit/preact-mdl/downloads\",\n      \"issues_url\": \"https://api.github.com/repos/developit/preact-mdl/issues{/number}\",\n      \"pulls_url\": \"https://api.github.com/repos/developit/preact-mdl/pulls{/number}\",\n      \"milestones_url\": \"https://api.github.com/repos/developit/preact-mdl/milestones{/number}\",\n      \"notifications_url\": \"https://api.github.com/repos/developit/preact-mdl/notifications{?since,all,participating}\",\n      \"labels_url\": \"https://api.github.com/repos/developit/preact-mdl/labels{/name}\",\n      \"releases_url\": \"https://api.github.com/repos/developit/preact-mdl/releases{/id}\",\n      \"deployments_url\": \"https://api.github.com/repos/developit/preact-mdl/deployments\",\n      \"created_at\": \"2016-01-27T22:16:37Z\",\n      \"updated_at\": \"2020-03-22T21:17:17Z\",\n      \"pushed_at\": \"2018-07-18T23:43:09Z\",\n      \"git_url\": \"git://github.com/developit/preact-mdl.git\",\n      \"ssh_url\": \"git@github.com:developit/preact-mdl.git\",\n      \"clone_url\": \"https://github.com/developit/preact-mdl.git\",\n      \"svn_url\": \"https://github.com/developit/preact-mdl\",\n      \"homepage\": \"\",\n      \"size\": 47,\n      \"stargazers_count\": 178,\n      \"watchers_count\": 178,\n      \"language\": \"JavaScript\",\n      \"has_issues\": true,\n      \"has_projects\": true,\n      \"has_downloads\": true,\n      \"has_wiki\": true,\n      \"has_pages\": false,\n      \"forks_count\": 27,\n      \"mirror_url\": null,\n      \"archived\": false,\n      \"disabled\": false,\n      \"open_issues_count\": 10,\n      \"license\": {\n        \"key\": \"mit\",\n        \"name\": \"MIT License\",\n        \"spdx_id\": \"MIT\",\n        \"url\": \"https://api.github.com/licenses/mit\",\n        \"node_id\": \"MDc6TGljZW5zZTEz\"\n      },\n      \"forks\": 27,\n      \"open_issues\": 10,\n      \"watchers\": 178,\n      \"default_branch\": \"master\",\n      \"score\": 1.0\n    },\n    {\n      \"id\": 81686392,\n      \"node_id\": \"MDEwOlJlcG9zaXRvcnk4MTY4NjM5Mg==\",\n      \"name\": \"preact-minimal\",\n      \"full_name\": \"aganglada/preact-minimal\",\n      \"private\": false,\n      \"owner\": {\n        \"login\": \"aganglada\",\n        \"id\": 922348,\n        \"node_id\": \"MDQ6VXNlcjkyMjM0OA==\",\n        \"avatar_url\": \"https://avatars0.githubusercontent.com/u/922348?v=4\",\n        \"gravatar_id\": \"\",\n        \"url\": \"https://api.github.com/users/aganglada\",\n        \"html_url\": \"https://github.com/aganglada\",\n        \"followers_url\": \"https://api.github.com/users/aganglada/followers\",\n        \"following_url\": \"https://api.github.com/users/aganglada/following{/other_user}\",\n        \"gists_url\": \"https://api.github.com/users/aganglada/gists{/gist_id}\",\n        \"starred_url\": \"https://api.github.com/users/aganglada/starred{/owner}{/repo}\",\n        \"subscriptions_url\": \"https://api.github.com/users/aganglada/subscriptions\",\n        \"organizations_url\": \"https://api.github.com/users/aganglada/orgs\",\n        \"repos_url\": \"https://api.github.com/users/aganglada/repos\",\n        \"events_url\": \"https://api.github.com/users/aganglada/events{/privacy}\",\n        \"received_events_url\": \"https://api.github.com/users/aganglada/received_events\",\n        \"type\": \"User\",\n        \"site_admin\": false\n      },\n      \"html_url\": \"https://github.com/aganglada/preact-minimal\",\n      \"description\": \"🚀 Minimal preact structure\",\n      \"fork\": false,\n      \"url\": \"https://api.github.com/repos/aganglada/preact-minimal\",\n      \"forks_url\": \"https://api.github.com/repos/aganglada/preact-minimal/forks\",\n      \"keys_url\": \"https://api.github.com/repos/aganglada/preact-minimal/keys{/key_id}\",\n      \"collaborators_url\": \"https://api.github.com/repos/aganglada/preact-minimal/collaborators{/collaborator}\",\n      \"teams_url\": \"https://api.github.com/repos/aganglada/preact-minimal/teams\",\n      \"hooks_url\": \"https://api.github.com/repos/aganglada/preact-minimal/hooks\",\n      \"issue_events_url\": \"https://api.github.com/repos/aganglada/preact-minimal/issues/events{/number}\",\n      \"events_url\": \"https://api.github.com/repos/aganglada/preact-minimal/events\",\n      \"assignees_url\": \"https://api.github.com/repos/aganglada/preact-minimal/assignees{/user}\",\n      \"branches_url\": \"https://api.github.com/repos/aganglada/preact-minimal/branches{/branch}\",\n      \"tags_url\": \"https://api.github.com/repos/aganglada/preact-minimal/tags\",\n      \"blobs_url\": \"https://api.github.com/repos/aganglada/preact-minimal/git/blobs{/sha}\",\n      \"git_tags_url\": \"https://api.github.com/repos/aganglada/preact-minimal/git/tags{/sha}\",\n      \"git_refs_url\": \"https://api.github.com/repos/aganglada/preact-minimal/git/refs{/sha}\",\n      \"trees_url\": \"https://api.github.com/repos/aganglada/preact-minimal/git/trees{/sha}\",\n      \"statuses_url\": \"https://api.github.com/repos/aganglada/preact-minimal/statuses/{sha}\",\n      \"languages_url\": \"https://api.github.com/repos/aganglada/preact-minimal/languages\",\n      \"stargazers_url\": \"https://api.github.com/repos/aganglada/preact-minimal/stargazers\",\n      \"contributors_url\": \"https://api.github.com/repos/aganglada/preact-minimal/contributors\",\n      \"subscribers_url\": \"https://api.github.com/repos/aganglada/preact-minimal/subscribers\",\n      \"subscription_url\": \"https://api.github.com/repos/aganglada/preact-minimal/subscription\",\n      \"commits_url\": \"https://api.github.com/repos/aganglada/preact-minimal/commits{/sha}\",\n      \"git_commits_url\": \"https://api.github.com/repos/aganglada/preact-minimal/git/commits{/sha}\",\n      \"comments_url\": \"https://api.github.com/repos/aganglada/preact-minimal/comments{/number}\",\n      \"issue_comment_url\": \"https://api.github.com/repos/aganglada/preact-minimal/issues/comments{/number}\",\n      \"contents_url\": \"https://api.github.com/repos/aganglada/preact-minimal/contents/{+path}\",\n      \"compare_url\": \"https://api.github.com/repos/aganglada/preact-minimal/compare/{base}...{head}\",\n      \"merges_url\": \"https://api.github.com/repos/aganglada/preact-minimal/merges\",\n      \"archive_url\": \"https://api.github.com/repos/aganglada/preact-minimal/{archive_format}{/ref}\",\n      \"downloads_url\": \"https://api.github.com/repos/aganglada/preact-minimal/downloads\",\n      \"issues_url\": \"https://api.github.com/repos/aganglada/preact-minimal/issues{/number}\",\n      \"pulls_url\": \"https://api.github.com/repos/aganglada/preact-minimal/pulls{/number}\",\n      \"milestones_url\": \"https://api.github.com/repos/aganglada/preact-minimal/milestones{/number}\",\n      \"notifications_url\": \"https://api.github.com/repos/aganglada/preact-minimal/notifications{?since,all,participating}\",\n      \"labels_url\": \"https://api.github.com/repos/aganglada/preact-minimal/labels{/name}\",\n      \"releases_url\": \"https://api.github.com/repos/aganglada/preact-minimal/releases{/id}\",\n      \"deployments_url\": \"https://api.github.com/repos/aganglada/preact-minimal/deployments\",\n      \"created_at\": \"2017-02-11T22:22:11Z\",\n      \"updated_at\": \"2020-04-23T20:31:50Z\",\n      \"pushed_at\": \"2019-09-19T14:22:23Z\",\n      \"git_url\": \"git://github.com/aganglada/preact-minimal.git\",\n      \"ssh_url\": \"git@github.com:aganglada/preact-minimal.git\",\n      \"clone_url\": \"https://github.com/aganglada/preact-minimal.git\",\n      \"svn_url\": \"https://github.com/aganglada/preact-minimal\",\n      \"homepage\": \"\",\n      \"size\": 283,\n      \"stargazers_count\": 132,\n      \"watchers_count\": 132,\n      \"language\": \"JavaScript\",\n      \"has_issues\": true,\n      \"has_projects\": true,\n      \"has_downloads\": true,\n      \"has_wiki\": true,\n      \"has_pages\": false,\n      \"forks_count\": 19,\n      \"mirror_url\": null,\n      \"archived\": false,\n      \"disabled\": false,\n      \"open_issues_count\": 3,\n      \"license\": {\n        \"key\": \"mit\",\n        \"name\": \"MIT License\",\n        \"spdx_id\": \"MIT\",\n        \"url\": \"https://api.github.com/licenses/mit\",\n        \"node_id\": \"MDc6TGljZW5zZTEz\"\n      },\n      \"forks\": 19,\n      \"open_issues\": 3,\n      \"watchers\": 132,\n      \"default_branch\": \"master\",\n      \"score\": 1.0\n    },\n    {\n      \"id\": 50375662,\n      \"node_id\": \"MDEwOlJlcG9zaXRvcnk1MDM3NTY2Mg==\",\n      \"name\": \"preact-markup\",\n      \"full_name\": \"developit/preact-markup\",\n      \"private\": false,\n      \"owner\": {\n        \"login\": \"developit\",\n        \"id\": 105127,\n        \"node_id\": \"MDQ6VXNlcjEwNTEyNw==\",\n        \"avatar_url\": \"https://avatars2.githubusercontent.com/u/105127?v=4\",\n        \"gravatar_id\": \"\",\n        \"url\": \"https://api.github.com/users/developit\",\n        \"html_url\": \"https://github.com/developit\",\n        \"followers_url\": \"https://api.github.com/users/developit/followers\",\n        \"following_url\": \"https://api.github.com/users/developit/following{/other_user}\",\n        \"gists_url\": \"https://api.github.com/users/developit/gists{/gist_id}\",\n        \"starred_url\": \"https://api.github.com/users/developit/starred{/owner}{/repo}\",\n        \"subscriptions_url\": \"https://api.github.com/users/developit/subscriptions\",\n        \"organizations_url\": \"https://api.github.com/users/developit/orgs\",\n        \"repos_url\": \"https://api.github.com/users/developit/repos\",\n        \"events_url\": \"https://api.github.com/users/developit/events{/privacy}\",\n        \"received_events_url\": \"https://api.github.com/users/developit/received_events\",\n        \"type\": \"User\",\n        \"site_admin\": false\n      },\n      \"html_url\": \"https://github.com/developit/preact-markup\",\n      \"description\": \":zap: Render HTML5 as VDOM, with Components as Custom Elements!\",\n      \"fork\": false,\n      \"url\": \"https://api.github.com/repos/developit/preact-markup\",\n      \"forks_url\": \"https://api.github.com/repos/developit/preact-markup/forks\",\n      \"keys_url\": \"https://api.github.com/repos/developit/preact-markup/keys{/key_id}\",\n      \"collaborators_url\": \"https://api.github.com/repos/developit/preact-markup/collaborators{/collaborator}\",\n      \"teams_url\": \"https://api.github.com/repos/developit/preact-markup/teams\",\n      \"hooks_url\": \"https://api.github.com/repos/developit/preact-markup/hooks\",\n      \"issue_events_url\": \"https://api.github.com/repos/developit/preact-markup/issues/events{/number}\",\n      \"events_url\": \"https://api.github.com/repos/developit/preact-markup/events\",\n      \"assignees_url\": \"https://api.github.com/repos/developit/preact-markup/assignees{/user}\",\n      \"branches_url\": \"https://api.github.com/repos/developit/preact-markup/branches{/branch}\",\n      \"tags_url\": \"https://api.github.com/repos/developit/preact-markup/tags\",\n      \"blobs_url\": \"https://api.github.com/repos/developit/preact-markup/git/blobs{/sha}\",\n      \"git_tags_url\": \"https://api.github.com/repos/developit/preact-markup/git/tags{/sha}\",\n      \"git_refs_url\": \"https://api.github.com/repos/developit/preact-markup/git/refs{/sha}\",\n      \"trees_url\": \"https://api.github.com/repos/developit/preact-markup/git/trees{/sha}\",\n      \"statuses_url\": \"https://api.github.com/repos/developit/preact-markup/statuses/{sha}\",\n      \"languages_url\": \"https://api.github.com/repos/developit/preact-markup/languages\",\n      \"stargazers_url\": \"https://api.github.com/repos/developit/preact-markup/stargazers\",\n      \"contributors_url\": \"https://api.github.com/repos/developit/preact-markup/contributors\",\n      \"subscribers_url\": \"https://api.github.com/repos/developit/preact-markup/subscribers\",\n      \"subscription_url\": \"https://api.github.com/repos/developit/preact-markup/subscription\",\n      \"commits_url\": \"https://api.github.com/repos/developit/preact-markup/commits{/sha}\",\n      \"git_commits_url\": \"https://api.github.com/repos/developit/preact-markup/git/commits{/sha}\",\n      \"comments_url\": \"https://api.github.com/repos/developit/preact-markup/comments{/number}\",\n      \"issue_comment_url\": \"https://api.github.com/repos/developit/preact-markup/issues/comments{/number}\",\n      \"contents_url\": \"https://api.github.com/repos/developit/preact-markup/contents/{+path}\",\n      \"compare_url\": \"https://api.github.com/repos/developit/preact-markup/compare/{base}...{head}\",\n      \"merges_url\": \"https://api.github.com/repos/developit/preact-markup/merges\",\n      \"archive_url\": \"https://api.github.com/repos/developit/preact-markup/{archive_format}{/ref}\",\n      \"downloads_url\": \"https://api.github.com/repos/developit/preact-markup/downloads\",\n      \"issues_url\": \"https://api.github.com/repos/developit/preact-markup/issues{/number}\",\n      \"pulls_url\": \"https://api.github.com/repos/developit/preact-markup/pulls{/number}\",\n      \"milestones_url\": \"https://api.github.com/repos/developit/preact-markup/milestones{/number}\",\n      \"notifications_url\": \"https://api.github.com/repos/developit/preact-markup/notifications{?since,all,participating}\",\n      \"labels_url\": \"https://api.github.com/repos/developit/preact-markup/labels{/name}\",\n      \"releases_url\": \"https://api.github.com/repos/developit/preact-markup/releases{/id}\",\n      \"deployments_url\": \"https://api.github.com/repos/developit/preact-markup/deployments\",\n      \"created_at\": \"2016-01-25T19:36:48Z\",\n      \"updated_at\": \"2020-05-14T04:24:16Z\",\n      \"pushed_at\": \"2020-04-22T22:17:43Z\",\n      \"git_url\": \"git://github.com/developit/preact-markup.git\",\n      \"ssh_url\": \"git@github.com:developit/preact-markup.git\",\n      \"clone_url\": \"https://github.com/developit/preact-markup.git\",\n      \"svn_url\": \"https://github.com/developit/preact-markup\",\n      \"homepage\": \"http://npm.im/preact-markup\",\n      \"size\": 185,\n      \"stargazers_count\": 143,\n      \"watchers_count\": 143,\n      \"language\": \"JavaScript\",\n      \"has_issues\": true,\n      \"has_projects\": true,\n      \"has_downloads\": true,\n      \"has_wiki\": false,\n      \"has_pages\": false,\n      \"forks_count\": 26,\n      \"mirror_url\": null,\n      \"archived\": false,\n      \"disabled\": false,\n      \"open_issues_count\": 20,\n      \"license\": {\n        \"key\": \"mit\",\n        \"name\": \"MIT License\",\n        \"spdx_id\": \"MIT\",\n        \"url\": \"https://api.github.com/licenses/mit\",\n        \"node_id\": \"MDc6TGljZW5zZTEz\"\n      },\n      \"forks\": 26,\n      \"open_issues\": 20,\n      \"watchers\": 143,\n      \"default_branch\": \"master\",\n      \"score\": 1.0\n    },\n    {\n      \"id\": 47047829,\n      \"node_id\": \"MDEwOlJlcG9zaXRvcnk0NzA0NzgyOQ==\",\n      \"name\": \"preact-todomvc\",\n      \"full_name\": \"developit/preact-todomvc\",\n      \"private\": false,\n      \"owner\": {\n        \"login\": \"developit\",\n        \"id\": 105127,\n        \"node_id\": \"MDQ6VXNlcjEwNTEyNw==\",\n        \"avatar_url\": \"https://avatars2.githubusercontent.com/u/105127?v=4\",\n        \"gravatar_id\": \"\",\n        \"url\": \"https://api.github.com/users/developit\",\n        \"html_url\": \"https://github.com/developit\",\n        \"followers_url\": \"https://api.github.com/users/developit/followers\",\n        \"following_url\": \"https://api.github.com/users/developit/following{/other_user}\",\n        \"gists_url\": \"https://api.github.com/users/developit/gists{/gist_id}\",\n        \"starred_url\": \"https://api.github.com/users/developit/starred{/owner}{/repo}\",\n        \"subscriptions_url\": \"https://api.github.com/users/developit/subscriptions\",\n        \"organizations_url\": \"https://api.github.com/users/developit/orgs\",\n        \"repos_url\": \"https://api.github.com/users/developit/repos\",\n        \"events_url\": \"https://api.github.com/users/developit/events{/privacy}\",\n        \"received_events_url\": \"https://api.github.com/users/developit/received_events\",\n        \"type\": \"User\",\n        \"site_admin\": false\n      },\n      \"html_url\": \"https://github.com/developit/preact-todomvc\",\n      \"description\": \"💣 TodoMVC done in Preact. Under 6kb and fast.\",\n      \"fork\": false,\n      \"url\": \"https://api.github.com/repos/developit/preact-todomvc\",\n      \"forks_url\": \"https://api.github.com/repos/developit/preact-todomvc/forks\",\n      \"keys_url\": \"https://api.github.com/repos/developit/preact-todomvc/keys{/key_id}\",\n      \"collaborators_url\": \"https://api.github.com/repos/developit/preact-todomvc/collaborators{/collaborator}\",\n      \"teams_url\": \"https://api.github.com/repos/developit/preact-todomvc/teams\",\n      \"hooks_url\": \"https://api.github.com/repos/developit/preact-todomvc/hooks\",\n      \"issue_events_url\": \"https://api.github.com/repos/developit/preact-todomvc/issues/events{/number}\",\n      \"events_url\": \"https://api.github.com/repos/developit/preact-todomvc/events\",\n      \"assignees_url\": \"https://api.github.com/repos/developit/preact-todomvc/assignees{/user}\",\n      \"branches_url\": \"https://api.github.com/repos/developit/preact-todomvc/branches{/branch}\",\n      \"tags_url\": \"https://api.github.com/repos/developit/preact-todomvc/tags\",\n      \"blobs_url\": \"https://api.github.com/repos/developit/preact-todomvc/git/blobs{/sha}\",\n      \"git_tags_url\": \"https://api.github.com/repos/developit/preact-todomvc/git/tags{/sha}\",\n      \"git_refs_url\": \"https://api.github.com/repos/developit/preact-todomvc/git/refs{/sha}\",\n      \"trees_url\": \"https://api.github.com/repos/developit/preact-todomvc/git/trees{/sha}\",\n      \"statuses_url\": \"https://api.github.com/repos/developit/preact-todomvc/statuses/{sha}\",\n      \"languages_url\": \"https://api.github.com/repos/developit/preact-todomvc/languages\",\n      \"stargazers_url\": \"https://api.github.com/repos/developit/preact-todomvc/stargazers\",\n      \"contributors_url\": \"https://api.github.com/repos/developit/preact-todomvc/contributors\",\n      \"subscribers_url\": \"https://api.github.com/repos/developit/preact-todomvc/subscribers\",\n      \"subscription_url\": \"https://api.github.com/repos/developit/preact-todomvc/subscription\",\n      \"commits_url\": \"https://api.github.com/repos/developit/preact-todomvc/commits{/sha}\",\n      \"git_commits_url\": \"https://api.github.com/repos/developit/preact-todomvc/git/commits{/sha}\",\n      \"comments_url\": \"https://api.github.com/repos/developit/preact-todomvc/comments{/number}\",\n      \"issue_comment_url\": \"https://api.github.com/repos/developit/preact-todomvc/issues/comments{/number}\",\n      \"contents_url\": \"https://api.github.com/repos/developit/preact-todomvc/contents/{+path}\",\n      \"compare_url\": \"https://api.github.com/repos/developit/preact-todomvc/compare/{base}...{head}\",\n      \"merges_url\": \"https://api.github.com/repos/developit/preact-todomvc/merges\",\n      \"archive_url\": \"https://api.github.com/repos/developit/preact-todomvc/{archive_format}{/ref}\",\n      \"downloads_url\": \"https://api.github.com/repos/developit/preact-todomvc/downloads\",\n      \"issues_url\": \"https://api.github.com/repos/developit/preact-todomvc/issues{/number}\",\n      \"pulls_url\": \"https://api.github.com/repos/developit/preact-todomvc/pulls{/number}\",\n      \"milestones_url\": \"https://api.github.com/repos/developit/preact-todomvc/milestones{/number}\",\n      \"notifications_url\": \"https://api.github.com/repos/developit/preact-todomvc/notifications{?since,all,participating}\",\n      \"labels_url\": \"https://api.github.com/repos/developit/preact-todomvc/labels{/name}\",\n      \"releases_url\": \"https://api.github.com/repos/developit/preact-todomvc/releases{/id}\",\n      \"deployments_url\": \"https://api.github.com/repos/developit/preact-todomvc/deployments\",\n      \"created_at\": \"2015-11-29T03:03:19Z\",\n      \"updated_at\": \"2020-05-07T14:14:28Z\",\n      \"pushed_at\": \"2019-04-30T12:16:58Z\",\n      \"git_url\": \"git://github.com/developit/preact-todomvc.git\",\n      \"ssh_url\": \"git@github.com:developit/preact-todomvc.git\",\n      \"clone_url\": \"https://github.com/developit/preact-todomvc.git\",\n      \"svn_url\": \"https://github.com/developit/preact-todomvc\",\n      \"homepage\": \"https://preact-todomvc.surge.sh\",\n      \"size\": 163,\n      \"stargazers_count\": 79,\n      \"watchers_count\": 79,\n      \"language\": \"JavaScript\",\n      \"has_issues\": true,\n      \"has_projects\": true,\n      \"has_downloads\": true,\n      \"has_wiki\": false,\n      \"has_pages\": true,\n      \"forks_count\": 29,\n      \"mirror_url\": null,\n      \"archived\": false,\n      \"disabled\": false,\n      \"open_issues_count\": 4,\n      \"license\": null,\n      \"forks\": 29,\n      \"open_issues\": 4,\n      \"watchers\": 79,\n      \"default_branch\": \"master\",\n      \"score\": 1.0\n    },\n    {\n      \"id\": 68534861,\n      \"node_id\": \"MDEwOlJlcG9zaXRvcnk2ODUzNDg2MQ==\",\n      \"name\": \"react-hint\",\n      \"full_name\": \"slmgc/react-hint\",\n      \"private\": false,\n      \"owner\": {\n        \"login\": \"slmgc\",\n        \"id\": 5236786,\n        \"node_id\": \"MDQ6VXNlcjUyMzY3ODY=\",\n        \"avatar_url\": \"https://avatars1.githubusercontent.com/u/5236786?v=4\",\n        \"gravatar_id\": \"\",\n        \"url\": \"https://api.github.com/users/slmgc\",\n        \"html_url\": \"https://github.com/slmgc\",\n        \"followers_url\": \"https://api.github.com/users/slmgc/followers\",\n        \"following_url\": \"https://api.github.com/users/slmgc/following{/other_user}\",\n        \"gists_url\": \"https://api.github.com/users/slmgc/gists{/gist_id}\",\n        \"starred_url\": \"https://api.github.com/users/slmgc/starred{/owner}{/repo}\",\n        \"subscriptions_url\": \"https://api.github.com/users/slmgc/subscriptions\",\n        \"organizations_url\": \"https://api.github.com/users/slmgc/orgs\",\n        \"repos_url\": \"https://api.github.com/users/slmgc/repos\",\n        \"events_url\": \"https://api.github.com/users/slmgc/events{/privacy}\",\n        \"received_events_url\": \"https://api.github.com/users/slmgc/received_events\",\n        \"type\": \"User\",\n        \"site_admin\": false\n      },\n      \"html_url\": \"https://github.com/slmgc/react-hint\",\n      \"description\": \"Tooltip component for React, Preact, Inferno\",\n      \"fork\": false,\n      \"url\": \"https://api.github.com/repos/slmgc/react-hint\",\n      \"forks_url\": \"https://api.github.com/repos/slmgc/react-hint/forks\",\n      \"keys_url\": \"https://api.github.com/repos/slmgc/react-hint/keys{/key_id}\",\n      \"collaborators_url\": \"https://api.github.com/repos/slmgc/react-hint/collaborators{/collaborator}\",\n      \"teams_url\": \"https://api.github.com/repos/slmgc/react-hint/teams\",\n      \"hooks_url\": \"https://api.github.com/repos/slmgc/react-hint/hooks\",\n      \"issue_events_url\": \"https://api.github.com/repos/slmgc/react-hint/issues/events{/number}\",\n      \"events_url\": \"https://api.github.com/repos/slmgc/react-hint/events\",\n      \"assignees_url\": \"https://api.github.com/repos/slmgc/react-hint/assignees{/user}\",\n      \"branches_url\": \"https://api.github.com/repos/slmgc/react-hint/branches{/branch}\",\n      \"tags_url\": \"https://api.github.com/repos/slmgc/react-hint/tags\",\n      \"blobs_url\": \"https://api.github.com/repos/slmgc/react-hint/git/blobs{/sha}\",\n      \"git_tags_url\": \"https://api.github.com/repos/slmgc/react-hint/git/tags{/sha}\",\n      \"git_refs_url\": \"https://api.github.com/repos/slmgc/react-hint/git/refs{/sha}\",\n      \"trees_url\": \"https://api.github.com/repos/slmgc/react-hint/git/trees{/sha}\",\n      \"statuses_url\": \"https://api.github.com/repos/slmgc/react-hint/statuses/{sha}\",\n      \"languages_url\": \"https://api.github.com/repos/slmgc/react-hint/languages\",\n      \"stargazers_url\": \"https://api.github.com/repos/slmgc/react-hint/stargazers\",\n      \"contributors_url\": \"https://api.github.com/repos/slmgc/react-hint/contributors\",\n      \"subscribers_url\": \"https://api.github.com/repos/slmgc/react-hint/subscribers\",\n      \"subscription_url\": \"https://api.github.com/repos/slmgc/react-hint/subscription\",\n      \"commits_url\": \"https://api.github.com/repos/slmgc/react-hint/commits{/sha}\",\n      \"git_commits_url\": \"https://api.github.com/repos/slmgc/react-hint/git/commits{/sha}\",\n      \"comments_url\": \"https://api.github.com/repos/slmgc/react-hint/comments{/number}\",\n      \"issue_comment_url\": \"https://api.github.com/repos/slmgc/react-hint/issues/comments{/number}\",\n      \"contents_url\": \"https://api.github.com/repos/slmgc/react-hint/contents/{+path}\",\n      \"compare_url\": \"https://api.github.com/repos/slmgc/react-hint/compare/{base}...{head}\",\n      \"merges_url\": \"https://api.github.com/repos/slmgc/react-hint/merges\",\n      \"archive_url\": \"https://api.github.com/repos/slmgc/react-hint/{archive_format}{/ref}\",\n      \"downloads_url\": \"https://api.github.com/repos/slmgc/react-hint/downloads\",\n      \"issues_url\": \"https://api.github.com/repos/slmgc/react-hint/issues{/number}\",\n      \"pulls_url\": \"https://api.github.com/repos/slmgc/react-hint/pulls{/number}\",\n      \"milestones_url\": \"https://api.github.com/repos/slmgc/react-hint/milestones{/number}\",\n      \"notifications_url\": \"https://api.github.com/repos/slmgc/react-hint/notifications{?since,all,participating}\",\n      \"labels_url\": \"https://api.github.com/repos/slmgc/react-hint/labels{/name}\",\n      \"releases_url\": \"https://api.github.com/repos/slmgc/react-hint/releases{/id}\",\n      \"deployments_url\": \"https://api.github.com/repos/slmgc/react-hint/deployments\",\n      \"created_at\": \"2016-09-18T16:57:59Z\",\n      \"updated_at\": \"2020-05-13T21:14:30Z\",\n      \"pushed_at\": \"2020-04-14T02:55:58Z\",\n      \"git_url\": \"git://github.com/slmgc/react-hint.git\",\n      \"ssh_url\": \"git@github.com:slmgc/react-hint.git\",\n      \"clone_url\": \"https://github.com/slmgc/react-hint.git\",\n      \"svn_url\": \"https://github.com/slmgc/react-hint\",\n      \"homepage\": \"https://react-hint.js.org/\",\n      \"size\": 215,\n      \"stargazers_count\": 333,\n      \"watchers_count\": 333,\n      \"language\": \"JavaScript\",\n      \"has_issues\": true,\n      \"has_projects\": true,\n      \"has_downloads\": true,\n      \"has_wiki\": false,\n      \"has_pages\": true,\n      \"forks_count\": 27,\n      \"mirror_url\": null,\n      \"archived\": false,\n      \"disabled\": false,\n      \"open_issues_count\": 10,\n      \"license\": {\n        \"key\": \"mit\",\n        \"name\": \"MIT License\",\n        \"spdx_id\": \"MIT\",\n        \"url\": \"https://api.github.com/licenses/mit\",\n        \"node_id\": \"MDc6TGljZW5zZTEz\"\n      },\n      \"forks\": 27,\n      \"open_issues\": 10,\n      \"watchers\": 333,\n      \"default_branch\": \"master\",\n      \"score\": 1.0\n    },\n    {\n      \"id\": 110067296,\n      \"node_id\": \"MDEwOlJlcG9zaXRvcnkxMTAwNjcyOTY=\",\n      \"name\": \"preact-fluid\",\n      \"full_name\": \"ajainvivek/preact-fluid\",\n      \"private\": false,\n      \"owner\": {\n        \"login\": \"ajainvivek\",\n        \"id\": 1182600,\n        \"node_id\": \"MDQ6VXNlcjExODI2MDA=\",\n        \"avatar_url\": \"https://avatars2.githubusercontent.com/u/1182600?v=4\",\n        \"gravatar_id\": \"\",\n        \"url\": \"https://api.github.com/users/ajainvivek\",\n        \"html_url\": \"https://github.com/ajainvivek\",\n        \"followers_url\": \"https://api.github.com/users/ajainvivek/followers\",\n        \"following_url\": \"https://api.github.com/users/ajainvivek/following{/other_user}\",\n        \"gists_url\": \"https://api.github.com/users/ajainvivek/gists{/gist_id}\",\n        \"starred_url\": \"https://api.github.com/users/ajainvivek/starred{/owner}{/repo}\",\n        \"subscriptions_url\": \"https://api.github.com/users/ajainvivek/subscriptions\",\n        \"organizations_url\": \"https://api.github.com/users/ajainvivek/orgs\",\n        \"repos_url\": \"https://api.github.com/users/ajainvivek/repos\",\n        \"events_url\": \"https://api.github.com/users/ajainvivek/events{/privacy}\",\n        \"received_events_url\": \"https://api.github.com/users/ajainvivek/received_events\",\n        \"type\": \"User\",\n        \"site_admin\": false\n      },\n      \"html_url\": \"https://github.com/ajainvivek/preact-fluid\",\n      \"description\": \"✅ A minimal UI kit for Preact\",\n      \"fork\": false,\n      \"url\": \"https://api.github.com/repos/ajainvivek/preact-fluid\",\n      \"forks_url\": \"https://api.github.com/repos/ajainvivek/preact-fluid/forks\",\n      \"keys_url\": \"https://api.github.com/repos/ajainvivek/preact-fluid/keys{/key_id}\",\n      \"collaborators_url\": \"https://api.github.com/repos/ajainvivek/preact-fluid/collaborators{/collaborator}\",\n      \"teams_url\": \"https://api.github.com/repos/ajainvivek/preact-fluid/teams\",\n      \"hooks_url\": \"https://api.github.com/repos/ajainvivek/preact-fluid/hooks\",\n      \"issue_events_url\": \"https://api.github.com/repos/ajainvivek/preact-fluid/issues/events{/number}\",\n      \"events_url\": \"https://api.github.com/repos/ajainvivek/preact-fluid/events\",\n      \"assignees_url\": \"https://api.github.com/repos/ajainvivek/preact-fluid/assignees{/user}\",\n      \"branches_url\": \"https://api.github.com/repos/ajainvivek/preact-fluid/branches{/branch}\",\n      \"tags_url\": \"https://api.github.com/repos/ajainvivek/preact-fluid/tags\",\n      \"blobs_url\": \"https://api.github.com/repos/ajainvivek/preact-fluid/git/blobs{/sha}\",\n      \"git_tags_url\": \"https://api.github.com/repos/ajainvivek/preact-fluid/git/tags{/sha}\",\n      \"git_refs_url\": \"https://api.github.com/repos/ajainvivek/preact-fluid/git/refs{/sha}\",\n      \"trees_url\": \"https://api.github.com/repos/ajainvivek/preact-fluid/git/trees{/sha}\",\n      \"statuses_url\": \"https://api.github.com/repos/ajainvivek/preact-fluid/statuses/{sha}\",\n      \"languages_url\": \"https://api.github.com/repos/ajainvivek/preact-fluid/languages\",\n      \"stargazers_url\": \"https://api.github.com/repos/ajainvivek/preact-fluid/stargazers\",\n      \"contributors_url\": \"https://api.github.com/repos/ajainvivek/preact-fluid/contributors\",\n      \"subscribers_url\": \"https://api.github.com/repos/ajainvivek/preact-fluid/subscribers\",\n      \"subscription_url\": \"https://api.github.com/repos/ajainvivek/preact-fluid/subscription\",\n      \"commits_url\": \"https://api.github.com/repos/ajainvivek/preact-fluid/commits{/sha}\",\n      \"git_commits_url\": \"https://api.github.com/repos/ajainvivek/preact-fluid/git/commits{/sha}\",\n      \"comments_url\": \"https://api.github.com/repos/ajainvivek/preact-fluid/comments{/number}\",\n      \"issue_comment_url\": \"https://api.github.com/repos/ajainvivek/preact-fluid/issues/comments{/number}\",\n      \"contents_url\": \"https://api.github.com/repos/ajainvivek/preact-fluid/contents/{+path}\",\n      \"compare_url\": \"https://api.github.com/repos/ajainvivek/preact-fluid/compare/{base}...{head}\",\n      \"merges_url\": \"https://api.github.com/repos/ajainvivek/preact-fluid/merges\",\n      \"archive_url\": \"https://api.github.com/repos/ajainvivek/preact-fluid/{archive_format}{/ref}\",\n      \"downloads_url\": \"https://api.github.com/repos/ajainvivek/preact-fluid/downloads\",\n      \"issues_url\": \"https://api.github.com/repos/ajainvivek/preact-fluid/issues{/number}\",\n      \"pulls_url\": \"https://api.github.com/repos/ajainvivek/preact-fluid/pulls{/number}\",\n      \"milestones_url\": \"https://api.github.com/repos/ajainvivek/preact-fluid/milestones{/number}\",\n      \"notifications_url\": \"https://api.github.com/repos/ajainvivek/preact-fluid/notifications{?since,all,participating}\",\n      \"labels_url\": \"https://api.github.com/repos/ajainvivek/preact-fluid/labels{/name}\",\n      \"releases_url\": \"https://api.github.com/repos/ajainvivek/preact-fluid/releases{/id}\",\n      \"deployments_url\": \"https://api.github.com/repos/ajainvivek/preact-fluid/deployments\",\n      \"created_at\": \"2017-11-09T04:29:37Z\",\n      \"updated_at\": \"2020-05-14T17:36:11Z\",\n      \"pushed_at\": \"2019-02-20T07:46:32Z\",\n      \"git_url\": \"git://github.com/ajainvivek/preact-fluid.git\",\n      \"ssh_url\": \"git@github.com:ajainvivek/preact-fluid.git\",\n      \"clone_url\": \"https://github.com/ajainvivek/preact-fluid.git\",\n      \"svn_url\": \"https://github.com/ajainvivek/preact-fluid\",\n      \"homepage\": \"https://ajainvivek.github.io/preact-fluid/\",\n      \"size\": 921,\n      \"stargazers_count\": 148,\n      \"watchers_count\": 148,\n      \"language\": \"JavaScript\",\n      \"has_issues\": true,\n      \"has_projects\": true,\n      \"has_downloads\": true,\n      \"has_wiki\": true,\n      \"has_pages\": true,\n      \"forks_count\": 23,\n      \"mirror_url\": null,\n      \"archived\": false,\n      \"disabled\": false,\n      \"open_issues_count\": 5,\n      \"license\": {\n        \"key\": \"mit\",\n        \"name\": \"MIT License\",\n        \"spdx_id\": \"MIT\",\n        \"url\": \"https://api.github.com/licenses/mit\",\n        \"node_id\": \"MDc6TGljZW5zZTEz\"\n      },\n      \"forks\": 23,\n      \"open_issues\": 5,\n      \"watchers\": 148,\n      \"default_branch\": \"master\",\n      \"score\": 1.0\n    },\n    {\n      \"id\": 53229795,\n      \"node_id\": \"MDEwOlJlcG9zaXRvcnk1MzIyOTc5NQ==\",\n      \"name\": \"preact-portal\",\n      \"full_name\": \"developit/preact-portal\",\n      \"private\": false,\n      \"owner\": {\n        \"login\": \"developit\",\n        \"id\": 105127,\n        \"node_id\": \"MDQ6VXNlcjEwNTEyNw==\",\n        \"avatar_url\": \"https://avatars2.githubusercontent.com/u/105127?v=4\",\n        \"gravatar_id\": \"\",\n        \"url\": \"https://api.github.com/users/developit\",\n        \"html_url\": \"https://github.com/developit\",\n        \"followers_url\": \"https://api.github.com/users/developit/followers\",\n        \"following_url\": \"https://api.github.com/users/developit/following{/other_user}\",\n        \"gists_url\": \"https://api.github.com/users/developit/gists{/gist_id}\",\n        \"starred_url\": \"https://api.github.com/users/developit/starred{/owner}{/repo}\",\n        \"subscriptions_url\": \"https://api.github.com/users/developit/subscriptions\",\n        \"organizations_url\": \"https://api.github.com/users/developit/orgs\",\n        \"repos_url\": \"https://api.github.com/users/developit/repos\",\n        \"events_url\": \"https://api.github.com/users/developit/events{/privacy}\",\n        \"received_events_url\": \"https://api.github.com/users/developit/received_events\",\n        \"type\": \"User\",\n        \"site_admin\": false\n      },\n      \"html_url\": \"https://github.com/developit/preact-portal\",\n      \"description\": \":satellite: Render Preact components in (a) SPACE :milky_way: :stars:\",\n      \"fork\": false,\n      \"url\": \"https://api.github.com/repos/developit/preact-portal\",\n      \"forks_url\": \"https://api.github.com/repos/developit/preact-portal/forks\",\n      \"keys_url\": \"https://api.github.com/repos/developit/preact-portal/keys{/key_id}\",\n      \"collaborators_url\": \"https://api.github.com/repos/developit/preact-portal/collaborators{/collaborator}\",\n      \"teams_url\": \"https://api.github.com/repos/developit/preact-portal/teams\",\n      \"hooks_url\": \"https://api.github.com/repos/developit/preact-portal/hooks\",\n      \"issue_events_url\": \"https://api.github.com/repos/developit/preact-portal/issues/events{/number}\",\n      \"events_url\": \"https://api.github.com/repos/developit/preact-portal/events\",\n      \"assignees_url\": \"https://api.github.com/repos/developit/preact-portal/assignees{/user}\",\n      \"branches_url\": \"https://api.github.com/repos/developit/preact-portal/branches{/branch}\",\n      \"tags_url\": \"https://api.github.com/repos/developit/preact-portal/tags\",\n      \"blobs_url\": \"https://api.github.com/repos/developit/preact-portal/git/blobs{/sha}\",\n      \"git_tags_url\": \"https://api.github.com/repos/developit/preact-portal/git/tags{/sha}\",\n      \"git_refs_url\": \"https://api.github.com/repos/developit/preact-portal/git/refs{/sha}\",\n      \"trees_url\": \"https://api.github.com/repos/developit/preact-portal/git/trees{/sha}\",\n      \"statuses_url\": \"https://api.github.com/repos/developit/preact-portal/statuses/{sha}\",\n      \"languages_url\": \"https://api.github.com/repos/developit/preact-portal/languages\",\n      \"stargazers_url\": \"https://api.github.com/repos/developit/preact-portal/stargazers\",\n      \"contributors_url\": \"https://api.github.com/repos/developit/preact-portal/contributors\",\n      \"subscribers_url\": \"https://api.github.com/repos/developit/preact-portal/subscribers\",\n      \"subscription_url\": \"https://api.github.com/repos/developit/preact-portal/subscription\",\n      \"commits_url\": \"https://api.github.com/repos/developit/preact-portal/commits{/sha}\",\n      \"git_commits_url\": \"https://api.github.com/repos/developit/preact-portal/git/commits{/sha}\",\n      \"comments_url\": \"https://api.github.com/repos/developit/preact-portal/comments{/number}\",\n      \"issue_comment_url\": \"https://api.github.com/repos/developit/preact-portal/issues/comments{/number}\",\n      \"contents_url\": \"https://api.github.com/repos/developit/preact-portal/contents/{+path}\",\n      \"compare_url\": \"https://api.github.com/repos/developit/preact-portal/compare/{base}...{head}\",\n      \"merges_url\": \"https://api.github.com/repos/developit/preact-portal/merges\",\n      \"archive_url\": \"https://api.github.com/repos/developit/preact-portal/{archive_format}{/ref}\",\n      \"downloads_url\": \"https://api.github.com/repos/developit/preact-portal/downloads\",\n      \"issues_url\": \"https://api.github.com/repos/developit/preact-portal/issues{/number}\",\n      \"pulls_url\": \"https://api.github.com/repos/developit/preact-portal/pulls{/number}\",\n      \"milestones_url\": \"https://api.github.com/repos/developit/preact-portal/milestones{/number}\",\n      \"notifications_url\": \"https://api.github.com/repos/developit/preact-portal/notifications{?since,all,participating}\",\n      \"labels_url\": \"https://api.github.com/repos/developit/preact-portal/labels{/name}\",\n      \"releases_url\": \"https://api.github.com/repos/developit/preact-portal/releases{/id}\",\n      \"deployments_url\": \"https://api.github.com/repos/developit/preact-portal/deployments\",\n      \"created_at\": \"2016-03-06T00:18:05Z\",\n      \"updated_at\": \"2020-05-11T06:26:23Z\",\n      \"pushed_at\": \"2019-09-15T00:27:49Z\",\n      \"git_url\": \"git://github.com/developit/preact-portal.git\",\n      \"ssh_url\": \"git@github.com:developit/preact-portal.git\",\n      \"clone_url\": \"https://github.com/developit/preact-portal.git\",\n      \"svn_url\": \"https://github.com/developit/preact-portal\",\n      \"homepage\": \"http://npm.im/preact-portal\",\n      \"size\": 16,\n      \"stargazers_count\": 152,\n      \"watchers_count\": 152,\n      \"language\": \"JavaScript\",\n      \"has_issues\": true,\n      \"has_projects\": true,\n      \"has_downloads\": true,\n      \"has_wiki\": true,\n      \"has_pages\": false,\n      \"forks_count\": 20,\n      \"mirror_url\": null,\n      \"archived\": false,\n      \"disabled\": false,\n      \"open_issues_count\": 11,\n      \"license\": {\n        \"key\": \"mit\",\n        \"name\": \"MIT License\",\n        \"spdx_id\": \"MIT\",\n        \"url\": \"https://api.github.com/licenses/mit\",\n        \"node_id\": \"MDc6TGljZW5zZTEz\"\n      },\n      \"forks\": 20,\n      \"open_issues\": 11,\n      \"watchers\": 152,\n      \"default_branch\": \"master\",\n      \"score\": 1.0\n    },\n    {\n      \"id\": 56397188,\n      \"node_id\": \"MDEwOlJlcG9zaXRvcnk1NjM5NzE4OA==\",\n      \"name\": \"preact-virtual-list\",\n      \"full_name\": \"developit/preact-virtual-list\",\n      \"private\": false,\n      \"owner\": {\n        \"login\": \"developit\",\n        \"id\": 105127,\n        \"node_id\": \"MDQ6VXNlcjEwNTEyNw==\",\n        \"avatar_url\": \"https://avatars2.githubusercontent.com/u/105127?v=4\",\n        \"gravatar_id\": \"\",\n        \"url\": \"https://api.github.com/users/developit\",\n        \"html_url\": \"https://github.com/developit\",\n        \"followers_url\": \"https://api.github.com/users/developit/followers\",\n        \"following_url\": \"https://api.github.com/users/developit/following{/other_user}\",\n        \"gists_url\": \"https://api.github.com/users/developit/gists{/gist_id}\",\n        \"starred_url\": \"https://api.github.com/users/developit/starred{/owner}{/repo}\",\n        \"subscriptions_url\": \"https://api.github.com/users/developit/subscriptions\",\n        \"organizations_url\": \"https://api.github.com/users/developit/orgs\",\n        \"repos_url\": \"https://api.github.com/users/developit/repos\",\n        \"events_url\": \"https://api.github.com/users/developit/events{/privacy}\",\n        \"received_events_url\": \"https://api.github.com/users/developit/received_events\",\n        \"type\": \"User\",\n        \"site_admin\": false\n      },\n      \"html_url\": \"https://github.com/developit/preact-virtual-list\",\n      \"description\": \":card_index: Virtual List that only renders visible items. Supports millions of rows.\",\n      \"fork\": false,\n      \"url\": \"https://api.github.com/repos/developit/preact-virtual-list\",\n      \"forks_url\": \"https://api.github.com/repos/developit/preact-virtual-list/forks\",\n      \"keys_url\": \"https://api.github.com/repos/developit/preact-virtual-list/keys{/key_id}\",\n      \"collaborators_url\": \"https://api.github.com/repos/developit/preact-virtual-list/collaborators{/collaborator}\",\n      \"teams_url\": \"https://api.github.com/repos/developit/preact-virtual-list/teams\",\n      \"hooks_url\": \"https://api.github.com/repos/developit/preact-virtual-list/hooks\",\n      \"issue_events_url\": \"https://api.github.com/repos/developit/preact-virtual-list/issues/events{/number}\",\n      \"events_url\": \"https://api.github.com/repos/developit/preact-virtual-list/events\",\n      \"assignees_url\": \"https://api.github.com/repos/developit/preact-virtual-list/assignees{/user}\",\n      \"branches_url\": \"https://api.github.com/repos/developit/preact-virtual-list/branches{/branch}\",\n      \"tags_url\": \"https://api.github.com/repos/developit/preact-virtual-list/tags\",\n      \"blobs_url\": \"https://api.github.com/repos/developit/preact-virtual-list/git/blobs{/sha}\",\n      \"git_tags_url\": \"https://api.github.com/repos/developit/preact-virtual-list/git/tags{/sha}\",\n      \"git_refs_url\": \"https://api.github.com/repos/developit/preact-virtual-list/git/refs{/sha}\",\n      \"trees_url\": \"https://api.github.com/repos/developit/preact-virtual-list/git/trees{/sha}\",\n      \"statuses_url\": \"https://api.github.com/repos/developit/preact-virtual-list/statuses/{sha}\",\n      \"languages_url\": \"https://api.github.com/repos/developit/preact-virtual-list/languages\",\n      \"stargazers_url\": \"https://api.github.com/repos/developit/preact-virtual-list/stargazers\",\n      \"contributors_url\": \"https://api.github.com/repos/developit/preact-virtual-list/contributors\",\n      \"subscribers_url\": \"https://api.github.com/repos/developit/preact-virtual-list/subscribers\",\n      \"subscription_url\": \"https://api.github.com/repos/developit/preact-virtual-list/subscription\",\n      \"commits_url\": \"https://api.github.com/repos/developit/preact-virtual-list/commits{/sha}\",\n      \"git_commits_url\": \"https://api.github.com/repos/developit/preact-virtual-list/git/commits{/sha}\",\n      \"comments_url\": \"https://api.github.com/repos/developit/preact-virtual-list/comments{/number}\",\n      \"issue_comment_url\": \"https://api.github.com/repos/developit/preact-virtual-list/issues/comments{/number}\",\n      \"contents_url\": \"https://api.github.com/repos/developit/preact-virtual-list/contents/{+path}\",\n      \"compare_url\": \"https://api.github.com/repos/developit/preact-virtual-list/compare/{base}...{head}\",\n      \"merges_url\": \"https://api.github.com/repos/developit/preact-virtual-list/merges\",\n      \"archive_url\": \"https://api.github.com/repos/developit/preact-virtual-list/{archive_format}{/ref}\",\n      \"downloads_url\": \"https://api.github.com/repos/developit/preact-virtual-list/downloads\",\n      \"issues_url\": \"https://api.github.com/repos/developit/preact-virtual-list/issues{/number}\",\n      \"pulls_url\": \"https://api.github.com/repos/developit/preact-virtual-list/pulls{/number}\",\n      \"milestones_url\": \"https://api.github.com/repos/developit/preact-virtual-list/milestones{/number}\",\n      \"notifications_url\": \"https://api.github.com/repos/developit/preact-virtual-list/notifications{?since,all,participating}\",\n      \"labels_url\": \"https://api.github.com/repos/developit/preact-virtual-list/labels{/name}\",\n      \"releases_url\": \"https://api.github.com/repos/developit/preact-virtual-list/releases{/id}\",\n      \"deployments_url\": \"https://api.github.com/repos/developit/preact-virtual-list/deployments\",\n      \"created_at\": \"2016-04-16T17:40:06Z\",\n      \"updated_at\": \"2020-04-28T00:37:36Z\",\n      \"pushed_at\": \"2019-07-22T23:14:11Z\",\n      \"git_url\": \"git://github.com/developit/preact-virtual-list.git\",\n      \"ssh_url\": \"git@github.com:developit/preact-virtual-list.git\",\n      \"clone_url\": \"https://github.com/developit/preact-virtual-list.git\",\n      \"svn_url\": \"https://github.com/developit/preact-virtual-list\",\n      \"homepage\": \"https://jsfiddle.net/developit/qqan9pdo/\",\n      \"size\": 12,\n      \"stargazers_count\": 184,\n      \"watchers_count\": 184,\n      \"language\": \"JavaScript\",\n      \"has_issues\": true,\n      \"has_projects\": true,\n      \"has_downloads\": true,\n      \"has_wiki\": true,\n      \"has_pages\": false,\n      \"forks_count\": 25,\n      \"mirror_url\": null,\n      \"archived\": false,\n      \"disabled\": false,\n      \"open_issues_count\": 7,\n      \"license\": {\n        \"key\": \"mit\",\n        \"name\": \"MIT License\",\n        \"spdx_id\": \"MIT\",\n        \"url\": \"https://api.github.com/licenses/mit\",\n        \"node_id\": \"MDc6TGljZW5zZTEz\"\n      },\n      \"forks\": 25,\n      \"open_issues\": 7,\n      \"watchers\": 184,\n      \"default_branch\": \"master\",\n      \"score\": 1.0\n    }\n  ]\n}\n"
  },
  {
    "path": "example_old/fakeApi.js",
    "content": "export function fetchProfileData() {\n  const userPromise = fetchUser();\n  const postsPromise = fetchPosts();\n  const triviaPromise = fetchTrivia();\n  return {\n    user: wrapPromise(userPromise),\n    posts: wrapPromise(postsPromise),\n    trivia: wrapPromise(triviaPromise),\n  };\n}\n\n// Suspense integrations like Relay implement\n// a contract like this to integrate with React.\n// Real implementations can be significantly more complex.\n// Don't copy-paste this into your project!\nfunction wrapPromise(promise) {\n  const promiseId = performance.now();\n  let status = 'pending';\n  let result;\n  const suspender = promise.then(\n    (r) => {\n      // console.log('promiseId on success ---', promiseId, r);\n      status = 'success';\n      result = r;\n      return result;\n    },\n    (e) => {\n      status = 'error';\n      result = e;\n    },\n  );\n  return {\n    read() {\n      if (status === 'pending') {\n        // console.log('promiseId on suspend ---', promiseId);\n        throw suspender;\n      } else if (status === 'error') {\n        throw result;\n      } else if (status === 'success') {\n        return result;\n      }\n    },\n  };\n}\n\nfunction fetchUser() {\n  // console.log('fetch user...');\n  return new Promise((resolve) => {\n    setTimeout(() => {\n      console.log('fetched user');\n      resolve({\n        name: 'Ringo Starr',\n      });\n    }, 1000);\n  });\n}\n\nconst ringoPosts = [\n  {\n    id: 0,\n    text: 'I get by with a little help from my friends',\n  },\n  {\n    id: 1,\n    text: \"I'd like to be under the sea in an octupus's garden\",\n  },\n  {\n    id: 2,\n    text: 'You got that sand all over your feet',\n  },\n];\n\nfunction fetchPosts() {\n  const ringoPostsAtTheTime = ringoPosts;\n  // console.log('fetch posts...');\n  return new Promise((resolve) => {\n    setTimeout(() => {\n      console.log('fetched posts');\n      resolve(ringoPostsAtTheTime);\n    }, 2000);\n  });\n}\n\nfunction fetchTrivia() {\n  return new Promise((resolve) => {\n    setTimeout(() => {\n      console.log('fetched trivia');\n\n      resolve([\n        {\n          id: 1,\n          text: 'The nickname \"Ringo\" came from his habit of wearing numerous rings.',\n        },\n        {\n          id: 2,\n          text: 'Plays the drums left-handed with a right-handed drum set.',\n        },\n        {\n          id: 3,\n          text: 'Nominated for one Daytime Emmy Award, but did not win',\n        },\n        {\n          id: 4,\n          text: 'Nominated for one Daytime Emmy Award, and did win this time',\n        },\n      ]);\n    }, 3000);\n  });\n}\n"
  },
  {
    "path": "example_old/fakeApiSuspenseList.js",
    "content": "export function fetchProfileData() {\n  const userPromise = fetchUser();\n  const postsPromise = fetchPosts();\n  const triviaPromise = fetchTrivia();\n  return {\n    user: wrapPromise(userPromise),\n    posts: wrapPromise(postsPromise),\n    trivia: wrapPromise(triviaPromise),\n  };\n}\n\n// Suspense integrations like Relay implement\n// a contract like this to integrate with React.\n// Real implementations can be significantly more complex.\n// Don't copy-paste this into your project!\nfunction wrapPromise(promise) {\n  let status = 'pending';\n  let result;\n  const suspender = promise.then(\n    (r) => {\n      status = 'success';\n      result = r;\n    },\n    (e) => {\n      status = 'error';\n      result = e;\n    },\n  );\n  return {\n    read() {\n      if (status === 'pending') {\n        throw suspender;\n      } else if (status === 'error') {\n        throw result;\n      } else if (status === 'success') {\n        return result;\n      }\n    },\n  };\n}\n\nfunction fetchUser() {\n  console.log('fetch user...');\n  return new Promise((resolve) => {\n    setTimeout(() => {\n      console.log('fetched user');\n      resolve({\n        name: 'Ringo Starr',\n      });\n    }, 500);\n  });\n}\n\nconst ringoPosts = [\n  {\n    id: 0,\n    text: 'I get by with a little help from my friends',\n  },\n  {\n    id: 1,\n    text: \"I'd like to be under the sea in an octupus's garden\",\n  },\n  {\n    id: 2,\n    text: 'You got that sand all over your feet',\n  },\n];\n\nfunction fetchPosts() {\n  const ringoPostsAtTheTime = ringoPosts;\n  console.log('fetch posts...');\n  return new Promise((resolve) => {\n    setTimeout(() => {\n      console.log('fetched posts');\n      resolve(ringoPostsAtTheTime);\n    }, 3000);\n  });\n}\n\nfunction fetchTrivia() {\n  return new Promise((resolve) => {\n    setTimeout(() => {\n      console.log('fetched trivia');\n\n      resolve([\n        {\n          id: 1,\n          text: 'The nickname \"Ringo\" came from his habit of wearing numerous rings.',\n        },\n        {\n          id: 2,\n          text: 'Plays the drums left-handed with a right-handed drum set.',\n        },\n        {\n          id: 3,\n          text: 'Nominated for one Daytime Emmy Award, but did not win',\n        },\n      ]);\n    }, 4000);\n  });\n}\n"
  },
  {
    "path": "example_old/friends.json",
    "content": "[\n  {\n    \"_id\": \"5d029d30bc3e8f972d3aa50f\",\n    \"name\": \"Roberta Wall\"\n  },\n  {\n    \"_id\": \"5d029d3022013fcdad4791d7\",\n    \"name\": \"Ayala Bowers\"\n  },\n  {\n    \"_id\": \"5d029d30c27654147e7b103c\",\n    \"name\": \"Frances Deleon\"\n  },\n  {\n    \"_id\": \"5d029d30a0087a9cb5c0f72e\",\n    \"name\": \"Nell Summers\"\n  },\n  {\n    \"_id\": \"5d029d3046f20fff8ad9c81e\",\n    \"name\": \"Glenda Garza\"\n  },\n  {\n    \"_id\": \"5d029d304cba24d1a145fc8c\",\n    \"name\": \"Jimenez Mcgowan\"\n  },\n  {\n    \"_id\": \"5d029d30e2d4ac6ce472b5e8\",\n    \"name\": \"Jessica Langley\"\n  },\n  {\n    \"_id\": \"5d029d306ad4ded1c5c951b7\",\n    \"name\": \"Perez Mcknight\"\n  },\n  {\n    \"_id\": \"5d029d3017df1f3ed37e5f3a\",\n    \"name\": \"Jeanne Moss\"\n  },\n  {\n    \"_id\": \"5d029d30b1b76e96f5969739\",\n    \"name\": \"Carla Boyer\"\n  },\n  {\n    \"_id\": \"5d029d3044d6388bb864446c\",\n    \"name\": \"Wendy Nash\"\n  }\n]"
  },
  {
    "path": "example_old/index.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>Brahmos Demo</title>\n    <meta charset=\"UTF-8\" />\n    <style>\n      html,\n      body {\n        font: 14px/1.21 'Helvetica Neue', arial, sans-serif;\n        font-weight: 400;\n        color: #444;\n        -webkit-font-smoothing: antialiased;\n        -moz-osx-font-smoothing: grayscale;\n      }\n    </style>\n  </head>\n\n  <body>\n    <h1>App</h1>\n    <div id=\"app\"></div>\n    <div id=\"another-root\"></div>\n    <div id=\"unmount-node\"></div>\n  </body>\n</html>\n"
  },
  {
    "path": "example_old/index.js",
    "content": "import App from './App.js';\nimport UnMountAtNode from './UnMountAtNode';\nimport Brahmos, { render } from '../src';\nimport ConcurrentApp from './concurrentApp';\nimport SuspenseApp from './suspenseExamples';\nimport SuspenseListApp from './suspenseListExample';\n\nrender(<App />, document.getElementById('app'));\n\nrender(<UnMountAtNode />, document.getElementById('unmount-node'));\n"
  },
  {
    "path": "example_old/lazySuspenseExample.js",
    "content": "import Brahmos, { Suspense, lazy } from '../src';\nimport TodoList from './TodoList';\n\nconst LazyToDo = lazy(() => {\n  return new Promise((resolve) => {\n    setTimeout(() => {\n      resolve(import('./TodoList'));\n    }, 1000);\n  });\n});\n\nconst LazyUseStateExample = lazy(() => import('./UseStateExample'));\n\nexport default function LazySuspenseExample() {\n  const message = 'Hello world';\n\n  return (\n    <Suspense fallback={<h2>LOADING !!!</h2>}>\n      <section className=\"\">\n        <h2> Hurray !! </h2>\n        <p>{message}</p>\n        <LazyToDo />\n        <h2> hey !! </h2>\n      </section>\n      {/** Adding TODOList to check if the lifecycle methods are called */}\n      <TodoList />\n      <h1>Something</h1>\n      <LazyUseStateExample />\n    </Suspense>\n  );\n}\n"
  },
  {
    "path": "example_old/suspenseExamples.js",
    "content": "import Brahmos, { useState, useTransition, Suspense } from '../src';\n\nimport { fetchProfileData } from './fakeApi';\n\n// const initialResource = fetchProfileData(0);\n\nexport default function App() {\n  const [tab, setTab] = useState('home');\n\n  function showProfile(id) {\n    setTab('profile');\n  }\n\n  let page;\n  if (tab === 'home') {\n    page = <HomePage showProfile={showProfile} />;\n  } else if (tab === 'profile') {\n    page = <ProfilePage />;\n  }\n\n  // return page;\n  return <Suspense fallback={<h1>Loading the app...</h1>}>{page}</Suspense>;\n}\n\nfunction HomePage({ showProfile }) {\n  return (\n    <>\n      <h1>Home Page</h1>\n      <Button onClick={showProfile}>Open Profile</Button>\n    </>\n  );\n}\n\nfunction Separator() {\n  return <div>Something Separator</div>;\n}\n\nfunction ProfilePage() {\n  const [resource, setResource] = useState();\n\n  function showProfile(id) {\n    setResource(fetchProfileData(id));\n  }\n\n  return (\n    <>\n      <Button onClick={showProfile}>Open Profile</Button>\n      <Suspense fallback={<h2>Loading posts...</h2>}>\n        {resource && (\n          <>\n            <ProfileDetails resource={resource} />\n          </>\n        )}\n        <Separator />\n        <Suspense fallback={<h2>Loading timeline...</h2>}>\n          {resource && (\n            <>\n              <ProfileTimeline resource={resource} />\n              <Suspense fallback={<h2>Loading Trivia...</h2>}>\n                <ProfileTrivia resource={resource} />\n              </Suspense>\n            </>\n          )}\n        </Suspense>\n      </Suspense>\n      {/* <Suspense fallback={<h2>Loading timeline...</h2>}>\n        {resource && (\n          <>\n            <ProfileTimeline resource={resource} />\n            <Suspense fallback={<h2>Loading Trivia...</h2>}>\n              <ProfileTrivia resource={resource} />\n            </Suspense>\n          </>\n        )}\n      </Suspense> */}\n    </>\n  );\n}\n\nfunction ProfileDetails({ resource }) {\n  const user = resource.user.read();\n  return <h1>{user.name}</h1>;\n}\n\nfunction ProfileTimeline({ resource }) {\n  const posts = resource.posts.read();\n  return (\n    <ul>\n      {posts.map((post) => (\n        <li key={post.id}>{post.text}</li>\n      ))}\n    </ul>\n  );\n}\n\nfunction ProfileTrivia({ resource }) {\n  const trivia = resource.trivia.read();\n  return (\n    <>\n      <h2>Fun Facts</h2>\n      <ul>\n        {trivia.map((fact) => (\n          <li key={fact.id}>{fact.text}</li>\n        ))}\n      </ul>\n    </>\n  );\n}\n\nfunction Button({ children, onClick }) {\n  const [startTransition, isPending] = useTransition({\n    timeoutMs: 10000,\n  });\n\n  function handleClick() {\n    onClick();\n\n    // startTransition(() => {\n    //   onClick();\n    // });\n  }\n\n  const spinner = (\n    <span\n      className=\"DelayedSpinner\"\n      style={{\n        marginLeft: 4,\n        fontSize: 'small',\n      }}\n    >\n      Loading...\n    </span>\n  );\n\n  return (\n    <>\n      <button onClick={handleClick} disabled={isPending}>\n        {children}\n      </button>\n      {isPending ? spinner : null}\n    </>\n  );\n}\n"
  },
  {
    "path": "example_old/suspenseListExample.js",
    "content": "import Brahmos, { SuspenseList, Suspense } from '../src';\n\nimport { fetchProfileData } from './fakeApiSuspenseList';\n\nconst initialResource = fetchProfileData(0);\n\nexport default function App() {\n  return <ProfilePage resource={initialResource} />;\n}\n\nfunction ProfilePage({ resource }) {\n  return (\n    <SuspenseList revealOrder=\"forwards\" tail=\"collapsed\">\n      <Suspense fallback={<h1>Loading...</h1>}>\n        <ProfileDetails resource={resource} />\n      </Suspense>\n      <SuspenseList revealOrder=\"forwards\" tail=\"collapsed\">\n        <Suspense fallback={<h2>Loading posts...</h2>}>\n          <ProfileTimeline resource={resource} />\n        </Suspense>\n        <Suspense fallback={<h2>Loading fun facts...</h2>}>\n          <ProfileTrivia resource={resource} />\n        </Suspense>\n      </SuspenseList>\n    </SuspenseList>\n  );\n}\n\nfunction ProfileDetails({ resource }) {\n  const user = resource.user.read();\n  return <h1>{user.name}</h1>;\n}\n\nfunction ProfileTimeline({ resource }) {\n  const posts = resource.posts.read();\n  return (\n    <ul>\n      {posts.map((post) => (\n        <li key={post.id}>{post.text}</li>\n      ))}\n    </ul>\n  );\n}\n\nfunction ProfileTrivia({ resource }) {\n  const trivia = resource.trivia.read();\n  return (\n    <>\n      <h2>Fun Facts</h2>\n      <ul>\n        {trivia.map((fact) => (\n          <li key={fact.id}>{fact.text}</li>\n        ))}\n      </ul>\n    </>\n  );\n}\n"
  },
  {
    "path": "jest.config.js",
    "content": "module.exports = {\n  rootDir: './src',\n  transform: {\n    '^.+\\\\.js$': 'babel-jest',\n  },\n  moduleNameMapper: {\n    '^brahmos$': '<rootDir>/index.js',\n  },\n  setupFilesAfterEnv: ['<rootDir>/__tests__/jest.setup.js'],\n  testPathIgnorePatterns: ['jest.setup.js', 'testUtils.js'],\n};\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"brahmos\",\n  \"version\": \"0.11.1\",\n  \"description\": \"Super charged UI library with modern React API and native templates.\",\n  \"main\": \"dist/brahmos.js\",\n  \"module\": \"dist/brahmos.es.js\",\n  \"author\": \"s-yadav <sudhanshuyadav2@gmail.com>\",\n  \"license\": \"MIT\",\n  \"scripts\": {\n    \"flow\": \"flow\",\n    \"test\": \"jest\",\n    \"test:watch\": \"jest --watch --collect-coverage=false\",\n    \"test:debug\": \"node --inspect-brk ./node_modules/.bin/jest --runInBand --watch --collect-coverage=false\",\n    \"test:bundlesize\": \"yarn bundle && bundlesize\",\n    \"start\": \"webpack-dev-server --open\",\n    \"build\": \"babel src --out-dir lib\",\n    \"bundle\": \"cross-env NODE_ENV=production rollup -c rollup.config.js\",\n    \"lint\": \"eslint ./src ./example --fix\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/s-yadav/brahmos\"\n  },\n  \"bugs\": {\n    \"mail\": \"sudhanshuyadav2@gmail.com\",\n    \"url\": \"https://github.com/s-yadav/brahmos/issues\"\n  },\n  \"devDependencies\": {\n    \"@ampproject/rollup-plugin-closure-compiler\": \"^0.26.0\",\n    \"@babel/cli\": \"^7.11.6\",\n    \"@babel/core\": \"^7.11.6\",\n    \"@babel/plugin-proposal-class-properties\": \"^7.10.4\",\n    \"@babel/plugin-proposal-object-rest-spread\": \"^7.11.0\",\n    \"@babel/plugin-transform-flow-strip-types\": \"^7.10.4\",\n    \"@babel/plugin-transform-runtime\": \"^7.11.5\",\n    \"@babel/preset-env\": \"^7.11.5\",\n    \"@babel/runtime\": \"^7.11.2\",\n    \"@rollup/plugin-buble\": \"^0.21.3\",\n    \"@rollup/plugin-commonjs\": \"^15.0.0\",\n    \"@rollup/plugin-json\": \"^4.1.0\",\n    \"@rollup/plugin-node-resolve\": \"^9.0.0\",\n    \"@rollup/plugin-replace\": \"^2.3.3\",\n    \"@testing-library/dom\": \"^7.26.6\",\n    \"babel-eslint\": \"^10.1.0\",\n    \"babel-jest\": \"^26.3.0\",\n    \"babel-loader\": \"^8.1.0\",\n    \"babel-plugin-brahmos\": \"0.6.1\",\n    \"bulma\": \"^0.9.0\",\n    \"bundlesize\": \"^0.18.0\",\n    \"cross-env\": \"^7.0.2\",\n    \"css-loader\": \"^4.3.0\",\n    \"eslint\": \"^7.9.0\",\n    \"eslint-config-prettier\": \"^6.11.0\",\n    \"eslint-config-standard\": \"^14.1.1\",\n    \"eslint-plugin-flowtype\": \"^5.2.0\",\n    \"eslint-plugin-import\": \"^2.22.0\",\n    \"eslint-plugin-jest\": \"^24.0.2\",\n    \"eslint-plugin-node\": \"^11.1.0\",\n    \"eslint-plugin-promise\": \"^4.2.1\",\n    \"eslint-plugin-standard\": \"^4.0.1\",\n    \"flow-bin\": \"^0.133.0\",\n    \"google-closure-compiler\": \"^20200830.0.0\",\n    \"html-webpack-plugin\": \"^4.4.1\",\n    \"jest\": \"^26.4.2\",\n    \"js-beautify\": \"^1.13.0\",\n    \"mobx\": \"^6.0.4\",\n    \"mobx-react-lite\": \"^3.1.6\",\n    \"prettier\": \"^2.1.2\",\n    \"react-query\": \"^2.26.3\",\n    \"react-redux\": \"^7.2.2\",\n    \"react-router-dom\": \"^5.2.0\",\n    \"recharts\": \"^1.8.5\",\n    \"redux\": \"^4.0.5\",\n    \"rollup\": \"^2.27.1\",\n    \"rollup-plugin-filesize\": \"^9.0.2\",\n    \"rollup-plugin-flow\": \"^1.1.1\",\n    \"rollup-plugin-license\": \"^2.2.0\",\n    \"rollup-plugin-terser\": \"^7.0.2\",\n    \"sass\": \"^1.26.11\",\n    \"sass-loader\": \"^10.0.2\",\n    \"style-loader\": \"^1.2.1\",\n    \"webpack\": \"^4.44.2\",\n    \"webpack-cli\": \"^3.3.12\",\n    \"webpack-dev-server\": \"^3.11.0\",\n    \"zustand\": \"^3.2.0\"\n  },\n  \"resolutions\": {\n    \"@ampproject/rollup-plugin-closure-compiler/google-closure-compiler\": \"^20200830.0.0\"\n  }\n}\n"
  },
  {
    "path": "rollup.config.js",
    "content": "import fileSize from 'rollup-plugin-filesize';\nimport commonjs from '@rollup/plugin-commonjs';\nimport license from 'rollup-plugin-license';\nimport replace from '@rollup/plugin-replace';\nimport resolve from '@rollup/plugin-node-resolve';\nimport buble from '@rollup/plugin-buble';\nimport flow from 'rollup-plugin-flow';\nimport compiler from '@ampproject/rollup-plugin-closure-compiler';\n\nimport PACKAGE from './package.json';\n\nconst fullYear = new Date().getFullYear();\n\nconst banner = `${PACKAGE.name} - ${PACKAGE.version}\n  Author : ${PACKAGE.author}\n  Copyright (c) ${fullYear !== 2016 ? '2016,' : ''} ${fullYear} to ${\n  PACKAGE.author\n}, released under the ${PACKAGE.license} license.\n  ${PACKAGE.repository.url}`;\n\nconst rollupConfig = {\n  input: './src/index.js',\n  output: [\n    {\n      file: 'dist/brahmos.es.js',\n      format: 'esm',\n    },\n    {\n      file: 'dist/brahmos.js',\n      format: 'umd',\n      name: 'Brahmos',\n    },\n  ],\n  plugins: [\n    flow(),\n    buble({\n      objectAssign: true,\n    }),\n    replace({\n      'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),\n    }),\n    resolve(),\n    commonjs({\n      include: 'node_modules/**',\n    }),\n    fileSize(),\n    license({\n      banner,\n    }),\n    compiler({\n      compilationLevel: 'SIMPLE',\n    }),\n  ],\n};\n\nexport default [rollupConfig];\n"
  },
  {
    "path": "src/Children.js",
    "content": "// @flow\nimport { BRAHMOS_DATA_KEY } from './configs';\nimport { isTagElementNode, isComponentNode, isTagNode, isHtmlTagNode } from './brahmosNode';\nimport { getNormalizedProps, isNil, toArray } from './utils';\nimport type { BrahmosNode, ArrayCallback, ObjectLiteral } from './flow.types';\nimport parseChildren from './parseChildren';\n\nfunction isPlaceholderTagNode(children: BrahmosNode): boolean {\n  /**\n   * if the template string for a tag node does not have any thing,\n   * it means the tag node is just used to wrap children.\n   * Note: We always wrap the children except when children is already an array\n   * or there is single child. We do this to make the all of the child positional\n   * */\n  // $FlowFixMe: We are checking for tag node so template key will be present\n  return isTagNode(children) && !children.template.strings.some(Boolean);\n}\n\nfunction flattenChildren(children) {\n  let _children = [];\n  children.forEach((child) => {\n    if (Array.isArray(child)) {\n      _children = _children.concat(flattenChildren(child));\n    } else if (child && isHtmlTagNode(child)) {\n      _children.push(parseChildren(child));\n    } else {\n      _children.push(child);\n    }\n  });\n\n  return _children;\n}\n\nfunction getChildrenArray(children: any): ?Array<any> {\n  if (isNil(children)) return undefined;\n  else if (typeof children === 'boolean') return [];\n\n  // if the transformed value is in cache return from the cache\n  if (children[BRAHMOS_DATA_KEY]) return children[BRAHMOS_DATA_KEY];\n\n  let _children = children;\n\n  if (isPlaceholderTagNode(_children)) {\n    // if children is a tag node and is just a placeholder for all the children use the values from the node\n    _children = _children.values;\n  }\n\n  // if the children is a html tag node parse the whole static tree\n  if (isHtmlTagNode(_children)) {\n    _children = parseChildren(_children);\n  }\n\n  if (!Array.isArray(_children)) _children = [_children];\n\n  // flatten the children\n  _children = flattenChildren(_children);\n\n  // store the transformed children in cache, so we don't perform same action again\n  // Perf of adding random property in an array: https://www.measurethat.net/Benchmarks/Show/10737/1/adding-random-property-in-array\n  children[BRAHMOS_DATA_KEY] = _children;\n\n  return _children;\n}\n\nfunction map(children: any, cb: ArrayCallback): ?Array<any> {\n  const _children = getChildrenArray(children);\n  if (!_children) return children;\n  return _children.map(cb);\n}\n\nfunction childrenToArray(children: any): Array<any> {\n  const _children = getChildrenArray(children) || [];\n\n  return _children.map((child, index) => {\n    /**\n     * As we have converted children to a flat array node\n     * assign key to each elements if it isn't already present\n     */\n    if (child && child.key === undefined) {\n      child.key = index;\n    }\n    return child;\n  });\n}\n\nfunction forEach(children: any, cb: ArrayCallback): void {\n  const _children = getChildrenArray(children) || [];\n  _children.forEach(cb);\n}\n\nfunction only(children: any) {\n  const _children = getChildrenArray(children);\n  return _children && children.length === 1;\n}\n\nfunction count(children: any): number {\n  const _children = getChildrenArray(children);\n  return _children ? _children.length : 0;\n}\n\nexport const Children = {\n  map,\n  toArray: childrenToArray,\n  forEach,\n  only,\n  count,\n};\n\nexport function isValidElement(node: any) {\n  return node && (isComponentNode(node) || isTagElementNode(node));\n}\n\nexport function cloneElement(node: any, props: ObjectLiteral): ?BrahmosNode {\n  // extend props can be undefined, so have default value for it\n  props = props || {};\n\n  const argLn = arguments.length;\n\n  // We have to add children prop in case only when third param is provided.\n  if (argLn > 2) {\n    const children = argLn > 3 ? toArray(arguments, 2) : arguments[2];\n    props.children = children;\n  }\n\n  if (node) {\n    if (isHtmlTagNode(node)) {\n      const parsedChildren = parseChildren(node);\n      return cloneElement(parsedChildren, props);\n    } else if (isComponentNode(node) || isTagElementNode(node)) {\n      return {\n        ...node,\n        props: { ...node.props, ...getNormalizedProps(props, false) },\n        ref: props.ref,\n      };\n    }\n  }\n\n  return node;\n}\n"
  },
  {
    "path": "src/Component.js",
    "content": "// @flow\nimport reRender from './reRender';\nimport { guardedSetState } from './updateUtils';\nimport { BRAHMOS_DATA_KEY } from './configs';\n\nimport type {\n  ComponentInstance,\n  PureComponentInstance,\n  NewState,\n  StateCallback,\n  ObjectLiteral,\n} from './flow.types';\n\nexport class Component implements ComponentInstance {\n  $key: any;\n\n  $value: any;\n\n  props: ObjectLiteral;\n\n  state: ?ObjectLiteral;\n\n  context: any;\n  isReactComponent: boolean;\n\n  constructor(props: ObjectLiteral) {\n    this.props = props;\n\n    this.state = undefined;\n    this.context = undefined;\n\n    this[BRAHMOS_DATA_KEY] = {\n      lastSnapshot: null,\n      pendingSyncUpdates: [],\n      pendingDeferredUpdates: [],\n      fiber: null,\n      nodes: null,\n      mounted: false,\n      committedValues: {},\n      memoizedValues: null,\n      isDirty: false,\n      renderCount: 0,\n    };\n  }\n\n  setState(newState: NewState, callback: StateCallback) {\n    const shouldRerender = guardedSetState(this, (transitionId) => ({\n      state: newState,\n      transitionId,\n      callback,\n    }));\n\n    if (shouldRerender) reRender(this);\n  }\n\n  forceUpdate(callback: StateCallback) {\n    const brahmosData = this[BRAHMOS_DATA_KEY];\n\n    // if there is no fiber (when component is not mounted) we don't need to do anything\n    const { fiber } = brahmosData;\n    if (!fiber) return;\n\n    // keep the track of component through which force update is started\n    fiber.root.forcedUpdateWith = this;\n\n    this[BRAHMOS_DATA_KEY].isDirty = true;\n    reRender(this);\n    if (callback) callback(this.state);\n  }\n\n  render() {}\n\n  __render() {\n    // get the new rendered node\n    const nodes = this.render();\n\n    // store the current reference of nodes so we can use this this on next render cycle\n    this[BRAHMOS_DATA_KEY].nodes = nodes;\n    return nodes;\n  }\n}\n\nComponent.prototype.isReactComponent = true;\n\nexport class PureComponent extends Component implements PureComponentInstance {\n  isPureReactComponent: boolean;\n}\n\nPureComponent.prototype.isPureReactComponent = true;\n"
  },
  {
    "path": "src/Suspense.js",
    "content": "// @flow\nimport { createBrahmosNode, Component } from './circularDep';\n\nimport { forwardRef } from './refs';\nimport { getPromiseSuspendedValue, timestamp, resolvedPromise, isMounted } from './utils';\nimport {\n  PREDEFINED_TRANSITION_DEFERRED,\n  getTransitionFromFiber,\n  isTransitionCompleted,\n} from './transitionUtils';\nimport { withTransition, deferredUpdates } from './updateUtils';\nimport reRender from './reRender';\nimport {\n  BRAHMOS_DATA_KEY,\n  UPDATE_TYPE_DEFERRED,\n  SUSPENSE_REVEAL_INTERVAL,\n  TRANSITION_STATE_SUSPENDED,\n  TRANSITION_STATE_TIMED_OUT,\n  TRANSITION_STATE_RESOLVED,\n  TRANSITION_STATE_START,\n} from './configs';\nimport { getCurrentComponentFiber, getFiberFromComponent, setUpdateTime } from './fiber';\n\nimport type {\n  Fiber,\n  Transition,\n  AnyTransition,\n  SuspenseProps,\n  SuspenseListProps,\n  SuspenseInstance,\n  SuspenseListInstance,\n  ClassComponent,\n  FunctionalComponent,\n} from './flow.types';\n\ntype LazyComponentModule = {\n  default: ClassComponent | FunctionalComponent,\n};\n\nexport function getClosestSuspenseFiber(fiber: Fiber, includeSuspenseList: boolean): ?Fiber {\n  const { root } = fiber;\n  let { nodeInstance } = fiber;\n  while (\n    !(\n      nodeInstance instanceof Suspense ||\n      /* eslint-disable no-unmodified-loop-condition */\n      (includeSuspenseList && nodeInstance instanceof SuspenseList)\n    )\n  ) {\n    fiber = fiber.parent;\n\n    if (fiber === root) return null;\n\n    nodeInstance = fiber.nodeInstance;\n  }\n\n  return fiber;\n}\n\nexport function resetSiblingFibers(fiber: Fiber): Fiber {\n  const parentSuspenseFiber = getClosestSuspenseFiber(fiber.parent, true);\n  const isSuspenseList =\n    parentSuspenseFiber && parentSuspenseFiber.nodeInstance instanceof SuspenseList;\n\n  // if parent is not a suspense list we don't have to do anything\n  if (!isSuspenseList) return fiber;\n\n  // $FlowFixMe: This will not come here if parentSuspenseFiber is not present.\n  const { nodeInstance: component } = parentSuspenseFiber;\n  const { childManagers } = component.suspenseManagers[\n    getTransitionFromFiber(fiber, null).transitionId\n  ];\n  const { revealOrder } = component.props;\n\n  /**\n   * If a Suspense is suspended in case of backwards and together we should reset all\n   * siblings as dirty as they might need processing again.\n   * For forwards revealOrder we don't have to do anything as we in work loop we loop\n   * in forward direction only\n   */\n  if (revealOrder === 'backwards' || revealOrder === 'together') {\n    childManagers.forEach((manager) => {\n      manager.component[BRAHMOS_DATA_KEY].isDirty = true;\n    });\n\n    return childManagers[0].fiber;\n  }\n\n  return fiber;\n}\n\nfunction getClosestSuspenseListManager(manager) {\n  const { parentSuspenseManager } = manager;\n  return parentSuspenseManager && parentSuspenseManager.isSuspenseList\n    ? parentSuspenseManager\n    : null;\n}\n\n// eslint-disable-next-line no-use-before-define\nfunction getSuspenseManager(fiber: Fiber, transition: AnyTransition): SuspenseManager {\n  const { nodeInstance: component } = fiber;\n\n  const { suspenseManagers } = component;\n\n  const { transitionId } = transition;\n\n  let suspenseManager = suspenseManagers[transitionId];\n  if (!suspenseManager) {\n    suspenseManager = suspenseManagers[transitionId] = new SuspenseManager(fiber, transition);\n  }\n\n  // if the transition is on start state (restarted), remove the earlier suspender\n  if (transition.transitionState === TRANSITION_STATE_START) {\n    suspenseManager.suspender = null;\n  }\n\n  return suspenseManager;\n}\n\nfunction markComponentDirty(component: SuspenseInstance | SuspenseListInstance) {\n  component[BRAHMOS_DATA_KEY].isDirty = true;\n}\n\nfunction markManagerDirty(manager) {\n  const fiber = getFiberFromComponent(manager.component);\n  if (manager.isUnresolved() && fiber) {\n    markComponentDirty(manager.component);\n    setUpdateTime(fiber, UPDATE_TYPE_DEFERRED);\n  }\n}\n\nclass SuspenseManager {\n  fiber: Fiber;\n\n  component: SuspenseInstance | SuspenseListInstance;\n\n  transition: AnyTransition;\n\n  childManagers: Array<SuspenseManager>;\n\n  suspender: ?Promise<any>;\n\n  isSuspenseList: boolean;\n\n  parentSuspenseManager: ?SuspenseManager;\n\n  rootSuspenseManager: SuspenseManager;\n\n  handleSuspense: () => Promise<any>;\n\n  constructor(fiber, transition) {\n    const { nodeInstance } = fiber;\n    this.fiber = fiber; // this is just for reference for suspense which gets resolved before committed\n    this.component = nodeInstance;\n    this.transition = transition;\n    this.childManagers = [];\n    this.suspender = null;\n    this.isSuspenseList = nodeInstance instanceof SuspenseList;\n\n    const parentSuspenseFiber = getClosestSuspenseFiber(fiber.parent, true);\n    this.parentSuspenseManager =\n      parentSuspenseFiber && getSuspenseManager(parentSuspenseFiber, transition);\n    this.recordChildSuspense();\n\n    // bind handleSuspense\n    this.handleSuspense = this.handleSuspense.bind(this);\n  }\n\n  recordChildSuspense() {\n    const { parentSuspenseManager } = this;\n    if (parentSuspenseManager) {\n      parentSuspenseManager.childManagers.push(this);\n      this.rootSuspenseManager = parentSuspenseManager.rootSuspenseManager;\n    } else {\n      this.rootSuspenseManager = this;\n    }\n  }\n\n  addRootToProcess() {\n    const { rootSuspenseManager } = this;\n    const { root } = getCurrentComponentFiber();\n    root.afterRender(rootSuspenseManager.handleSuspense);\n  }\n\n  suspend(suspender) {\n    this.suspender = suspender;\n\n    // mark root suspense to process\n    this.addRootToProcess();\n  }\n\n  handleSuspense() {\n    const { component, suspender } = this;\n\n    const isSuspenseList = component instanceof SuspenseList;\n\n    if (isSuspenseList) {\n      return this.handleSuspenseList();\n    }\n\n    return Promise.resolve(suspender).then(this.resolve.bind(this, suspender));\n  }\n\n  isUnresolved() {\n    // if the manager is a suspense list, check if any of the child is unresolved\n    // or in case of suspense if has a suspender it means its unresolved.\n    if (this.isSuspenseList) {\n      return this.childManagers.some((manager) => manager.isUnresolved());\n    } else {\n      return this.suspender;\n    }\n  }\n\n  shouldShowFallback() {\n    const suspenseListManager = getClosestSuspenseListManager(this);\n\n    // if there is no closest suspense list manager then return true\n    if (!suspenseListManager) return true;\n\n    const { component: suspenseList, childManagers: siblingManagers } = suspenseListManager;\n\n    // get the parent of suspenseListManger\n    // $FlowFixMe: It comes here only for suspense list, so can be ignored\n    const { tail } = suspenseList.props;\n\n    // get the parent of suspenseListManger\n    const parentSuspenseListManager = getClosestSuspenseListManager(suspenseListManager);\n\n    /**\n     * If suspense list has another parent suspense list, and the suspense list\n     * is marked to not show fallback return false\n     *\n     * Or else in case of collapsed show the fallback on the first unresolved suspense.\n     */\n    if (parentSuspenseListManager && !suspenseListManager.shouldShowFallback()) {\n      return false;\n    } else if (tail === 'collapsed') {\n      for (let i = 0, ln = siblingManagers.length; i < ln; i++) {\n        const manager = siblingManagers[i];\n\n        /**\n         * If any of previous manager is suspended and which is not same as the manager\n         * we are testing then return false\n         */\n        if (tail === 'collapsed' && manager.isUnresolved()) {\n          return manager === this;\n        }\n      }\n    }\n\n    return tail !== 'hidden';\n  }\n\n  shouldRenderChildren() {\n    const suspenseListManager = getClosestSuspenseListManager(this);\n    const { suspender } = this;\n    // if there is no closest suspense list manager then return based on it has suspender\n    if (!suspenseListManager) return !suspender;\n\n    /**\n     * Also, if component is rendered without suspend once, we should not bring it\n     * to suspended state\n     */\n    if (isMounted(this.component) && !suspender) return true;\n\n    /**\n     * if parent suspenseList has a reveal order and sibling (based on reveal order)\n     * is not resolved yet, we need to wait for the sibling to resolve\n     */\n    const {\n      component: {\n        // $FlowFixMe: It comes here only for suspense list, so can be ignored\n        props: { revealOrder },\n      },\n      childManagers,\n    } = suspenseListManager;\n\n    const suspenseIndex = childManagers.indexOf(this);\n\n    const hasSuspendedSibling = childManagers.some((manager, index) => {\n      const { suspender } = manager;\n      if (suspender) {\n        return (\n          revealOrder === 'together' ||\n          (revealOrder === 'forwards' && index <= suspenseIndex) ||\n          (revealOrder === 'backwards' && index >= suspenseIndex)\n        );\n      }\n\n      return false;\n    });\n\n    return !hasSuspendedSibling;\n  }\n\n  resolve(resolvedWithSuspender) {\n    const { component, transition, suspender, childManagers } = this;\n    const pendingSuspense = transition.pendingSuspense || [];\n\n    /**\n     * if it is resolved with different suspender then current suspender\n     * Then no nee to process further\n     */\n    if (resolvedWithSuspender !== suspender) return;\n\n    /**\n     * if there isn't any suspender, child managers may have suspender\n     * Loop on child manager and handle their suspense\n     */\n    if (!suspender) {\n      childManagers.forEach((manager) => {\n        manager.handleSuspense();\n      });\n      return;\n    }\n\n    // mark the suspense to be resolved and component as dirty\n    this.suspender = null;\n    markComponentDirty(this.component);\n\n    const transitionTimedOut = transition.transitionState === TRANSITION_STATE_TIMED_OUT;\n\n    // Get the unresolved suspense for the transition.\n    const transitionHasUnresolvedSuspense = pendingSuspense.filter(\n      (suspense) => suspense.suspenseManagers[transition.transitionId].suspender,\n    ).length;\n\n    /**\n     * set transition state as resolved if transition is not timed out and it doesn't\n     * have any unresolved sibling\n     */\n    if (!transitionTimedOut && !transitionHasUnresolvedSuspense) {\n      // $FlowFixMe: We have check for not timed out, so error can be ignored\n      transition.transitionState = TRANSITION_STATE_RESOLVED;\n    }\n    /**\n     * If the transition is timed out or the suspense is not part of\n     * the transition pendingSuspense list we need to do normal deferred rendering\n     * Otherwise do re-render with the transition.\n     */\n    const doSuspenseRerender = () => {\n      let targetComponent = component;\n      /**\n       * If there is no fiber reference on the component, it means suspense is resolved before commit.\n       * In which case there must be some parent which has pending update.\n       * So we just need to restart deferred workLoop, which we can do by rerendering from wip fiber.\n       */\n      // $FlowFixMe: wip node will always be present after first render\n      if (!getFiberFromComponent(component)) targetComponent = this.fiber.root.wip.nodeInstance;\n\n      reRender(targetComponent);\n    };\n\n    // trigger rerender on specific intervals\n    setTimeout(() => {\n      if (transitionTimedOut || !pendingSuspense.includes(component)) {\n        deferredUpdates(doSuspenseRerender);\n      } else {\n        withTransition(transition, doSuspenseRerender);\n      }\n    }, timestamp() % SUSPENSE_REVEAL_INTERVAL);\n  }\n\n  getChildrenSuspenders() {\n    let childSuspenders = [];\n    this.childManagers.forEach((manager) => {\n      if (manager.isSuspenseList) {\n        childSuspenders = childSuspenders.concat(manager.getChildrenSuspenders());\n      } else if (manager.suspender) {\n        childSuspenders.push(manager.suspender);\n      }\n    });\n\n    return childSuspenders;\n  }\n\n  handleSuspenseList() {\n    const { component, childManagers } = this;\n    // $FlowFixMe: It comes here only for suspense list, so can be ignored\n    const { revealOrder = 'together', tail } = component.props;\n\n    // resolve the child managers based on reveal order\n    const handleManagerInOrder = (promise, manager) => {\n      return promise.then(() => {\n        /**\n         * If we are doing forward reveal order and have mentioned\n         * tail to be collapsed we need to mark the next manager as dirty\n         * so that the next component can show loading state\n         */\n        if (revealOrder === 'forwards' && tail === 'collapsed') {\n          markManagerDirty(manager);\n        }\n\n        return manager.handleSuspense();\n      });\n    };\n\n    /**\n     * Create a promise which resolves after all the child managers are resolved\n     */\n    const allSuspenderPromise = Promise.all(this.getChildrenSuspenders());\n\n    /**\n     * If reveal order is together we resolve all the manager only\n     * when all the suspenders are resolved.\n     *\n     * In case of forwards and backwards the managers need to resolved\n     * in the provided order event the promise resolves concurrently\n     */\n    if (revealOrder === 'together') {\n      allSuspenderPromise.then(() => {\n        childManagers.forEach((manager) => manager.handleSuspense());\n      });\n    } else if (revealOrder === 'forwards') {\n      let promise = resolvedPromise;\n      for (let i = 0, ln = childManagers.length; i < ln; i++) {\n        promise = handleManagerInOrder(promise, childManagers[i]);\n      }\n    } else if (revealOrder === 'backwards') {\n      let promise = resolvedPromise;\n      for (let i = childManagers.length - 1; i >= 0; i--) {\n        promise = handleManagerInOrder(promise, childManagers[i]);\n      }\n    }\n\n    return allSuspenderPromise;\n  }\n}\n\nfunction getActiveTransition(component: SuspenseList): AnyTransition {\n  const fiber = getCurrentComponentFiber();\n  let transition = getTransitionFromFiber(fiber, PREDEFINED_TRANSITION_DEFERRED);\n\n  /**\n   * If the transition is resolved and pendingSuspense does not include the instance\n   * then use the predefined deferred transition as transition\n   * This will happen only when called through handleSuspense\n   */\n  if (\n    transition.transitionState === TRANSITION_STATE_RESOLVED &&\n    !transition.pendingSuspense.includes(component)\n  ) {\n    transition = PREDEFINED_TRANSITION_DEFERRED;\n  }\n\n  return transition;\n}\n\nexport class SuspenseList extends Component {\n  constructor(props: SuspenseListProps) {\n    super(props);\n    this.suspenseManagers = {};\n  }\n\n  render() {\n    return this.props.children;\n  }\n}\n\nexport class Suspense extends Component implements SuspenseInstance {\n  constructor(props: SuspenseProps) {\n    super(props);\n\n    this.suspenseManagers = {};\n  }\n\n  handleSuspender(suspender: Promise<any>, suspenseFiber: Fiber) {\n    /**\n     * $FlowFixMe: We only care about custom transition in this function\n     * For predefined transition we don't wait, and we don't have to mark them pending\n     */\n    const transition: Transition = getActiveTransition(this);\n\n    const suspenseManager = getSuspenseManager(suspenseFiber, transition);\n\n    /**\n     * Mark current transition as suspended\n     * only if transition is not completed or timed out.\n     */\n    if (!isTransitionCompleted(transition)) {\n      /**\n       * Add current suspense to pending suspense\n       */\n      if (!transition.pendingSuspense.includes(this)) {\n        transition.pendingSuspense.push(this);\n      }\n\n      // Mark the transition as suspended\n      transition.transitionState = TRANSITION_STATE_SUSPENDED;\n    }\n\n    suspenseManager.suspend(suspender);\n  }\n\n  render() {\n    const { fallback, children } = this.props;\n\n    const transition = getActiveTransition(this);\n    const fiber = getCurrentComponentFiber();\n\n    const suspenseManager = getSuspenseManager(fiber, transition);\n\n    if (suspenseManager.shouldRenderChildren()) return children;\n    else if (suspenseManager.shouldShowFallback()) return fallback;\n    else return null;\n  }\n}\n\nexport const lazy = (lazyCallback: () => Promise<LazyComponentModule>) => {\n  let componentSuspender;\n\n  const LazyComponent: FunctionalComponent = forwardRef((props, ref) => {\n    const ComponentModule = componentSuspender.read();\n\n    // $FlowFixMe: lazy\n    return createBrahmosNode(ComponentModule.default, { ...props, ref: ref });\n  });\n\n  // assign a method to lazy load to start loading during createBrahmosNode call\n  LazyComponent.__loadLazyComponent = () => {\n    if (!componentSuspender) componentSuspender = getPromiseSuspendedValue(lazyCallback());\n  };\n\n  return LazyComponent;\n};\n"
  },
  {
    "path": "src/TagNode.js",
    "content": "// @flow\nimport { addDataContainer } from './utils';\nimport type { BrahmosNode, TagNodeType, NodePart } from './flow.types';\n/**\n * Generate a similar structure as Template node from BrahmosTagElement,\n * so that it can be processed in a same way tagged template literals.\n *\n * For any tag element, there are only two parts attributes and children.\n * So create parts based on that information one for attribute and one for children node,\n * And this parts will be pointing to two values [attributes, children];\n */\nexport default function getTagNode(node: BrahmosNode, isSvgPart: boolean): TagNodeType {\n  const { type } = node;\n\n  const domNode = isSvgPart\n    ? document.createElementNS('http://www.w3.org/2000/svg', type)\n    : document.createElement(type);\n\n  addDataContainer(domNode);\n\n  const nodePart: NodePart = {\n    previousSibling: null,\n    parentNode: domNode,\n    isNode: true,\n  };\n\n  return {\n    fragment: [domNode],\n    domNodes: [domNode],\n    parts: [nodePart],\n  };\n}\n"
  },
  {
    "path": "src/TemplateNode.js",
    "content": "// @flow\nimport { BRAHMOS_PLACEHOLDER } from './configs';\nimport { toArray, createEmptyTextNode, addDataContainer, remove } from './utils';\n\nimport type { TemplateNodeType, TemplateTagType, Part, NodePart } from './flow.types';\n\nfunction isBrahmosCommentNode(node: ?Node): boolean {\n  return !!node && node.nodeType === 8 && node.textContent === BRAHMOS_PLACEHOLDER;\n}\n\nexport default class TemplateNode implements TemplateNodeType {\n  templateResult: TemplateTagType;\n\n  fragment: DocumentFragment;\n\n  parts: Array<Part>;\n\n  domNodes: Array<Node>;\n\n  patched: boolean;\n\n  constructor(templateResult: TemplateTagType, isSvgPart: boolean) {\n    this.templateResult = templateResult;\n\n    // create the template first time the element is used\n    templateResult.create(isSvgPart);\n\n    // create dom fragment out of template\n    this.fragment = this.createNode(isSvgPart);\n\n    this.parts = this.getParts();\n\n    // keep the reference of child nodes\n    // TODO: Check if you want to use Array.from instead\n    this.domNodes = toArray(this.fragment.childNodes);\n\n    this.patched = false;\n  }\n\n  createNode(isSvgPart: boolean): DocumentFragment {\n    const { template, svgTemplate } = this.templateResult;\n    const templateElement = isSvgPart ? svgTemplate : template;\n    // $FlowFixMe: createNode will be called only after create method call, so templateElement will always be present\n    return document.importNode(templateElement.content, true);\n  }\n\n  getParts(): Array<Part> {\n    const { fragment, templateResult } = this;\n\n    const { partsMeta } = templateResult;\n\n    const parts = [];\n\n    // get the flattened list of elements.\n    const elements = fragment.querySelectorAll('*');\n\n    // generate part information which actual dom nodes which will be added in dom\n    // eslint-disable-next-line no-unmodified-loop-condition\n    for (let i = 0, ln = partsMeta.length; i < ln; i++) {\n      const partMeta = partsMeta[i];\n      const {\n        isAttribute,\n        attrIndex,\n        refNodeIndex,\n        prevChildIndex,\n        hasExpressionSibling,\n      } = partMeta;\n      let refNode = elements[refNodeIndex];\n\n      if (isAttribute) {\n        // cache the tagAttribute calculate in templateTag part object, so we don't need to calculate it again.\n        if (!partMeta.tagAttrs) partMeta.tagAttrs = toArray(refNode.attributes);\n        parts.push({\n          isAttribute: true,\n          tagAttrs: partMeta.tagAttrs,\n          domNode: refNode,\n          attrIndex,\n        });\n\n        addDataContainer(refNode);\n      } else {\n        refNode = refNode || fragment;\n        const hasPreviousSibling = prevChildIndex !== -1;\n\n        let previousSibling;\n\n        /**\n         * If we get a dynamic part between two consecutive text node,\n         * that gets combined as single text node when we create template element with static part.\n         * For that we add an extra comment node during the compile time (babel-plugin), so they don't mix.\n         * On runtime we need to check if that comment node is present, and if present remove the comment node.\n         */\n        const possibleCommentNode = refNode.childNodes[prevChildIndex + 1];\n\n        if (hasPreviousSibling && isBrahmosCommentNode(possibleCommentNode)) {\n          remove(possibleCommentNode);\n        }\n\n        if (!hasPreviousSibling) {\n          previousSibling = null;\n        } else if (hasExpressionSibling) {\n          /**\n           * If there are two consecutive dynamic parts, we add an empty text node,\n           * So it gets easier to locate any dynamic part there.\n           */\n          previousSibling = createEmptyTextNode(refNode, prevChildIndex);\n        } else {\n          previousSibling = refNode.childNodes[prevChildIndex];\n        }\n\n        parts.push({\n          isNode: true,\n          parentNode: refNode,\n          previousSibling,\n        });\n      }\n    }\n\n    return parts;\n  }\n\n  patchParts(nodePart: NodePart) {\n    const { parts } = this;\n    const { parentNode, previousSibling } = nodePart;\n\n    if (this.patched) return;\n\n    for (let i = 0, ln = parts.length; i < ln; i++) {\n      // $FlowFixMe: We only care of NodePart and isNode check will properly check for it\n      const part: NodePart = parts[i];\n      if (part.isNode && part.parentNode instanceof DocumentFragment) {\n        part.parentNode = parentNode;\n        part.previousSibling = part.previousSibling || previousSibling;\n      }\n    }\n\n    this.patched = true;\n  }\n}\n"
  },
  {
    "path": "src/TemplateTag.js",
    "content": "// @flow\nimport type { PartMeta, TemplateTagType } from './flow.types';\n\n/**\n * Parts meta code looks like this.\n * typeCode|primaryIndex|secondaryIndex\n *\n * typeCode = 0 -> its an attribute part\n * typeCode = 1 | 2 -> Its and node part\n * typeCode = 2 -> Its has a previous sibling which is an expression\n *\n * For attributes\n * primaryIndex -> Index of element in a flattened element list, for which attribute belongs to.\n * secondaryIndex -> Dynamic attribute index. This is required to identify which is overriding which.\n *\n * For node\n * primaryIndex -> Index of parent element in a flattened element list.\n * secondaryIndex -> Index of previous children in the childNodes list of parent.\n */\nfunction decodePartMeta(partMetaCode: string): Array<PartMeta> {\n  const parts = partMetaCode.split(',');\n  return parts.map((partCodeStr) => {\n    const [typeCode, primaryIndex, secondaryIndex] = partCodeStr.split('|');\n    const isAttribute = typeCode === '0';\n    const hasExpressionSibling = typeCode === '2';\n\n    return {\n      isAttribute,\n      refNodeIndex: primaryIndex ? Number(primaryIndex) : -1,\n      attrIndex: isAttribute ? Number(secondaryIndex) : -1,\n      prevChildIndex: !isAttribute && secondaryIndex ? Number(secondaryIndex) : -1,\n      hasExpressionSibling,\n      tagAttrs: undefined,\n    };\n  });\n}\n\nexport default class TemplateTag implements TemplateTagType {\n  $key: 'svgTemplate' | 'template';\n\n  $value: ?HTMLTemplateElement;\n\n  strings: Array<string>;\n\n  template: ?HTMLTemplateElement;\n\n  svgTemplate: ?HTMLTemplateElement;\n\n  partsMeta: Array<PartMeta>;\n\n  partMetaCode: string;\n\n  staticTree: any;\n\n  constructor(strings: Array<string>, partMetaCode: string) {\n    this.strings = strings;\n    this.template = null;\n    this.svgTemplate = null;\n    this.partsMeta = [];\n    this.partMetaCode = partMetaCode;\n  }\n\n  create(isSvgPart: boolean) {\n    if (isSvgPart && this.svgTemplate) return;\n\n    if (this.template) return;\n\n    if (!this.partsMeta.length) {\n      this.partsMeta = decodePartMeta(this.partMetaCode);\n    }\n\n    this.createTemplate(isSvgPart);\n  }\n\n  createTemplate(isSvgPart: boolean) {\n    const { strings } = this;\n    const template = document.createElement('template');\n\n    const htmlStr = strings.join('');\n\n    /**\n     * if its svg child wrap it inside svg\n     * so that inner elements are parsed in svg context\n     * Or else add the htmlStr directly\n     */\n    template.innerHTML = isSvgPart ? `<svg>${htmlStr}</svg>` : htmlStr;\n\n    /**\n     * Once added to template unwrap the element from svg wrap\n     */\n    if (isSvgPart) {\n      const { content } = template;\n\n      // $FlowFixMe: In this case there will always have a wrap.\n      const svgWrap: SVGElement = content.firstChild;\n\n      // move all children out of the element\n      while (svgWrap.firstChild) content.insertBefore(svgWrap.firstChild, svgWrap);\n\n      // remove the empty element\n      content.removeChild(svgWrap);\n    }\n\n    const templateKey = isSvgPart ? 'svgTemplate' : 'template';\n\n    this[templateKey] = template;\n  }\n}\n"
  },
  {
    "path": "src/__tests__/BrahmosES6class.test.js",
    "content": "/*\nForked from -\nhttps://github.com/facebook/react/blob/master/packages/react/src/__tests__/ReactES6Class-test.js\n\nTODO: Simplify this specs.\n*/\nimport Brahmos, { render } from '..';\nimport { sleep } from './testUtils';\n\ndescribe('BrahmosES6Class', () => {\n  let container;\n  const freeze = function (expectation) {\n    Object.freeze(expectation);\n    return expectation;\n  };\n  let Inner;\n  let attachedListener = null;\n  let attachedListenerWithCallback = null;\n  let renderedName = null;\n  beforeEach(() => {\n    attachedListener = null;\n    attachedListenerWithCallback = null;\n    renderedName = null;\n    container = document.createElement('div');\n    Inner = class extends Brahmos.Component {\n      getName() {\n        return this.props.name;\n      }\n\n      render() {\n        attachedListenerWithCallback = (callback) => this.props.onClick(callback);\n        attachedListener = this.props.onClick;\n        renderedName = this.props.name;\n        return <div className={this.props.name} />;\n      }\n    };\n  });\n\n  function test(element, expectedTag, expectedClassName) {\n    const instance = render(element, container);\n    expect(container.firstChild).not.toBeNull();\n    expect(container.firstChild.tagName).toBe(expectedTag);\n    expect(container.firstChild.className).toBe(expectedClassName);\n    return instance;\n  }\n\n  it('preserves the name of the class for use in error messages', () => {\n    class Foo extends Brahmos.Component {}\n    expect(Foo.name).toBe('Foo');\n  });\n\n  it('renders a simple stateless component with prop', () => {\n    class Foo extends Brahmos.Component {\n      render() {\n        return <Inner name={this.props.bar} />;\n      }\n    }\n    test(<Foo bar=\"foo\" />, 'DIV', 'foo');\n    test(<Foo bar=\"bar\" />, 'DIV', 'bar');\n  });\n\n  it('renders based on state using initial values in this.props', () => {\n    class Foo extends Brahmos.Component {\n      constructor(props) {\n        super(props);\n        this.state = { bar: this.props.initialValue };\n      }\n\n      render() {\n        return <span className={this.state.bar} />;\n      }\n    }\n    test(<Foo initialValue=\"foo\" />, 'SPAN', 'foo');\n  });\n\n  it('renders based on state using props in the constructor', () => {\n    class Foo extends Brahmos.Component {\n      constructor(props) {\n        super(props);\n        this.state = { bar: props.initialValue };\n      }\n\n      changeState() {\n        this.setState({ bar: 'bar' });\n      }\n\n      render() {\n        if (this.state.bar === 'foo') {\n          return <div className=\"foo\" />;\n        }\n        return <span className={this.state.bar} />;\n      }\n    }\n    const instance = test(<Foo initialValue=\"foo\" />, 'DIV', 'foo');\n    instance.changeState();\n    test(<Foo />, 'SPAN', 'bar');\n  });\n\n  it('sets initial state with value returned by static getDerivedStateFromProps', () => {\n    class Foo extends Brahmos.Component {\n      state = {};\n\n      static getDerivedStateFromProps(nextProps, prevState) {\n        return {\n          foo: nextProps.foo,\n          bar: 'bar',\n        };\n      }\n\n      render() {\n        return <div className={`${this.state.foo} ${this.state.bar}`} />;\n      }\n    }\n    test(<Foo foo=\"foo\" />, 'DIV', 'foo bar');\n  });\n\n  it('updates initial state with values returned by static getDerivedStateFromProps', () => {\n    class Foo extends Brahmos.Component {\n      state = {\n        foo: 'foo',\n        bar: 'bar',\n      };\n\n      static getDerivedStateFromProps(nextProps, prevState) {\n        return {\n          foo: `not-${prevState.foo}`,\n        };\n      }\n\n      render() {\n        return <div className={`${this.state.foo} ${this.state.bar}`} />;\n      }\n    }\n    test(<Foo />, 'DIV', 'not-foo bar');\n  });\n\n  it('renders updated state with values returned by static getDerivedStateFromProps', () => {\n    class Foo extends Brahmos.Component {\n      state = {\n        value: 'initial',\n      };\n\n      static getDerivedStateFromProps(nextProps, prevState) {\n        if (nextProps.update) {\n          return {\n            value: 'updated',\n          };\n        }\n        return null;\n      }\n\n      render() {\n        return <div className={this.state.value} />;\n      }\n    }\n    test(<Foo update={false} />, 'DIV', 'initial');\n    test(<Foo update={true} />, 'DIV', 'updated');\n  });\n\n  it('should render with null in the initial state property', () => {\n    class Foo extends Brahmos.Component {\n      constructor() {\n        super();\n        this.state = null;\n      }\n\n      render() {\n        return <span />;\n      }\n    }\n    test(<Foo />, 'SPAN', '');\n  });\n\n  it('setState through an event handler', () => {\n    class Foo extends Brahmos.Component {\n      constructor(props) {\n        super(props);\n        this.state = { bar: props.initialValue };\n      }\n\n      handleClick(callback) {\n        this.setState({ bar: 'bar' }, () => callback());\n      }\n\n      render() {\n        return <Inner name={this.state.bar} onClick={this.handleClick.bind(this)} />;\n      }\n    }\n    test(<Foo initialValue=\"foo\" />, 'DIV', 'foo');\n    attachedListenerWithCallback(() => expect(renderedName).toBe('bar'));\n    // Passed the test as a callback\n  });\n\n  it('should not implicitly bind event handlers', () => {\n    class Foo extends Brahmos.Component {\n      constructor(props) {\n        super(props);\n        this.state = { bar: props.initialValue };\n      }\n\n      handleClick() {\n        this.setState({ bar: 'bar' });\n      }\n\n      render() {\n        return <Inner name={this.state.bar} onClick={this.handleClick} />;\n      }\n    }\n    test(<Foo initialValue=\"foo\" />, 'DIV', 'foo');\n    expect(attachedListener).toThrow();\n  });\n\n  it('will call all the normal life cycle methods', () => {\n    let lifeCycles = [];\n    class Foo extends Brahmos.Component {\n      constructor() {\n        super();\n        this.state = {};\n      }\n\n      componentDidMount() {\n        lifeCycles.push('did-mount');\n      }\n\n      shouldComponentUpdate(nextProps, nextState) {\n        lifeCycles.push('should-update', nextProps, nextState);\n        return true;\n      }\n\n      componentDidUpdate(prevProps, prevState) {\n        lifeCycles.push('did-update', prevProps, prevState);\n      }\n\n      componentWillUnmount() {\n        lifeCycles.push('will-unmount');\n      }\n\n      render() {\n        return <span className={this.props.value} />;\n      }\n    }\n    class Outer extends Brahmos.Component {\n      constructor(props) {\n        super(props);\n        this.state = {\n          isFooVisible: this.props.visible,\n        };\n      }\n\n      unmountFoo(callback) {\n        this.setState(\n          {\n            isFooVisible: false,\n          },\n          () => callback,\n        );\n      }\n\n      render() {\n        if (this.state.isFooVisible) {\n          return <Foo value={this.props.value} />;\n        }\n        return <div />;\n      }\n    }\n    test(<Outer visible value=\"foo\" />, 'SPAN', 'foo');\n    expect(lifeCycles).toEqual(['did-mount']);\n    lifeCycles = []; // reset\n    const instance = test(<Outer visible value=\"bar\" />, 'SPAN', 'bar');\n    expect(lifeCycles).toEqual([\n      'should-update',\n      freeze({ value: 'bar' }),\n      {},\n      'did-update',\n      freeze({ value: 'foo' }),\n      {},\n    ]);\n    lifeCycles = []; // reset\n    instance.unmountFoo(() => expect(lifeCycles).toEqual(['will-unmount']));\n  });\n\n  it('renders using forceUpdate even when there is no state', async () => {\n    class Foo extends Brahmos.Component {\n      constructor(props) {\n        super(props);\n        this.mutativeValue = props.initialValue;\n      }\n\n      handleClick(callback) {\n        this.mutativeValue = 'bar';\n        this.forceUpdate(() => callback());\n      }\n\n      render() {\n        return <Inner name={this.mutativeValue} onClick={this.handleClick.bind(this)} />;\n      }\n    }\n    test(<Foo initialValue=\"foo\" />, 'DIV', 'foo');\n    attachedListenerWithCallback(() => {});\n    await sleep(10);\n    expect(renderedName).toBe('bar');\n  });\n});\n"
  },
  {
    "path": "src/__tests__/BrahmosPureComponent.test.js",
    "content": "/*\nForked from -\nhttps://github.com/facebook/react/blob/master/packages/react/src/__tests__/ReactPureComponent-test.js\n*/\nimport Brahmos, { render } from '..';\n\ndescribe('BrahmosPureComponent', () => {\n  it('should re-render only when old and new props or state are not shallow equal', (done) => {\n    let renders = 0;\n    class Component extends Brahmos.PureComponent {\n      constructor() {\n        super();\n        this.state = { type: 'mushrooms' };\n      }\n\n      render() {\n        renders++;\n        return <div>{this.props.text[0]}</div>;\n      }\n    }\n\n    const container = document.createElement('div');\n    let text;\n    let component;\n\n    text = ['porcini'];\n    component = render(<Component text={text} />, container);\n    expect(container.textContent).toBe('porcini');\n    expect(renders).toBe(1);\n\n    text = ['morel'];\n    component = render(<Component text={text} />, container);\n    expect(container.textContent).toBe('morel');\n    expect(renders).toBe(2);\n\n    text[0] = 'portobello';\n    component = render(<Component text={text} />, container);\n    expect(container.textContent).toBe('morel');\n    expect(renders).toBe(2);\n\n    // Setting state without changing it doesn't cause a rerender.\n    component.setState({ type: 'mushrooms' }, () => {\n      expect(container.textContent).toBe('morel');\n      expect(renders).toBe(2);\n      // But changing state does.\n      component.setState({ type: 'portobello mushrooms' }, () => {\n        expect(container.textContent).toBe('portobello');\n        expect(renders).toBe(3);\n        done();\n      });\n    });\n  });\n\n  it('extends Brahmos.Component', () => {\n    let renders = 0;\n    class Component extends Brahmos.PureComponent {\n      constructor() {\n        super(); // Doesn't render if constructor is removed\n      }\n\n      render() {\n        renders++;\n        return <div />;\n      }\n    }\n    const pureComponentInstance = render(<Component />, document.createElement('div'));\n    expect(pureComponentInstance instanceof Brahmos.Component).toBe(true);\n    expect(pureComponentInstance instanceof Brahmos.PureComponent).toBe(true);\n    expect(renders).toBe(1);\n  });\n});\n"
  },
  {
    "path": "src/__tests__/__snapshots__/listRendering.test.js.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`Test list rendering Test Stateful Components in Array should handle adding item on state full component which is part of an array. 1`] = `\n\"<div>\n    <li>a</li>\n    <li><button data-testid=\\\\\"bcount\\\\\">Increase Count</button></li>\n    <li>b0</li>\n    <li>b1</li>\n    <li>b2</li>\n    <li><button data-testid=\\\\\"ccount\\\\\">Decrease Count</button></li>\n    <li>c0</li>\n    <li>c1</li>\n    <li><button data-testid=\\\\\"dreverse\\\\\">Reverse List</button></li>\n    <li>d0</li>\n    <li>d1</li>\n    <li>e</li>\n</div>\"\n`;\n\nexports[`Test list rendering Test Stateful Components in Array should handle removing item on state full component which is part of an array. 1`] = `\n\"<div>\n    <li>a</li>\n    <li><button data-testid=\\\\\"bcount\\\\\">Increase Count</button></li>\n    <li>b0</li>\n    <li>b1</li>\n    <li><button data-testid=\\\\\"ccount\\\\\">Decrease Count</button></li>\n    <li>c0</li>\n    <li><button data-testid=\\\\\"dreverse\\\\\">Reverse List</button></li>\n    <li>d0</li>\n    <li>d1</li>\n    <li>e</li>\n</div>\"\n`;\n\nexports[`Test list rendering Test Stateful Components in Array should handle shuffle of items on state full component which is part of an array. 1`] = `\n\"<div>\n    <li>a</li>\n    <li><button data-testid=\\\\\"bcount\\\\\">Increase Count</button></li>\n    <li>b0</li>\n    <li>b1</li>\n    <li><button data-testid=\\\\\"ccount\\\\\">Decrease Count</button></li>\n    <li>c0</li>\n    <li>c1</li>\n    <li>d1</li>\n    <li>d0</li>\n    <li><button data-testid=\\\\\"dreverse\\\\\">Reverse List</button></li>\n    <li>e</li>\n</div>\"\n`;\n\nexports[`Test list rendering Test Stateful Components in Array should render nested elements in correct order 1`] = `\n\"<div>\n    <li>a</li>\n    <li><button data-testid=\\\\\"bcount\\\\\">Increase Count</button></li>\n    <li>b0</li>\n    <li>b1</li>\n    <li><button data-testid=\\\\\"ccount\\\\\">Decrease Count</button></li>\n    <li>c0</li>\n    <li>c1</li>\n    <li><button data-testid=\\\\\"dreverse\\\\\">Reverse List</button></li>\n    <li>d0</li>\n    <li>d1</li>\n    <li>e</li>\n</div>\"\n`;\n"
  },
  {
    "path": "src/__tests__/attributes.test.js",
    "content": "import { fireEvent } from '@testing-library/dom';\n\nimport { createContext, useState } from '../';\nimport { useContext } from '../brahmos';\n\nimport { render, unmountAll, sleep } from './testUtils';\n\ndescribe('Test attribute', () => {\n  const TestContext = createContext();\n  const { Provider, Consumer } = TestContext;\n\n  it('should allow passing null on style prop', async () => {\n    function Test(style) {\n      return <div style={null}>Hell World</div>;\n    }\n\n    expect(() => render(<Test />)).not.toThrow();\n  });\n});\n"
  },
  {
    "path": "src/__tests__/children_apis.test.js",
    "content": "import { cloneElement, Children } from '../';\nimport { render } from './testUtils';\n\ndescribe('Test cloneElement', () => {\n  const Test = (props) => props.children;\n  const element = <Test type=\"welcome\">Hello World!</Test>;\n\n  it('should not change any thing if props are not provided', () => {\n    const elementClone = cloneElement(element);\n\n    expect(elementClone).not.toStrictEqual(element);\n\n    expect(elementClone.props).toEqual({\n      type: 'welcome',\n      children: 'Hello World!',\n    });\n  });\n\n  it('should update props when replacement prop is provided', () => {\n    // update props partially\n    expect(cloneElement(element, { type: 'greet' }).props).toEqual({\n      type: 'greet',\n      children: 'Hello World!',\n    });\n\n    // update props along with children\n    expect(cloneElement(element, { type: 'greet', children: 'Hello Brahmos!' }).props).toEqual({\n      type: 'greet',\n      children: 'Hello Brahmos!',\n    });\n  });\n\n  it('should update children when replacement children is provided', () => {\n    expect(cloneElement(element, { type: 'greet' }, 'Hello Brahmos!').props).toEqual({\n      type: 'greet',\n      children: 'Hello Brahmos!',\n    });\n\n    // passing undefined should replace child\n    expect(cloneElement(element, { type: 'greet' }, undefined).props).toEqual({\n      type: 'greet',\n      children: undefined,\n    });\n\n    // should allow passing multiple children\n    expect(cloneElement(element, { type: 'greet' }, 'Hello', 'Brahmos!').props).toEqual({\n      type: 'greet',\n      children: ['Hello', 'Brahmos!'],\n    });\n  });\n});\n\ndescribe('Test Children [forEach, map, count]', () => {\n  const Child = ({ children }) => <span className=\"child\">{children}</span>;\n\n  it('should loop correctly on the flattened children', () => {\n    const Parent = ({ children }) => {\n      const count = Children.count(children);\n      let forEachCount = 0;\n\n      Children.forEach(children, () => {\n        forEachCount += 1;\n      });\n\n      const modifiedChildren = Children.map(children, (child) => {\n        return cloneElement(child, { children: 2 });\n      });\n\n      return (\n        <div>\n          <div className=\"child-wrap\">{modifiedChildren}</div>\n          <div className=\"count\">{count}</div>\n          <div className=\"foreach-count\">{forEachCount}</div>\n        </div>\n      );\n    };\n\n    const { container } = render(\n      <Parent>\n        <Child>1</Child>\n        <>\n          <Child>1</Child>\n          <Child>1</Child>\n        </>\n        {[1, 1].map((value) => (\n          <Child>{value}</Child>\n        ))}\n      </Parent>,\n    );\n\n    expect(container.querySelector('.count').textContent).toEqual('5');\n    expect(container.querySelector('.foreach-count').textContent).toEqual('5');\n    expect(container.querySelector('.child-wrap').textContent).toEqual('22222');\n  });\n});\n"
  },
  {
    "path": "src/__tests__/context.test.js",
    "content": "import { fireEvent } from '@testing-library/dom';\n\nimport { createContext, useState } from '..';\nimport { useContext } from '../brahmos';\n\nimport { render, sleep, unmountAll } from './testUtils';\n\ndescribe('Test context API', () => {\n  const TestContext = createContext();\n  const { Provider, Consumer } = TestContext;\n\n  beforeEach(unmountAll);\n\n  it('should rerender Consumers if Provider passes new data and Consumer is not the direct child', async () => {\n    const Parent = ({ children }) => {\n      const [count, setCounter] = useState(1);\n      return (\n        <Provider\n          value={{\n            count,\n            setCounter,\n          }}\n        >\n          {children}\n        </Provider>\n      );\n    };\n\n    const Button = () => {\n      // Try the useContext hook\n      const { count, setCounter } = useContext(TestContext);\n      return <button onClick={() => setCounter(count + 1)}>Increment</button>;\n    };\n\n    const Value = () => {\n      // Try the hoc based consumer\n      return (\n        <Consumer>\n          {(countContext) => {\n            return <span className=\"value\">{countContext.count}</span>;\n          }}\n        </Consumer>\n      );\n    };\n\n    const Wrap = ({ children }) => {\n      return <div>{children}</div>;\n    };\n\n    const { container } = render(\n      <Parent>\n        <Wrap>\n          <Value />\n        </Wrap>\n        <Button />\n      </Parent>,\n    );\n\n    fireEvent.click(container.querySelector('button'));\n\n    await sleep(0);\n\n    expect(container.querySelector('.value').textContent).toEqual('2');\n  });\n});\n"
  },
  {
    "path": "src/__tests__/jest.setup.js",
    "content": "/**\n * RequestIdleCallback sim\n * Source: https://developers.google.com/web/updates/2015/08/using-requestidlecallback\n */\n\nwindow.requestIdleCallback =\n  window.requestIdleCallback ||\n  function (cb) {\n    var start = Date.now();\n    return setTimeout(function () {\n      const deadline = {\n        didTimeout: false,\n        timeRemaining: function () {\n          return Math.max(0, 50 - (Date.now() - start));\n        },\n      };\n      cb(deadline);\n    }, 1);\n  };\n\nwindow.cancelIdleCallback =\n  window.cancelIdleCallback ||\n  function (id) {\n    clearTimeout(id);\n  };\n"
  },
  {
    "path": "src/__tests__/listRendering.test.js",
    "content": "import { fireEvent } from '@testing-library/dom';\nimport { html } from 'js-beautify';\n\nimport { useState } from '../brahmos';\nimport { render, unmountAll } from './testUtils';\n\ndescribe('Test list rendering', () => {\n  describe('Test non keyed and keyed list', () => {\n    beforeEach(unmountAll);\n\n    it('should render a list properly', () => {\n      const items = [1, 2, 3, 4];\n      function TestComp() {\n        return (\n          <ul>\n            {items.map((item) => {\n              return <li key={item}>{item}</li>;\n            })}\n          </ul>\n        );\n      }\n\n      const { container } = render(<TestComp />);\n      expect(container.innerHTML).toEqual('<ul><li>1</li><li>2</li><li>3</li><li>4</li></ul>');\n    });\n\n    it('should maintain the element based on key', () => {\n      const items = [1, 2, 3, 4];\n      const items2 = [3, 2, 1, 4];\n\n      function TestComp({ items }) {\n        return (\n          <ul>\n            {items.map((item) => {\n              return (\n                <li key={item} data-testid={item}>\n                  {item}\n                </li>\n              );\n            })}\n          </ul>\n        );\n      }\n\n      const { container, update } = render(<TestComp items={items} />);\n\n      // Find the initial element to do reference check with next render\n      const item1 = container.getByTestId('1');\n\n      update({ items: items2 });\n\n      expect(container.textContent).toEqual('3214');\n\n      // after rerender it should hold the same element reference\n      expect(container.getByTestId('1')).toEqual(item1);\n    });\n\n    it('should update the value without reordering element if key is not provided', () => {\n      const items = [1, 2, 3, 4];\n      const items2 = [3, 2, 1, 4];\n\n      function TestComp({ items }) {\n        return (\n          <ul>\n            {items.map((item) => {\n              return <li data-testid={item}>{item}</li>;\n            })}\n          </ul>\n        );\n      }\n\n      const { container, update } = render(<TestComp items={items} />);\n\n      // Find the firest element to do reference check with next render\n      const firstChild = container.querySelectorAll('li')[0];\n\n      update({ items: items2 });\n\n      // renders correctly\n      expect(container.textContent).toEqual('3214');\n\n      // after rerender it should hold the same element reference\n      expect(container.querySelectorAll('li')[0]).toEqual(firstChild);\n    });\n  });\n\n  describe('Test nested list', () => {\n    const items = [1, 2, [3, 4], 5, 6];\n\n    function List({ items }) {\n      return items.map((item, index) => {\n        if (Array.isArray(item)) return <List key={'a' + index} items={item} />;\n\n        return (\n          <li key={item} data-testid={item}>\n            {item}\n          </li>\n        );\n      });\n    }\n\n    function TestComp({ items }) {\n      return (\n        <ul>\n          <List items={items} />\n        </ul>\n      );\n    }\n\n    let container, update;\n\n    beforeAll(() => {\n      ({ container, update } = render(<TestComp items={items} />));\n    });\n\n    afterEach(() => {\n      update({ items });\n    });\n\n    it('should correctly render nested list', () => {\n      expect(container.textContent).toEqual('123456');\n      expect(container.querySelectorAll('li').length).toEqual(6);\n    });\n\n    it('should correctly handle update when a item is added on first level nesting', () => {\n      update({ items: [1, 2, 7, [3, 4], 5, 6] });\n      expect(container.textContent).toEqual('1273456');\n    });\n\n    it('should correctly handle update when a item is removed on first level nesting', () => {\n      update({ items: [1, [3, 4], 5, 6] });\n      expect(container.textContent).toEqual('13456');\n\n      update({ items: [1, [3, 4], 6] });\n      expect(container.textContent).toEqual('1346');\n    });\n\n    it('should correctly handle update when a item is added on second level nesting', () => {\n      update({ items: [1, 2, [3, 4, 7], 5, 6] });\n      expect(container.textContent).toEqual('1234756');\n    });\n\n    it('should correctly handle update when a item is removed on first level nesting', () => {\n      update({ items: [1, 2, [3], 5, 6] });\n      expect(container.textContent).toEqual('12356');\n    });\n  });\n\n  describe('Test Stateful Components in Array', () => {\n    const Item = ({ item }) => <li>{item}</li>;\n    const Repeater = ({ id, increment, reverse }) => {\n      const [count, setCount] = useState(2);\n      const [reverseList, setReverseState] = useState(false);\n\n      const items = [];\n      if (reverse) {\n        items.push(\n          <li key={id + 'btn'}>\n            <button\n              data-testid={id + 'reverse'}\n              onClick={() => {\n                setReverseState(!reverseList);\n              }}\n            >\n              Reverse List\n            </button>\n          </li>,\n        );\n      } else {\n        items.push(\n          <li key={id + 'btn'}>\n            <button\n              data-testid={id + 'count'}\n              onClick={() => {\n                setCount(increment ? count + 1 : count - 1);\n              }}\n            >\n              {increment ? 'Increase' : 'Decrease'} Count\n            </button>\n          </li>,\n        );\n      }\n\n      Array.from({ length: count }).forEach((val, index) => {\n        items.push(<Item key={id + index} item={id + index} />);\n      });\n\n      if (reverseList) items.reverse();\n\n      return items;\n    };\n\n    let container;\n\n    beforeEach(() => {\n      ({ container } = render(\n        <div>\n          {[\n            <Item key=\"a\" item={'a'} />,\n            <Repeater key=\"b\" id={'b'} increment />,\n            <Repeater key=\"c\" id={'c'} increment={false} />,\n            <Repeater key=\"d\" id={'d'} reverse />,\n            <Item key=\"e\" item={'e'} />,\n          ]}\n        </div>,\n      ));\n    });\n\n    afterEach(unmountAll);\n\n    it('should render nested elements in correct order', () => {\n      expect(html(container.innerHTML)).toMatchSnapshot();\n    });\n\n    it('should handle adding item on state full component which is part of an array.', async () => {\n      // should handle adding elements in between\n      fireEvent.click(container.getByTestId('bcount'));\n\n      // wait for current stack to empty.\n      await 1;\n\n      expect(container.getByText('b2')).not.toBeNull();\n      expect(html(container.innerHTML)).toMatchSnapshot();\n    });\n\n    it('should handle removing item on state full component which is part of an array.', async () => {\n      // should handle deleting elements in between\n      fireEvent.click(container.getByTestId('ccount'));\n\n      // wait for current stack to empty.\n      await 1;\n      //   expect(container.getByText('c1')).toBeNull();\n      expect(html(container.innerHTML)).toMatchSnapshot();\n    });\n\n    it('should handle shuffle of items on state full component which is part of an array.', async () => {\n      // should handle deleting elements in between\n      fireEvent.click(container.getByTestId('dreverse'));\n\n      // wait for current stack to empty.\n      await 1;\n      //   expect(container.getByText('c1')).toBeNull();\n      expect(html(container.innerHTML)).toMatchSnapshot();\n    });\n  });\n});\n"
  },
  {
    "path": "src/__tests__/memo.test.js",
    "content": "import { fireEvent } from '@testing-library/dom';\n\nimport { memo, useState } from '../';\n\nimport { render, sleep } from './testUtils';\n\ndescribe('Test memoization', () => {\n  it('should rerender on state change in memoized functional component ', async () => {\n    const Test = memo(() => {\n      const [value, setValue] = useState(1);\n      return (\n        <div className=\"wrap\">\n          <span className=\"value\">{value}</span>\n          <button onClick={() => setValue(value + 1)}>Increment</button>\n        </div>\n      );\n    });\n\n    const { container } = render(<Test />);\n\n    fireEvent.click(container.querySelector('button'));\n\n    await sleep(0);\n\n    expect(container.querySelector('.value').textContent).toEqual('2');\n  });\n\n  it('should work for multiple memoized instance ', async () => {\n    const Test = memo(({ onRender, testId }) => {\n      onRender();\n      return <div className=\"wrap\">Hello World</div>;\n    });\n\n    let renderCount1 = 0;\n    let renderCount2 = 0;\n\n    const onRender1 = () => (renderCount1 += 1);\n    const onRender2 = () => (renderCount2 += 1);\n\n    const { update: update1 } = render(<Test onRender={onRender1} testId={0} />);\n    const { update: update2 } = render(<Test onRender={onRender2} testId={0} />);\n\n    expect(renderCount1).toEqual(1);\n    expect(renderCount2).toEqual(1);\n\n    // try re rendering with same props,  render count should not change\n    update1({ onRender: onRender1, testId: 0 });\n    expect(renderCount1).toEqual(1);\n\n    // try re rendering with other props, render count should change\n    update2({ onRender: onRender2, testId: 1 });\n    expect(renderCount2).toEqual(2);\n  });\n});\n"
  },
  {
    "path": "src/__tests__/setState.test.js",
    "content": "import { fireEvent } from '@testing-library/dom';\nimport { html } from 'js-beautify';\n\nimport { Component } from '../';\n\nimport { render, unmountAll, sleep } from './testUtils';\n\ndescribe('Test setState', () => {\n  it('should handle setState in componentDidMount in multiple level', async () => {\n    class Child extends Component {\n      state = {\n        value: 1,\n      };\n\n      componentDidMount() {\n        this.setState({ value: 2 });\n      }\n\n      render() {\n        return (\n          <div>\n            <span>{this.state.value}</span>\n          </div>\n        );\n      }\n    }\n\n    class Parent extends Component {\n      state = {\n        value: 1,\n      };\n\n      componentDidMount() {\n        this.setState({ value: 2 });\n      }\n\n      render() {\n        return (\n          <div>\n            <span>{this.state.value}</span>\n            <Child />\n          </div>\n        );\n      }\n    }\n\n    // we await as set states are happened on next micro task\n    const { container } = await render(<Parent />);\n\n    expect(container.textContent).toEqual('22');\n  });\n\n  it('should give correct value of state inside setState callback ', async () => {\n    let effectiveState = 0;\n\n    class Test extends Component {\n      state = {\n        value: 1,\n      };\n\n      componentDidMount() {\n        this.setState({ value: 2 }, () => {\n          effectiveState = this.state.value;\n        });\n      }\n\n      render() {\n        return (\n          <div>\n            <span>{this.state.value}</span>\n          </div>\n        );\n      }\n    }\n\n    // we await as set states are happened on next micro task\n    await render(<Test />);\n\n    await sleep(0);\n\n    expect(effectiveState).toEqual(2);\n  });\n\n  it('should not cause multiple repaint if another setState happens in setState callback', async () => {\n    class Test extends Component {\n      state = {\n        value: 1,\n      };\n\n      onClick = () => {\n        this.setState({ value: 2 }, () => {\n          this.setState({ value: 3 });\n        });\n      };\n\n      render() {\n        return (\n          <div>\n            <span className=\"value\">{this.state.value}</span>\n            <button data-testid=\"button\" onClick={this.onClick}>\n              Increment\n            </button>\n          </div>\n        );\n      }\n    }\n\n    const { container } = await render(<Test />);\n\n    fireEvent.click(container.getByTestId('button'));\n\n    await sleep(0);\n\n    expect(container.querySelector('.value').textContent).toEqual('3');\n  });\n\n  it('should not cause multiple repaint if another setState happens in componentDidMount/componentDidUpdate', async () => {\n    class Test extends Component {\n      state = {\n        value: 1,\n      };\n\n      componentDidUpdate() {\n        if (this.state.value !== 3) {\n          this.setState({ value: 3 });\n        }\n      }\n\n      render() {\n        return (\n          <div>\n            <span className=\"value\">{this.state.value}</span>\n          </div>\n        );\n      }\n    }\n\n    const { container, ref } = await render(<Test />);\n\n    ref.setState({ value: 2 });\n    /**\n     * We are trying to simulate actual repaint case.\n     * await for micro task as setState updates are batched\n     */\n    await 1;\n\n    await sleep(0);\n\n    expect(container.querySelector('.value').textContent).toEqual('3');\n  });\n});\n"
  },
  {
    "path": "src/__tests__/testUtils.js",
    "content": "import * as testLib from '@testing-library/dom';\nimport { render, unmountComponentAtNode } from '..';\n\nconst queryMethodRegex = /^(getBy|findBy|queryBy|getAllBy|findAllBy|queryAllBy)/;\n\nconst containersList = [];\n\nexport function unmountAll() {\n  containersList.forEach(unmountComponentAtNode);\n}\n\nfunction renderNode(node) {\n  const container = document.createElement('div');\n  const ref = render(node, container);\n\n  const methodCache = {};\n\n  containersList.push(container);\n\n  const containerProxy = new Proxy(container, {\n    get(target, key, receiver) {\n      if (typeof key === 'string' && key.match(queryMethodRegex)) {\n        methodCache[key] = methodCache[key] || testLib[key].bind(null, container);\n\n        return methodCache[key];\n      }\n\n      return Reflect.get(...arguments);\n    },\n  });\n\n  return {\n    container: containerProxy,\n    ref,\n    update: (newProps) => render({ ...node, props: newProps }, container),\n    unmount: () => unmountComponentAtNode(container),\n  };\n}\n\nexport function sleep(time) {\n  return new Promise((resolve, reject) => {\n    setTimeout(() => {\n      resolve();\n    }, time);\n  });\n}\n\nexport { renderNode as render };\n"
  },
  {
    "path": "src/__tests__/utils.test.js",
    "content": "import {\n  isHTMLElement,\n  isEventAttribute,\n  getNodeName,\n  getEventName,\n  isCustomElement,\n} from '../utils';\n\ndescribe('Test utility functions', () => {\n  describe('Test isHTMLElement', () => {\n    it('should return true for valid HTML element tag', () => {\n      expect(isHTMLElement('a')).toBe(true);\n      expect(isHTMLElement('span')).toBe(true);\n      expect(isHTMLElement('div')).toBe(true);\n    });\n\n    it('should return false for invalid HTML element tag', () => {\n      expect(isHTMLElement('CustomComponent')).toBe(false);\n      expect(isHTMLElement('_Component')).toBe(false);\n    });\n  });\n\n  describe('Test isEventAttribute', () => {\n    it('should return true if valid event attribute', () => {\n      expect(isEventAttribute('onChange')).toBe(true);\n      expect(isEventAttribute('onLoad')).toBe(true);\n      expect(isEventAttribute('onHover')).toBe(true);\n    });\n\n    it('should return false if invalid event attribute', () => {\n      expect(isEventAttribute('change')).toBe(false);\n      expect(isEventAttribute('load')).toBe(false);\n      expect(isEventAttribute('hover')).toBe(false);\n    });\n  });\n\n  describe('Test getNodeName', () => {\n    it('should return name of the current node', () => {\n      const node = document.createElement('a');\n      expect(getNodeName(node)).toBe('a');\n\n      const text = document.createTextNode('some text');\n      expect(getNodeName(text)).toBe('#text');\n    });\n  });\n\n  describe('Test getEventName', () => {\n    it('should return event name from handler attribute', () => {\n      expect(getEventName('onChange')).toBe('change');\n      expect(getEventName('onKeyDown')).toBe('keydown');\n    });\n  });\n\n  describe('Test isCustomElement', () => {\n    it('should return true for custom web components', () => {\n      expect(isCustomElement('web-component')).toBe(true);\n    });\n\n    it('should return false for components and native elements', () => {\n      expect(isCustomElement('span')).toBe(false);\n      expect(isCustomElement('MyComponent')).toBe(false);\n    });\n  });\n});\n"
  },
  {
    "path": "src/brahmos.js",
    "content": "/** Component classes,  Suspense and lazy */\nimport {\n  Component,\n  PureComponent,\n  createElement,\n  createBrahmosNode,\n  Suspense,\n  SuspenseList,\n  lazy,\n} from './circularDep';\n\nimport { html } from './tags';\n\n/** render methods */\nimport render from './render';\n\n/** Portal */\nimport createPortal from './createPortal';\n\n/** Hooks */\nimport {\n  useState,\n  useEffect,\n  useRef,\n  useReducer,\n  useMemo,\n  useCallback,\n  useLayoutEffect,\n  useContext,\n  useTransition,\n  useDeferredValue,\n  useDebugValue,\n} from './hooks';\n\n/** createContext */\nimport createContext from './createContext';\n\n/** ForwardRef and createRef */\nimport { forwardRef, createRef } from './refs';\n\n/** unmountComponentAtNode */\nimport unmountComponentAtNode from './unmountComponentAtNode';\n\n/** unstableBatchedUpdate */\nimport { deferredUpdates, syncUpdates } from './updateUtils';\n\n/** import top level api */\nimport { Children, isValidElement, cloneElement } from './Children';\n\nimport memo from './memo';\n\nconst NoopComponent = (props) => props.children;\n\n// add a noop component for StrictMode and Fragment, as brahmos don't support any deprecated API\nconst StrictMode = NoopComponent;\nconst Fragment = NoopComponent;\n\n/**\n * Mock for unstable_batchedUpdates as third party lib like Redux uses it.\n * Brahmos by default batches update so we can just call the passed callback directly\n */\nfunction unstable_batchedUpdates(cb) {\n  cb();\n}\n\nexport {\n  createElement,\n  render,\n  Component,\n  PureComponent,\n  useState,\n  useEffect,\n  useRef,\n  useReducer,\n  useMemo,\n  useCallback,\n  useLayoutEffect,\n  useContext,\n  useTransition,\n  useDeferredValue,\n  useDebugValue,\n  createContext,\n  forwardRef,\n  createRef,\n  createPortal,\n  unmountComponentAtNode,\n  Suspense,\n  SuspenseList,\n  lazy,\n  Children,\n  isValidElement,\n  cloneElement,\n  deferredUpdates as unstable_deferredUpdates,\n  syncUpdates as unstable_syncUpdates,\n  unstable_batchedUpdates,\n  memo,\n  StrictMode,\n  Fragment,\n};\n\n/** Export transforms */\nexport const jsx = createBrahmosNode;\nexport const jsxs = createBrahmosNode;\nexport const jsxDev = createBrahmosNode;\nexport { html };\n"
  },
  {
    "path": "src/brahmosNode.js",
    "content": "// @flow\nimport { isNil } from './utils';\n\nimport type { BrahmosNode, ObjectLiteral } from './flow.types';\nimport { REACT_ELEMENT } from './configs';\n\nexport const TAG_NODE = Symbol.for('tag');\nexport const TAG_ELEMENT_NODE = Symbol.for('tag-element');\nexport const CLASS_COMPONENT_NODE = Symbol.for('class-component');\nexport const FUNCTIONAL_COMPONENT_NODE = Symbol.for('functional-component');\nexport const ATTRIBUTE_NODE = Symbol.for('attribute');\n\ntype NotNil = $NonMaybeType<mixed>;\n\n// $FlowFixMe: As we are just comparing a property, on any type of non nil node\nexport function isTagElementNode({ nodeType }: NotNil): boolean {\n  return nodeType === TAG_ELEMENT_NODE;\n}\n\n// $FlowFixMe: As we are just comparing a property, on any type of non nil node\nexport function isHtmlTagNode({ nodeType }: NotNil): boolean {\n  return nodeType === TAG_NODE;\n}\n\nexport function isTagNode(node: NotNil): boolean {\n  return isTagElementNode(node) || isHtmlTagNode(node);\n}\n\n// $FlowFixMe: As we are just comparing a property, on any type of non nil node\nexport function isComponentNode({ nodeType }: NotNil): boolean {\n  return nodeType === CLASS_COMPONENT_NODE || nodeType === FUNCTIONAL_COMPONENT_NODE;\n}\n\nexport function isBrahmosNode(node: any): boolean {\n  return !!node && (isTagNode(node) || isComponentNode(node));\n}\n\n/**\n * Function to check if a node should be rendered as string\n */\nexport function isPrimitiveNode(node: any): boolean {\n  return typeof node === 'string' || typeof node === 'number';\n}\n\n/**\n * Function to check if node can be rendered or not\n */\nexport function isRenderableNode(node: any): boolean {\n  return !(isNil(node) || typeof node === 'boolean');\n}\n\n/**\n * Get the key of looped node\n */\nexport function getKey(node: BrahmosNode, index: number): number | string {\n  const key = node && node.key;\n\n  /**\n   * if key is defined use key or else use index as key.\n   */\n  return key === undefined ? index : key;\n}\n\nexport function brahmosNode(props: ?ObjectLiteral, values: ?Array<any>, key?: string): BrahmosNode {\n  return {\n    $$typeof: REACT_ELEMENT,\n    /** Common node properties */\n    nodeType: null,\n    key,\n    ref: null,\n    portalContainer: null,\n\n    /** Component specific properties */\n    type: null,\n    props,\n\n    /** tag node specific properties */\n    values,\n    template: null,\n  };\n}\n"
  },
  {
    "path": "src/circularDep.js",
    "content": "/**\n * The following components cause circular dependency\n * issue in webpack, so to mitigate that the order of\n * import in bundler is forced through this\n */\n\nexport * from './Component';\nexport * from './createElement';\nexport * from './Suspense';\n"
  },
  {
    "path": "src/configs.js",
    "content": "// @flow\n// React element types\n// We have to add same type of to support third party plugins\nexport const REACT_ELEMENT = Symbol.for('react.element');\nexport const REACT_FORWARD_REF = Symbol.for('react.forward_ref');\n\n// Brahmos placeholder\nexport const BRAHMOS_PLACEHOLDER = '{{brahmos}}';\n\n// reserved props which cannot be forward to component props\nexport const RESERVED_ATTRIBUTES = {\n  key: 1,\n  ref: 1,\n};\n\nexport const MODIFIED_ATTRIBUTES: { [key: string]: string } = {\n  className: 'class',\n  htmlFor: 'for',\n  acceptCharset: 'accept-charset',\n  httpEquiv: 'http-equiv',\n  tabIndex: 'tabindex', // tabIndex is supported both on svg and html, but in svg the camelCase does not work. So transform this\n};\n\nexport const RENAMED_EVENTS = {\n  doubleclick: 'dblclick',\n};\n\n\n/**\n * Regex taken from Preact. (https://github.com/preactjs/preact/blob/master/compat/src/render.js)\n */\n// Input types for which onchange should not be converted to oninput.\n// type=\"file|checkbox|radio\", plus \"range\" in IE11.\n// (IE11 doesn't support Symbol, which we use here to turn `rad` into `ra` which matches \"range\")\nexport const ONCHANGE_INPUT_TYPES =\n\ttypeof Symbol !== 'undefined' ? /fil|che|rad/i : /fil|che|ra/i;\n\nexport const CAMEL_ATTRIBUTES = /^(?:accent|alignment|arabic|baseline|cap|clip(?!PathU)|color|fill|flood|font|glyph(?!R)|horiz|marker(?!H|W|U)|overline|paint|stop|strikethrough|stroke|text(?!L)|underline|unicode|units|v|vector|vert|word|writing|x(?!C))[A-Z]/;\n\n\n/**\n * Regex taken from Preact. (https://github.com/preactjs/preact/blob/master/src/constants.js)\n */\nexport const IS_NON_DIMENSIONAL = /acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|^--/i;\n\n/**\n * xlink namespace for svgs\n */\nexport const XLINK_NS = 'http://www.w3.org/1999/xlink';\n\nexport const SUSPENSE_REVEAL_INTERVAL = 100; // in ms\n\n/**\n * Brahmos data key which shouldn't be touched\n */\nexport const BRAHMOS_DATA_KEY: '__brahmosData' = '__brahmosData';\nexport const LAST_ARRAY_DOM_KEY: '__brahmosLastArrayDom' = '__brahmosLastArrayDom';\nexport const ROOT_FIBER_KEY: '__rootFiber' = '__rootFiber';\n\n/** update type related constants */\nexport const UPDATE_TYPE_SYNC: 'sync' = 'sync';\nexport const UPDATE_TYPE_DEFERRED: 'deferred' = 'deferred';\n\n/** Update source related constants */\nexport const UPDATE_SOURCE_DEFAULT: 'js' = 'js';\nexport const UPDATE_SOURCE_IMMEDIATE_ACTION: 'immediate_action' = 'immediate_action';\nexport const UPDATE_SOURCE_TRANSITION: 'transition' = 'transition';\n\n/** Effect type ENUMS */\nexport const EFFECT_TYPE_NONE: 0 = 0;\nexport const EFFECT_TYPE_PLACEMENT: 1 = 1;\nexport const EFFECT_TYPE_OTHER: 2 = 2;\n\n/** Transition states */\nexport const TRANSITION_STATE_INITIAL: 'initial' = 'initial';\nexport const TRANSITION_STATE_START: 'start' = 'start';\nexport const TRANSITION_STATE_SUSPENDED: 'suspended' = 'suspended';\nexport const TRANSITION_STATE_RESOLVED: 'resolved' = 'resolved';\nexport const TRANSITION_STATE_COMPLETED: 'completed' = 'completed';\nexport const TRANSITION_STATE_TIMED_OUT: 'timedOut' = 'timedOut';\n"
  },
  {
    "path": "src/createContext.js",
    "content": "// @flow\nimport { Component } from './circularDep';\nimport { BRAHMOS_DATA_KEY } from './configs';\nimport { setUpdateTime, getFiberFromComponent } from './fiber';\n\nimport type { Fiber, AnyComponentInstance, ContextType } from './flow.types';\n\ntype ConsumerCallbackReturn = (value: any) => void;\n\nlet ctxId = 1;\nexport function getConsumerCallback(component: AnyComponentInstance): ConsumerCallbackReturn {\n  return function (value: any): void {\n    /**\n     * just set the correct update time on subscribed component,\n     * and then workloop will take care of updating them.\n     */\n    const fiber: Fiber = getFiberFromComponent(component);\n    const { updateType } = fiber.root;\n\n    // update time only when context value has been changed\n    if (component.context !== value) {\n      // mark consumer dirty\n      component[BRAHMOS_DATA_KEY].isDirty = true;\n\n      setUpdateTime(fiber, updateType);\n    }\n  };\n}\n\nexport default function createContext(defaultValue: any): ContextType {\n  const id = `cC${ctxId++}`;\n\n  class Provider extends Component {\n    constructor(props) {\n      super(props);\n      this.subs = [];\n    }\n\n    shouldComponentUpdate(nextProp) {\n      const { value } = this.props;\n      if (value !== nextProp.value) {\n        this.subs.forEach((cb) => cb(nextProp.value));\n      }\n      return true;\n    }\n\n    sub(component) {\n      const { subs } = this;\n      const callback = getConsumerCallback(component);\n\n      subs.push(callback);\n\n      const { componentWillUnmount } = component;\n\n      component.componentWillUnmount = () => {\n        subs.splice(subs.indexOf(callback), 1);\n        if (componentWillUnmount) componentWillUnmount();\n      };\n    }\n\n    render() {\n      return this.props.children;\n    }\n  }\n\n  // add metadata for provider\n  Provider.__ccId = id;\n\n  /**\n   * consumer component which subscribes to provider on initialization\n   * and unsubscribe on component unmount\n   */\n  class Consumer extends Component {\n    render() {\n      return this.props.children(this.context);\n    }\n  }\n\n  const context = {\n    id,\n    defaultValue,\n    Provider,\n    Consumer,\n  };\n\n  // add contextType information on Consumer\n  Consumer.contextType = context;\n\n  return context;\n}\n"
  },
  {
    "path": "src/createElement.js",
    "content": "// @flow\nimport { getNormalizedProps, toArray } from './utils';\nimport {\n  brahmosNode,\n  TAG_ELEMENT_NODE,\n  CLASS_COMPONENT_NODE,\n  FUNCTIONAL_COMPONENT_NODE,\n} from './brahmosNode';\n\nimport type { BrahmosNode, Ref } from './flow.types';\n\ntype Configs = { key: string, ref: Ref, children: any };\n\nexport function createBrahmosNode(element: string | Function, props: Configs, key: string) {\n  const { ref } = props;\n\n  // There can be chances key might be in props, if key is not passed as arg try to find it in props\n  if (key === undefined) key = props.key;\n\n  // remove key and ref property from props if present\n  // $FlowFixMe: It's okay to access __isForwardRef always.\n  props = getNormalizedProps(props, element.__isForwardRef);\n\n  const node = brahmosNode(props, null, key);\n  node.type = element;\n\n  /**\n   * If the create element is receiving an string element it means it is not a component,\n   * but a simple tag instead. In that case set the nodeType to tagElement\n   */\n  if (typeof element === 'string') {\n    node.nodeType = TAG_ELEMENT_NODE;\n    node.ref = ref;\n\n    return node;\n  }\n\n  // otherwise if its a component handle the component node\n  const _isClassComponent = element.prototype && element.prototype.isReactComponent;\n\n  node.nodeType = _isClassComponent ? CLASS_COMPONENT_NODE : FUNCTIONAL_COMPONENT_NODE;\n\n  // Add ref for class component\n  node.ref = _isClassComponent ? ref : null;\n\n  // if the element is a lazy component, start fetching the underlying component\n  if (element.__loadLazyComponent) element.__loadLazyComponent();\n\n  // add default props values\n  const defaultProps = typeof element === 'function' && element.defaultProps;\n  if (defaultProps) {\n    for (key in defaultProps) {\n      if (props[key] === undefined) props[key] = defaultProps[key];\n    }\n  }\n\n  return node;\n}\n\nexport function createElement(\n  element: string | Function,\n  props: Configs,\n  children: any,\n): BrahmosNode {\n  props = props || {};\n  /**\n   * If there is single children no need to keep it as an array\n   */\n  const argLn = arguments.length;\n  const _children = argLn > 3 ? toArray(arguments, 2) : children;\n\n  // add children to props\n  if (_children) props.children = _children;\n\n  return createBrahmosNode(element, props, props.key);\n}\n"
  },
  {
    "path": "src/createPortal.js",
    "content": "// @flow\nimport type { BrahmosNode } from './flow.types';\n/**\n *  Render children outside the main DOM hierarchy of\n *  the parent component without losing the context\n */\nfunction createPortal(child: ?BrahmosNode, container: HTMLElement) {\n  // add portal container information in child\n  // which we can use for forming the part\n  if (child) child.portalContainer = container;\n\n  return child;\n}\n\nexport default createPortal;\n"
  },
  {
    "path": "src/effectLoop.js",
    "content": "// @flow\nimport {\n  isTagElementNode,\n  isTagNode,\n  isComponentNode,\n  isPrimitiveNode,\n  ATTRIBUTE_NODE,\n  CLASS_COMPONENT_NODE,\n} from './brahmosNode';\nimport { callLifeCycle, insertBefore, getNextSibling } from './utils';\nimport { getTransitionFromFiber } from './transitionUtils';\nimport { getPendingUpdatesKey } from './updateUtils';\nimport { runEffects, cleanEffects } from './hooks';\n\nimport updateNodeAttributes from './updateAttribute';\nimport {\n  EFFECT_TYPE_NONE,\n  BRAHMOS_DATA_KEY,\n  UPDATE_TYPE_DEFERRED,\n  LAST_ARRAY_DOM_KEY,\n  EFFECT_TYPE_OTHER,\n  UPDATE_TYPE_SYNC,\n} from './configs';\nimport { getUpdateTimeKey, getLastCompleteTimeKey } from './fiber';\nimport { setRef } from './refs';\n\nimport type {\n  HostFiber,\n  Fiber,\n  Part,\n  NodePart,\n  ArrayPart,\n  TemplateNodeType,\n  ExtendedElement,\n} from './flow.types';\n\n/**\n * Updater to handle text node\n */\nfunction updateTextNode(fiber: Fiber): void {\n  const { node, alternate } = fiber;\n\n  // $FlowFixMe: We come to this method only as node part/array part so we don't need to handle Attribute part\n  const part: ArrayPart | NodePart = fiber.part;\n\n  const { parentNode, previousSibling } = part;\n  /**\n   * Get the next sibling before which we need to append the text node.\n   */\n  const nextSibling = getNextSibling(parentNode, previousSibling);\n\n  /**\n   * The nextSibling will point to text node if the tag fiber is already rendered\n   * In which case we just have to update the node value of the nextSibling\n   */\n  if (alternate && nextSibling) {\n    // if we have text node just update the text node\n    nextSibling.nodeValue = node;\n  } else {\n    // add nodes at the right location\n    insertBefore(parentNode, nextSibling, node);\n  }\n}\n\nfunction getTagChild(fiber: Fiber): Fiber {\n  while (fiber.child && fiber.node && !isTagNode(fiber.node)) fiber = fiber.child;\n\n  return fiber;\n}\n\nfunction setLastItemInParentDOM(parentNode: ExtendedElement, nodeInstance: TemplateNodeType): void {\n  const { domNodes } = nodeInstance;\n  parentNode[LAST_ARRAY_DOM_KEY] = domNodes[domNodes.length - 1];\n}\n\n/**\n * For array item we need to store first element reference in the part of parent fiber.\n * This is required to calculate correct prev sibling of first dom node in the list .\n */\nfunction setFirstNodeReference(part: Part, firstDOMNode: Node) {\n  if (part.isArrayNode && part.nodeIndex === 0) {\n    // $FlowFixMe: the while loop here checks if part is not undefined\n    while ((part = part.parentArrayPart)) {\n      part.firstDOMNode = firstDOMNode;\n    }\n  }\n}\n\nfunction getCorrectPreviousSibling(part: NodePart | ArrayPart): ?Node {\n  let { previousSibling } = part;\n\n  /**\n   * When the part is a array part we might not have correct previous sibling\n   * In such case we have different ways to find the previous sibling\n   */\n  if (part.isArrayNode) {\n    const { firstDOMNode, nodeIndex } = part;\n    /**\n     * if the the nodeIndex is > 0 then we can always rely on the LAST_ARRAY_DOM_KEY,\n     * As during mount and update we maintain this information.\n     */\n    if (nodeIndex > 0) {\n      previousSibling = part.parentNode[LAST_ARRAY_DOM_KEY];\n    } else if (part.parentArrayPart) {\n      /**\n       * If the part has parentArrayPart. It means there is array inside array.\n       * With that there can be two cases.\n       *\n       * 1. On mount phase where the elements are not inserted yet, we will not have first node info.\n       * In which case we want to rely on LAST_ARRAY_DOM_KEY on parent element.\n       *\n       * 2. On update we will always have firstDOMNode reference, in this case we find the previousSibling\n       * using firstDOMNode, so we always get the correct prevSibling of the array part.\n       */\n      previousSibling = firstDOMNode\n        ? firstDOMNode.previousSibling\n        : part.parentNode[LAST_ARRAY_DOM_KEY];\n    }\n  }\n\n  return previousSibling;\n}\n\nfunction reArrangeExistingNode(fiber: Fiber, alternate: Fiber): void {\n  // $FlowFixMe: We only handle ArrayPart in this function so can ignore other types\n  const { part }: { part: ArrayPart } = fiber;\n\n  if (!part.isArrayNode) return;\n\n  const { nodeIndex, parentNode } = part;\n\n  // $FlowFixMe: We only handle ArrayPart in this function so can ignore other types\n  const oldNodeIndex = alternate.part.nodeIndex;\n\n  const tagChild = getTagChild(fiber);\n  const { nodeInstance } = tagChild;\n\n  // if there is no nodeInstance or if tagChild has pendingEffects bail out from rearrange in component level\n  const componentChildHasEffect = tagChild !== fiber && tagChild.hasUncommittedEffect;\n  if (!nodeInstance || componentChildHasEffect) return;\n\n  // if the item position on last render and current render is not same, then do a rearrange\n  if (nodeIndex !== oldNodeIndex) {\n    const { domNodes } = nodeInstance;\n\n    const previousSibling = getCorrectPreviousSibling(part);\n    const nextSibling = getNextSibling(parentNode, previousSibling);\n\n    // if there is dom node and it isn't in correct place rearrange the nodes\n    const firstDOMNode = domNodes[0];\n    if (\n      firstDOMNode &&\n      firstDOMNode.previousSibling !== previousSibling &&\n      firstDOMNode !== nextSibling\n    ) {\n      insertBefore(parentNode, nextSibling, domNodes);\n    }\n\n    setFirstNodeReference(part, firstDOMNode);\n  }\n\n  // set the last item of domNodes in parentNode\n  setLastItemInParentDOM(parentNode, nodeInstance);\n}\n\nfunction handleTagEffect(fiber: Fiber) {\n  const { nodeInstance, alternate, node } = fiber;\n\n  // $FlowFixMe: TagNode will always be inside Array part of node part\n  const part: ArrayPart | NodePart = fiber.part;\n  const { parentNode } = part;\n\n  const _isTagElement = isTagElementNode(node);\n\n  // if it is the tag element handle the attributes from same fiber\n  if (_isTagElement) {\n    handleAttributeEffect(fiber, nodeInstance.domNodes[0]);\n  }\n\n  // if the alternate node is there rearrange the element if required, or else just add the new node\n  if (alternate) {\n    reArrangeExistingNode(fiber, alternate);\n  } else {\n    const previousSibling = getCorrectPreviousSibling(part);\n    const nextSibling = getNextSibling(parentNode, previousSibling);\n\n    const domNodes: Array<Node> = insertBefore(parentNode, nextSibling, nodeInstance.fragment);\n\n    /**\n     * when we add nodes first time\n     * and we are rendering as fragment it means the fragment might have childNodes\n     * which nodeInstance does not have, so for such cases we should reset nodeList on nodeInstance;\n     */\n    if (!_isTagElement) {\n      nodeInstance.domNodes = domNodes;\n    }\n\n    setFirstNodeReference(part, domNodes[0]);\n\n    // set the last item of domNodes in parentNode\n    setLastItemInParentDOM(parentNode, nodeInstance);\n  }\n}\n\nfunction handleComponentEffect(fiber) {\n  const { node, nodeInstance, root } = fiber;\n  const { updateType } = root;\n  const { nodeType } = node;\n  const brahmosData = nodeInstance[BRAHMOS_DATA_KEY];\n\n  const isDeferredUpdate = updateType === UPDATE_TYPE_DEFERRED;\n\n  if (nodeType === CLASS_COMPONENT_NODE) {\n    // if it is deferredUpdate set the memoizedValues into nodeInstance state and prop\n    if (isDeferredUpdate) {\n      Object.assign(nodeInstance, brahmosData.memoizedValues);\n    }\n\n    const { props: prevProps, state: prevState } = brahmosData.committedValues;\n\n    brahmosData.lastSnapshot = callLifeCycle(nodeInstance, 'getSnapshotBeforeUpdate', [\n      prevProps,\n      prevState,\n    ]);\n  } else {\n    // clean the existing effect\n    cleanEffects(fiber, false);\n  }\n\n  // remove all the pending updates associated with current transition\n  const { transitionId } = getTransitionFromFiber(fiber, null);\n  const pendingUpdatesKey = getPendingUpdatesKey(updateType);\n  brahmosData[pendingUpdatesKey] = isDeferredUpdate\n    ? brahmosData[pendingUpdatesKey].filter((stateMeta) => stateMeta.transitionId !== transitionId)\n    : [];\n\n  // reset isDirty flag\n  brahmosData.isDirty = false;\n  brahmosData.renderCount = 0;\n\n  root.postCommitEffects.push(fiber);\n}\n\nfunction handleComponentPostCommitEffect(fiber) {\n  const { node, nodeInstance, root, childFiberError } = fiber;\n  const { updateType } = root;\n\n  const { nodeType, ref } = node;\n  const brahmosData = nodeInstance[BRAHMOS_DATA_KEY];\n\n  if (nodeType === CLASS_COMPONENT_NODE) {\n    const { props, state } = nodeInstance;\n    const { committedValues, lastSnapshot } = brahmosData;\n    // get the previous state and prevProps\n    const { props: prevProps, state: prevState } = committedValues;\n    /**\n     * if it is first time rendered call componentDidMount or else call componentDidUpdate\n     * prevProps will not be available for first time render\n     */\n    if (!prevProps) {\n      callLifeCycle(nodeInstance, 'componentDidMount');\n    } else {\n      callLifeCycle(nodeInstance, 'componentDidUpdate', [prevProps, prevState, lastSnapshot]);\n    }\n\n    if (childFiberError) {\n      callLifeCycle(nodeInstance, 'componentDidCatch', [\n        childFiberError.error,\n        childFiberError.errorInfo,\n      ]);\n\n      // reset the error\n      fiber.childFiberError = null;\n    }\n\n    // if the component node has ref call the ref with the node instance\n    if (ref) setRef(ref, nodeInstance);\n\n    // after commit is done set the current prop and state on committed values\n    committedValues.props = props;\n    committedValues.state = state;\n\n    brahmosData.memoizedValues = null;\n  } else {\n    // call effects of functional component\n    runEffects(fiber);\n\n    // switch deferred hooks array and syncHooks hooks array, if it is deferred state update\n    if (updateType === UPDATE_TYPE_DEFERRED) {\n      const { syncHooks, deferredHooks } = nodeInstance;\n      nodeInstance.deferredHooks = syncHooks;\n      nodeInstance.syncHooks = deferredHooks;\n    }\n  }\n\n  // mark component as mounted\n  brahmosData.mounted = true;\n\n  // add fiber reference on component instance, so the component is aware of its fiber\n  brahmosData.fiber = fiber;\n}\n\nfunction handleAttributeEffect(fiber, domNode) {\n  const { node, alternate, isSvgPart } = fiber;\n  const { props, ref } = node;\n  const oldProps = alternate && alternate.node.props;\n\n  updateNodeAttributes(domNode, props, oldProps, isSvgPart);\n\n  // set ref if present\n  if (ref) setRef(ref, domNode);\n}\n\nexport function resetEffectProperties(root: HostFiber) {\n  root.tearDownFibers = [];\n  root.postCommitEffects = [];\n  root.hasUncommittedEffect = false;\n\n  /**\n   * reset retryFiber. A retryFiber might not get reset if\n   * the sync render happened while the fiber processing is\n   * scheduled\n   */\n  root.retryFiber = null;\n\n  // reset after render callbacks\n  root.resetRenderCallbacks();\n}\n\n/**\n * reset properties which are not required in future\n * of alternate fiber so those property values can be garbage collected\n */\nfunction resetAlternate(alternate) {\n  alternate.node = null;\n  alternate.nodeInstance = null;\n  alternate.child = null;\n  alternate.sibling = null;\n}\n\nexport function removeTransitionFromRoot(root: HostFiber): void {\n  const { currentTransition, pendingTransitions } = root;\n  const currentTransitionIndex = pendingTransitions.indexOf(currentTransition);\n  if (currentTransitionIndex !== -1) {\n    pendingTransitions.splice(currentTransitionIndex, 1);\n  }\n}\n\nfunction handleFiberEffect(fiber) {\n  const { node, alternate } = fiber;\n  const _isComponentNode = node && isComponentNode(node);\n\n  // if the fiber is part of an array and requires rearrange then do it\n  if (_isComponentNode && alternate) {\n    reArrangeExistingNode(fiber, alternate);\n  }\n\n  // if node has uncommitted effect, handle the effect\n  if (fiber.hasUncommittedEffect === EFFECT_TYPE_OTHER) {\n    if (isPrimitiveNode(node)) {\n      updateTextNode(fiber);\n    } else if (isTagNode(node)) {\n      handleTagEffect(fiber);\n      // TODO: Handle rearrange type of effect\n    } else if (_isComponentNode) {\n      handleComponentEffect(fiber);\n    } else if (node.nodeType === ATTRIBUTE_NODE) {\n      handleAttributeEffect(fiber, fiber.part.domNode);\n    }\n\n    // reset the hasUncommittedEffect flag\n    fiber.hasUncommittedEffect = EFFECT_TYPE_NONE;\n  }\n\n  /**\n   * once the fiber is committed, we can remove child and sibling link from alternate,\n   * so unused child and sibling fiber (if not linked as alternate of any current node)\n   * can be garbage collected\n   */\n  if (alternate) {\n    resetAlternate(alternate);\n  }\n}\n\n/**\n * Fix pointers on fibers, and return the fibers with effects\n */\nexport function preCommitBookkeeping(root: HostFiber): Array<Fiber> {\n  const { updateType, wip, current } = root;\n  const updateTimeKey = getUpdateTimeKey(updateType);\n  const lastCompleteTime = root[getLastCompleteTimeKey(updateType)];\n  const fibersWithEffect = [];\n\n  let fiber = updateType === UPDATE_TYPE_SYNC ? current : wip;\n\n  while (fiber) {\n    const { createdAt, node, child, hasUncommittedEffect } = fiber;\n    const updateTime = fiber[updateTimeKey];\n    const fiberIsNew = createdAt > lastCompleteTime;\n    const hierarchyHasUpdates = hasUncommittedEffect || updateTime > lastCompleteTime;\n\n    if (hasUncommittedEffect) {\n      // push fiber in new fiber list\n      fibersWithEffect.push(fiber);\n    }\n\n    // correct the references\n    if (fiberIsNew) {\n      /**\n       * if child is there and it does not point back to correct parent\n       * set the pointer back to parent. This can happen if the fiber is new\n       * but the child is an existing fiber. This can happen when we haven't\n       * processed fiber and just cloned from the current tree\n       * We don't do this during rendering phase to not disturb the current tree\n       */\n      if (child && child.parent !== fiber) child.parent = fiber;\n\n      /**\n       * If fiber is new and it is a component node we will need update the fiber\n       * reference in the component node\n       */\n      if (node && isComponentNode(node)) {\n        fiber.nodeInstance[BRAHMOS_DATA_KEY].fiber = fiber;\n      }\n    }\n\n    /**\n     * do a depth first traversal,\n     * go to child fiber only if the fiber is new, if its not\n     * it means no child has updates\n     */\n    if (child && hierarchyHasUpdates) fiber = child;\n    else {\n      while (fiber !== root && !fiber.sibling) fiber = fiber.parent;\n      fiber = fiber.sibling;\n    }\n  }\n\n  return fibersWithEffect;\n}\n\nexport default function effectLoop(root: HostFiber, fibersWithEffect: Array<Fiber>): void {\n  // loop on new fibers hand call if effect needs to be called\n  for (let i = 0, ln = fibersWithEffect.length; i < ln; i++) {\n    handleFiberEffect(fibersWithEffect[i]);\n  }\n\n  const { postCommitEffects } = root;\n\n  // after applying the effects run all the post effects\n  for (let i = postCommitEffects.length - 1; i >= 0; i--) {\n    handleComponentPostCommitEffect(postCommitEffects[i]);\n  }\n\n  // remove the current transition from pending transition\n  removeTransitionFromRoot(root);\n\n  // once all effect has been processed update root's last effect node and postCommitEffects\n  resetEffectProperties(root);\n\n  // clear the force update node from root only after the effect\n  root.forcedUpdateWith = null;\n}\n"
  },
  {
    "path": "src/fiber.js",
    "content": "// @flow\n\nimport {\n  isComponentNode,\n  isPrimitiveNode,\n  ATTRIBUTE_NODE,\n  isTagElementNode,\n  isHtmlTagNode,\n} from './brahmosNode';\nimport {\n  UPDATE_TYPE_DEFERRED,\n  BRAHMOS_DATA_KEY,\n  EFFECT_TYPE_NONE,\n  UPDATE_TYPE_SYNC,\n  UPDATE_SOURCE_DEFAULT,\n} from './configs';\nimport { now, isNil } from './utils';\n\nimport type {\n  Fiber,\n  HostFiber,\n  BrahmosNode,\n  Part,\n  UpdateType,\n  EffectType,\n  AnyComponentInstance,\n  ExtendedElement,\n} from './flow.types';\n\nlet currentComponentFiber;\n\nexport function setCurrentComponentFiber(fiber: ?Fiber) {\n  currentComponentFiber = fiber;\n}\n\nexport function getCurrentComponentFiber(): Fiber {\n  // $FlowFixMe: Get current component is always called during render, where it will be present\n  return currentComponentFiber;\n}\n\nexport function getLastCompleteTimeKey(\n  type: string,\n): 'lastDeferredCompleteTime' | 'lastCompleteTime' {\n  return type === UPDATE_TYPE_DEFERRED ? 'lastDeferredCompleteTime' : 'lastCompleteTime';\n}\n\nexport function getUpdateTimeKey(type: string): 'deferredUpdateTime' | 'updateTime' {\n  return type === UPDATE_TYPE_DEFERRED ? 'deferredUpdateTime' : 'updateTime';\n}\n\nexport function setUpdateTime(fiber: Fiber, type: UpdateType) {\n  const key = getUpdateTimeKey(type);\n  const time = now();\n\n  while (fiber) {\n    fiber[key] = time;\n    fiber = fiber.parent;\n  }\n}\n\n// link the new fiber to its parent or it's previous sibling\nfunction linkFiber(fiber, refFiber, parentFiber) {\n  if (refFiber === parentFiber) {\n    parentFiber.child = fiber;\n  } else {\n    refFiber.sibling = fiber;\n  }\n\n  fiber.parent = parentFiber;\n}\n\n// function to mark pending effects on the fiber and root\nexport function markPendingEffect(fiber: Fiber, effectType: EffectType) {\n  fiber.hasUncommittedEffect = effectType;\n  fiber.root.hasUncommittedEffect = true;\n}\n\nexport function cloneCurrentFiber(\n  fiber: Fiber,\n  wipFiber: ?Fiber,\n  refFiber: Fiber,\n  parentFiber: Fiber,\n): Fiber {\n  const { root, node, part, nodeInstance, child } = fiber;\n  const updateTimeKey = getUpdateTimeKey(root.updateType);\n\n  if (!wipFiber) {\n    wipFiber = createFiber(root, node, part);\n    // add fibers as each others alternate\n    addAlternates(fiber, wipFiber);\n  } else {\n    wipFiber.node = node;\n    wipFiber.part = part;\n\n    /**\n     * As the cloned node is treated as new fiber, reset the createdAt time\n     */\n    wipFiber.createdAt = now();\n  }\n\n  /**\n   * When we are cloning a fiber we should prevent the fiber to tear down\n   * A fiber can be marked for tearDown but after suspend (through suspense) / or error boundaries\n   * it can be used again making the tear down stale.\n   */\n  fiber.shouldTearDown = false;\n\n  // add the nodeInstance to cloned fiber\n  wipFiber.nodeInstance = nodeInstance;\n\n  /**\n   * Add the current child to wipFiber.\n   * This is required so that new fiber is pointing to the existing child fiber\n   * Note: We don't need to copy sibling as it will be set by loop, from where ever\n   * the cloneMethod is called.\n   * So make sure clone method is not called for only a single child if there multiple child.\n   * */\n  wipFiber.child = child;\n\n  /**\n   * We should add update times from parent fiber.\n   */\n  wipFiber[updateTimeKey] = parentFiber[updateTimeKey];\n\n  // link the new fiber to its parent or it's previous sibling\n  linkFiber(wipFiber, refFiber, parentFiber);\n\n  return wipFiber;\n}\n\nexport function getNextChildFiber(refFiber: Fiber, parentFiber: Fiber): ?Fiber {\n  return refFiber === parentFiber ? refFiber.child : refFiber.sibling;\n}\n\nexport function cloneChildrenFibers(fiber: Fiber): void {\n  let { child, root } = fiber;\n\n  /**\n   * No need to clone children if the updateType is sync,\n   */\n  if (root.updateType === UPDATE_TYPE_SYNC) {\n    return;\n  }\n\n  let lastChild;\n\n  while (child) {\n    /**\n     * use the alternate node as wip node, as its no longer used by current node,\n     * so we can reuse the object instead of creating a new one.\n     * If it doesn't have any alternate node it means this is a new node,\n     * so need to create them again\n     */\n    const { alternate } = child;\n\n    lastChild = cloneCurrentFiber(child, alternate, lastChild || fiber, fiber);\n\n    child = child.sibling;\n  }\n}\n\nexport function createHostFiber(domNode: ExtendedElement): HostFiber {\n  let afterRenderCallbacks = [];\n\n  return {\n    updateType: UPDATE_TYPE_DEFERRED,\n    updateSource: UPDATE_SOURCE_DEFAULT,\n    cancelSchedule: null,\n    domNode,\n    forcedUpdateWith: null,\n    // $FlowFixMe: Current will be set as soon after we create host fiber\n    current: null,\n    wip: null,\n    child: null,\n    retryFiber: null,\n    currentTransition: null,\n    hasUncommittedEffect: false,\n    pendingTransitions: [],\n    tearDownFibers: [],\n    postCommitEffects: [],\n    batchUpdates: {},\n    lastDeferredCompleteTime: 0,\n    lastCompleteTime: 0,\n    deferredUpdateTime: 0,\n    updateTime: 0,\n\n    /** After render utils */\n    afterRender(cb) {\n      // if the callback is not already added add the callback\n      if (!afterRenderCallbacks.includes(cb)) {\n        afterRenderCallbacks.push(cb);\n      }\n    },\n    callRenderCallbacks() {\n      for (let i = 0, ln = afterRenderCallbacks.length; i < ln; i++) {\n        afterRenderCallbacks[i]();\n      }\n    },\n    resetRenderCallbacks() {\n      afterRenderCallbacks = [];\n    },\n  };\n}\n\nexport function createFiber(root: HostFiber, node: BrahmosNode, part: Part): Fiber {\n  // if a node is ported node, update the part information\n  if (node && node.portalContainer) {\n    // $FlowFixMe: If node has portal container, the fiber part has to be ArrayPart or NodePart\n    part.parentNode = node.portalContainer;\n  }\n\n  return {\n    node,\n    nodeInstance: null,\n    root,\n    // $FlowFixMe: We always link fiber with its parent, so after creating parent will always be set\n    parent: null,\n    child: null,\n    sibling: null,\n    part,\n    alternate: null, // points to the current fiber\n    context: null, // Points to the context applicable for that fiber\n    childFiberError: null,\n    isSvgPart: false,\n    deferredUpdateTime: 0,\n    updateTime: 0,\n    processedTime: 0, // processedTime 0 signifies it needs processing\n    createdAt: now(),\n    shouldTearDown: false,\n    hasUncommittedEffect: EFFECT_TYPE_NONE,\n  };\n}\n\n/**\n * add to fibers as alternate to each other\n */\nexport function addAlternates(current: Fiber, wip: Fiber): void {\n  if (current) {\n    current.alternate = wip;\n  }\n  wip.alternate = current;\n}\n\nexport function createAndLink(\n  node: any,\n  part: Part,\n  currentFiber: ?Fiber,\n  refFiber: Fiber,\n  parentFiber: Fiber,\n): Fiber {\n  const { root } = refFiber;\n  const updateTimeKey = getUpdateTimeKey(root.updateType);\n  let fiber;\n  if (\n    currentFiber &&\n    !isNil(currentFiber.node) &&\n    !isNil(node) &&\n    shouldClone(node, currentFiber.node)\n  ) {\n    fiber = cloneCurrentFiber(currentFiber, currentFiber.alternate, refFiber, parentFiber);\n\n    // assign new node and part to the fiber\n    fiber.node = node;\n    fiber.part = part;\n  } else {\n    fiber = createFiber(root, node, part);\n\n    // if current fiber is there mark it to tear down\n    if (currentFiber) {\n      markToTearDown(currentFiber);\n    }\n  }\n\n  linkFiber(fiber, refFiber, parentFiber);\n\n  fiber.processedTime = 0;\n\n  // add parent's inheriting property to children\n  fiber[updateTimeKey] = parentFiber[updateTimeKey];\n  fiber.context = parentFiber.context;\n  fiber.isSvgPart = parentFiber.isSvgPart;\n\n  return fiber;\n}\n\nfunction shouldClone(newNode: any, oldNode: any): boolean {\n  return (\n    // if it is primitive node and old node is also primitive we can clone the previous fiber\n    (isPrimitiveNode(newNode) && isPrimitiveNode(oldNode)) ||\n    /**\n     * if the new node is attribute node, no need to check for old node as the\n     * if there is oldNode it will always be same type in case of attribute node\n     */\n    newNode.nodeType === ATTRIBUTE_NODE ||\n    // if both are array type than clone\n    (Array.isArray(newNode) && Array.isArray(oldNode)) ||\n    // if it is component node or tag element node and node type matches with oldNode's type we should clone the current\n    ((isComponentNode(newNode) || isTagElementNode(newNode)) && newNode.type === oldNode.type) ||\n    // if it is tag node and node's template matches with oldNode's template we should clone the current\n    (isHtmlTagNode(newNode) && newNode.template === oldNode.template)\n  );\n}\n\nfunction needProcessing(fiber, lastCompleteTime, updateTimeKey) {\n  return fiber && fiber[updateTimeKey] >= lastCompleteTime;\n}\n\nfunction getFiberWhichRequiresProcessing(fiber, lastCompleteTime, updateTimeKey) {\n  if (!fiber) return;\n\n  // keep looping till we find a child which needs processing\n  while (fiber && !needProcessing(fiber, lastCompleteTime, updateTimeKey)) fiber = fiber.sibling;\n\n  return fiber;\n}\n\nexport function getNextFiber(\n  fiber: Fiber,\n  topFiber: Fiber | HostFiber,\n  lastCompleteTime: number,\n  updateTimeKey: string,\n): Fiber {\n  /**\n   * Skip fibers which does not require processing\n   */\n  // if there is a child which required processing return that child\n  const child = getFiberWhichRequiresProcessing(fiber.child, lastCompleteTime, updateTimeKey);\n  if (child) return child;\n\n  let sibling;\n\n  // or else return the sibling or the next uncle which requires processing\n  while (\n    !(sibling = getFiberWhichRequiresProcessing(fiber.sibling, lastCompleteTime, updateTimeKey))\n  ) {\n    // go to fiber parents\n    fiber = fiber.parent;\n\n    // if the parent fiber is topFiber, no further processing is required, so return that\n    if (fiber === topFiber) return fiber;\n  }\n\n  // return fiber's sibling\n  return sibling;\n}\n\n/** Function to get fiber from the component */\nexport function getFiberFromComponent(component: AnyComponentInstance): Fiber {\n  /**\n   * $FlowFixMe: Component will always fiber once its rendered, so we can assume fiber is not null here\n   * And this method is always called after component is mounted once\n   */\n  return component[BRAHMOS_DATA_KEY].fiber;\n}\n\n/**\n * Function to reset child to committed fiber.\n * This is a usual case when we interrupt workLoop, the fiber might be pointing to\n * the wrong uncommitted fiber, in which case we reset it to the alternate\n * (which points to the committed one)\n */\nexport function resetToCommittedChild(fiber: Fiber): void {\n  const { root, child } = fiber;\n  /**\n   * if the child fiber is created but not committed yet,\n   * reset the child fiber to alternate child\n   */\n  if (child && child.createdAt > root.lastCompleteTime) {\n    fiber.child = child.alternate;\n  }\n}\n\n/**\n * function to push a fiber for tearDown\n */\nexport function markToTearDown(fiber: Fiber): void {\n  fiber.shouldTearDown = true;\n  fiber.root.tearDownFibers.push(fiber);\n}\n"
  },
  {
    "path": "src/flow.types.js",
    "content": "// @flow\nimport typeof {\n  LAST_ARRAY_DOM_KEY,\n  ROOT_FIBER_KEY,\n  BRAHMOS_DATA_KEY,\n  UPDATE_TYPE_SYNC,\n  UPDATE_TYPE_DEFERRED,\n  UPDATE_SOURCE_DEFAULT,\n  UPDATE_SOURCE_IMMEDIATE_ACTION,\n  UPDATE_SOURCE_TRANSITION,\n  TRANSITION_STATE_INITIAL,\n  TRANSITION_STATE_START,\n  TRANSITION_STATE_SUSPENDED,\n  TRANSITION_STATE_RESOLVED,\n  TRANSITION_STATE_COMPLETED,\n  TRANSITION_STATE_TIMED_OUT,\n  EFFECT_TYPE_NONE,\n  EFFECT_TYPE_PLACEMENT,\n  EFFECT_TYPE_OTHER,\n} from './configs';\n\n/** Extend dom type */\nexport type ExtendedElement = Element & {\n  [key: LAST_ARRAY_DOM_KEY | ROOT_FIBER_KEY]: any,\n};\n\n/** Utility types */\nexport type ObjectLiteral = { [key: string]: any };\nexport type ArrayCallback = (child: any, index: number, array: Array<any>) => any;\n\n/** Effect type */\nexport type EffectType = EFFECT_TYPE_NONE | EFFECT_TYPE_PLACEMENT | EFFECT_TYPE_OTHER;\n\n/** Error Type */\nexport type ErrorInfo = { componentStack: string };\n\n/** Update types */\nexport type UpdateType = UPDATE_TYPE_SYNC | UPDATE_TYPE_DEFERRED;\n\nexport type UpdateSource =\n  | UPDATE_SOURCE_DEFAULT\n  | UPDATE_SOURCE_IMMEDIATE_ACTION\n  | UPDATE_SOURCE_TRANSITION;\n\n/** Update types end */\n\n/** Part types */\nexport type PartMeta = {|\n  tagAttrs?: Array<string>,\n  attrIndex: number,\n  isAttribute: boolean,\n  refNodeIndex: number,\n  prevChildIndex: number,\n  hasExpressionSibling: boolean,\n|};\n\nexport type AttributePart = {|\n  isAttribute: true,\n  domNode: ExtendedElement,\n  tagAttrs: Array<string>,\n  attrIndex: number,\n|};\n\nexport type NodePart = {|\n  isNode: boolean,\n  parentNode: ExtendedElement,\n  previousSibling: ?Node,\n|};\n\nexport type ArrayPart = {|\n  isArrayNode: boolean,\n  parentNode: ExtendedElement,\n  previousSibling: ?Node,\n  nodeIndex: number,\n  firstDOMNode?: Node,\n  parentArrayPart?: ArrayPart,\n|};\n\nexport type Part = AttributePart | NodePart | ArrayPart;\n\n/** Part types end */\n\n/** Transition types */\nexport type TransitionState =\n  | TRANSITION_STATE_INITIAL\n  | TRANSITION_STATE_START\n  | TRANSITION_STATE_SUSPENDED\n  | TRANSITION_STATE_RESOLVED\n  | TRANSITION_STATE_COMPLETED\n  | TRANSITION_STATE_TIMED_OUT;\n\nexport type PredefinedTransition = {|\n  transitionId: string,\n  tryCount: number,\n  transitionState: TRANSITION_STATE_TIMED_OUT,\n|};\n\nexport type Transition = {|\n  transitionId: string,\n  tryCount: number,\n  transitionTimeout: ?TimeoutID,\n  transitionState: TransitionState,\n  isPending: boolean,\n  // eslint-disable-next-line no-use-before-define\n  pendingSuspense: Array<SuspenseInstance>,\n  clearTimeout: () => void,\n  updatePendingState: (isPending: boolean, updateSource: UpdateSource) => void,\n  startTransition: (cb: Function) => void,\n|};\n\nexport type AnyTransition = Transition | PredefinedTransition;\n/** Transition types end */\n\n/** Refs type */\nexport type ObjectRef = { current: any };\nexport type FunctionalRef = (ref: any) => void;\nexport type Ref = ObjectRef | FunctionalRef;\n\n/** Template interface */\nexport interface TemplateTagType {\n  [key: 'svgTemplate' | 'template']: ?HTMLTemplateElement;\n  template: ?HTMLTemplateElement;\n  svgTemplate: ?HTMLTemplateElement;\n  strings: Array<string>;\n  partsMeta: Array<PartMeta>;\n  partMetaCode: string;\n  staticTree: any;\n  +create: (isSvgPart: boolean) => void;\n}\n\nexport interface TemplateNodeType {\n  templateResult: TemplateTagType;\n  fragment: DocumentFragment;\n  parts: Array<Part>;\n  domNodes: Array<Node>;\n  patched: boolean;\n\n  +patchParts: (nodePart: NodePart) => void;\n}\n\nexport interface TagNodeType {\n  fragment: Array<Node>;\n  parts: Array<Part>;\n  domNodes: Array<Node>;\n}\n/** Template interface end */\n\n/** Brahmos Node type */\nexport type BrahmosNode = {|\n  $$typeof: symbol,\n  nodeType: ?symbol,\n  key?: number | string,\n  ref: ?Ref,\n  portalContainer: ?ExtendedElement,\n  type: Function,\n  props: ?ObjectLiteral,\n  values: ?Array<any>,\n  template: ?TemplateTagType,\n|};\n/** Brahmos Node type end */\n\n/** Fiber types */\nexport type Fiber = {|\n  node: any,\n  nodeInstance: any,\n  // eslint-disable-next-line no-use-before-define\n  root: HostFiber,\n  parent: Fiber,\n  child: ?Fiber,\n  sibling: ?Fiber,\n  part: any,\n  alternate: ?Fiber,\n  // eslint-disable-next-line no-use-before-define\n  context: ?AllContext,\n  childFiberError: ?{ error: Error, errorInfo: ErrorInfo },\n  isSvgPart: boolean,\n  deferredUpdateTime: number,\n  updateTime: number,\n  processedTime: number,\n  createdAt: number,\n  shouldTearDown: boolean,\n  hasUncommittedEffect: EffectType,\n|};\n\nexport type HostFiber = {|\n  updateType: UpdateType,\n  updateSource: UpdateSource,\n  cancelSchedule: Function,\n  domNode: ExtendedElement,\n  forcedUpdateWith: ?Fiber,\n  current: Fiber,\n  wip: ?Fiber,\n  child: ?Fiber,\n  retryFiber: ?Fiber,\n  currentTransition: ?AnyTransition,\n  hasUncommittedEffect: boolean,\n  pendingTransitions: Array<AnyTransition>,\n  tearDownFibers: Array<Fiber>,\n  postCommitEffects: Array<Fiber>,\n  batchUpdates: { [key: string]: number },\n  lastDeferredCompleteTime: number,\n  lastCompleteTime: number,\n  deferredUpdateTime: number,\n  updateTime: number,\n  afterRender: (cb: Function) => void,\n  callRenderCallbacks: () => void,\n  resetRenderCallbacks: () => void,\n|};\n/** Fiber types end */\n\n/** NodeInstance Interfaces */\n\nexport type ComponentBrahmosData = {|\n  pendingSyncUpdates: Array<Function>,\n  pendingDeferredUpdates: Array<Function>,\n  fiber: ?Fiber,\n  nodes: any,\n  isDirty: boolean,\n  mounted: boolean,\n  renderCount: number,\n|};\n\ntype CommittedValues = {\n  props: ObjectLiteral,\n  state: ?ObjectLiteral,\n};\n\ntype MemoizedValues = ?{\n  props: ObjectLiteral,\n  state: ?ObjectLiteral,\n  transitionId: string,\n};\n\nexport type ClassComponentBrahmosData = {|\n  ...ComponentBrahmosData,\n  committedValues: CommittedValues,\n  memoizedValues: MemoizedValues,\n|};\n\nexport type NewState = Object | ((state: ?ObjectLiteral) => Object);\nexport type StateCallback = (state: ?ObjectLiteral) => void;\n\nexport interface ComponentInstance {\n  props: ObjectLiteral;\n  state: ?ObjectLiteral;\n  context: any;\n  [key: BRAHMOS_DATA_KEY]: ClassComponentBrahmosData;\n  +setState: (newState: NewState, callback: StateCallback) => void;\n  +forceUpdate: (callback: () => void) => void;\n  componentDidMount?: () => void;\n  shouldComponentUpdate?: (nextProps: ObjectLiteral, nextState: ?ObjectLiteral) => boolean;\n  getSnapshotBeforeUpdate?: (prevProps: ObjectLiteral, prevState: ?ObjectLiteral) => void;\n  componentDidUpdate?: (prevProps: ObjectLiteral, prevState: ?ObjectLiteral, snapshot: any) => void;\n  componentDidCatch?: (error: Error, info: ErrorInfo) => void;\n  componentWillUnmount?: () => void;\n  +render: () => any;\n  +__render: () => any;\n}\n\nexport interface PureComponentInstance extends ComponentInstance {\n  isPureReactComponent: boolean;\n}\n\nexport type SuspenseProps = {\n  fallback: any,\n};\n\nexport type SuspenseListProps = {\n  revealOrder: 'forwards' | 'backwards' | 'together',\n  tail: 'collapsed' | 'hidden',\n};\n\nexport interface SuspenseInstance extends ComponentInstance {\n  props: SuspenseProps;\n  suspenseManagers: ObjectLiteral;\n  +handleSuspender: (Promise<any>, Fiber) => void;\n}\n\nexport interface SuspenseListInstance extends ComponentInstance {\n  props: SuspenseListProps;\n  suspenseManagers: ObjectLiteral;\n}\n\nexport interface ProviderInstance extends ComponentInstance {\n  subs: Array<(providerValue: any) => void>;\n  // eslint-disable-next-line no-use-before-define\n  sub: (componentInstance: ComponentClassInstance) => void;\n}\n\nexport type FunctionalComponentInstance = {\n  syncHooks: Array<any>,\n  deferredHooks: Array<any>,\n  pointer: number,\n  context: any,\n  __render: (props: ObjectLiteral) => any,\n  [key: BRAHMOS_DATA_KEY]: ComponentBrahmosData,\n};\n\nexport type ComponentClassInstance =\n  | ComponentInstance\n  | PureComponentInstance\n  | SuspenseInstance\n  | SuspenseListInstance;\n\nexport type AnyComponentInstance = ComponentClassInstance | FunctionalComponentInstance;\n\nexport type FunctionalComponent = {\n  (props: ObjectLiteral, ref: ?Ref): any,\n  displayName: ?string,\n  __loadLazyComponent: ?() => void,\n};\n\nexport type ClassComponent = {\n  getDerivedStateFromProps: (props: ObjectLiteral, state: ?ObjectLiteral) => ObjectLiteral | null,\n  getDerivedStateFromError: (error: Error) => ObjectLiteral | null,\n  displayName: ?string,\n  name: string,\n  prototype: ComponentClassInstance,\n};\n\nexport type ProviderClassType = ClassComponent & {\n  __ccId: string,\n};\n\nexport type NodeInstance = AnyComponentInstance | TemplateNodeType;\n/** NodeInstance Interfaces end */\n\n/** Context type */\nexport type ContextType = {\n  id: string,\n  defaultValue: any,\n  Provider: ProviderClassType,\n  Consumer: ClassComponent,\n};\n\nexport type AllContext = { [key: string]: ProviderInstance };\n\n/** Update types */\nexport type ClassComponentUpdate = {\n  transitionId: string,\n  state: NewState,\n  callback: StateCallback,\n};\n\nexport type FunctionalComponentUpdate = {\n  transitionId: string,\n  updater: () => void,\n};\n\nexport type PendingUpdates = Array<ClassComponentUpdate> | Array<FunctionalComponentUpdate>;\n"
  },
  {
    "path": "src/functionalComponentInstance.js",
    "content": "// @flow\nimport { prepareHooksForRender } from './hooks';\nimport { BRAHMOS_DATA_KEY } from './configs';\nimport type { FunctionalComponentInstance, ObjectLiteral } from './flow.types';\n\nexport default function functionalComponentInstance(\n  FuncComponent: Function,\n): FunctionalComponentInstance {\n  return {\n    syncHooks: [],\n    deferredHooks: [],\n    context: undefined,\n    pointer: 0,\n    __render(props: ObjectLiteral) {\n      prepareHooksForRender();\n      const nodes = FuncComponent(props);\n\n      this[BRAHMOS_DATA_KEY].nodes = nodes;\n      return nodes;\n    },\n    // keep the dynamic attributes on last so it's transpiled in compact way\n    [BRAHMOS_DATA_KEY]: {\n      pendingSyncUpdates: [],\n      pendingDeferredUpdates: [],\n      fiber: null,\n      nodes: null,\n      isDirty: false,\n      mounted: false,\n      renderCount: 0,\n    },\n  };\n}\n"
  },
  {
    "path": "src/helpers/shallowEqual.js",
    "content": "// @flow\n/**\n * Source :  https://github.com/facebook/react/blob/master/packages/shared/shallowEqual.js\n */\n\nfunction shallowEqual(objA: any, objB: any): boolean {\n  if (Object.is(objA, objB)) {\n    return true;\n  }\n\n  if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) {\n    return false;\n  }\n\n  const keysA = Object.keys(objA);\n  const keysB = Object.keys(objB);\n\n  if (keysA.length !== keysB.length) {\n    return false;\n  }\n\n  // Test for A's keys different from B.\n  for (let i = 0; i < keysA.length; i++) {\n    if (!hasOwnProperty.call(objB, keysA[i]) || !Object.is(objA[keysA[i]], objB[keysA[i]])) {\n      return false;\n    }\n  }\n\n  return true;\n}\n\nexport default shallowEqual;\n"
  },
  {
    "path": "src/hooks.js",
    "content": "// @flow\n\nimport reRender from './reRender';\nimport { getConsumerCallback } from './createContext';\nimport { getUniqueId, timestamp } from './utils';\n\nimport {\n  UPDATE_TYPE_SYNC,\n  UPDATE_TYPE_DEFERRED,\n  UPDATE_SOURCE_TRANSITION,\n  BRAHMOS_DATA_KEY,\n  UPDATE_SOURCE_IMMEDIATE_ACTION,\n  TRANSITION_STATE_INITIAL,\n  TRANSITION_STATE_START,\n  TRANSITION_STATE_TIMED_OUT,\n} from './configs';\n\nimport {\n  getCurrentUpdateSource,\n  withUpdateSource,\n  withTransition,\n  getPendingUpdates,\n  getUpdateType,\n  guardedSetState,\n} from './updateUtils';\n\nimport { getFiberFromComponent, getCurrentComponentFiber } from './fiber';\n\nimport type {\n  Fiber,\n  Transition,\n  ObjectRef,\n  StateCallback,\n  ContextType,\n  FunctionalComponentUpdate,\n} from './flow.types';\n\ntype DeferredValueHookOptions = {\n  timeoutMs: number,\n};\n\ntype TransitionOptions = {\n  timeoutMs: number,\n};\n\ntype StateHookResult = [any, (state: any) => any];\n\ntype UseTransitionResult = [(cb: Function) => void, boolean];\n\nfunction getCurrentComponent() {\n  return getCurrentComponentFiber().nodeInstance;\n}\n\n/**\n * clone hooks, syncHooks to deferredHooks\n */\nfunction cloneHooks(component) {\n  const { renderCount } = component[BRAHMOS_DATA_KEY];\n\n  component.deferredHooks = component.syncHooks.map((hook, index) => {\n    if (Array.isArray(hook)) {\n      return [...hook];\n    } else if (hook.transitionId) {\n      /**\n       * Transition hooks are shared across sync and deferred hooks,\n       * so use the same instance of hook don't clone it\n       */\n      return hook;\n      // eslint-disable-next-line no-prototype-builtins\n    } else if (hook.hasOwnProperty('current') && renderCount > 1) {\n      /**\n       * In case of useRef we need to retain the the reference if there if the\n       * render is getting called multiple times in one render cycle\n       */\n      return component.deferredHooks[index] || hook;\n    }\n    return { ...hook };\n  });\n}\n\n/**\n * Get the current hooks array based on updateType\n */\nfunction getHooksList(updateType, component) {\n  const { syncHooks, deferredHooks } = component;\n  return updateType === UPDATE_TYPE_SYNC ? syncHooks : deferredHooks;\n}\n\n/**\n * Get the current hooks array from the fiber\n */\nfunction getHooksListFromFiber(fiber) {\n  const {\n    nodeInstance,\n    root: { updateType },\n  } = fiber;\n\n  return getHooksList(updateType, nodeInstance);\n}\n\n/**\n * Get current hook, based on the type of update we are doing\n * If it is inside transition of deferred update we need deferredHooksList,\n * or else we need the sync hooks list\n */\nfunction getCurrentHook(updateType, hookIndex, component) {\n  /**\n   * if deferred hooks is not populated clone from the syncHooks\n   * This will happen if the component has never been rendered in deferred mode.\n   */\n  if (updateType === UPDATE_TYPE_DEFERRED && !component.deferredHooks.length) {\n    cloneHooks(component);\n  }\n\n  const hooks = getHooksList(updateType, component);\n  return hooks[hookIndex];\n}\n\n/**\n * Method to check if two dependency array are same\n */\nfunction isDependenciesChanged(deps, oldDeps) {\n  // if oldDeps or deps are not defined consider it is changed every time\n  if (!deps || !oldDeps || deps.length !== oldDeps.length) return true;\n  for (let i = 0, ln = deps.length; i < ln; i++) {\n    if (deps[i] !== oldDeps[i]) return true;\n  }\n  return false;\n}\n\n/**\n * Function to rerender component if state is changed\n */\nfunction reRenderComponentIfRequired(component, state, lastState) {\n  /**\n   * check if state are different before rerendering, for seState triggered by event\n   * we should always reRerender as event can have some side effects which are controlled\n   */\n  if (getCurrentUpdateSource() === UPDATE_SOURCE_IMMEDIATE_ACTION || !Object.is(state, lastState)) {\n    reRender(component);\n  }\n}\n\n/**\n * A base method to return hook at specific pointer,\n * and if not available create a new pane\n * We also pass a method to get value from the hook which is passed to the component\n * Plus a method to check if hook has to be updated\n *\n * H: Hook, R: Hook result\n */\nfunction defaultShouldUpdate<H>(hook: H): boolean {\n  return false;\n}\n\nfunction defaultReduce<H, R>(hook: H): H | R {\n  return hook;\n}\n\nfunction getHook<+H, R>(\n  createHook: () => H,\n  shouldUpdate: (hook: H) => boolean,\n  reduce: (hook: H) => R,\n): R {\n  const fiber = getCurrentComponentFiber();\n  const { nodeInstance: component } = fiber;\n  const { pointer } = component;\n  const hooks = getHooksListFromFiber(fiber);\n  let hook = hooks[pointer];\n\n  // if hook is not there initialize and add it to the pointer\n  if (!hook || shouldUpdate(hook)) {\n    hook = createHook();\n    hooks[pointer] = hook;\n  }\n\n  // increment the hook pointer\n  component.pointer += 1;\n  return reduce(hook);\n}\n\nexport function prepareHooksForRender() {\n  const fiber = getCurrentComponentFiber();\n  const {\n    nodeInstance: component,\n    root: { updateType },\n  } = fiber;\n  component.pointer = 0;\n\n  // based on update type clone the hooks to deferred hooks\n  if (updateType === UPDATE_TYPE_DEFERRED) {\n    cloneHooks(component);\n  }\n\n  // call all the pending update before trying to render,\n  const pendingUpdates = ((getPendingUpdates(fiber): any): Array<FunctionalComponentUpdate>);\n  pendingUpdates.forEach((task) => task.updater());\n}\n\n/**\n * Base logic for state hooks\n */\n\nfunction useStateBase(\n  initialState: any,\n  getNewState: (state: any, lastState: any) => any,\n): StateHookResult {\n  const component = getCurrentComponent();\n  const { pointer: hookIndex } = component;\n  return getHook(\n    (): StateHookResult => {\n      /**\n       * create a state hook\n       */\n\n      if (typeof initialState === 'function') initialState = initialState();\n\n      const hook = [\n        initialState,\n        (param: any): void => {\n          const updateType = getUpdateType();\n\n          // get committed lastState, which will be up to date in sync hook list\n          const currentHook = getCurrentHook(UPDATE_TYPE_SYNC, hookIndex, component);\n\n          const lastState = currentHook[0];\n          const state = getNewState(param, lastState);\n\n          const shouldRerender = guardedSetState(component, (transitionId) => ({\n            transitionId,\n            updater() {\n              /**\n               * get the hook again inside, as the reference of currentHook might change\n               * if we clone sync hook to deferred hook\n               */\n              const stateHook = getCurrentHook(updateType, hookIndex, component);\n\n              // call getNewState again as currentHook[0] might change if there are multiple setState\n              stateHook[0] = getNewState(param, currentHook[0]);\n            },\n          }));\n\n          if (shouldRerender) reRenderComponentIfRequired(component, state, lastState);\n        },\n      ];\n\n      return hook;\n    },\n    defaultShouldUpdate,\n    defaultReduce,\n  );\n}\n\n/**\n * Use state hook\n */\nexport function useState(initialState: any): [any, StateCallback] {\n  return useStateBase(initialState, (state, lastState) => {\n    if (typeof state === 'function') state = state(lastState);\n    return state;\n  });\n}\n\n/**\n * Use ref hook\n */\nexport function useRef(initialValue: any): ObjectRef {\n  return getHook(\n    (): ObjectRef => {\n      /**\n       * create a ref hook\n       */\n      return {\n        current: initialValue,\n      };\n    },\n    defaultShouldUpdate,\n    defaultReduce,\n  );\n}\n\n/**\n * Use reducer hook\n */\nexport function useReducer(\n  reducer: (state: any, action: any) => any,\n  initialState: any,\n  getInitialState: (initialState: any) => any,\n): StateHookResult {\n  /**\n   * If getInitialState method is provided, use that to form correct initial state\n   * Or else use passed initialState\n   */\n\n  const _initialState = getInitialState ? () => getInitialState(initialState) : initialState;\n\n  return useStateBase(_initialState, (action, lastState) => {\n    const state = reducer(lastState, action);\n    return state;\n  });\n}\n\n/**\n * use memo hook\n */\nexport function useMemo(create: () => any, dependencies: Array<any>): any {\n  const createHook = () => {\n    return {\n      value: create(),\n      dependencies,\n    };\n  };\n\n  const shouldUpdate = (hook) => isDependenciesChanged(dependencies, hook.dependencies);\n\n  const reduce = (hook) => hook.value;\n\n  return getHook(createHook, shouldUpdate, reduce);\n}\n\n/**\n * Use callback hook\n */\nexport function useCallback(callback: Function, dependencies: Array<any>): Function {\n  return useMemo(() => callback, dependencies);\n}\n\n/**\n * Base module to create effect hooks\n */\nfunction useEffectBase(effectHandler, dependencies) {\n  const fiber = getCurrentComponentFiber();\n  const { nodeInstance: component } = fiber;\n  const { pointer } = component;\n  const hooks = getHooksListFromFiber(fiber);\n\n  const lastHook = hooks[pointer] || {\n    animationFrame: null,\n    cleanEffect: null,\n  };\n\n  const hook = {\n    ...lastHook,\n    isDependenciesChanged: isDependenciesChanged(dependencies, lastHook.dependencies),\n    dependencies,\n    effect() {\n      // if dependency is changed then only call the the effect handler\n      if (hook.isDependenciesChanged) {\n        effectHandler(hook);\n      }\n    },\n  };\n\n  hooks[pointer] = hook;\n  component.pointer += 1;\n}\n\n/**\n * Use effect hook\n */\nexport function useEffect(callback: () => ?Function, dependencies: Array<any>): void {\n  useEffectBase((hook) => {\n    /**\n     * Run effect asynchronously after the paint cycle is finished\n     */\n\n    // cancel the previous callback if not yet executed\n    cancelAnimationFrame(hook.animationFrame);\n\n    // run affect after next paint\n    hook.animationFrame = requestAnimationFrame(() => {\n      setTimeout(() => {\n        hook.cleanEffect = callback();\n      });\n    });\n  }, dependencies);\n}\n\nexport function useLayoutEffect(callback: () => ?Function, dependencies: Array<any>): void {\n  useEffectBase((hook) => {\n    // run effect synchronously\n    hook.cleanEffect = callback();\n  }, dependencies);\n}\n\n/**\n * useDebugValue hook. For now this is just a placeholder,\n * As there is no devtool support it. Revisit it when devtool is supported\n */\nexport function useDebugValue() {\n  // This is just a placeholder for react compatibility\n}\n\n/**\n * Create context hook\n */\nexport function useContext(Context: ContextType): any {\n  const { nodeInstance: component, context } = getCurrentComponentFiber();\n  const { id, defaultValue } = Context;\n\n  /**\n   * $FlowFixMe: Context will always be present in component fiber\n   * We have kept it optional for fiber as we don't want to create new object for each fiber\n   */\n  const provider = context[id];\n\n  const value = provider ? provider.props.value : defaultValue;\n\n  useLayoutEffect(() => {\n    // subscribe to provider for the context value change\n    if (provider) {\n      const { subs } = provider;\n\n      const callback = getConsumerCallback(component);\n\n      subs.push(callback);\n\n      return () => {\n        subs.splice(subs.indexOf(callback), 1);\n      };\n    }\n  }, []);\n\n  // store the context value in current component so we can check if value is changed on subscribed callback\n  component.context = value;\n\n  return value;\n}\n\n/**\n * Transition hook\n */\nexport function useTransition({ timeoutMs }: TransitionOptions): UseTransitionResult {\n  const component = getCurrentComponent();\n\n  return getHook(\n    () => {\n      /**\n       * create a transition hook\n       */\n\n      const hook: Transition = {\n        transitionId: getUniqueId(),\n        tryCount: 0,\n        isPending: false,\n        transitionTimeout: null,\n        pendingSuspense: [],\n        transitionState: TRANSITION_STATE_INITIAL,\n        clearTimeout() {\n          clearTimeout(hook.transitionTimeout);\n        },\n        updatePendingState(isPending, updateSource) {\n          hook.isPending = isPending;\n\n          // mark component to force update as isPending is not treated as state change\n          component[BRAHMOS_DATA_KEY].isDirty = true;\n\n          const reRenderCb = () => {\n            reRender(component);\n          };\n\n          if (updateSource === UPDATE_SOURCE_TRANSITION) {\n            withTransition(hook, reRenderCb);\n          } else {\n            withUpdateSource(updateSource, reRenderCb);\n          }\n        },\n        startTransition(cb: Function) {\n          const initialUpdateSource = getCurrentUpdateSource();\n          const { root } = getFiberFromComponent(component);\n\n          // reset the transitionState and pending suspense\n          hook.transitionState = TRANSITION_STATE_START;\n          hook.pendingSuspense = [];\n\n          // clear pending timeout\n          hook.clearTimeout();\n\n          // set the transitionId globally so that state updates can get the transition id\n          withTransition(hook, cb);\n\n          /**\n           * If cb does not have any setState, we don't have to unnecessary\n           * set isPending flag, transitionState and trigger reRender.\n           */\n          if (root.lastDeferredCompleteTime < root.deferredUpdateTime) {\n            hook.updatePendingState(true, initialUpdateSource);\n          }\n\n          /**\n           * Set a timeout which set's the is pending to false and then triggers a deferred update\n           */\n          hook.transitionTimeout = setTimeout(() => {\n            hook.transitionState = TRANSITION_STATE_TIMED_OUT;\n            hook.updatePendingState(false, UPDATE_SOURCE_TRANSITION);\n          }, timeoutMs);\n        },\n      };\n\n      return hook;\n    },\n    defaultShouldUpdate,\n    ({ startTransition, isPending }: Transition): UseTransitionResult => [\n      startTransition,\n      isPending,\n    ],\n  );\n}\n\n/**\n * A hook to have deferred value\n */\nexport function useDeferredValue(value: any, { timeoutMs }: DeferredValueHookOptions): any {\n  const [startTransition] = useTransition({ timeoutMs });\n  const [deferredValue, setDeferredValue] = useState(value);\n  const timeStampRef = useRef(0);\n\n  /**\n   * If there is a timestamp that denotes the timestamp form where the data\n   * went stale, timestamp 0 means the data is not stale.\n   */\n  const { current: staleTime } = timeStampRef;\n  const currentTime = timestamp();\n\n  if (value === deferredValue) {\n    // if value is not stale reset timestamp\n    timeStampRef.current = 0;\n  } else if (staleTime === 0) {\n    // if the value just got stale mark the stale time\n    timeStampRef.current = currentTime;\n  } else if (currentTime > staleTime + timeoutMs) {\n    // when ever the stale data times out update the deferred value\n    timeStampRef.current = 0;\n    setDeferredValue(value);\n  }\n\n  useEffect(() => {\n    startTransition(() => {\n      setDeferredValue(value);\n    });\n  }, [value]);\n\n  return deferredValue;\n}\n\n/**\n * Method to run all the effects of a component\n */\nexport function runEffects(fiber: Fiber) {\n  const hooks = getHooksListFromFiber(fiber);\n\n  for (let i = 0, ln = hooks.length; i < ln; i++) {\n    const hook = hooks[i];\n    if (hook.effect) {\n      hook.effect();\n    }\n  }\n}\n\n/**\n * Method to run cleanup all the effects of a component\n */\nexport function cleanEffects(fiber: Fiber, unmount: boolean): void {\n  const hooks = getHooksListFromFiber(fiber);\n\n  for (let i = 0, ln = hooks.length; i < ln; i++) {\n    const hook = hooks[i];\n    if (hook.cleanEffect && (hook.isDependenciesChanged || unmount)) {\n      hook.cleanEffect();\n    }\n\n    // clear any pending transitions on unmount\n    if (hook.clearTimeout && unmount) {\n      hook.clearTimeout();\n    }\n  }\n}\n"
  },
  {
    "path": "src/index.js",
    "content": "import * as Brahmos from './brahmos';\n\nexport * from './brahmos';\nexport default Brahmos;\n"
  },
  {
    "path": "src/memo.js",
    "content": "import { PureComponent } from './Component';\nimport { createBrahmosNode } from './circularDep';\n\nexport default function memo(Component, comparator) {\n  class MemoizedComponent extends PureComponent {\n    render() {\n      return createBrahmosNode(Component, this.props);\n    }\n  }\n\n  MemoizedComponent.displayName = `Memo(${Component.displayName || Component.name})`;\n\n  return MemoizedComponent;\n}\n"
  },
  {
    "path": "src/parseChildren.js",
    "content": "// @flow\n\nimport { TAG_ELEMENT_NODE } from './brahmosNode';\nimport { REACT_ELEMENT } from './configs';\nimport type { BrahmosNode, TemplateTagType } from './flow.types';\n\nconst TAG_REGEX = /<([^\\s\"'=<>/]+)/g;\n\nconst ATTR_REGEX = /\\s*([^\\s\"'=<>/]*)/g;\n\nconst DOUBLE_QUOTE_REGEX = /[^\"]*/g;\nconst SINGLE_QUOTE_REGEX = /[^\"]*/g;\n\nconst TAG_END_REGEX = /<\\/([^\\s\"'=<>]+)>/g;\n\nconst STRING_CHILDREN_REGEX = /[^<]*/g;\n\nconst COMMENT_REGEX = /<!--.*?-->/g;\n\nconst SELF_CLOSING_TAGS = [\n  'area',\n  'base',\n  'br',\n  'col',\n  'embed',\n  'hr',\n  'img',\n  'input',\n  'link',\n  'meta',\n  'param',\n  'source',\n  'track',\n  'wbr',\n];\n\n/**\n * Convert static string to dynamic nodes\n */\nfunction parseStatic(strings: Array<string>) {\n  const elmStack = [];\n  let insideTagOpenElem = false;\n  let currentElm;\n  const rootProps = {};\n\n  const addToProps = (props, child) => {\n    if (!props.children) {\n      // if there isn't a children, child becomes the only children\n      props.children = child;\n    } else if (Array.isArray(props.children)) {\n      props.children.push(child);\n    } else {\n      // if node has single children create a array of child\n      props.children = [props.children, child];\n    }\n  };\n\n  const pushToParent = (child) => {\n    const parentElm = elmStack[elmStack.length - 1];\n\n    // if there is any element in stack use that as parent or else add on root.\n    addToProps(parentElm ? parentElm.props : rootProps, child);\n  };\n\n  /**\n   * Method to handle the children on close of opening element\n   */\n  const pushChildren = () => {\n    insideTagOpenElem = false;\n\n    pushToParent(currentElm);\n\n    /**\n     * If the element is not self closing tag, add it in stack\n     * We don't need to do it for self closing tags because they don't have any child\n     */\n    if (!SELF_CLOSING_TAGS.includes(currentElm.type)) {\n      elmStack.push(currentElm);\n    }\n  };\n\n  /** Function to add a dynamic part information,\n   * so dynamic parts can be applied on the static tree\n   * */\n  const pushDynamicPart = (index) => {\n    const dynamicInfo = {\n      $$BrahmosDynamicPart: index,\n    };\n\n    // if we are inside tag opening element, we need to add dynamic part in attribute otherwise as child\n    if (!currentElm) {\n      addToProps(rootProps, dynamicInfo);\n    } else if (insideTagOpenElem) {\n      currentElm.props[`$$BrahmosDynamicPart${index}`] = dynamicInfo;\n    } else {\n      addToProps(currentElm.props, dynamicInfo);\n    }\n  };\n\n  strings.forEach((str, index) => {\n    const ln = str.length;\n    let tag;\n    let i = 0;\n\n    const regexSearch = (regex) => {\n      // start searching from last index\n      regex.lastIndex = i;\n      const result = regex.exec(str);\n\n      // if we find a result set the index to regex last index\n      if (result) {\n        i = regex.lastIndex;\n      }\n\n      return result;\n    };\n\n    const getAttributeValue = (quoteRegex) => {\n      /**\n       * We need to start searching from i + 2 to accommodate =' or =\"\n       */\n      quoteRegex.lastIndex = i + 2;\n      const result = quoteRegex.exec(str);\n\n      // after successful search of value we need to set the i to lastIndex + 1 to accommodate ' or \"\n      i = quoteRegex.lastIndex + 1;\n      /**\n       * $FlowFixMe: We are running on a valid transform template,\n       * so the regex will always have value on this logic\n       */\n      return result[0];\n    };\n\n    while (i < ln) {\n      if (str[i] === '<' && str[i + 1] === '/') {\n        /**\n         * when we see </ on the string, it means we are closing a tag.\n         * In such case remove the current element from stack and also\n         * set the index to end of the closing tag.\n         */\n        elmStack.pop();\n        regexSearch(TAG_END_REGEX);\n        continue;\n      } else if (str[i] === '<' && str[i + 1] === '!') {\n        /**\n         * if we see <! it means we got a comment node, ignore the whole comment node\n         * Set the index to end of the comment node\n         */\n        regexSearch(COMMENT_REGEX);\n        continue;\n      } else if (str[i] === '<') {\n        /**\n         * Or else if we just get < it means we are inside opening element.\n         * In this case get the tag name, create a current element and mark we\n         * are inside opening element, so that the next part are treated as attributes\n         * unless we encounter >\n         */\n        const result = regexSearch(TAG_REGEX);\n        // $FlowFixMe: the result will be always be there here as the JSX transformation will have valid html\n        tag = result[1];\n\n        currentElm = {\n          $$typeof: REACT_ELEMENT,\n          type: tag,\n          nodeType: TAG_ELEMENT_NODE,\n          props: {},\n        };\n\n        insideTagOpenElem = true;\n        continue;\n      } else if (str[i] === ' ' && insideTagOpenElem) {\n        // If we encounter an empty space there is chance that we may get attribute next\n        ATTR_REGEX.lastIndex = i;\n        const result = regexSearch(ATTR_REGEX);\n        let attrName;\n        let attrValue;\n\n        /**\n         * If we got an attribute, get the attribute value and\n         * associate the attribute name and value to currentElement\n         */\n        if (result) {\n          attrName = result[1];\n\n          if (str[i] !== '=') {\n            // if there is no = followed by attribute name, it means its a boolean attribute with value true\n            attrValue = true;\n          } else if (str[i + 1] === `\"`) {\n            // if attribute name is followed by =\" find the value between double quote\n            attrValue = getAttributeValue(DOUBLE_QUOTE_REGEX);\n          } else if (str[i + 1] === `'`) {\n            // if attribute name is followed by =' find the value between single quote\n            attrValue = getAttributeValue(SINGLE_QUOTE_REGEX);\n          }\n\n          if (attrName) {\n            currentElm.props[attrName] = attrValue;\n          }\n          continue;\n        }\n      } else if (str[i] === '>' && insideTagOpenElem) {\n        /**\n         * If we encounter > and are inside tag opening element,\n         * we are done with attributes, and we have start procession the children now\n         * We also add the currentElement on stack so children have information about the parent hierarchy.\n         */\n        pushChildren();\n      } else if (!insideTagOpenElem) {\n        const result = regexSearch(STRING_CHILDREN_REGEX);\n        // $FlowFixMe: regex search will always return something either empty string or some text data\n        pushToParent(result[0]);\n        continue;\n      }\n      i++;\n    }\n\n    pushDynamicPart(index);\n  });\n\n  return rootProps.children;\n}\n\nconst { hasOwnProperty } = Object.prototype;\n\n/**\n * function to merge dynamic values in static tree.\n * It creates clones and replaces placeholders by dynamic values\n */\nfunction apply(tree: any, values) {\n  if (tree == null || typeof tree !== 'object') {\n    return tree;\n  }\n\n  let newTree = new tree.constructor();\n\n  // for objects/arrays create clone\n  for (var key in tree) {\n    if (hasOwnProperty.call(tree, key)) {\n      const node = tree[key];\n      const valueIndex = node && node.$$BrahmosDynamicPart;\n      /**\n       * If we get a dynamic place holder check if its an attribute\n       * If its an attribute we want to merge the dynamic part with other attributes,\n       * or else we replace the placeholder by dynamic value\n       */\n      if (valueIndex !== undefined) {\n        const value = values[valueIndex];\n        if (key[0] === '$') {\n          newTree = Object.assign(newTree, value);\n        } else {\n          newTree[key] = value;\n        }\n      } else {\n        newTree[key] = apply(tree[key], values);\n      }\n    }\n  }\n\n  return newTree;\n}\n\nexport default function parseChildren(node: BrahmosNode): BrahmosNode {\n  // $FlowFixMe: Only template nodes are passed in this function\n  const { values, template }: { values: Array<any>, template: TemplateTagType } = node;\n  const { strings } = template;\n  if (!template.staticTree) {\n    template.staticTree = parseStatic(strings);\n  }\n\n  return apply(template.staticTree, values);\n}\n"
  },
  {
    "path": "src/processArrayFiber.js",
    "content": "// @flow\nimport { getNextChildFiber, createAndLink, markToTearDown, markPendingEffect } from './fiber';\nimport { getKey } from './brahmosNode';\nimport { EFFECT_TYPE_PLACEMENT, EFFECT_TYPE_OTHER } from './configs';\n\nimport type { Fiber } from './flow.types';\n\n// handle array nodes\nexport default function processArrayFiber(fiber: Fiber): void {\n  const { node: nodes, part } = fiber;\n  let refFiber = fiber;\n\n  // $FlowFixMe: part will always be node part on array fiber\n  const { parentNode, previousSibling, firstDOMNode } = part;\n\n  const childKeyMap = new Map();\n\n  let i = 0;\n  let childFiber = fiber;\n  /**\n   * check if getNextChildFiber(childFiber, fiber) return a child if yes then add it to map\n   */\n  while ((childFiber = getNextChildFiber(childFiber, fiber))) {\n    const key = getKey(childFiber.node, i);\n    childKeyMap.set(key, childFiber);\n    i++;\n  }\n\n  //\n  /**\n   * reset the previous children as we will link new children on fiber\n   * This will make sure if there are no new child the old child is removed\n   */\n  fiber.child = null;\n\n  nodes.forEach((node, index) => {\n    const key = getKey(node, index);\n    const currentFiber = childKeyMap.get(key);\n\n    if (currentFiber) {\n      // delete the currentFiber from map, so we can use map to remove pending elements\n      childKeyMap.delete(key);\n    }\n\n    const previousFiber = refFiber;\n\n    // create fiber if required and link it\n    refFiber = createAndLink(\n      node,\n      // $FlowFixMe: property a is added for some weird chrome de-optimizaion issue\n      {\n        parentNode,\n        previousSibling,\n        /**\n         * Surprisingly an undefined dummy property increases V8 performance.\n         * We remove nextSibling which when being undefined was running faster\n         * Looks like inlining and deopt issue. But still have to figure out why\n         * undefined property changed anything\n         * Inlining this whole body inside processFiber was not giving issue without\n         * undefined property\n         */\n        a: undefined,\n        firstDOMNode,\n        isArrayNode: true,\n        nodeIndex: index,\n        parentArrayPart: part.isArrayNode ? part : null,\n      },\n      currentFiber,\n      previousFiber,\n      fiber,\n    );\n\n    // reset the sibling fiber on the ref fiber. This will be set on next iteration of loop.\n    refFiber.sibling = null;\n\n    /**\n     * if current fiber nodeIndex is different than new index,or if it is a new fiber without any alternate\n     * mark fiber and its previous fiber to have uncommitted placement effect\n     */\n    // $FlowFixMe: we only have to check for array part here\n    if (currentFiber && currentFiber.part.nodeIndex !== index) {\n      markPendingEffect(refFiber, EFFECT_TYPE_PLACEMENT);\n\n      // mark the previous fiber as well having the placement effect, as it makes it easier to\n      // rearrange the dom nodes\n      if (index !== 0) markPendingEffect(previousFiber, EFFECT_TYPE_PLACEMENT);\n    }\n  });\n\n  // mark non used node to tear down\n  childKeyMap.forEach((fiber) => {\n    markToTearDown(fiber);\n  });\n\n  // mark the array fiber for handling effects\n  markPendingEffect(fiber, EFFECT_TYPE_OTHER);\n}\n"
  },
  {
    "path": "src/processComponentFiber.js",
    "content": "// @flow\nimport {\n  cloneChildrenFibers,\n  createAndLink,\n  resetToCommittedChild,\n  markPendingEffect,\n  setCurrentComponentFiber,\n} from './fiber';\n\nimport functionalComponentInstance from './functionalComponentInstance';\nimport { CLASS_COMPONENT_NODE, isComponentNode } from './brahmosNode';\nimport { getClosestSuspenseFiber, resetSiblingFibers } from './circularDep';\n\nimport { callLifeCycle, getComponentName, BrahmosRootComponent, afterCurrentStack } from './utils';\nimport { getPendingUpdates, withUpdateSource } from './updateUtils';\n\nimport shallowEqual from './helpers/shallowEqual';\nimport { BRAHMOS_DATA_KEY, EFFECT_TYPE_OTHER, UPDATE_TYPE_DEFERRED } from './configs';\nimport { Component } from './Component';\n\nimport type {\n  Fiber,\n  ErrorInfo,\n  AllContext,\n  ClassComponentBrahmosData,\n  ComponentBrahmosData,\n  ComponentClassInstance,\n  ClassComponentUpdate,\n} from './flow.types';\n\nexport function getErrorBoundaryFiber(fiber: Fiber): ?Fiber {\n  const { root } = fiber;\n\n  while (\n    (fiber = fiber.parent) &&\n    !(\n      fiber.nodeInstance instanceof Component &&\n      (fiber.nodeInstance.componentDidCatch || fiber.node.type.getDerivedStateFromError)\n    )\n  ) {\n    if (fiber === root) return null;\n  }\n\n  return fiber;\n}\n\nexport function getErrorInfo(fiber: Fiber): ErrorInfo {\n  let error = '';\n  while (fiber) {\n    const { node } = fiber;\n    if (node && isComponentNode(node) && node.type !== BrahmosRootComponent) {\n      error += `    at ${getComponentName(node.type)} \\n`;\n    }\n    fiber = fiber.parent;\n  }\n\n  return {\n    componentStack: error,\n  };\n}\n\nfunction getCurrentContext(fiber: Fiber): AllContext {\n  const {\n    node: { type: Component },\n    nodeInstance,\n    parent,\n  } = fiber;\n\n  // if component has createContext index, we treat it as provider\n  const { __ccId } = Component;\n  const context = parent.context || {};\n\n  // if component is not a provider return the same context\n  if (!__ccId) return context;\n\n  // for new provider instance create a new context by extending the parent context\n  const newContext = Object.create(context);\n\n  // store the nodeInstance\n  newContext[__ccId] = nodeInstance;\n\n  return newContext;\n}\n\nfunction getUpdatedState(prevState, updates) {\n  return updates.reduce((combinedState, { state }) => {\n    if (typeof state === 'function') state = state(combinedState);\n    return { ...combinedState, ...state };\n  }, prevState);\n}\n\n// method to reset work loop to a fiber of given component\nfunction resetLoopToComponentsFiber(fiber) {\n  const { root, nodeInstance } = fiber;\n\n  // mark component as dirty, so it can be rendered again\n  nodeInstance[BRAHMOS_DATA_KEY].isDirty = true;\n\n  // set the alternate fiber as retry fiber, as\n  root.retryFiber = fiber;\n}\n\nexport default function processComponentFiber(fiber: Fiber): void {\n  const { node, part, root, childFiberError } = fiber;\n  const { type: Component, nodeType, props = {} } = node;\n  const { currentTransition } = root;\n\n  const isDeferredUpdate = root.updateType === UPDATE_TYPE_DEFERRED;\n\n  let shouldUpdate = true;\n  let usedMemoizedValues = false;\n  const isClassComponent = nodeType === CLASS_COMPONENT_NODE;\n\n  /**\n   * Reset the fiber children to a committed child\n   */\n  resetToCommittedChild(fiber);\n\n  /** If Component instance is not present on node create a new instance */\n  let { nodeInstance } = fiber;\n  let isFirstRender = false;\n  if (!nodeInstance) {\n    // create an instance of the component\n    nodeInstance = isClassComponent ? new Component(props) : functionalComponentInstance(Component);\n\n    // keep the reference of instance to the node.\n    fiber.nodeInstance = nodeInstance;\n\n    isFirstRender = true;\n  }\n\n  //\n  const brahmosData: ComponentBrahmosData = nodeInstance[BRAHMOS_DATA_KEY];\n\n  // get current context\n  const context = getCurrentContext(fiber);\n\n  // store context in fiber\n  fiber.context = context;\n\n  /**\n   * If it is a class component,\n   * associate state, props to component instance\n   * and call all the life cycle method which comes before rendering.\n   */\n  if (isClassComponent) {\n    const componentClassInstance = ((nodeInstance: any): ComponentClassInstance);\n    const classBrahmosData = ((brahmosData: any): ClassComponentBrahmosData);\n    const { committedValues, memoizedValues } = classBrahmosData;\n\n    // if it is first render we should store the initial state on committedValues\n    if (isFirstRender) committedValues.state = componentClassInstance.state;\n\n    let { props: prevProps, state: prevState } = committedValues;\n\n    if (\n      memoizedValues &&\n      currentTransition &&\n      currentTransition.transitionId === memoizedValues.transitionId\n    ) {\n      ({ props: prevProps, state: prevState } = memoizedValues);\n      usedMemoizedValues = true;\n    }\n\n    //\n    /**\n     * reset the component instance values to prevProps and prevState,\n     * The state and prop value might have been effected by deferred rendering\n     * For sync render it should point to previous committed value, and for\n     * deferred render it should point to memoized values\n     */\n    componentClassInstance.props = prevProps;\n    componentClassInstance.state = prevState;\n\n    const { shouldComponentUpdate } = componentClassInstance;\n\n    let state = prevState;\n\n    // apply the pending updates in state if\n    const pendingUpdates = ((getPendingUpdates(fiber): any): Array<ClassComponentUpdate>);\n    if (pendingUpdates.length) state = getUpdatedState(prevState, pendingUpdates);\n\n    const checkShouldUpdate = !isFirstRender && root.forcedUpdateWith !== nodeInstance;\n\n    // call getDerivedStateFromProps lifecycle with the unCommitted state and apply the derivedState on state\n    const derivedState = callLifeCycle(Component, 'getDerivedStateFromProps', [props, state]);\n\n    const derivedErrorState = childFiberError\n      ? callLifeCycle(Component, 'getDerivedStateFromError', [childFiberError.error])\n      : undefined;\n\n    if (derivedState || derivedErrorState) {\n      // $FlowFixMe\n      state = { ...state, ...derivedState, ...derivedErrorState };\n    }\n    /**\n     * check if component is instance of PureComponent, if yes then,\n     * do shallow check for props and states\n     */\n\n    if (componentClassInstance.isPureReactComponent && checkShouldUpdate) {\n      shouldUpdate = !shallowEqual(state, prevState) || !shallowEqual(props, prevProps);\n    }\n\n    /**\n     * check if component should update or not. If PureComponent shallow check has already\n     * marked component to not update then we don't have to call shouldComponentUpdate\n     * Also we shouldn't call shouldComponentUpdate on first render\n     */\n    if (shouldComponentUpdate && shouldUpdate && checkShouldUpdate) {\n      shouldUpdate = shouldComponentUpdate.call(componentClassInstance, props, state);\n    }\n\n    /**\n     * If it is a context consumer add provider on the props\n     */\n    const { contextType } = Component;\n    if (contextType) {\n      const { id, defaultValue } = contextType;\n      const provider = context[id];\n      const contextValue = provider ? provider.props.value : defaultValue;\n\n      // if it is a first render subscribe component for provider value change\n      if (provider && isFirstRender) {\n        provider.sub(componentClassInstance);\n      }\n      componentClassInstance.context = contextValue;\n    }\n\n    // set the new state, props, context and reset uncommitted state\n    componentClassInstance.state = state;\n\n    // $FlowFixMe: We are just setting the existing prop, so we can ignore the error\n    componentClassInstance.props = props;\n\n    // call setState callbacks after its set to component instance\n    pendingUpdates.forEach(({ callback }) => {\n      if (callback) {\n        // call the callback with same update source as callbacks can have setState, and we want to reduce repaints\n        const { updateSource } = root;\n        afterCurrentStack(() => {\n          withUpdateSource(updateSource, () => callback(state));\n        });\n      }\n    });\n\n    // store the state and props on memoized value as well\n    if (currentTransition) {\n      classBrahmosData.memoizedValues = {\n        state,\n        props,\n        transitionId: currentTransition.transitionId,\n      };\n    }\n  }\n\n  // render the nodes\n  if (shouldUpdate) {\n    // set the current component fiber we are processing\n    setCurrentComponentFiber(fiber);\n    // increment the render count. This is to track how many times a component is rendered in a render cycle\n    brahmosData.renderCount += 1;\n\n    // if the component is error boundary with error and it does not have getDerivedStateFromError, render null\n    const hasNonHandledError = childFiberError && !Component.getDerivedStateFromError;\n\n    try {\n      if (hasNonHandledError) {\n        brahmosData.nodes = null;\n      } else {\n        // else get the new elements\n        nodeInstance.__render(props);\n      }\n    } catch (error) {\n      const errorBoundary = getErrorBoundaryFiber(fiber);\n      // TODO: handle error boundaries\n\n      // if error is a suspender, handle the suspender in suspense component\n      // TODO: this is very basic case for suspender, add better code to check if it is a suspender\n      if (typeof error.then === 'function') {\n        const suspenseFiber = getClosestSuspenseFiber(fiber);\n\n        /**\n         * if there is no suspense in parent hierarchy throw error that suspender can't be\n         * used outside of suspense\n         * TODO: think for better message\n         */\n        if (!suspenseFiber) {\n          throw new Error(`Rendering which got suspended can't be used outside of suspense.`);\n        }\n\n        suspenseFiber.nodeInstance.handleSuspender(error, suspenseFiber);\n\n        // reset the work loop to suspense fiber or suspense list fiber, if it has suspense list as parent\n        const resetFiber = resetSiblingFibers(suspenseFiber);\n        resetLoopToComponentsFiber(resetFiber);\n        /**\n         * else if there is any error boundary handle the error in error boundary\n         * It should not handle error if its already been handled once\n         */\n      } else if (errorBoundary && !errorBoundary.childFiberError) {\n        const errorInfo = getErrorInfo(fiber);\n        // log the error and retry rendering\n        console.error(error);\n\n        const errorDetail = `The above error occurred in the <${getComponentName(\n          node.type,\n        )}> component: \\n${errorInfo.componentStack}`;\n        console.error(errorDetail);\n        errorBoundary.childFiberError = { error, errorInfo };\n\n        // reset the work loop to errorBoundary fiber\n        resetLoopToComponentsFiber(errorBoundary);\n\n        // else throw error\n      } else {\n        throw error;\n      }\n\n      return;\n    } finally {\n      // reset the component fiber\n      setCurrentComponentFiber(null);\n\n      // if it class component reset the state and prop to committed value\n      const brahmosData = nodeInstance[BRAHMOS_DATA_KEY];\n      if (isClassComponent && isDeferredUpdate) {\n        const { committedValues } = ((brahmosData: any): ClassComponentBrahmosData);\n        Object.assign(((nodeInstance: any): ComponentClassInstance), committedValues);\n      }\n    }\n  }\n\n  /**\n   * If the new rendered node is different from the previously render node\n   * create new child, link it and mark as pending effect\n   *\n   * shouldUpdate can be false in case we are using memoized value,\n   * so in such case as well try to create new child.\n   */\n  if (usedMemoizedValues || shouldUpdate) {\n    const { child } = fiber;\n    const { nodes: newNodes } = brahmosData;\n\n    if (!child || child.node !== newNodes) {\n      // component will always return a single node so we can pass the previous child as current fiber\n      createAndLink(newNodes, part, child, fiber, fiber);\n\n      // mark that the fiber has uncommitted effects\n      markPendingEffect(fiber, EFFECT_TYPE_OTHER);\n    } else if (!usedMemoizedValues) {\n      /**\n       * if we don't need to update the child fibers, we should clone the child fiber from current tree\n       * But if we have memoized props and states and no update is required, it means we already are\n       * pointing to correct child fibers, in which case we shouldn't clone the child\n       */\n      cloneChildrenFibers(fiber);\n    }\n  } else {\n    cloneChildrenFibers(fiber);\n  }\n}\n"
  },
  {
    "path": "src/processTagFiber.js",
    "content": "// @flow\nimport { TAG_ELEMENT_NODE, ATTRIBUTE_NODE } from './brahmosNode';\nimport { createAndLink, cloneChildrenFibers, markPendingEffect } from './fiber';\nimport getTagNode from './TagNode';\nimport TemplateNode from './TemplateNode';\nimport { getEffectiveAttrName, loopEntries } from './utils';\nimport { RESERVED_ATTRIBUTES, EFFECT_TYPE_OTHER } from './configs';\n\nimport type { Fiber, AttributePart } from './flow.types';\n\nfunction isAttrOverridden(tagAttrs, attrName, attrIndex) {\n  const lastIndex = tagAttrs.lastIndexOf(attrName);\n  // if attrIndex is before the last attribute with same name it means its overridden\n  return attrIndex <= lastIndex;\n}\n\nfunction attributeNode(props, ref) {\n  return {\n    nodeType: ATTRIBUTE_NODE,\n    props,\n    ref,\n  };\n}\n\nfunction partsToFiber(parts, values, parentFiber) {\n  let refFiber = parentFiber;\n  let oldChildFiber = parentFiber.child;\n\n  for (let i = 0, ln = parts.length; i < ln; i++) {\n    let part = parts[i];\n    const value = values[i];\n\n    let node;\n\n    if (part.isAttribute) {\n      const { domNode } = part;\n\n      // mix all the consecutive attributes if they belong to same domNode\n      const dynamicAttributes = {};\n      let refValue;\n      while (part && domNode === part.domNode) {\n        loopEntries(values[i], (attrName, attrValue) => {\n          const attributePart = ((part: any): AttributePart);\n          const effectiveAttrName = getEffectiveAttrName(attrName);\n          const isOverridden = isAttrOverridden(\n            attributePart.tagAttrs,\n            effectiveAttrName,\n            attributePart.attrIndex,\n          );\n          if (!isOverridden && !RESERVED_ATTRIBUTES[attrName]) {\n            dynamicAttributes[attrName] = attrValue;\n          } else if (attrName === 'ref') {\n            // Note only functional refs are supported\n            refValue = attrValue;\n          }\n        });\n        part = parts[++i];\n      }\n\n      // reduce the counter to correct the loop index. As it is extra incremented in while loop\n      i--;\n      part = parts[i];\n\n      node = attributeNode(dynamicAttributes, refValue);\n\n      // $FlowFixMe: Not sure why flow is not able to infer this\n    } else if (part.isNode) {\n      node = value;\n    }\n\n    /**\n     * create a fiber from node and link it to reference fiber\n     */\n    // get the current old fiber\n    refFiber = createAndLink(node, part, oldChildFiber, refFiber, parentFiber);\n\n    // set the next old child to oldChildFiber\n    oldChildFiber = oldChildFiber && oldChildFiber.sibling;\n  }\n}\n\n/**\n * Update tagged template node\n */\nexport default function processTagFiber(fiber: Fiber): void {\n  const { node } = fiber;\n  const {\n    part,\n    alternate,\n    parent: { context },\n  } = fiber;\n\n  const oldNode = alternate && alternate.node;\n  const { values, nodeType } = node;\n\n  const isTagElement = nodeType === TAG_ELEMENT_NODE;\n\n  // if the node is an svg element, or fiber is already mentioned as svgPart set the isSvgPart true\n  const isSvgPart = fiber.isSvgPart || node.type === 'svg';\n\n  // store isSvgPart info back to fiber, this will be forwarded to children\n  fiber.isSvgPart = isSvgPart;\n\n  let { nodeInstance } = fiber;\n\n  if (!nodeInstance) {\n    nodeInstance = isTagElement\n      ? getTagNode(node, isSvgPart)\n      : new TemplateNode(node.template, isSvgPart);\n\n    // add nodeInstance to node so we can access it on next updates\n    fiber.nodeInstance = nodeInstance;\n  }\n\n  /**\n   * if any of nodeInstance part does not have proper parent node and its not first render\n   * patch the part information using the current node's part\n   * This can happen if the parent node is fragment, or it is the first or last item\n   */\n  if (!isTagElement) {\n    // $FlowFixMe: We only patchParts in TemplateNode\n    nodeInstance.patchParts(part);\n  }\n\n  /**\n   * Associate parts to fiber.\n   * No need to perform this if node and oldNode are same\n   * This will only happen when we are just doing position change\n   * In which case just clone the children fibers\n   * CHECK: Will there be ever any case where node is same as oldNode\n   * and process is called.\n   */\n  if (node !== oldNode) {\n    if (isTagElement) {\n      createAndLink(node.props.children, nodeInstance.parts[0], fiber.child, fiber, fiber);\n    } else {\n      partsToFiber(nodeInstance.parts, values, fiber);\n    }\n  } else {\n    cloneChildrenFibers(fiber);\n  }\n\n  // mark that the fiber has uncommitted effects\n  markPendingEffect(fiber, EFFECT_TYPE_OTHER);\n\n  // attach context on fiber\n  fiber.context = context;\n}\n"
  },
  {
    "path": "src/processTextFiber.js",
    "content": "// @flow\n\nimport { markPendingEffect } from './fiber';\nimport { EFFECT_TYPE_OTHER } from './configs';\n\nimport type { Fiber } from './flow.types';\n\nexport function processTextFiber(fiber: Fiber): void {\n  const { node, alternate } = fiber;\n  const oldNode = alternate && alternate.node;\n\n  // if text is different then only we should add it as an effect\n  if (node !== oldNode) {\n    // mark that the fiber has uncommitted effects\n    markPendingEffect(fiber, EFFECT_TYPE_OTHER);\n  }\n}\n"
  },
  {
    "path": "src/reRender.js",
    "content": "// @flow\nimport {\n  UPDATE_SOURCE_IMMEDIATE_ACTION,\n  UPDATE_SOURCE_TRANSITION,\n  UPDATE_TYPE_SYNC,\n} from './configs';\nimport { getCurrentUpdateSource, getCurrentTransition, getUpdateType } from './updateUtils';\nimport { PREDEFINED_TRANSITION_DEFERRED } from './transitionUtils';\nimport { setUpdateTime, getFiberFromComponent } from './fiber';\nimport { doSyncProcessing, doDeferredProcessing } from './workLoop';\nimport { afterCurrentStack } from './utils';\n\nimport type { AnyComponentInstance } from './flow.types';\n\n/**\n * Method to rerender a given component\n * In case of reRender, start from the root,\n * clone the current fiber to wip, and use the wip which is pointing\n * to children of current tree.\n */\nexport default function reRender(component: AnyComponentInstance): void {\n  const fiber = getFiberFromComponent(component);\n\n  const { root } = fiber;\n  const { pendingTransitions, batchUpdates } = root;\n\n  const currentUpdateSource = getCurrentUpdateSource();\n  const currentTransition = getCurrentTransition();\n\n  const updateType = getUpdateType();\n\n  // set updateTime on fiber parent hierarchy based on updateType\n  setUpdateTime(fiber, updateType);\n\n  /**\n   * if the update source is transition, and the transition is not already present in pending list\n   * add the transition in pending transition\n   */\n  if (\n    currentUpdateSource === UPDATE_SOURCE_TRANSITION &&\n    !pendingTransitions.includes(currentTransition)\n  ) {\n    /**\n     * If it is predefined deferred transition, we need to add current transition\n     * as first item as PREDEFINED_TRANSITION_DEFERRED has more priority\n     * or else add it in last of pendingTransitions\n     */\n\n    if (currentTransition === PREDEFINED_TRANSITION_DEFERRED) {\n      pendingTransitions.unshift(currentTransition);\n    } else {\n      pendingTransitions.push(currentTransition);\n    }\n  }\n\n  /**\n   * if there is already a batch update happening, increment the reRender count and\n   * early return as all the state change will be covered with that batch update\n   */\n  if (batchUpdates[currentUpdateSource]) {\n    batchUpdates[currentUpdateSource] += 1;\n    return;\n  }\n\n  batchUpdates[currentUpdateSource] = 1;\n\n  afterCurrentStack(() => {\n    const reRenderCount = batchUpdates[currentUpdateSource];\n    // reset batch update so it can start taking new updates\n    batchUpdates[currentUpdateSource] = 0;\n\n    const isDeferredUpdate = currentUpdateSource === UPDATE_SOURCE_TRANSITION;\n\n    /**\n     * Don't try to do deferred rendering if a sync render is pending,\n     * as deferred rendering happens after sync render\n     */\n    if (isDeferredUpdate && root.lastCompleteTime < root.updateTime) return;\n\n    root.updateSource = currentUpdateSource;\n\n    if (isDeferredUpdate) {\n      doDeferredProcessing(root);\n    } else {\n      /**\n       * if the update source is event and we don't have any ongoing sync update\n       * which we can figure out based on last updateType and if there is any cancelSchedule\n       * Start the processing from the fiber which cause the update.\n       *\n       * Also, when reRenderCount is more than one it means there are multiple update pending\n       */\n      const hasOngoingSyncUpdates = root.updateType === UPDATE_TYPE_SYNC && root.cancelSchedule;\n      const startFromFiber =\n        currentUpdateSource === UPDATE_SOURCE_IMMEDIATE_ACTION &&\n        !hasOngoingSyncUpdates &&\n        reRenderCount === 1;\n\n      doSyncProcessing(startFromFiber ? fiber : root.current);\n    }\n  });\n}\n"
  },
  {
    "path": "src/reactEvents.js",
    "content": "import { getNodeName } from './utils';\nimport { syncUpdates } from './updateUtils';\nimport { RENAMED_EVENTS, ONCHANGE_INPUT_TYPES } from './configs';\n\nexport function getEffectiveEventName(eventName, node) {\n  const { type } = node;\n  const nodeName = getNodeName(node);\n\n  if (RENAMED_EVENTS[eventName]) return RENAMED_EVENTS[eventName];\n\n  /**\n   * Logic Source:  (https://github.com/preactjs/preact/blob/master/src/constants.js)\n   */\n  return /^change(textarea|input)/i.test(eventName + nodeName) && !ONCHANGE_INPUT_TYPES.test(type) ? 'input': eventName;\n}\n\nexport function getInputStateType(node) {\n  const { type } = node;\n  const nodeName = getNodeName(node);\n  if (nodeName === 'input' && (type === 'radio' || type === 'checkbox')) {\n    return 'checked';\n  } else if (nodeName === 'input' || nodeName === 'select' || nodeName === 'textarea') {\n    return 'value';\n  }\n}\n\nexport function handleControlledReset(node) {\n  const inputStateType = getInputStateType(node);\n\n  // if it is not an controlled input type return\n  if (!inputStateType) return;\n\n  const propValue = node[`${inputStateType}Prop`];\n  const value = node[inputStateType];\n\n  if (propValue !== undefined && propValue !== value) {\n    node[inputStateType] = propValue;\n  }\n}\n\nexport function handleInputProperty(inputStateType, node, attrName, attrValue) {\n  /**\n   * if we are passing checked prop / value prop, set the value and also store the prop value\n   * to the node so we can check if the element is controlled or not, and in controlled element\n   * reset the property to the property passed as stored prop\n   *\n   * For other properties just set it\n   * */\n  if (inputStateType === 'checked') {\n    if (attrName === 'checked') {\n      node.checked = attrValue;\n      node.checkedProp = attrValue;\n    } else if (attrName === 'defaultChecked' && node.checkedProp === undefined) {\n      node.checked = attrValue;\n    } else {\n      node[attrName] = attrValue;\n    }\n  } else if (inputStateType === 'value') {\n    if (attrName === 'value') {\n      node.value = attrValue;\n      node.valueProp = attrValue;\n    } else if (attrName === 'defaultValue' && node.valueProp === undefined) {\n      node.value = attrValue;\n    } else {\n      node[attrName] = attrValue;\n    }\n  }\n}\n\nexport function getPatchedEventHandler(node, attrName, handler) {\n  const eventHandlers = node.__brahmosData.events;\n  let eventHandlerObj = eventHandlers[attrName];\n\n  /**\n   * if eventHandlerObj is already defined update it with new handler\n   * or else create a new object\n   */\n  //\n  if (eventHandlerObj) {\n    eventHandlerObj.handler = handler;\n    return eventHandlerObj.patched;\n  } else {\n    eventHandlerObj = eventHandlers[attrName] = {\n      handler,\n      patched: null,\n    };\n  }\n\n  eventHandlerObj.patched = function(event) {\n    // if the handler is defined call the handler\n    if (eventHandlerObj.handler) {\n      syncUpdates(() => {\n        eventHandlerObj.handler.call(this, event);\n      });\n    }\n  };\n\n  return eventHandlerObj.patched;\n}\n"
  },
  {
    "path": "src/refs.js",
    "content": "// @flow\nimport { getNormalizedProps } from './utils';\nimport type { ObjectLiteral, Ref, ObjectRef, FunctionalComponent } from './flow.types';\nimport { REACT_FORWARD_REF } from './configs';\n\nexport function forwardRef(Component: FunctionalComponent): FunctionalComponent {\n  function ForwardRefComponent(props: ObjectLiteral) {\n    return Component(getNormalizedProps(props, false), props.ref);\n  }\n\n  ForwardRefComponent.__isForwardRef = true;\n  ForwardRefComponent.$$typeof = REACT_FORWARD_REF;\n\n  return ForwardRefComponent;\n}\n\nexport function createRef(): ObjectRef {\n  return { current: null };\n}\n\n/** function to attach ref to the passed ref prop */\nexport function setRef(ref: Ref, instance: any): void {\n  /**\n   * Note: we only support ref as callback and createRef syntax.\n   * Brahmos does not support string ref as they are deprecated\n   */\n  if (typeof ref === 'function') {\n    ref(instance);\n  } else if (typeof ref === 'object') {\n    ref.current = instance;\n  }\n}\n"
  },
  {
    "path": "src/render.js",
    "content": "// @flow\nimport { createBrahmosNode } from './circularDep';\nimport { CLASS_COMPONENT_NODE } from './brahmosNode';\nimport { BrahmosRootComponent } from './utils';\nimport { createFiber, createHostFiber, setUpdateTime } from './fiber';\nimport { doSyncProcessing } from './workLoop';\nimport { syncUpdates, getCurrentUpdateSource } from './updateUtils';\n\nimport { UPDATE_TYPE_SYNC } from './configs';\n\nimport type { ExtendedElement } from './flow.types';\n\n/**\n * Method to render a node\n */\nexport default function render(node: any, target: ExtendedElement) {\n  let { __rootFiber: rootFiber } = target;\n\n  let fiber;\n\n  if (!rootFiber) {\n    const rootNode = createBrahmosNode(BrahmosRootComponent, { children: node });\n\n    const part = {\n      parentNode: target,\n      previousSibling: null,\n      isNode: true,\n    };\n\n    rootFiber = createHostFiber(target);\n\n    fiber = createFiber(rootFiber, rootNode, part);\n\n    // make the rootFiber parent of fiber\n    // $FlowFixMe: rootFiber can only be parent in case of rootNode\n    fiber.parent = rootFiber;\n\n    // make the root fiber the wip fiber of rootFiber\n    rootFiber.current = fiber;\n\n    // add root fiber on target\n    target.__rootFiber = rootFiber;\n  } else {\n    /**\n     * Update the children in BrahmosRootComponent node and also reset the processedTime\n     * so it can processed again.\n     */\n    fiber = rootFiber.current;\n    fiber.node.props.children = node;\n    fiber.processedTime = 0;\n    setUpdateTime(fiber, UPDATE_TYPE_SYNC);\n  }\n\n  /**\n   * do not schedule in render\n   * NOTE: This will also affect sync setStates inside componentDidMount, or useEffects.\n   * This is expected to prevent multiple repaints\n   */\n  syncUpdates(() => {\n    rootFiber.updateSource = getCurrentUpdateSource();\n    doSyncProcessing(fiber);\n  });\n\n  // if it is a class component return the component instance, or else return null\n  // $FlowFixMe: As the fiber is a wrapper component, it will always have child\n  return node && node.nodeType === CLASS_COMPONENT_NODE ? fiber.child.nodeInstance : null;\n}\n"
  },
  {
    "path": "src/scheduler.js",
    "content": "// @flow\nimport { PREDEFINED_TRANSITION_DEFERRED } from './transitionUtils';\n\nimport type { HostFiber } from './flow.types';\ntype TimeRemaining = () => boolean;\n\nconst RENDER_SLOT = 5;\nconst MAX_RENDER_SLOT = 30; // We can allow to drop frame rate to minimum 30 fps\nconst FRAME_DURATION_DEFAULT = 16; // Default we try to keep it under 60 fps\nconst DEFERRED_TRANSITION_MAX_RETRY = 300; // close to 5000ms -> 16 * 300 with some buffer\nconst OTHER_TRANSITION_MAX_RETRY = 600; // close to 10000ms -> 16 * 600 with some buffer\n\nlet firstFrameTime;\nrequestAnimationFrame((time) => {\n  firstFrameTime = time;\n});\n\nconst getTime = () => performance.now();\n\nconst timedOutRemaining: TimeRemaining = () => true;\n\nconst frameRemainingTime = (currentTime, frameDuration) => {\n  frameDuration = frameDuration || FRAME_DURATION_DEFAULT;\n\n  return frameDuration - ((currentTime - firstFrameTime) % frameDuration);\n};\n\n/**\n * create a message channel instead of using setTimeouts\n * setTimeouts are clamped to ~4ms which make scheduling slow\n */\nlet port, channelCallbacks;\nif (typeof MessageChannel !== 'undefined') {\n  channelCallbacks = [];\n  const channel = new MessageChannel();\n  channel.port1.onmessage = function() {\n    channelCallbacks.forEach((handle) => handle());\n  };\n  port = channel.port2;\n}\n\nfunction schedule(cb) {\n  /**\n   * If Message channel is not available or frame is about to end use combination of timeout and requestIdleCallback,\n   */\n  if (!port || frameRemainingTime(getTime()) < 1) {\n    const scheduleCb = () => {\n      cancelSchedule();\n      cb();\n    };\n\n    /**\n     * Start both timer and request idle callback to schedule processing in next frame\n     * and which ever is called first cancel the other one\n     */\n    const timeoutId = setTimeout(scheduleCb, 1);\n    const ricId = requestIdleCallback(scheduleCb);\n\n    const cancelSchedule = () => {\n      clearTimeout(timeoutId);\n      cancelIdleCallback(ricId);\n    };\n\n    return cancelSchedule;\n  }\n\n  // If we have enough time use message channel as message channels are called more often\n  channelCallbacks.push(cb);\n  port.postMessage(null);\n\n  return () => {\n    const index = channelCallbacks.indexOf(cb);\n    if (index !== -1) channelCallbacks.splice(index, 1);\n  };\n}\n\nexport default function scheduleTask(\n  root: HostFiber,\n  shouldSchedule: boolean,\n  cb: (timeRemaining: TimeRemaining) => void,\n) {\n  const { cancelSchedule } = root;\n\n  // cancel any existing scheduled task on root\n  if (cancelSchedule) {\n    cancelSchedule();\n    root.cancelSchedule = null;\n  }\n\n  if (shouldSchedule) {\n    root.cancelSchedule = schedule(() => {\n      const { currentTransition } = root;\n      const tryCount = currentTransition ? currentTransition.tryCount : 0;\n\n      /**\n       * we get to limit retries in deferred update, otherwise deferred updated\n       * can starve by a sync update. So eventually deferred update has to be flushed.\n       */\n      const maxAllowedRetry =\n        currentTransition === PREDEFINED_TRANSITION_DEFERRED\n          ? DEFERRED_TRANSITION_MAX_RETRY\n          : OTHER_TRANSITION_MAX_RETRY;\n\n      const slotStartTime = getTime();\n\n      /**\n       * We keep incrementing slot time based on tryCount max to MAX_RENDER_SLOT.\n       * This may reduce the frame rate, but allows the deferred update to execute.\n       * We are clamping the minimum frame rate to 30fps, so increasing frame time is\n       * fine.\n       */\n      const slotTime = Math.min(MAX_RENDER_SLOT, RENDER_SLOT + tryCount);\n\n      /**\n       * For a render slot time we round frameDuration to nearest frame size.\n       */\n      const frameDuration = Math.floor(slotTime / FRAME_DURATION_DEFAULT) * FRAME_DURATION_DEFAULT;\n\n      const timeRemaining = () => {\n        const currentTime = getTime();\n\n        /**\n         * Make sure we don't eat up a frame, so clamping it to remaining frame time is required.\n         * Its not perfect as its heuristic based on initial frame time, but does the job when\n         * combined with requestIdleCallback\n         */\n        const maxSlotTime = frameRemainingTime(currentTime, frameDuration);\n        const slotEndTime = slotStartTime + Math.min(RENDER_SLOT, maxSlotTime);\n        return currentTime < slotEndTime;\n      };\n\n      // If we cross max allowed retry we need to flush render synchronously\n      cb(tryCount > maxAllowedRetry ? timedOutRemaining : timeRemaining);\n    });\n\n    return;\n  }\n\n  cb(timedOutRemaining);\n}\n"
  },
  {
    "path": "src/tags.js",
    "content": "// @flow\nimport TemplateTag from './TemplateTag';\nimport { brahmosNode, TAG_NODE } from './brahmosNode';\nimport type { TemplateTagType, BrahmosNode } from './flow.types';\n\ntype TagReturn = (partMetaCode: string) => BrahmosNode;\n\nconst templateTagCache = new WeakMap();\n\nexport function createTagNode(template: TemplateTagType, values: Array<any>): BrahmosNode {\n  const node = brahmosNode(null, values, undefined);\n\n  node.nodeType = TAG_NODE;\n  node.template = template;\n\n  return node;\n}\n\nexport function html(strings: Array<string>, ...values: Array<any>): TagReturn {\n  return (partMetaCode) => {\n    let template = templateTagCache.get(strings);\n\n    if (!template) {\n      template = new TemplateTag(strings, partMetaCode);\n      templateTagCache.set(strings, template);\n    }\n\n    return createTagNode(template, values);\n  };\n}\n"
  },
  {
    "path": "src/tearDown.js",
    "content": "// @flow\nimport { callLifeCycle, remove, getNextSibling, isMounted } from './utils';\n\nimport {\n  isComponentNode,\n  isRenderableNode,\n  isTagNode,\n  CLASS_COMPONENT_NODE,\n  isPrimitiveNode,\n} from './brahmosNode';\n\nimport { setRef } from './refs';\n\nimport { cleanEffects } from './hooks';\n\nimport type { HostFiber } from './flow.types';\n\nfunction tearDownChild(child, part, _isTagNode, removeDOM) {\n  /**\n   * if we got a tag to remove for child nodes we don't need to remove those\n   * nodes in child fibers as it will be remove by current fiber\n   * Note, some child node can be outside of the dom boundary a TagNode is covering\n   * So we should check if the parent node of the child is not same as the tagNode.\n   */\n  let _removeDOM = child.part.parentNode !== part.parentNode && _isTagNode ? false : removeDOM;\n\n  // if a child is portal then we should keep the remove dom to true\n  const { node } = child;\n  if (node && node.portalContainer) {\n    _removeDOM = true;\n  }\n\n  tearDownFiber(child, _removeDOM);\n}\n\nfunction tearDownFiber(fiber, removeDOM) {\n  const { node, part, nodeInstance } = fiber;\n\n  /**\n   * mark the fiber shouldTearDown to false to avoid extra teardown in case\n   * same fiber is pushed twice, this can happen when we looped in between the\n   * render cycle\n   */\n  fiber.shouldTearDown = false;\n\n  // bail out shouldTearDown is false or if node is non-renderable node\n  if (!isRenderableNode(node)) return;\n\n  // recurse to the children and tear them down first\n  const _isTagNode = isTagNode(node);\n  let { child } = fiber;\n\n  if (child) {\n    tearDownChild(child, part, _isTagNode, removeDOM);\n\n    while (child.sibling) {\n      child = child.sibling;\n      tearDownChild(child, part, _isTagNode, removeDOM);\n    }\n  }\n\n  // if it is primitive node we need to delete the text node associated with it\n  if (isPrimitiveNode(node) && removeDOM) {\n    const textNode = getNextSibling(part.parentNode, part.previousSibling);\n    if (textNode) remove(textNode);\n    return;\n  }\n\n  const { ref } = node;\n  /**\n   * We have to only handle tag, component and attributes,\n   * as tag has elements to remove, attribute fiber can have ref to unset\n   * and component can have ref and lifecycle method to call.\n   *\n   * Text nodes will be remove by removing its parent tag node. So no\n   * need to handle text node separately\n   */\n\n  /**\n   * This will cover ATTRIBUTE_NODE as well, so no need to handle them separately\n   */\n  if (ref) {\n    setRef(ref, null);\n  }\n\n  // if there is no nodeInstance it means its not rendered yet so no need do anything on that\n  // NOTE: This has to be after ref logic as attribute nodes do not have nodeInstance but setRef has to be done\n  if (!nodeInstance) return;\n\n  // if it is a tag node remove the dom elements added by tag node\n  if (_isTagNode) {\n    const { domNodes } = nodeInstance;\n\n    // remove all the elements of nodeInstance\n    if (removeDOM) remove(domNodes);\n  }\n  // if its a component node and is mounted then call lifecycle methods\n  else if (isComponentNode(node) && isMounted(nodeInstance)) {\n    // for class component call componentWillUnmount and for functional comp clean effects\n    if (node.nodeType === CLASS_COMPONENT_NODE) {\n      callLifeCycle(nodeInstance, 'componentWillUnmount');\n    } else {\n      cleanEffects(fiber, true);\n    }\n  }\n}\n\nexport default function(root: HostFiber): void {\n  const { tearDownFibers } = root;\n\n  tearDownFibers.forEach((fiber) => {\n    // only tear down those fibers which are marked for tear down\n    if (fiber.shouldTearDown) tearDownFiber(fiber, true);\n  });\n\n  // rest the tear down fibers\n  root.tearDownFibers = [];\n}\n"
  },
  {
    "path": "src/transitionUtils.js",
    "content": "// @flow\nimport { getUniqueId } from './utils';\nimport {\n  UPDATE_SOURCE_TRANSITION,\n  TRANSITION_STATE_START,\n  TRANSITION_STATE_SUSPENDED,\n  TRANSITION_STATE_RESOLVED,\n  TRANSITION_STATE_COMPLETED,\n  TRANSITION_STATE_TIMED_OUT,\n} from './configs';\n\nimport type {\n  PredefinedTransition,\n  Transition,\n  AnyTransition,\n  Fiber,\n  HostFiber,\n} from './flow.types';\n\nexport const PREDEFINED_TRANSITION_SYNC: PredefinedTransition = {\n  transitionId: '',\n  tryCount: 0,\n  transitionState: TRANSITION_STATE_TIMED_OUT,\n};\n\nexport const PREDEFINED_TRANSITION_DEFERRED: PredefinedTransition = {\n  transitionId: getUniqueId(),\n  tryCount: 0,\n  transitionState: TRANSITION_STATE_TIMED_OUT,\n};\n\nfunction shouldProcessTransition(transition: AnyTransition) {\n  const { transitionState } = transition;\n  return (\n    transitionState === TRANSITION_STATE_START ||\n    transitionState === TRANSITION_STATE_RESOLVED ||\n    transitionState === TRANSITION_STATE_TIMED_OUT\n  );\n}\n\nexport function isTransitionCompleted(transition: AnyTransition): boolean {\n  const { transitionState } = transition;\n\n  return (\n    transitionState === TRANSITION_STATE_COMPLETED || transitionState === TRANSITION_STATE_TIMED_OUT\n  );\n}\n\nexport function isTransitionResolved(transition: Transition): boolean {\n  const { transitionState } = transition;\n\n  // send true, on either the transition is resolved or completed\n  return transitionState === TRANSITION_STATE_RESOLVED || isTransitionCompleted(transition);\n}\n\nexport function setTransitionComplete(transition: AnyTransition): void {\n  const { transitionState } = transition;\n  if (\n    transitionState !== TRANSITION_STATE_TIMED_OUT &&\n    transitionState !== TRANSITION_STATE_SUSPENDED\n  ) {\n    /**\n     * If transition is in pending state, first reset the isPending state\n     * and then on next render cycle mark transition as completed\n     * so that isPending and transition changes can be shown on one commit phase\n     */\n    if (transition.isPending) {\n      transition.clearTimeout();\n      transition.updatePendingState(false, UPDATE_SOURCE_TRANSITION);\n    } else {\n      // $FlowFixMe: We check if its not timed out already, so we can ignore flowtype error here\n      transition.transitionState = TRANSITION_STATE_COMPLETED;\n    }\n  }\n}\n\n/**\n * get current transition id from the current rendering\n */\nexport function getTransitionFromFiber(\n  fiber: Fiber,\n  defaultTransition: ?PredefinedTransition,\n): AnyTransition {\n  defaultTransition = defaultTransition || PREDEFINED_TRANSITION_SYNC;\n  // if there is currentTransition return that or else return SYNC transition\n  return fiber.root.currentTransition || defaultTransition;\n}\n\n/**\n * function to get first pending transition\n */\nexport function getFirstTransitionToProcess(root: HostFiber): ?AnyTransition {\n  const { pendingTransitions } = root;\n  return pendingTransitions.find(shouldProcessTransition);\n}\n\n/**\n * function to check if a transition is a custom transition\n */\nexport function isCustomTransition(transition: Transition): boolean {\n  return !!transition.startTransition;\n}\n"
  },
  {
    "path": "src/unmountComponentAtNode.js",
    "content": "// @flow\nimport tearDown from './tearDown';\nimport { markToTearDown } from './fiber';\n\nimport type { ExtendedElement } from './flow.types';\n\nfunction unmountComponentAtNode(container: ExtendedElement): boolean {\n  /**\n   * Most of the time we only to unmount component from the root elem\n   * TODO: Should we support unmounting from any element rendered by react itself. Check if React allows that\n   */\n  const { __rootFiber: root } = container;\n  if (root) {\n    // tear down the current tree\n    markToTearDown(root.current);\n    tearDown(root);\n\n    // remove the __rootFiber reference\n    container.__rootFiber = undefined;\n\n    return true;\n  }\n\n  return false;\n}\n\nexport default unmountComponentAtNode;\n"
  },
  {
    "path": "src/updateAttribute.js",
    "content": "import { getEffectiveAttrName, getEventName, isEventAttribute, loopEntries } from './utils';\n\nimport {\n  getEffectiveEventName,\n  getInputStateType,\n  handleInputProperty,\n  getPatchedEventHandler,\n  handleControlledReset,\n} from './reactEvents';\n\nimport { XLINK_NS, IS_NON_DIMENSIONAL } from './configs';\n\n/**\n * Lot of diffing and applying attribute logic in this file is inspired/forked from Preact\n * Reference:\n * https://github.com/preactjs/preact/blob/master/src/diff/props.js\n */\n\nfunction applyDiffProperty(newObj, oldObj, resetValue, cb) {\n  oldObj = oldObj || {};\n  // add new attributes\n  loopEntries(newObj, (key, value) => {\n    const oldValue = oldObj[key];\n    if (value !== oldValue) {\n      cb(key, value, oldValue);\n    }\n  });\n\n  // remove old attributes\n  loopEntries(oldObj, (key, value) => {\n    if (newObj[key] === undefined && value !== undefined) {\n      cb(key, resetValue, value);\n    }\n  });\n}\n\nfunction setAttribute(node, attrName, attrValue, oldAttrValue, isSvgAttribute) {\n  /**\n   * children attrName is not a valid attribute, if the attrName is coming as children\n   * ignore it. This happens when we are the brahmos nodeType is tag element node.\n   * We don't remove children from props to avoid extra object creation.\n   */\n  if (attrName === 'children') return;\n\n  const isEventAttr = isEventAttribute(attrName);\n\n  // Handle event attributes\n  if (isEventAttr) {\n    // Reference https://github.com/facebook/react/blob/master/packages/react-dom/src/events/DOMPluginEventSystem.js#L498\n    const isCaptureEvent =\n      attrName.substr(-7) === 'Capture' && attrName.substr(-14, 7) === 'Pointer';\n    let eventName = getEventName(attrName, isCaptureEvent);\n    eventName = getEffectiveEventName(eventName, node);\n\n    // get patched event handler\n    const patchedHandler = getPatchedEventHandler(node, attrName, attrValue);\n\n    // if new event handler is not there but it had old handler, remove the old one\n    if (oldAttrValue && !attrValue) {\n      node.removeEventListener(eventName, patchedHandler, isCaptureEvent);\n      // if the event is getting added first time add a listener\n    } else if (!oldAttrValue && attrValue) {\n      node.addEventListener(eventName, patchedHandler, isCaptureEvent);\n    }\n\n    // handle style attributes\n  } else if (attrName === 'style') {\n    const { style } = node;\n    applyDiffProperty(attrValue || {}, oldAttrValue, '', (key, value) => {\n      /**\n       * check if it is custom property (--some-custom-property),then use setProperty to assign value\n       * otherwise just add the property in style object\n       */\n      if (key[0] === '-') {\n        style.setProperty(key, value);\n      } else {\n        style[key] =\n          typeof value === 'number' && IS_NON_DIMENSIONAL.test(key) === false\n            ? value + 'px'\n            : value;\n      }\n    });\n\n    // handle dangerously set innerHTML\n  } else if (attrName === 'dangerouslySetInnerHTML') {\n    const oldHTML = oldAttrValue && oldAttrValue.__html;\n    const newHTML = attrValue && attrValue.__html;\n    if (newHTML !== oldHTML) {\n      node.innerHTML = newHTML == null ? '' : newHTML; // `==` here will check for undefined and null\n    }\n    // handle node properties\n  } else if (attrName in node && !isSvgAttribute) {\n    const inputStateType = getInputStateType(node);\n    /**\n     * if it is input element it has to be handled differently,\n     * otherwise just set the property value\n     */\n    if (inputStateType) {\n      handleInputProperty(inputStateType, node, attrName, attrValue);\n    } else {\n      node[attrName] = attrValue == null ? '' : attrValue; // `==` here will check for undefined and null\n    }\n\n    // handle all other node attributes\n  } else {\n    // if attribute name is modified for JSX props, reset the name\n    attrName = getEffectiveAttrName(attrName);\n\n    /**\n     * If attribute is prefixed with xlink then we have to set attribute with namespace\n     * if attribute value is defined set the new attribute value and if\n     * it is not defined and oldAttribute is present remove the oldAttribute;\n     */\n    let attrNameWithoutNS = attrName.replace(/^xlink:?/, '');\n\n    // if attribute value is null, undefined or false remove the attribute\n    const removeAttribute = attrValue == null || attrValue === false;\n\n    if (attrName !== attrNameWithoutNS) {\n      attrNameWithoutNS = attrNameWithoutNS.toLowerCase();\n      if (removeAttribute) {\n        node.removeAttributeNS(XLINK_NS, attrNameWithoutNS);\n      } else {\n        node.setAttributeNS(XLINK_NS, attrNameWithoutNS, attrValue);\n      }\n    } else if (removeAttribute) {\n      node.removeAttribute(attrName);\n    } else {\n      node.setAttribute(attrName, attrValue);\n    }\n  }\n}\n\nexport default function updateNodeAttributes(node, attributes, oldAttributes, isSvgAttribute) {\n  applyDiffProperty(attributes, oldAttributes, null, (attrName, attrValue, oldAttrValue) => {\n    setAttribute(node, attrName, attrValue, oldAttrValue, isSvgAttribute);\n  });\n\n  // handle controlled input resetting\n  handleControlledReset(node);\n}\n"
  },
  {
    "path": "src/updateUtils.js",
    "content": "// @flow\nimport { afterCurrentStack } from './utils';\nimport {\n  PREDEFINED_TRANSITION_SYNC,\n  PREDEFINED_TRANSITION_DEFERRED,\n  getTransitionFromFiber,\n} from './transitionUtils';\nimport {\n  UPDATE_SOURCE_DEFAULT,\n  UPDATE_SOURCE_TRANSITION,\n  UPDATE_SOURCE_IMMEDIATE_ACTION,\n  BRAHMOS_DATA_KEY,\n  UPDATE_TYPE_SYNC,\n  UPDATE_TYPE_DEFERRED,\n} from './configs';\nimport { getCurrentComponentFiber } from './fiber';\n\nimport type {\n  AnyComponentInstance,\n  HostFiber,\n  Fiber,\n  UpdateSource,\n  AnyTransition,\n  UpdateType,\n  PendingUpdates,\n  ClassComponentUpdate,\n  FunctionalComponentUpdate,\n} from './flow.types';\n\nexport const deferredMeta = {\n  initialized: false,\n  timeout: 0,\n};\n\nlet updateSource = UPDATE_SOURCE_DEFAULT;\nlet currentTransition = PREDEFINED_TRANSITION_SYNC;\n\nexport function getDeferredMeta() {\n  return { ...deferredMeta };\n}\n\nexport function setUpdateSource(source: UpdateSource) {\n  updateSource = source;\n}\n\nexport function getCurrentUpdateSource() {\n  return updateSource;\n}\n\nexport function getCurrentTransition() {\n  return currentTransition;\n}\n\nfunction resetUpdateSource() {\n  /**\n   * reset update source when the current stack execution is done,\n   * This will make sure if there is sync update like event or\n   * force update, or initial render all the sync render and commit phase is done\n   */\n  afterCurrentStack(() => {\n    updateSource = UPDATE_SOURCE_DEFAULT;\n  });\n}\n\n/**\n * Function to execute something in context of custom source\n */\nexport function withUpdateSource(source: UpdateSource, cb: Function): void {\n  updateSource = source;\n  cb();\n  updateSource = UPDATE_SOURCE_DEFAULT;\n}\n\nexport function withTransition(transition: AnyTransition, cb: Function): void {\n  const prevTransition = currentTransition;\n  currentTransition = transition;\n  // set update source as a transition before calling callback\n  withUpdateSource(UPDATE_SOURCE_TRANSITION, cb);\n  currentTransition = prevTransition;\n}\n\nexport function shouldPreventSchedule(root: HostFiber): boolean {\n  // it should prevent scheduling if immediate update is required\n  return root.updateSource === UPDATE_SOURCE_IMMEDIATE_ACTION;\n}\n\nexport function isDeferredUpdate(): boolean {\n  return updateSource === UPDATE_SOURCE_TRANSITION;\n}\n\nexport function getUpdateType(): UpdateType {\n  return isDeferredUpdate() ? UPDATE_TYPE_DEFERRED : UPDATE_TYPE_SYNC;\n}\n\n/**\n * Get the pendingUpdates key in class component instance\n */\n\nexport function getPendingUpdatesKey(updateType: UpdateType) {\n  return updateType === UPDATE_TYPE_DEFERRED ? 'pendingDeferredUpdates' : 'pendingSyncUpdates';\n}\n\n/**\n * Get pending states based on update type and current transition\n */\nexport function getPendingUpdates(fiber: Fiber): PendingUpdates {\n  const {\n    root: { updateType },\n    nodeInstance: component,\n  } = fiber;\n  const brahmosData = component[BRAHMOS_DATA_KEY];\n  const pendingUpdatesKey = getPendingUpdatesKey(updateType);\n\n  if (updateType === UPDATE_TYPE_SYNC) {\n    return brahmosData[pendingUpdatesKey];\n  }\n\n  const currentTransitionId = getTransitionFromFiber(fiber, null).transitionId;\n\n  return brahmosData[pendingUpdatesKey].filter(\n    (stateMeta) => stateMeta.transitionId === currentTransitionId,\n  );\n}\n\n// function to trigger deferred updates\nexport function deferredUpdates(cb: Function): void {\n  withTransition(PREDEFINED_TRANSITION_DEFERRED, cb);\n}\n\n/**\n * function to trigger sync updates which doesn't schedule\n * And rendered and committed synchronously\n */\nexport function syncUpdates(cb: Function): void {\n  withUpdateSource(UPDATE_SOURCE_IMMEDIATE_ACTION, cb);\n}\n\nfunction getComponentFiberInWorkingTree(fiber, nodeInstance) {\n  const { root } = fiber;\n\n  while (!(fiber.nodeInstance === nodeInstance)) {\n    fiber = fiber.parent;\n\n    if (fiber === root) return null;\n  }\n\n  return fiber;\n}\n/**\n * get guarded update meta details. Through error if setState is called\n * too many times\n */\nexport function guardedSetState(\n  componentInstance: AnyComponentInstance,\n  getStateMeta: (transitionId: string) => ClassComponentUpdate | FunctionalComponentUpdate,\n): boolean {\n  let updateType, currentTransition;\n  let shouldRerender = true;\n  const brahmosData = componentInstance[BRAHMOS_DATA_KEY];\n\n  const fiber = getCurrentComponentFiber();\n  /**\n   * if the setState is called while rendering, which will be the case when current fiber is set\n   */\n  if (fiber) {\n    const { renderCount } = brahmosData;\n\n    // if render count is more than 50 probably we got into infinite loop\n    if (renderCount > 50) {\n      throw new Error(\n        'Too many rerender. Check your setState call, this may cause an infinite loop.',\n      );\n    }\n\n    const { root } = fiber;\n\n    // mark the component to retry the components fiber\n    root.retryFiber = getComponentFiberInWorkingTree(fiber, componentInstance);\n\n    updateType = root.updateType;\n    currentTransition = root.currentTransition || PREDEFINED_TRANSITION_SYNC;\n\n    // we do not want to rerender in this case as the component fiber will be retried\n    shouldRerender = false;\n  } else {\n    // reset the renderCount if not called during the render phase\n    brahmosData.renderCount = 0;\n\n    updateType = getUpdateType();\n    currentTransition = getCurrentTransition();\n  }\n\n  const pendingUpdateKey = getPendingUpdatesKey(updateType);\n  const stateMeta = getStateMeta(currentTransition.transitionId);\n\n  brahmosData[pendingUpdateKey].push(stateMeta);\n\n  return shouldRerender;\n}\n"
  },
  {
    "path": "src/utils.js",
    "content": "// @flow\nimport { BRAHMOS_DATA_KEY, CAMEL_ATTRIBUTES, MODIFIED_ATTRIBUTES } from './configs';\nimport type {\n  ObjectLiteral,\n  AnyComponentInstance,\n  FunctionalComponent,\n  ClassComponent,\n} from './flow.types';\n\n/**\n * Method to identify if a jsx element is a html element or custom component\n * Taken from https://github.com/babel/babel/blob/master/packages/babel-types/src/validators/react/isCompatTag.js\n * */\nexport function isHTMLElement(tagName: string): boolean {\n  // Must start with a lowercase ASCII letter\n  return !!tagName && /^[a-z]/.test(tagName);\n}\n\nexport function isEventAttribute(attrName: string): boolean {\n  // must start with on prefix\n  /**\n   * Check inspired by preact.\n   * Benchmark for comparison: https://esbench.com/bench/574c954bdb965b9a00965ac6\n   */\n  return attrName[0] === 'o' && attrName[1] === 'n';\n}\n\n// Convert React's camel-cased attributes to hypen cased.\nexport function getEffectiveAttrName(attrName: string): string {\n  /**\n   * if the attribute is camel cased for react, convert it to lower case and return it\n   * Or else\n   * If the attribute is an modified attribute return the html attribute.\n   */\n  const hyphenCasedAttribute = CAMEL_ATTRIBUTES.test(attrName)\n    ? attrName.replace(/[A-Z0-9]/, '-$&').toLowerCase()\n    : attrName;\n\n  return MODIFIED_ATTRIBUTES[attrName] || hyphenCasedAttribute;\n}\n\n// get the node name from the node in lowercase format\nexport function getNodeName(node: HTMLElement): string {\n  return node.nodeName.toLowerCase();\n}\n\nexport function getEventName(attrName: string, isCaptureEvent: boolean): string {\n  if (isCaptureEvent) {\n    attrName = attrName.replace(/Capture$/, '');\n  }\n  return attrName.replace('on', '').toLowerCase();\n}\n\nexport function isCustomElement(tagName: string): boolean {\n  // Must match html tag check and have a hyphen in the tag name\n  return isHTMLElement(tagName) && tagName.indexOf('-') !== -1;\n}\n\n// check if value is null or undefined\nexport function isNil(val: any): boolean {\n  return val === undefined || val === null;\n}\n\n/**\n * function to return artificial time, we are using counter\n * instead of time as Date.now or performance.now is little slower than just a counter\n * Note: when we add support for SSR, we should have a way to reset the initial time to\n * not let this initialTime grow infinitely\n */\nlet initialTime = 0;\nexport function now(): number {\n  return initialTime++;\n}\n\n/**\n * Function to return current timestamp\n */\nexport function timestamp(): number {\n  return Date.now();\n}\n\n// add brahmos data container to domNode\nexport function addDataContainer(domNode: Node): void {\n  // add brahmos data container\n  // $FlowFixMe: Adding a key is intentional here\n  domNode.__brahmosData = {\n    events: {},\n  };\n}\n\n/**\n * function to separate props, key and ref\n */\nexport function getNormalizedProps(props: ObjectLiteral, includeRef: boolean): ObjectLiteral {\n  // if we don't have to remove anything from props no need to create a new object\n  if (!('key' in props || ('ref' in props && !includeRef))) return props;\n\n  const newProps = {};\n\n  let key;\n  for (key in props) {\n    if (key !== 'key' && (key !== 'ref' || includeRef)) newProps[key] = props[key];\n  }\n  return newProps;\n}\n\n/**\n * Function to loop over object entries\n */\nexport function loopEntries(obj: ObjectLiteral, cb: (key: string, value: any) => void) {\n  const keys = Object.keys(obj);\n\n  for (let i = 0, ln = keys.length; i < ln; i++) {\n    const key = keys[i];\n    const value = obj[key];\n    cb(key, value);\n  }\n}\n\n/**\n * Remove nodes from parent\n */\n\nexport function remove(nodes: Array<Node> | Node): void {\n  if (!Array.isArray(nodes)) nodes = [nodes];\n  for (let i = nodes.length - 1; i >= 0; i--) {\n    const node = nodes[i];\n    // $FlowFixMe: remove is present on all browser except IE11\n    node.remove();\n  }\n}\n\n/**\n * Convert an array like object to array\n */\n\nexport function toArray(list: Iterable<any>, start: ?number) {\n  start = start || 0;\n  return Array.prototype.slice.call(list, start);\n}\n\n/**\n * Given a object/string crate a node which can be appended.\n */\nexport function changeToNode(value: Array<Node> | NodeList<Node> | Node | string): Node {\n  const isNodeList = value instanceof NodeList;\n\n  if (value instanceof Node) {\n    return value;\n    // if it is a array of Nodes or NodList return a fragment\n  } else if (Array.isArray(value) || isNodeList) {\n    const fragment = document.createDocumentFragment();\n\n    let i = 0;\n\n    while (value[i]) {\n      // $FlowFixMe: Flow Not able to identify condition if `value instanceof NodeList` stored as value\n      fragment.appendChild(value[i]);\n\n      // no need to increment on nodeList as nodeList is spliced when elements are moved\n      if (!isNodeList) i += 1;\n    }\n    return fragment;\n  }\n\n  // In other case it will be string so return a text node\n  // $FlowFixMe: Flow Not able to identify condition if `value instanceof NodeList` stored as value\n  return document.createTextNode(value);\n}\n\n/**\n * Function to add child nodes before endNode, if it is not defined or null\n * It will add nodes on the last\n */\nexport function insertBefore(parent: Element, end: ?Node, value: any): Array<Node> {\n  const node = changeToNode(value);\n\n  /**\n   * Fragment child nodes gets cleared after its appended to dom.\n   * So if it is fragment keep the reference of all childNodes as array.\n   */\n  let persistentNode;\n  if (Array.isArray(value)) {\n    // if value was already an array no need to convert document fragment to array\n    persistentNode = value;\n  } else if (node instanceof DocumentFragment) {\n    persistentNode = toArray(node.childNodes);\n  } else {\n    persistentNode = value;\n  }\n\n  parent.insertBefore(node, end);\n\n  return persistentNode;\n}\n\n// function to get next sibling based on parent node and previous sibling\nexport function getNextSibling(parentNode: Element, previousSibling: ?Node): ?Node {\n  return previousSibling ? previousSibling.nextSibling : parentNode.firstChild;\n}\n\n/**\n * Merge newState with old state for components\n */\nexport function mergeState(state: ObjectLiteral, newState: any): ObjectLiteral {\n  // if new state is not present or any falsy value, just return the state\n  if (!newState) return state;\n\n  // allow all type of objects to be spread\n  // this behaviour is similar to react\n  if (typeof newState === 'object') {\n    state = { ...state, ...newState };\n  }\n  return state;\n}\n\n/**\n * Function to call life cycle of a given component, or component instance\n */\nexport function callLifeCycle(object: any, method: string, args: ?Array<any>): void {\n  if (object[method]) {\n    return object[method].apply(object, args);\n  }\n}\n\n/**\n * Create an empty text node before a given node\n */\nexport function createEmptyTextNode(parent: Node, index: number): ?Node {\n  const nextSibling = index === 0 ? parent.firstChild : parent.childNodes[index];\n\n  const textNode = document.createTextNode('');\n  parent.insertBefore(textNode, nextSibling);\n  return textNode;\n}\n\n/**\n * Put a code execution in micro task, so that it's executed after current stack\n */\nexport const resolvedPromise = Promise.resolve();\nexport function afterCurrentStack(cb: Function): Promise<void> {\n  return resolvedPromise.then(cb);\n}\n\n/**\n * Function to create a unique id\n */\nexport function getUniqueId(): string {\n  return now() + '-' + Math.random() * 1000000;\n}\n\n/**\n * Method to get a promise which support suspension of rendering\n */\nexport function getPromiseSuspendedValue<T>(promise: Promise<T>) {\n  let status = 'pending';\n  let result;\n  const suspender = promise.then(\n    (r) => {\n      status = 'success';\n      result = r;\n    },\n    (e) => {\n      status = 'error';\n      result = e;\n    },\n  );\n  return {\n    read() {\n      if (status === 'pending') {\n        throw suspender;\n      } else if (status === 'error') {\n        throw result;\n      } else if (status === 'success') {\n        return result;\n      }\n    },\n  };\n}\n\n/** function to check if component is mounted */\nexport function isMounted(component: AnyComponentInstance): boolean {\n  return component[BRAHMOS_DATA_KEY].mounted;\n}\n\n/** function to get component name by its constructor */\nexport function getComponentName(Component: ClassComponent | FunctionalComponent): string {\n  return Component.displayName || Component.name;\n}\n\n/**\n * A wrapper component which wraps the render elements\n */\nexport function BrahmosRootComponent({ children }: ObjectLiteral): any {\n  return children;\n}\n"
  },
  {
    "path": "src/workLoop.js",
    "content": "// @flow\nimport {\n  isComponentNode,\n  isPrimitiveNode,\n  isRenderableNode,\n  isTagNode,\n  ATTRIBUTE_NODE,\n} from './brahmosNode';\n\nimport {\n  UPDATE_SOURCE_TRANSITION,\n  BRAHMOS_DATA_KEY,\n  UPDATE_TYPE_DEFERRED,\n  EFFECT_TYPE_OTHER,\n  UPDATE_TYPE_SYNC,\n  UPDATE_SOURCE_IMMEDIATE_ACTION,\n} from './configs';\n\nimport processComponentFiber from './processComponentFiber';\nimport { processTextFiber } from './processTextFiber';\nimport processTagFiber from './processTagFiber';\nimport effectLoop, {\n  preCommitBookkeeping,\n  resetEffectProperties,\n  removeTransitionFromRoot,\n} from './effectLoop';\nimport { shouldPreventSchedule, getPendingUpdates, withUpdateSource } from './updateUtils';\nimport {\n  getFirstTransitionToProcess,\n  setTransitionComplete,\n  isTransitionCompleted,\n} from './transitionUtils';\nimport {\n  getNextFiber,\n  cloneChildrenFibers,\n  getUpdateTimeKey,\n  getLastCompleteTimeKey,\n  cloneCurrentFiber,\n  markToTearDown,\n  markPendingEffect,\n} from './fiber';\nimport processArrayFiber from './processArrayFiber';\nimport tearDown from './tearDown';\nimport { now } from './utils';\nimport schedule from './scheduler';\n\nimport type { Fiber, HostFiber } from './flow.types';\n\nfunction fiberHasUnprocessedUpdates(fiber) {\n  const { node, nodeInstance } = fiber;\n\n  /**\n   * Return if node is not component type or if it is component\n   * which is yet to mount (nodeInstance will be null in such case)\n   */\n  if (!(isComponentNode(node) && nodeInstance)) return false;\n\n  return !!getPendingUpdates(fiber).length || nodeInstance[BRAHMOS_DATA_KEY].isDirty;\n}\n\nexport function processFiber(fiber: Fiber) {\n  const { node, alternate } = fiber;\n\n  // if new node is null mark old node to tear down\n  if (!isRenderableNode(node)) {\n    if (alternate) markToTearDown(alternate);\n    return;\n  }\n\n  const nodeHasUpdates = fiberHasUnprocessedUpdates(fiber);\n\n  /**\n   * If a fiber is processed and node is not dirty we clone all the children from current tree\n   *\n   * This will not affect the first render as fiber will never be on processed state\n   * on the first render.\n   */\n  if (fiber.processedTime && !nodeHasUpdates) {\n    // We need to clone children only in case we are doing deferred rendering\n    cloneChildrenFibers(fiber);\n    return;\n  }\n\n  if (isPrimitiveNode(node)) {\n    processTextFiber(fiber);\n  } else if (Array.isArray(node)) {\n    processArrayFiber(fiber);\n  } else if (isTagNode(node)) {\n    processTagFiber(fiber);\n  } else if (isComponentNode(node)) {\n    processComponentFiber(fiber);\n  } else if (node.nodeType === ATTRIBUTE_NODE) {\n    // nothing to on process phase, just mark that the fiber has uncommitted effects\n    markPendingEffect(fiber, EFFECT_TYPE_OTHER);\n  }\n\n  // after processing, set the processedTime to the fiber\n  fiber.processedTime = now();\n}\n\nfunction shouldCommit(root) {\n  // if there is transition processed on work loop check if its completed\n  if (root.currentTransition) {\n    /**\n     * all sync changes should be committed before committing transition,\n     * for a transition to be committed it shouldn't have any pending commits\n     * if not no need to run the commit phase\n     */\n    return (\n      root.lastCompleteTime >= root.updateTime &&\n      root.hasUncommittedEffect &&\n      isTransitionCompleted(root.currentTransition)\n    );\n  }\n\n  // otherwise return true for sync commits\n  return true;\n}\n\n/**\n * This is the part where all the changes are flushed on dom,\n * It will also take care of tearing the old nodes down\n */\n// Use object notation to avoid inlining of commit changes fn in workloop\nconst avoidInlineCommitChange = {\n  fn: (root) => {\n    const { updateType, current } = root;\n    const lastCompleteTimeKey = getLastCompleteTimeKey(updateType);\n\n    // tearDown old nodes\n    tearDown(root);\n\n    const fibersWithEffect = preCommitBookkeeping(root);\n    /**\n     * set the last updated time for render\n     * NOTE: We do it before effect loop so if there is\n     * setStates in effect updateTime for setState should not\n     * fall behind the complete time\n     *\n     * Also, lastCompleteTime should be marked always\n     * weather its deferred or sync updates\n     */\n    root[lastCompleteTimeKey] = root.lastCompleteTime = now();\n\n    // if it deferred swap the wip and current tree\n    if (updateType === UPDATE_TYPE_DEFERRED) {\n      // $FlowFixMe: wip fiber is set after deferred render\n      root.current = root.wip;\n      root.wip = current;\n    }\n\n    // After correcting the tree flush the effects on new fibers\n    /**\n     * There can be state updates inside effects/lifecycle, so we should mark it as\n     * immediate update  so we don't have multiple paints\n     */\n    withUpdateSource(UPDATE_SOURCE_IMMEDIATE_ACTION, () => effectLoop(root, fibersWithEffect));\n  },\n};\n\nexport default function workLoop(fiber: Fiber, topFiber: Fiber | HostFiber) {\n  const { root } = fiber;\n  const { updateType, currentTransition } = root;\n  const lastCompleteTimeKey = getLastCompleteTimeKey(updateType);\n  const updateTimeKey = getUpdateTimeKey(updateType);\n  const lastCompleteTime = root[lastCompleteTimeKey];\n\n  /**\n   * If the update is triggered from update source which needs to be flushed\n   * synchronously we don't need requestIdleCallback, in other case we should\n   * schedule our renders.\n   */\n  const shouldSchedule = !shouldPreventSchedule(root);\n  schedule(root, shouldSchedule, (timeRemaining) => {\n    while (fiber !== topFiber) {\n      // process the current fiber which will return the next fiber\n      /**\n       * If there is time remaining to do some chunk of work,\n       * process the current fiber, and then move to next\n       * and keep doing it till we are out of time.\n       */\n      if (timeRemaining()) {\n        processFiber(fiber);\n\n        /**\n         * if the fiber jump due to suspense or error boundary,\n         * we need to use that as next fiber. We also need to reset\n         * topFiber to root, as the retry fiber can be in upper hierarchy\n         */\n        const { retryFiber } = root;\n        if (retryFiber) {\n          fiber = retryFiber;\n          topFiber = root;\n          root.retryFiber = null;\n        } else {\n          fiber = getNextFiber(fiber, topFiber, lastCompleteTime, updateTimeKey);\n        }\n      } else {\n        // if we are out of time schedule work for next fiber\n        workLoop(fiber, topFiber);\n\n        return;\n      }\n    }\n\n    // call all the render callbacks\n    root.callRenderCallbacks();\n\n    if (currentTransition) {\n      // set transition complete if it is not on suspended or timed out state\n      setTransitionComplete(currentTransition);\n\n      // reset try count\n      currentTransition.tryCount = 0;\n\n      /**\n       * if transition is completed and it does not have any effect to commit, we should remove the\n       * transition from pending transition\n       */\n      if (!root.hasUncommittedEffect && isTransitionCompleted(currentTransition)) {\n        removeTransitionFromRoot(root);\n      }\n    }\n\n    if (shouldCommit(root)) {\n      avoidInlineCommitChange.fn(root);\n    }\n\n    // check if there are any pending transition, if yes try rendering them\n    if (getFirstTransitionToProcess(root)) {\n      withUpdateSource(UPDATE_SOURCE_TRANSITION, () => {\n        root.updateSource = UPDATE_SOURCE_TRANSITION;\n        doDeferredProcessing(root);\n      });\n    }\n  });\n}\n\nexport function doDeferredProcessing(root: HostFiber) {\n  // if there is no deferred work or pending transition return\n  const pendingTransition = getFirstTransitionToProcess(root);\n\n  if (!pendingTransition) return;\n\n  root.updateType = UPDATE_TYPE_DEFERRED;\n\n  // reset the effect list before starting new one\n  resetEffectProperties(root);\n\n  // set the pending transition as current transition\n  root.currentTransition = pendingTransition;\n\n  pendingTransition.tryCount += 1;\n\n  // $FlowFixMe: Passing root on top level component is exception\n  root.wip = cloneCurrentFiber(root.current, root.wip, root, root);\n\n  workLoop(root.wip, root);\n}\n\nexport function doSyncProcessing(fiber: Fiber) {\n  const { root, parent } = fiber;\n  root.updateType = UPDATE_TYPE_SYNC;\n\n  // set current transition as null for sync processing\n  root.currentTransition = null;\n\n  // reset the effect list before starting new one\n  resetEffectProperties(root);\n\n  workLoop(fiber, parent);\n}\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"outDir\": \"./lib\",\n    \"allowJs\": true,\n    \"checkJs\": true,\n    \"target\": \"es5\",\n    \"jsx\": \"preserve\"\n  },\n  \"include\": [\"./src/**/*\"]\n}\n"
  },
  {
    "path": "webpack.config.js",
    "content": "var HtmlWebpackPlugin = require('html-webpack-plugin');\nvar path = require('path');\n\nmodule.exports = {\n  entry: './example/index.js',\n  mode: 'development',\n  output: {\n    path: path.resolve(__dirname, './dist'),\n    filename: 'bundle.js',\n  },\n  devServer: {\n    compress: true,\n    port: 8083,\n  },\n  plugins: [\n    new HtmlWebpackPlugin({\n      template: './example/index.html',\n    }),\n  ],\n  resolve: {\n    alias: {\n      brahmos: path.resolve(__dirname, 'src'),\n      react: path.resolve(__dirname, 'src'),\n      'react-dom': path.resolve(__dirname, 'src'),\n    },\n  },\n  module: {\n    rules: [\n      {\n        test: /\\.js$/,\n        exclude: /(node_modules|bower_components)/,\n        use: {\n          loader: 'babel-loader',\n        },\n      },\n      {\n        test: /\\.s[ac]ss|\\.css$/i,\n        use: [\n          // Creates `style` nodes from JS strings\n          'style-loader',\n          // Translates CSS into CommonJS\n          'css-loader',\n          // Compiles Sass to CSS\n          'sass-loader',\n        ],\n      },\n    ],\n  },\n};\n"
  }
]