diff --git a/.gitignore b/.gitignore
new file mode 100644
index 000000000..99d4298ab
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,18 @@
+coverage
+dist
+dist_save
+*.tgz
+*.zip
+angular/
+react/
+
+!node_modules/
+node_modules/*
+!node_modules/gridstack/
+node_modules/gridstack/*
+!node_modules/gridstack/dist/
+node_modules/gridstack/dist/*
+!node_modules/gridstack/dist/gridstack-all.js
+!node_modules/gridstack/dist/gridstack-all.js.map
+!node_modules/gridstack/dist/gridstack.css
+!node_modules/gridstack/dist/gridstack.min.css
diff --git a/.nojekyll b/.nojekyll
new file mode 100644
index 000000000..e69de29bb
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 000000000..c304efe30
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1,4 @@
+./demo
+./freelancer
+./logo
+**/node_modules
\ No newline at end of file
diff --git a/.prettierrc.json b/.prettierrc.json
new file mode 100644
index 000000000..66e7e941c
--- /dev/null
+++ b/.prettierrc.json
@@ -0,0 +1,6 @@
+{
+  "trailingComma": "es5",
+  "tabWidth": 2,
+  "semi": false,
+  "singleQuote": true
+}
\ No newline at end of file
diff --git a/CNAME b/CNAME
new file mode 100644
index 000000000..3530eb4f0
--- /dev/null
+++ b/CNAME
@@ -0,0 +1 @@
+gridstackjs.com
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index 511ea0819..000000000
--- a/LICENSE
+++ /dev/null
@@ -1,22 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2014 Pavel Reznikov
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
diff --git a/README.md b/README.md
index e0460911b..a1b5993c1 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,34 @@
-gridstack.js
-============
+# Gridstack Website
 
-gridstack.js is a jQuery plugin for widget layout
+## Technos
+### Icons
+- Lucide Icons
+> We use Lucide Icons for the website, but we copy svg instead of using the lib directly. You can find them [here](https://lucide.dev/)
+- Dev icons
+(We use the link for now but will be replaced by svg)
+> We use Dev icons for the website, but we copy svg instead of using the lib directly. You can find them [here](https://devicon.dev/)
+### Gridstack
+(Of course 🙃)
+### Highlight.js
+For code highlighting, used in the homepage to have a beautiful code snippet `<pre><code>...</code></pre>`
+A custom theme is used, you can find it in the `src/styles/highlight.css` file
+### Dev dependencies
+- Prettier
+For code formatting
+
+
+> The tailwind.config.js file is useless but make code editor plugins works.
+### Roadmap
+
+- [ ] Create a beautiful examples/ page
+- [ ] Create a beautiful documentation/ page
+- [ ] Create a beautiful changes/ page
+- [ ] Improve demo.css to follow the same style as the website
+- [ ] Create a layout in the examples/[name.html] to switch easily between examples
+- [ ] Add micro-interactions to the website
+- [ ] Add animation to mobile navbar
+- [x] Add lucide icons to the website & in many sections
+- [ ] Improve SEO with meta tags on each page
+- [ ] Find a way to update automatically `Current version | v10.1.2`
+- [ ] Improve responsive design (mobile version) by changing grid to 6 columns instead of 12 for example and reduce padding on x, etc.
+- [ ] Fix advanced demo "Add widget" to not impact the background & fix margins when dropped in the grid
\ No newline at end of file
diff --git a/demo/anijs.html b/demo/anijs.html
new file mode 100644
index 000000000..53538feb6
--- /dev/null
+++ b/demo/anijs.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="utf-8" />
+  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
+  <meta name="viewport" content="width=device-width, initial-scale=1" />
+  <title>AniJS demo</title>
+
+  <link rel="stylesheet" href="https://anijs.github.io/lib/anicollection/anicollection.css" />
+  <link rel="stylesheet" href="demo.css"/>
+
+  <script src="../node_modules/gridstack/dist/gridstack-all.js"></script>
+  <script src="https://cdnjs.cloudflare.com/ajax/libs/AniJS/0.9.3/anijs.js"></script>
+</head>
+<body>
+  <div class="container-fluid">
+    <h1>AniJS demo</h1>
+    <div>
+      <a onClick="addWidget()" class="btn btn-primary" href="#">Add Widget</a>
+    </div>
+    <h4>Widget added</h4>
+    <br>
+    <div class="grid-stack"></div>
+  </div>
+
+  <script type="text/javascript">
+    let grid = GridStack.init();
+    let self = this;
+    grid.on('added', function(e, items) {
+      // add anijs data to gridstack item
+      for (let i = 0; i < items.length; i++) {
+        items[i].el.setAttribute('data-anijs', 'if: added, do: swing animated, after: $removeAnimations, on: $gridstack');
+      }
+      AniJS.run();
+      self.gridstackNotifier = AniJS.getNotifier('gridstack');
+      // fire added event!
+      self.gridstackNotifier.dispatchEvent('added');
+    });
+
+    function addWidget() {
+      grid.addWidget({w: Math.floor(1 + 3 * Math.random()), h: Math.floor(1 + 3 * Math.random())});
+    };
+
+    let animationHelper = AniJS.getHelper();
+
+    //Defining removeAnimations to remove existing animations
+    animationHelper.removeAnimations = function(e, animationContext) {
+      document.querySelectorAll('.grid-stack-item').forEach( function(el) {
+        el.removeAttribute('data-anijs');
+      });
+    }
+
+    addWidget();
+  </script>
+</body>
+</html>
diff --git a/demo/canvasJS.html b/demo/canvasJS.html
new file mode 100644
index 000000000..71c5368bc
--- /dev/null
+++ b/demo/canvasJS.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <title>CanvasJS grid demo</title>
+
+  <link rel="stylesheet" href="demo.css"/>
+  <script src="../node_modules/gridstack/dist/gridstack-all.js"></script>
+  <script src="https://canvasjs.com/assets/script/canvasjs.min.js"></script>
+
+  <style type="text/css">
+    body { margin: 8px 0; } /* make grid take entire vw so we have correct square cells */
+  </style>
+</head>
+<body>
+<div>
+  <h1>CanvasJS grid demo</h1>
+  <br/>
+  <div class="grid-stack">
+  </div>
+</div>
+
+<script type="text/javascript">
+  let grid = GridStack.init({
+    cellHeight: 'initial', // start square but will set to % of window width later
+    animate: false, // show immediate (animate: true is nice for user dragging though)
+    float: true
+  });
+
+  let items = [ // our initial 12 column layout loaded first so we can compare
+    {x: 1, y: 1, w: 7, h:3 , content: '<div id="chartContainer" style="height: 370px; width: 100%;"></div>'},
+  ];
+  grid.load(items);
+
+  var chart = new CanvasJS.Chart("chartContainer", {
+    animationEnabled: true,
+    title:{
+      text: "Company Revenue by Year"
+    },
+    axisY: {
+      title: "Revenue in USD",
+      valueFormatString: "#0,,.",
+      suffix: "mn",
+      prefix: "$"
+    },
+    data: [{
+      type: "splineArea",
+      color: "rgba(54,158,173,.7)",
+      markerSize: 5,
+      xValueFormatString: "YYYY",
+      yValueFormatString: "$#,##0.##",
+      dataPoints: [
+        { x: new Date(2000, 0), y: 3289000 },
+        { x: new Date(2001, 0), y: 3830000 },
+        { x: new Date(2002, 0), y: 2009000 },
+        { x: new Date(2003, 0), y: 2840000 },
+        { x: new Date(2004, 0), y: 2396000 },
+        { x: new Date(2005, 0), y: 1613000 },
+        { x: new Date(2006, 0), y: 2821000 },
+        { x: new Date(2007, 0), y: 2000000 },
+        { x: new Date(2008, 0), y: 1397000 },
+        { x: new Date(2009, 0), y: 2506000 },
+        { x: new Date(2010, 0), y: 2798000 },
+        { x: new Date(2011, 0), y: 3386000 },
+        { x: new Date(2012, 0), y: 6704000},
+        { x: new Date(2013, 0), y: 6026000 },
+        { x: new Date(2014, 0), y: 2394000 },
+        { x: new Date(2015, 0), y: 1872000 },
+        { x: new Date(2016, 0), y: 2140000 }
+      ]
+    }]
+  });
+  chart.render();
+</script>
+</body>
+</html>
diff --git a/demo/cell-height.html b/demo/cell-height.html
new file mode 100644
index 000000000..1de5799e4
--- /dev/null
+++ b/demo/cell-height.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="utf-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <title>cell height demo</title>
+
+  <link rel="stylesheet" href="demo.css"/>
+  <script src="../node_modules/gridstack/dist/gridstack-all.js"></script>
+  <style type="text/css">
+  .container {
+    background-color: lightblue;
+    width: 100%;
+    height: 800px;
+  }
+  </style>
+
+</head>
+<body>
+  <div class="container">
+    <h1>Cell Height grid options demo</h1>
+    <p>sample showing the different cellHeight options and what happens when you resize the window</p>
+    <div>
+      <a class="btn btn-primary" onClick="setOpt('auto')" href="#">auto</a>
+      <a class="btn btn-primary" onClick="setOpt('initial')" href="#">initial</a>
+      <a class="btn btn-primary" onClick="setOpt(100)" href="#">100px</a>
+      <a class="btn btn-primary" onClick="setOpt('10vh')" href="#">'10vh'</a>
+      <a class="btn btn-primary" onClick="setOpt('10%')" href="#">'10%' of blue (broken)</a>
+      <span>settings:</span><span id="info"></span>
+    </div>
+    <br>
+    <div class="grid-stack"></div>
+  </div>
+  <script type="text/javascript">
+    let opts = {
+      cellHeight: 'auto', // see other possible values (best to do in here)
+      cellHeightThrottle: 100,
+    }
+    let grid = GridStack.init(opts);
+    let items = [
+      {x:0, y:0, content:'0'},
+      {x:1, y:0, w:2, content:'1'},
+      {x:3, y:0, h:2, content:'2'},
+    ];
+    grid.load(items);
+
+    let info = document.querySelector('#info');
+    info.innerHTML = opts.cellHeight;
+    setOpt = function(val) {
+      grid.cellHeight(val);
+      info.innerHTML = val;
+    }
+  </script>
+</body>
+</html>
diff --git a/demo/column.html b/demo/column.html
new file mode 100644
index 000000000..9f1d8fa39
--- /dev/null
+++ b/demo/column.html
@@ -0,0 +1,125 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="utf-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <title>Column grid demo</title>
+
+  <link rel="stylesheet" href="demo.css"/>
+  <script src="../node_modules/gridstack/dist/gridstack-all.js"></script>
+</head>
+<body>
+  <div class="container-fluid">
+    <h1>column() grid demo (fix cellHeight)</h1>
+    <div><span>Number of Columns:</span> <span id="column-text">12</span></div>
+    <div>
+      <label>Choose re-layout:</label>
+      <select onchange="setLayout(this.value)">
+        <option value="list">list</option>
+        <option value="compact">compact</option>
+        <option value="moveScale">move + scale</option>
+        <option value="move">move</option>
+        <option value="scale">scale</option>
+        <option value="none">none</option>
+        <option value="custom">custom</option>
+      </select>
+    </div>
+    <div>
+      load:
+      <a onClick="grid.removeAll().load(list)" class="btn btn-primary" href="#">list</a>
+      <a onClick="grid.removeAll().load(test1)" class="btn btn-primary" href="#">case 1</a>
+      <a onClick="random()" class="btn btn-primary" href="#">random</a>
+      <a onClick="addWidget()" class="btn btn-primary" href="#">Add Widget</a>
+      column:
+      <a onClick="column(1)" class="btn btn-primary" href="#">1</a>
+      <a onClick="column(2)" class="btn btn-primary" href="#">2</a>
+      <a onClick="column(3)" class="btn btn-primary" href="#">3</a>
+      <a onClick="column(4)" class="btn btn-primary" href="#">4</a>
+      <a onClick="column(6)" class="btn btn-primary" href="#">6</a>
+      <a onClick="column(8)" class="btn btn-primary" href="#">8</a>
+      <a onClick="column(10)" class="btn btn-primary" href="#">10</a>
+      <a onClick="column(12)" class="btn btn-primary" href="#">12</a>
+    </div>
+    <br>
+    <div class="grid-stack"></div>
+  </div>
+
+  <script type="text/javascript">
+    // NOTE: REAL apps would sanitize-html or DOMPurify before blinding setting innerHTML. see #2736
+    GridStack.renderCB = function(el, w) {
+      el.innerHTML = w.content;
+    };
+
+    let test1 = [ // DOM order will be 0,1,2,3,4,5,6 vs column1 = 0,1,4,3,2,5,6
+      /* match karma testing
+      {x: 0, y: 0, w: 4, h: 2},
+      {x: 4, y: 0, w: 4, h: 4},
+      {text: ' auto'},
+      */
+      {x: 0, y: 0, w: 2, h: 2},
+      {x: 2, y: 0, w: 2},
+      {x: 5, y: 1},
+      {x: 5, y: 0, w: 2},
+      // {x: 0, y: 0}, // conflict
+      {text: ' auto'}, // autoPosition testing
+      // {x: 4, y: 0}, // same auto-pos
+      {x: 5, y: 3, w: 2},
+      {x: 0, y: 4, w: 12}
+    ];
+    let list = [{h:2},{},{},{},{},{},{},{},{},{w:2},{},{},{},{},{},{}];
+    list.forEach((n,i) => {
+      n.content = '<button onClick="grid.removeWidget(this.parentNode.parentNode)">X</button><br>' + ++i;
+    });
+    let count = 0;
+    test1.forEach(n => {
+      n.content = '<button onClick="grid.removeWidget(this.parentNode.parentNode)">X</button><br>' + count++ + (n.text ? n.text : '');
+    });
+
+    let grid = GridStack.init({
+      float: true,
+      cellHeight: 100 // fixed as default 'auto' (square) makes it hard to test 1-3 column in actual large windows tests
+    }).load(list);
+    let text = document.querySelector('#column-text');
+    let layout = 'list';
+
+    grid.on('added removed change', function(e, items) {
+      let str = '';
+      items.forEach(function(item) { str += ' (x,y)=' + item.x + ',' + item.y; });
+      console.log(e.type + ' ' + items.length + ' items:' + str );
+    });
+
+
+    function random() {
+      grid.removeAll();
+      count = 0;
+      for (i=0; i<8; i++) addWidget(true);
+    }
+
+    function addWidget() {
+      let n = {
+        w: Math.round(1 + 3 * Math.random()),
+        h: Math.round(1 + 3 * Math.random()),
+        content: '<button onClick="grid.removeWidget(this.parentNode.parentNode)">X</button><br>' + count++,
+      };
+      grid.addWidget(n);
+    };
+
+    function column(n) {
+      grid.column(n, layout);
+      text.innerHTML = n;
+    }
+    // dummy test method that moves items to the right each new layout... grid engine will validate those values (can't be neg or out of bounds) anyway...
+    function columnLayout(column, oldColumn, nodes, oldNodes) {
+      oldNodes.forEach(n => {
+        n.x = n.x + 1;
+        nodes.push(n);
+      });
+      oldNodes.length = 0;
+    }
+    function setLayout(name) {
+      layout = name === 'custom' ? this.columnLayout : name;
+    }
+  </script>
+</body>
+</html>
diff --git a/demo/css_attributes.html b/demo/css_attributes.html
new file mode 100644
index 000000000..68bb57330
--- /dev/null
+++ b/demo/css_attributes.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="utf-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <title>CSS & attributes demo</title>
+
+  <link rel="stylesheet" href="demo.css"/>
+  <script src="../node_modules/gridstack/dist/gridstack-all.js"></script>
+</head>
+<body>
+  <div class="container-fluid">
+    <h1>Demo showcasing how to use gridstack.js attributes in CSS</h1>
+    <p>The center of the widget shows its dimensions by purely using CSS, no JavaScript involved.</p>
+    <div>
+      <a class="btn btn-primary" onClick="addNewWidget()" href="#">Add Widget</a>
+    </div>
+    <br><br>
+    <div class="grid-stack show-dimensions"></div>
+  </div>
+  <script src="events.js"></script>
+  <script type="text/javascript">
+    let grid = GridStack.init({
+      float: true,
+      resizable: { handles: 'all'}
+    });
+    addEvents(grid);
+
+    let items = [
+      {x: 1, y: 1},
+      {x: 2, y: 2, w: 3},
+      {x: 4, y: 2},
+      {x: 3, y: 1, h: 2},
+      {x: 0, y: 6, w: 2, h: 2}
+    ];
+    let count = 0;
+
+    getNode = function() {
+      let n = items[count] || {
+        x: Math.round(12 * Math.random()),
+        y: Math.round(5 * Math.random()),
+        w: Math.round(1 + 3 * Math.random()),
+        h: Math.round(1 + 3 * Math.random())
+      };
+      n.content = n.content || String(count);
+      count++;
+      return n;
+    };
+
+    addNewWidget = function() {
+      grid.addWidget(getNode());
+    };
+
+    addNewWidget();
+  </script>
+</body>
+</html>
diff --git a/demo/custom-engine.html b/demo/custom-engine.html
new file mode 100644
index 000000000..9d4619933
--- /dev/null
+++ b/demo/custom-engine.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="utf-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <title>Custom Engine</title>
+
+  <link rel="stylesheet" href="demo.css"/>
+  <script src="../node_modules/gridstack/dist/gridstack-all.js"></script>
+  <script src="events.js"></script>
+</head>
+<body>
+  <div class="container-fluid">
+    <h1>Custom Engine</h1>
+    <p>shows a custom engine subclass in Typescript that only allows objects to move vertically.</p>
+    <div>
+      <a class="btn btn-primary" onClick="addNewWidget()" href="#">Add Widget</a>
+      <a class="btn btn-primary" onclick="toggleFloat()" id="float" href="#">float: true</a>
+    </div>
+    <br><br>
+    <div class="grid-stack"></div>
+  </div>
+
+  <script type="module" > // so we can use import
+    // get CORS error in Chrome...need to have http://localhost/ URL - see https://stackoverflow.com/questions/50197495/javascript-modules-and-cors
+    import { GridStack, GridStackEngine } from '../node_modules/gridstack/dist/gridstack-all.js';
+
+    /**
+     * Custom engine class that only allows vertical movement and resizing
+     */
+    class CustomEngine extends GridStackEngine {
+      /** refined this to move the node to the given new location */
+      moveNode(node, o) {
+        // keep the same original X and Width and let base do it all...
+        o.x = node.x;
+        o.w = node.w;
+        return super.moveNode(node, o);
+      }
+    }
+    GridStack.registerEngine(CustomEngine); // globally set our custom class
+
+    let count = 0;
+    let items = [
+      {x: 0, y: 0},
+      {x: 1, y: 0},
+      {x: 1, y: 2, w: 3},
+    ];
+    items.forEach(n => n.content = String(count++));
+
+    let grid = GridStack.init({
+      float: true, 
+      cellHeight: 70
+    }).load(items);
+    addEvents(grid);
+
+    let addNewWidget = function() {
+      let n = items[count] || {
+        x: Math.round(12 * Math.random()),
+        y: Math.round(5 * Math.random()),
+        w: Math.round(1 + 3 * Math.random()),
+        h: Math.round(1 + 3 * Math.random())
+      };
+      n.content = n.content || String(count++);
+      grid.addWidget(n);
+    };
+
+    let toggleFloat = function() {
+      grid.float(! grid.getFloat());
+      document.querySelector('#float').innerHTML = 'float: ' + grid.getFloat();
+    };
+  </script>
+</body>
+</html>
diff --git a/demo/demo.css b/demo/demo.css
new file mode 100644
index 000000000..5fbdd174c
--- /dev/null
+++ b/demo/demo.css
@@ -0,0 +1,111 @@
+/* required file for gridstack to work */
+@import "../node_modules/gridstack/dist/gridstack.min.css";
+
+/* Optional styles for demos */
+.btn-primary {
+  color: #fff;
+  background-color: #007bff;
+}
+
+.btn {
+  display: inline-block;
+  padding: .375rem .75rem;
+  line-height: 1.5;
+  border-radius: .25rem;
+}
+
+a {
+  text-decoration: none;
+}
+
+h1 {
+  font-size: 2.5rem;
+  margin-bottom: .5rem;
+}
+
+.sidebar {
+  background: rgb(215, 243, 215);
+  padding: 25px 0;
+  height: 100px;
+  text-align: center;
+}
+.sidebar > .grid-stack-item,
+.sidebar-item {
+  width: 100px;
+  height: 50px;
+  border: 2px dashed green;
+  text-align: center;
+  line-height: 35px;
+  background: rgb(192, 231, 192);
+  cursor: default;
+  display: inline-block;
+}
+
+.grid-stack {
+  background: #FAFAD2;
+}
+.grid-stack.grid-stack-static {
+  background: #eee;
+}
+
+.sidebar > .grid-stack-item,
+.grid-stack-item-content {
+  text-align: center;
+  background-color: #18bc9c;
+}
+
+.card-header {
+  margin: 0;
+  cursor: move;
+  min-height: 25px;
+  background-color: #16af91;
+}
+.card-header:hover {
+  background-color: #149b80;
+}
+
+.ui-draggable-disabled.ui-resizable-disabled > .grid-stack-item-content {
+  background-color: #777;
+}
+
+.grid-stack-item-removing {
+  opacity: 0.5;
+}
+.trash {
+  height: 100px;
+  background: rgba(255, 0, 0, 0.1) center center url(data:image/svg+xml;utf8;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pgo8IS0tIEdlbmVyYXRvcjogQWRvYmUgSWxsdXN0cmF0b3IgMTYuMC4wLCBTVkcgRXhwb3J0IFBsdWctSW4gLiBTVkcgVmVyc2lvbjogNi4wMCBCdWlsZCAwKSAgLS0+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiBpZD0iQ2FwYV8xIiB4PSIwcHgiIHk9IjBweCIgd2lkdGg9IjY0cHgiIGhlaWdodD0iNjRweCIgdmlld0JveD0iMCAwIDQzOC41MjkgNDM4LjUyOSIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgNDM4LjUyOSA0MzguNTI5OyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+CjxnPgoJPGc+CgkJPHBhdGggZD0iTTQxNy42ODksNzUuNjU0Yy0xLjcxMS0xLjcwOS0zLjkwMS0yLjU2OC02LjU2My0yLjU2OGgtODguMjI0TDMwMi45MTcsMjUuNDFjLTIuODU0LTcuMDQ0LTcuOTk0LTEzLjA0LTE1LjQxMy0xNy45ODkgICAgQzI4MC4wNzgsMi40NzMsMjcyLjU1NiwwLDI2NC45NDUsMGgtOTEuMzYzYy03LjYxMSwwLTE1LjEzMSwyLjQ3My0yMi41NTQsNy40MjFjLTcuNDI0LDQuOTQ5LTEyLjU2MywxMC45NDQtMTUuNDE5LDE3Ljk4OSAgICBsLTE5Ljk4NSw0Ny42NzZoLTg4LjIyYy0yLjY2NywwLTQuODUzLDAuODU5LTYuNTY3LDIuNTY4Yy0xLjcwOSwxLjcxMy0yLjU2OCwzLjkwMy0yLjU2OCw2LjU2N3YxOC4yNzQgICAgYzAsMi42NjQsMC44NTUsNC44NTQsMi41NjgsNi41NjRjMS43MTQsMS43MTIsMy45MDQsMi41NjgsNi41NjcsMi41NjhoMjcuNDA2djI3MS44YzAsMTUuODAzLDQuNDczLDI5LjI2NiwxMy40MTgsNDAuMzk4ICAgIGM4Ljk0NywxMS4xMzksMTkuNzAxLDE2LjcwMywzMi4yNjQsMTYuNzAzaDIzNy41NDJjMTIuNTY2LDAsMjMuMzE5LTUuNzU2LDMyLjI2NS0xNy4yNjhjOC45NDUtMTEuNTIsMTMuNDE1LTI1LjE3NCwxMy40MTUtNDAuOTcxICAgIFYxMDkuNjI3aDI3LjQxMWMyLjY2MiwwLDQuODUzLTAuODU2LDYuNTYzLTIuNTY4YzEuNzA4LTEuNzA5LDIuNTctMy45LDIuNTctNi41NjRWODIuMjIxICAgIEM0MjAuMjYsNzkuNTU3LDQxOS4zOTcsNzcuMzY3LDQxNy42ODksNzUuNjU0eiBNMTY5LjMwMSwzOS42NzhjMS4zMzEtMS43MTIsMi45NS0yLjc2Miw0Ljg1My0zLjE0aDkwLjUwNCAgICBjMS45MDMsMC4zODEsMy41MjUsMS40Myw0Ljg1NCwzLjE0bDEzLjcwOSwzMy40MDRIMTU1LjMxMUwxNjkuMzAxLDM5LjY3OHogTTM0Ny4xNzMsMzgwLjI5MWMwLDQuMTg2LTAuNjY0LDguMDQyLTEuOTk5LDExLjU2MSAgICBjLTEuMzM0LDMuNTE4LTIuNzE3LDYuMDg4LTQuMTQxLDcuNzA2Yy0xLjQzMSwxLjYyMi0yLjQyMywyLjQyNy0yLjk5OCwyLjQyN0gxMDAuNDkzYy0wLjU3MSwwLTEuNTY1LTAuODA1LTIuOTk2LTIuNDI3ICAgIGMtMS40MjktMS42MTgtMi44MS00LjE4OC00LjE0My03LjcwNmMtMS4zMzEtMy41MTktMS45OTctNy4zNzktMS45OTctMTEuNTYxVjEwOS42MjdoMjU1LjgxNVYzODAuMjkxeiIgZmlsbD0iI2ZmOWNhZSIvPgoJCTxwYXRoIGQ9Ik0xMzcuMDQsMzQ3LjE3MmgxOC4yNzFjMi42NjcsMCw0Ljg1OC0wLjg1NSw2LjU2Ny0yLjU2N2MxLjcwOS0xLjcxOCwyLjU2OC0zLjkwMSwyLjU2OC02LjU3VjE3My41ODEgICAgYzAtMi42NjMtMC44NTktNC44NTMtMi41NjgtNi41NjdjLTEuNzE0LTEuNzA5LTMuODk5LTIuNTY1LTYuNTY3LTIuNTY1SDEzNy4wNGMtMi42NjcsMC00Ljg1NCwwLjg1NS02LjU2NywyLjU2NSAgICBjLTEuNzExLDEuNzE0LTIuNTY4LDMuOTA0LTIuNTY4LDYuNTY3djE2NC40NTRjMCwyLjY2OSwwLjg1NCw0Ljg1MywyLjU2OCw2LjU3QzEzMi4xODYsMzQ2LjMxNiwxMzQuMzczLDM0Ny4xNzIsMTM3LjA0LDM0Ny4xNzJ6IiBmaWxsPSIjZmY5Y2FlIi8+CgkJPHBhdGggZD0iTTIxMC4xMjksMzQ3LjE3MmgxOC4yNzFjMi42NjYsMCw0Ljg1Ni0wLjg1NSw2LjU2NC0yLjU2N2MxLjcxOC0xLjcxOCwyLjU2OS0zLjkwMSwyLjU2OS02LjU3VjE3My41ODEgICAgYzAtMi42NjMtMC44NTItNC44NTMtMi41NjktNi41NjdjLTEuNzA4LTEuNzA5LTMuODk4LTIuNTY1LTYuNTY0LTIuNTY1aC0xOC4yNzFjLTIuNjY0LDAtNC44NTQsMC44NTUtNi41NjcsMi41NjUgICAgYy0xLjcxNCwxLjcxNC0yLjU2OCwzLjkwNC0yLjU2OCw2LjU2N3YxNjQuNDU0YzAsMi42NjksMC44NTQsNC44NTMsMi41NjgsNi41N0MyMDUuMjc0LDM0Ni4zMTYsMjA3LjQ2NSwzNDcuMTcyLDIxMC4xMjksMzQ3LjE3MnogICAgIiBmaWxsPSIjZmY5Y2FlIi8+CgkJPHBhdGggZD0iTTI4My4yMiwzNDcuMTcyaDE4LjI2OGMyLjY2OSwwLDQuODU5LTAuODU1LDYuNTctMi41NjdjMS43MTEtMS43MTgsMi41NjItMy45MDEsMi41NjItNi41N1YxNzMuNTgxICAgIGMwLTIuNjYzLTAuODUyLTQuODUzLTIuNTYyLTYuNTY3Yy0xLjcxMS0xLjcwOS0zLjkwMS0yLjU2NS02LjU3LTIuNTY1SDI4My4yMmMtMi42NywwLTQuODUzLDAuODU1LTYuNTcxLDIuNTY1ICAgIGMtMS43MTEsMS43MTQtMi41NjYsMy45MDQtMi41NjYsNi41Njd2MTY0LjQ1NGMwLDIuNjY5LDAuODU1LDQuODUzLDIuNTY2LDYuNTdDMjc4LjM2NywzNDYuMzE2LDI4MC41NSwzNDcuMTcyLDI4My4yMiwzNDcuMTcyeiIgZmlsbD0iI2ZmOWNhZSIvPgoJPC9nPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+Cjwvc3ZnPgo=) no-repeat;
+}
+
+/* make nested grid have slightly darker bg take almost all space (need some to tell them apart) so items inside can have similar to external size+margin */
+.grid-stack > .grid-stack-item.grid-stack-sub-grid > .grid-stack-item-content {
+  background: rgba(0,0,0,0.1);
+  inset: 0 2px;
+}
+.grid-stack.grid-stack-nested {
+  background: none;
+  inset: 0;
+}
+
+.grid-stack.show-dimensions .grid-stack-item:after {
+   content: '1x1';
+   position: absolute;
+   top: 50%;
+   left: 50%;
+   transform: translate(-50%, -50%);
+   padding: 2px;
+   color: black;
+   background-color: white;
+   pointer-events: none; /* to not interfere with dragging the item */
+}
+
+.grid-stack.show-dimensions .grid-stack-item[gs-h]::after {
+   content: '1x' attr(gs-h);
+}
+
+.grid-stack.show-dimensions .grid-stack-item[gs-w]::after {
+   content: attr(gs-w) 'x1';
+}
+
+.grid-stack.show-dimensions .grid-stack-item[gs-h][gs-w]::after {
+   content: attr(gs-w) 'x' attr(gs-h);
+}
diff --git a/demo/esmodule.html b/demo/esmodule.html
new file mode 100644
index 000000000..228266b43
--- /dev/null
+++ b/demo/esmodule.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="utf-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <title>ES Module demo</title>
+
+  <link rel="stylesheet" href="demo.css"/>
+
+</head>
+<body>
+  <h1>ES Module loading demo</h1>
+  <div class="grid-stack"></div>
+
+  <!-- loading GS as an ES module instead of commonjs all.js. doesn't work (see #2476) and get CORS error locally -->
+  <script type="module">
+    import { GridStack } from '../node_modules/gridstack/dist/gridstack.js';
+
+    let items = [{x: 1, y: 1}, {x: 2, y: 2, w: 3}];
+    let count = 0;
+    items.forEach(e => e.content = String(count++));
+
+    GridStack.init({float: true}).load(items);
+  </script>
+</body>
+</html>
diff --git a/demo/events.js b/demo/events.js
new file mode 100644
index 000000000..bca7ae3f8
--- /dev/null
+++ b/demo/events.js
@@ -0,0 +1,59 @@
+function addEvents(grid, id) {
+  let g = (id !== undefined ? 'grid' + id : '');
+
+  grid.on('added removed change', function(event, items) {
+    let str = '';
+    items.forEach(function(item) { str += ' (' + item.x + ',' + item.y + ' ' + item.w + 'x' + item.h + ')'; });
+    console.log((g || items[0].grid.opts.id) + ' ' + event.type + ' ' + items.length + ' items (x,y w h):' + str );
+  })
+  .on('enable', function(event) {
+    let el = event.target;
+    console.log((g || el.gridstackNode.grid.opts.id) + ' enable');
+  })
+  .on('disable', function(event) {
+    let el = event.target;
+    console.log((g || el.gridstackNode.grid.opts.id) + ' disable');
+  })
+  .on('dragstart', function(event, el) {
+    let n = el.gridstackNode;
+    let x = el.getAttribute('gs-x'); // verify node (easiest) and attr are the same
+    let y = el.getAttribute('gs-y');
+    console.log((g || el.gridstackNode.grid.opts.id) + ' dragstart ' + (n.content || '') + ' pos: (' + n.x + ',' + n.y + ') = (' + x + ',' + y + ')');
+  })
+  .on('drag', function(event, el) {
+    let n = el.gridstackNode;
+    let x = el.getAttribute('gs-x'); // verify node (easiest) and attr are the same
+    let y = el.getAttribute('gs-y');
+    // console.log((g || el.gridstackNode.grid.opts.id) + ' drag ' + (n.content || '') + ' pos: (' + n.x + ',' + n.y + ') = (' + x + ',' + y + ')');
+  })
+  .on('dragstop', function(event, el) {
+    let n = el.gridstackNode;
+    let x = el.getAttribute('gs-x'); // verify node (easiest) and attr are the same
+    let y = el.getAttribute('gs-y');
+    console.log((g || el.gridstackNode.grid.opts.id) + ' dragstop ' + (n.content || '') + ' pos: (' + n.x + ',' + n.y + ') = (' + x + ',' + y + ')');
+  })
+  .on('dropped', function(event, previousNode, newNode) {
+    if (previousNode) {
+      console.log((g || previousNode.grid.opts.id) + ' dropped - Removed widget from grid:', previousNode);
+    }
+    if (newNode) {
+      console.log((g || newNode.grid.opts.id) + ' dropped - Added widget in grid:', newNode);
+    }
+  })
+  .on('resizestart', function(event, el) {
+    let n = el.gridstackNode;
+    let rec = el.getBoundingClientRect();
+    console.log(`${g || el.gridstackNode.grid.opts.id} resizestart ${n.content || ''} size: (${n.w}x${n.h}) = (${Math.round(rec.width)}x${Math.round(rec.height)})px`);
+
+  })
+  .on('resize', function(event, el) {
+    let n = el.gridstackNode;
+    let rec = el.getBoundingClientRect();
+    console.log(`${g || el.gridstackNode.grid.opts.id} resize ${n.content || ''} size: (${n.w}x${n.h}) = (${Math.round(rec.width)}x${Math.round(rec.height)})px`);
+  })
+  .on('resizestop', function(event, el) {
+    let n = el.gridstackNode;
+    let rec = el.getBoundingClientRect();
+    console.log(`${g || el.gridstackNode.grid.opts.id} resizestop ${n.content || ''} size: (${n.w}x${n.h}) = (${Math.round(rec.width)}x${Math.round(rec.height)})px`);
+  });
+}
\ No newline at end of file
diff --git a/demo/float.html b/demo/float.html
new file mode 100644
index 000000000..8ed725d6b
--- /dev/null
+++ b/demo/float.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="utf-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <title>Float grid demo</title>
+
+  <link rel="stylesheet" href="demo.css"/>
+  <script src="../node_modules/gridstack/dist/gridstack-all.js"></script>
+
+</head>
+<body>
+  <div class="container-fluid">
+    <h1>Float grid demo</h1>
+    <div>
+      <a class="btn btn-primary" onClick="addNewWidget()" href="#">Add Widget</a>
+      <a class="btn btn-primary" onClick="makeNewWidget()" href="#">Make Widget</a>
+      <a class="btn btn-primary" onclick="toggleFloat()" id="float" href="#">float: true</a>
+    </div>
+    <br><br>
+    <div class="grid-stack"></div>
+  </div>
+  <script src="events.js"></script>
+  <script type="text/javascript">
+    let grid = GridStack.init({
+      float: true, 
+      // disableResize: true, // TEST no resizing, but dragging
+      resizable: { handles: 'all'} // do all sides for testing
+    });
+    addEvents(grid);
+
+    let items = [
+      {x: 1, y: 1}, //, locked:true, content:"locked"},
+      {x: 2, y: 2, w: 3},
+      {x: 4, y: 2},
+      {x: 3, y: 1, h: 2},
+      {x: 0, y: 6, w: 2, h: 2}
+    ];
+    let count = 0;
+
+    getNode = function() {
+      let n = items[count] || {
+        x: Math.round(12 * Math.random()),
+        y: Math.round(5 * Math.random()),
+        w: Math.round(1 + 3 * Math.random()),
+        h: Math.round(1 + 3 * Math.random())
+      };
+      n.content = n.content || String(count);
+      count++;
+      return n;
+    };
+
+    addNewWidget = function() {
+      let w = grid.addWidget(getNode());
+    };
+
+    makeNewWidget = function() {
+      let n = getNode();
+      let doc = document.implementation.createHTMLDocument();
+      doc.body.innerHTML = `<div class="item" gs-x="${n.x}" gs-y="${n.y}" gs-w="${n.w || 1}" gs-h="${n.h || 1}"><div class="grid-stack-item-content">${n.content}</div></div>`;
+      let el = doc.body.children[0];
+      grid.el.appendChild(el);
+      // example showing when DOM is created elsewhere (eg Angular/Vue/React) and GS is used to convert to a widget
+      let w = grid.makeWidget(el);
+    };
+
+    toggleFloat = function() {
+      grid.float(! grid.getFloat());
+      document.querySelector('#float').innerHTML = 'float: ' + grid.getFloat();
+    };
+    addNewWidget();
+  </script>
+</body>
+</html>
diff --git a/demo/index.html b/demo/index.html
new file mode 100644
index 000000000..ed3b6b780
--- /dev/null
+++ b/demo/index.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+  <meta charset="utf-8">
+  <title>Demo</title>
+</head>
+
+<body>
+  <h1>Demos</h1>
+  <ul>
+    <li><a href="anijs.html">AniJS</a></li>
+    <li><a href="cell-height.html">Cell Height</a></li>
+    <li><a href="column.html">Column</a></li>
+    <li><a href="css_attributes.html">CSS & attributes</a></li>
+    <!-- <li><a href="esmodule.html">ES Module test</a></li> -->
+    <li><a href="float.html">Float grid</a></li>
+    <li><a href="knockout.html">Knockout.js</a></li>
+    <li><a href="lazy_load.html">Lazy Load</a></li>
+    <li><a href="mobile.html">Mobile touch</a></li>
+    <li><a href="nested.html">Nested grids</a></li>
+    <li><a href="nested_advanced.html">Nested Advanced grids</a></li>
+    <li><a href="nested_constraint.html">Nested Constraint grids</a></li>
+    <li><a href="react-hooks-controlled-multiple.html">ReactJS (Hooks), multiple grid, controlled (NOT Ideal)</a></li>
+    <li><a href="react-hooks.html">ReactJS (Hooks)</a></li>
+    <li><a href="react.html">ReactJS</a></li>
+    <li><a href="responsive.html">Responsive: by column size</a></li>
+    <li><a href="responsive_break.html">Responsive: using breakpoints</a></li>
+    <li><a href="responsive_none.html">Responsive: using layout:'none'</a></li>
+    <li><a href="right-to-left(rtl).html">Right-To-Left (RTL)</a></li>
+    <li><a href="serialization.html">Serialization</a></li>
+    <li><a href="sizeToContent.html">Size To Content</a></li>
+    <li><a href="static.html">Static</a></li>
+    <li><a href="title_drag.html">Title drag</a></li>
+    <li><a href="transform.html">Transform (scale+offset)</a></li>
+    <li><a href="two.html">Two grids</a></li>
+    <li><a href="two_vertical.html">Two grids Vertical</a></li>
+    <li><a href="vue2js.html">Vue2.js</a></li>
+    <li><a href="vue3js.html">Vue3.js</a></li>
+    <li><a href="vue3js_dynamic-render_grid-item-content.html">Vue3: Gridstack Controls Vue Rendering Grid Item Content</a></li>
+    <li><a href="vue3js_dynamic-render_grid-item.html">Vue3: Gridstack Controls Vue Rendering Grid Item</a></li>
+    <li><a href="vue3js_v-for.html">Vue3 with v-for</a></li>
+    <li><a href="vue3js_dynamic-modern-renderCB.html">Vue3: Render GridStack item content using GridStack.renderCB</a></li>
+    <li><a href="web-comp.html">Web Component</a></li>
+    <li><a href="web1.html">Website demo 1</a></li>
+    <li><a href="web2.html">Website demo 2</a></li>
+  </ul>
+  <h1>Angular wrapper</h1>
+  <p>We now ship an <a href="https://github.com/gridstack/gridstack.js/tree/master/angular/" target="_blank">Angular Component</a>
+    to make it supper easy for that framework</p>
+  <h1>React wrapper</h1>
+  <p>React original examples are shown above, but upcoming and better TS based <a href="https://github.com/gridstack/gridstack.js/tree/master/react/" target="_blank">/react</a> folder (working to make that official and ship it) should be looked at instead. </p>
+  <h1>Old v5.1.1 Jquery Demos</h1>
+  Note: those are no longer supported, and use an old version of the lib to compare functionality.
+  <ul>
+    <li><a href="old_two-jq.html">Two grids</a></li>
+    <li><a href="old_nested-jq.html">Nested grids</a></li>
+  </ul>
+</body>
+
+</html>
diff --git a/demo/knockout.html b/demo/knockout.html
new file mode 100644
index 000000000..108f8bf83
--- /dev/null
+++ b/demo/knockout.html
@@ -0,0 +1,92 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="utf-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <title>Knockout.js demo</title>
+
+  <link rel="stylesheet" href="demo.css"/>
+
+  <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.5.0/knockout-debug.js"></script>
+  <script src="../node_modules/gridstack/dist/gridstack-all.js"></script>
+</head>
+<body>
+  <div class="container-fluid">
+    <h1>knockout.js Demo</h1>
+    <div>
+      <a class="btn btn-primary" data-bind="click: addNewWidget">Add Widget</a>
+    </div>
+    <br>
+    <div data-bind="component: {name: 'dashboard-grid', params: $data}"></div>
+  </div>
+
+  <script type="text/javascript">
+    ko.components.register('dashboard-grid', {
+      viewModel: {
+        createViewModel: function (controller, componentInfo) {
+          let ViewModel = function (controller, componentInfo) {
+            let grid = null;
+
+            this.widgets = controller.widgets;
+
+            this.afterAddWidget = function (items) {
+              if (!grid ) {
+                grid = GridStack.init({auto: false});
+              }
+
+              let item = items.find(function (i) { return i.nodeType == 1 });
+              grid.makeWidget(item);
+              ko.utils.domNodeDisposal.addDisposeCallback(item, function () {
+                grid.removeWidget(item);
+              });
+            };
+          };
+
+          return new ViewModel(controller, componentInfo);
+        }
+      },
+      template:
+        [
+          '<div class="grid-stack" data-bind="foreach: {data: widgets, afterRender: afterAddWidget}">',
+          '   <div class="grid-stack-item" data-bind="attr: {\'gs-x\': $data.x, \'gs-y\': $data.y, \'gs-w\': $data.w, \'gs-h\': $data.h, \'gs-auto-position\': $data.auto_position, \'gs-id\': $data.id}">',
+          '     <div class="grid-stack-item-content"><button data-bind="click: $root.deleteWidget">Delete me</button></div>',
+          '   </div>',
+          '</div> '
+        ].join('')
+    });
+
+    let Controller = function (widgets) {
+      let self = this;
+
+      this.widgets = ko.observableArray(widgets);
+
+      this.addNewWidget = function () {
+        this.widgets.push({
+          x: 0,
+          y: 0,
+          w: Math.floor(1 + 3 * Math.random()),
+          h: Math.floor(1 + 3 * Math.random()),
+          auto_position: true
+        });
+        return false;
+      };
+
+      this.deleteWidget = function (item) {
+        self.widgets.remove(item);
+        return false;
+      };
+    };
+
+    let widgets = [
+      {x: 0, y: 0, w: 2, h: 2, id: '0'},
+      {x: 2, y: 0, w: 4, h: 2, id: '1'},
+      {x: 6, y: 0, w: 2, h: 4, id: '2'},
+      {x: 1, y: 2, w: 4, h: 2, id: '3'}
+    ];
+
+    let controller = new Controller(widgets);
+    ko.applyBindings(controller);
+  </script>
+</body>
+</html>
diff --git a/demo/lazy_load.html b/demo/lazy_load.html
new file mode 100644
index 000000000..5d967b6f9
--- /dev/null
+++ b/demo/lazy_load.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="utf-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <title>Lazy loading demo</title>
+
+  <link rel="stylesheet" href="demo.css"/>
+  <script src="../node_modules/gridstack/dist/gridstack-all.js"></script>
+</head>
+<body>
+  <div>
+    <h1>Lazy loading + renderCB demo</h1>
+    <p>New V11 GridStackWidget.lazyLoad feature. open console and see widget content (or angular components) created as they become visible.</p>
+    <div style="height: 300px; overflow-y: auto">
+      <div class="grid-stack"></div>
+    </div>
+  </div>
+  <script type="text/javascript">
+    // print when widgets are created, verify dragging by newly added content
+    GridStack.renderCB = function(el, w) {
+      const title = document.createElement('h3');
+      title.textContent = 'Drag me by title';
+      title.className = 'card-header';
+      el.appendChild(title);
+      const div = document.createElement('div');
+      div.textContent = w.id;
+      el.appendChild(div);
+      console.log('created node id ', w.id);
+    };
+
+    let children = [];
+    for (let y = 0; y <= 5; y++) children.push({x:0, y, id:String(y), content: String(y)});
+    
+    let grid = GridStack.init({
+      cellHeight: 200,
+      children,
+      lazyLoad: true,  // delay creation until visible
+      handle: '.card-header',
+    });
+  </script>
+</body>
+</html>
diff --git a/demo/locked.html b/demo/locked.html
new file mode 100644
index 000000000..8561e0c33
--- /dev/null
+++ b/demo/locked.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="utf-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <title>Locked demo</title>
+
+  <link rel="stylesheet" href="demo.css"/>
+  <script src="../node_modules/gridstack/dist/gridstack-all.js"></script>
+  </style>
+</head>
+<body>
+  <div class="container-fluid">
+    <h1>Locked demo</h1>
+    <div>
+      <a class="btn btn-primary" onClick="addNewWidget()" href="#">Add Widget</a>
+      <a class="btn btn-primary" onclick="toggleFloat()" id="float" href="#">float: true</a>
+    </div>
+    <br><br>
+    <div class="grid-stack"></div>
+  </div>
+
+  <script type="text/javascript">
+    let grid = GridStack.init({float: true});
+
+    grid.on('added removed change', function(e, items) {
+      let str = '';
+      items.forEach(function(item) { str += ' (x,y)=' + item.x + ',' + item.y; });
+      console.log(e.type + ' ' + items.length + ' items:' + str );
+    });
+
+    let items = [
+      {x: 0, y: 1, w: 12, locked: 'yes', noMove: true, noResize: true, text: 'locked, noResize, noMove'},
+      {x: 1, y: 0, w: 2, h: 3},
+      {x: 4, y: 2},
+      {x: 3, y: 1, h: 2},
+      {x: 0, y: 6, w: 2, h: 2}
+    ];
+    let count = 0;
+
+    addNewWidget = function() {
+      let n = items[count] || {
+        x: Math.round(12 * Math.random()),
+        y: Math.round(5 * Math.random()),
+        w: Math.round(1 + 3 * Math.random()),
+        h: Math.round(1 + 3 * Math.random())
+      };
+      n.content = n.text ? n.text : String(count);
+      grid.addWidget(n);
+      count++
+    };
+
+    toggleFloat = function() {
+      grid.float(! grid.float());
+      document.querySelector('#float').innerHTML = 'float: ' + grid.float();
+    };
+    addNewWidget();
+  </script>
+</body>
+</html>
diff --git a/demo/mobile.html b/demo/mobile.html
new file mode 100644
index 000000000..78dcb0c30
--- /dev/null
+++ b/demo/mobile.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="utf-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <title>Simple mobile demo</title>
+
+  <link rel="stylesheet" href="demo.css"/>
+  <script src="../node_modules/gridstack/dist/gridstack-all.js"></script>
+
+</head>
+<body>
+  <h1>Simple mobile demo</h1>
+  <p>shows resize handle on mobile and support native touch events</p>
+  <div class="grid-stack"></div>
+  <script type="text/javascript">
+    let grid = GridStack.init({
+      column: 3,
+    });
+    grid.load([{x:0, y:0, content: '1'}, {x:1, y:0, h:2, content: '2'}, {x:2, y:0, content: '3'}])
+  </script>
+</body>
+</html>
diff --git a/demo/nested.html b/demo/nested.html
new file mode 100644
index 000000000..9f3618e39
--- /dev/null
+++ b/demo/nested.html
@@ -0,0 +1,140 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="utf-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <title>Nested grids demo</title>
+  <link rel="stylesheet" href="demo.css"/>
+  <script src="../node_modules/gridstack/dist/gridstack-all.js"></script>
+</head>
+<body>
+  <div class="container-fluid">
+    <h1>Nested grids demo</h1>
+    <p>This example shows v5.x dragging between nested grids (dark yellow) and parent grid (bright yellow.)<br>
+      Use v9.2 <b>sizeToContent:true</b> on first subgrid item parent to grow/shrink as needed, while leaving leaf green items unchanged.<br>
+      Uses v3.1 API to load the entire nested grid from JSON.<br>
+      Nested grids uses v5 <b>column:'auto'</b> to keep items same size during resize.</p>
+    <div class="actions" style="display: flex; flex-direction: row; gap: 5px;">
+      <a class="btn btn-primary" onClick="addWidget()" href="#">Add Widget</a>
+      <a class="btn btn-primary" onClick="addNewWidget('.sub1')" href="#">Add Widget Grid1</a>
+      <a class="btn btn-primary" onClick="addNewWidget('.sub2')" href="#">Add Widget Grid2</a>
+      <a class="btn btn-primary" onClick="addNested()" href="#">Add Nested Grid</a>
+      <!-- add .grid-stack-item for acceptWidgets:true -->
+      <div class="sidebar-item grid-stack-item">Drag nested</div>
+    </div>
+    <br />
+    <div>
+      <span>Grid Mode: </span>
+      <input type="radio" id="static" name="mode" value="true" onClick="setStatic(true)"><label for="static">static</label>
+      <input type="radio" id="edit" name="mode" value="false" checked onClick="setStatic(false)"><label for="edit">editable</label>
+    </div>
+    <span>entire save/re-create:</span>
+    <a class="btn btn-primary" onClick="save()" href="#">Save</a>
+    <a class="btn btn-primary" onClick="destroy()" href="#">Destroy</a>
+    <a class="btn btn-primary" onClick="load()" href="#">Create</a>
+    <span>partial save/load:</span>
+    <a class="btn btn-primary" onClick="save(true, false)" href="#">Save list</a>
+    <a class="btn btn-primary" onClick="save(false, false)" href="#">Save no content</a>
+    <a class="btn btn-primary" onClick="destroy(false)" href="#">Clear</a>
+    <a class="btn btn-primary" onClick="load(false)" href="#">Load</a>
+    <br><br>
+    <!-- grid will be added here -->
+  </div>
+  <script src="events.js"></script>
+  <script type="text/javascript">
+    // NOTE: REAL apps would sanitize-html or DOMPurify before blinding setting innerHTML. see #2736
+    GridStack.renderCB = function(el, w) {
+      if (w.content) el.innerHTML = w.content;
+    };
+
+    let staticGrid = false;
+    let sub1 = [ {x:0, y:0}, {x:1, y:0}, {x:2, y:0}, {x:3, y:0}, {x:0, y:1}, {x:1, y:1}];
+    let sub2 = [ {x:0, y:0, h:2}, {x:1, y:1, w:2}];
+    let count = 0;
+    [...sub1, ...sub2].forEach(d => d.content = String(count++));
+    let options = { // main grid options
+      staticGrid, // test - force children to inherit too if we set to true above ^^^
+      // disableDrag: true,
+      // disableResize: true,
+      cellHeight: 50,
+      margin: 5,
+      minRow: 2, // don't collapse when empty
+      acceptWidgets: true,
+      id: 'main',
+      resizable: { handles: 'se,e,s,sw,w'},
+      // subGridOpts, // options for all subgrids, but defaults to column='auto' now so no need.
+      children: [
+        {x:0, y:0, content: 'regular item'},
+        {x:1, y:0, w:4, h:4, sizeToContent: true, content: '<div>nested grid sizeToContent:true with some header content</div>', subGridOpts: {children: sub1, id:'sub1_grid', class: 'sub1'}},
+        {x:5, y:0, w:3, h:4, subGridOpts: {children: sub2, id:'sub2_grid', class: 'sub2'}},
+      ]
+    };
+
+    // create and load it all from JSON above
+    let grid = GridStack.addGrid(document.querySelector('.container-fluid'), options);
+
+    // add debug event handlers to main grid (new v12.1 handles sub-grids too)
+    addEvents(grid);
+
+    // setup drag drop behavior
+    let sidebarContent = [
+     { w:2, h:2, subGridOpts: { children: [{content: 'nest 1'}, {content: 'nest 2'}]}}
+    ];
+    GridStack.setupDragIn('.sidebar-item', undefined, sidebarContent);
+
+    function setStatic(val) {
+      staticGrid = val;
+      grid.setStatic(staticGrid);
+    }
+
+    function addWidget() {
+      grid.addWidget({x:0, y:100, content:"new item"});
+    }
+
+    function addNested() {
+      grid.addWidget({x:0, y:100, sizeToContent: true, subGridOpts: {
+        children: [ {content: 'hello'}, {y:1, content: 'world'}],
+        ...subOptions}
+      });
+    }
+
+    function addNewWidget(selector) {
+      let subGrid = document.querySelector(selector).gridstack;
+      let node = {
+        x: Math.round(6 * Math.random()),
+        y: Math.round(5 * Math.random()),
+        w: Math.round(1 + 1 * Math.random()),
+        h: Math.round(1 + 1 * Math.random()),
+        content: String(count++)
+      };
+      subGrid.addWidget(node);
+      return false;
+    };
+
+    //--- end of Drag and Drop Nested widget logic
+
+    function save(content = true, full = true) {
+      options = grid.save(content, full);
+      console.log(options);
+      // console.log(JSON.stringify(options));
+    }
+    function destroy(full = true) {
+      if (full) {
+        grid.off('dropped');
+        grid.destroy();
+        grid = undefined;
+      } else {
+        grid.removeAll();
+      }
+    }
+    function load(full = true) {
+      if (full) {
+        grid = GridStack.addGrid(document.querySelector('.container-fluid'), options);
+      } else {
+        grid.load(options);
+      }
+    }
+  </script>
+</body>
+</html>
diff --git a/demo/nested_advanced.html b/demo/nested_advanced.html
new file mode 100644
index 000000000..0b29f67fb
--- /dev/null
+++ b/demo/nested_advanced.html
@@ -0,0 +1,117 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="utf-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <title>Advance Nested grids demo</title>
+  <link rel="stylesheet" href="demo.css"/>
+  <!-- test using CSS rather than minRow -->
+  <style type="text/css">
+    .container-fluid > .grid-stack { min-height: 250px}
+  </style>
+  <script src="../node_modules/gridstack/dist/gridstack-all.js"></script>
+</head>
+<body>
+  <div class="container-fluid">
+    <h1>Advanced Nested grids demo</h1>
+    <p>Create sub-grids (darker background) on the fly, by dragging items completely over others (nest) vs partially (push) using
+      the new v7 API <code>GridStackOptions.subGridDynamic=true</code></p>
+    <p>This will use the new delay drag&drop option <code>DDDragOpt.pause</code> to tell the gesture difference</p>
+    <a class="btn btn-primary" onClick="addMainWidget()" href="#">Add Widget</a>
+    <a class="btn btn-primary" onClick="addNewWidget(0)" href="#">Add W Grid0</a>
+    <a class="btn btn-primary" onClick="addNewWidget(1)" href="#">Add W Grid1</a>
+    <a class="btn btn-primary" onClick="addNewWidget(2)" href="#">Add W Grid2</a>
+    <span>entire option+layout:</span>
+    <a class="btn btn-primary" onClick="save()" href="#">Save Full</a>
+    <a class="btn btn-primary" onClick="destroy()" href="#">Destroy</a>
+    <a class="btn btn-primary" onClick="load()" href="#">Re-create</a>
+    <span>layout list:</span>
+    <a class="btn btn-primary" onClick="save(true, false)" href="#">Save layout</a>
+    <a class="btn btn-primary" onClick="save(false, false)" href="#">Save layout no content</a>
+    <a class="btn btn-primary" onClick="destroy(false)" href="#">Clear</a>
+    <a class="btn btn-primary" onClick="load(false)" href="#">Load</a>
+    <br><br>
+    <!-- grid will be added here -->
+  </div>
+  <p>Output</p>
+  <textarea id="saved" style="width:100%; height:200px;"></textarea>
+  <script type="text/javascript">
+    let subOptions = {
+      cellHeight: 50, // should be 50 - top/bottom
+      column: 'auto', // size to match container
+      acceptWidgets: true, // will accept .grid-stack-item by default
+      margin: 5,
+      subGridDynamic: true, // make it recursive for all future sub-grids
+    };
+    let main = [{x:0, y:0}, {x:0, y:1}, {x:1, y:0}]
+    let sub1 = [{x:0, y:0}];
+    let sub0 = [{x:0, y:0}, {x:1, y:0}];
+    // let sub0 = [{x:0, y:0}, {x:1, y:0}, {x:1, y:1, h:2, subGridOpts: {children: sub1, ...subOptions}}];
+    let options = { // main grid options
+      cellHeight: 50,
+      margin: 5,
+      minRow: 2, // don't collapse when empty
+      acceptWidgets: true,
+      subGridOpts: subOptions,
+      subGridDynamic: true, // v7 api to create sub-grids on the fly
+      children: [
+        ...main,
+        {x:2, y:0, w:2, h:3, id: 'sub0', subGridOpts: {children: sub0, ...subOptions}},
+        {x:4, y:0, h:2, id: 'sub1', subGridOpts: {children: sub1, ...subOptions}},
+        // {x:2, y:0, w:2, h:3, subGridOpts: {children: [...sub1, {x:0, y:1, subGridOpts: subOptions}], ...subOptions}/*,content: "<div>nested grid here</div>"*/},
+      ]
+    };
+    let count = 0;
+    // create unique ids+content so we can incrementally load() and not re-create anything (updates)
+    [...main, ...sub0, ...sub1].forEach(d => d.id = d.content = String(count++));
+
+    // create and load it all from JSON above
+    document.querySelector('#saved').value = JSON.stringify(options);
+    let grid = GridStack.addGrid(document.querySelector('.container-fluid'), options);
+
+    function addMainWidget() {
+      grid.addWidget({x:0, y:100, content:"new item"});
+    }
+
+    function addNewWidget(i) {
+      let subGrid = document.querySelectorAll('.grid-stack-nested')[i]?.gridstack;
+      if (!subGrid) return;
+      let node = {
+        // x: Math.round(6 * Math.random()),
+        // y: Math.round(5 * Math.random()),
+        // w: Math.round(1 + 1 * Math.random()),
+        // h: Math.round(1 + 1 * Math.random()),
+        content: String(count++)
+      };
+      subGrid.addWidget(node);
+      return false;
+    };
+
+    function save(content = true, full = true) {
+      options = grid?.save(content, full);
+      console.log(options);
+      document.querySelector('#saved').value = JSON.stringify(options);
+    }
+    function destroy(full = true) {
+      if (!grid) return;
+      if (full) {
+        grid.destroy();
+        grid = undefined;
+      } else {
+        grid.removeAll();
+      }
+    }
+    function load(full = true) {
+      // destroy(full); // in case user didn't call
+      if (full || !grid) {
+        grid = GridStack.addGrid(document.querySelector('.container-fluid'), options);
+      } else {
+        grid.load(options);
+      }
+    }
+
+    // save(true, false); load(false); // TESTing
+  </script>
+</body>
+</html>
diff --git a/demo/nested_constraint.html b/demo/nested_constraint.html
new file mode 100644
index 000000000..763d57bc6
--- /dev/null
+++ b/demo/nested_constraint.html
@@ -0,0 +1,105 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="utf-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <title>Constraint nested grids demo</title>
+  <link rel="stylesheet" href="demo.css"/>
+  <script src="../node_modules/gridstack/dist/gridstack-all.js"></script>
+  <style type="text/css">
+    .grid-stack-item.sub .grid-stack-item-content {
+      background: lightpink;
+    }
+  </style>
+</head>
+<body>
+  <div class="container-fluid">
+    <h1>Constraint Nested grids demo</h1>
+    <p>This example shows sub-grids only accepting pink items, while parent accept all.</p>
+    <a class="btn btn-primary" onClick="addNested()" href="#">Add Widget</a>
+    <a class="btn btn-primary" onClick="addNewWidget('.sub1')" href="#">Add Widget Grid1</a>
+    <a class="btn btn-primary" onClick="addNewWidget('.sub2')" href="#">Add Widget Grid2</a>
+    <span>entire save/re-create:</span>
+    <a class="btn btn-primary" onClick="save()" href="#">Save</a>
+    <a class="btn btn-primary" onClick="destroy()" href="#">Destroy</a>
+    <a class="btn btn-primary" onClick="load()" href="#">Create</a>
+    <span>partial save/load:</span>
+    <a class="btn btn-primary" onClick="save(true, false)" href="#">Save list</a>
+    <a class="btn btn-primary" onClick="save(false, false)" href="#">Save no content</a>
+    <a class="btn btn-primary" onClick="destroy(false)" href="#">Clear</a>
+    <a class="btn btn-primary" onClick="load(false)" href="#">Load</a>
+    <br><br>
+    <!-- grid will be added here -->
+  </div>
+
+  <script type="text/javascript">
+    let sub1 = [ {x:0, y:0}, {x:1, y:0}, {x:2, y:0}, {x:3, y:0}, {x:0, y:1}, {x:1, y:1}];
+    let sub2 = [ {x:0, y:0}, {x:0, y:1, w:2}];
+    let count = 0;
+    [...sub1, ...sub2].forEach(d => d.content = String(count++));
+    let subOptions = {
+      cellHeight: 50,
+      column: 'auto', // size to match container
+      itemClass: 'sub', // style sub items differently and use to prevent dragging in/out
+      acceptWidgets: '.grid-stack-item.sub', // only pink sub items can be inserted
+      margin: 2,
+      minRow: 1, // don't collapse when empty
+    };
+    let options = { // main grid options
+      cellHeight: 50,
+      margin: 5,
+      minRow: 2, // don't collapse when empty
+      acceptWidgets: true,
+      id: 'main',
+      children: [
+        {y:0, content: 'regular item'},
+        {x:1, w:4, h:4, subGridOpts: {children: sub1, class: 'sub1', ...subOptions}},
+        {x:5, w:4, h:4, subGridOpts: {children: sub2, class: 'sub2', ...subOptions}},
+      ]
+    };
+
+    // create and load it all from JSON above
+    let grid = GridStack.addGrid(document.querySelector('.container-fluid'), options);
+
+    addNested = function() {
+      grid.addWidget({x:0, y:100, content:"new item"});
+    }
+
+    addNewWidget = function(selector) {
+      let subGrid = document.querySelector(selector).gridstack;
+      let node = {
+        x: Math.round(6 * Math.random()),
+        y: Math.round(5 * Math.random()),
+        w: Math.round(1 + 1 * Math.random()),
+        h: Math.round(1 + 1 * Math.random()),
+        content: String(count++)
+      };
+      subGrid.addWidget(node);
+      return false;
+    };
+
+    save = function(content = true, full = true) {
+      options = grid.save(content, full);
+      console.log(options);
+      // console.log(JSON.stringify(options));
+    }
+    destroy = function(full = true) {
+      if (full) {
+        grid.destroy();
+        grid = undefined;
+      } else {
+        grid.removeAll();
+      }
+    }
+    load = function(full = true) {
+      if (full) {
+        grid = GridStack.addGrid(document.querySelector('.container-fluid'), options);
+      } else {
+        grid.load(options);
+      }
+    }
+
+  </script>
+</body>
+</html>
diff --git a/demo/old_nested-jq.html b/demo/old_nested-jq.html
new file mode 100644
index 000000000..0bccb24cf
--- /dev/null
+++ b/demo/old_nested-jq.html
@@ -0,0 +1,137 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="utf-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <title>Nested JQuery grids demo (old v5.1.1) which never worked fully</title>
+  <link rel="stylesheet" href="demo.css"/>
+  <script src="https://cdn.jsdelivr.net/npm/gridstack@5.1.1/dist/gridstack-jq.js"></script>
+  <style type="text/css">
+    /* make nested grids have slightly darker bg */
+    .grid-stack.grid-stack-nested {
+      background: #e4e4c1;
+    }
+    /* make nested grid take almost all space (need some to tell them apart) so items inside can have similar to external size+margin */
+    .grid-stack > .grid-stack-item.grid-stack-nested > .grid-stack-item-content {
+      /* inset: 0 2px; not IE */
+      top: 0;
+      bottom: 0;
+      left: 2px;
+      right: 2px;
+    }
+    /* make nested grid take entire item content */
+    .grid-stack-item-content .grid-stack {
+      min-height: 100%;
+      min-width: 100%;
+    }
+  </style>
+</head>
+<body>
+  <div class="container-fluid">
+    <h1>Nested JQuery grids demo</h1>
+    <p>This is the same nested grid demo, but for Jquery which has additional work required, and options.<br>
+      1. dragOut is implemented (second subgrid cannot drag outside, only adding item).<br>
+    </p>
+    <a class="btn btn-primary" onClick="addNested()" href="#">Add Widget</a>
+    <a class="btn btn-primary" onClick="addNewWidget('.sub1')" href="#">Add Widget Grid1</a>
+    <a class="btn btn-primary" onClick="addNewWidget('.sub2')" href="#">Add Widget Grid2</a>
+    <span>entire save/re-create:</span>
+    <a class="btn btn-primary" onClick="save()" href="#">Save</a>
+    <a class="btn btn-primary" onClick="destroy()" href="#">Destroy</a>
+    <a class="btn btn-primary" onClick="load()" href="#">Create</a>
+    <span>partial save/load:</span>
+    <a class="btn btn-primary" onClick="save(true, false)" href="#">Save list</a>
+    <a class="btn btn-primary" onClick="save(false, false)" href="#">Save no content</a>
+    <a class="btn btn-primary" onClick="destroy(false)" href="#">Clear</a>
+    <a class="btn btn-primary" onClick="load(false)" href="#">Load</a>
+    <br><br>
+    <!-- grid will be added here -->
+  </div>
+
+  <script type="text/javascript">
+    let sub1 = [ {x:0, y:0}, {x:1, y:0}, {x:2, y:0}, {x:3, y:0}, {x:0, y:1}, {x:1, y:1}];
+    let sub2 = [ {x:0, y:0}, {x:0, y:1, w:2}];
+    let count = 0;
+    [...sub1, ...sub2].forEach(d => d.content = String(count++));
+    let subOptions = {
+      cellHeight: 50, // should be 50 - top/bottom
+      column: 'auto', // size to match container
+      acceptWidgets: true, // will accept .grid-stack-item by default
+      margin: 5,
+      draggable: {
+        scroll: false,
+        appendTo: 'body',
+        helper: myClone,
+        // handle: ".grid-stack-item"
+        // zIndex: true,
+      }
+    };
+    let options = { // main grid options
+      cellHeight: 50,
+      margin: 5,
+      minRow: 2, // don't collapse when empty
+      acceptWidgets: true,
+      id: 'main',
+      children: [
+        {x:0, y:0, content: 'regular item'},
+        {x:1, w:4, h:4, subGridOpts: {children: sub1, dragOut: true, class: 'sub1', ...subOptions}},
+        {x:5, w:3, h:4, subGridOpts: {children: sub2, dragOut: false, class: 'sub2', ...subOptions}},
+      ]
+    };
+
+    // create and load it all from JSON above
+    let grid = GridStack.addGrid(document.querySelector('.container-fluid'), options);
+
+    // WORK-IN_PROGRESS the target is content, but we need to drag the grid-item parent and jquery-ui needs helper
+    // to be different, and re-parented (so it doesn't get clipped by other containers overflow-x:hidden, overflow-y:auto which are needed behavior)
+    // but jq-ui doesn't support position:fixed
+    function myClone(event) {
+      let item = event.target.parentElement;
+      item = item.cloneNode(true);
+      grid.el.append(item)
+      // item.style.position = 'fixed'
+      return item;
+    }
+
+    function addNested() {
+      grid.addWidget({x:0, y:100, content:"new item"});
+    }
+
+    function addNewWidget(selector) {
+      let subGrid = document.querySelector(selector).gridstack;
+      let node = {
+        x: Math.round(6 * Math.random()),
+        y: Math.round(5 * Math.random()),
+        w: Math.round(1 + 1 * Math.random()),
+        h: Math.round(1 + 1 * Math.random()),
+        content: String(count++)
+      };
+      subGrid.addWidget(node);
+      return false;
+    };
+
+    function save(content = true, full = true) {
+      options = grid.save(content, full);
+      console.log(options);
+      // console.log(JSON.stringify(options));
+    }
+    function destroy(full = true) {
+      if (full) {
+        grid.destroy();
+        grid = undefined;
+      } else {
+        grid.removeAll();
+      }
+    }
+    function load(full = true) {
+      if (full) {
+        grid = GridStack.addGrid(document.querySelector('.container-fluid'), options);
+      } else {
+        grid.load(options);
+      }
+    }
+
+  </script>
+</body>
+</html>
diff --git a/demo/old_two-jq.html b/demo/old_two-jq.html
new file mode 100644
index 000000000..234c38bc9
--- /dev/null
+++ b/demo/old_two-jq.html
@@ -0,0 +1,101 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="utf-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <title>Two grids JQ demo</title>
+
+  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
+  <link rel="stylesheet" href="demo.css"/>
+
+  <script src="https://cdn.jsdelivr.net/npm/gridstack@5.1.1/dist/gridstack-jq.js"></script>
+</head>
+<body>
+  <div class="container-fluid">
+    <h1>Two grids demo (old v5.1.1 Jquery version)</h1>
+
+    <div class="row">
+      <div class="col-md-3">
+        <div class="sidebar">
+          <!-- will size to match content -->
+          <div class="grid-stack-item">
+            <div class="grid-stack-item-content">Drag me</div>
+          </div>
+          <!-- manually force a drop size of 2x1 -->
+          <div class="grid-stack-item" gs-w="2" gs-h="1" gs-max-w="3">
+            <div class="grid-stack-item-content">2x1, max=3</div>
+          </div>
+        </div>
+      </div>
+      <div class="col-md-9">
+        <div class="trash">
+        </div>
+      </div>
+    </div>
+
+    <div class="row" style="margin-top: 20px">
+      <div class="col-md-6">
+        <a onClick="toggleFloat(this, 0)" class="btn btn-primary" href="#">float: false</a>
+        <a onClick="compact(0)" class="btn btn-primary" href="#">Compact</a>
+        <div class="grid-stack"></div>
+      </div>
+      <div class="col-md-6">
+        <a onClick="toggleFloat(this, 1)" class="btn btn-primary" href="#">float: true</a>
+        <a onClick="compact(1)" class="btn btn-primary" href="#">Compact</a>
+        <div class="grid-stack"></div>
+      </div>
+    </div>
+  </div>
+  <script src="events.js"></script>
+  <script type="text/javascript">
+  let grids;
+  $(function () { // testing $ works (delay loading here)
+    let options = {
+      column: 6,
+      minRow: 1, // don't collapse when empty
+      cellHeight: 70,
+disableOneColumnMode: true,
+      float: false,
+      // dragIn: '.sidebar .grid-stack-item', // add draggable to class
+      // dragInOptions: { revert: 'invalid', scroll: false, appendTo: 'body', helper: 'clone' }, // clone
+      removable: '.trash', // true or drag-out delete class
+      acceptWidgets: function(el) { return true; } // function example, but can also be: true | false | '.someClass' value
+    };
+    let grids = GridStack.initAll(options);
+    grids[1].float(true);
+
+    // new 4.x static method instead of setting up options on every grid (never been per grid really) but old options still works
+    GridStack.setupDragIn('.sidebar .grid-stack-item', { revert: 'invalid', scroll: false, appendTo: 'body', helper: myClone });
+    // GridStack.setupDragIn(); // second call will now work (cache last values)
+
+    let items = [
+      {x: 0, y: 0, w: 2, h: 2},
+      {x: 3, y: 1, h: 2},
+      {x: 4, y: 1},
+      {x: 2, y: 3, w: 3, maxW: 3, id: 'special', content: 'has maxW=3'},
+      {x: 2, y: 5}
+    ];
+
+    grids.forEach(function (grid, i) {
+      addEvents(grid, i);
+      grid.load(items);
+    });
+  });
+
+    // decide what the dropped item will be - for now just a clone but can be anything
+    function myClone(event) {
+      return event.target.cloneNode(true);
+    }
+
+    function toggleFloat(button, i) {
+      grids[i].float(! grids[i].getFloat());
+      button.innerHTML = 'float: ' + grids[i].getFloat();
+    }
+
+    function compact(i) {
+      grids[i].compact();
+    }
+  </script>
+</body>
+</html>
diff --git a/demo/react-hooks-controlled-multiple.html b/demo/react-hooks-controlled-multiple.html
new file mode 100644
index 000000000..85df67d42
--- /dev/null
+++ b/demo/react-hooks-controlled-multiple.html
@@ -0,0 +1,165 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+  <meta charset="UTF-8" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+  <title>Gridstack.js React integration example</title>
+  <link rel="stylesheet" href="demo.css" />
+
+  <script src="../node_modules/gridstack/dist/gridstack-all.js"></script>
+
+  <!-- Scripts to use react inside html - DEVELOPMENT FILES -->
+  <script src="https://unpkg.com/react@16/umd/react.development.js"></script>
+  <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
+  <script src="https://unpkg.com/babel-standalone@6.15.0/babel.js"></script>
+</head>
+
+<body>
+  <div>
+    <h2>Controlled stack</h2>
+    <div id="controlled-stack"></div>
+  </div>
+</body>
+
+<script type="text/babel">
+  /***********************************************************************************************************/
+  /********************************* NOT IDEAL - see comments below line ~96) ********************************/
+  /***********************************************************************************************************/
+
+  const { useState, useEffect, useLayoutEffect, createRef, useRef } = React
+  const Item = ({ id }) => <div>{id}</div>
+
+  //
+  // Controlled example
+  //
+  const ControlledStack = ({ items, addItem, changeItems }) => {
+    const refs = useRef({})
+    const gridRef = useRef()
+    const gridContainerRef = useRef(null)
+    refs.current = {}
+
+    if (Object.keys(refs.current).length !== items.length) {
+      items.forEach(({ id }) => {
+        refs.current[id] = refs.current[id] || createRef()
+      })
+    }
+
+    useLayoutEffect(() => {
+      if (!gridRef.current) {
+        // no need to init twice (would will return same grid) or register dup events
+        const grid = gridRef.current = GridStack.init(
+          {
+            float: false,
+            acceptWidgets: true,
+            column: 6,
+            minRow: 1,
+          },
+          gridContainerRef.current
+        )
+        .on('added', (ev, gsItems) => {
+          if (grid._ignoreCB) return;
+          // remove the new element as React will re-create it again (dup) once we add to the list or we get 2 of them with same ids but different DOM el!
+          // TODO: this is really not ideal - we shouldn't mix React templating with GS making it own edits as those get out of sync! see comment below ~96.
+          gsItems.forEach(n => {
+            grid.removeWidget(n.el, true, false); // true=remove DOM, false=don't call use back!
+            // can't pass n directly even though similar structs as it has n.el.gridstackNode which gives JSON error for circular write.
+            addItem({id:n.id, x:n.x, y:n.y, w:n.w, h:n.h});
+          });
+        })
+        .on('removed change', (ev, gsItems) => {
+          // synch our version from GS....
+          // Note: we could just update those few items passed but save() is fast and it's easier to just set an entire new list
+          // and since we have the same ids, React will not re-create anything...
+          const newItems = grid.save(false); // saveContent=false
+          changeItems(newItems);
+        })
+        // addEvents(grid, i);
+      } else {
+        //
+        // update existing GS layout, which is optimized to updates only diffs and add new/delete items as well
+        //
+        const grid = gridRef.current;
+        const layout = items.map((a) => 
+          // use exiting nodes (which will skip diffs being the same) else new elements Widget but passing the React dom .el so we know what to makeWidget() on!
+          refs.current[a.id].current.gridstackNode || {...a, el: refs.current[a.id].current}
+        );
+        grid._ignoreCB = true; // hack: ignore added/removed since we're the one doing the update
+        grid.load(layout);
+        delete grid._ignoreCB;
+      }
+
+    }, [items])
+
+    return (
+      // ********************
+      // NOTE: constructing DOM grid items in template when gridstack is also allowed creating (dragging between grids, or adding/removing from say a toolbar)
+      // is NOT A GOOD IDEA as you end up fighting between gridstack users' edits and your template items structure which are not in sync.
+      // At best, you end up re-creating widgets DOM (from React template) and all their content & state after a widget was inserted/re-parented by the user.
+      // a MUCH better way is to let GS create React components using it's API/user interactions, with only initial load() of a stored layout.
+      // See the Angular component wrapper that does that: https://github.com/gridstack/gridstack.js/tree/master/angular/ (lib author uses Angular)
+      // ...TBD creating React equivalent...
+      //
+      // Also templating forces you to spell out the 15+ GridStackWidget attributes (only x,y,w,h done below), instead of passing an option structure that 
+      // supports everything, is not robust as things get added and pollutes the DOM attr for default/missing entries, vs the optimized code in GS.
+      // ********************
+      <div style={{ width: '100%', marginRight: '10px' }}>
+        <div className="grid-stack" ref={gridContainerRef}>
+          {items.map((item, i) => {
+            return (
+              <div ref={refs.current[item.id]} key={item.id} className="grid-stack-item" gs-id={item.id} gs-w={item.w} gs-h={item.h} gs-x={item.x} gs-y={item.y}>
+                <div className="grid-stack-item-content">
+                  <Item {...item} />
+                </div>
+              </div>
+            )
+          })}
+        </div>
+        <code>
+          <pre>{JSON.stringify(items, null, 2)}</pre>
+        </code>
+      </div>
+    )
+  }
+
+  const ControlledExample = () => {
+    const [items1, setItems1] = useState([{ id: 'item-1-1', x: 0, y: 0, w: 2, h: 2 }, { id: 'item-1-2', x: 2, y: 0, w: 2, h: 2 }])
+    const [items2, setItems2] = useState([{ id: 'item-2-1', x: 0, y: 0 }, { id: 'item-2-2', x: 0, y: 1 }, { id: 'item-2-3', x: 1, y: 0 }])
+
+    return (
+      <div>
+        <div style={{display: 'flex', gap: '16px', marginBottom: '16px'}}>
+          <div></div>
+        </div>
+
+        <div style={{ display: 'flex', gap: '16px', marginBottom: '16px' }}>
+          <button onClick={() => setItems1(items => [...items, { id: `item-1-${Date.now()}`, x: 2, y: 0, w: 2, h: 2 }])}>Add Item to 1 grid</button>
+          <button onClick={() => setItems2(items => [...items, { id: `item-2-${Date.now()}`, x: 2, y: 0, w: 2, h: 2 }])}>Add Item to 2 grid</button>
+        </div>
+        <div style={{display: 'flex'}}>
+          <div style={{ display: 'flex', width: '50%' }}>
+            <ControlledStack
+              items={items1}
+              addItem={(item) => {
+                setItems1(items => [...items, item])
+              }}
+              changeItems={(items) => setItems1(items)}
+            />
+          </div >
+          <div style={{ display: 'flex', width: '50%' }}>
+            <ControlledStack
+              items={items2}
+              addItem={(item) => {
+                setItems2(items => [...items, item])
+              }}
+              changeItems={(items) => setItems2(items)}
+            />
+          </div>
+        </div >
+      </div>
+    )
+  }
+
+  ReactDOM.render(<ControlledExample />, document.getElementById('controlled-stack'))
+</script>
+</html>
\ No newline at end of file
diff --git a/demo/react-hooks.html b/demo/react-hooks.html
new file mode 100644
index 000000000..5ceaaa744
--- /dev/null
+++ b/demo/react-hooks.html
@@ -0,0 +1,174 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+  <meta charset="UTF-8" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+  <title>Gridstack.js React integration example</title>
+  <link rel="stylesheet" href="demo.css" />
+  <script src="../node_modules/gridstack/dist/gridstack-all.js"></script>
+
+  <!-- Scripts to use react inside html -->
+  <script src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
+  <script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
+  <script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
+</head>
+
+<body>
+  <div>
+    <h1>Using GridStack.js with React hooks</h1>
+    <p>
+      As with any virtual DOM based framework, you need to check if React has rendered the DOM (or any updates to it)
+      <strong>before</strong> you initialize GridStack or call its methods. This example shows how to make rendered
+      components widgets:
+    </p>
+    <ol>
+      <li>Render items, each with a reference</li>
+      <li>Convert each rendered item to a widget using the reference and the <a
+          href="https://github.com/gridstack/gridstack.js/tree/master/doc#makewidgetel">
+          makeWidget()</a> function</li>
+    </ol>
+  </div>
+  <div>
+    <h2>Controlled stack</h2>
+    <div id="controlled-stack"></div>
+  </div>
+  <div>
+    <h2>Uncontrolled stack</h2>
+    <div id="uncontrolled-stack"></div>
+  </div>
+</body>
+
+<script type="text/babel">
+  const { useState, useEffect, createRef, useRef } = React
+  const Item = ({ id }) => <div>{id}</div>
+
+  //
+  // Controlled example
+  //
+  const ControlledStack = ({ items, addItem }) => {
+    const refs = useRef({})
+    const gridRef = useRef()
+
+    if (Object.keys(refs.current).length !== items.length) {
+      items.forEach(({ id }) => {
+        refs.current[id] = refs.current[id] || createRef()
+      })
+    }
+
+    useEffect(() => {
+      gridRef.current = gridRef.current ||
+        GridStack.init({float: true}, '.controlled')
+      const grid = gridRef.current
+      grid.batchUpdate()
+      grid.removeAll(false)
+      items.forEach(({ id }) => grid.makeWidget(refs.current[id].current))
+      grid.batchUpdate(false)
+    }, [items])
+
+    return (
+      <div>
+        <button onClick={addItem}>Add new widget</button>
+        <div className={`grid-stack controlled`}>
+          {items.map((item, i) => {
+            return (
+              <div ref={refs.current[item.id]} key={item.id} className={'grid-stack-item'}>
+                <div className="grid-stack-item-content">
+                  <Item {...item} />
+                </div>
+              </div>
+            )
+          })}
+        </div>
+      </div>
+    )
+  }
+
+  const ControlledExample = () => {
+    const [items, setItems] = useState([{ id: 'item-1' }, { id: 'item-2' }])
+    return (
+      <ControlledStack
+        items={items}
+        addItem={() => setItems([...items, { id: `item-${items.length + 1}` }])}
+      />
+    )
+  }
+
+  //
+  // Uncontrolled example
+  //
+  const UncontrolledExample = () => {
+    const gridRef = useRef()
+    const [state, setState] = useState({
+      count: 0,
+      info: '',
+      items: [
+        { x: 2, y: 1, h: 2 },
+        { x: 2, y: 4, w: 3 },
+        { x: 4, y: 2 },
+        { x: 3, y: 1, h: 2 },
+        { x: 0, y: 6, w: 2, h: 2 },
+      ],
+    })
+
+    useEffect(() => {
+      gridRef.current = gridRef.current ||
+        GridStack.init(
+          {
+            float: true,
+            cellHeight: '70px',
+            minRow: 1,
+          },
+          '.uncontrolled'
+        )
+      const grid = gridRef.current
+
+      grid.on('dragstop', (event, element) => {
+        const node = element.gridstackNode
+        setState(prevState => ({
+          ...prevState,
+          info: `you just dragged node #${node.id} to ${node.x},${node.y} – good job!`,
+        }))
+
+        let timerId
+        window.clearTimeout(timerId)
+        timerId = window.setTimeout(() => {
+          setState(prevState => ({
+            ...prevState,
+            info: '',
+          }))
+        }, 2000)
+      })
+    }, [])
+
+    return (
+      <div>
+        <button
+          onClick={() => {
+            const grid = gridRef.current
+            const node = state.items[state.count] || {
+              x: Math.round(12 * Math.random()),
+              y: Math.round(5 * Math.random()),
+              w: Math.round(1 + 3 * Math.random()),
+              h: Math.round(1 + 3 * Math.random()),
+            }
+            node.id = node.content = String(state.count)
+            setState(prevState => ({
+              ...prevState,
+              count: prevState.count + 1,
+            }))
+            grid.addWidget(node)
+          }}
+        >
+          Add Widget
+        </button>
+        <div>{JSON.stringify(state)}</div>
+        <section class="grid-stack uncontrolled"></section>
+      </div>
+    )
+  }
+
+  ReactDOM.render(<ControlledExample />, document.getElementById('controlled-stack'))
+  ReactDOM.render(<UncontrolledExample />, document.getElementById('uncontrolled-stack'))
+</script>
+</html>
\ No newline at end of file
diff --git a/demo/react.html b/demo/react.html
new file mode 100644
index 000000000..711986963
--- /dev/null
+++ b/demo/react.html
@@ -0,0 +1,104 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="UTF-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+    <title>Gridstack.js React integration example</title>
+    <link rel="stylesheet" href="demo.css" />
+    <script src="../node_modules/gridstack/dist/gridstack-all.js"></script>
+
+    <!-- Scripts to use react inside html -->
+    <script src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
+    <script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
+    <script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
+  </head>
+
+  <body>
+    <div id="root"></div>
+  </body>
+
+  <script type="text/babel">
+    class App extends React.Component {
+      state = {
+        count: 0,
+        info: "",
+        items: [
+          { x: 2, y: 1, h: 2 },
+          { x: 2, y: 4, w: 3 },
+          { x: 4, y: 2 },
+          { x: 3, y: 1, h: 2 },
+          { x: 0, y: 6, w: 2, h: 2 },
+        ],
+      };
+
+      componentDidMount() {
+        // Provides access to the GridStack instance across the React component.
+        this.grid = GridStack.init({
+          float: true,
+          cellHeight: "70px",
+          minRow: 1,
+        });
+
+        this.grid.on("dragstop", (event, element) => {
+          const node = element.gridstackNode;
+          this.setState({
+            info: `you just dragged node #${node.id} to ${node.x},${node.y} – good job!`,
+          });
+
+          // Clear the info text after a two second timeout.
+          // Clears previous timeout first.
+          window.clearTimeout(this.timerId);
+          this.timerId = window.setTimeout(() => {
+            this.setState({
+              info: "",
+            });
+          }, 2000);
+        });
+      }
+
+      addNewWidget = () => {
+        const node = this.state.items[this.state.count] || {
+          x: Math.round(12 * Math.random()),
+          y: Math.round(5 * Math.random()),
+          w: Math.round(1 + 3 * Math.random()),
+          h: Math.round(1 + 3 * Math.random()),
+        };
+        node.id = node.content = String(this.state.count);
+        this.setState((prevState) => ({
+          count: prevState.count + 1,
+        }));
+        this.grid.addWidget(node);
+      };
+
+      render() {
+        return (
+          <div>
+            <h1>How to integrate GridStack.js with React.js</h1>
+            <p>
+              As with any virtual DOM based framework, you need to check if React
+              has rendered the DOM (or any updates to it){" "}
+              <strong>before</strong> you initialize GridStack or call its
+              methods. As a basic example, check this component's{" "}
+              <code>mounted</code> hook.
+            </p>
+            <p>
+              If your app requires more complex render logic than the inline
+              template in `addWidget`, consider&nbsp;
+              <a href="https://github.com/gridstack/gridstack.js/tree/master/doc#makewidgetel">
+                makeWidget
+              </a>
+              &nbsp;to let React deal with DOM rendering.
+            </p>
+            <button type="button" onClick={this.addNewWidget}>
+              Add Widget
+            </button>
+            {this.state.info}
+            <section class="grid-stack"></section>
+          </div>
+        );
+      }
+    }
+
+    ReactDOM.render(<App />, document.getElementById("root"));
+  </script>
+</html>
diff --git a/demo/responsive.html b/demo/responsive.html
new file mode 100644
index 000000000..a58f41cfa
--- /dev/null
+++ b/demo/responsive.html
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <title>Responsive column</title>
+
+  <link rel="stylesheet" href="demo.css"/>
+  <script src="../node_modules/gridstack/dist/gridstack-all.js"></script>
+</head>
+<body>
+  <div>
+    <h1>Responsive: by column size</h1>
+    <p>Using new v10 <code>GridStackOptions.columnOpts: { columnWidth: x }</code></p>
+
+    <div>
+      <span>Number of Columns:</span> <span id="column-text"></span>
+    </div>
+    <div>
+      <label>Choose re-layout:</label>
+      <select onchange="grid.opts.columnOpts.layout = this.value">
+        <option value="moveScale">move + scale</option>
+        <option value="move">move</option>
+        <option value="scale">scale</option>
+        <option value="list">list</option>
+        <option value="compact">compact</option>
+        <option value="none">none</option>
+      </select>
+      <a onClick="grid.removeAll()" class="btn btn-primary" href="#">Clear</a>
+      <a onClick="addWidget()" class="btn btn-primary" href="#">Add Widget</a>
+    </div>
+    <br/>
+    <div class="grid-stack">
+    </div>
+  </div>
+
+  <script type="text/javascript">
+    let text = document.querySelector('#column-text');
+
+    function addWidget() {
+      grid.addWidget({x:0, y:0, w:4, id:count++, content: '4x1'});
+    };
+    
+    let count = 0;
+    let items = [ // our initial 12 column layout loaded first so we can compare
+      {x: 0, y: 0},
+      {x: 1, y: 0, w: 2, h: 2, minW: 4},
+      {x: 4, y: 0, w: 2},
+      {x: 1, y: 3, w: 4},
+      {x: 5, y: 3, w: 2},
+      {x: 0, y: 4, w: 12}
+    ];
+    items.forEach(n => {n.id = count; n.content = String(count++)});
+
+    let grid = GridStack.init({
+      cellHeight: 80, // use 'auto' to make square
+      animate: false, // show immediate (animate: true is nice for user dragging though)
+      columnOpts: {
+        columnWidth: 100, // wanted width
+      },
+      children: items,
+      float: true })
+    .on('change', (ev, gsItems) => text.innerHTML = grid.getColumn());
+    text.innerHTML = grid.getColumn();
+  </script>
+</body>
+</html>
diff --git a/demo/responsive_break.html b/demo/responsive_break.html
new file mode 100644
index 000000000..d93490d07
--- /dev/null
+++ b/demo/responsive_break.html
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <title>Responsive breakpoint</title>
+
+  <link rel="stylesheet" href="demo.css"/>
+  <script src="../node_modules/gridstack/dist/gridstack-all.js"></script>
+</head>
+<body>
+  <div>
+    <h1>Responsive: using breakpoint</h1>
+    <p>Using new v10 <code>GridStackOptions.columnOpts: { breakpoints: [] }</code></p>
+    <div>
+      <span>Number of Columns:</span> <span id="column-text"></span>
+    </div>
+    <div>
+      <label>Choose re-layout:</label>
+      <select onchange="grid.opts.columnOpts.layout = this.value">
+        <option value="moveScale">move + scale</option>
+        <option value="move">move</option>
+        <option value="scale">scale</option>
+        <option value="list">list</option>
+        <option value="compact">compact</option>
+        <option value="none">none</option>
+      </select>
+      <a onClick="grid.removeAll()" class="btn btn-primary" href="#">Clear</a>
+      <a onClick="addWidget()" class="btn btn-primary" href="#">Add Widget</a>
+    </div>
+    <br/>
+    <div class="grid-stack">
+    </div>
+  </div>
+
+  <script type="text/javascript">
+    let text = document.querySelector('#column-text');
+
+    function addWidget() {
+      grid.addWidget({x:0, y:0, w:4, id:count++, content: '4x1'});
+    };
+    
+    let count = 0;
+    let items = [ // our initial 12 column layout loaded first so we can compare
+      {x: 0, y: 0},
+      {x: 1, y: 0, w: 2, h: 2},
+      {x: 4, y: 0, w: 2},
+      {x: 1, y: 3, w: 4},
+      {x: 5, y: 3, w: 2},
+      {x: 0, y: 4, w: 12}
+    ];
+    items.forEach(n => {n.id = count; n.content = String(count++)});
+
+    let grid = GridStack.init({
+      cellHeight: 80,
+      animate: false, // show immediate (animate: true is nice for user dragging though)
+      columnOpts: {
+        breakpointForWindow: true,  // test window vs grid size
+        breakpoints: [{w:700, c:1},{w:850, c:3},{w:950, c:6},{w:1100, c:8}]
+      },
+      children: items,
+      float: true })
+    .on('change', (ev, gsItems) => text.innerHTML = grid.getColumn());
+    text.innerHTML = grid.getColumn();
+  </script>
+</body>
+</html>
diff --git a/demo/responsive_none.html b/demo/responsive_none.html
new file mode 100644
index 000000000..0da16869c
--- /dev/null
+++ b/demo/responsive_none.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="utf-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <title>Responsive layout:'none'</title>
+
+  <link rel="stylesheet" href="demo.css"/>
+  <script src="../node_modules/gridstack/dist/gridstack-all.js"></script>
+
+</head>
+<body>
+  <div class="container-fluid">
+    <h1>Responsive layout:'none'</h1>
+    <p>show loading a fixed (<b>layout:'none'</b>) but still responsive design (150px columns) with items w:2-4</p>
+    <p>showing how it will not change the layout unless it doesn't fit. loading into small view remembers the full layout (column:6)</p>
+    <div class="grid-stack"></div>
+  </div>
+  <script src="events.js"></script>
+  <script type="text/javascript">
+    let children = [ {}, {}, {}];
+    children.forEach((w, i) => { 
+      w.x=i, w.y=i, // comment out to have autoPosition:true which behaves differently
+      w.w=i+2, w.content = `${i} w:${w.w}`})
+    
+    GridStack.init({
+      children,
+      column: 6,
+      cellHeight: 100,
+      columnOpts: {
+        columnWidth: 150,
+        columnMax: 12,
+        layout: 'none',
+      },
+    });
+  </script>
+</body>
+</html>
diff --git a/demo/right-to-left(rtl).html b/demo/right-to-left(rtl).html
new file mode 100644
index 000000000..8c91b6610
--- /dev/null
+++ b/demo/right-to-left(rtl).html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html lang="en" dir="rtl"> <!-- set text reading direction -->
+<head>
+  <meta charset="utf-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <title>Right-To-Left (RTL) demo</title>
+  <style type="text/css">
+    /* don't include demo.css as that has some forced text aligment */
+    @import "../node_modules/gridstack/dist/gridstack.min.css";
+    .grid-stack {
+      background: #FAFAD2;
+    }
+    .grid-stack-item-content {
+      background-color: #18bc9c;
+    }
+  </style>
+  <script src="../node_modules/gridstack/dist/gridstack-all.js"></script>
+</head>
+<body>
+  <h1>RTL Demo</h1>
+  <div>
+    <button onClick="addWidget()">Add Widget</button>
+  </div>
+  <br>
+  <div class="grid-stack"></div>
+
+  <script type="text/javascript">
+    let items = [
+      {x: 0, y: 0, w: 2, h: 1},
+      {x: 2, y: 0, w: 4, h: 1},
+      {x: 6, y: 0, w: 2, h: 2},
+    ];
+    items.forEach((item, i) => item.content = 'item ' + i);
+    let grid = GridStack.init({rtl: true, children: items});
+
+    function addWidget() {
+      let w = {
+        w: Math.round(1 + 3 * Math.random()),
+        h: Math.round(1 + 3 * Math.random()),
+        content: 'new item',
+      };
+      grid.addWidget(w);
+    };
+
+  </script>
+</body>
+</html>
diff --git a/demo/serialization.html b/demo/serialization.html
new file mode 100644
index 000000000..f064644e6
--- /dev/null
+++ b/demo/serialization.html
@@ -0,0 +1,93 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="utf-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <title>Serialization demo</title>
+
+  <link rel="stylesheet" href="demo.css"/>
+  <script src="../node_modules/gridstack/dist/gridstack-all.js"></script>
+</head>
+<body>
+  <div class="container-fluid">
+    <h1>Serialization demo</h1>
+    <a onclick="saveGrid()" class="btn btn-primary" href="#">Save</a>
+    <a onclick="loadGrid()" class="btn btn-primary" href="#">Load</a>
+    <a onclick="saveFullGrid()" class="btn btn-primary" href="#">Save Full</a>
+    <a onclick="loadFullGrid()" class="btn btn-primary" href="#">Load Full</a>
+    <a onclick="clearGrid()" class="btn btn-primary" href="#">Clear</a>
+    <br/><br/>
+    <div id="gridCont"><div class="grid-stack"></div></div>
+    <hr/>
+    <textarea id="saved-data" style="width: 100%" cols="100" rows="20" readonly="readonly"></textarea>
+  </div>
+  <script src="events.js"></script>
+  <script type="text/javascript">
+    // NOTE: REAL apps would sanitize-html or DOMPurify before blinding setting innerHTML. see #2736
+    GridStack.renderCB = function(el, w) {
+      el.innerHTML = w.content;
+    };
+
+    let serializedData = [
+      {x: 0, y: 0, w: 2, h: 2},
+      {x: 2, y: 1, w: 2, h: 3, 
+      content: `<button onclick=\"alert('clicked!')\">Press me</button><div>text area</div><div><textarea></textarea></div><div>Input Field</div><input type="text"><div contenteditable=\"true\">Editable Div</div><div class=\"no-drag\">no drag</div>`},
+      {x: 4, y: 1},
+      {x: 1, y: 3},
+      {x: 2, y: 3, w:3},
+    ];
+    serializedData.forEach((n, i) => {
+      n.id = String(i);
+      n.content = `<button onclick="removeWidget(this.parentElement.parentElement)">X</button><br> ${i}<br> ${n.content ? n.content : ''}`;
+    });
+    let serializedFull;
+
+    let grid = GridStack.init({
+      minRow: 1, // don't let it collapse when empty
+      cellHeight: 80,
+      float: true,
+      draggable: { cancel: '.no-drag'} // example of additional custom elements to skip drag on
+    }).load(serializedData);
+    addEvents(grid);
+
+    // 2.x method - just saving list of widgets with content (default)
+    function loadGrid() {
+      grid.load(serializedData);
+    }
+
+    // 2.x method
+    function saveGrid() {
+      delete serializedFull;
+      serializedData = grid.save();
+      document.querySelector('#saved-data').value = JSON.stringify(serializedData, null, '  ');
+    }
+
+    // 3.1 full method saving the grid options + children (which is recursive for nested grids)
+    function saveFullGrid() {
+      serializedFull = grid.save(true, true);
+      serializedData = serializedFull.children;
+      document.querySelector('#saved-data').value = JSON.stringify(serializedFull, null, '  ');
+    }
+
+    // 3.1 full method to reload from scratch - delete the grid and add it back from JSON
+    function loadFullGrid() {
+      if (!serializedFull) return;
+      grid.destroy(true); // nuke everything
+      grid = GridStack.addGrid(document.querySelector('#gridCont'), serializedFull)
+    }
+
+    function clearGrid() {
+      grid.removeAll();
+    }
+
+    function removeWidget(el) {
+      // TEST removing from DOM first like Angular/React/Vue would do
+      el.remove();
+      grid.removeWidget(el, false);
+    }
+
+    // setTimeout(() => loadGrid(), 1000); // TEST force a second load which should be no-op
+  </script>
+</body>
+</html>
diff --git a/demo/sizeToContent.html b/demo/sizeToContent.html
new file mode 100644
index 000000000..b8135d677
--- /dev/null
+++ b/demo/sizeToContent.html
@@ -0,0 +1,135 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="utf-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <title>sizeToContent demo</title>
+
+  <link rel="stylesheet" href="demo.css"/>
+  <script src="../node_modules/gridstack/dist/gridstack-all.js"></script>
+  <style type="text/css">
+    .grid-stack-item-content {
+      text-align: unset;
+    }
+    .sidebar.inline {
+      width: fit-content;
+      height: fit-content;
+      display: inline-block;
+      padding: 0;
+    }
+  </style>  
+</head>
+<body>
+  <div class="container">
+    <h1>sizeToContent options demo</h1>
+    <p>New 9.x feature that size the items to fit their content height as to not have scroll bars
+    <br>case C: `sizeToContent:false` to turn off.
+    <br>case E: has soft maxsize `sizeToContent:3`, shrinking to smaller content as needed
+    <br>Defaulting to different initial size (see code) to show grow/shrink behavior</p>
+    <div>
+      <a onClick="clearGrid()" class="btn btn-primary" href="#">clear</a>
+      <a onClick="load()" class="btn btn-primary" href="#">load</a>
+      column:
+      <a onClick="column(8)" class="btn btn-primary" href="#">8</a>
+      <a onClick="column(12)" class="btn btn-primary" href="#">12</a>
+      cellHeight:
+      <a onClick="cellHeight(25)" class="btn btn-primary" href="#">25</a>
+      <a onClick="cellHeight('3rem')" class="btn btn-primary" href="#">3rem</a>
+      <a onClick="cellHeight(50)" class="btn btn-primary" href="#">50</a>
+      <a onClick="cellHeight(75)" class="btn btn-primary" href="#">75</a>
+      Widget:
+      <a onClick="addWidget()" class="btn btn-primary" href="#">Add</a>
+      <a onClick="makeWidget()" class="btn btn-primary" href="#">Make w:2</a>
+      <div class="sidebar inline">
+        <div class="grid-stack-item" gs-w="2" gs-h="3">
+          <div class="grid-stack-item-content"><div>Insert me 2x3</div></div>
+        </div>
+      </div>
+    </div>
+    <br>
+    <div id="grid1"></div>
+    <p>from DOM test:</p>
+    <div id="grid2">
+      <div class="grid-stack-item" gs-x="11" gs-y="0" gs-h="4">
+        <div class="grid-stack-item-content">
+          <div>DOM: h:4 sized down</div>
+        </div>
+      </div>
+    </div>
+
+  </div>
+  <script type="text/javascript">
+    // NOTE: REAL apps would sanitize-html or DOMPurify before blinding setting innerHTML. see #2736
+    GridStack.renderCB = function(el, w) {
+      el.innerHTML = w.content;
+    };
+
+    let text ='some very large content that will normally not fit in the window.'
+    text = text + text;
+    let count = 0;
+    let items = [
+      // {x:0, y:0, w:2, h:3, sizeToContent: false, content: `<div>A no h: ${text}</div>`},
+      {x:0, y:0, w:2, content: `<div>A no h: ${text}</div>`},
+      {x:2, y:0, w:1, h:2, content: '<div>B: shrink h=2</div>'}, // make taller than needed upfront
+      {x:3, y:0, w:2, sizeToContent: false, content: `<div>C: WILL SCROLL. ${text}</div>`}, // prevent this from fitting testing
+      {x:0, y:1, w:3, content: `<div>D no h: ${text} ${text}</div>`},
+      {x:3, y:1, w:2, sizeToContent:3, content: `<div>E sizeToContent=3 <button onClick="more()">more</button><button onClick="less()">less</button><div id="dynContent">${text} ${text} ${text}</div></div>`},
+    ];
+    items.forEach(n => n.id = String(count++));
+    let opts = {
+      margin: 5,
+      cellHeight: '3rem', // = 48px
+      sizeToContent: true, // default to make them all fit
+      resizable: { handles: 'all'}, // do all sides for testing
+      acceptWidgets: true,
+      // cellHeightThrottle: 100, // ms before sizeToContent happens
+      // children: items, // test loading first
+    }
+    let grid = GridStack.init(opts, '#grid1');
+    grid.load(items); // test loading after
+    GridStack.init({...opts, children:undefined}, '#grid2');
+
+    GridStack.setupDragIn('.sidebar>.grid-stack-item');
+
+    function clearGrid() {
+      grid.removeAll();
+    }
+    function load() {
+      grid.load(items);
+    }
+    function column(n) {
+      grid.column(n, 'none');
+    }
+    function cellHeight(n) {
+      grid.cellHeight(n);
+    }
+    function addWidget() {
+      grid.addWidget({content: `<div>New: ${text}</div>`});
+    }
+    function makeWidget() {
+      let el = grid.createWidgetDivs({content: `<div>New Make: ${text}</div>`}, grid.el)
+      grid.makeWidget(el, {w:2});
+    }
+    function more() {
+      let cont = document.getElementById('dynContent');
+      if (!cont) return;
+      cont.innerHTML += cont.innerHTML;
+      let el = cont.parentElement.parentElement.parentElement;
+      grid.resizeToContent(el)
+    }
+    function less() {
+      let cont = document.getElementById('dynContent');
+      if (!cont) return;
+      let content = cont.innerHTML;
+      cont.innerHTML = content.substring(0, content.length/2);
+      let el = cont.parentElement.parentElement.parentElement;
+      grid.resizeToContent(el);
+    }
+
+    // TEST
+    // grid.update(grid.engine.nodes[0].el, {x:7});
+    // load();
+  </script>
+</body>
+</html>
diff --git a/demo/static.html b/demo/static.html
new file mode 100644
index 000000000..72240615c
--- /dev/null
+++ b/demo/static.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="utf-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <title>Static Grid</title>
+
+  <link rel="stylesheet" href="demo.css"/>
+  <script src="../node_modules/gridstack/dist/gridstack-all.js"></script>
+
+</head>
+<body>
+  <div class="container-fluid">
+    <h1>Static vs can move/drag Demo</h1>
+    <p>we start with a static grid (no drag&drop initialized) with button to make it editable.</p>
+
+    <div class="sidebar" style="height:50px">
+      <div class="grid-stack-item">
+        <div class="grid-stack-item-content">Drag me</div>
+      </div>
+      <div class="grid-stack-item" gs-w="2" gs-h="1" gs-max-w="3">
+        <div class="grid-stack-item-content">2x1, max=3</div>
+      </div>
+    </div>
+    <div>
+      <a class="btn btn-primary" onClick="grid.setStatic(true)" href="#">Static</a>
+      <a class="btn btn-primary" onclick="grid.setStatic(false)" id="float" href="#">Editable</a>
+    </div>
+    <div class="grid-stack"></div>
+  </div>
+  <script src="events.js"></script>
+  <script type="text/javascript">
+    let grid = GridStack.init({
+      float: true,
+      cellHeight: 70,
+      acceptWidgets: true,
+      removable: true,
+      staticGrid: true
+    });
+    addEvents(grid);
+
+    let serializedData = [
+      {x: 0, y: 0, w: 2, h: 2, id: '0'},
+      {x: 3, y: 1, h: 2, id: 'no_move', noMove: true, content: 'no move'},
+      {x: 4, y: 1, id: '2'},
+      {x: 2, y: 3, w: 3, id: 'no_resize', noResize: true, content: 'no resize'},
+      {x: 1, y: 3, id: 'locked', locked: true, content: 'locked'}
+    ];
+    grid.load(serializedData);
+
+    GridStack.setupDragIn('.sidebar>.grid-stack-item');
+
+    // grid.setStatic(false); // TEST enable after disabled
+
+  </script>
+</body>
+</html>
diff --git a/demo/title_drag.html b/demo/title_drag.html
new file mode 100644
index 000000000..2e5307bfb
--- /dev/null
+++ b/demo/title_drag.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="utf-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <title>Title area drag</title>
+
+  <link rel="stylesheet" href="demo.css"/>
+  <script src="../node_modules/gridstack/dist/gridstack-all.js"></script>
+</head>
+<body>
+  <div class="container-fluid">
+    <h1>Title area drag</h1>
+    <br><br>
+    <div class="grid-stack">
+      <div class="grid-stack-item" gs-w="3" gs-h="3"><div class="grid-stack-item-content">
+        <div class="card-header">- Drag here -</div>
+        <div class="card">the rest of the panel content doesn't drag</div>
+      </div></div>
+    </div>
+  </div>
+  <script src="events.js"></script>
+  <script type="text/javascript">
+    let grid = GridStack.init({ handle: '.card-header' }); // drag by the header only
+    addEvents(grid);
+  </script>
+</body>
+</html>
diff --git a/demo/transform.html b/demo/transform.html
new file mode 100644
index 000000000..bc2e9f017
--- /dev/null
+++ b/demo/transform.html
@@ -0,0 +1,122 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="utf-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <title>Transform Parent demo</title>
+
+  <link rel="stylesheet" href="demo.css"/>
+  <script src="../node_modules/gridstack/dist/gridstack-all.js"></script>
+
+</head>
+<body>
+  <div class="container-fluid">
+    <h1>Transform Parent demo</h1>
+    <p>example where the grid parent has a translate(50px, 100px) and a scale(<span id="scale-x"></span>, <span id="scale-y"></span>)</p>
+    <div>
+      <a class="btn btn-primary" onClick="addNewWidget()" href="#">Add Widget</a>
+      <a class="btn btn-primary" onClick="zoomIn()" href="#">Zoom in</a>
+      <a class="btn btn-primary" onClick="zoomOut()" href="#">Zoom out</a>
+      <a class="btn btn-primary" onClick="increaseScaleX()" href="#">Increase Scale X</a>
+      <a class="btn btn-primary" onClick="decreaseScaleX()" href="#">Decrease Scale X</a>
+      <a class="btn btn-primary" onClick="increaseScaleY()" href="#">Increase Scale Y</a>
+      <a class="btn btn-primary" onClick="decreaseScaleY()" href="#">Decrease Scale Y</a>
+    </div>
+    <br><br>
+    <div style="transform: translate(50px, 100px) scale(var(--global-scale-x), var(--global-scale-y)); transform-origin: 0 0;">
+        <div class="grid-stack"></div>
+    </div>
+  </div>
+  <script src="events.js"></script>
+  <script type="text/javascript">
+    let scaleX = 0.5;
+    let scaleY = 0.5;
+
+    let grid = GridStack.init({float: true});
+    addEvents(grid);
+
+    let items = [
+      {x: 0, y: 0, w: 2, h: 2},
+      {x: 2, y: 0, w: 1},
+      {x: 3, y: 0, h: 1},
+      {x: 0, y: 2, w: 2},
+    ];
+    let count = 0;
+
+    getNode = function() {
+      let n = items[count] || {
+        x: Math.round(12 * Math.random()),
+        y: Math.round(5 * Math.random()),
+        w: Math.round(1 + 3 * Math.random()),
+        h: Math.round(1 + 3 * Math.random())
+      };
+      n.content = n.content || String(count);
+      count++;
+      return n;
+    };
+
+    addNewWidget = function() {
+      let w = grid.addWidget(getNode());
+    };
+
+    const updateScaleCssVariable = () => {
+      document.body.style.setProperty('--global-scale-x', `${scaleX}`);
+      document.body.style.setProperty('--global-scale-y', `${scaleY}`);
+      document.getElementById("scale-x").textContent = scaleX.toFixed(2);
+      document.getElementById("scale-y").textContent = scaleY.toFixed(2);
+    }
+
+    zoomIn = function() {
+      const scaleStep = scaleX < 1 ? 0.05 : 0.1;
+      scaleX += scaleStep;
+      scaleY += scaleStep;
+      updateScaleCssVariable();
+    }
+
+    zoomOut = function() {
+      if(scaleX >= 0.2 && scaleY >= 0.2) {
+        const scaleStep = scaleX < 1 ? 0.05 : 0.1;
+        scaleX -= scaleStep;
+        scaleY -= scaleStep;
+        updateScaleCssVariable();
+      }
+    }
+
+    increaseScaleX = function() {
+      const scaleStep = scaleX < 1 ? 0.05 : 0.1;
+      scaleX += scaleStep;
+      updateScaleCssVariable();
+    }
+
+    decreaseScaleX = function() {
+      if(scaleX >= 0.2) {
+        const scaleStep = scaleX < 1 ? 0.05 : 0.1;
+        scaleX -= scaleStep;
+        updateScaleCssVariable();
+      }
+    }
+
+    increaseScaleY = function() {
+      const scaleStep = scaleX < 1 ? 0.05 : 0.1;
+      scaleY += scaleStep;
+      updateScaleCssVariable();
+    }
+    
+    decreaseScaleY = function() {
+      if(scaleY >= 0.2) {
+        const scaleStep = scaleX < 1 ? 0.05 : 0.1;
+        scaleY -= scaleStep;
+        updateScaleCssVariable();
+      }
+    }
+
+    updateScaleCssVariable();
+
+
+    addNewWidget();
+    addNewWidget();
+    addNewWidget();
+  </script>
+</body>
+</html>
diff --git a/demo/two.html b/demo/two.html
new file mode 100644
index 000000000..621ee84a8
--- /dev/null
+++ b/demo/two.html
@@ -0,0 +1,127 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="utf-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <title>Two grids demo</title>
+
+  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
+  <link rel="stylesheet" href="demo.css"/>
+  <style type="text/css">
+    .with-lines { border: 1px dotted #777}
+  </style>
+
+  <script src="../node_modules/gridstack/dist/gridstack-all.js"></script>
+</head>
+<body>
+  <div class="container-fluid">
+    <h1>Two grids demo</h1>
+    <p>Two grids, one floating one not, showing drag&drop from sidebar and between grids.
+    <br>New v10.2: use 'Esc' to cancel any move/resize. Use 'r' to rotate as you drag.</p>
+
+    <div class="row">
+      <div class="col-md-8">
+        <!-- NOTE: add .grid-stack-item for acceptWidgets:true, but not needed for function which handles .sidebar-item (anything) -->
+        <div class="sidebar">
+          <!-- will size to match content. Also see sidebarContent -->
+          <div class="sidebar-item">Drag me</div>
+          <!-- constrained in code using GridStackWidget[] sidebarContent -->
+          <div class="sidebar-item">2x1, max=3</div>
+          <!-- DOM JSON spelling GridStackWidget. NOTE: require content:'xyz' to work and RenderCB() to render -->
+          <div class="sidebar-item" data-gs-widget='{"w":3, "content":"drop w:3"}'>w:3</div>
+          <!-- DOM id handled by myClone() case -->
+          <div class="sidebar-item" gs-id="manual">gs-id case</div>
+          <!-- DOM require proper GS format to be dropped as is without GridStackWidget above -->
+          <div class="grid-stack-item" gs-w="3">
+            <div class="grid-stack-item-content">DOM gs-w:3</div>
+          </div>
+          <div class="grid-stack-item" data-gs-widget='{"w":2}'>
+            <div class="grid-stack-item-content">DOM w:2</div>
+          </div>
+        </div>
+      </div>
+      <div class="col-md-4">
+        <div class="trash" id="trash">
+        </div>
+      </div>
+    </div>
+
+    <div class="row" style="margin-top: 20px">
+      <div class="col-md-6">
+        <a onClick="toggleFloat(this, 0)" class="btn btn-primary" href="#">float: true</a>
+        <a onClick="compact(0)" class="btn btn-primary" href="#">Compact</a>
+        <div class="grid-stack" id="left_grid"></div>
+      </div>
+      <div class="col-md-6">
+        <a onClick="toggleFloat(this, 1)" class="btn btn-primary" href="#">float: false</a>
+        <a onClick="compact(1)" class="btn btn-primary" href="#">Compact</a>
+        <div class="grid-stack" id="right_grid"></div>
+      </div>
+    </div>
+  </div>
+  <script src="events.js"></script>
+  <script type="text/javascript">
+    let items = [
+      {x: 0, y: 0, w: 2, h: 2},
+      {x: 1, y: 1, h: 2}, // intentional overlap to test collision on load
+      {x: 1, y: 1}, // intentional overlap to test collision on load
+      {x: 3, y: 1},
+      {x: 2, y: 3, w: 3, maxW: 3, content: 'has maxW=3'},
+      {x: 2, y: 5}
+    ];
+    items.forEach((item, i) => item.content = item.content || String(i));
+
+    // sidebar content (just 2, rest is other behavior) to create when we get dropped, instead of inserting the clone version
+    let sidebarContent = [
+      {content: 'dropped', id: 'dup_id'}, // test to make sure unique ids are created when dropped mutliple times...
+      {content: 'max=3', w:2, h:1, maxW: 3},
+    ];
+
+    let options = {
+      column: 6,
+      minRow: 1, // don't collapse when empty
+      cellHeight: 70,
+      float: true,
+      removable: '.trash', // true or drag-out delete class
+      /** accepts everything fcn, not just .grid-stack-item (true case) but can also be: true | false | '.someClass' value */
+      acceptWidgets: function(el) { return true },
+      children: items,
+      // itemClass: 'with-lines', // test a custom additional class #2110
+    };
+    let grids = GridStack.initAll(options);
+    grids[1].float(false);
+
+    // new v4 static method instead of setting up options on every grid (never been per grid really)
+    // new v11 method takes GridStackWidget[] to specify what to create on drop
+    // NOTE: helper:'clone' is default and typically used but have custom logic here to showcase
+    // NOTE2: handle not set to drag entire self.
+    GridStack.setupDragIn('.sidebar-item, .sidebar>.grid-stack-item', { helper: myClone }, sidebarContent);
+    // GridStack.setupDragIn(); // second call will now work (cache last values)
+
+    grids.forEach(function (grid, i) {
+      addEvents(grid, i);
+    });
+
+    // clone the sidepanel item so we drag a copy, and in some case ('manual') create the final widget, else sidebarContent will be used.
+    function myClone(el) {
+      if (el.getAttribute('gs-id') === 'manual') {
+        return grids[0].createWidgetDivs({w:2, content:'manual'}); // RenderCB() will be called
+      }
+      el = el.cloneNode(true);
+      // el.setAttribute('gs-id', 'foo'); // help debug #2231
+      // el.innerHTML = 'cloned'; // help debug
+      return el;
+    }
+
+    function toggleFloat(button, i) {
+      grids[i].float(! grids[i].getFloat());
+      button.innerHTML = 'float: ' + grids[i].getFloat();
+    }
+
+    function compact(i) {
+      grids[i].compact();
+    }
+  </script>
+</body>
+</html>
diff --git a/demo/two_vertical.html b/demo/two_vertical.html
new file mode 100644
index 000000000..9c671dc1a
--- /dev/null
+++ b/demo/two_vertical.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="utf-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <title>Two vertical grids demo</title>
+  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
+  <link rel="stylesheet" href="demo.css"/>
+  <script src="../node_modules/gridstack/dist/gridstack-all.js"></script>
+</head>
+<body>
+  <div class="container-fluid">
+    <h1>Two vertical grids demo - with maxRow</h1>
+    <p>special care is needed to prevent top grid from growing and causing shifts while you are dragging (which is a know issue).<br>
+    You can either set a fix row, or have enough padding on a parent div to allow for an extra row to be created as needed), or....</p>
+    <div class="grid-stack" id="grid1"></div>
+    <br>
+    <div class="grid-stack" id="grid2"></div>
+  </div>
+  <script src="events.js"></script>
+  <script type="text/javascript">
+    let opts = {
+      row: 1, // set min and max row to freeze the height
+      dragOut: true,
+      acceptWidgets: true
+    }
+    GridStack.init(opts, document.getElementById('grid1'))
+      .load([{x:0, y:0, content: '0'}, {x:1, y:0, content: '1'}]);
+    GridStack.init(opts, document.getElementById('grid2'))
+      .load([{x:0, y:0, content: '2'}, {x:1, y:0, content: '3'}]);
+  </script>
+</body>
+</html>
diff --git a/demo/vue2js.html b/demo/vue2js.html
new file mode 100644
index 000000000..5cd015e41
--- /dev/null
+++ b/demo/vue2js.html
@@ -0,0 +1,89 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="UTF-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+    <title>Gridstack.js Vue integration example</title>
+    <link rel="stylesheet" href="demo.css"/>
+    <script src="../node_modules/gridstack/dist/gridstack-all.js"></script>
+  </head>
+  <body>
+    <main id="app">
+      <h1>How to integrate GridStack.js with Vue.js</h1>
+      <p>
+        As with any virtual DOM based framework, you need to check if Vue has
+        rendered the DOM (or any updates to it) <strong>before</strong> you
+        initialize GridStack or call its methods. As a basic example, check this
+        component's <code>mounted</code> hook.
+      </p>
+      <p>
+        If your app requires more complex render logic than the inline template
+        in `addWidget`, consider
+        <a
+          href="https://github.com/gridstack/gridstack.js/tree/master/doc#makewidgetel"
+          >makeWidget</a
+        >
+        to let Vue deal with DOM rendering.
+      </p>
+      <button type="button" @click="addNewWidget()">Add Widget</button> {{ info }}
+      <div class="grid-stack"></div>
+    </main>
+    <script type="module">
+      import Vue from "https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.esm.browser.js";
+
+      let app = new Vue({
+        el: "#app",
+        data: {
+          // Reference to the GridStack instance to access it later
+          grid: undefined,
+          count: 0,
+          info: "",
+          timerId: undefined,
+        },
+        items: [
+          { x: 2, y: 1, h: 2 },
+          { x: 2, y: 4, w: 3},
+          { x: 4, y: 2},
+          { x: 3, y: 1, h: 2 },
+          { x: 0, y: 6, w: 2, h: 2 }
+        ],
+        watch: {
+          /**
+           * Clear the info text after a two second timeout. Clears previous timeout first.
+           */
+          info: function (newVal, oldVal) {
+            if (newVal.length === 0) return;
+
+            window.clearTimeout(this.timerId);
+            this.timerId = window.setTimeout(() => {
+              this.info = "";
+            }, 2000);
+          },
+        },
+        mounted: function () {
+          // Provides access to the GridStack instance across the Vue component.
+          this.grid = GridStack.init({ float: true, cellHeight: '70px', minRow: 1 });
+
+          // Use an arrow function so that `this` is bound to the Vue instance. Alternatively, use a custom Vue directive on the `.grid-stack` container element: https://vuejs.org/v2/guide/custom-directive.html
+          this.grid.on("dragstop", (event, element) => {
+            const node = element.gridstackNode;
+            // `this` will only access your Vue instance if you used an arrow function, otherwise `this` binds to window scope. see https://hacks.mozilla.org/2015/06/es6-in-depth-arrow-functions/
+            this.info = `you just dragged node #${node.id} to ${node.x},${node.y} – good job!`;
+          });
+        },
+        methods: {
+          addNewWidget: function () {
+            const node = this.$options.items[this.count] || {
+              x: Math.round(12 * Math.random()),
+              y: Math.round(5 * Math.random()),
+              w: Math.round(1 + 3 * Math.random()),
+              h: Math.round(1 + 3 * Math.random()),
+            };
+            node.id = node.content = String(this.count++);
+            this.grid.addWidget(node);
+          },
+        },
+      });
+    </script>
+  </body>
+</html>
diff --git a/demo/vue3js.html b/demo/vue3js.html
new file mode 100644
index 000000000..0c15d3ce7
--- /dev/null
+++ b/demo/vue3js.html
@@ -0,0 +1,93 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="UTF-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+    <title>Vue3 Gridstack</title>
+    <link rel="stylesheet" href="demo.css"/>
+    <script src="../node_modules/gridstack/dist/gridstack-all.js"></script>
+  </head>
+  <body>
+    <main id="app">
+      <h1>How to integrate GridStack.js with Vue.js</h1>
+      <p>
+        As with any virtual DOM based framework, you need to check if Vue has
+        rendered the DOM (or any updates to it) <strong>before</strong> you
+        initialize GridStack or call its methods. As a basic example, check this
+        component's <code>mounted</code> hook.
+      </p>
+      <p>
+        If your app requires more complex render logic than the inline template
+        in `addWidget`, consider
+        <a
+          href="https://github.com/gridstack/gridstack.js/tree/master/doc#makewidgetel"
+          >makeWidget</a
+        >
+        to let Vue deal with DOM rendering.
+      </p>
+      <button type="button" @click="addNewWidget()">Add Widget</button> {{ info }}
+      <div class="grid-stack"></div>
+    </main>
+    <script type="module">
+      import { createApp, ref, onMounted } from "https://cdn.jsdelivr.net/npm/vue@3.0.11/dist/vue.esm-browser.js";
+
+      createApp({
+        setup() {
+          let count = ref(0);
+          let info = ref("");
+          let grid = null; // DO NOT use ref(null) as proxies GS will break all logic when comparing structures... see https://github.com/gridstack/gridstack.js/issues/2115
+          const items = [
+            { x: 2, y: 1, h: 2 },
+            { x: 2, y: 4, w: 3 },
+            { x: 4, y: 2 },
+            { x: 3, y: 1, h: 2 },
+            { x: 0, y: 6, w: 2, h: 2 },
+          ];
+
+          onMounted(() => {
+            grid = GridStack.init({ // DO NOT use grid.value = GridStack.init(), see above
+              float: true,
+              cellHeight: "70px",
+              minRow: 1,
+            });
+
+            grid.on("dragstop", function (event, element) {
+              const node = element.gridstackNode;
+              info.value = `you just dragged node #${node.id} to ${node.x},${node.y} – good job!`;
+            });
+          });
+
+          function addNewWidget() {
+            const node = items[count.value] || {
+              x: Math.round(12 * Math.random()),
+              y: Math.round(5 * Math.random()),
+              w: Math.round(1 + 3 * Math.random()),
+              h: Math.round(1 + 3 * Math.random()),
+            };
+            node.id = node.content = String(count.value++);
+            grid.addWidget(node);
+          }
+
+          return {
+            info,
+            addNewWidget,
+          };
+        },
+
+        watch: {
+          /**
+           * Clear the info text after a two second timeout. Clears previous timeout first.
+           */
+          info: function (newVal) {
+            if (newVal.length === 0) return;
+
+            window.clearTimeout(this.timerId);
+            this.timerId = window.setTimeout(() => {
+              this.info = "";
+            }, 2000);
+          },
+        },
+      }).mount("#app");
+    </script>
+  </body>
+</html>
diff --git a/demo/vue3js_dynamic-modern-renderCB.html b/demo/vue3js_dynamic-modern-renderCB.html
new file mode 100644
index 000000000..f796ce72a
--- /dev/null
+++ b/demo/vue3js_dynamic-modern-renderCB.html
@@ -0,0 +1,157 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+  <meta charset="UTF-8" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+  <title>Vue3 Gridstack: Gridstack DOM with Vue Rendering</title>
+  <link rel="stylesheet" href="demo.css" />
+  <script src="../node_modules/gridstack/dist/gridstack-all.js"></script>
+</head>
+
+<body>
+  <main id="app">
+    <a href="./index.html">Back to All Demos</a>
+    <h1>Vue3: Gridstack Controls Vue Rendering Grid Items</h1>
+    <p>
+      <strong>Use Vue3 render functions with GridStack.renderCB</strong><br />
+      GridStack handles widget creation and Vue handles rendering the content using the modern (since V11) GridStack.renderCB.
+    </p>
+    <p>
+      Helpful Resources:
+    <ul>
+      <li><a href="https://vuejs.org/guide/extras/render-function.html#render-functions-jsx" target="_blank">Vue Render Functions</a></li>
+      <li><a href="https://stackblitz.com/edit/vitejs-vite-phhdkeju" target="_blank">This Demo as a Vue SFC on Stackblitz</a></li>
+    </ul>
+    </p>
+    <button type="button" @click="addNewWidget">Add Widget</button> {{ info }}
+    <div class="grid-stack"></div>
+  </main>
+  <script type="module">
+    import { createApp, ref, onMounted, onBeforeUnmount, h, render, toRefs } from "https://cdn.jsdelivr.net/npm/vue@3.0.11/dist/vue.esm-browser.js";
+
+    const GridItemComponent = {
+      props: {
+        itemId: {
+          type: [String, Number],
+          required: true,
+        },
+      },
+      emits: ['remove'],
+      setup(props, { emit }) {
+        const { itemId } = toRefs(props)
+
+        onBeforeUnmount(() => {
+          console.log(`In vue onBeforeUnmount for item ${itemId.value}`)
+        });
+
+        function handleRemove() {
+          emit('remove')
+        }
+
+        return {
+          itemId,
+          handleRemove,
+        }
+      },
+      template: `
+        <button @click="handleRemove">X</button>
+        <p>
+            Vue Grid Item {{ itemId }}
+        </p>
+        `
+    }
+
+    createApp({
+      setup() {
+        let info = ref("");
+        let grid = null;
+        const items = [
+          { id: 1, x: 2, y: 1, h: 2 },
+          { id: 2, x: 2, y: 4, w: 3 },
+          { id: 3, x: 4, y: 2 },
+          { id: 4, x: 3, y: 1, h: 2 },
+          { id: 5, x: 0, y: 6, w: 2, h: 2 },
+        ];
+        let count = ref(items.length);
+        const shadowDom = {}
+
+        onMounted(() => {
+          grid = GridStack.init({
+            float: true,
+            cellHeight: "70px",
+            minRow: 1,
+          });
+
+          // Listen for remove events to clean up Vue renders
+          grid.on('removed', function (event, items) {
+            items.forEach(item => {
+              if (shadowDom[item.id]) {
+                render(null, shadowDom[item.id]);
+                delete shadowDom[item.id];
+              }
+            });
+          });
+
+          GridStack.renderCB = function (el, widget) {
+            // el: HTMLElement div.grid-stack-item-content
+            // widget: GridStackWidget
+
+            const gridItemEl = el.closest('.grid-stack-item'); // div.grid-stack-item (parent of el)
+
+            // Create Vue component for the widget content
+            const itemId = widget.id
+            const widgetNode = h(GridItemComponent, {
+              itemId: itemId,
+              onRemove: () => { // Catch the remove event from the Vue component
+                grid.removeWidget(gridItemEl); // div.grid-stack-item
+                info.value = `Widget ${itemId} removed`;
+              }
+            })
+            shadowDom[itemId] = el
+            render(widgetNode, el) // Render Vue component into the GridStack-created element
+          }
+
+          grid.load(items);
+        });
+
+        onBeforeUnmount(() => {
+          // Clean up Vue renders
+          Object.values(shadowDom).forEach(el => {
+            render(null, el)
+          })
+        });
+
+        function addNewWidget() {
+          const node = items[count.value] || {
+            x: Math.round(12 * Math.random()),
+            y: Math.round(5 * Math.random()),
+            w: Math.round(1 + 3 * Math.random()),
+            h: Math.round(1 + 3 * Math.random()),
+          };
+          node.id = String(count.value++);
+          grid.addWidget(node);
+          info.value = `Widget ${node.id} added`;
+        }
+
+        return {
+          info,
+          addNewWidget,
+        };
+      },
+
+      watch: {
+        info: function (newVal) {
+          if (newVal.length === 0) return;
+
+          window.clearTimeout(this.timerId);
+          this.timerId = window.setTimeout(() => {
+            this.info = "";
+          }, 2000);
+        },
+      },
+    }).mount("#app");
+  </script>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/demo/vue3js_dynamic-render_grid-item-content.html b/demo/vue3js_dynamic-render_grid-item-content.html
new file mode 100644
index 000000000..441e742ef
--- /dev/null
+++ b/demo/vue3js_dynamic-render_grid-item-content.html
@@ -0,0 +1,161 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="UTF-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+    <title>Vue3 Gridstack: Gridstack DOM with Vue Rendering</title>
+    <link rel="stylesheet" href="demo.css"/>
+    <script src="../node_modules/gridstack/dist/gridstack-all.js"></script>
+  </head>
+  <body>
+    <main id="app">
+      <a href="./index.html">Back to All Demos</a>
+      <h1>Vue3: Gridstack Controls Vue Rendering Grid Item Content</h1>
+      <p>
+        <strong>Use Vue3 render functions to dynamically render only the grid item content.</strong><br />
+        GridStack is handles when items are added/removed, rendering grid item element, and Vue handles rendering <i>only</i> the item content.
+      </p>
+      <p>
+        Helpful Resources:
+        <ul>
+          <li><a href="https://vuejs.org/guide/extras/render-function.html#render-functions-jsx" target="_blank">Vue Render Functions</a></li>
+        </ul>
+      </p>
+      <p>
+        Notes:
+        <ul>
+          <li>This implementation currently does not support nested grid</li>
+        </ul>
+      </p>
+      <button type="button" @click="addNewWidget()">Add Widget</button> {{ info }}
+      <div class="grid-stack"></div>
+    </main>
+    <script type="module">
+      import { createApp, ref, onMounted, onBeforeUnmount, h, render, toRefs } from "https://cdn.jsdelivr.net/npm/vue@3.0.11/dist/vue.esm-browser.js";
+
+      const GridContentComponent = {
+        props: {
+          itemId: {
+            type: [String, Number],
+            required: true,
+          },
+        },
+        emits: ['remove'],
+        setup(props, { emit }) {
+          const { itemId } = toRefs(props)
+
+          onBeforeUnmount(() => {
+            console.log(`In vue onBeforeUnmount for item ${itemId.value}`)
+          });
+
+          function handleRemove() {
+            emit('remove', itemId.value)
+          }
+
+          return {
+            itemId,
+            handleRemove,
+          }
+        },
+        template: `
+          <div class="my-custom-grid-item-content">
+            <button @click=handleRemove>X</button>
+            <p>
+              Vue Grid Item Content {{ itemId }}
+            </p>
+          </div>
+        `
+      }
+
+      createApp({
+        setup() {
+          let info = ref("");
+          let grid = null; // DO NOT use ref(null) as proxies GS will break all logic when comparing structures... see https://github.com/gridstack/gridstack.js/issues/2115
+          const items = [
+            { id: 1, x: 2, y: 1, h: 2 },
+            { id: 2, x: 2, y: 4, w: 3 },
+            { id: 3, x: 4, y: 2 },
+            { id: 4, x: 3, y: 1, h: 2 },
+            { id: 5, x: 0, y: 6, w: 2, h: 2 },
+          ];
+          let count = ref(items.length);
+
+          onMounted(() => {
+            grid = GridStack.init({ // DO NOT user grid.value = GridStack.init(), see above
+              float: true,
+              cellHeight: "70px",
+              minRow: 1,
+            });
+
+            grid.on('added', function(event, items) {
+              for (const item of items) {
+                const itemEl = item.el
+                const itemElContent = itemEl.querySelector('.grid-stack-item-content')
+
+                const itemId = item.id
+
+                // Use Vue's render function to create the content
+                // See https://vuejs.org/guide/extras/render-function.html#render-functions-jsx
+                //      Supports: emit, slots, props, attrs, see onRemove event below
+                const itemContentVNode = h(
+                  GridContentComponent,
+                  {
+                    itemId: itemId,
+                    onRemove: (itemId) => {
+                      grid.removeWidget(itemEl)
+                    }
+                  }
+                )
+
+                // Render the vue node into the item element
+                render(itemContentVNode, itemElContent)
+              }
+            });
+
+            grid.on('removed', function(event, items) {
+              for (const item of items) {
+                const itemEl = item.el
+                const itemElContent = itemEl.querySelector('.grid-stack-item-content')
+                // Unmount the vue node from the item element
+                // Calling render with null will allow vue to clean up the DOM, and trigger lifecycle hooks
+                render(null, itemElContent)
+              }
+            });
+
+            grid.load(items);
+          });
+
+          function addNewWidget() {
+            const node = items[count.value] || {
+              x: Math.round(12 * Math.random()),
+              y: Math.round(5 * Math.random()),
+              w: Math.round(1 + 3 * Math.random()),
+              h: Math.round(1 + 3 * Math.random()),
+            };
+            node.id = String(count.value++);
+            grid.addWidget(node);
+          }
+
+          return {
+            info,
+            addNewWidget,
+          };
+        },
+
+        watch: {
+          /**
+           * Clear the info text after a two second timeout. Clears previous timeout first.
+           */
+          info: function (newVal) {
+            if (newVal.length === 0) return;
+
+            window.clearTimeout(this.timerId);
+            this.timerId = window.setTimeout(() => {
+              this.info = "";
+            }, 2000);
+          },
+        },
+      }).mount("#app");
+    </script>
+  </body>
+</html>
diff --git a/demo/vue3js_dynamic-render_grid-item.html b/demo/vue3js_dynamic-render_grid-item.html
new file mode 100644
index 000000000..2f3567f41
--- /dev/null
+++ b/demo/vue3js_dynamic-render_grid-item.html
@@ -0,0 +1,168 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="UTF-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+    <title>Vue3 Gridstack: Gridstack DOM with Vue Rendering</title>
+    <link rel="stylesheet" href="demo.css"/>
+    <script src="../node_modules/gridstack/dist/gridstack-all.js"></script>
+  </head>
+  <body>
+    <main id="app">
+      <a href="./index.html">Back to All Demos</a>
+      <h1>Vue3: Gridstack Controls Vue Rendering Grid Item</h1>
+      <p>
+        <strong>Use Vue3 render functions to dynamically render the entire Gridstack item (wrapper and contents)</strong><br />
+        GridStack is handles when items are added/removed, and Vue handles rendering of the entire item in <code>GridStack.addRemoveCB</code>.
+      </p>
+      <p>
+        Helpful Resources:
+        <ul>
+          <li><a href="https://vuejs.org/guide/extras/render-function.html#render-functions-jsx" target="_blank">Vue Render Functions</a></li>
+        </ul>
+      </p>
+      <p>
+        Notes:
+        <ul>
+          <li>This implementation currently does not support nested grid</li>
+        </ul>
+      </p>
+      <button type="button" @click="addNewWidget()">Add Widget</button> {{ info }}
+      <div class="grid-stack"></div>
+    </main>
+    <script type="module">
+      import { createApp, ref, onMounted, onBeforeUnmount, h, render, toRefs } from "https://cdn.jsdelivr.net/npm/vue@3.0.11/dist/vue.esm-browser.js";
+
+      const GridItemComponent = {
+        props: {
+          itemId: {
+            type: [String, Number],
+            required: true,
+          },
+        },
+        emits: ['remove'],
+        setup(props, { emit }) {
+          const root = ref(null)
+          const { itemId } = toRefs(props)
+
+          onBeforeUnmount(() => {
+            console.log(`In vue onBeforeUnmount for item ${itemId.value}`)
+          });
+
+          function handleRemove() {
+            emit('remove', root.value)
+          }
+
+          return {
+            root,
+            itemId,
+            handleRemove,
+          }
+        },
+        template: `
+          <div ref="root" class="grid-stack-item my-custom-grid-item-component">
+            <div class="grid-stack-item-content">
+              <button @click=handleRemove>X</button>
+              <p>
+                Vue Grid Item {{ itemId }}
+              </p>
+            </div>
+          </div>
+        `
+      }
+
+      createApp({
+        setup() {
+          let info = ref("");
+          let grid = null; // DO NOT use ref(null) as proxies GS will break all logic when comparing structures... see https://github.com/gridstack/gridstack.js/issues/2115
+          const items = [
+            { id: 1, x: 2, y: 1, h: 2 },
+            { id: 2, x: 2, y: 4, w: 3 },
+            { id: 3, x: 4, y: 2 },
+            { id: 4, x: 3, y: 1, h: 2 },
+            { id: 5, x: 0, y: 6, w: 2, h: 2 },
+          ];
+          let count = ref(items.length);
+          const shadowDom = {}
+
+          onMounted(() => {
+            grid = GridStack.init({ // DO NOT user grid.value = GridStack.init(), see above
+              float: true,
+              cellHeight: "70px",
+              minRow: 1,
+            });
+
+            GridStack.addRemoveCB = gsAddRemoveVueComponents;
+
+            grid.load(items);
+          });
+
+          function gsAddRemoveVueComponents(host, item, add, isGrid) {
+            if (!host) {
+              return
+            }
+
+            // Not supported yet
+            if (isGrid) {
+              return;
+            }
+
+            if (add) {
+              const itemId = item.id
+
+              // Use Vue's render function to create the content
+              // See https://vuejs.org/guide/extras/render-function.html#render-functions-jsx
+              //      Supports: emit, slots, props, attrs, see onRemove event below
+              const itemVNode = h(
+                GridItemComponent,
+                {
+                  itemId: itemId,
+                  onRemove: (itemEl) => {
+                    grid.removeWidget(itemEl)
+                  }
+                }
+              )
+              shadowDom[itemId] = document.createElement('div')
+              render(itemVNode, shadowDom[itemId])
+              return itemVNode.el
+            } else {
+              const itemId = item.id
+              render(null, shadowDom[itemId])
+              return;
+            }
+          }
+
+          function addNewWidget() {
+            const node = items[count.value] || {
+              x: Math.round(12 * Math.random()),
+              y: Math.round(5 * Math.random()),
+              w: Math.round(1 + 3 * Math.random()),
+              h: Math.round(1 + 3 * Math.random()),
+            };
+            node.id = String(count.value++);
+            grid.addWidget(node);
+          }
+
+          return {
+            info,
+            addNewWidget,
+          };
+        },
+
+        watch: {
+          /**
+           * Clear the info text after a two second timeout. Clears previous timeout first.
+           */
+          info: function (newVal) {
+            if (newVal.length === 0) return;
+
+            window.clearTimeout(this.timerId);
+            this.timerId = window.setTimeout(() => {
+              this.info = "";
+            }, 2000);
+          },
+        },
+      }).mount("#app");
+    </script>
+  </body>
+</html>
diff --git a/demo/vue3js_v-for.html b/demo/vue3js_v-for.html
new file mode 100644
index 000000000..6f1ce29c6
--- /dev/null
+++ b/demo/vue3js_v-for.html
@@ -0,0 +1,163 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+  <meta charset="UTF-8" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+  <title>Vue3 v-for Gridstack</title>
+  <link rel="stylesheet" href="demo.css" />
+  <script src="../node_modules/gridstack/dist/gridstack-all.js"></script>
+</head>
+
+<body>
+  <main id="app">
+    <h1>How to integrate GridStack.js with Vue.js</h1>
+    <p>
+      As with any virtual DOM based framework, you need to check if Vue has
+      rendered the DOM (or any updates to it) <strong>before</strong> you
+      initialize GridStack or call its methods. As a basic example, check this
+      component's <code>mounted</code> hook.
+    </p>
+    <p>
+      If your app requires more complex render logic than the inline template
+      in `addWidget`, consider
+      <a href="https://github.com/gridstack/gridstack.js/tree/master/doc#makewidgetel">makeWidget</a>
+      to let Vue deal with DOM rendering.
+    </p>
+    <button type="button" @click="addNewWidget2()">Add Widget pos [0,0]</button>
+    <button type="button" @click="removeLastWidget()">Remove Last Widget</button>
+    <br>
+    <br>
+    <button type="button" @click="changeFloat()">Float: {{gridFloat}}</button>
+
+    <div>{{ info }}</div>
+    <br>
+    <div><b :style="{color: color}">{{ gridInfo }}</b></div>
+    <br>
+
+    <div class="grid-stack">
+      <div v-for="(w, indexs) in items" class="grid-stack-item" :gs-x="w.x" :gs-y="w.y" :gs-w="w.w" :gs-h="w.h"
+        :gs-id="w.id" :id="w.id" :key="w.id">
+        <div class="grid-stack-item-content">
+          <button @click="remove(w)">remove</button>
+          {{w}}
+        </div>
+      </div>
+    </div>
+
+  </main>
+  <script type="module">
+    import { createApp, ref, onMounted, nextTick } from "https://cdn.jsdelivr.net/npm/vue@3.0.11/dist/vue.esm-browser.js";
+
+      createApp({
+        setup() {
+          let count = ref(0);
+          let info = ref("");
+          let gridFloat = ref(false);
+          let color = ref("black");
+          let gridInfo = ref("");
+          let grid = null; // DO NOT use ref(null) as proxies GS will break all logic when comparing structures... see https://github.com/gridstack/gridstack.js/issues/2115
+          let items = ref([]);
+
+          onMounted(() => {
+            grid = GridStack.init({ // DO NOT user grid.value = GridStack.init(), see above
+              float: false,
+              cellHeight: "70px",
+              minRow: 1,
+            });
+
+            grid.on("dragstop", function (event, element) {
+              const node = element.gridstackNode;
+              info.value = `you just dragged node #${node.id} to ${node.x},${node.y} – good job!`;
+            });
+            
+            grid.on('change', onChange);
+            // gridFloat.value = grid.float();
+          });
+          
+          function changeFloat() {
+            gridFloat.value = !gridFloat.value;
+            grid.float(gridFloat.value);
+          }
+          
+          function onChange(event, changeItems) {
+            updateInfo();
+            // update item position
+            changeItems.forEach(item => {
+              var widget = items.value.find(w => w.id == item.id);
+              if (!widget) {
+                alert("Widget not found: " + item.id);
+                return;
+              }
+              widget.x = item.x;
+              widget.y = item.y;
+              widget.w = item.w;
+              widget.h = item.h;            
+            });
+          }
+
+          function addNewWidget2() {
+            const node = items[count.value] || { x: 0, y: 0, w: 2, h: 2 };
+            node.id = 'w_'+ (count.value++);
+//          grid.addWidget(node);
+            items.value.push(node);
+            nextTick(()=>{
+              grid.makeWidget(node.id);
+              updateInfo();
+            });
+          }
+          
+          function removeLastWidget() {
+            if (count.value == 0) return;
+            var id = `w_${count.value-1}`;
+            var index = items.value.findIndex(w => w.id == id);    
+            if (index < 0) return;
+            var removed = items.value[index];
+            remove(removed);
+          }
+          
+          function remove(widget) {
+            var index = items.value.findIndex(w => w.id == widget.id);
+            items.value.splice(index, 1);
+            const selector = `#${widget.id}`;
+            grid.removeWidget(selector, false);
+            updateInfo();            
+          }
+          
+          function updateInfo() {
+            color.value = grid.engine.nodes.length == items.value.length ? "black" : "red";
+            gridInfo.value = `Grid engine: ${grid.engine.nodes.length}, widgets: ${items.value.length}`;
+          }
+
+          return {
+            info,
+            items,
+            addNewWidget2,
+            removeLastWidget,
+            onChange,
+            grid,
+            gridInfo,
+            remove,
+            gridFloat,
+            changeFloat,
+            color
+          };
+        },
+
+        watch: {
+          /**
+           * Clear the info text after a two second timeout. Clears previous timeout first.
+           */
+          info: function (newVal) {
+            if (newVal.length === 0) return;
+            window.clearTimeout(this.timerId);
+            this.timerId = window.setTimeout(() => {
+              this.info = "";
+            }, 2000);
+          },
+        },
+      }).mount("#app");
+    </script>
+</body>
+
+</html>
diff --git a/demo/web-comp.html b/demo/web-comp.html
new file mode 100644
index 000000000..4db376947
--- /dev/null
+++ b/demo/web-comp.html
@@ -0,0 +1,32 @@
+<html>
+<head>
+  <title>Web Component demo</title>
+  <!-- Polyfills only needed for Firefox and Edge. -->
+  <script src="https://unpkg.com/@webcomponents/webcomponentsjs@latest/webcomponents-loader.js"></script>
+  <link rel="stylesheet" href="demo.css"/>
+  <script src="../node_modules/gridstack/dist/gridstack-all.js"></script>
+</head>
+<body>
+  <h1>LitElement Web Component</h1>
+  <script type="module">
+    import {LitElement, html, css} from 'https://unpkg.com/lit-element@3/lit-element.js?module';
+
+    class MyElement extends LitElement {
+      static get properties() { return {} }
+      render() { return html`<style>:host {display: block;} </style><slot></slot>`; }
+    }
+    customElements.define('my-element', MyElement);
+</script>
+
+<my-element class="grid-stack"></my-element>
+
+<script type="text/javascript">
+  let items = [
+    {x:0, y:0, w:2, content: 'item 0'},
+    {x:0, y:1, content: 'item 1'}
+  ];
+  let grid = GridStack.init();
+  grid.load(items);
+</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/demo/web1.html b/demo/web1.html
new file mode 100644
index 000000000..ea6d37a22
--- /dev/null
+++ b/demo/web1.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+  <meta charset="utf-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <title>demo1</title>
+
+  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
+  <link rel="stylesheet" href="demo.css" />
+
+  <script type="module" src="https://unpkg.com/ionicons@4.5.10-0/dist/ionicons/ionicons.esm.js"></script>
+  <script nomodule="" src="https://unpkg.com/ionicons@4.5.10-0/dist/ionicons/ionicons.js"></script>
+  <script src="../node_modules/gridstack/dist/gridstack-all.js"></script>
+</head>
+
+<body>
+  <h1>Web demo 1</h1>
+  <div class="grid-stack"></div>
+
+  <script type="text/javascript">
+    // NOTE: REAL apps would sanitize-html or DOMPurify before blinding setting innerHTML. see #2736
+    GridStack.renderCB = function(el, w) {
+      el.innerHTML = w.content;
+    };
+
+    let children = [
+      {x: 0, y: 0, w: 4, h: 2, content: '1'},
+      {x: 4, y: 0, w: 4, h: 4, content: '2'},
+      {x: 8, y: 0, w: 2, h: 2, content: '<p class="card-text text-center" style="margin-bottom: 0">Drag me!<p class="card-text text-center"style="margin-bottom: 0"><ion-icon name="hand" style="font-size: 300%"></ion-icon><p class="card-text text-center" style="margin-bottom: 0">'},
+      {x: 10, y: 0, w: 2, h: 2, content: '4'},
+      {x: 0, y: 2, w: 2, h: 2, content: '5'},
+      {x: 2, y: 2, w: 2, h: 4, content: '6'},
+      {x: 8, y: 2, w: 4, h: 2, content: '7'},
+      {x: 0, y: 4, w: 2, h: 2, content: '8'},
+      {x: 4, y: 4, w: 4, h: 2, content: '9'},
+      {x: 8, y: 4, w: 2, h: 2, content: '10'},
+      {x: 10, y: 4, w: 2, h: 2, content: '11'},
+    ];
+
+    let grid = GridStack.init({ cellHeight: 70, children });
+    grid.on('added removed change', function(e, items) {
+      let str = '';
+      items.forEach(function(item) { str += ' (x,y)=' + item.x + ',' + item.y; });
+      console.log(e.type + ' ' + items.length + ' items:' + str );
+    });
+  </script>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/demo/web2.html b/demo/web2.html
new file mode 100644
index 000000000..74065c42e
--- /dev/null
+++ b/demo/web2.html
@@ -0,0 +1,92 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+  <meta charset="utf-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <title>Advanced grid demo</title>
+
+  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
+  <link rel="stylesheet" href="demo.css" />
+
+  <script type="module" src="https://unpkg.com/ionicons@4.5.10-0/dist/ionicons/ionicons.esm.js"></script>
+  <script nomodule="" src="https://unpkg.com/ionicons@4.5.10-0/dist/ionicons/ionicons.js"></script>
+  <script src="../node_modules/gridstack/dist/gridstack-all.js"></script>
+
+  <style type="text/css">
+    .grid-stack-item-removing {
+      opacity: 0.8;
+      filter: blur(5px);
+    }
+    .sidepanel-item {
+      background-color: #18bc9c;
+      text-align: center;
+      padding: 5px;
+      margin-bottom: 15px;
+    }
+    #trash {
+      background-color: rgba(255, 0, 0, 0.4);
+    }
+    ion-icon {
+      font-size: 300%;
+    }
+  </style>
+</head>
+
+<body>
+  <h1>Advanced Demo</h1>
+  <div class="row">
+    <div class="sidepanel col-md-2 d-none d-md-block">
+      <div id="trash" class="sidepanel-item">
+        <ion-icon name="trash"></ion-icon>
+        <div>Drop here to remove!</div>
+      </div>
+      <div class="grid-stack-item sidepanel-item">
+        <ion-icon name="add-circle"></ion-icon>
+        <div>Drag me in the dashboard!</div>
+      </div>
+    </div>
+    <div class="col-sm-12 col-md-10">
+      <div class="grid-stack"></div>
+    </div>
+  </div>
+
+  <script type="text/javascript">
+    // NOTE: REAL apps would sanitize-html or DOMPurify before blinding setting innerHTML. see #2736
+    GridStack.renderCB = function(el, w) {
+      el.innerHTML = w.content;
+    };
+
+    let children = [
+      {x: 0, y: 0, w: 4, h: 2, content: '1'},
+      {x: 4, y: 0, w: 4, h: 4, locked: true, content: 'locked: can\'t be pushed by others, only user!<br><ion-icon name="ios-lock"></ion-icon>'},
+      {x: 8, y: 0, w: 2, h: 2, minW: 2, noResize: true, content: '<p class="card-text text-center" style="margin-bottom: 0">Drag me!<p class="card-text text-center"style="margin-bottom: 0"><ion-icon name="hand"></ion-icon><p class="card-text text-center" style="margin-bottom: 0">...but don\'t resize me!'},
+      {x: 10, y: 0, w: 2, h: 2, content: '4'},
+      {x: 0, y: 2, w: 2, h: 2, content: '5'},
+      {x: 2, y: 2, w: 2, h: 4, content: '6'},
+      {x: 8, y: 2, w: 4, h: 2, content: '7'},
+      {x: 0, y: 4, w: 2, h: 2, content: '8'},
+      {x: 4, y: 4, w: 4, h: 2, content: '9'},
+      {x: 8, y: 4, w: 2, h: 2, content: '10'},
+      {x: 10, y: 4, w: 2, h: 2, content: '11'},
+    ];
+    let insert = [ {h: 2, content: 'new item'}];
+
+    let grid = GridStack.init({
+      cellHeight: 70,
+      acceptWidgets: true,
+      removable: '#trash', // drag-out delete class
+      children
+    });
+    GridStack.setupDragIn('.sidepanel>.grid-stack-item', undefined, insert);
+    
+    grid.on('added removed change', function(e, items) {
+      let str = '';
+      items.forEach(function(item) { str += ' (x,y)=' + item.x + ',' + item.y; });
+      console.log(e.type + ' ' + items.length + ' items:' + str );
+    });
+  </script>
+</body>
+
+</html>
diff --git a/demo/website.html b/demo/website.html
new file mode 100644
index 000000000..9b71d4704
--- /dev/null
+++ b/demo/website.html
@@ -0,0 +1,426 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+  <meta charset="utf-8" />
+  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
+  <meta name="description" content="gridstack.js Build interactive dashboards in minutes." />
+  <meta name="keywords"
+    content="gridstack, typescript, jquery, grid, layout, drag-n-drop, widgets, js, javascript, gridstack.js, dashboard" />
+  <title>gridstack.js | Build interactive dashboards in minutes.</title>
+  <script src="../node_modules/gridstack/dist/gridstack-all.js"></script>
+  
+  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
+  <script src="https://getbootstrap.com/docs/4.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-xrRywqdh3PHs8keKZN+8zzc5TX0GRTLCcmivcbNJWm2rs5C8PRhcEn3czEjhAO9o" crossorigin="anonymous"></script>
+  <script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@9.16.2/build/highlight.min.js"></script>
+
+  <!-- Bootstrap core CSS -->
+  <link href="https://bootswatch.com/4/yeti/bootstrap.min.css" rel="stylesheet" />
+  <link href="../node_modules/gridstack/dist/gridstack.min.css" rel="stylesheet" />
+  <link href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@9.16.2/build/styles/default.min.css"  rel="stylesheet"/>
+  <style type="text/css">
+    .grid-container {
+      padding: 15px;
+      border: 1px solid white;
+      max-width: 1000px;
+    }
+    .center {
+      margin-left: auto;
+      margin-right: auto;
+    }
+    .grid-stack-item {
+      border: 0;
+    }
+    .grid-stack-item-content {
+      background-color: white;
+      text-align: center;
+    }
+    h1 {
+      text-align: center;
+      font-size: 3rem;
+      margin-top: 2rem;
+      margin-bottom: 1.5rem;
+    }
+    .card {
+      background: none;
+    }
+    section {
+      padding: 0 15px 0 15px;
+    }
+    .grid-stack-item-removing {
+      opacity: 0.8;
+      filter: blur(5px);
+    }
+    @media all and (max-width: 575px) {
+      #hero {
+        margin-top: 32px;
+      }
+    }
+    .logo {
+      display: inline;
+      margin-right: 15px;
+    }
+    #trash {
+      background-color: #cc6857;
+    }
+    .newWidget > .grid-stack-item-content {
+      background-color: #6cad84;
+    }
+  </style>
+</head>
+
+<body>
+  <nav class="navbar navbar-expand-lg navbar-dark bg-primary fixed-top">
+    <a class="navbar-brand" href="#">
+      <ion-icon name="grid" style="vertical-align: middle"></ion-icon>gridstack.js
+    </a>
+    <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarColor01"
+      aria-controls="navbarColor01" aria-expanded="false" aria-label="Toggle navigation">
+      <span class="navbar-toggler-icon"></span>
+    </button>
+
+    <div class="collapse navbar-collapse" id="navbarColor01">
+      <ul class="navbar-nav mr-auto">
+        <li class="nav-item nav-item-highlight">
+          <a class="nav-link" href="#demo">Demo</a>
+        </li>
+        <li class="nav-item nav-item-highlight">
+          <a class="nav-link" href="#getStarted">Getting Started</a>
+        </li>
+        <li class="nav-item">
+          <a class="nav-link" href="https://github.com/gridstack/gridstack.js/blob/develop/README.md" target="_blank">Docs</a>
+        </li>
+        <li class="nav-item dropdown">
+          <a class="nav-link dropdown-toggle" href="#" id="moreExamples" data-toggle="dropdown" aria-haspopup="true"
+            aria-expanded="false">Examples</a>
+          <div class="dropdown-menu" aria-labelledby="moreExamples">
+            <a class="dropdown-item" href="demo/advance.html" target="_blank">Advance</a>
+            <a class="dropdown-item" href="demo/serialization.html" target="_blank">Save and restore layout</a>
+            <a class="dropdown-item" href="demo/two.html" target="_blank">Drag widgets between two grids</a>
+            <a class="dropdown-item" href="demo/nested.html" target="_blank">Nested grids</a>
+            <a class="dropdown-item" href="demo/responsive.html" target="_blank">Responsive layout</a>
+            <a class="dropdown-item" href="demo/anijs.html" target="_blank">Animate widgets</a>
+            <a class="dropdown-item" href="demo/index.html" target="_blank">more...</a>
+          </div>
+        </li>
+        <li class="nav-item">
+          <a class="nav-link" target="_blank"
+            href="https://github.com/gridstack/gridstack.js/blob/develop/doc/CHANGES.md">Changes</a>
+        </li>
+        <li class="nav-item">
+          <a class="nav-link" target="_blank"
+            href="https://join.slack.com/t/gridstackjs/shared_invite/zt-3978nsff6-HDNE_N45DydP36NBSV9JFQ">Slack
+            <ion-icon name="logo-slack"></ion-icon></a>
+        </li>
+        <li class="nav-item">
+          <a class="nav-link" target="_blank" href="https://github.com/gridstack/gridstack.js">GitHub</a>
+        </li>
+      </ul>
+      <form class="form-inline my-2 my-lg-0" id="search">
+        <input class="form-control mr-sm-2" type="text" placeholder="Search Issues" id="searchTerm" />
+        <button class="btn btn-secondary my-2 my-sm-0" type="submit">
+          Search
+        </button>
+      </form>
+    </div>
+  </nav>
+
+  <div class="container-fluid">
+    <div class="row bg-dark" id="hero">
+      <div class="col-lg-12">
+        <div class="jumbotron bg-dark text-white" style="margin-bottom: 0;">
+          <h1 class="display-3">gridstack.js</h1>
+          <p class="lead text-center">
+            Build interactive dashboards in minutes.
+          </p>
+          <hr class="my-4" />
+          <p>
+            gridstack.js is a modern Typescript library designed to help developers create
+            beautiful draggable, resizable, responsive layouts with just a few lines of code.<br>
+            You can create more advanced grids: allow users to persist
+            changes, create a sidebar of widgets to drag into your grid, nested grids, and
+            much more.<br><br>
+            Features:
+          </p>
+          <ul>
+            <li>pure TS can be used in any UI framework</li>
+            <li>mobile support</li>
+            <li>draggable, resizable items</li>
+            <li>drag'n'drop from sidebar to insert/delete</li>
+            <li>responsive layouts, column based</li>
+            <li>save/restore</li>
+            <li>drag between multiple grids</li>
+            <li>nested grids, including creation on the fly to any depth</li>
+            <li>Angular (included), demo and external Vue, React, Ember, Knockout.js bindings and more</li>
+          </ul>
+          <p>
+            If you find this lib useful, please donate
+            <a href="https://www.paypal.me/alaind831" target="_blank">PayPal</a> (use <b>“send to a friend”</b> to avoid 3% fee) or
+            <a href="https://www.venmo.com/adumesny" target="_blank">Venmo (adumesny)</a>
+            and help support it!
+          </p>
+        </div>
+      </div>
+    </div>
+  </div>
+  <main role="main" class="container-fluid" style="padding: 0">
+    <section id="demo" class="bg-primary">
+      <div class="row">
+        <div class="col-lg-12 text-white">
+          <ion-icon class="float-right" name="grid" style="font-size: 350%; margin-top: 10px"></ion-icon>
+          <h1>Basic Demo</h1>
+          <hr />
+        </div>
+      </div>
+
+      <div class="row">
+        <div class="col-sm-12" style="padding-bottom: 25px;">
+          <div class="grid-container center">
+            <div class="grid-stack" id="simple-grid"></div>
+          </div>
+        </div>
+      </div>
+    </section>
+    <section id="getStarted" class="bg-info">
+      <div class="row">
+        <div class="col-lg-12 text-white">
+          <ion-icon name="code" class="float-right" style="font-size: 350%"></ion-icon>
+          <h1>Getting Started</h1>
+          <p>
+            Create your first interactive grid by copy-pasting the HTML+JS, as seen below...
+          </p>
+          <hr />
+          <h3>Code</h3>
+          <pre>
+<code class="html">npm install gridstack</code>
+<p class="text-white">then in html:</p>
+<code class="html">&lt;script src="../node_modules/gridstack/dist/gridstack-all.js"&gt;&lt;/script&gt;
+&lt;link href="../node_modules/gridstack/dist/gridstack.min.css" rel="stylesheet"/&gt;
+&lt;style type="text/css"&gt;
+  .grid-stack { background: #FAFAD2; }
+  .grid-stack-item-content { background-color: #18BC9C; }
+&lt;/style&gt;
+
+&lt;div class=&quot;grid-stack&quot;&gt;&lt;/div&gt;
+
+&lt;script type=&quot;text/javascript&quot;&gt;
+  var items = [
+    {content: 'my first widget'}, // will default to location (0,0) and 1x1
+    {w: 2, content: 'another longer widget!'} // will be placed next at (1,0) and 2x1
+  ];
+  var grid = GridStack.init();
+  grid.load(items);
+&lt;/script&gt;
+</code>
+    </pre>
+          <p>
+            ...and that's it! Drag, drop, and resize to your heart's content.
+            Looking for more complex examples? Check out the advanced example below, the links in the nav
+            bar, or our docs in <a href="https://github.com/gridstack/gridstack.js/blob/develop/README.md" target="_blank">GitHub</a>
+          </p>
+        </div>
+      </div>
+    </section>
+
+    <section id="advancedDemo" class="bg-primary">
+      <div class="row">
+        <div class="col-lg-12 text-white">
+          <ion-icon class="float-right" name="grid" style="font-size: 350%; margin-top: 10px"></ion-icon>
+          <h1>Advanced Demo</h1>
+          <hr />
+        </div>
+      </div>
+      <div class="row">
+        <div class="col-md-2 d-none d-md-block" style="border-right: 1px dashed white;">
+          <div id="trash" style="padding: 15px; margin-bottom: 15px;" class="text-center text-white">
+            <div>
+              <ion-icon name="trash" style="font-size: 400%"></ion-icon>
+            </div>
+            <div>
+              <span>Drop here to remove widget!</span>
+            </div>
+          </div>
+          <div class="text-center card text-white grid-stack-item newWidget">
+            <div class="card-body grid-stack-item-content">
+              <div>
+                <ion-icon name="add-circle" style="font-size: 400%"></ion-icon>
+              </div>
+              <div>
+                <span>Drag me into the dashboard!</span>
+              </div>
+            </div>
+          </div>
+        </div>
+        <div class="col-sm-12 col-md-10" style="padding-bottom: 25px;">
+          <div class="grid-container">
+            <div class="grid-stack" id="advanced-grid"></div>
+          </div>
+        </div>
+      </div>
+    </section>
+    <section id="usedBy" class="bg-info text-white">
+      <div class="row" style="margin-bottom: 15px;">
+        <div class="col-lg-12">
+          <ion-icon name="desktop" class="float-right" style="font-size: 350%"></ion-icon>
+
+          <h1>Why use it</h1>
+          <hr />
+          <ul>
+            <li><a href="https://www.npmjs.com/package/gridstack" target="_blank">npm downloads</a></li>
+            <li><a href="https://www.formget.com/jquery-layout-plugins/" target="_blank">6 Best jQuery Layout Plugins 2020</a></li>
+          </ul>
+          <h1>Used by</h1>
+          <hr />
+          <div>
+            <div class="logo">
+              <a href="https://vmware.com" target="_blank">
+                <img style="max-width: 100px;" class="img-responsive" src="logos/VMW_09Q3_LOGO_Corp_Gray.png" /></a>
+            </div>
+            <div class="logo">
+              <a href="https://duckerfrontier.com" target="_blank">
+                <img style="max-width: 150px;" class="img-responsive" src="logos/df-logo-transparent-bg.png" />
+              </a>
+            </div>
+            <div class="logo">
+              <a href="https://guard.no/" target="_blank">
+                <img style="max-width: 100px;" class="img-responsive" src="logos/Guard-Logo-RGB.png" /></a>
+            </div>
+            <div class="logo">
+              <a href="https://nodered.org/" target="_blank">
+                <img style="max-width: 50px;" class="img-responsive" src="logos/node-red-icon.png" /></a>
+            </div>
+            <div class="logo">
+              <a href="https://flexitanalytics.com" target="_blank">
+                <img style="max-width: 50px;" class="img-responsive" src="logos/Flex-X-medium.png" /></a>
+            </div>
+          </div>
+        </div>
+      </div>
+      <div class="row">
+        <div class="col-sm-12">
+          <p>
+            ...and many, many others.
+          </p>
+          <p>
+            Does your company use gridstack.js? We'd love to add your logo!
+            Come join our
+            <a target="_blank"
+              href="https://join.slack.com/t/gridstackjs/shared_invite/zt-3978nsff6-HDNE_N45DydP36NBSV9JFQ">
+              <ion-icon name="logo-slack"></ion-icon>Slack community
+            </a>
+            and let us know.
+          </p>
+        </div>
+      </div>
+    </section>
+  </main>
+  <footer>
+    <section id="getStarted" class="bg-dark">
+      <div class="row">
+        <div class="col-lg-12 text-white">
+          <p style="margin-top: 0.5rem;">
+            <small>
+              ©2019-2020 gridstack.js is open source software maintained by
+              <a href="https://github.com/gridstack/gridstack.js#the-team" target="_blank">the gridstack.js team</a>
+              but wouldn't be possible without the help of developers
+              everywhere
+            </small>
+          </p>
+        </div>
+      </div>
+    </section>
+  </footer>
+  <!-- /.container -->
+
+  <script type="text/javascript">
+    var simple = [
+      {x: 0, y: 0, w: 4, h: 2, content: '1'},
+      {x: 4, y: 0, w: 4, h: 4, content: '2'},
+      {x: 8, y: 0, w: 2, h: 2, content: '<p class="card-text text-center" style="margin-bottom: 0">Drag me!<p class="card-text text-center"style="margin-bottom: 0"><ion-icon name="hand" style="font-size: 300%"></ion-icon>'},
+      {x: 10, y: 0, w: 2, h: 2, content: '4'},
+      {x: 0, y: 2, w: 2, h: 2, content: '5'},
+      {x: 2, y: 2, w: 2, h: 4, content: '6'},
+      {x: 8, y: 2, w: 4, h: 2, content: '7'},
+      {x: 0, y: 4, w: 2, h: 2, content: '8'},
+      {x: 4, y: 4, w: 4, h: 2, content: '9'},
+      {x: 8, y: 4, w: 2, h: 2, content: '10'},
+      {x: 10, y: 4, w: 2, h: 2, content: '11'},
+    ];
+   var advanced = [
+      {x: 0, y: 0, w: 4, h: 2, content: '1'},
+      {x: 4, y: 0, w: 4, h: 4, noMove: true, noResize: true, locked: true, content: 'I can\'t be moved or dragged!<br><ion-icon name="ios-lock" style="font-size:300%"></ion-icon>'},
+      {x: 8, y: 0, w: 2, h: 2, minW: 2, noResize: true, content: '<p class="card-text text-center" style="margin-bottom: 0">Drag me!<p class="card-text text-center"style="margin-bottom: 0"><ion-icon name="hand" style="font-size: 300%"></ion-icon><p class="card-text text-center" style="margin-bottom: 0">...but don\'t resize me!</p>'},
+      {x: 10, y: 0, w: 2, h: 2, content: '4'},
+      {x: 0, y: 2, w: 2, h: 2, content: '5'},
+      {x: 2, y: 2, w: 2, h: 4, content: '6'},
+      {x: 8, y: 2, w: 4, h: 2, content: '7'},
+      {x: 0, y: 4, w: 2, h: 2, content: '8'},
+      {x: 4, y: 4, w: 4, h: 2, content: '9'},
+      {x: 8, y: 4, w: 2, h: 2, content: '10'},
+      {x: 10, y: 4, w: 2, h: 2, content: '11'},
+    ];
+
+    var simpleGrid = GridStack.init({
+      margin: 5,
+    }, '#simple-grid');
+    simpleGrid.load(simple);
+
+    var advGrid = GridStack.init({
+      margin: 5,
+      acceptWidgets: true,
+      removable: '#trash',
+      removeTimeout: 100
+    }, '#advanced-grid')
+    .load(advanced);
+    
+    GridStack.setupDragIn('.newWidget', { appendTo: 'body', helper: 'clone' });
+
+    $('#search').on('submit', function (event) {
+      event.preventDefault();
+      var searchTerm = $('#searchTerm').val();
+      window.open(
+        'https://github.com/gridstack/gridstack.js/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+' +
+        searchTerm,
+        '_blank'
+      );
+    });
+    $('.nav-item').on('click', function (event) {
+      $('.nav-item').removeClass('active');
+      var target = $(event.currentTarget);
+      if (target.hasClass('nav-item-highlight')) {
+        target.addClass('active');
+      }
+    });
+    hljs.initHighlightingOnLoad();
+  </script>
+  <script type="module" src="https://unpkg.com/ionicons@4.5.10-0/dist/ionicons/ionicons.esm.js"></script>
+  <script nomodule="" src="https://unpkg.com/ionicons@4.5.10-0/dist/ionicons/ionicons.js"></script>
+  <!-- Google Analytics -->
+  <script>
+    (function (i, s, o, g, r, a, m) {
+      i['GoogleAnalyticsObject'] = r;
+      (i[r] =
+        i[r] ||
+        function () {
+          (i[r].q = i[r].q || []).push(arguments);
+        }),
+      (i[r].l = 1 * new Date());
+      (a = s.createElement(o)), (m = s.getElementsByTagName(o)[0]);
+      a.async = 1;
+      a.src = g;
+      m.parentNode.insertBefore(a, m);
+    })(
+      window,
+      document,
+      'script',
+      'https://www.google-analytics.com/analytics.js',
+      'ga'
+    );
+
+    ga('create', 'UA-1891156-8', 'auto');
+    ga('send', 'pageview');
+  </script>
+  <!-- End Google Analytics -->
+</body>
+
+</html>
\ No newline at end of file
diff --git a/favicon.ico b/favicon.ico
new file mode 100644
index 000000000..4feec167e
Binary files /dev/null and b/favicon.ico differ
diff --git a/freelancer/css/freelancer.css b/freelancer/css/freelancer.css
new file mode 100755
index 000000000..efd48376f
--- /dev/null
+++ b/freelancer/css/freelancer.css
@@ -0,0 +1,445 @@
+/*!
+ * Start Bootstrap - Freelancer Bootstrap Theme (http://startbootstrap.com)
+ * Code licensed under the Apache License v2.0.
+ * For details, see http://www.apache.org/licenses/LICENSE-2.0.
+ */
+
+body {
+    overflow-x: hidden;
+}
+
+p {
+    font-size: 20px;
+}
+
+p.small {
+    font-size: 16px;
+}
+
+a,
+a:hover,
+a:focus,
+a:active,
+a.active {
+    outline: 0;
+    color: #18bc9c;
+}
+
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
+    text-transform: uppercase;
+    font-family: Montserrat,"Helvetica Neue",Helvetica,Arial,sans-serif;
+    font-weight: 700;
+}
+
+hr.star-light,
+hr.star-primary {
+    margin: 25px auto 30px;
+    padding: 0;
+    max-width: 250px;
+    border: 0;
+    border-top: solid 5px;
+    text-align: center;
+}
+
+hr.star-light:after,
+hr.star-primary:after {
+    content: "\f005";
+    display: inline-block;
+    position: relative;
+    top: -.8em;
+    padding: 0 .25em;
+    font-family: FontAwesome;
+    font-size: 2em;
+}
+
+hr.star-light {
+    border-color: #fff;
+}
+
+hr.star-light:after {
+    color: #fff;
+    background-color: #18bc9c;
+}
+
+hr.star-primary {
+    border-color: #2c3e50;
+}
+
+hr.star-primary:after {
+    color: #2c3e50;
+    background-color: #fff;
+}
+
+.img-centered {
+    margin: 0 auto;
+}
+
+header {
+    text-align: center;
+    color: #fff;
+    background: #18bc9c;
+}
+
+header .container {
+    padding-top: 100px;
+    padding-bottom: 50px;
+}
+
+header img {
+    display: block;
+    margin: 0 auto 20px;
+}
+
+header .intro-text .name {
+    display: block;
+    text-transform: uppercase;
+    font-family: Montserrat,"Helvetica Neue",Helvetica,Arial,sans-serif;
+    font-size: 2em;
+    font-weight: 700;
+}
+
+header .intro-text .skills {
+    font-size: 1.25em;
+    font-weight: 300;
+}
+
+@media(min-width:768px) {
+    header .container {
+        padding-top: 200px;
+        padding-bottom: 100px;
+    }
+
+    header .intro-text .name {
+        font-size: 4.75em;
+    }
+
+    header .intro-text .skills {
+        font-size: 1.75em;
+    }
+}
+
+@media(min-width:768px) {
+    .navbar-fixed-top {
+        padding: 25px 0;
+        -webkit-transition: padding .3s;
+        -moz-transition: padding .3s;
+        transition: padding .3s;
+    }
+
+    .navbar-fixed-top .navbar-brand {
+        font-size: 2em;
+        -webkit-transition: all .3s;
+        -moz-transition: all .3s;
+        transition: all .3s;
+    }
+
+    .navbar-fixed-top.navbar-shrink {
+        padding: 10px 0;
+    }
+
+    .navbar-fixed-top.navbar-shrink .navbar-brand {
+        font-size: 1.5em;
+    }
+}
+
+.navbar {
+    text-transform: uppercase;
+    font-family: Montserrat,"Helvetica Neue",Helvetica,Arial,sans-serif;
+    font-weight: 700;
+}
+
+.navbar a:focus {
+    outline: 0;
+}
+
+.navbar .navbar-nav {
+    letter-spacing: 1px;
+}
+
+.navbar .navbar-nav li a:focus {
+    outline: 0;
+}
+
+.navbar-default,
+.navbar-inverse {
+    border: 0;
+}
+
+section {
+    padding: 100px 0;
+}
+
+section h2 {
+    margin: 0;
+    font-size: 3em;
+}
+
+section.success {
+    color: #fff;
+    background: #18bc9c;
+}
+
+@media(max-width:767px) {
+    section {
+        padding: 75px 0;
+    }
+
+    section.first {
+        padding-top: 75px;
+    }
+}
+
+#portfolio .portfolio-item {
+    right: 0;
+    margin: 0 0 15px;
+}
+
+#portfolio .portfolio-item .portfolio-link {
+    display: block;
+    position: relative;
+    margin: 0 auto;
+    max-width: 400px;
+}
+
+#portfolio .portfolio-item .portfolio-link .caption {
+    position: absolute;
+    width: 100%;
+    height: 100%;
+    opacity: 0;
+    background: rgba(24,188,156,.9);
+    -webkit-transition: all ease .5s;
+    -moz-transition: all ease .5s;
+    transition: all ease .5s;
+}
+
+#portfolio .portfolio-item .portfolio-link .caption:hover {
+    opacity: 1;
+}
+
+#portfolio .portfolio-item .portfolio-link .caption .caption-content {
+    position: absolute;
+    top: 50%;
+    width: 100%;
+    height: 20px;
+    margin-top: -12px;
+    text-align: center;
+    font-size: 20px;
+    color: #fff;
+}
+
+#portfolio .portfolio-item .portfolio-link .caption .caption-content i {
+    margin-top: -12px;
+}
+
+#portfolio .portfolio-item .portfolio-link .caption .caption-content h3,
+#portfolio .portfolio-item .portfolio-link .caption .caption-content h4 {
+    margin: 0;
+}
+
+#portfolio * {
+    z-index: 2;
+}
+
+@media(min-width:767px) {
+    #portfolio .portfolio-item {
+        margin: 0 0 30px;
+    }
+}
+
+.btn-outline {
+    margin-top: 15px;
+    border: solid 2px #fff;
+    font-size: 20px;
+    color: #fff;
+    background: 0 0;
+    transition: all .3s ease-in-out;
+}
+
+.btn-outline:hover,
+.btn-outline:focus,
+.btn-outline:active,
+.btn-outline.active {
+    border: solid 2px #fff;
+    color: #18bc9c;
+    background: #fff;
+}
+
+.floating-label-form-group {
+    position: relative;
+    margin-bottom: 0;
+    padding-bottom: .5em;
+    border-bottom: 1px solid #eee;
+}
+
+.floating-label-form-group input,
+.floating-label-form-group textarea {
+    z-index: 1;
+    position: relative;
+    padding-right: 0;
+    padding-left: 0;
+    border: 0;
+    border-radius: 0;
+    font-size: 1.5em;
+    background: 0 0;
+    box-shadow: none!important;
+    resize: none;
+}
+
+.floating-label-form-group label {
+    display: block;
+    z-index: 0;
+    position: relative;
+    top: 2em;
+    margin: 0;
+    font-size: .85em;
+    line-height: 1.764705882em;
+    vertical-align: middle;
+    vertical-align: baseline;
+    opacity: 0;
+    -webkit-transition: top .3s ease,opacity .3s ease;
+    -moz-transition: top .3s ease,opacity .3s ease;
+    -ms-transition: top .3s ease,opacity .3s ease;
+    transition: top .3s ease,opacity .3s ease;
+}
+
+.floating-label-form-group::not(:first-child) {
+    padding-left: 14px;
+    border-left: 1px solid #eee;
+}
+
+.floating-label-form-group-with-value label {
+    top: 0;
+    opacity: 1;
+}
+
+.floating-label-form-group-with-focus label {
+    color: #18bc9c;
+}
+
+form .row:first-child .floating-label-form-group {
+    border-top: 1px solid #eee;
+}
+
+footer {
+    color: #fff;
+}
+
+footer h3 {
+    margin-bottom: 30px;
+}
+
+footer .footer-above {
+    padding-top: 50px;
+    background-color: #2c3e50;
+}
+
+footer .footer-col {
+    margin-bottom: 50px;
+}
+
+footer .footer-below {
+    padding: 25px 0;
+    background-color: #233140;
+}
+
+.btn-social {
+    display: inline-block;
+    width: 50px;
+    height: 50px;
+    border: 2px solid #fff;
+    border-radius: 100%;
+    text-align: center;
+    font-size: 20px;
+    line-height: 45px;
+}
+
+.btn:focus,
+.btn:active,
+.btn.active {
+    outline: 0;
+}
+
+.scroll-top {
+    z-index: 1049;
+    position: fixed;
+    right: 2%;
+    bottom: 2%;
+    width: 50px;
+    height: 50px;
+}
+
+.scroll-top .btn {
+    width: 50px;
+    height: 50px;
+    border-radius: 100%;
+    font-size: 20px;
+    line-height: 28px;
+}
+
+.scroll-top .btn:focus {
+    outline: 0;
+}
+
+.portfolio-modal .modal-content {
+    padding: 100px 0;
+    min-height: 100%;
+    border: 0;
+    border-radius: 0;
+    text-align: center;
+    background-clip: border-box;
+    -webkit-box-shadow: none;
+    box-shadow: none;
+}
+
+.portfolio-modal .modal-content h2 {
+    margin: 0;
+    font-size: 3em;
+}
+
+.portfolio-modal .modal-content img {
+    margin-bottom: 30px;
+}
+
+.portfolio-modal .modal-content .item-details {
+    margin: 30px 0;
+}
+
+.portfolio-modal .close-modal {
+    position: absolute;
+    top: 25px;
+    right: 25px;
+    width: 75px;
+    height: 75px;
+    background-color: transparent;
+    cursor: pointer;
+}
+
+.portfolio-modal .close-modal:hover {
+    opacity: .3;
+}
+
+.portfolio-modal .close-modal .lr {
+    z-index: 1051;
+    width: 1px;
+    height: 75px;
+    margin-left: 35px;
+    background-color: #2c3e50;
+    -webkit-transform: rotate(45deg);
+    -ms-transform: rotate(45deg);
+    transform: rotate(45deg);
+}
+
+.portfolio-modal .close-modal .lr .rl {
+    z-index: 1052;
+    width: 1px;
+    height: 75px;
+    background-color: #2c3e50;
+    -webkit-transform: rotate(90deg);
+    -ms-transform: rotate(90deg);
+    transform: rotate(90deg);
+}
\ No newline at end of file
diff --git a/freelancer/js/cbpAnimatedHeader.js b/freelancer/js/cbpAnimatedHeader.js
new file mode 100755
index 000000000..7c3bbc172
--- /dev/null
+++ b/freelancer/js/cbpAnimatedHeader.js
@@ -0,0 +1,44 @@
+/**
+ * cbpAnimatedHeader.js v1.0.0
+ * http://www.codrops.com
+ *
+ * Licensed under the MIT license.
+ * http://www.opensource.org/licenses/mit-license.php
+ * 
+ * Copyright 2013, Codrops
+ * http://www.codrops.com
+ */
+var cbpAnimatedHeader = (function() {
+
+	var docElem = document.documentElement,
+		header = document.querySelector( '.navbar-fixed-top' ),
+		didScroll = false,
+		changeHeaderOn = 300;
+
+	function init() {
+		window.addEventListener( 'scroll', function( event ) {
+			if( !didScroll ) {
+				didScroll = true;
+				setTimeout( scrollPage, 250 );
+			}
+		}, false );
+	}
+
+	function scrollPage() {
+		var sy = scrollY();
+		if ( sy >= changeHeaderOn ) {
+			classie.add( header, 'navbar-shrink' );
+		}
+		else {
+			classie.remove( header, 'navbar-shrink' );
+		}
+		didScroll = false;
+	}
+
+	function scrollY() {
+		return window.pageYOffset || docElem.scrollTop;
+	}
+
+	init();
+
+})();
\ No newline at end of file
diff --git a/freelancer/js/cbpAnimatedHeader.min.js b/freelancer/js/cbpAnimatedHeader.min.js
new file mode 100755
index 000000000..b39cb0dcd
--- /dev/null
+++ b/freelancer/js/cbpAnimatedHeader.min.js
@@ -0,0 +1,11 @@
+/**
+ * cbpAnimatedHeader.min.js v1.0.0
+ * http://www.codrops.com
+ *
+ * Licensed under the MIT license.
+ * http://www.opensource.org/licenses/mit-license.php
+ * 
+ * Copyright 2013, Codrops
+ * http://www.codrops.com
+ */
+var cbpAnimatedHeader=(function(){var b=document.documentElement,g=document.querySelector(".cbp-af-header"),e=false,a=300;function f(){window.addEventListener("scroll",function(h){if(!e){e=true;setTimeout(d,250)}},false)}function d(){var h=c();if(h>=a){classie.add(g,"cbp-af-header-shrink")}else{classie.remove(g,"cbp-af-header-shrink")}e=false}function c(){return window.pageYOffset||b.scrollTop}f()})();
\ No newline at end of file
diff --git a/freelancer/js/classie.js b/freelancer/js/classie.js
new file mode 100755
index 000000000..a96755488
--- /dev/null
+++ b/freelancer/js/classie.js
@@ -0,0 +1,80 @@
+/*!
+ * classie - class helper functions
+ * from bonzo https://github.com/ded/bonzo
+ * 
+ * classie.has( elem, 'my-class' ) -> true/false
+ * classie.add( elem, 'my-new-class' )
+ * classie.remove( elem, 'my-unwanted-class' )
+ * classie.toggle( elem, 'my-class' )
+ */
+
+/*jshint browser: true, strict: true, undef: true */
+/*global define: false */
+
+( function( window ) {
+
+'use strict';
+
+// class helper functions from bonzo https://github.com/ded/bonzo
+
+function classReg( className ) {
+  return new RegExp("(^|\\s+)" + className + "(\\s+|$)");
+}
+
+// classList support for class management
+// altho to be fair, the api sucks because it won't accept multiple classes at once
+var hasClass, addClass, removeClass;
+
+if ( 'classList' in document.documentElement ) {
+  hasClass = function( elem, c ) {
+    return elem.classList.contains( c );
+  };
+  addClass = function( elem, c ) {
+    elem.classList.add( c );
+  };
+  removeClass = function( elem, c ) {
+    elem.classList.remove( c );
+  };
+}
+else {
+  hasClass = function( elem, c ) {
+    return classReg( c ).test( elem.className );
+  };
+  addClass = function( elem, c ) {
+    if ( !hasClass( elem, c ) ) {
+      elem.className = elem.className + ' ' + c;
+    }
+  };
+  removeClass = function( elem, c ) {
+    elem.className = elem.className.replace( classReg( c ), ' ' );
+  };
+}
+
+function toggleClass( elem, c ) {
+  var fn = hasClass( elem, c ) ? removeClass : addClass;
+  fn( elem, c );
+}
+
+var classie = {
+  // full names
+  hasClass: hasClass,
+  addClass: addClass,
+  removeClass: removeClass,
+  toggleClass: toggleClass,
+  // short names
+  has: hasClass,
+  add: addClass,
+  remove: removeClass,
+  toggle: toggleClass
+};
+
+// transport
+if ( typeof define === 'function' && define.amd ) {
+  // AMD
+  define( classie );
+} else {
+  // browser global
+  window.classie = classie;
+}
+
+})( window );
diff --git a/freelancer/js/freelancer.js b/freelancer/js/freelancer.js
new file mode 100755
index 000000000..6a98ae4dd
--- /dev/null
+++ b/freelancer/js/freelancer.js
@@ -0,0 +1,37 @@
+/*!
+ * Start Bootstrap - Freelancer Bootstrap Theme (http://startbootstrap.com)
+ * Code licensed under the Apache License v2.0.
+ * For details, see http://www.apache.org/licenses/LICENSE-2.0.
+ */
+
+// jQuery for page scrolling feature - requires jQuery Easing plugin
+$(function() {
+    $('.page-scroll a').bind('click', function(event) {
+        var $anchor = $(this);
+        $('html, body').stop().animate({
+            scrollTop: $($anchor.attr('href')).offset().top
+        }, 1500, 'easeInOutExpo');
+        event.preventDefault();
+    });
+});
+
+// Floating label headings for the contact form
+$(function() {
+    $("body").on("input propertychange", ".floating-label-form-group", function(e) {
+        $(this).toggleClass("floating-label-form-group-with-value", !! $(e.target).val());
+    }).on("focus", ".floating-label-form-group", function() {
+        $(this).addClass("floating-label-form-group-with-focus");
+    }).on("blur", ".floating-label-form-group", function() {
+        $(this).removeClass("floating-label-form-group-with-focus");
+    });
+});
+
+// Highlight the top nav as scrolling occurs
+$('body').scrollspy({
+    target: '.navbar-fixed-top'
+})
+
+// Closes the Responsive Menu on Menu Item Click
+$('.navbar-collapse ul li a').click(function() {
+    $('.navbar-toggle:visible').click();
+});
\ No newline at end of file
diff --git a/gridstack-demo.css b/gridstack-demo.css
new file mode 100644
index 000000000..098c42818
--- /dev/null
+++ b/gridstack-demo.css
@@ -0,0 +1,26 @@
+.grid-stack-item-content {
+  background: white;
+  color: #2c3e50;
+  font-family: 'Indie Flower', cursive;
+  text-align: center;
+  font-size: 20px;
+}
+
+.grid-stack-item-content .fa {
+  font-size: 64px;
+  display: block;
+  margin: 20px 0 10px;
+}
+
+header a,
+header a:hover {
+  color: #fff;
+}
+
+.darklue {
+  background: #2c3e50;
+  color: #fff;
+}
+.darklue hr.star-light::after {
+  background-color: #2c3e50;
+}
diff --git a/gridstack.css b/gridstack.css
deleted file mode 100644
index 5cea38591..000000000
--- a/gridstack.css
+++ /dev/null
@@ -1,130 +0,0 @@
-.grid-stack {
-    position: relative;
-}
-
-.grid-stack-item {
-    position: absolute;
-    padding: 0;
-}
-
-.grid-stack-item .grid-stack-item-content,
-.grid-stack-item .placeholder-content {
-    margin: 0;
-    position: absolute;
-    top: 0;
-    left: 10px;
-    right: 10px;
-    bottom: 0;
-    width: auto;
-    z-index: 0 !important;
-}
-
-.grid-stack-placeholder .placeholder-content {
-    border: 1px dashed lightgray;
-}
-
-.grid-stack-item.ui-draggable-dragging,
-.grid-stack-item.ui-resizable-resizing {
-    z-index: 100;
-}
-
-.grid-stack-item.ui-draggable-dragging .box,
-.grid-stack-item.ui-resizable-resizing .box {
-    box-shadow: 1px 4px 6px rgba(0, 0, 0, 0.2);
-    opacity: 0.8;
-}
-
-.grid-stack-item .ui-resizable-handle {
-    padding: 3px;
-    margin: 3px 0;
-    cursor: nwse-resize;
-    color: gray;
-
-    position: absolute;
-    bottom: 0;
-    right: 15px;
-
-    font: normal normal normal 14px/1 FontAwesome;
-    text-rendering: auto;
-    -webkit-font-smoothing: antialiased;
-    -moz-osx-font-smoothing: grayscale;
-
-    filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1);
-    -webkit-transform: rotate(90deg);
-    -ms-transform: rotate(90deg);
-    transform: rotate(90deg);
-
-    font-size: 10px;
-}
-
-.grid-stack-item .ui-resizable-handle::before {
-    content: "\f065";
-}
-
-.grid-stack-item[data-gs-width="12"] { width: 100% }
-.grid-stack-item[data-gs-width="11"] { width: 91.66666667% }
-.grid-stack-item[data-gs-width="10"] { width: 83.33333333% }
-.grid-stack-item[data-gs-width="9"]  { width: 75% }
-.grid-stack-item[data-gs-width="8"]  { width: 66.66666667% }
-.grid-stack-item[data-gs-width="7"]  { width: 58.33333333% }
-.grid-stack-item[data-gs-width="6"]  { width: 50% }
-.grid-stack-item[data-gs-width="5"]  { width: 41.66666667% }
-.grid-stack-item[data-gs-width="4"]  { width: 33.33333333% }
-.grid-stack-item[data-gs-width="3"]  { width: 25% }
-.grid-stack-item[data-gs-width="2"]  { width: 16.66666667% }
-.grid-stack-item[data-gs-width="1"]  { width: 8.33333333% }
-
-.grid-stack-item[data-gs-x="12"] { left: 100% }
-.grid-stack-item[data-gs-x="11"] { left: 91.66666667% }
-.grid-stack-item[data-gs-x="10"] { left: 83.33333333% }
-.grid-stack-item[data-gs-x="9"]  { left: 75% }
-.grid-stack-item[data-gs-x="8"]  { left: 66.66666667% }
-.grid-stack-item[data-gs-x="7"]  { left: 58.33333333% }
-.grid-stack-item[data-gs-x="6"]  { left: 50% }
-.grid-stack-item[data-gs-x="5"]  { left: 41.66666667% }
-.grid-stack-item[data-gs-x="4"]  { left: 33.33333333% }
-.grid-stack-item[data-gs-x="3"]  { left: 25% }
-.grid-stack-item[data-gs-x="2"]  { left: 16.66666667% }
-.grid-stack-item[data-gs-x="1"]  { left: 8.33333333% }
-
-.grid-stack-item[data-gs-height="1"]  { height: 60px; }
-.grid-stack-item[data-gs-height="2"]  { height: 140px; }
-.grid-stack-item[data-gs-height="3"]  { height: 220px; }
-.grid-stack-item[data-gs-height="4"]  { height: 300px; }
-.grid-stack-item[data-gs-height="5"]  { height: 380px; }
-.grid-stack-item[data-gs-height="6"]  { height: 460px; }
-.grid-stack-item[data-gs-height="7"]  { height: 540px; }
-.grid-stack-item[data-gs-height="8"]  { height: 620px; }
-.grid-stack-item[data-gs-height="9"]  { height: 700px; }
-.grid-stack-item[data-gs-height="10"] { height: 780px; }
-.grid-stack-item[data-gs-height="11"] { height: 860px; }
-.grid-stack-item[data-gs-height="12"] { height: 940px; }
-.grid-stack-item[data-gs-height="13"] { height: 1020px; }
-.grid-stack-item[data-gs-height="14"] { height: 1100px; }
-.grid-stack-item[data-gs-height="15"] { height: 1180px; }
-.grid-stack-item[data-gs-height="16"] { height: 1260px; }
-.grid-stack-item[data-gs-height="17"] { height: 1340px; }
-.grid-stack-item[data-gs-height="18"] { height: 1420px; }
-.grid-stack-item[data-gs-height="19"] { height: 1500px; }
-.grid-stack-item[data-gs-height="20"] { height: 1580px; }
-
-.grid-stack-item[data-gs-y="0"]  { top: 0 }
-.grid-stack-item[data-gs-y="1"]  { top: 80px; }
-.grid-stack-item[data-gs-y="2"]  { top: 160px; }
-.grid-stack-item[data-gs-y="3"]  { top: 240px; }
-.grid-stack-item[data-gs-y="4"]  { top: 320px; }
-.grid-stack-item[data-gs-y="5"]  { top: 400px; }
-.grid-stack-item[data-gs-y="6"]  { top: 480px; }
-.grid-stack-item[data-gs-y="7"]  { top: 560px; }
-.grid-stack-item[data-gs-y="8"]  { top: 640px; }
-.grid-stack-item[data-gs-y="9"]  { top: 720px; }
-.grid-stack-item[data-gs-y="10"] { top: 800px; }
-.grid-stack-item[data-gs-y="11"] { top: 880px; }
-.grid-stack-item[data-gs-y="12"] { top: 960px; }
-.grid-stack-item[data-gs-y="13"] { top: 1040px; }
-.grid-stack-item[data-gs-y="14"] { top: 1120px; }
-.grid-stack-item[data-gs-y="15"] { top: 1200px; }
-.grid-stack-item[data-gs-y="16"] { top: 1280px; }
-.grid-stack-item[data-gs-y="17"] { top: 1360px; }
-.grid-stack-item[data-gs-y="18"] { top: 1440px; }
-.grid-stack-item[data-gs-y="19"] { top: 1520px; }
diff --git a/gridstack.js b/gridstack.js
deleted file mode 100644
index 7ba5f0030..000000000
--- a/gridstack.js
+++ /dev/null
@@ -1,298 +0,0 @@
-(function (scope, _) {
-
-    var Utils = {
-        is_intercepted: function (a, b) {
-            return !(a.x + a.width <= b.x || b.x + b.width <= a.x || a.y + a.height <= b.y || b.y + b.height <= a.y);
-        }
-    };
-
-    var id_seq = 0;
-
-    var GridStackEngine = function (width, onchange) {
-        this.width = width;
-
-        this.nodes = [];
-        this.onchange = onchange || function () {};
-    };
-
-    GridStackEngine.prototype._fix_collisions = function (node) {
-        this.nodes = _.sortBy(this.nodes, function (n) { return -(n.x + n.y * this.width); }, this);
-
-        while (true) {
-            var collision_node = _.find(this.nodes, function (n) {
-                return n != node && Utils.is_intercepted(n, node);
-            }, this);
-            if (typeof collision_node == 'undefined') {
-                return;
-            }
-            this.move_node(collision_node, collision_node.x, node.y + node.height,
-                collision_node.width, collision_node.height, true);
-        }
-    };
-
-    GridStackEngine.prototype._pack_nodes = function () {
-        this.nodes = _.sortBy(this.nodes, function (n) { return n.x + n.y * this.width; }, this);
-
-        _.each(this.nodes, function (n, i) {
-            while (n.y > 0) {
-                var new_y = n.y - 1;
-                var can_be_moved = i == 0;
-
-                if (i > 0) {
-                    var collision_node = _.chain(this.nodes)
-                        .first(i)
-                        .find(function (bn) {
-                            return Utils.is_intercepted({x: n.x, y: new_y, width: n.width, height: n.height}, bn);
-                        })
-                        .value();
-                    can_be_moved = typeof collision_node == 'undefined';
-                }
-
-                if (!can_be_moved) {
-                    break;
-                }
-                n.y = new_y;
-            }
-        }, this);
-    };
-
-    GridStackEngine.prototype._prepare_node = function (node, moving) {
-        node = _.defaults(node || {}, {width: 1, height: 1, x: 0, y: 0 });
-
-        node.x = parseInt('' + node.x);
-        node.y = parseInt('' + node.y);
-        node.width = parseInt('' + node.width);
-        node.height = parseInt('' + node.height);
-
-        if (node.width > this.width) {
-            node.width = this.width;
-        }
-        else if (node.width < 1) {
-            node.width = 1;
-        }
-
-        if (node.height < 1) {
-            node.height = 1;
-        }
-
-        if (node.x < 0) {
-            node.x = 0;
-        }
-
-        if (node.x + node.width > this.width) {
-            if (moving) {
-                node.x = this.width - node.width;
-            }
-            else {
-                node.width = this.width - node.x;
-            }
-        }
-
-        if (node.y < 0) {
-            node.y = 0;
-        }
-
-        return node;
-    };
-
-    GridStackEngine.prototype._notify = function () {
-        this.onchange(this.nodes);
-    };
-
-    GridStackEngine.prototype.add_node = function(node) {
-        node = this._prepare_node(node);
-
-        if (typeof node.max_width != 'undefined') node.width = Math.min(node.width, node.max_width);
-        if (typeof node.max_height != 'undefined') node.height = Math.min(node.height, node.max_height);
-        if (typeof node.min_width != 'undefined') node.width = Math.max(node.width, node.min_width);
-        if (typeof node.min_height != 'undefined') node.height = Math.max(node.height, node.min_height);
-
-        node._id = ++id_seq;
-        this.nodes.push(node);
-        this._fix_collisions(node);
-        this._pack_nodes();
-        this._notify();
-        return node;
-    };
-
-    GridStackEngine.prototype.remove_node = function (node) {
-        node._id = null;
-        this.nodes = _.without(this.nodes, node);
-        this._pack_nodes();
-        this._notify(node);
-    };
-
-    GridStackEngine.prototype.move_node = function (node, x, y, width, height, no_pack) {
-        if (typeof x == 'undefined') x = node.x;
-        if (typeof y == 'undefined') y = node.y;
-        if (typeof width == 'undefined') width = node.width;
-        if (typeof height == 'undefined') height = node.height;
-
-        if (typeof node.max_width != 'undefined') width = Math.min(width, node.max_width);
-        if (typeof node.max_height != 'undefined') height = Math.min(height, node.max_height);
-        if (typeof node.min_width != 'undefined') width = Math.max(width, node.min_width);
-        if (typeof node.min_height != 'undefined') height = Math.max(height, node.min_height);
-
-        if (node.x == x && node.y == y && node.width == width && node.height == height) {
-            return node;
-        }
-
-        var moving = node.x != x;
-
-        node.x = x;
-        node.y = y;
-        node.width = width;
-        node.height = height;
-
-        node = this._prepare_node(node, moving);
-
-        this._fix_collisions(node);
-        if (!no_pack) {
-            this._pack_nodes();
-            this._notify();
-        }
-        return node;
-    };
-
-    GridStackEngine.prototype.get_grid_height = function () {
-        return _.reduce(this.nodes, function (memo, n) { return Math.max(memo, n.y + n.height); }, 0);
-    };
-
-    var GridStack = function (el, opts) {
-        var self = this;
-
-        this.container = $(el);
-
-        this.opts = _.defaults(opts || {}, {
-            width: 12,
-            item_class: 'grid-stack-item',
-            placeholder_class: 'grid-stack-placeholder',
-            handle: '.grid-stack-item-content',
-            cell_height: 60,
-            vertical_margin: 20
-        });
-
-        this.grid = new GridStackEngine(this.opts.width, function (nodes) {
-            _.each(nodes, function (n) {
-                n.el
-                    .attr('data-gs-x', n.x)
-                    .attr('data-gs-y', n.y)
-                    .attr('data-gs-width', n.width)
-                    .attr('data-gs-height', n.height);
-            });
-        });
-
-        this.container.find('.' + this.opts.item_class).each(function (index, el) {
-            self._prepare_element(el);
-        });
-
-        this.placeholder = $('<div class="' + this.opts.placeholder_class + ' ' + this.opts.item_class + '"><div class="placeholder-content" /></div>').hide();
-        this.container.append(this.placeholder);
-        this.container.height((this.grid.get_grid_height()) * (this.opts.cell_height + this.opts.vertical_margin) - this.opts.vertical_margin);
-    };
-
-    GridStack.prototype._update_container_height = function () {
-        this.container.height(this.grid.get_grid_height() * (this.opts.cell_height + this.opts.vertical_margin) - this.opts.vertical_margin);
-    };
-
-    GridStack.prototype._prepare_element = function (el) {
-        var self = this;
-        el = $(el);
-
-        var node = self.grid.add_node({
-            x: el.attr('data-gs-x'),
-            y: el.attr('data-gs-y'),
-            width: el.attr('data-gs-width'),
-            height: el.attr('data-gs-height'),
-            max_width: el.attr('data-gs-max-width'),
-            min_width: el.attr('data-gs-min-width'),
-            max_height: el.attr('data-gs-max-height'),
-            min_height: el.attr('data-gs-min-height'),
-            el: el
-        });
-        el.data('_gridstack_node', node);
-
-        var cell_width, cell_height = this.opts.cell_height + this.opts.vertical_margin / 2;
-
-        var on_start_moving = function (event, ui) {
-            var o = $(this);
-            cell_width = Math.ceil(o.outerWidth() / o.attr('data-gs-width'));
-            self.placeholder
-                .attr('data-gs-x', o.attr('data-gs-x'))
-                .attr('data-gs-y', o.attr('data-gs-y'))
-                .attr('data-gs-width', o.attr('data-gs-width'))
-                .attr('data-gs-height', o.attr('data-gs-height'))
-                .show();
-            node.el = self.placeholder;
-        };
-
-        var on_end_moving = function (event, ui) {
-            var o = $(this);
-            node.el = o;
-            self.placeholder.hide();
-            o
-                .attr('data-gs-x', node.x)
-                .attr('data-gs-y', node.y)
-                .attr('data-gs-width', node.width)
-                .attr('data-gs-height', node.height)
-                .removeAttr('style');
-            self._update_container_height();
-        };
-
-        el.draggable({
-            handle: this.opts.handle,
-            scroll: true,
-            appendTo: 'body',
-
-            start: on_start_moving,
-            stop: on_end_moving,
-            drag: function (event, ui) {
-                var x = Math.round(ui.position.left / cell_width),
-                    y = Math.floor(ui.position.top / cell_height);
-                self.grid.move_node(node, x, y);
-                self._update_container_height();
-            }
-        }).resizable({
-            autoHide: true,
-            handles: 'se',
-            minHeight: this.opts.cell_height - 10,
-            minWidth: 70,
-
-            start: on_start_moving,
-            stop: on_end_moving,
-            resize: function (event, ui) {
-                var width = Math.round(ui.size.width / cell_width),
-                    height = Math.round(ui.size.height / cell_height);
-                self.grid.move_node(node, node.x, node.y, width, height);
-                self._update_container_height();
-            }
-        });
-    };
-
-    GridStack.prototype.add_widget = function (el, x, y, width, height) {
-        el = $(el);
-        if (typeof x != 'undefined') el.attr('data-gs-x', x);
-        if (typeof y != 'undefined') el.attr('data-gs-y', y);
-        if (typeof width != 'undefined') el.attr('data-gs-width', width);
-        if (typeof height != 'undefined') el.attr('data-gs-height', height);
-        this.container.append(el);
-        this._prepare_element(el);
-    };
-
-    GridStack.prototype.remove_widget = function (el) {
-        var node = $(el).data('_gridstack_node');
-        this.grid.remove_node(node);
-        el.remove();
-    };
-
-    scope.GridStackUI = GridStack;
-
-    $.fn.gridstack = function (opts) {
-        return this.each(function () {
-            if (!$(this).data('_gridstack')) {
-                $(this).data('_gridstack', new GridStack(this, opts));
-            }
-        });
-    };
-
-})(window, _);
diff --git a/index.html b/index.html
index 7ffbb595a..38648feb1 100644
--- a/index.html
+++ b/index.html
@@ -1,17 +1,1003 @@
-<!DOCTYPE html>
-<html>
-<head lang="en">
-    <meta charset="UTF-8">
-    <title>gridstack.js</title>
-
-    <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
-    <link rel="stylesheet" href="gridstack.css"/>
-</head>
-<body>
-
-    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
-    <script src="//code.jquery.com/ui/1.11.2/jquery-ui.min.js"></script>
-    <script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.7.0/underscore-min.js"></script>
-    <script src="gridstack.js"></script>
-</body>
+<!doctype html>
+<html lang="en" class="scroll-smooth">
+  <head>
+    <meta charset="utf-8" />
+    <title>Gridstack.js | Build interactive dashboards in minutes.</title>
+
+    <meta
+      name="viewport"
+      content="width=device-width, initial-scale=1, shrink-to-fit=no"
+    />
+    <meta
+      name="description"
+      content="Easily create dynamic and responsive dashboards with Gridstack.js. Ideal for projects involving React, Vue, Angular, and more."
+    />
+    <meta
+      name="keywords"
+      content="gridstack.js, JavaScript grid layout, draggable widgets, responsive dashboards, TypeScript, React, Vue, Angular, dashboard creation, web development"
+    />
+    <link rel="canonical" href="https://gridstackjs.com/" />
+
+    <meta
+      property="og:title"
+      content="Create Responsive Dashboards with Gridstack.js"
+    />
+    <meta
+      property="og:description"
+      content="Start building highly interactive and responsive dashboards quickly with Gridstack.js. Explore features and integrations with React, Vue, Angular, and more."
+    />
+    <meta property="og:type" content="website" />
+    <meta property="og:url" content="https://gridstackjs.com/" />
+    <!-- TODO <meta property="og:image" content="https://www.yourwebsite.com/path/to/og-image.jpg" /> -->
+    <meta property="og:site_name" content="Gridstack.js Official Site" />
+    <meta property="og:locale" content="en_US" />
+
+    <!-- Twitter Meta Tags -->
+    <meta property="twitter:card" content="summary_large_image" />
+    <meta
+      property="twitter:title"
+      content="Gridstack.js | Create Responsive Dashboards with JavaScript"
+    />
+    <meta
+      property="twitter:description"
+      content="Build dynamic and responsive dashboards quickly with Gridstack.js. Explore features suitable for React, Vue, Angular."
+    />
+    <!-- TODO <meta property="twitter:image" content="https://www.yourwebsite.com/path/to/twitter-image.jpg" /> -->
+
+    <script type="application/ld+json">
+      {
+        "@context": "https://schema.org",
+        "@type": "SoftwareApplication",
+        "name": "Gridstack.js",
+        "applicationCategory": "DeveloperSoftware",
+        "operatingSystem": "All",
+        "url": "https://gridstackjs.com/",
+        "description": "Interactive JavaScript grid layout library that allows you to build dynamic and responsive dashboards in minutes."
+      }
+    </script>
+
+    <!-- Favicon -->
+    <link rel="icon" type="image/x-icon" href="favicon.ico" />
+
+    <script src="node_modules/gridstack/dist/gridstack-all.js"></script>
+
+    <!-- Highlight.js -->
+    <!-- Used to add style to <code> tags -->
+    <link
+      rel="stylesheet"
+      href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css"
+    />
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
+    <script>
+      hljs.highlightAll()
+    </script>
+    <!-- custom style -->
+    <link rel="stylesheet" href="./src/styles/highlight.css" />
+
+    <!-- Tailwind css -->
+    <script src="https://cdn.tailwindcss.com"></script>
+    <script>
+      tailwind.config = {
+        theme: {
+          extend: {
+            animation: {
+              'infinite-scroll': 'infinite-scroll 25s linear infinite',
+            },
+            keyframes: {
+              'infinite-scroll': {
+                from: { transform: 'translateX(0)' },
+                to: { transform: 'translateX(-100%)' },
+              },
+            },
+            colors: {
+              clifford: '#da373d',
+            },
+            fontFamily: {
+              sans: ['Lexend', 'sans-serif'],
+            },
+          },
+        },
+      }
+    </script>
+
+    <!-- Font -->
+    <link rel="preconnect" href="https://fonts.googleapis.com" />
+    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
+    <link
+      href="https://fonts.googleapis.com/css2?family=Lexend:wght@100..900&family=Urbanist:wght@100;200;300;400;500;600;700;800;900&display=swap"
+      rel="stylesheet"
+    />
+    <!-- ICONS -->
+    <!-- Dev icons -->
+    <link
+      rel="stylesheet"
+      type="text/css"
+      href="https://cdn.jsdelivr.net/gh/devicons/devicon@latest/devicon.min.css"
+    />
+    <!-- GRIDSTACK -->
+    <link
+      href="node_modules/gridstack/dist/gridstack.min.css"
+      rel="stylesheet"
+    />
+    <link rel="stylesheet" href="src/styles/globals.css" />
+  </head>
+
+  <body class="font-lexend bg-gray-50">
+    <!-- Navbar -->
+    <nav
+      class="fixed top-0 z-50 flex items-center justify-between w-full h-16 px-4 border-b border-white rounded-b-lg shadow-2xl backdrop-blur-md bg-white/40 shadow-white"
+    >
+      <!-- Logo -->
+      <a
+        href="#"
+        class="flex items-center gap-1 text-2xl font-semibold tracking-tighter text-gray-700 hover:text-[#0038FF] transition-colors"
+      >
+        <img
+          src="logos/gridstack-logo-small.png"
+          alt="gridstack.js logo"
+          class="h-8 object-fit"
+        />
+        Gridstack
+      </a>
+      <!-- End logo -->
+      <!-- Mobile menu button -->
+      <input type="checkbox" id="menu-btn" class="hidden peer" />
+      <label for="menu-btn" class="block cursor-pointer md:hidden">
+        <svg
+          class="w-6 h-6"
+          fill="none"
+          stroke="currentColor"
+          viewBox="0 0 24 24"
+          xmlns="http://www.w3.org/2000/svg"
+        >
+          <path
+            stroke-linecap="round"
+            stroke-linejoin="round"
+            stroke-width="2"
+            d="M4 6h16M4 12h16m-7 6h7"
+          ></path>
+        </svg>
+      </label>
+      <!-- End mobile menu button -->
+      <!-- Menu items -->
+      <ul
+        class="absolute left-0 right-0 z-50 flex flex-col items-center gap-4 py-0 overflow-hidden transition-all duration-500 ease-out bg-white md:gap-0 md:overflow-visible md:bg-transparent md:max-h-16 md:py-0 max-h-0 peer-checked:py-6 peer-checked:max-h-screen md:flex-row peer-checked:backdrop-blur-lg rounded-b-xl md:rounded-none top-full md:top-0 md:relative md:flex"
+      >
+        <li class="hidden lg:block">
+          <a
+            href="#demo"
+            class="px-4 py-2 text-gray-700 transition-all hover:scale-105 hover:text-indigo-400"
+            >Demo</a
+          >
+        </li>
+        <li class="hidden lg:block">
+          <a
+            href="#getStarted"
+            class="px-4 py-2 text-gray-700 transition-all whitespace-nowrap hover:scale-105 hover:text-indigo-400"
+            >Getting Started</a
+          >
+        </li>
+        <li>
+          <a
+            href="https://github.com/gridstack/gridstack.js/blob/develop/README.md"
+            target="_blank"
+            class="px-4 py-2 text-gray-700 transition-all hover:scale-105 hover:text-indigo-400"
+            >Docs</a
+          >
+        </li>
+        <li>
+          <a
+            href="demo/index.html"
+            class="px-4 py-2 text-gray-700 transition-all hover:scale-105 hover:text-indigo-400"
+            >Examples</a
+          >
+        </li>
+        <li>
+          <a
+            href="https://github.com/gridstack/gridstack.js/blob/develop/doc/CHANGES.md"
+            class="px-4 py-2 text-gray-700 transition-all hover:scale-105 hover:text-indigo-400"
+            target="_blank"
+            >Changes</a
+          >
+        </li>
+        <li>
+          <a
+            class="inline-flex items-center gap-1 px-4 py-2 text-gray-700 transition-all whitespace-nowrap hover:scale-105 hover:text-indigo-400"
+            target="_blank"
+            href="https://join.slack.com/t/gridstackjs/shared_invite/zt-3978nsff6-HDNE_N45DydP36NBSV9JFQ"
+          >
+            <svg
+              class="size-4"
+              xmlns="http://www.w3.org/2000/svg"
+              width="24"
+              height="24"
+              viewBox="0 0 24 24"
+              fill="none"
+              stroke="currentColor"
+              stroke-width="2"
+              stroke-linecap="round"
+              stroke-linejoin="round"
+              class="lucide lucide-slack"
+            >
+              <rect width="3" height="8" x="13" y="2" rx="1.5" />
+              <path d="M19 8.5V10h1.5A1.5 1.5 0 1 0 19 8.5" />
+              <rect width="3" height="8" x="8" y="14" rx="1.5" />
+              <path d="M5 15.5V14H3.5A1.5 1.5 0 1 0 5 15.5" />
+              <rect width="8" height="3" x="14" y="13" rx="1.5" />
+              <path d="M15.5 19H14v1.5a1.5 1.5 0 1 0 1.5-1.5" />
+              <rect width="8" height="3" x="2" y="8" rx="1.5" />
+              <path d="M8.5 5H10V3.5A1.5 1.5 0 1 0 8.5 5" />
+            </svg>
+            Slack
+          </a>
+        </li>
+        <li>
+          <form id="search" class="relative shadow-sm">
+            <input
+              type="text"
+              id="searchTerm"
+              class="form-control block w-full rounded-lg border-0 py-1.5 pl-4 pr-20 text-gray-900 ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-inset focus:ring-blue-500 transition-all sm:text-sm h-8"
+              placeholder="Search issues"
+            />
+            <div class="absolute inset-y-0 right-0 flex items-center">
+              <label for="send" class="sr-only">Github issues</label>
+              <button
+                id="send"
+                name="send"
+                type="submit"
+                class="h-full py-0 pl-2 pr-4 text-gray-500 bg-transparent border-0 rounded-md focus:ring-2 focus:ring-inset focus:ring-blue-500 sm:text-sm"
+              >
+                Search
+              </button>
+            </div>
+          </form>
+        </li>
+      </ul>
+      <!-- End menu items -->
+    </nav>
+    <!-- End navbar -->
+    <!-- Hero Section -->
+    <section>
+      <div class="gradient-background -z-10"></div>
+      <div class="z-50 pt-40 mb-48 text-center">
+        <!-- Version badge -->
+        <div
+          class="inline-flex items-center h-10 gap-2 px-4 text-sm text-gray-600 border border-gray-400 rounded-full bg-gradient-to-b from-gray-200/50 to-gray-50/50"
+        >
+          <!-- Zap icon -->
+          <svg
+            xmlns="http://www.w3.org/2000/svg"
+            width="24"
+            height="24"
+            viewBox="0 0 24 24"
+            fill="none"
+            stroke="currentColor"
+            stroke-width="2"
+            stroke-linecap="round"
+            stroke-linejoin="round"
+            class="lucide lucide-zap"
+          >
+            <path
+              d="M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z"
+            ></path>
+          </svg>
+          <p>Current version | <span id="release-version">v10.3.1</span></p>
+        </div>
+        <h1
+          class="mt-6 text-6xl font-semibold tracking-tighter text-gray-800 sm:text-7xl"
+        >
+          Gridstack.js
+        </h1>
+
+        <p class="mt-8">Build interactive dashboards in minutes</p>
+
+        <!-- Github button link -->
+        <a
+          href="https://github.com/gridstack/gridstack.js"
+          target="_blank"
+          class="inline-flex items-center h-16 gap-2 px-8 mt-8 text-lg font-semibold text-white transition-all rounded-full shadow-inner bg-gradient-to-br from-indigo-400 to-indigo-600 shadow-white/25 group hover:scale-95 hover:opacity-80"
+        >
+          <!-- Github Icon -->
+          <svg
+            xmlns="http://www.w3.org/2000/svg"
+            width="24"
+            height="24"
+            viewBox="0 0 24 24"
+            fill="none"
+            stroke="currentColor"
+            stroke-width="2"
+            stroke-linecap="round"
+            stroke-linejoin="round"
+            class="transition-all lucide lucide-github group-hover:scale-110"
+          >
+            <path
+              d="M15 22v-4a4.8 4.8 0 0 0-1-3.5c3 0 6-2 6-5.5.08-1.25-.27-2.48-1-3.5.28-1.15.28-2.35 0-3.5 0 0-1 0-3 1.5-2.64-.5-5.36-.5-8 0C6 2 5 2 5 2c-.3 1.15-.3 2.35 0 3.5A5.403 5.403 0 0 0 4 9c0 3.5 3 5.5 6 5.5-.39.49-.68 1.05-.85 1.65-.17.6-.22 1.23-.15 1.85v4"
+            ></path>
+            <path d="M9 18c-4.51 2-5-2-7-2"></path>
+          </svg>
+          View on Github
+        </a>
+        <p class="mx-auto mt-4 text-gray-500 sm:w-2/3 lg:w-1/3">
+          If you find this library useful, please donate via
+          <a
+            href="https://www.paypal.me/alaind831"
+            target="_blank"
+            class="text-indigo-500 transition-colors hover:text-indigo-600"
+            >PayPal</a
+          >
+          or
+          <a
+            href="https://www.venmo.com/adumesny"
+            target="_blank"
+            class="text-indigo-500 transition-colors hover:text-indigo-600"
+            >Venmo (adumesny)</a
+          >
+          and help support it!
+        </p>
+      </div>
+    </section>
+    <!-- End hero section -->
+    <section class="pt-40 mx-auto max-w-7xl">
+      <p
+        class="inline px-4 py-1 text-sm tracking-tight text-indigo-700 rounded-lg bg-indigo-500/15"
+      >
+        Workflow
+      </p>
+      <h2 class="mt-4 text-4xl font-medium">Framework Agnostic</h2>
+      <p class="mt-4 font-light">
+        Gridstack.js is a modern pure Typescript library, with no external
+        dependencies, that can work with any framework. It comes bundled with an
+        Angular wrapper, and include many React|Vue examples (wrapper coming
+        soon) as well as others.
+      </p>
+      <ul class="grid grid-cols-1 gap-8 mt-8 md:grid-cols-2">
+        <li class="flex items-center gap-4 text-blue-700">
+          <i
+            class="inline-flex items-center justify-center rounded-full devicon-typescript-plain bg-blue-500/15 devicon-laravel-plain icon size-8"
+          ></i>
+          <p class="">Pure Typescript</p>
+        </li>
+        <li class="flex items-center gap-4 text-red-700">
+          <i
+            class="inline-flex items-center justify-center rounded-full bg-red-500/15 devicon-angularjs-plain icon size-8"
+          ></i>
+          <p class="">Angular (included)</p>
+        </li>
+        <li class="flex items-center gap-4 text-sky-700 text text--500">
+          <i
+            class="inline-flex items-center justify-center rounded-full bg-sky-500/15 devicon-react-original icon size-8"
+          ></i>
+          <p class="">React</p>
+        </li>
+        <li class="flex items-center gap-4 text-emerald-700">
+          <i
+            class="inline-flex items-center justify-center rounded-full bg-emerald-500/15 devicon-vuejs-plain icon size-8"
+          ></i>
+          <p class="">Vue</p>
+        </li>
+        <li class="flex items-center gap-4">
+          <p class="">And many more...</p>
+        </li>
+      </ul>
+    </section>
+    <section class="pt-40 mx-auto max-w-7xl">
+      <p
+        class="inline px-4 py-1 text-sm tracking-tight rounded-lg bg-violet-500/15 text-violet-700"
+      >
+        Features
+      </p>
+      <h2 class="mt-4 text-4xl font-medium">Advanced features</h2>
+      <p class="mt-4 font-light">
+        Gridstack.js is a modern Typescript library designed to help developers
+        create beautiful draggable, resizable, responsive layouts with just a
+        few lines of code.
+      </p>
+      <div class="grid grid-cols-1 gap-2 mt-8 md:grid-cols-2">
+        <article class="flex flex-col gap-2 p-4 bg-gray-100 rounded-xl">
+          <h5 class="text-xl font-medium">Full Mobile Support</h5>
+          <p class="font-light">
+            Craft responsive, mobile-friendly applications with ease.
+          </p>
+        </article>
+
+        <article class="flex flex-col gap-2 p-4 bg-gray-100 rounded-xl">
+          <h5 class="text-xl font-medium">Draggable & Resizable Elements</h5>
+          <p class="font-light">
+            Intuitive interfaces with interactive components.
+          </p>
+        </article>
+
+        <article class="flex flex-col gap-2 p-4 bg-gray-100 rounded-xl">
+          <h5 class="text-xl font-medium">Effortless Drag-and-Drop</h5>
+          <p class="font-light">
+            Manage content dynamically from a sidebar for insertions and
+            deletions.
+          </p>
+        </article>
+
+        <article class="flex flex-col gap-2 p-4 bg-gray-100 rounded-xl">
+          <h5 class="text-xl font-medium">Responsive, Column-Based Layouts</h5>
+          <p class="font-light">
+            Design adaptable and visually appealing web layouts.
+          </p>
+        </article>
+
+        <article class="flex flex-col gap-2 p-4 bg-gray-100 rounded-xl">
+          <h5 class="text-xl font-medium">Save and Restore Feature</h5>
+          <p class="font-light">
+            Easily preserve and revert to previous layouts.
+          </p>
+        </article>
+
+        <article class="flex flex-col gap-2 p-4 bg-gray-100 rounded-xl">
+          <h5 class="text-xl font-medium">Inter-grid Interactivity</h5>
+          <p class="font-light">
+            Drag items across multiple grids for sophisticated layout
+            management.
+          </p>
+        </article>
+
+        <article class="flex flex-col gap-2 p-4 bg-gray-100 rounded-xl">
+          <h5 class="text-xl font-medium">Nested Grids</h5>
+          <p class="font-light">
+            Create and manipulate nested grids dynamically to any depth.
+          </p>
+        </article>
+
+        <article class="flex flex-col gap-2 p-4 bg-gray-100 rounded-xl">
+          <h5 class="text-xl font-medium">Extensive Framework Support</h5>
+          <p class="font-light">
+            Native Angular support, along with external bindings for Vue, React,
+            Ember, Knockout.js, and more.
+          </p>
+        </article>
+      </div>
+    </section>
+
+    <main role="main" class="container-fluid" style="padding: 0">
+      <section id="demo" class="pt-40 mx-auto max-w-7xl">
+        <p
+          class="inline px-4 py-1 text-sm tracking-tight text-red-700 rounded-lg bg-red-500/15"
+        >
+          Demonstration
+        </p>
+        <h2 class="mt-4 text-4xl font-medium">Basic demo</h2>
+        <p class="my-4 font-light">
+          Simple to use, configure, and customize. Drag and drop the items below
+          to try !
+        </p>
+
+        <div
+          class="p-1 border rounded-lg bg-gradient-to-br from-gray-200 to-gray-50"
+        >
+          <div class="grid-stack" id="simple-grid"></div>
+        </div>
+      </section>
+      <section id="getStarted" class="pt-40 mx-auto max-w-7xl">
+        <p
+          class="inline px-4 py-1 text-sm tracking-tight rounded-lg bg bg-stone-500/15 text-stone-700"
+        >
+          Code
+        </p>
+        <h2 class="mt-4 text-4xl font-medium">Getting started</h2>
+        <p class="my-4 font-light">
+          Create your first interactive grid by copy-pasting the HTML+JS, as
+          seen below...
+        </p>
+        <pre><code class="bg-gray-100 border border-gray-200 rounded-lg">npm install gridstack</code></pre>
+
+        <p class="my-4 font-light">
+          Then, in your HTML file, include the following code...
+        </p>
+        <pre>
+<code class="bg-gray-100 border border-gray-200 rounded-lg">&lt;script src="node_modules/gridstack/dist/gridstack-all.js"&gt;&lt;/script&gt;
+&lt;link href="node_modules/gridstack/dist/gridstack.min.css" rel="stylesheet"/&gt;
+&lt;style type="text/css"&gt;
+  .grid-stack { background: #FAFAD2; }
+  .grid-stack-item-content { background-color: #18BC9C; }
+&lt;/style&gt;
+
+&lt;div class=&quot;grid-stack&quot;&gt;&lt;/div&gt;
+
+&lt;script type=&quot;text/javascript&quot;&gt;
+  var items = [
+    {content: 'my first widget'}, // will default to location (0,0) and 1x1
+    {w: 2, content: 'another longer widget!'} // will be placed next at (1,0) and 2x1
+  ];
+  var grid = GridStack.init();
+  grid.load(items);
+&lt;/script&gt;
+</code>
+</pre>
+        <p>
+          ...and that's it! Drag, drop, and resize to your heart's content.
+          Looking for more complex examples? Check out the advanced example
+          below, the links in the nav bar, or our docs in
+          <a
+            href="https://github.com/gridstack/gridstack.js/blob/develop/README.md"
+            target="_blank"
+            class="text-indigo-500 transition-colors hover:text-indigo-600"
+            >GitHub</a
+          >
+        </p>
+      </section>
+
+      <section id="advancedDemo" class="pt-40 mx-auto max-w-7xl">
+        <p
+          class="inline px-4 py-1 text-sm tracking-tight rounded-lg bg-amber-500/15 text-amber-700"
+        >
+          Demonstration
+        </p>
+        <h2 class="mt-4 text-4xl font-medium">Advanced demo</h2>
+        <p>
+          A full control example with a trash can to remove widgets and a drag
+          in widget.
+          <br />
+          <br />
+          More complex examples are available to demonstrate the full power of
+          gridstack.js.
+          <br />
+          Drag and drop the items below to try!
+        </p>
+        <div class="grid grid-cols-2 gap-8 mt-8">
+          <div
+            class="flex flex-col items-center justify-center p-1 mx-auto transition-colors rounded-lg cursor-pointer bg-green-500/15 hover:bg-green-500/30 size-40 grid-stack-item newWidget"
+          >
+            <svg
+              class="text-green-700 size-8"
+              xmlns="http://www.w3.org/2000/svg"
+              width="24"
+              height="24"
+              viewBox="0 0 24 24"
+              fill="none"
+              stroke="currentColor"
+              stroke-width="2"
+              stroke-linecap="round"
+              stroke-linejoin="round"
+              class="lucide lucide-hand"
+            >
+              <path d="M18 11V6a2 2 0 0 0-2-2v0a2 2 0 0 0-2 2v0" />
+              <path d="M14 10V4a2 2 0 0 0-2-2v0a2 2 0 0 0-2 2v2" />
+              <path d="M10 10.5V6a2 2 0 0 0-2-2v0a2 2 0 0 0-2 2v8" />
+              <path
+                d="M18 8a2 2 0 1 1 4 0v6a8 8 0 0 1-8 8h-2c-2.8 0-4.5-.86-5.99-2.34l-3.6-3.6a2 2 0 0 1 2.83-2.82L7 15"
+              />
+            </svg>
+            <p class="text-center text-green-700">
+              Drag me into the dashboard!
+            </p>
+          </div>
+          <div
+            id="trash"
+            class="flex flex-col items-center justify-center p-1 mx-auto rounded-lg bg-red-500/15 size-40"
+          >
+            <svg
+              class="text-red-700 size-8"
+              xmlns="http://www.w3.org/2000/svg"
+              width="24"
+              height="24"
+              viewBox="0 0 24 24"
+              fill="none"
+              stroke="currentColor"
+              stroke-width="2"
+              stroke-linecap="round"
+              stroke-linejoin="round"
+              class="lucide lucide-trash-2"
+            >
+              <path d="M3 6h18" />
+              <path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6" />
+              <path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2" />
+              <line x1="10" x2="10" y1="11" y2="17" />
+              <line x1="14" x2="14" y1="11" y2="17" />
+            </svg>
+            <p class="text-center text-red-700">Drop here to remove widget!</p>
+          </div>
+        </div>
+
+        <div
+          class="p-1 mt-8 border rounded-lg bg-gradient-to-br from-gray-200 to-gray-50"
+        >
+          <div class="grid-stack" id="advanced-grid"></div>
+        </div>
+      </section>
+
+      <section id="usedBy" class="pt-40 mx-auto max-w-7xl">
+        <p
+          class="inline px-4 py-1 text-sm tracking-tight text-purple-700 rounded-lg bg-purple-500/15"
+        >
+          Articles
+        </p>
+        <h2 class="mt-4 text-4xl font-medium">Why use gridstack.js ?</h2>
+        <p class="mt-4 font-light">
+          Find out why developers everywhere are choosing gridstack.js for their
+          projects.
+        </p>
+        <ul class="mt-8">
+          <li>
+            Check the package statistics on
+            <a
+              href="https://www.npmjs.com/package/gridstack"
+              target="_blank"
+              class="text-indigo-500 hover:text-indigo-600"
+              >npmjs.org gridstack package</a
+            >
+            and see the evolution of it.
+          </li>
+          <li>
+            Check the gridstack rank on the
+            <a
+              href="https://www.formget.com/jquery-layout-plugins/"
+              target="_blank"
+              class="text-indigo-500 hover:text-indigo-600"
+              >6 Best jQuery Layout Plugins 2020
+            </a>
+            article on formget.
+          </li>
+        </ul>
+      </section>
+      <section class="pt-40 mx-auto max-w-7xl">
+        <p
+          class="inline px-4 py-1 text-sm tracking-tight text-yellow-700 rounded-lg bg-yellow-500/15"
+        >
+          Companies
+        </p>
+        <h2 class="mt-4 text-4xl font-medium">Used by</h2>
+        <p class="mt-4 font-light">
+          Discover the companies and projects that trust gridstack.js for their
+          applications.
+        </p>
+        <div
+          class="grid items-center grid-cols-2 gap-8 my-8 md:grid-cols-3 justify-items-center lg:grid-cols-6"
+        >
+          <a
+            href="https://vmware.com"
+            target="_blank"
+            class="transition-transform hover:scale-105"
+          >
+            <img
+              alt="VMware logo"
+              style="max-width: 100px"
+              class="img-responsive"
+              src="logos/VMW_09Q3_LOGO_Corp_Gray.png"
+          /></a>
+          <a
+            href="https://duckerfrontier.com"
+            target="_blank"
+            class="transition-transform hover:scale-105"
+          >
+            <img
+              alt="Ducker Frontier logo"
+              style="max-width: 150px"
+              class="img-responsive"
+              src="logos/df-logo-transparent-bg.png"
+            />
+          </a>
+          <a
+            href="https://guard.no/"
+            target="_blank"
+            class="transition-transform hover:scale-105"
+          >
+            <img
+              alt="Guard logo"
+              style="max-width: 100px"
+              class="img-responsive"
+              src="logos/Guard-Logo-RGB.png"
+          /></a>
+          <a
+            href="https://www.modul.day/"
+            target="_blank"
+            class="transition-transform hover:scale-105"
+          >
+            <img
+              alt="Modul logo"
+              style="max-width: 100px"
+              class="img-responsive"
+              src="logos/modul-large-logo.png"
+          /></a>
+          <a
+            href="https://nodered.org/"
+            target="_blank"
+            class="transition-transform hover:scale-105"
+          >
+            <img
+              alt="Node-RED logo"
+              style="max-width: 50px"
+              class="img-responsive"
+              src="logos/node-red-icon.png"
+          /></a>
+          <a
+            href="https://flexitanalytics.com"
+            target="_blank"
+            class="transition-transform hover:scale-105"
+          >
+            <img
+              alt="Flexitanalytics logo"
+              style="max-width: 50px"
+              class="img-responsive"
+              src="logos/Flex-X-medium.png"
+          /></a>
+        </div>
+        <p>...and many, many others.</p>
+        <h4 class="mt-20 mb-4 text-2xl">
+          Does your company use gridstack.js ?
+        </h4>
+        <p>
+          We'd love to add your logo! Come join our
+          <a
+            target="_blank"
+            href="https://join.slack.com/t/gridstackjs/shared_invite/zt-3978nsff6-HDNE_N45DydP36NBSV9JFQ"
+            class="text-indigo-500 hover:text-indigo-600 relative pl-5 ml-0.5"
+          >
+            <svg
+              class="absolute left-0 -translate-y-1/2 size-4 top-1/2"
+              xmlns="http://www.w3.org/2000/svg"
+              width="24"
+              height="24"
+              viewBox="0 0 24 24"
+              fill="none"
+              stroke="currentColor"
+              stroke-width="2"
+              stroke-linecap="round"
+              stroke-linejoin="round"
+              class="lucide lucide-slack"
+            >
+              <rect width="3" height="8" x="13" y="2" rx="1.5" />
+              <path d="M19 8.5V10h1.5A1.5 1.5 0 1 0 19 8.5" />
+              <rect width="3" height="8" x="8" y="14" rx="1.5" />
+              <path d="M5 15.5V14H3.5A1.5 1.5 0 1 0 5 15.5" />
+              <rect width="8" height="3" x="14" y="13" rx="1.5" />
+              <path d="M15.5 19H14v1.5a1.5 1.5 0 1 0 1.5-1.5" />
+              <rect width="8" height="3" x="2" y="8" rx="1.5" />
+              <path d="M8.5 5H10V3.5A1.5 1.5 0 1 0 8.5 5" />
+            </svg>
+            Slack community
+          </a>
+          and let us know.
+        </p>
+      </section>
+    </main>
+
+    <footer class="mt-40 border-t">
+      <div class="px-8 py-12 mx-auto md:px-12 lg:px-32 max-w-7xl">
+        <div class="xl:grid xl:grid-cols-3 xl:gap-8">
+          <div>
+            <p class="text-2xl font-bold uppercase">Gridstack.JS</p>
+            <p class="mt-2 text-sm font-medium text-gray-500 lg:w-4/5">
+              Create beautiful draggable, resizable, responsive layouts in
+              minutes.
+            </p>
+          </div>
+          <div
+            class="grid grid-cols-2 gap-8 mt-12 text-sm font-medium text-gray-500 lg:grid-cols-3 lg:mt-0 xl:col-span-2"
+          >
+            <div>
+              <h3 class="text-base text-black">Contribute</h3>
+              <ul role="list" class="mt-4 space-y-2">
+                <li>
+                  <a
+                    href="https://github.com/gridstack/gridstack.js"
+                    target="_blank"
+                    class="inline-flex items-center gap-1 hover:text-indigo-600"
+                  >
+                    <svg
+                      class="size-4"
+                      xmlns="http://www.w3.org/2000/svg"
+                      width="24"
+                      height="24"
+                      viewBox="0 0 24 24"
+                      fill="none"
+                      stroke="currentColor"
+                      stroke-width="2"
+                      stroke-linecap="round"
+                      stroke-linejoin="round"
+                      class="lucide lucide-github"
+                    >
+                      <path
+                        d="M15 22v-4a4.8 4.8 0 0 0-1-3.5c3 0 6-2 6-5.5.08-1.25-.27-2.48-1-3.5.28-1.15.28-2.35 0-3.5 0 0-1 0-3 1.5-2.64-.5-5.36-.5-8 0C6 2 5 2 5 2c-.3 1.15-.3 2.35 0 3.5A5.403 5.403 0 0 0 4 9c0 3.5 3 5.5 6 5.5-.39.49-.68 1.05-.85 1.65-.17.6-.22 1.23-.15 1.85v4"
+                      />
+                      <path d="M9 18c-4.51 2-5-2-7-2" />
+                    </svg>
+                    GitHub
+                  </a>
+                </li>
+              </ul>
+            </div>
+            <div>
+              <h3 class="text-base text-black">Main maintainer</h3>
+              <ul role="list" class="mt-4 space-y-2">
+                <li>
+                  <a
+                    href="https://github.com/adumesny"
+                    target="_blank"
+                    class="hover:text-indigo-600"
+                  >
+                    @Alain Dumesny
+                  </a>
+                </li>
+              </ul>
+              <h3 class="mt-4 text-base text-black">Website</h3>
+              <ul role="list" class="mt-4 space-y-2">
+                <li>
+                  <a
+                    href="https://github.com/damien-schneider"
+                    target="_blank"
+                    class="hover:text-indigo-600"
+                  >
+                    @Damien Schneider
+                  </a>
+                </li>
+              </ul>
+            </div>
+            <div class="mt-12 md:mt-0">
+              <h3 class="text-base text-black">Join the community</h3>
+              <ul role="list" class="mt-4 space-y-2">
+                <li>
+                  <a
+                    href="https://join.slack.com/t/gridstackjs/shared_invite/zt-3978nsff6-HDNE_N45DydP36NBSV9JFQ"
+                    target="_blank"
+                    class="inline-flex items-center gap-1 hover:text-indigo-600"
+                  >
+                    <svg
+                      class="size-4"
+                      xmlns="http://www.w3.org/2000/svg"
+                      width="24"
+                      height="24"
+                      viewBox="0 0 24 24"
+                      fill="none"
+                      stroke="currentColor"
+                      stroke-width="2"
+                      stroke-linecap="round"
+                      stroke-linejoin="round"
+                      class="lucide lucide-slack"
+                    >
+                      <rect width="3" height="8" x="13" y="2" rx="1.5" />
+                      <path d="M19 8.5V10h1.5A1.5 1.5 0 1 0 19 8.5" />
+                      <rect width="3" height="8" x="8" y="14" rx="1.5" />
+                      <path d="M5 15.5V14H3.5A1.5 1.5 0 1 0 5 15.5" />
+                      <rect width="8" height="3" x="14" y="13" rx="1.5" />
+                      <path d="M15.5 19H14v1.5a1.5 1.5 0 1 0 1.5-1.5" />
+                      <rect width="8" height="3" x="2" y="8" rx="1.5" />
+                      <path d="M8.5 5H10V3.5A1.5 1.5 0 1 0 8.5 5" />
+                    </svg>
+                    Slack
+                  </a>
+                </li>
+              </ul>
+            </div>
+          </div>
+        </div>
+        <div
+          class="flex flex-col pt-12 md:flex-row md:items-center md:justify-between"
+        >
+          <span class="text-sm font-medium text-gray-500">
+            Copyright ©2019-2024 gridstack.js is open source software
+            maintained by
+            <a
+              aria-label="Gridstack.js team"
+              href="https://github.com/gridstack/gridstack.js#the-team"
+              target="_blank"
+              class="text-indigo-500 hover:text-indigo-600"
+            >
+              the gridstack.js team
+            </a>
+            but wouldn't be possible without the help of developers everywhere.
+          </span>
+        </div>
+      </div>
+    </footer>
+    <script src="src/scripts/fetch-latest-github-release.js"></script>
+    <script type="text/javascript">
+      // NOTE: REAL apps would sanitize-html or DOMPurify before blinding setting innerHTML. see #2736
+      GridStack.renderCB = function(el, w) {
+        el.innerHTML = w.content;
+      };
+      var simple = [
+        { x: 0, y: 0, w: 4, h: 2, content: '1' },
+        { x: 4, y: 0, w: 4, h: 4, content: '2' },
+        { x: 8, y: 0, w: 2, h: 2,
+          content: `<div class="flex flex-col items-center justify-center w-full h-full text-indigo-600">
+          <svg class="size-8" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-hand">
+            <path d="M18 11V6a2 2 0 0 0-2-2v0a2 2 0 0 0-2 2v0"/><path d="M14 10V4a2 2 0 0 0-2-2v0a2 2 0 0 0-2 2v2"/>
+            <path d="M10 10.5V6a2 2 0 0 0-2-2v0a2 2 0 0 0-2 2v8"/><path d="M18 8a2 2 0 1 1 4 0v6a8 8 0 0 1-8 8h-2c-2.8 0-4.5-.86-5.99-2.34l-3.6-3.6a2 2 0 0 1 2.83-2.82L7 15"/>
+          </svg>
+          <p>Drag me !</p>
+        </div>`,
+        },
+        { x: 10, y: 0, w: 2, h: 2, content: '4' },
+        { x: 0, y: 2, w: 2, h: 2, content: '5' },
+        { x: 2, y: 2, w: 2, h: 4, content: '6' },
+        { x: 8, y: 2, w: 4, h: 2, content: '7' },
+        { x: 0, y: 4, w: 2, h: 2, content: '8' },
+        { x: 4, y: 4, w: 4, h: 2, content: '9' },
+        { x: 8, y: 4, w: 2, h: 2, content: '10' },
+        { x: 10, y: 4, w: 2, h: 2, content: '11' },
+      ]
+      var advanced = [
+        { x: 0, y: 0, w: 4, h: 2, content: '1' },
+        { x: 4, y: 0, w: 4, h: 4, noMove: true, noResize: true, locked: true,
+          content: `<div class="flex flex-col items-center justify-center w-full h-full gap-2 text-red-600">
+          <svg class="text-red-600 size-8" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-lock-keyhole">
+            <circle cx="12" cy="16" r="1"/><rect x="3" y="10" width="18" height="12" rx="2"/>
+            <path d="M7 10V7a5 5 0 0 1 10 0v3"/>
+          </svg>
+          <p>locked: can't be pushed by others, only user!</p>
+        </div>`,
+        },
+        { x: 8, y: 0, w: 2, h: 2, minW: 2, noResize: true,
+          content: `<div class="flex flex-col items-center justify-center w-full h-full gap-2 text-red-600">
+          <svg class="size-8" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-scaling">
+            <path d="M12 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/>
+            <path d="M14 15H9v-5"/><path d="M16 3h5v5"/><path d="M21 3 9 15"/>
+          </svg>
+          <p>Resize locked</p>
+        </div>`,
+        },
+        { x: 10, y: 0, w: 2, h: 2, content: '4' },
+        { x: 0, y: 2, w: 2, h: 2, content: '5' },
+        { x: 2, y: 2, w: 2, h: 4, content: '6' },
+        { x: 8, y: 2, w: 4, h: 2, content: '7' },
+        { x: 0, y: 4, w: 2, h: 2, content: '8' },
+        { x: 4, y: 4, w: 4, h: 2, content: '9' },
+        { x: 8, y: 4, w: 2, h: 2, content: '10' },
+        { x: 10, y: 4, w: 2, h: 2, content: '11' },
+      ]
+
+      // Setup Grids without jQuery
+      document.addEventListener('DOMContentLoaded', function () {
+        var simpleGrid = GridStack.init( { margin: 5,  children: simple }, '#simple-grid' )
+
+        var advGrid = GridStack.init(
+          {
+            margin: 5,
+            acceptWidgets: true,
+            removable: '#trash',
+            removeTimeout: 100,
+            children: advanced
+          },
+          '#advanced-grid'
+        )
+
+        var insert = [ {h: 2, content: 'new item'}];
+        GridStack.setupDragIn('.newWidget', undefined, insert);
+
+        document
+          .getElementById('search')
+          .addEventListener('submit', function (event) {
+            event.preventDefault()
+            var searchTerm = document.getElementById('searchTerm').value
+            window.open(
+              `https://github.com/gridstack/gridstack.js/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+${searchTerm}`,
+              '_blank'
+            )
+          })
+      })
+    </script>
+
+    <!-- Google Analytics -->
+    <script>
+      ;(function (i, s, o, g, r, a, m) {
+        i['GoogleAnalyticsObject'] = r
+        ;(i[r] =
+          i[r] ||
+          function () {
+            ;(i[r].q = i[r].q || []).push(arguments)
+          }),
+          (i[r].l = 1 * new Date())
+        ;(a = s.createElement(o)), (m = s.getElementsByTagName(o)[0])
+        a.async = 1
+        a.src = g
+        m.parentNode.insertBefore(a, m)
+      })(
+        window,
+        document,
+        'script',
+        'https://www.google-analytics.com/analytics.js',
+        'ga'
+      )
+
+      ga('create', 'UA-1891156-8', 'auto')
+      ga('send', 'pageview')
+    </script>
+    <!-- End Google Analytics -->
+  </body>
 </html>
diff --git a/logos/Flex-X-medium.png b/logos/Flex-X-medium.png
new file mode 100644
index 000000000..ff3eae0c6
Binary files /dev/null and b/logos/Flex-X-medium.png differ
diff --git a/logos/Guard-Logo-RGB.png b/logos/Guard-Logo-RGB.png
new file mode 100644
index 000000000..16d6cdbcf
Binary files /dev/null and b/logos/Guard-Logo-RGB.png differ
diff --git a/logos/VMW_09Q3_LOGO_Corp_Gray.png b/logos/VMW_09Q3_LOGO_Corp_Gray.png
new file mode 100644
index 000000000..09476bb01
Binary files /dev/null and b/logos/VMW_09Q3_LOGO_Corp_Gray.png differ
diff --git a/logos/df-logo-transparent-bg.png b/logos/df-logo-transparent-bg.png
new file mode 100644
index 000000000..7fe682101
Binary files /dev/null and b/logos/df-logo-transparent-bg.png differ
diff --git a/logos/gridstack-logo-large.png b/logos/gridstack-logo-large.png
new file mode 100644
index 000000000..14d57e711
Binary files /dev/null and b/logos/gridstack-logo-large.png differ
diff --git a/logos/gridstack-logo-small.png b/logos/gridstack-logo-small.png
new file mode 100644
index 000000000..66e108250
Binary files /dev/null and b/logos/gridstack-logo-small.png differ
diff --git a/logos/modul-large-logo.png b/logos/modul-large-logo.png
new file mode 100644
index 000000000..eb3711bb5
Binary files /dev/null and b/logos/modul-large-logo.png differ
diff --git a/logos/node-red-icon.png b/logos/node-red-icon.png
new file mode 100644
index 000000000..898c242b6
Binary files /dev/null and b/logos/node-red-icon.png differ
diff --git a/node_modules/gridstack/dist/gridstack-all.js b/node_modules/gridstack/dist/gridstack-all.js
new file mode 100644
index 000000000..f87af0ec3
--- /dev/null
+++ b/node_modules/gridstack/dist/gridstack-all.js
@@ -0,0 +1,3 @@
+/*! For license information please see gridstack-all.js.LICENSE.txt */
+!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.GridStack=t():e.GridStack=t()}(self,(()=>(()=>{"use strict";var e={d:(t,i)=>{for(var s in i)e.o(i,s)&&!e.o(t,s)&&Object.defineProperty(t,s,{enumerable:!0,get:i[s]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)},t={};e.d(t,{GridStack:()=>x});class i{static getElements(e,t=document){if("string"==typeof e){const i="getElementById"in t?t:void 0;if(i&&!isNaN(+e[0])){const t=i.getElementById(e);return t?[t]:[]}let s=t.querySelectorAll(e);return s.length||"."===e[0]||"#"===e[0]||(s=t.querySelectorAll("."+e),s.length||(s=t.querySelectorAll("#"+e))),Array.from(s)}return[e]}static getElement(e,t=document){if("string"==typeof e){const i="getElementById"in t?t:void 0;if(!e.length)return null;if(i&&"#"===e[0])return i.getElementById(e.substring(1));if("#"===e[0]||"."===e[0]||"["===e[0])return t.querySelector(e);if(i&&!isNaN(+e[0]))return i.getElementById(e);let s=t.querySelector(e);return i&&!s&&(s=i.getElementById(e)),s||(s=t.querySelector("."+e)),s}return e}static lazyLoad(e){return e.lazyLoad||e.grid?.opts?.lazyLoad&&!1!==e.lazyLoad}static createDiv(e,t){const i=document.createElement("div");return e.forEach((e=>{e&&i.classList.add(e)})),t?.appendChild(i),i}static shouldSizeToContent(e,t=!1){return e?.grid&&(t?!0===e.sizeToContent||!0===e.grid.opts.sizeToContent&&void 0===e.sizeToContent:!!e.sizeToContent||e.grid.opts.sizeToContent&&!1!==e.sizeToContent)}static isIntercepted(e,t){return!(e.y>=t.y+t.h||e.y+e.h<=t.y||e.x+e.w<=t.x||e.x>=t.x+t.w)}static isTouching(e,t){return i.isIntercepted(e,{x:t.x-.5,y:t.y-.5,w:t.w+1,h:t.h+1})}static areaIntercept(e,t){const i=e.x>t.x?e.x:t.x,s=e.x+e.w<t.x+t.w?e.x+e.w:t.x+t.w;if(s<=i)return 0;const o=e.y>t.y?e.y:t.y,n=e.y+e.h<t.y+t.h?e.y+e.h:t.y+t.h;return n<=o?0:(s-i)*(n-o)}static area(e){return e.w*e.h}static sort(e,t=1){const i=1e4;return e.sort(((e,s)=>{const o=t*((e.y??i)-(s.y??i));return 0===o?t*((e.x??i)-(s.x??i)):o}))}static find(e,t){return t?e.find((e=>e.id===t)):void 0}static toBool(e){return"boolean"==typeof e?e:"string"==typeof e?!(""===(e=e.toLowerCase())||"no"===e||"false"===e||"0"===e):Boolean(e)}static toNumber(e){return null===e||0===e.length?void 0:Number(e)}static parseHeight(e){let t,i="px";if("string"==typeof e)if("auto"===e||""===e)t=0;else{const s=e.match(/^(-[0-9]+\.[0-9]+|[0-9]*\.[0-9]+|-[0-9]+|[0-9]+)(px|em|rem|vh|vw|%|cm|mm)?$/);if(!s)throw new Error(`Invalid height val = ${e}`);i=s[2]||"px",t=parseFloat(s[1])}else t=e;return{h:t,unit:i}}static defaults(e,...t){return t.forEach((t=>{for(const i in t){if(!t.hasOwnProperty(i))return;null===e[i]||void 0===e[i]?e[i]=t[i]:"object"==typeof t[i]&&"object"==typeof e[i]&&this.defaults(e[i],t[i])}})),e}static same(e,t){if("object"!=typeof e)return e==t;if(typeof e!=typeof t)return!1;if(Object.keys(e).length!==Object.keys(t).length)return!1;for(const i in e)if(e[i]!==t[i])return!1;return!0}static copyPos(e,t,i=!1){return void 0!==t.x&&(e.x=t.x),void 0!==t.y&&(e.y=t.y),void 0!==t.w&&(e.w=t.w),void 0!==t.h&&(e.h=t.h),i&&(t.minW&&(e.minW=t.minW),t.minH&&(e.minH=t.minH),t.maxW&&(e.maxW=t.maxW),t.maxH&&(e.maxH=t.maxH)),e}static samePos(e,t){return e&&t&&e.x===t.x&&e.y===t.y&&(e.w||1)===(t.w||1)&&(e.h||1)===(t.h||1)}static sanitizeMinMax(e){e.minW||delete e.minW,e.minH||delete e.minH,e.maxW||delete e.maxW,e.maxH||delete e.maxH}static removeInternalAndSame(e,t){if("object"==typeof e&&"object"==typeof t)for(let s in e){const o=e[s],n=t[s];"_"===s[0]||o===n?delete e[s]:o&&"object"==typeof o&&void 0!==n&&(i.removeInternalAndSame(o,n),Object.keys(o).length||delete e[s])}}static removeInternalForSave(e,t=!0){for(let t in e)"_"!==t[0]&&null!==e[t]&&void 0!==e[t]||delete e[t];delete e.grid,t&&delete e.el,e.autoPosition||delete e.autoPosition,e.noResize||delete e.noResize,e.noMove||delete e.noMove,e.locked||delete e.locked,1!==e.w&&e.w!==e.minW||delete e.w,1!==e.h&&e.h!==e.minH||delete e.h}static throttle(e,t){let i=!1;return(...s)=>{i||(i=!0,setTimeout((()=>{e(...s),i=!1}),t))}}static removePositioningStyles(e){const t=e.style;t.position&&t.removeProperty("position"),t.left&&t.removeProperty("left"),t.top&&t.removeProperty("top"),t.width&&t.removeProperty("width"),t.height&&t.removeProperty("height")}static getScrollElement(e){if(!e)return document.scrollingElement||document.documentElement;const t=getComputedStyle(e);return/(auto|scroll)/.test(t.overflow+t.overflowY)?e:this.getScrollElement(e.parentElement)}static updateScrollPosition(e,t,i){const s=e.getBoundingClientRect(),o=window.innerHeight||document.documentElement.clientHeight;if(s.top<0||s.bottom>o){const n=s.bottom-o,r=s.top,a=this.getScrollElement(e);if(null!==a){const h=a.scrollTop;s.top<0&&i<0?e.offsetHeight>o?a.scrollTop+=i:a.scrollTop+=Math.abs(r)>Math.abs(i)?i:r:i>0&&(e.offsetHeight>o?a.scrollTop+=i:a.scrollTop+=n>i?i:n),t.top+=a.scrollTop-h}}}static updateScrollResize(e,t,i){const s=this.getScrollElement(t),o=s.clientHeight,n=s===this.getScrollElement()?0:s.getBoundingClientRect().top,r=e.clientY-n,a=r>o-i;r<i?s.scrollBy({behavior:"smooth",top:r-i}):a&&s.scrollBy({behavior:"smooth",top:i-(o-r)})}static clone(e){return null==e||"object"!=typeof e?e:e instanceof Array?[...e]:{...e}}static cloneDeep(e){const t=["parentGrid","el","grid","subGrid","engine"],s=i.clone(e);for(const o in s)s.hasOwnProperty(o)&&"object"==typeof s[o]&&"__"!==o.substring(0,2)&&!t.find((e=>e===o))&&(s[o]=i.cloneDeep(e[o]));return s}static cloneNode(e){const t=e.cloneNode(!0);return t.removeAttribute("id"),t}static appendTo(e,t){let s;s="string"==typeof t?i.getElement(t):t,s&&s.appendChild(e)}static addElStyles(e,t){if(t instanceof Object)for(const i in t)t.hasOwnProperty(i)&&(Array.isArray(t[i])?t[i].forEach((t=>{e.style[i]=t})):e.style[i]=t[i])}static initEvent(e,t){const i={type:t.type},s={button:0,which:0,buttons:1,bubbles:!0,cancelable:!0,target:t.target?t.target:e.target};return["altKey","ctrlKey","metaKey","shiftKey"].forEach((t=>i[t]=e[t])),["pageX","pageY","clientX","clientY","screenX","screenY"].forEach((t=>i[t]=e[t])),{...i,...s}}static simulateMouseEvent(e,t,i){const s=e,o=new MouseEvent(t,{bubbles:!0,composed:!0,cancelable:!0,view:window,detail:1,screenX:e.screenX,screenY:e.screenY,clientX:e.clientX,clientY:e.clientY,ctrlKey:s.ctrlKey??!1,altKey:s.altKey??!1,shiftKey:s.shiftKey??!1,metaKey:s.metaKey??!1,button:0,relatedTarget:e.target});(i||e.target).dispatchEvent(o)}static getValuesFromTransformedElement(e){const t=document.createElement("div");i.addElStyles(t,{opacity:"0",position:"fixed",top:"0px",left:"0px",width:"1px",height:"1px",zIndex:"-999999"}),e.appendChild(t);const s=t.getBoundingClientRect();return e.removeChild(t),t.remove(),{xScale:1/s.width,yScale:1/s.height,xOffset:s.left,yOffset:s.top}}static swap(e,t,i){if(!e)return;const s=e[t];e[t]=e[i],e[i]=s}static canBeRotated(e){return!(!e||e.w===e.h||e.locked||e.noResize||e.grid?.opts.disableResize||e.minW&&e.minW===e.maxW||e.minH&&e.minH===e.maxH)}}class s{constructor(e={}){this.addedNodes=[],this.removedNodes=[],this.defaultColumn=12,this.column=e.column||this.defaultColumn,this.column>this.defaultColumn&&(this.defaultColumn=this.column),this.maxRow=e.maxRow,this._float=e.float,this.nodes=e.nodes||[],this.onChange=e.onChange}batchUpdate(e=!0,t=!0){return!!this.batchMode===e||(this.batchMode=e,e?(this._prevFloat=this._float,this._float=!0,this.cleanNodes(),this.saveInitial()):(this._float=this._prevFloat,delete this._prevFloat,t&&this._packNodes(),this._notify())),this}_useEntireRowArea(e,t){return(!this.float||this.batchMode&&!this._prevFloat)&&!this._hasLocked&&(!e._moving||e._skipDown||t.y<=e.y)}_fixCollisions(e,t=e,s,o={}){if(this.sortNodes(-1),!(s=s||this.collide(e,t)))return!1;if(e._moving&&!o.nested&&!this.float&&this.swap(e,s))return!0;let n=t;!this._loading&&this._useEntireRowArea(e,t)&&(n={x:0,w:this.column,y:t.y,h:t.h},s=this.collide(e,n,o.skip));let r=!1;const a={nested:!0,pack:!1};let h=0;for(;s=s||this.collide(e,n,o.skip);){if(h++>2*this.nodes.length)throw new Error("Infinite collide check");let n;if(s.locked||this._loading||e._moving&&!e._skipDown&&t.y>e.y&&!this.float&&(!this.collide(s,{...s,y:e.y},e)||!this.collide(s,{...s,y:t.y-s.h},e))){e._skipDown=e._skipDown||t.y>e.y;const h={...t,y:s.y+s.h,...a};n=!(!this._loading||!i.samePos(e,h))||this.moveNode(e,h),(s.locked||this._loading)&&n?i.copyPos(t,e):!s.locked&&n&&o.pack&&(this._packNodes(),t.y=s.y+s.h,i.copyPos(e,t)),r=r||n}else n=this.moveNode(s,{...s,y:t.y+t.h,skip:e,...a});if(!n)return r;s=void 0}return r}collide(e,t=e,s){const o=e._id,n=s?._id;return this.nodes.find((e=>e._id!==o&&e._id!==n&&i.isIntercepted(e,t)))}collideAll(e,t=e,s){const o=e._id,n=s?._id;return this.nodes.filter((e=>e._id!==o&&e._id!==n&&i.isIntercepted(e,t)))}directionCollideCoverage(e,t,i){if(!t.rect||!e._rect)return;const s=e._rect,o={...t.rect};let n;o.y>s.y?(o.h+=o.y-s.y,o.y=s.y):o.h+=s.y-o.y,o.x>s.x?(o.w+=o.x-s.x,o.x=s.x):o.w+=s.x-o.x;let r=.5;for(let e of i){if(e.locked||!e._rect)break;const t=e._rect;let i=Number.MAX_VALUE,a=Number.MAX_VALUE;s.y<t.y?i=(o.y+o.h-t.y)/t.h:s.y+s.h>t.y+t.h&&(i=(t.y+t.h-o.y)/t.h),s.x<t.x?a=(o.x+o.w-t.x)/t.w:s.x+s.w>t.x+t.w&&(a=(t.x+t.w-o.x)/t.w);const h=Math.min(a,i);h>r&&(r=h,n=e)}return t.collide=n,n}cacheRects(e,t,i,s,o,n){return this.nodes.forEach((r=>r._rect={y:r.y*t+i,x:r.x*e+n,w:r.w*e-n-s,h:r.h*t-i-o})),this}swap(e,t){if(!t||t.locked||!e||e.locked)return!1;function s(){const i=t.x,s=t.y;return t.x=e.x,t.y=e.y,e.h!=t.h?(e.x=i,e.y=t.y+t.h):e.w!=t.w?(e.x=t.x+t.w,e.y=s):(e.x=i,e.y=s),e._dirty=t._dirty=!0,!0}let o;if(e.w===t.w&&e.h===t.h&&(e.x===t.x||e.y===t.y)&&(o=i.isTouching(e,t)))return s();if(!1!==o){if(e.w===t.w&&e.x===t.x&&(o||(o=i.isTouching(e,t)))){if(t.y<e.y){const i=e;e=t,t=i}return s()}if(!1!==o){if(e.h===t.h&&e.y===t.y&&(o||(o=i.isTouching(e,t)))){if(t.x<e.x){const i=e;e=t,t=i}return s()}return!1}}}isAreaEmpty(e,t,i,s){const o={x:e||0,y:t||0,w:i||1,h:s||1};return!this.collide(o)}compact(e="compact",t=!0){if(0===this.nodes.length)return this;t&&this.sortNodes();const i=this.batchMode;i||this.batchUpdate();const s=this._inColumnResize;s||(this._inColumnResize=!0);const o=this.nodes;return this.nodes=[],o.forEach(((t,i,s)=>{let o;t.locked||(t.autoPosition=!0,"list"===e&&i&&(o=s[i-1])),this.addNode(t,!1,o)})),s||delete this._inColumnResize,i||this.batchUpdate(!1),this}set float(e){this._float!==e&&(this._float=e||!1,e||this._packNodes()._notify())}get float(){return this._float||!1}sortNodes(e=1){return this.nodes=i.sort(this.nodes,e),this}_packNodes(){return this.batchMode||(this.sortNodes(),this.float?this.nodes.forEach((e=>{if(e._updating||void 0===e._orig||e.y===e._orig.y)return;let t=e.y;for(;t>e._orig.y;)--t,this.collide(e,{x:e.x,y:t,w:e.w,h:e.h})||(e._dirty=!0,e.y=t)})):this.nodes.forEach(((e,t)=>{if(!e.locked)for(;e.y>0;){const i=0===t?0:e.y-1;if(0!==t&&this.collide(e,{x:e.x,y:i,w:e.w,h:e.h}))break;e._dirty=e.y!==i,e.y=i}}))),this}prepareNode(e,t){e._id=e._id??s._idSeq++;const o=e.id;if(o){let t=1;for(;this.nodes.find((t=>t.id===e.id&&t!==e));)e.id=o+"_"+t++}void 0!==e.x&&void 0!==e.y&&null!==e.x&&null!==e.y||(e.autoPosition=!0);const n={x:0,y:0,w:1,h:1};return i.defaults(e,n),e.autoPosition||delete e.autoPosition,e.noResize||delete e.noResize,e.noMove||delete e.noMove,i.sanitizeMinMax(e),"string"==typeof e.x&&(e.x=Number(e.x)),"string"==typeof e.y&&(e.y=Number(e.y)),"string"==typeof e.w&&(e.w=Number(e.w)),"string"==typeof e.h&&(e.h=Number(e.h)),isNaN(e.x)&&(e.x=n.x,e.autoPosition=!0),isNaN(e.y)&&(e.y=n.y,e.autoPosition=!0),isNaN(e.w)&&(e.w=n.w),isNaN(e.h)&&(e.h=n.h),this.nodeBoundFix(e,t),e}nodeBoundFix(e,t){const s=e._orig||i.copyPos({},e);if(e.maxW&&(e.w=Math.min(e.w||1,e.maxW)),e.maxH&&(e.h=Math.min(e.h||1,e.maxH)),e.minW&&(e.w=Math.max(e.w||1,e.minW)),e.minH&&(e.h=Math.max(e.h||1,e.minH)),(e.x||0)+(e.w||1)>this.column&&this.column<this.defaultColumn&&!this._inColumnResize&&!this.skipCacheUpdate&&e._id&&-1===this.findCacheLayout(e,this.defaultColumn)){const t={...e};t.autoPosition||void 0===t.x?(delete t.x,delete t.y):t.x=Math.min(this.defaultColumn-1,t.x),t.w=Math.min(this.defaultColumn,t.w||1),this.cacheOneLayout(t,this.defaultColumn)}return e.w>this.column?e.w=this.column:e.w<1&&(e.w=1),this.maxRow&&e.h>this.maxRow?e.h=this.maxRow:e.h<1&&(e.h=1),e.x<0&&(e.x=0),e.y<0&&(e.y=0),e.x+e.w>this.column&&(t?e.w=this.column-e.x:e.x=this.column-e.w),this.maxRow&&e.y+e.h>this.maxRow&&(t?e.h=this.maxRow-e.y:e.y=this.maxRow-e.h),i.samePos(e,s)||(e._dirty=!0),this}getDirtyNodes(e){return e?this.nodes.filter((e=>e._dirty&&!i.samePos(e,e._orig))):this.nodes.filter((e=>e._dirty))}_notify(e){if(this.batchMode||!this.onChange)return this;const t=(e||[]).concat(this.getDirtyNodes());return this.onChange(t),this}cleanNodes(){return this.batchMode||this.nodes.forEach((e=>{delete e._dirty,delete e._lastTried})),this}saveInitial(){return this.nodes.forEach((e=>{e._orig=i.copyPos({},e),delete e._dirty})),this._hasLocked=this.nodes.some((e=>e.locked)),this}restoreInitial(){return this.nodes.forEach((e=>{e._orig&&!i.samePos(e,e._orig)&&(i.copyPos(e,e._orig),e._dirty=!0)})),this._notify(),this}findEmptyPosition(e,t=this.nodes,s=this.column,o){let n=!1;for(let r=o?o.y*s+(o.x+o.w):0;!n;++r){const o=r%s,a=Math.floor(r/s);if(o+e.w>s)continue;const h={x:o,y:a,w:e.w,h:e.h};t.find((e=>i.isIntercepted(h,e)))||(e.x===o&&e.y===a||(e._dirty=!0),e.x=o,e.y=a,delete e.autoPosition,n=!0)}return n}addNode(e,t=!1,i){const s=this.nodes.find((t=>t._id===e._id));if(s)return s;let o;return this._inColumnResize?this.nodeBoundFix(e):this.prepareNode(e),delete e._temporaryRemoved,delete e._removeDOM,e.autoPosition&&this.findEmptyPosition(e,this.nodes,this.column,i)&&(delete e.autoPosition,o=!0),this.nodes.push(e),t&&this.addedNodes.push(e),o||this._fixCollisions(e),this.batchMode||this._packNodes()._notify(),e}removeNode(e,t=!0,i=!1){return this.nodes.find((t=>t._id===e._id))?(i&&this.removedNodes.push(e),t&&(e._removeDOM=!0),this.nodes=this.nodes.filter((t=>t._id!==e._id)),e._isAboutToRemove||this._packNodes(),this._notify([e]),this):this}removeAll(e=!0,t=!0){if(delete this._layouts,!this.nodes.length)return this;e&&this.nodes.forEach((e=>e._removeDOM=!0));const i=this.nodes;return this.removedNodes=t?i:[],this.nodes=[],this._notify(i)}moveNodeCheck(e,t){if(!this.changedPosConstrain(e,t))return!1;if(t.pack=!0,!this.maxRow)return this.moveNode(e,t);let o;const n=new s({column:this.column,float:this.float,nodes:this.nodes.map((t=>t._id===e._id?(o={...t},o):{...t}))});if(!o)return!1;const r=n.moveNode(o,t)&&n.getRow()<=Math.max(this.getRow(),this.maxRow);if(!r&&!t.resizing&&t.collide){const i=t.collide.el.gridstackNode;if(this.swap(e,i))return this._notify(),!0}return!!r&&(n.nodes.filter((e=>e._dirty)).forEach((e=>{const t=this.nodes.find((t=>t._id===e._id));t&&(i.copyPos(t,e),t._dirty=!0)})),this._notify(),!0)}willItFit(e){if(delete e._willFitPos,!this.maxRow)return!0;const t=new s({column:this.column,float:this.float,nodes:this.nodes.map((e=>({...e})))}),o={...e};return this.cleanupNode(o),delete o.el,delete o._id,delete o.content,delete o.grid,t.addNode(o),t.getRow()<=this.maxRow&&(e._willFitPos=i.copyPos({},o),!0)}changedPosConstrain(e,t){return t.w=t.w||e.w,t.h=t.h||e.h,e.x!==t.x||e.y!==t.y||(e.maxW&&(t.w=Math.min(t.w,e.maxW)),e.maxH&&(t.h=Math.min(t.h,e.maxH)),e.minW&&(t.w=Math.max(t.w,e.minW)),e.minH&&(t.h=Math.max(t.h,e.minH)),e.w!==t.w||e.h!==t.h)}moveNode(e,t){if(!e||!t)return!1;let s;void 0!==t.pack||this.batchMode||(s=t.pack=!0),"number"!=typeof t.x&&(t.x=e.x),"number"!=typeof t.y&&(t.y=e.y),"number"!=typeof t.w&&(t.w=e.w),"number"!=typeof t.h&&(t.h=e.h);const o=e.w!==t.w||e.h!==t.h,n=i.copyPos({},e,!0);if(i.copyPos(n,t),this.nodeBoundFix(n,o),i.copyPos(t,n),!t.forceCollide&&i.samePos(e,t))return!1;const r=i.copyPos({},e),a=this.collideAll(e,n,t.skip);let h=!0;if(a.length){const o=e._moving&&!t.nested;let r=o?this.directionCollideCoverage(e,t,a):a[0];if(o&&r&&e.grid?.opts?.subGridDynamic&&!e.grid._isTemp){const s=i.areaIntercept(t.rect,r._rect),o=i.area(t.rect),n=i.area(r._rect);s/(o<n?o:n)>.8&&(r.grid.makeSubGrid(r.el,void 0,e),r=void 0)}r?h=!this._fixCollisions(e,n,r,t):(h=!1,s&&delete t.pack)}return h&&!i.samePos(e,n)&&(e._dirty=!0,i.copyPos(e,n)),t.pack&&this._packNodes()._notify(),!i.samePos(e,r)}getRow(){return this.nodes.reduce(((e,t)=>Math.max(e,t.y+t.h)),0)}beginUpdate(e){return e._updating||(e._updating=!0,delete e._skipDown,this.batchMode||this.saveInitial()),this}endUpdate(){const e=this.nodes.find((e=>e._updating));return e&&(delete e._updating,delete e._skipDown),this}save(e=!0,t){const s=this._layouts?.length,o=s&&this.column!==s-1?this._layouts[s-1]:null,n=[];return this.sortNodes(),this.nodes.forEach((s=>{const r=o?.find((e=>e._id===s._id)),a={...s,...r||{}};i.removeInternalForSave(a,!e),t&&t(s,a),n.push(a)})),n}layoutsNodesChange(e){return!this._layouts||this._inColumnResize||this._layouts.forEach(((t,i)=>{if(!t||i===this.column)return this;if(i<this.column)this._layouts[i]=void 0;else{const s=i/this.column;e.forEach((e=>{if(!e._orig)return;const i=t.find((t=>t._id===e._id));i&&(i.y>=0&&e.y!==e._orig.y&&(i.y+=e.y-e._orig.y),e.x!==e._orig.x&&(i.x=Math.round(e.x*s)),e.w!==e._orig.w&&(i.w=Math.round(e.w*s)))}))}})),this}columnChanged(e,t,s="moveScale"){if(!this.nodes.length||!t||e===t)return this;const o="compact"===s||"list"===s;o&&this.sortNodes(1),t<e&&this.cacheLayout(this.nodes,e),this.batchUpdate();let n=[],r=o?this.nodes:i.sort(this.nodes,-1);if(t>e&&this._layouts){const i=this._layouts[t]||[],s=this._layouts.length-1;!i.length&&e!==s&&this._layouts[s]?.length&&(e=s,this._layouts[s].forEach((e=>{const t=r.find((t=>t._id===e._id));t&&(o||e.autoPosition||(t.x=e.x??t.x,t.y=e.y??t.y),t.w=e.w??t.w,null!=e.x&&void 0!==e.y||(t.autoPosition=!0))}))),i.forEach((e=>{const t=r.findIndex((t=>t._id===e._id));if(-1!==t){const i=r[t];if(o)return void(i.w=e.w);(e.autoPosition||isNaN(e.x)||isNaN(e.y))&&this.findEmptyPosition(e,n),e.autoPosition||(i.x=e.x??i.x,i.y=e.y??i.y,i.w=e.w??i.w,n.push(i)),r.splice(t,1)}}))}if(o)this.compact(s,!1);else{if(r.length)if("function"==typeof s)s(t,e,n,r);else{const i=o||"none"===s?1:t/e,a="move"===s||"moveScale"===s,h="scale"===s||"moveScale"===s;r.forEach((s=>{s.x=1===t?0:a?Math.round(s.x*i):Math.min(s.x,t-1),s.w=1===t||1===e?1:h?Math.round(s.w*i)||1:Math.min(s.w,t),n.push(s)})),r=[]}n=i.sort(n,-1),this._inColumnResize=!0,this.nodes=[],n.forEach((e=>{this.addNode(e,!1),delete e._orig}))}return this.nodes.forEach((e=>delete e._orig)),this.batchUpdate(!1,!o),delete this._inColumnResize,this}cacheLayout(e,t,i=!1){const o=[];return e.forEach(((e,t)=>{if(void 0===e._id){const t=e.id?this.nodes.find((t=>t.id===e.id)):void 0;e._id=t?._id??s._idSeq++}o[t]={x:e.x,y:e.y,w:e.w,_id:e._id}})),this._layouts=i?[]:this._layouts||[],this._layouts[t]=o,this}cacheOneLayout(e,t){e._id=e._id??s._idSeq++;const i={x:e.x,y:e.y,w:e.w,_id:e._id};(e.autoPosition||void 0===e.x)&&(delete i.x,delete i.y,e.autoPosition&&(i.autoPosition=!0)),this._layouts=this._layouts||[],this._layouts[t]=this._layouts[t]||[];const o=this.findCacheLayout(e,t);return-1===o?this._layouts[t].push(i):this._layouts[t][o]=i,this}findCacheLayout(e,t){return this._layouts?.[t]?.findIndex((t=>t._id===e._id))??-1}removeNodeFromLayoutCache(e){if(this._layouts)for(let t=0;t<this._layouts.length;t++){const i=this.findCacheLayout(e,t);-1!==i&&this._layouts[t].splice(i,1)}}cleanupNode(e){for(const t in e)"_"===t[0]&&"_id"!==t&&delete e[t];return this}}s._idSeq=0;const o={alwaysShowResizeHandle:"mobile",animate:!0,auto:!0,cellHeight:"auto",cellHeightThrottle:100,cellHeightUnit:"px",column:12,draggable:{handle:".grid-stack-item-content",appendTo:"body",scroll:!0},handle:".grid-stack-item-content",itemClass:"grid-stack-item",margin:10,marginUnit:"px",maxRow:0,minRow:0,placeholderClass:"grid-stack-placeholder",placeholderText:"",removableOptions:{accept:"grid-stack-item",decline:"grid-stack-non-removable"},resizable:{handles:"se"},rtl:"auto"};class n{}const r="undefined"!=typeof window&&"undefined"!=typeof document&&("ontouchstart"in document||"ontouchstart"in window||window.DocumentTouch&&document instanceof window.DocumentTouch||navigator.maxTouchPoints>0||navigator.msMaxTouchPoints>0);class a{}function h(e,t){e.touches.length>1||(e.cancelable&&e.preventDefault(),i.simulateMouseEvent(e.changedTouches[0],t))}function l(e,t){e.cancelable&&e.preventDefault(),i.simulateMouseEvent(e,t)}function d(e){a.touchHandled||(a.touchHandled=!0,h(e,"mousedown"))}function c(e){a.touchHandled&&h(e,"mousemove")}function g(e){if(!a.touchHandled)return;a.pointerLeaveTimeout&&(window.clearTimeout(a.pointerLeaveTimeout),delete a.pointerLeaveTimeout);const t=!!n.dragElement;h(e,"mouseup"),t||h(e,"click"),a.touchHandled=!1}function u(e){"mouse"!==e.pointerType&&e.target.releasePointerCapture(e.pointerId)}function p(e){n.dragElement&&"mouse"!==e.pointerType&&l(e,"mouseenter")}function m(e){n.dragElement&&"mouse"!==e.pointerType&&(a.pointerLeaveTimeout=window.setTimeout((()=>{delete a.pointerLeaveTimeout,l(e,"mouseleave")}),10))}class f{constructor(e,t,i){this.host=e,this.dir=t,this.option=i,this.moving=!1,this._mouseDown=this._mouseDown.bind(this),this._mouseMove=this._mouseMove.bind(this),this._mouseUp=this._mouseUp.bind(this),this._keyEvent=this._keyEvent.bind(this),this._init()}_init(){const e=this.el=document.createElement("div");return e.classList.add("ui-resizable-handle"),e.classList.add(`${f.prefix}${this.dir}`),e.style.zIndex="100",e.style.userSelect="none",this.host.appendChild(this.el),this.el.addEventListener("mousedown",this._mouseDown),r&&(this.el.addEventListener("touchstart",d),this.el.addEventListener("pointerdown",u)),this}destroy(){return this.moving&&this._mouseUp(this.mouseDownEvent),this.el.removeEventListener("mousedown",this._mouseDown),r&&(this.el.removeEventListener("touchstart",d),this.el.removeEventListener("pointerdown",u)),this.host.removeChild(this.el),delete this.el,delete this.host,this}_mouseDown(e){this.mouseDownEvent=e,document.addEventListener("mousemove",this._mouseMove,{capture:!0,passive:!0}),document.addEventListener("mouseup",this._mouseUp,!0),r&&(this.el.addEventListener("touchmove",c),this.el.addEventListener("touchend",g)),e.stopPropagation(),e.preventDefault()}_mouseMove(e){const t=this.mouseDownEvent;this.moving?this._triggerEvent("move",e):Math.abs(e.x-t.x)+Math.abs(e.y-t.y)>2&&(this.moving=!0,this._triggerEvent("start",this.mouseDownEvent),this._triggerEvent("move",e),document.addEventListener("keydown",this._keyEvent)),e.stopPropagation()}_mouseUp(e){this.moving&&(this._triggerEvent("stop",e),document.removeEventListener("keydown",this._keyEvent)),document.removeEventListener("mousemove",this._mouseMove,!0),document.removeEventListener("mouseup",this._mouseUp,!0),r&&(this.el.removeEventListener("touchmove",c),this.el.removeEventListener("touchend",g)),delete this.moving,delete this.mouseDownEvent,e.stopPropagation(),e.preventDefault()}_keyEvent(e){"Escape"===e.key&&(this.host.gridstackNode?.grid?.engine.restoreInitial(),this._mouseUp(this.mouseDownEvent))}_triggerEvent(e,t){return this.option[e]&&this.option[e](t),this}}f.prefix="ui-resizable-";class v{constructor(){this._eventRegister={}}get disabled(){return this._disabled}on(e,t){this._eventRegister[e]=t}off(e){delete this._eventRegister[e]}enable(){this._disabled=!1}disable(){this._disabled=!0}destroy(){delete this._eventRegister}triggerEvent(e,t){if(!this.disabled&&this._eventRegister&&this._eventRegister[e])return this._eventRegister[e](t)}}class _ extends v{constructor(e,t={}){super(),this.el=e,this.option=t,this.rectScale={x:1,y:1},this._ui=()=>{const e=this.el.parentElement.getBoundingClientRect(),t={width:this.originalRect.width,height:this.originalRect.height+this.scrolled,left:this.originalRect.left,top:this.originalRect.top-this.scrolled},i=this.temporalRect||t;return{position:{left:(i.left-e.left)*this.rectScale.x,top:(i.top-e.top)*this.rectScale.y},size:{width:i.width*this.rectScale.x,height:i.height*this.rectScale.y}}},this._mouseOver=this._mouseOver.bind(this),this._mouseOut=this._mouseOut.bind(this),this.enable(),this._setupAutoHide(this.option.autoHide),this._setupHandlers()}on(e,t){super.on(e,t)}off(e){super.off(e)}enable(){super.enable(),this.el.classList.remove("ui-resizable-disabled"),this._setupAutoHide(this.option.autoHide)}disable(){super.disable(),this.el.classList.add("ui-resizable-disabled"),this._setupAutoHide(!1)}destroy(){this._removeHandlers(),this._setupAutoHide(!1),delete this.el,super.destroy()}updateOption(e){const t=e.handles&&e.handles!==this.option.handles,i=e.autoHide&&e.autoHide!==this.option.autoHide;return Object.keys(e).forEach((t=>this.option[t]=e[t])),t&&(this._removeHandlers(),this._setupHandlers()),i&&this._setupAutoHide(this.option.autoHide),this}_setupAutoHide(e){return e?(this.el.classList.add("ui-resizable-autohide"),this.el.addEventListener("mouseover",this._mouseOver),this.el.addEventListener("mouseout",this._mouseOut)):(this.el.classList.remove("ui-resizable-autohide"),this.el.removeEventListener("mouseover",this._mouseOver),this.el.removeEventListener("mouseout",this._mouseOut),n.overResizeElement===this&&delete n.overResizeElement),this}_mouseOver(e){n.overResizeElement||n.dragElement||(n.overResizeElement=this,this.el.classList.remove("ui-resizable-autohide"))}_mouseOut(e){n.overResizeElement===this&&(delete n.overResizeElement,this.el.classList.add("ui-resizable-autohide"))}_setupHandlers(){return this.handlers=this.option.handles.split(",").map((e=>e.trim())).map((e=>new f(this.el,e,{start:e=>{this._resizeStart(e)},stop:e=>{this._resizeStop(e)},move:t=>{this._resizing(t,e)}}))),this}_resizeStart(e){this.sizeToContent=i.shouldSizeToContent(this.el.gridstackNode,!0),this.originalRect=this.el.getBoundingClientRect(),this.scrollEl=i.getScrollElement(this.el),this.scrollY=this.scrollEl.scrollTop,this.scrolled=0,this.startEvent=e,this._setupHelper(),this._applyChange();const t=i.initEvent(e,{type:"resizestart",target:this.el});return this.option.start&&this.option.start(t,this._ui()),this.el.classList.add("ui-resizable-resizing"),this.triggerEvent("resizestart",t),this}_resizing(e,t){this.scrolled=this.scrollEl.scrollTop-this.scrollY,this.temporalRect=this._getChange(e,t),this._applyChange();const s=i.initEvent(e,{type:"resize",target:this.el});return this.option.resize&&this.option.resize(s,this._ui()),this.triggerEvent("resize",s),this}_resizeStop(e){const t=i.initEvent(e,{type:"resizestop",target:this.el});return this._cleanHelper(),this.option.stop&&this.option.stop(t),this.el.classList.remove("ui-resizable-resizing"),this.triggerEvent("resizestop",t),delete this.startEvent,delete this.originalRect,delete this.temporalRect,delete this.scrollY,delete this.scrolled,this}_setupHelper(){this.elOriginStyleVal=_._originStyleProp.map((e=>this.el.style[e])),this.parentOriginStylePosition=this.el.parentElement.style.position;const e=this.el.parentElement,t=i.getValuesFromTransformedElement(e);return this.rectScale={x:t.xScale,y:t.yScale},getComputedStyle(this.el.parentElement).position.match(/static/)&&(this.el.parentElement.style.position="relative"),this.el.style.position="absolute",this.el.style.opacity="0.8",this}_cleanHelper(){return _._originStyleProp.forEach(((e,t)=>{this.el.style[e]=this.elOriginStyleVal[t]||null})),this.el.parentElement.style.position=this.parentOriginStylePosition||null,this}_getChange(e,t){const i=this.startEvent,s={width:this.originalRect.width,height:this.originalRect.height+this.scrolled,left:this.originalRect.left,top:this.originalRect.top-this.scrolled},o=e.clientX-i.clientX,n=this.sizeToContent?0:e.clientY-i.clientY;let r,a;t.indexOf("e")>-1?s.width+=o:t.indexOf("w")>-1&&(s.width-=o,s.left+=o,r=!0),t.indexOf("s")>-1?s.height+=n:t.indexOf("n")>-1&&(s.height-=n,s.top+=n,a=!0);const h=this._constrainSize(s.width,s.height,r,a);return Math.round(s.width)!==Math.round(h.width)&&(t.indexOf("w")>-1&&(s.left+=s.width-h.width),s.width=h.width),Math.round(s.height)!==Math.round(h.height)&&(t.indexOf("n")>-1&&(s.top+=s.height-h.height),s.height=h.height),s}_constrainSize(e,t,i,s){const o=this.option,n=(i?o.maxWidthMoveLeft:o.maxWidth)||Number.MAX_SAFE_INTEGER,r=o.minWidth/this.rectScale.x||e,a=(s?o.maxHeightMoveUp:o.maxHeight)||Number.MAX_SAFE_INTEGER,h=o.minHeight/this.rectScale.y||t;return{width:Math.min(n,Math.max(r,e)),height:Math.min(a,Math.max(h,t))}}_applyChange(){let e={left:0,top:0,width:0,height:0};if("absolute"===this.el.style.position){const t=this.el.parentElement,{left:i,top:s}=t.getBoundingClientRect();e={left:i,top:s,width:0,height:0}}return this.temporalRect?(Object.keys(this.temporalRect).forEach((t=>{const i=this.temporalRect[t],s="width"===t||"left"===t?this.rectScale.x:"height"===t||"top"===t?this.rectScale.y:1;this.el.style[t]=(i-e[t])*s+"px"})),this):this}_removeHandlers(){return this.handlers.forEach((e=>e.destroy())),delete this.handlers,this}}_._originStyleProp=["width","height","position","left","top","opacity","zIndex"];class y extends v{constructor(e,t={}){super(),this.el=e,this.option=t,this.dragTransform={xScale:1,yScale:1,xOffset:0,yOffset:0};const i=t?.handle?.substring(1),s=e.gridstackNode;this.dragEls=!i||e.classList.contains(i)?[e]:s?.subGrid?[e.querySelector(t.handle)||e]:Array.from(e.querySelectorAll(t.handle)),0===this.dragEls.length&&(this.dragEls=[e]),this._mouseDown=this._mouseDown.bind(this),this._mouseMove=this._mouseMove.bind(this),this._mouseUp=this._mouseUp.bind(this),this._keyEvent=this._keyEvent.bind(this),this.enable()}on(e,t){super.on(e,t)}off(e){super.off(e)}enable(){!1!==this.disabled&&(super.enable(),this.dragEls.forEach((e=>{e.addEventListener("mousedown",this._mouseDown),r&&(e.addEventListener("touchstart",d),e.addEventListener("pointerdown",u))})),this.el.classList.remove("ui-draggable-disabled"))}disable(e=!1){!0!==this.disabled&&(super.disable(),this.dragEls.forEach((e=>{e.removeEventListener("mousedown",this._mouseDown),r&&(e.removeEventListener("touchstart",d),e.removeEventListener("pointerdown",u))})),e||this.el.classList.add("ui-draggable-disabled"))}destroy(){this.dragTimeout&&window.clearTimeout(this.dragTimeout),delete this.dragTimeout,this.mouseDownEvent&&this._mouseUp(this.mouseDownEvent),this.disable(!0),delete this.el,delete this.helper,delete this.option,super.destroy()}updateOption(e){return Object.keys(e).forEach((t=>this.option[t]=e[t])),this}_mouseDown(e){if(!n.mouseHandled)return 0!==e.button||!this.dragEls.find((t=>t===e.target))&&e.target.closest('input,textarea,button,select,option,[contenteditable="true"],.ui-resizable-handle')||this.option.cancel&&e.target.closest(this.option.cancel)||(this.mouseDownEvent=e,delete this.dragging,delete n.dragElement,delete n.dropElement,document.addEventListener("mousemove",this._mouseMove,{capture:!0,passive:!0}),document.addEventListener("mouseup",this._mouseUp,!0),r&&(e.currentTarget.addEventListener("touchmove",c),e.currentTarget.addEventListener("touchend",g)),e.preventDefault(),document.activeElement&&document.activeElement.blur(),n.mouseHandled=!0),!0}_callDrag(e){if(!this.dragging)return;const t=i.initEvent(e,{target:this.el,type:"drag"});this.option.drag&&this.option.drag(t,this.ui()),this.triggerEvent("drag",t)}_mouseMove(e){const t=this.mouseDownEvent;if(this.lastDrag=e,this.dragging)if(this._dragFollow(e),n.pauseDrag){const t=Number.isInteger(n.pauseDrag)?n.pauseDrag:100;this.dragTimeout&&window.clearTimeout(this.dragTimeout),this.dragTimeout=window.setTimeout((()=>this._callDrag(e)),t)}else this._callDrag(e);else if(Math.abs(e.x-t.x)+Math.abs(e.y-t.y)>3){this.dragging=!0,n.dragElement=this;const t=this.el.gridstackNode?.grid;t?n.dropElement=t.el.ddElement.ddDroppable:delete n.dropElement,this.helper=this._createHelper(),this._setupHelperContainmentStyle(),this.dragTransform=i.getValuesFromTransformedElement(this.helperContainment),this.dragOffset=this._getDragOffset(e,this.el,this.helperContainment),this._setupHelperStyle(e);const s=i.initEvent(e,{target:this.el,type:"dragstart"});this.option.start&&this.option.start(s,this.ui()),this.triggerEvent("dragstart",s),document.addEventListener("keydown",this._keyEvent)}return!0}_mouseUp(e){if(document.removeEventListener("mousemove",this._mouseMove,!0),document.removeEventListener("mouseup",this._mouseUp,!0),r&&e.currentTarget&&(e.currentTarget.removeEventListener("touchmove",c,!0),e.currentTarget.removeEventListener("touchend",g,!0)),this.dragging){delete this.dragging,delete this.el.gridstackNode?._origRotate,document.removeEventListener("keydown",this._keyEvent),n.dropElement?.el===this.el.parentElement&&delete n.dropElement,this.helperContainment.style.position=this.parentOriginStylePosition||null,this.helper!==this.el&&this.helper.remove(),this._removeHelperStyle();const t=i.initEvent(e,{target:this.el,type:"dragstop"});this.option.stop&&this.option.stop(t),this.triggerEvent("dragstop",t),n.dropElement&&n.dropElement.drop(e)}delete this.helper,delete this.mouseDownEvent,delete n.dragElement,delete n.dropElement,delete n.mouseHandled,e.preventDefault()}_keyEvent(e){const t=this.el.gridstackNode,s=t?.grid||n.dropElement?.el?.gridstack;if("Escape"===e.key)t&&t._origRotate&&(t._orig=t._origRotate,delete t._origRotate),s?.cancelDrag(),this._mouseUp(this.mouseDownEvent);else if(t&&s&&("r"===e.key||"R"===e.key)){if(!i.canBeRotated(t))return;t._origRotate=t._origRotate||{...t._orig},delete t._moving,s.setAnimation(!1).rotate(t.el,{top:-this.dragOffset.offsetTop,left:-this.dragOffset.offsetLeft}).setAnimation(),t._moving=!0,this.dragOffset=this._getDragOffset(this.lastDrag,t.el,this.helperContainment),this.helper.style.width=this.dragOffset.width+"px",this.helper.style.height=this.dragOffset.height+"px",i.swap(t._orig,"w","h"),delete t._rect,this._mouseMove(this.lastDrag)}}_createHelper(){let e=this.el;return"function"==typeof this.option.helper?e=this.option.helper(this.el):"clone"===this.option.helper&&(e=i.cloneNode(this.el)),e.parentElement||i.appendTo(e,"parent"===this.option.appendTo?this.el.parentElement:this.option.appendTo),this.dragElementOriginStyle=y.originStyleProp.map((e=>this.el.style[e])),e}_setupHelperStyle(e){this.helper.classList.add("ui-draggable-dragging");const t=this.helper.style;return t.pointerEvents="none",t.width=this.dragOffset.width+"px",t.height=this.dragOffset.height+"px",t.willChange="left, top",t.position="fixed",this._dragFollow(e),t.transition="none",setTimeout((()=>{this.helper&&(t.transition=null)}),0),this}_removeHelperStyle(){this.helper.classList.remove("ui-draggable-dragging");const e=this.helper?.gridstackNode;if(!e?._isAboutToRemove&&this.dragElementOriginStyle){const e=this.helper,t=this.dragElementOriginStyle.transition||null;e.style.transition=this.dragElementOriginStyle.transition="none",y.originStyleProp.forEach((t=>e.style[t]=this.dragElementOriginStyle[t]||null)),setTimeout((()=>e.style.transition=t),50)}return delete this.dragElementOriginStyle,this}_dragFollow(e){const t=this.helper.style,i=this.dragOffset;t.left=(e.clientX+i.offsetLeft-0)*this.dragTransform.xScale+"px",t.top=(e.clientY+i.offsetTop-0)*this.dragTransform.yScale+"px"}_setupHelperContainmentStyle(){return this.helperContainment=this.helper.parentElement,"fixed"!==this.helper.style.position&&(this.parentOriginStylePosition=this.helperContainment.style.position,getComputedStyle(this.helperContainment).position.match(/static/)&&(this.helperContainment.style.position="relative")),this}_getDragOffset(e,t,i){let s=0,o=0;i&&(s=this.dragTransform.xOffset,o=this.dragTransform.yOffset);const n=t.getBoundingClientRect();return{left:n.left,top:n.top,offsetLeft:-e.clientX+n.left-s,offsetTop:-e.clientY+n.top-o,width:n.width*this.dragTransform.xScale,height:n.height*this.dragTransform.yScale}}ui(){const e=this.el.parentElement.getBoundingClientRect(),t=this.helper.getBoundingClientRect();return{position:{top:(t.top-e.top)*this.dragTransform.yScale,left:(t.left-e.left)*this.dragTransform.xScale}}}}y.originStyleProp=["width","height","transform","transform-origin","transition","pointerEvents","position","left","top","minWidth","willChange"];class b extends v{constructor(e,t={}){super(),this.el=e,this.option=t,this._mouseEnter=this._mouseEnter.bind(this),this._mouseLeave=this._mouseLeave.bind(this),this.enable(),this._setupAccept()}on(e,t){super.on(e,t)}off(e){super.off(e)}enable(){!1!==this.disabled&&(super.enable(),this.el.classList.add("ui-droppable"),this.el.classList.remove("ui-droppable-disabled"),this.el.addEventListener("mouseenter",this._mouseEnter),this.el.addEventListener("mouseleave",this._mouseLeave),r&&(this.el.addEventListener("pointerenter",p),this.el.addEventListener("pointerleave",m)))}disable(e=!1){!0!==this.disabled&&(super.disable(),this.el.classList.remove("ui-droppable"),e||this.el.classList.add("ui-droppable-disabled"),this.el.removeEventListener("mouseenter",this._mouseEnter),this.el.removeEventListener("mouseleave",this._mouseLeave),r&&(this.el.removeEventListener("pointerenter",p),this.el.removeEventListener("pointerleave",m)))}destroy(){this.disable(!0),this.el.classList.remove("ui-droppable"),this.el.classList.remove("ui-droppable-disabled"),super.destroy()}updateOption(e){return Object.keys(e).forEach((t=>this.option[t]=e[t])),this._setupAccept(),this}_mouseEnter(e){if(!n.dragElement)return;if(!this._canDrop(n.dragElement.el))return;e.preventDefault(),e.stopPropagation(),n.dropElement&&n.dropElement!==this&&n.dropElement._mouseLeave(e,!0),n.dropElement=this;const t=i.initEvent(e,{target:this.el,type:"dropover"});this.option.over&&this.option.over(t,this._ui(n.dragElement)),this.triggerEvent("dropover",t),this.el.classList.add("ui-droppable-over")}_mouseLeave(e,t=!1){if(!n.dragElement||n.dropElement!==this)return;e.preventDefault(),e.stopPropagation();const s=i.initEvent(e,{target:this.el,type:"dropout"});if(this.option.out&&this.option.out(s,this._ui(n.dragElement)),this.triggerEvent("dropout",s),n.dropElement===this&&(delete n.dropElement,!t)){let t,i=this.el.parentElement;for(;!t&&i;)t=i.ddElement?.ddDroppable,i=i.parentElement;t&&t._mouseEnter(e)}}drop(e){e.preventDefault();const t=i.initEvent(e,{target:this.el,type:"drop"});this.option.drop&&this.option.drop(t,this._ui(n.dragElement)),this.triggerEvent("drop",t)}_canDrop(e){return e&&(!this.accept||this.accept(e))}_setupAccept(){return this.option.accept?("string"==typeof this.option.accept?this.accept=e=>e.classList.contains(this.option.accept)||e.matches(this.option.accept):this.accept=this.option.accept,this):this}_ui(e){return{draggable:e.el,...e.ui()}}}class w{static init(e){return e.ddElement||(e.ddElement=new w(e)),e.ddElement}constructor(e){this.el=e}on(e,t){return this.ddDraggable&&["drag","dragstart","dragstop"].indexOf(e)>-1?this.ddDraggable.on(e,t):this.ddDroppable&&["drop","dropover","dropout"].indexOf(e)>-1?this.ddDroppable.on(e,t):this.ddResizable&&["resizestart","resize","resizestop"].indexOf(e)>-1&&this.ddResizable.on(e,t),this}off(e){return this.ddDraggable&&["drag","dragstart","dragstop"].indexOf(e)>-1?this.ddDraggable.off(e):this.ddDroppable&&["drop","dropover","dropout"].indexOf(e)>-1?this.ddDroppable.off(e):this.ddResizable&&["resizestart","resize","resizestop"].indexOf(e)>-1&&this.ddResizable.off(e),this}setupDraggable(e){return this.ddDraggable?this.ddDraggable.updateOption(e):this.ddDraggable=new y(this.el,e),this}cleanDraggable(){return this.ddDraggable&&(this.ddDraggable.destroy(),delete this.ddDraggable),this}setupResizable(e){return this.ddResizable?this.ddResizable.updateOption(e):this.ddResizable=new _(this.el,e),this}cleanResizable(){return this.ddResizable&&(this.ddResizable.destroy(),delete this.ddResizable),this}setupDroppable(e){return this.ddDroppable?this.ddDroppable.updateOption(e):this.ddDroppable=new b(this.el,e),this}cleanDroppable(){return this.ddDroppable&&(this.ddDroppable.destroy(),delete this.ddDroppable),this}}const E=new class{resizable(e,t,i,s){return this._getDDElements(e,t).forEach((e=>{if("disable"===t||"enable"===t)e.ddResizable&&e.ddResizable[t]();else if("destroy"===t)e.ddResizable&&e.cleanResizable();else if("option"===t)e.setupResizable({[i]:s});else{const i=e.el.gridstackNode.grid;let s=e.el.getAttribute("gs-resize-handles")||i.opts.resizable.handles||"e,s,se";"all"===s&&(s="n,e,s,w,se,sw,ne,nw");const o=!i.opts.alwaysShowResizeHandle;e.setupResizable({...i.opts.resizable,handles:s,autoHide:o,start:t.start,stop:t.stop,resize:t.resize})}})),this}draggable(e,t,i,s){return this._getDDElements(e,t).forEach((e=>{if("disable"===t||"enable"===t)e.ddDraggable&&e.ddDraggable[t]();else if("destroy"===t)e.ddDraggable&&e.cleanDraggable();else if("option"===t)e.setupDraggable({[i]:s});else{const i=e.el.gridstackNode.grid;e.setupDraggable({...i.opts.draggable,start:t.start,stop:t.stop,drag:t.drag})}})),this}dragIn(e,t){return this._getDDElements(e).forEach((e=>e.setupDraggable(t))),this}droppable(e,t,i,s){return"function"!=typeof t.accept||t._accept||(t._accept=t.accept,t.accept=e=>t._accept(e)),this._getDDElements(e,t).forEach((e=>{"disable"===t||"enable"===t?e.ddDroppable&&e.ddDroppable[t]():"destroy"===t?e.ddDroppable&&e.cleanDroppable():"option"===t?e.setupDroppable({[i]:s}):e.setupDroppable(t)})),this}isDroppable(e){return!(!e?.ddElement?.ddDroppable||e.ddElement.ddDroppable.disabled)}isDraggable(e){return!(!e?.ddElement?.ddDraggable||e.ddElement.ddDraggable.disabled)}isResizable(e){return!(!e?.ddElement?.ddResizable||e.ddElement.ddResizable.disabled)}on(e,t,i){return this._getDDElements(e).forEach((e=>e.on(t,(e=>{i(e,n.dragElement?n.dragElement.el:e.target,n.dragElement?n.dragElement.helper:null)})))),this}off(e,t){return this._getDDElements(e).forEach((e=>e.off(t))),this}_getDDElements(e,t){const s=e.gridstack||"destroy"!==t&&"disable"!==t,o=i.getElements(e);return o.length?o.map((e=>e.ddElement||(s?w.init(e):null))).filter((e=>e)):[]}};class x{static init(e={},t=".grid-stack"){if("undefined"==typeof document)return null;const s=x.getGridElement(t);return s?(s.gridstack||(s.gridstack=new x(s,i.cloneDeep(e))),s.gridstack):("string"==typeof t?console.error('GridStack.initAll() no grid was found with selector "'+t+'" - element missing or wrong selector ?\nNote: ".grid-stack" is required for proper CSS styling and drag/drop, and is the default selector.'):console.error("GridStack.init() no grid element was passed."),null)}static initAll(e={},t=".grid-stack"){const s=[];return"undefined"==typeof document||(x.getGridElements(t).forEach((t=>{t.gridstack||(t.gridstack=new x(t,i.cloneDeep(e))),s.push(t.gridstack)})),0===s.length&&console.error('GridStack.initAll() no grid was found with selector "'+t+'" - element missing or wrong selector ?\nNote: ".grid-stack" is required for proper CSS styling and drag/drop, and is the default selector.')),s}static addGrid(e,t={}){if(!e)return null;let s=e;if(s.gridstack){const e=s.gridstack;return t&&(e.opts={...e.opts,...t}),void 0!==t.children&&e.load(t.children),e}return e.classList.contains("grid-stack")&&!x.addRemoveCB||(s=x.addRemoveCB?x.addRemoveCB(e,t,!0,!0):i.createDiv(["grid-stack",t.class],e)),x.init(t,s)}static registerEngine(e){x.engineClass=e}get placeholder(){if(!this._placeholder){this._placeholder=i.createDiv([this.opts.placeholderClass,o.itemClass,this.opts.itemClass]);const e=i.createDiv(["placeholder-content"],this._placeholder);this.opts.placeholderText&&(e.textContent=this.opts.placeholderText)}return this._placeholder}constructor(e,t={}){this.el=e,this.opts=t,this.animationDelay=310,this._gsEventHandler={},this._extraDragRow=0,this.dragTransform={xScale:1,yScale:1,xOffset:0,yOffset:0},e.gridstack=this,this.opts=t=t||{},e.classList.contains("grid-stack")||this.el.classList.add("grid-stack"),t.row&&(t.minRow=t.maxRow=t.row,delete t.row);const a=i.toNumber(e.getAttribute("gs-row"));"auto"===t.column&&delete t.column,void 0!==t.alwaysShowResizeHandle&&(t._alwaysShowResizeHandle=t.alwaysShowResizeHandle);const h=t.columnOpts;if(h){const e=h.breakpoints;h.columnWidth||e?.length?(h.columnMax=h.columnMax||12,e?.length>1&&e.sort(((e,t)=>(t.w||0)-(e.w||0)))):delete t.columnOpts}const l={...i.cloneDeep(o),column:i.toNumber(e.getAttribute("gs-column"))||o.column,minRow:a||i.toNumber(e.getAttribute("gs-min-row"))||o.minRow,maxRow:a||i.toNumber(e.getAttribute("gs-max-row"))||o.maxRow,staticGrid:i.toBool(e.getAttribute("gs-static"))||o.staticGrid,sizeToContent:i.toBool(e.getAttribute("gs-size-to-content"))||void 0,draggable:{handle:(t.handleClass?"."+t.handleClass:t.handle?t.handle:"")||o.draggable.handle},removableOptions:{accept:t.itemClass||o.removableOptions.accept,decline:o.removableOptions.decline}};e.getAttribute("gs-animate")&&(l.animate=i.toBool(e.getAttribute("gs-animate"))),t=i.defaults(t,l),this._initMargin(),this.checkDynamicColumn(),this._updateColumnVar(t),"auto"===t.rtl&&(t.rtl="rtl"===e.style.direction),t.rtl&&this.el.classList.add("grid-stack-rtl");const d=this.el.closest("."+o.itemClass),c=d?.gridstackNode;if(c&&(c.subGrid=this,this.parentGridNode=c,this.el.classList.add("grid-stack-nested"),c.el.classList.add("grid-stack-sub-grid")),this._isAutoCellHeight="auto"===t.cellHeight,this._isAutoCellHeight||"initial"===t.cellHeight)this.cellHeight(void 0);else{"number"==typeof t.cellHeight&&t.cellHeightUnit&&t.cellHeightUnit!==o.cellHeightUnit&&(t.cellHeight=t.cellHeight+t.cellHeightUnit,delete t.cellHeightUnit);const e=t.cellHeight;delete t.cellHeight,this.cellHeight(e)}"mobile"===t.alwaysShowResizeHandle&&(t.alwaysShowResizeHandle=r),this._setStaticClass();const g=t.engineClass||x.engineClass||s;if(this.engine=new g({column:this.getColumn(),float:t.float,maxRow:t.maxRow,onChange:e=>{e.forEach((e=>{const t=e.el;t&&(e._removeDOM?(t&&t.remove(),delete e._removeDOM):this._writePosAttr(t,e))})),this._updateContainerHeight()}}),t.auto&&(this.batchUpdate(),this.engine._loading=!0,this.getGridItems().forEach((e=>this._prepareElement(e))),delete this.engine._loading,this.batchUpdate(!1)),t.children){const e=t.children;delete t.children,e.length&&this.load(e)}this.setAnimation(),t.subGridDynamic&&!n.pauseDrag&&(n.pauseDrag=!0),void 0!==t.draggable?.pause&&(n.pauseDrag=t.draggable.pause),this._setupRemoveDrop(),this._setupAcceptWidget(),this._updateResizeEvent()}_updateColumnVar(e=this.opts){this.el.classList.add("gs-"+e.column),"number"==typeof e.column&&this.el.style.setProperty("--gs-column-width",100/e.column+"%")}addWidget(e){if("string"==typeof e)return void console.error("V11: GridStack.addWidget() does not support string anymore. see #2736");if(e.ELEMENT_NODE)return console.error("V11: GridStack.addWidget() does not support HTMLElement anymore. use makeWidget()"),this.makeWidget(e);let t,s=e;if(s.grid=this,t=s?.el?s.el:x.addRemoveCB?x.addRemoveCB(this.el,e,!0,!1):this.createWidgetDivs(s),!t)return;if(s=t.gridstackNode,s&&t.parentElement===this.el&&this.engine.nodes.find((e=>e._id===s._id)))return t;const o=this._readAttr(t);return i.defaults(e,o),this.engine.prepareNode(e),this.el.appendChild(t),this.makeWidget(t,e),t}createWidgetDivs(e){const t=i.createDiv(["grid-stack-item",this.opts.itemClass]),s=i.createDiv(["grid-stack-item-content"],t);return i.lazyLoad(e)?e.visibleObservable||(e.visibleObservable=new IntersectionObserver((([t])=>{t.isIntersecting&&(e.visibleObservable?.disconnect(),delete e.visibleObservable,x.renderCB(s,e),e.grid?.prepareDragDrop(e.el))})),window.setTimeout((()=>e.visibleObservable?.observe(t)))):x.renderCB(s,e),t}makeSubGrid(e,t,s,o=!0){let n,r=e.gridstackNode;if(r||(r=this.makeWidget(e).gridstackNode),r.subGrid?.el)return r.subGrid;let a,h=this;for(;h&&!n;)n=h.opts?.subGridOpts,h=h.parentGridNode?.grid;t=i.cloneDeep({...this.opts,id:void 0,children:void 0,column:"auto",columnOpts:void 0,layout:"list",subGridOpts:void 0,...n||{},...t||r.subGridOpts||{}}),r.subGridOpts=t,"auto"===t.column&&(a=!0,t.column=Math.max(r.w||1,s?.w||1),delete t.columnOpts);let l,d,c=r.el.querySelector(".grid-stack-item-content");if(o&&(this._removeDD(r.el),d={...r,x:0,y:0},i.removeInternalForSave(d),delete d.subGridOpts,r.content&&(d.content=r.content,delete r.content),x.addRemoveCB?l=x.addRemoveCB(this.el,d,!0,!1):(l=i.createDiv(["grid-stack-item"]),l.appendChild(c),c=i.createDiv(["grid-stack-item-content"],r.el)),this.prepareDragDrop(r.el)),s){const e=a?t.column:r.w,i=r.h+s.h,o=r.el.style;o.transition="none",this.update(r.el,{w:e,h:i}),setTimeout((()=>o.transition=null))}const g=r.subGrid=x.addGrid(c,t);return s?._moving&&(g._isTemp=!0),a&&(g._autoColumn=!0),o&&g.makeWidget(l,d),s&&(s._moving?window.setTimeout((()=>i.simulateMouseEvent(s._event,"mouseenter",g.el)),0):g.makeWidget(r.el,r)),this.resizeToContentCheck(!1,r),g}removeAsSubGrid(e){const t=this.parentGridNode?.grid;t&&(t.batchUpdate(),t.removeWidget(this.parentGridNode.el,!0,!0),this.engine.nodes.forEach((e=>{e.x+=this.parentGridNode.x,e.y+=this.parentGridNode.y,t.makeWidget(e.el,e)})),t.batchUpdate(!1),this.parentGridNode&&delete this.parentGridNode.subGrid,delete this.parentGridNode,e&&window.setTimeout((()=>i.simulateMouseEvent(e._event,"mouseenter",t.el)),0))}save(e=!0,t=!1,s=x.saveCB){const n=this.engine.save(e,s);if(n.forEach((i=>{if(e&&i.el&&!i.subGrid&&!s){const e=i.el.querySelector(".grid-stack-item-content");i.content=e?.innerHTML,i.content||delete i.content}else if(e||s||delete i.content,i.subGrid?.el){const o=i.subGrid.save(e,t,s);i.subGridOpts=t?o:{children:o},delete i.subGrid}delete i.el})),t){const e=i.cloneDeep(this.opts);e.marginBottom===e.marginTop&&e.marginRight===e.marginLeft&&e.marginTop===e.marginRight&&(e.margin=e.marginTop,delete e.marginTop,delete e.marginRight,delete e.marginBottom,delete e.marginLeft),e.rtl===("rtl"===this.el.style.direction)&&(e.rtl="auto"),this._isAutoCellHeight&&(e.cellHeight="auto"),this._autoColumn&&(e.column="auto");const t=e._alwaysShowResizeHandle;return delete e._alwaysShowResizeHandle,void 0!==t?e.alwaysShowResizeHandle=t:delete e.alwaysShowResizeHandle,i.removeInternalAndSame(e,o),e.children=n,e}return n}load(e,t=x.addRemoveCB||!0){e=i.cloneDeep(e);const s=this.getColumn();e.forEach((e=>{e.w=e.w||1,e.h=e.h||1})),e=i.sort(e),this.engine.skipCacheUpdate=this._ignoreLayoutsNodeChange=!0;let o=0;e.forEach((e=>{o=Math.max(o,(e.x||0)+e.w)})),o>this.engine.defaultColumn&&(this.engine.defaultColumn=o),o>s&&(0===this.engine.nodes.length&&this.responseLayout?(this.engine.nodes=e,this.engine.columnChanged(o,s,this.responseLayout),e=this.engine.nodes,this.engine.nodes=[],delete this.responseLayout):this.engine.cacheLayout(e,o,!0));const n=x.addRemoveCB;"function"==typeof t&&(x.addRemoveCB=t);const r=[];this.batchUpdate();const a=!this.engine.nodes.length,h=a&&this.opts.animate;h&&this.setAnimation(!1),!a&&t&&[...this.engine.nodes].forEach((t=>{t.id&&(i.find(e,t.id)||(x.addRemoveCB&&x.addRemoveCB(this.el,t,!1,!1),r.push(t),this.removeWidget(t.el,!0,!1)))})),this.engine._loading=!0;const l=[];return this.engine.nodes=this.engine.nodes.filter((t=>!i.find(e,t.id)||(l.push(t),!1))),e.forEach((e=>{const s=i.find(l,e.id);if(s){if(i.shouldSizeToContent(s)&&(e.h=s.h),this.engine.nodeBoundFix(e),(e.autoPosition||void 0===e.x||void 0===e.y)&&(e.w=e.w||s.w,e.h=e.h||s.h,this.engine.findEmptyPosition(e)),this.engine.nodes.push(s),i.samePos(s,e)&&this.engine.nodes.length>1&&(this.moveNode(s,{...e,forceCollide:!0}),i.copyPos(e,s)),this.update(s.el,e),e.subGridOpts?.children){const t=s.el.querySelector(".grid-stack");t&&t.gridstack&&t.gridstack.load(e.subGridOpts.children)}}else t&&this.addWidget(e)})),delete this.engine._loading,this.engine.removedNodes=r,this.batchUpdate(!1),delete this._ignoreLayoutsNodeChange,delete this.engine.skipCacheUpdate,n?x.addRemoveCB=n:delete x.addRemoveCB,h&&this.setAnimation(!0,!0),this}batchUpdate(e=!0){return this.engine.batchUpdate(e),e||(this._updateContainerHeight(),this._triggerRemoveEvent(),this._triggerAddEvent(),this._triggerChangeEvent()),this}getCellHeight(e=!1){if(this.opts.cellHeight&&"auto"!==this.opts.cellHeight&&(!e||!this.opts.cellHeightUnit||"px"===this.opts.cellHeightUnit))return this.opts.cellHeight;if("rem"===this.opts.cellHeightUnit)return this.opts.cellHeight*parseFloat(getComputedStyle(document.documentElement).fontSize);if("em"===this.opts.cellHeightUnit)return this.opts.cellHeight*parseFloat(getComputedStyle(this.el).fontSize);if("cm"===this.opts.cellHeightUnit)return this.opts.cellHeight*(96/2.54);if("mm"===this.opts.cellHeightUnit)return this.opts.cellHeight*(96/2.54)/10;const t=this.el.querySelector("."+this.opts.itemClass);if(t){const e=i.toNumber(t.getAttribute("gs-h"))||1;return Math.round(t.offsetHeight/e)}const s=parseInt(this.el.getAttribute("gs-current-row"));return s?Math.round(this.el.getBoundingClientRect().height/s):this.opts.cellHeight}cellHeight(e){if(void 0!==e&&this._isAutoCellHeight!==("auto"===e)&&(this._isAutoCellHeight="auto"===e,this._updateResizeEvent()),"initial"!==e&&"auto"!==e||(e=void 0),void 0===e){const t=-this.opts.marginRight-this.opts.marginLeft+this.opts.marginTop+this.opts.marginBottom;e=this.cellWidth()+t}const t=i.parseHeight(e);return this.opts.cellHeightUnit===t.unit&&this.opts.cellHeight===t.h||(this.opts.cellHeightUnit=t.unit,this.opts.cellHeight=t.h,this.el.style.setProperty("--gs-cell-height",`${this.opts.cellHeight}${this.opts.cellHeightUnit}`),this._updateContainerHeight(),this.resizeToContentCheck()),this}cellWidth(){return this._widthOrContainer()/this.getColumn()}_widthOrContainer(e=!1){return e&&this.opts.columnOpts?.breakpointForWindow?window.innerWidth:this.el.clientWidth||this.el.parentElement.clientWidth||window.innerWidth}checkDynamicColumn(){const e=this.opts.columnOpts;if(!e||!e.columnWidth&&!e.breakpoints?.length)return!1;const t=this.getColumn();let i=t;const s=this._widthOrContainer(!0);if(e.columnWidth)i=Math.min(Math.round(s/e.columnWidth)||1,e.columnMax);else{i=e.columnMax;let o=0;for(;o<e.breakpoints.length&&s<=e.breakpoints[o].w;)i=e.breakpoints[o++].c||t}if(i!==t){const t=e.breakpoints?.find((e=>e.c===i));return this.column(i,t?.layout||e.layout),!0}return!1}compact(e="compact",t=!0){return this.engine.compact(e,t),this._triggerChangeEvent(),this}column(e,t="moveScale"){if(!e||e<1||this.opts.column===e)return this;const i=this.getColumn();return this.opts.column=e,this.engine?(this.engine.column=e,this.el.classList.remove("gs-"+i),this._updateColumnVar(),this.engine.columnChanged(i,e,t),this._isAutoCellHeight&&this.cellHeight(),this.resizeToContentCheck(!0),this._ignoreLayoutsNodeChange=!0,this._triggerChangeEvent(),delete this._ignoreLayoutsNodeChange,this):(this.responseLayout=t,this)}getColumn(){return this.opts.column}getGridItems(){return Array.from(this.el.children).filter((e=>e.matches("."+this.opts.itemClass)&&!e.matches("."+this.opts.placeholderClass)))}isIgnoreChangeCB(){return this._ignoreLayoutsNodeChange}destroy(e=!0){if(this.el)return this.offAll(),this._updateResizeEvent(!0),this.setStatic(!0,!1),this.setAnimation(!1),e?this.el.parentNode.removeChild(this.el):(this.removeAll(e),this.el.removeAttribute("gs-current-row")),this.parentGridNode&&delete this.parentGridNode.subGrid,delete this.parentGridNode,delete this.opts,delete this._placeholder?.gridstackNode,delete this._placeholder,delete this.engine,delete this.el.gridstack,delete this.el,this}float(e){return this.opts.float!==e&&(this.opts.float=this.engine.float=e,this._triggerChangeEvent()),this}getFloat(){return this.engine.float}getCellFromPixel(e,t=!1){const i=this.el.getBoundingClientRect();let s;s=t?{top:i.top+document.documentElement.scrollTop,left:i.left}:{top:this.el.offsetTop,left:this.el.offsetLeft};const o=e.left-s.left,n=e.top-s.top,r=i.width/this.getColumn(),a=i.height/parseInt(this.el.getAttribute("gs-current-row"));return{x:Math.floor(o/r),y:Math.floor(n/a)}}getRow(){return Math.max(this.engine.getRow(),this.opts.minRow||0)}isAreaEmpty(e,t,i,s){return this.engine.isAreaEmpty(e,t,i,s)}makeWidget(e,t){const i=x.getElement(e);if(!i||i.gridstackNode)return i;i.parentElement||this.el.appendChild(i),this._prepareElement(i,!0,t);const s=i.gridstackNode;let o;return this._updateContainerHeight(),s.subGridOpts&&this.makeSubGrid(i,s.subGridOpts,void 0,!1),1!==this.opts.column||this._ignoreLayoutsNodeChange||(o=this._ignoreLayoutsNodeChange=!0),this._triggerAddEvent(),this._triggerChangeEvent(),o&&delete this._ignoreLayoutsNodeChange,i}on(e,t){if(-1!==e.indexOf(" "))return e.split(" ").forEach((e=>this.on(e,t))),this;if("change"===e||"added"===e||"removed"===e||"enable"===e||"disable"===e){const i="enable"===e||"disable"===e;this._gsEventHandler[e]=i?e=>t(e):e=>{e.detail&&t(e,e.detail)},this.el.addEventListener(e,this._gsEventHandler[e])}else"drag"===e||"dragstart"===e||"dragstop"===e||"resizestart"===e||"resize"===e||"resizestop"===e||"dropped"===e||"resizecontent"===e?this._gsEventHandler[e]=t:console.error("GridStack.on("+e+") event not supported");return this}off(e){return-1!==e.indexOf(" ")?(e.split(" ").forEach((e=>this.off(e))),this):("change"!==e&&"added"!==e&&"removed"!==e&&"enable"!==e&&"disable"!==e||this._gsEventHandler[e]&&this.el.removeEventListener(e,this._gsEventHandler[e]),delete this._gsEventHandler[e],this)}offAll(){return Object.keys(this._gsEventHandler).forEach((e=>this.off(e))),this}removeWidget(e,t=!0,i=!0){return e?(x.getElements(e).forEach((e=>{if(e.parentElement&&e.parentElement!==this.el)return;let s=e.gridstackNode;s||(s=this.engine.nodes.find((t=>e===t.el))),s&&(t&&x.addRemoveCB&&x.addRemoveCB(this.el,s,!1,!1),delete e.gridstackNode,this._removeDD(e),this.engine.removeNode(s,t,i),t&&e.parentElement&&e.remove())})),i&&(this._triggerRemoveEvent(),this._triggerChangeEvent()),this):(console.error("Error: GridStack.removeWidget(undefined) called"),this)}removeAll(e=!0,t=!0){return this.engine.nodes.forEach((t=>{e&&x.addRemoveCB&&x.addRemoveCB(this.el,t,!1,!1),delete t.el.gridstackNode,this.opts.staticGrid||this._removeDD(t.el)})),this.engine.removeAll(e,t),t&&this._triggerRemoveEvent(),this}setAnimation(e=this.opts.animate,t){return t?setTimeout((()=>{this.opts&&this.setAnimation(e)})):e?this.el.classList.add("grid-stack-animate"):this.el.classList.remove("grid-stack-animate"),this.opts.animate=e,this}hasAnimationCSS(){return this.el.classList.contains("grid-stack-animate")}setStatic(e,t=!0,i=!0){return!!this.opts.staticGrid===e||(e?this.opts.staticGrid=!0:delete this.opts.staticGrid,this._setupRemoveDrop(),this._setupAcceptWidget(),this.engine.nodes.forEach((s=>{this.prepareDragDrop(s.el),s.subGrid&&i&&s.subGrid.setStatic(e,t,i)})),t&&this._setStaticClass()),this}updateOptions(e){const t=this.opts;return e===t||(void 0!==e.acceptWidgets&&(t.acceptWidgets=e.acceptWidgets,this._setupAcceptWidget()),void 0!==e.animate&&this.setAnimation(e.animate),e.cellHeight&&this.cellHeight(e.cellHeight),void 0!==e.class&&e.class!==t.class&&(t.class&&this.el.classList.remove(t.class),e.class&&this.el.classList.add(e.class)),e.columnOpts?(this.opts.columnOpts=e.columnOpts,this.checkDynamicColumn()):null===e.columnOpts&&this.opts.columnOpts?(delete this.opts.columnOpts,this._updateResizeEvent()):"number"==typeof e.column&&this.column(e.column),void 0!==e.margin&&this.margin(e.margin),void 0!==e.staticGrid&&this.setStatic(e.staticGrid),void 0===e.disableDrag||e.staticGrid||this.enableMove(!e.disableDrag),void 0===e.disableResize||e.staticGrid||this.enableResize(!e.disableResize),void 0!==e.float&&this.float(e.float),void 0!==e.row?t.minRow=t.maxRow=t.row=e.row:(void 0!==e.minRow&&(t.minRow=e.minRow),void 0!==e.maxRow&&(t.maxRow=e.maxRow)),e.children?.length&&this.load(e.children)),this}update(e,t){return x.getElements(e).forEach((e=>{const s=e?.gridstackNode;if(!s)return;const o={...i.copyPos({},s),...i.cloneDeep(t)};this.engine.nodeBoundFix(o),delete o.autoPosition;const n=["x","y","w","h"];let r;if(n.some((e=>void 0!==o[e]&&o[e]!==s[e]))&&(r={},n.forEach((e=>{r[e]=void 0!==o[e]?o[e]:s[e],delete o[e]}))),!r&&(o.minW||o.minH||o.maxW||o.maxH)&&(r={}),void 0!==o.content){const t=e.querySelector(".grid-stack-item-content");t&&t.textContent!==o.content&&(s.content=o.content,x.renderCB(t,o),s.subGrid?.el&&(t.appendChild(s.subGrid.el),s.subGrid._updateContainerHeight())),delete o.content}let a=!1,h=!1;for(const e in o)"_"!==e[0]&&s[e]!==o[e]&&(s[e]=o[e],a=!0,h=h||!this.opts.staticGrid&&("noResize"===e||"noMove"===e||"locked"===e));if(i.sanitizeMinMax(s),r){const e=void 0!==r.w&&r.w!==s.w;this.moveNode(s,r),e&&s.subGrid?s.subGrid.onResize(this.hasAnimationCSS()?s.w:void 0):this.resizeToContentCheck(e,s),delete s._orig}(r||a)&&this._writeAttr(e,s),h&&this.prepareDragDrop(s.el)})),this}moveNode(e,t){const i=e._updating;i||this.engine.cleanNodes().beginUpdate(e),this.engine.moveNode(e,t),this._updateContainerHeight(),i||(this._triggerChangeEvent(),this.engine.endUpdate())}resizeToContent(e){if(!e)return;if(e.classList.remove("size-to-content-max"),!e.clientHeight)return;const t=e.gridstackNode;if(!t)return;const i=t.grid;if(!i||e.parentElement!==i.el)return;const s=i.getCellHeight(!0);if(!s)return;let o,n=t.h?t.h*s:e.clientHeight;if(t.resizeToContentParent&&(o=e.querySelector(t.resizeToContentParent)),o||(o=e.querySelector(x.resizeToContentParent)),!o)return;const r=e.clientHeight-o.clientHeight,a=t.h?t.h*s-r:o.clientHeight;let h;if(t.subGrid){h=t.subGrid.getRow()*t.subGrid.getCellHeight(!0);const i=t.subGrid.el.getBoundingClientRect(),s=e.getBoundingClientRect();h+=i.top-s.top}else{if(t.subGridOpts?.children?.length)return;{const e=o.firstElementChild;if(!e)return void console.error(`Error: GridStack.resizeToContent() widget id:${t.id} '${x.resizeToContentParent}'.firstElementChild is null, make sure to have a div like container. Skipping sizing.`);h=e.getBoundingClientRect().height||a}}if(a===h)return;n+=h-a;let l=Math.ceil(n/s);const d=Number.isInteger(t.sizeToContent)?t.sizeToContent:0;d&&l>d&&(l=d,e.classList.add("size-to-content-max")),t.minH&&l<t.minH?l=t.minH:t.maxH&&l>t.maxH&&(l=t.maxH),l!==t.h&&(i._ignoreLayoutsNodeChange=!0,i.moveNode(t,{h:l}),delete i._ignoreLayoutsNodeChange)}resizeToContentCBCheck(e){x.resizeToContentCB?x.resizeToContentCB(e):this.resizeToContent(e)}rotate(e,t){return x.getElements(e).forEach((e=>{const s=e.gridstackNode;if(!i.canBeRotated(s))return;const o={w:s.h,h:s.w,minH:s.minW,minW:s.minH,maxH:s.maxW,maxW:s.maxH};if(t){const e=t.left>0?Math.floor(t.left/this.cellWidth()):0,i=t.top>0?Math.floor(t.top/this.opts.cellHeight):0;o.x=s.x+e-(s.h-(i+1)),o.y=s.y+i-e}Object.keys(o).forEach((e=>{void 0===o[e]&&delete o[e]}));const n=s._orig;this.update(e,o),s._orig=n})),this}margin(e){if(!("string"==typeof e&&e.split(" ").length>1)){const t=i.parseHeight(e);if(this.opts.marginUnit===t.unit&&this.opts.margin===t.h)return}return this.opts.margin=e,this.opts.marginTop=this.opts.marginBottom=this.opts.marginLeft=this.opts.marginRight=void 0,this._initMargin(),this}getMargin(){return this.opts.margin}willItFit(e){if(arguments.length>1){console.warn("gridstack.ts: `willItFit(x,y,w,h,autoPosition)` is deprecated. Use `willItFit({x, y,...})`. It will be removed soon");const e=arguments;let t=0,i={x:e[t++],y:e[t++],w:e[t++],h:e[t++],autoPosition:e[t++]};return this.willItFit(i)}return this.engine.willItFit(e)}_triggerChangeEvent(){if(this.engine.batchMode)return this;const e=this.engine.getDirtyNodes(!0);return e&&e.length&&(this._ignoreLayoutsNodeChange||this.engine.layoutsNodesChange(e),this._triggerEvent("change",e)),this.engine.saveInitial(),this}_triggerAddEvent(){if(this.engine.batchMode)return this;if(this.engine.addedNodes?.length){this._ignoreLayoutsNodeChange||this.engine.layoutsNodesChange(this.engine.addedNodes),this.engine.addedNodes.forEach((e=>{delete e._dirty}));const e=[...this.engine.addedNodes];this.engine.addedNodes=[],this._triggerEvent("added",e)}return this}_triggerRemoveEvent(){if(this.engine.batchMode)return this;if(this.engine.removedNodes?.length){const e=[...this.engine.removedNodes];this.engine.removedNodes=[],this._triggerEvent("removed",e)}return this}_triggerEvent(e,t){const i=t?new CustomEvent(e,{bubbles:!1,detail:t}):new Event(e);let s=this;for(;s.parentGridNode;)s=s.parentGridNode.grid;return s.el.dispatchEvent(i),this}_updateContainerHeight(){if(!this.engine||this.engine.batchMode)return this;const e=this.parentGridNode;let t=this.getRow()+this._extraDragRow;const s=this.opts.cellHeight,o=this.opts.cellHeightUnit;if(!s)return this;if(!e){const e=i.parseHeight(getComputedStyle(this.el).minHeight);if(e.h>0&&e.unit===o){const i=Math.floor(e.h/s);t<i&&(t=i)}}return this.el.setAttribute("gs-current-row",String(t)),this.el.style.removeProperty("min-height"),this.el.style.removeProperty("height"),t&&(this.el.style[e?"minHeight":"height"]=t*s+o),e&&i.shouldSizeToContent(e)&&e.grid.resizeToContentCBCheck(e.el),this}_prepareElement(e,t=!1,s){s=s||this._readAttr(e),e.gridstackNode=s,s.el=e,s.grid=this,s=this.engine.addNode(s,t),this._writeAttr(e,s),e.classList.add(o.itemClass,this.opts.itemClass);const n=i.shouldSizeToContent(s);return n?e.classList.add("size-to-content"):e.classList.remove("size-to-content"),n&&this.resizeToContentCheck(!1,s),i.lazyLoad(s)||this.prepareDragDrop(s.el),this}_writePosAttr(e,t){return(t._moving||t._resizing)&&this._placeholder!==e||(e.style.top=t.y?1===t.y?"var(--gs-cell-height)":`calc(${t.y} * var(--gs-cell-height))`:null,e.style.left=t.x?1===t.x?"var(--gs-column-width)":`calc(${t.x} * var(--gs-column-width))`:null,e.style.width=t.w>1?`calc(${t.w} * var(--gs-column-width))`:null,e.style.height=t.h>1?`calc(${t.h} * var(--gs-cell-height))`:null),t.x>0?e.setAttribute("gs-x",String(t.x)):e.removeAttribute("gs-x"),t.y>0?e.setAttribute("gs-y",String(t.y)):e.removeAttribute("gs-y"),t.w>1?e.setAttribute("gs-w",String(t.w)):e.removeAttribute("gs-w"),t.h>1?e.setAttribute("gs-h",String(t.h)):e.removeAttribute("gs-h"),this}_writeAttr(e,t){if(!t)return this;this._writePosAttr(e,t);const i={noResize:"gs-no-resize",noMove:"gs-no-move",locked:"gs-locked",id:"gs-id",sizeToContent:"gs-size-to-content"};for(const s in i)t[s]?e.setAttribute(i[s],String(t[s])):e.removeAttribute(i[s]);return this}_readAttr(e,t=!0){const s={};s.x=i.toNumber(e.getAttribute("gs-x")),s.y=i.toNumber(e.getAttribute("gs-y")),s.w=i.toNumber(e.getAttribute("gs-w")),s.h=i.toNumber(e.getAttribute("gs-h")),s.autoPosition=i.toBool(e.getAttribute("gs-auto-position")),s.noResize=i.toBool(e.getAttribute("gs-no-resize")),s.noMove=i.toBool(e.getAttribute("gs-no-move")),s.locked=i.toBool(e.getAttribute("gs-locked"));const o=e.getAttribute("gs-size-to-content");o&&(s.sizeToContent="true"===o||"false"===o?i.toBool(o):parseInt(o,10)),s.id=e.getAttribute("gs-id"),s.maxW=i.toNumber(e.getAttribute("gs-max-w")),s.minW=i.toNumber(e.getAttribute("gs-min-w")),s.maxH=i.toNumber(e.getAttribute("gs-max-h")),s.minH=i.toNumber(e.getAttribute("gs-min-h")),t&&(1===s.w&&e.removeAttribute("gs-w"),1===s.h&&e.removeAttribute("gs-h"),s.maxW&&e.removeAttribute("gs-max-w"),s.minW&&e.removeAttribute("gs-min-w"),s.maxH&&e.removeAttribute("gs-max-h"),s.minH&&e.removeAttribute("gs-min-h"));for(const e in s){if(!s.hasOwnProperty(e))return;s[e]||0===s[e]||"gs-size-to-content"===e||delete s[e]}return s}_setStaticClass(){const e=["grid-stack-static"];return this.opts.staticGrid?(this.el.classList.add(...e),this.el.setAttribute("gs-static","true")):(this.el.classList.remove(...e),this.el.removeAttribute("gs-static")),this}onResize(e=this.el?.clientWidth){if(!e)return;if(this.prevWidth===e)return;this.prevWidth=e,this.batchUpdate();let t=!1;return this._autoColumn&&this.parentGridNode?this.opts.column!==this.parentGridNode.w&&(this.column(this.parentGridNode.w,this.opts.layout||"list"),t=!0):t=this.checkDynamicColumn(),this._isAutoCellHeight&&this.cellHeight(),this.engine.nodes.forEach((e=>{e.subGrid&&e.subGrid.onResize()})),this._skipInitialResize||this.resizeToContentCheck(t),delete this._skipInitialResize,this.batchUpdate(!1),this}resizeToContentCheck(e=!1,t=void 0){if(this.engine){if(e&&this.hasAnimationCSS())return setTimeout((()=>this.resizeToContentCheck(!1,t)),this.animationDelay);if(t)i.shouldSizeToContent(t)&&this.resizeToContentCBCheck(t.el);else if(this.engine.nodes.some((e=>i.shouldSizeToContent(e)))){const e=[...this.engine.nodes];this.batchUpdate(),e.forEach((e=>{i.shouldSizeToContent(e)&&this.resizeToContentCBCheck(e.el)})),this._ignoreLayoutsNodeChange=!0,this.batchUpdate(!1),this._ignoreLayoutsNodeChange=!1}this._gsEventHandler.resizecontent&&this._gsEventHandler.resizecontent(null,t?[t]:this.engine.nodes)}}_updateResizeEvent(e=!1){const t=!this.parentGridNode&&(this._isAutoCellHeight||this.opts.sizeToContent||this.opts.columnOpts||this.engine.nodes.find((e=>e.sizeToContent)));return e||!t||this.resizeObserver?!e&&t||!this.resizeObserver||(this.resizeObserver.disconnect(),delete this.resizeObserver,delete this._sizeThrottle):(this._sizeThrottle=i.throttle((()=>this.onResize()),this.opts.cellHeightThrottle),this.resizeObserver=new ResizeObserver((()=>this._sizeThrottle())),this.resizeObserver.observe(this.el),this._skipInitialResize=!0),this}static getElement(e=".grid-stack-item"){return i.getElement(e)}static getElements(e=".grid-stack-item"){return i.getElements(e)}static getGridElement(e){return x.getElement(e)}static getGridElements(e){return i.getElements(e)}_initMargin(){let e,t=0,s=[];"string"==typeof this.opts.margin&&(s=this.opts.margin.split(" ")),2===s.length?(this.opts.marginTop=this.opts.marginBottom=s[0],this.opts.marginLeft=this.opts.marginRight=s[1]):4===s.length?(this.opts.marginTop=s[0],this.opts.marginRight=s[1],this.opts.marginBottom=s[2],this.opts.marginLeft=s[3]):(e=i.parseHeight(this.opts.margin),this.opts.marginUnit=e.unit,t=this.opts.margin=e.h),["marginTop","marginRight","marginBottom","marginLeft"].forEach((s=>{void 0===this.opts[s]?this.opts[s]=t:(e=i.parseHeight(this.opts[s]),this.opts[s]=e.h,delete this.opts.margin)})),this.opts.marginUnit=e.unit,this.opts.marginTop===this.opts.marginBottom&&this.opts.marginLeft===this.opts.marginRight&&this.opts.marginTop===this.opts.marginRight&&(this.opts.margin=this.opts.marginTop);const o=this.el.style;return o.setProperty("--gs-item-margin-top",`${this.opts.marginTop}${this.opts.marginUnit}`),o.setProperty("--gs-item-margin-bottom",`${this.opts.marginBottom}${this.opts.marginUnit}`),o.setProperty("--gs-item-margin-right",`${this.opts.marginRight}${this.opts.marginUnit}`),o.setProperty("--gs-item-margin-left",`${this.opts.marginLeft}${this.opts.marginUnit}`),this}static getDD(){return E}static setupDragIn(e,t,s,o=document){void 0!==t?.pause&&(n.pauseDrag=t.pause),t={appendTo:"body",helper:"clone",...t||{}},("string"==typeof e?i.getElements(e,o):e).forEach(((e,i)=>{E.isDraggable(e)||E.dragIn(e,t),s?.[i]&&(e.gridstackNode=s[i])}))}movable(e,t){return this.opts.staticGrid||x.getElements(e).forEach((e=>{const i=e.gridstackNode;i&&(t?delete i.noMove:i.noMove=!0,this.prepareDragDrop(i.el))})),this}resizable(e,t){return this.opts.staticGrid||x.getElements(e).forEach((e=>{const i=e.gridstackNode;i&&(t?delete i.noResize:i.noResize=!0,this.prepareDragDrop(i.el))})),this}disable(e=!0){if(!this.opts.staticGrid)return this.enableMove(!1,e),this.enableResize(!1,e),this._triggerEvent("disable"),this}enable(e=!0){if(!this.opts.staticGrid)return this.enableMove(!0,e),this.enableResize(!0,e),this._triggerEvent("enable"),this}enableMove(e,t=!0){return this.opts.staticGrid||(e?delete this.opts.disableDrag:this.opts.disableDrag=!0,this.engine.nodes.forEach((i=>{this.prepareDragDrop(i.el),i.subGrid&&t&&i.subGrid.enableMove(e,t)}))),this}enableResize(e,t=!0){return this.opts.staticGrid||(e?delete this.opts.disableResize:this.opts.disableResize=!0,this.engine.nodes.forEach((i=>{this.prepareDragDrop(i.el),i.subGrid&&t&&i.subGrid.enableResize(e,t)}))),this}cancelDrag(){const e=this._placeholder?.gridstackNode;e&&(e._isExternal?(e._isAboutToRemove=!0,this.engine.removeNode(e)):e._isAboutToRemove&&x._itemRemoving(e.el,!1),this.engine.restoreInitial())}_removeDD(e){return E.draggable(e,"destroy").resizable(e,"destroy"),e.gridstackNode&&delete e.gridstackNode._initDD,delete e.ddElement,this}_setupAcceptWidget(){if(this.opts.staticGrid||!this.opts.acceptWidgets&&!this.opts.removable)return E.droppable(this.el,"destroy"),this;let e,t;const s=(s,o,n)=>{const r=(n=n||o).gridstackNode;if(!r)return;if(!r.grid?.el){n.style.transform=`scale(${1/this.dragTransform.xScale},${1/this.dragTransform.yScale})`;const e=n.getBoundingClientRect();n.style.left=e.x+(this.dragTransform.xScale-1)*(s.clientX-e.x)/this.dragTransform.xScale+"px",n.style.top=e.y+(this.dragTransform.yScale-1)*(s.clientY-e.y)/this.dragTransform.yScale+"px",n.style.transformOrigin="0px 0px"}let{top:a,left:h}=n.getBoundingClientRect();const l=this.el.getBoundingClientRect();h-=l.left,a-=l.top;const d={position:{top:a*this.dragTransform.xScale,left:h*this.dragTransform.yScale}};if(r._temporaryRemoved){if(r.x=Math.max(0,Math.round(h/t)),r.y=Math.max(0,Math.round(a/e)),delete r.autoPosition,this.engine.nodeBoundFix(r),!this.engine.willItFit(r)){if(r.autoPosition=!0,!this.engine.willItFit(r))return void E.off(o,"drag");r._willFitPos&&(i.copyPos(r,r._willFitPos),delete r._willFitPos)}this._onStartMoving(n,s,d,r,t,e)}else this._dragOrResize(n,s,d,r,t,e)};return E.droppable(this.el,{accept:e=>{const t=e.gridstackNode||this._readAttr(e,!1);if(t?.grid===this)return!0;if(!this.opts.acceptWidgets)return!1;let i=!0;if("function"==typeof this.opts.acceptWidgets)i=this.opts.acceptWidgets(e);else{const t=!0===this.opts.acceptWidgets?".grid-stack-item":this.opts.acceptWidgets;i=e.matches(t)}if(i&&t&&this.opts.maxRow){const e={w:t.w,h:t.h,minW:t.minW,minH:t.minH};i=this.engine.willItFit(e)}return i}}).on(this.el,"dropover",((i,o,n)=>{let r=n?.gridstackNode||o.gridstackNode;if(r?.grid===this&&!r._temporaryRemoved)return!1;if(r?._sidebarOrig&&(r.w=r._sidebarOrig.w,r.h=r._sidebarOrig.h),r?.grid&&r.grid!==this&&!r._temporaryRemoved&&r.grid._leave(o,n),n=n||o,t=this.cellWidth(),e=this.getCellHeight(!0),!r){const e=n.getAttribute("data-gs-widget")||n.getAttribute("gridstacknode");if(e){try{r=JSON.parse(e)}catch(t){console.error("Gridstack dropover: Bad JSON format: ",e)}n.removeAttribute("data-gs-widget"),n.removeAttribute("gridstacknode")}r||(r=this._readAttr(n)),r._sidebarOrig={w:r.w,h:r.h}}r.grid||(r.el||(r={...r}),r._isExternal=!0,n.gridstackNode=r);const a=r.w||Math.round(n.offsetWidth/t)||1,h=r.h||Math.round(n.offsetHeight/e)||1;return r.grid&&r.grid!==this?(o._gridstackNodeOrig||(o._gridstackNodeOrig=r),o.gridstackNode=r={...r,w:a,h,grid:this},delete r.x,delete r.y,this.engine.cleanupNode(r).nodeBoundFix(r),r._initDD=r._isExternal=r._temporaryRemoved=!0):(r.w=a,r.h=h,r._temporaryRemoved=!0),x._itemRemoving(r.el,!1),E.on(o,"drag",s),s(i,o,n),!1})).on(this.el,"dropout",((e,t,i)=>{const s=i?.gridstackNode||t.gridstackNode;return!!s&&(s.grid&&s.grid!==this||(this._leave(t,i),this._isTemp&&this.removeAsSubGrid(s)),!1)})).on(this.el,"drop",((e,t,s)=>{const o=s?.gridstackNode||t.gridstackNode;if(o?.grid===this&&!o._isExternal)return!1;const n=!!this.placeholder.parentElement,r=t!==s;this.placeholder.remove(),delete this.placeholder.gridstackNode,n&&this.opts.animate&&(this.setAnimation(!1),this.setAnimation(!0,!0));const a=t._gridstackNodeOrig;if(delete t._gridstackNodeOrig,n&&a?.grid&&a.grid!==this){const e=a.grid;e.engine.removeNodeFromLayoutCache(a),e.engine.removedNodes.push(a),e._triggerRemoveEvent()._triggerChangeEvent(),e.parentGridNode&&!e.engine.nodes.length&&e.opts.subGridDynamic&&e.removeAsSubGrid()}if(!o)return!1;if(n&&(this.engine.cleanupNode(o),o.grid=this),delete o.grid?._isTemp,E.off(t,"drag"),s!==t?(s.remove(),t=s):t.remove(),this._removeDD(t),!n)return!1;const h=o.subGrid?.el?.gridstack;return i.copyPos(o,this._readAttr(this.placeholder)),i.removePositioningStyles(t),r&&(o.content||o.subGridOpts||x.addRemoveCB)?(delete o.el,t=this.addWidget(o)):(this._prepareElement(t,!0,o),this.el.appendChild(t),this.resizeToContentCheck(!1,o),h&&(h.parentGridNode=o),this._updateContainerHeight()),this.engine.addedNodes.push(o),this._triggerAddEvent(),this._triggerChangeEvent(),this.engine.endUpdate(),this._gsEventHandler.dropped&&this._gsEventHandler.dropped({...e,type:"dropped"},a&&a.grid?a:void 0,o),!1})),this}static _itemRemoving(e,t){if(!e)return;const i=e?e.gridstackNode:void 0;i?.grid&&!e.classList.contains(i.grid.opts.removableOptions.decline)&&(t?i._isAboutToRemove=!0:delete i._isAboutToRemove,t?e.classList.add("grid-stack-item-removing"):e.classList.remove("grid-stack-item-removing"))}_setupRemoveDrop(){if("string"!=typeof this.opts.removable)return this;const e=document.querySelector(this.opts.removable);return e?(this.opts.staticGrid||E.isDroppable(e)||E.droppable(e,this.opts.removableOptions).on(e,"dropover",((e,t)=>x._itemRemoving(t,!0))).on(e,"dropout",((e,t)=>x._itemRemoving(t,!1))),this):this}prepareDragDrop(e,t=!1){const s=e?.gridstackNode;if(!s)return;const o=s.noMove||this.opts.disableDrag,n=s.noResize||this.opts.disableResize,r=this.opts.staticGrid||o&&n;if((t||r)&&(s._initDD&&(this._removeDD(e),delete s._initDD),r&&e.classList.add("ui-draggable-disabled","ui-resizable-disabled"),!t))return this;if(!s._initDD){let t,o;const n=(i,n)=>{this.triggerEvent(i,i.target),t=this.cellWidth(),o=this.getCellHeight(!0),this._onStartMoving(e,i,n,s,t,o)},r=(i,n)=>{this._dragOrResize(e,i,n,s,t,o)},a=t=>{this.placeholder.remove(),delete this.placeholder.gridstackNode,delete s._moving,delete s._resizing,delete s._event,delete s._lastTried;const o=s.w!==s._orig.w,n=t.target;if(n.gridstackNode&&n.gridstackNode.grid===this){if(s.el=n,s._isAboutToRemove){const i=e.gridstackNode.grid;i._gsEventHandler[t.type]&&i._gsEventHandler[t.type](t,n),i.engine.nodes.push(s),i.removeWidget(e,!0,!0)}else i.removePositioningStyles(n),s._temporaryRemoved?(i.copyPos(s,s._orig),this._writePosAttr(n,s),this.engine.addNode(s)):this._writePosAttr(n,s),this.triggerEvent(t,n);this._extraDragRow=0,this._updateContainerHeight(),this._triggerChangeEvent(),this.engine.endUpdate(),"resizestop"===t.type&&(Number.isInteger(s.sizeToContent)&&(s.sizeToContent=s.h),this.resizeToContentCheck(o,s))}};E.draggable(e,{start:n,stop:a,drag:r}).resizable(e,{start:n,stop:a,resize:r}),s._initDD=!0}return E.draggable(e,o?"disable":"enable").resizable(e,n?"disable":"enable"),this}_onStartMoving(e,t,s,o,n,r){if(this.engine.cleanNodes().beginUpdate(o),this._writePosAttr(this.placeholder,o),this.el.appendChild(this.placeholder),this.placeholder.gridstackNode=o,o.grid?.el)this.dragTransform=i.getValuesFromTransformedElement(e);else if(this.placeholder&&this.placeholder.closest(".grid-stack")){const e=this.placeholder.closest(".grid-stack");this.dragTransform=i.getValuesFromTransformedElement(e)}else this.dragTransform={xScale:1,xOffset:0,yScale:1,yOffset:0};if(o.el=this.placeholder,o._lastUiPosition=s.position,o._prevYPix=s.position.top,o._moving="dragstart"===t.type,o._resizing="resizestart"===t.type,delete o._lastTried,"dropover"===t.type&&o._temporaryRemoved&&(this.engine.addNode(o),o._moving=!0),this.engine.cacheRects(n,r,this.opts.marginTop,this.opts.marginRight,this.opts.marginBottom,this.opts.marginLeft),"resizestart"===t.type){const t=this.getColumn()-o.x,i=(this.opts.maxRow||Number.MAX_SAFE_INTEGER)-o.y;E.resizable(e,"option","minWidth",n*Math.min(o.minW||1,t)).resizable(e,"option","minHeight",r*Math.min(o.minH||1,i)).resizable(e,"option","maxWidth",n*Math.min(o.maxW||Number.MAX_SAFE_INTEGER,t)).resizable(e,"option","maxWidthMoveLeft",n*Math.min(o.maxW||Number.MAX_SAFE_INTEGER,o.x+o.w)).resizable(e,"option","maxHeight",r*Math.min(o.maxH||Number.MAX_SAFE_INTEGER,i)).resizable(e,"option","maxHeightMoveUp",r*Math.min(o.maxH||Number.MAX_SAFE_INTEGER,o.y+o.h))}}_dragOrResize(e,t,s,o,n,r){const a={...o._orig};let h,l=this.opts.marginLeft,d=this.opts.marginRight,c=this.opts.marginTop,g=this.opts.marginBottom;const u=Math.round(.1*r),p=Math.round(.1*n);if(l=Math.min(l,p),d=Math.min(d,p),c=Math.min(c,u),g=Math.min(g,u),"drag"===t.type){if(o._temporaryRemoved)return;const t=s.position.top-o._prevYPix;o._prevYPix=s.position.top,!1!==this.opts.draggable.scroll&&i.updateScrollPosition(e,s.position,t);const h=s.position.left+(s.position.left>o._lastUiPosition.left?-d:l),u=s.position.top+(s.position.top>o._lastUiPosition.top?-g:c);a.x=Math.round(h/n),a.y=Math.round(u/r);const p=this._extraDragRow;if(this.engine.collide(o,a)){const e=this.getRow();let t=Math.max(0,a.y+o.h-e);this.opts.maxRow&&e+t>this.opts.maxRow&&(t=Math.max(0,this.opts.maxRow-e)),this._extraDragRow=t}else this._extraDragRow=0;if(this._extraDragRow!==p&&this._updateContainerHeight(),o.x===a.x&&o.y===a.y)return}else if("resize"===t.type){if(a.x<0)return;if(i.updateScrollResize(t,e,r),a.w=Math.round((s.size.width-l)/n),a.h=Math.round((s.size.height-c)/r),o.w===a.w&&o.h===a.h)return;if(o._lastTried&&o._lastTried.w===a.w&&o._lastTried.h===a.h)return;const d=s.position.left+l,g=s.position.top+c;a.x=Math.round(d/n),a.y=Math.round(g/r),h=!0}o._event=t,o._lastTried=a;const m={x:s.position.left+l,y:s.position.top+c,w:(s.size?s.size.width:o.w*n)-l-d,h:(s.size?s.size.height:o.h*r)-c-g};if(this.engine.moveNodeCheck(o,{...a,cellWidth:n,cellHeight:r,rect:m,resizing:h})){o._lastUiPosition=s.position,this.engine.cacheRects(n,r,c,d,g,l),delete o._skipDown,h&&o.subGrid&&o.subGrid.onResize(),this._extraDragRow=0,this._updateContainerHeight();const e=t.target;o._sidebarOrig||this._writePosAttr(e,o),this.triggerEvent(t,e)}}triggerEvent(e,t){let i=this;for(;i.parentGridNode;)i=i.parentGridNode.grid;i._gsEventHandler[e.type]&&i._gsEventHandler[e.type](e,t)}_leave(e,t){const i=(t=t||e).gridstackNode;if(!i)return;if(t.style.transform=t.style.transformOrigin=null,E.off(e,"drag"),i._temporaryRemoved)return;i._temporaryRemoved=!0,this.engine.removeNode(i),i.el=i._isExternal&&t?t:e;const s=i._sidebarOrig;i._isExternal&&this.engine.cleanupNode(i),i._sidebarOrig=s,!0===this.opts.removable&&x._itemRemoving(e,!0),e._gridstackNodeOrig?(e.gridstackNode=e._gridstackNodeOrig,delete e._gridstackNodeOrig):i._isExternal&&this.engine.restoreInitial()}commit(){return this.batchUpdate(!1).prototype,this}}return x.renderCB=(e,t)=>{e&&t?.content&&(e.textContent=t.content)},x.resizeToContentParent=".grid-stack-item-content",x.Utils=i,x.Engine=s,x.GDRev="12.1.2",t.GridStack})()));
+//# sourceMappingURL=gridstack-all.js.map
\ No newline at end of file
diff --git a/node_modules/gridstack/dist/gridstack-all.js.map b/node_modules/gridstack/dist/gridstack-all.js.map
new file mode 100644
index 000000000..6a74b4b96
--- /dev/null
+++ b/node_modules/gridstack/dist/gridstack-all.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"gridstack-all.js","mappings":"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","sources":["webpack://GridStack/webpack/universalModuleDefinition","webpack://GridStack/webpack/bootstrap","webpack://GridStack/webpack/runtime/define property getters","webpack://GridStack/webpack/runtime/hasOwnProperty shorthand","webpack://GridStack/./src/utils.ts","webpack://GridStack/./src/gridstack-engine.ts","webpack://GridStack/./src/types.ts","webpack://GridStack/./src/dd-manager.ts","webpack://GridStack/./src/dd-touch.ts","webpack://GridStack/./src/dd-resizable-handle.ts","webpack://GridStack/./src/dd-base-impl.ts","webpack://GridStack/./src/dd-resizable.ts","webpack://GridStack/./src/dd-draggable.ts","webpack://GridStack/./src/dd-droppable.ts","webpack://GridStack/./src/dd-element.ts","webpack://GridStack/./src/gridstack.ts","webpack://GridStack/./src/dd-gridstack.ts"],"sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"GridStack\"] = factory();\n\telse\n\t\troot[\"GridStack\"] = factory();\n})(self, () => {\nreturn ","// The require scope\nvar __webpack_require__ = {};\n\n","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","/**\r\n * utils.ts 12.1.2\r\n * Copyright (c) 2021-2024 Alain Dumesny - see GridStack root license\r\n */\r\n\r\nimport { GridStackElement, GridStackNode, GridStackOptions, numberOrString, GridStackPosition, GridStackWidget } from './types';\r\n\r\nexport interface HeightData {\r\n  h: number;\r\n  unit: string;\r\n}\r\n\r\nexport interface DragTransform {\r\n  xScale: number;\r\n  yScale: number;\r\n  xOffset: number;\r\n  yOffset: number;\r\n}\r\n\r\n/** checks for obsolete method names */\r\n// eslint-disable-next-line\r\nexport function obsolete(self, f, oldName: string, newName: string, rev: string): (...args: any[]) => any {\r\n  const wrapper = (...args) => {\r\n    console.warn('gridstack.js: Function `' + oldName + '` is deprecated in ' + rev + ' and has been replaced ' +\r\n    'with `' + newName + '`. It will be **removed** in a future release');\r\n    return f.apply(self, args);\r\n  }\r\n  wrapper.prototype = f.prototype;\r\n  return wrapper;\r\n}\r\n\r\n/** checks for obsolete grid options (can be used for any fields, but msg is about options) */\r\nexport function obsoleteOpts(opts: GridStackOptions, oldName: string, newName: string, rev: string): void {\r\n  if (opts[oldName] !== undefined) {\r\n    opts[newName] = opts[oldName];\r\n    console.warn('gridstack.js: Option `' + oldName + '` is deprecated in ' + rev + ' and has been replaced with `' +\r\n      newName + '`. It will be **removed** in a future release');\r\n  }\r\n}\r\n\r\n/** checks for obsolete grid options which are gone */\r\nexport function obsoleteOptsDel(opts: GridStackOptions, oldName: string, rev: string, info: string): void {\r\n  if (opts[oldName] !== undefined) {\r\n    console.warn('gridstack.js: Option `' + oldName + '` is deprecated in ' + rev + info);\r\n  }\r\n}\r\n\r\n/** checks for obsolete Jquery element attributes */\r\nexport function obsoleteAttr(el: HTMLElement, oldName: string, newName: string, rev: string): void {\r\n  const oldAttr = el.getAttribute(oldName);\r\n  if (oldAttr !== null) {\r\n    el.setAttribute(newName, oldAttr);\r\n    console.warn('gridstack.js: attribute `' + oldName + '`=' + oldAttr + ' is deprecated on this object in ' + rev + ' and has been replaced with `' +\r\n      newName + '`. It will be **removed** in a future release');\r\n  }\r\n}\r\n\r\n/**\r\n * Utility methods\r\n */\r\nexport class Utils {\r\n\r\n  /** convert a potential selector into actual list of html elements. optional root which defaults to document (for shadow dom) */\r\n  static getElements(els: GridStackElement, root: HTMLElement | Document = document): HTMLElement[] {\r\n    if (typeof els === 'string') {\r\n      const doc = ('getElementById' in root) ? root as Document : undefined;\r\n\r\n      // Note: very common for people use to id='1,2,3' which is only legal as HTML5 id, but not CSS selectors\r\n      // so if we start with a number, assume it's an id and just return that one item...\r\n      // see https://github.com/gridstack/gridstack.js/issues/2234#issuecomment-1523796562\r\n      if (doc && !isNaN(+els[0])) { // start with digit\r\n        const el = doc.getElementById(els);\r\n        return el ? [el] : [];\r\n      }\r\n\r\n      let list = root.querySelectorAll(els);\r\n      if (!list.length && els[0] !== '.' && els[0] !== '#') {\r\n        list = root.querySelectorAll('.' + els);\r\n        if (!list.length) { list = root.querySelectorAll('#' + els) }\r\n      }\r\n      return Array.from(list) as HTMLElement[];\r\n    }\r\n    return [els];\r\n  }\r\n\r\n  /** convert a potential selector into actual single element. optional root which defaults to document (for shadow dom) */\r\n  static getElement(els: GridStackElement, root: HTMLElement | Document = document): HTMLElement {\r\n    if (typeof els === 'string') {\r\n      const doc = ('getElementById' in root) ? root as Document : undefined;\r\n      if (!els.length) return null;\r\n      if (doc && els[0] === '#') {\r\n        return doc.getElementById(els.substring(1));\r\n      }\r\n      if (els[0] === '#' || els[0] === '.' || els[0] === '[') {\r\n        return root.querySelector(els);\r\n      }\r\n\r\n      // if we start with a digit, assume it's an id (error calling querySelector('#1')) as class are not valid CSS\r\n      if (doc && !isNaN(+els[0])) { // start with digit\r\n        return doc.getElementById(els);\r\n      }\r\n\r\n      // finally try string, then id, then class\r\n      let el = root.querySelector(els);\r\n      if (doc && !el) { el = doc.getElementById(els) }\r\n      if (!el) { el = root.querySelector('.' + els) }\r\n      return el as HTMLElement;\r\n    }\r\n    return els;\r\n  }\r\n\r\n  /** true if widget (or grid) makes this item lazyLoad */\r\n  static lazyLoad(n: GridStackNode): boolean {\r\n    return n.lazyLoad || n.grid?.opts?.lazyLoad && n.lazyLoad !== false;\r\n  }\r\n\r\n  /** create a div with the given classes */\r\n  static createDiv(classes: string[], parent?: HTMLElement): HTMLElement {\r\n    const el = document.createElement('div');\r\n    classes.forEach(c => {if (c) el.classList.add(c)});\r\n    parent?.appendChild(el);\r\n    return el;\r\n  }\r\n\r\n  /** true if we should resize to content. strict=true when only 'sizeToContent:true' and not a number which lets user adjust */\r\n  static shouldSizeToContent(n: GridStackNode | undefined, strict = false): boolean {\r\n    return n?.grid && (strict ?\r\n      (n.sizeToContent === true || (n.grid.opts.sizeToContent === true && n.sizeToContent === undefined)) :\r\n      (!!n.sizeToContent || (n.grid.opts.sizeToContent && n.sizeToContent !== false)));\r\n  }\r\n\r\n  /** returns true if a and b overlap */\r\n  static isIntercepted(a: GridStackPosition, b: GridStackPosition): boolean {\r\n    return !(a.y >= b.y + b.h || a.y + a.h <= b.y || a.x + a.w <= b.x || a.x >= b.x + b.w);\r\n  }\r\n\r\n  /** returns true if a and b touch edges or corners */\r\n  static isTouching(a: GridStackPosition, b: GridStackPosition): boolean {\r\n    return Utils.isIntercepted(a, {x: b.x-0.5, y: b.y-0.5, w: b.w+1, h: b.h+1})\r\n  }\r\n\r\n  /** returns the area a and b overlap */\r\n  static areaIntercept(a: GridStackPosition, b: GridStackPosition): number {\r\n    const x0 = (a.x > b.x) ? a.x : b.x;\r\n    const x1 = (a.x+a.w < b.x+b.w) ? a.x+a.w : b.x+b.w;\r\n    if (x1 <= x0) return 0; // no overlap\r\n    const y0 = (a.y > b.y) ? a.y : b.y;\r\n    const y1 = (a.y+a.h < b.y+b.h) ? a.y+a.h : b.y+b.h;\r\n    if (y1 <= y0) return 0; // no overlap\r\n    return (x1-x0) * (y1-y0);\r\n  }\r\n\r\n  /** returns the area */\r\n  static area(a: GridStackPosition): number {\r\n    return a.w * a.h;\r\n  }\r\n\r\n  /**\r\n   * Sorts array of nodes\r\n   * @param nodes array to sort\r\n   * @param dir 1 for ascending, -1 for descending (optional)\r\n   **/\r\n  static sort(nodes: GridStackNode[], dir: 1 | -1 = 1): GridStackNode[] {\r\n    const und = 10000;\r\n    return nodes.sort((a, b) => {\r\n      const diffY = dir * ((a.y ?? und) - (b.y ?? und));\r\n      if (diffY === 0) return dir * ((a.x ?? und) - (b.x ?? und));\r\n      return diffY;\r\n    });\r\n  }\r\n\r\n  /** find an item by id */\r\n  static find(nodes: GridStackNode[], id: string): GridStackNode | undefined {\r\n    return id ? nodes.find(n => n.id === id) : undefined;\r\n  }\r\n\r\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n  static toBool(v: unknown): boolean {\r\n    if (typeof v === 'boolean') {\r\n      return v;\r\n    }\r\n    if (typeof v === 'string') {\r\n      v = v.toLowerCase();\r\n      return !(v === '' || v === 'no' || v === 'false' || v === '0');\r\n    }\r\n    return Boolean(v);\r\n  }\r\n\r\n  static toNumber(value: null | string): number {\r\n    return (value === null || value.length === 0) ? undefined : Number(value);\r\n  }\r\n\r\n  static parseHeight(val: numberOrString): HeightData {\r\n    let h: number;\r\n    let unit = 'px';\r\n    if (typeof val === 'string') {\r\n      if (val === 'auto' || val === '') h = 0;\r\n      else {\r\n        const match = val.match(/^(-[0-9]+\\.[0-9]+|[0-9]*\\.[0-9]+|-[0-9]+|[0-9]+)(px|em|rem|vh|vw|%|cm|mm)?$/);\r\n        if (!match) {\r\n          throw new Error(`Invalid height val = ${val}`);\r\n        }\r\n        unit = match[2] || 'px';\r\n        h = parseFloat(match[1]);\r\n      }\r\n    } else {\r\n      h = val;\r\n    }\r\n    return { h, unit };\r\n  }\r\n\r\n  /** copies unset fields in target to use the given default sources values */\r\n  // eslint-disable-next-line\r\n  static defaults(target, ...sources): {} {\r\n\r\n    sources.forEach(source => {\r\n      for (const key in source) {\r\n        if (!source.hasOwnProperty(key)) return;\r\n        if (target[key] === null || target[key] === undefined) {\r\n          target[key] = source[key];\r\n        } else if (typeof source[key] === 'object' && typeof target[key] === 'object') {\r\n          // property is an object, recursively add it's field over... #1373\r\n          this.defaults(target[key], source[key]);\r\n        }\r\n      }\r\n    });\r\n\r\n    return target;\r\n  }\r\n\r\n  /** given 2 objects return true if they have the same values. Checks for Object {} having same fields and values (just 1 level down) */\r\n  static same(a: unknown, b: unknown): boolean {\r\n    if (typeof a !== 'object')  return a == b;\r\n    if (typeof a !== typeof b) return false;\r\n    // else we have object, check just 1 level deep for being same things...\r\n    if (Object.keys(a).length !== Object.keys(b).length) return false;\r\n    for (const key in a) {\r\n      if (a[key] !== b[key]) return false;\r\n    }\r\n    return true;\r\n  }\r\n\r\n  /** copies over b size & position (GridStackPosition), and optionally min/max as well */\r\n  static copyPos(a: GridStackWidget, b: GridStackWidget, doMinMax = false): GridStackWidget {\r\n    if (b.x !== undefined) a.x = b.x;\r\n    if (b.y !== undefined) a.y = b.y;\r\n    if (b.w !== undefined) a.w = b.w;\r\n    if (b.h !== undefined) a.h = b.h;\r\n    if (doMinMax) {\r\n      if (b.minW) a.minW = b.minW;\r\n      if (b.minH) a.minH = b.minH;\r\n      if (b.maxW) a.maxW = b.maxW;\r\n      if (b.maxH) a.maxH = b.maxH;\r\n    }\r\n    return a;\r\n  }\r\n\r\n  /** true if a and b has same size & position */\r\n  static samePos(a: GridStackPosition, b: GridStackPosition): boolean {\r\n    return a && b && a.x === b.x && a.y === b.y && (a.w || 1) === (b.w || 1) && (a.h || 1) === (b.h || 1);\r\n  }\r\n\r\n  /** given a node, makes sure it's min/max are valid */\r\n  static sanitizeMinMax(node: GridStackNode) {\r\n    // remove 0, undefine, null\r\n    if (!node.minW) { delete node.minW; }\r\n    if (!node.minH) { delete node.minH; }\r\n    if (!node.maxW) { delete node.maxW; }\r\n    if (!node.maxH) { delete node.maxH; }\r\n  }\r\n\r\n  /** removes field from the first object if same as the second objects (like diffing) and internal '_' for saving */\r\n  static removeInternalAndSame(a: unknown, b: unknown):void {\r\n    if (typeof a !== 'object' || typeof b !== 'object') return;\r\n    for (let key in a) {\r\n      const aVal = a[key];\r\n      const bVal = b[key];\r\n      if (key[0] === '_' || aVal === bVal) {\r\n        delete a[key]\r\n      } else if (aVal && typeof aVal === 'object' && bVal !== undefined) {\r\n        Utils.removeInternalAndSame(aVal, bVal);\r\n        if (!Object.keys(aVal).length) { delete a[key] }\r\n      }\r\n    }\r\n  }\r\n\r\n  /** removes internal fields '_' and default values for saving */\r\n  static removeInternalForSave(n: GridStackNode, removeEl = true): void {\r\n    for (let key in n) { if (key[0] === '_' || n[key] === null || n[key] === undefined ) delete n[key]; }\r\n    delete n.grid;\r\n    if (removeEl) delete n.el;\r\n    // delete default values (will be re-created on read)\r\n    if (!n.autoPosition) delete n.autoPosition;\r\n    if (!n.noResize) delete n.noResize;\r\n    if (!n.noMove) delete n.noMove;\r\n    if (!n.locked) delete n.locked;\r\n    if (n.w === 1 || n.w === n.minW) delete n.w;\r\n    if (n.h === 1 || n.h === n.minH) delete n.h;\r\n  }\r\n\r\n  /** return the closest parent (or itself) matching the given class */\r\n  // static closestUpByClass(el: HTMLElement, name: string): HTMLElement {\r\n  //   while (el) {\r\n  //     if (el.classList.contains(name)) return el;\r\n  //     el = el.parentElement\r\n  //   }\r\n  //   return null;\r\n  // }\r\n\r\n  /** delay calling the given function for given delay, preventing new calls from happening while waiting */\r\n  static throttle(func: () => void, delay: number): () => void {\r\n    let isWaiting = false;\r\n    return (...args) => {\r\n      if (!isWaiting) {\r\n        isWaiting = true;\r\n        setTimeout(() => { func(...args); isWaiting = false; }, delay);\r\n      }\r\n    }\r\n  }\r\n\r\n  static removePositioningStyles(el: HTMLElement): void {\r\n    const style = el.style;\r\n    if (style.position) {\r\n      style.removeProperty('position');\r\n    }\r\n    if (style.left) {\r\n      style.removeProperty('left');\r\n    }\r\n    if (style.top) {\r\n      style.removeProperty('top');\r\n    }\r\n    if (style.width) {\r\n      style.removeProperty('width');\r\n    }\r\n    if (style.height) {\r\n      style.removeProperty('height');\r\n    }\r\n  }\r\n\r\n  /** @internal returns the passed element if scrollable, else the closest parent that will, up to the entire document scrolling element */\r\n  static getScrollElement(el?: HTMLElement): HTMLElement {\r\n    if (!el) return document.scrollingElement as HTMLElement || document.documentElement; // IE support\r\n    const style = getComputedStyle(el);\r\n    const overflowRegex = /(auto|scroll)/;\r\n\r\n    if (overflowRegex.test(style.overflow + style.overflowY)) {\r\n      return el;\r\n    } else {\r\n      return this.getScrollElement(el.parentElement);\r\n    }\r\n  }\r\n\r\n  /** @internal */\r\n  static updateScrollPosition(el: HTMLElement, position: {top: number}, distance: number): void {\r\n    // is widget in view?\r\n    const rect = el.getBoundingClientRect();\r\n    const innerHeightOrClientHeight = (window.innerHeight || document.documentElement.clientHeight);\r\n    if (rect.top < 0 ||\r\n      rect.bottom > innerHeightOrClientHeight\r\n    ) {\r\n      // set scrollTop of first parent that scrolls\r\n      // if parent is larger than el, set as low as possible\r\n      // to get entire widget on screen\r\n      const offsetDiffDown = rect.bottom - innerHeightOrClientHeight;\r\n      const offsetDiffUp = rect.top;\r\n      const scrollEl = this.getScrollElement(el);\r\n      if (scrollEl !== null) {\r\n        const prevScroll = scrollEl.scrollTop;\r\n        if (rect.top < 0 && distance < 0) {\r\n          // moving up\r\n          if (el.offsetHeight > innerHeightOrClientHeight) {\r\n            scrollEl.scrollTop += distance;\r\n          } else {\r\n            scrollEl.scrollTop += Math.abs(offsetDiffUp) > Math.abs(distance) ? distance : offsetDiffUp;\r\n          }\r\n        } else if (distance > 0) {\r\n          // moving down\r\n          if (el.offsetHeight > innerHeightOrClientHeight) {\r\n            scrollEl.scrollTop += distance;\r\n          } else {\r\n            scrollEl.scrollTop += offsetDiffDown > distance ? distance : offsetDiffDown;\r\n          }\r\n        }\r\n        // move widget y by amount scrolled\r\n        position.top += scrollEl.scrollTop - prevScroll;\r\n      }\r\n    }\r\n  }\r\n\r\n  /**\r\n   * @internal Function used to scroll the page.\r\n   *\r\n   * @param event `MouseEvent` that triggers the resize\r\n   * @param el `HTMLElement` that's being resized\r\n   * @param distance Distance from the V edges to start scrolling\r\n   */\r\n  static updateScrollResize(event: MouseEvent, el: HTMLElement, distance: number): void {\r\n    const scrollEl = this.getScrollElement(el);\r\n    const height = scrollEl.clientHeight;\r\n    // #1727 event.clientY is relative to viewport, so must compare this against position of scrollEl getBoundingClientRect().top\r\n    // #1745 Special situation if scrollEl is document 'html': here browser spec states that\r\n    // clientHeight is height of viewport, but getBoundingClientRect() is rectangle of html element;\r\n    // this discrepancy arises because in reality scrollbar is attached to viewport, not html element itself.\r\n    const offsetTop = (scrollEl === this.getScrollElement()) ? 0 : scrollEl.getBoundingClientRect().top;\r\n    const pointerPosY = event.clientY - offsetTop;\r\n    const top = pointerPosY < distance;\r\n    const bottom = pointerPosY > height - distance;\r\n\r\n    if (top) {\r\n      // This also can be done with a timeout to keep scrolling while the mouse is\r\n      // in the scrolling zone. (will have smoother behavior)\r\n      scrollEl.scrollBy({ behavior: 'smooth', top: pointerPosY - distance});\r\n    } else if (bottom) {\r\n      scrollEl.scrollBy({ behavior: 'smooth', top: distance - (height - pointerPosY)});\r\n    }\r\n  }\r\n\r\n  /** single level clone, returning a new object with same top fields. This will share sub objects and arrays */\r\n  static clone<T>(obj: T): T {\r\n    if (obj === null || obj === undefined || typeof(obj) !== 'object') {\r\n      return obj;\r\n    }\r\n    // return Object.assign({}, obj);\r\n    if (obj instanceof Array) {\r\n      // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n      return [...obj] as any;\r\n    }\r\n    return {...obj};\r\n  }\r\n\r\n  /**\r\n   * Recursive clone version that returns a full copy, checking for nested objects and arrays ONLY.\r\n   * Note: this will use as-is any key starting with double __ (and not copy inside) some lib have circular dependencies.\r\n   */\r\n  static cloneDeep<T>(obj: T): T {\r\n    // list of fields we will skip during cloneDeep (nested objects, other internal)\r\n    const skipFields = ['parentGrid', 'el', 'grid', 'subGrid', 'engine'];\r\n    // return JSON.parse(JSON.stringify(obj)); // doesn't work with date format ?\r\n    const ret = Utils.clone(obj);\r\n    for (const key in ret) {\r\n      // NOTE: we don't support function/circular dependencies so skip those properties for now...\r\n      if (ret.hasOwnProperty(key) && typeof(ret[key]) === 'object' && key.substring(0, 2) !== '__' && !skipFields.find(k => k === key)) {\r\n        ret[key] = Utils.cloneDeep(obj[key]);\r\n      }\r\n    }\r\n    return ret;\r\n  }\r\n\r\n  /** deep clone the given HTML node, removing teh unique id field */\r\n  public static cloneNode(el: HTMLElement): HTMLElement {\r\n    const node = el.cloneNode(true) as HTMLElement;\r\n    node.removeAttribute('id');\r\n    return node;\r\n  }\r\n\r\n  public static appendTo(el: HTMLElement, parent: string | HTMLElement): void {\r\n    let parentNode: HTMLElement;\r\n    if (typeof parent === 'string') {\r\n      parentNode = Utils.getElement(parent);\r\n    } else {\r\n      parentNode = parent;\r\n    }\r\n    if (parentNode) {\r\n      parentNode.appendChild(el);\r\n    }\r\n  }\r\n\r\n  // public static setPositionRelative(el: HTMLElement): void {\r\n  //   if (!(/^(?:r|a|f)/).test(getComputedStyle(el).position)) {\r\n  //     el.style.position = \"relative\";\r\n  //   }\r\n  // }\r\n\r\n  public static addElStyles(el: HTMLElement, styles: { [prop: string]: string | string[] }): void {\r\n    if (styles instanceof Object) {\r\n      for (const s in styles) {\r\n        if (styles.hasOwnProperty(s)) {\r\n          if (Array.isArray(styles[s])) {\r\n            // support fallback value\r\n            (styles[s] as string[]).forEach(val => {\r\n              el.style[s] = val;\r\n            });\r\n          } else {\r\n            el.style[s] = styles[s];\r\n          }\r\n        }\r\n      }\r\n    }\r\n  }\r\n\r\n  public static initEvent<T>(e: DragEvent | MouseEvent, info: { type: string; target?: EventTarget }): T {\r\n    const evt = { type: info.type };\r\n    const obj = {\r\n      button: 0,\r\n      which: 0,\r\n      buttons: 1,\r\n      bubbles: true,\r\n      cancelable: true,\r\n      target: info.target ? info.target : e.target\r\n    };\r\n    ['altKey','ctrlKey','metaKey','shiftKey'].forEach(p => evt[p] = e[p]); // keys\r\n    ['pageX','pageY','clientX','clientY','screenX','screenY'].forEach(p => evt[p] = e[p]); // point info\r\n    return {...evt, ...obj} as unknown as T;\r\n  }\r\n\r\n  /** copies the MouseEvent (or convert Touch) properties and sends it as another event to the given target */\r\n  public static simulateMouseEvent(e: MouseEvent | Touch, simulatedType: string, target?: EventTarget): void {\r\n    const me = e as MouseEvent;\r\n    const simulatedEvent = new MouseEvent(simulatedType, {\r\n      bubbles: true,\r\n      composed: true,\r\n      cancelable: true,\r\n      view: window,\r\n      detail: 1,\r\n      screenX: e.screenX,\r\n      screenY: e.screenY,\r\n      clientX: e.clientX,\r\n      clientY: e.clientY,\r\n      ctrlKey: me.ctrlKey??false,\r\n      altKey: me.altKey??false,\r\n      shiftKey: me.shiftKey??false,\r\n      metaKey: me.metaKey??false,\r\n      button: 0,\r\n      relatedTarget: e.target\r\n    });\r\n\r\n    (target || e.target).dispatchEvent(simulatedEvent);\r\n  }\r\n\r\n  /**\r\n   * defines an element that is used to get the offset and scale from grid transforms\r\n   * returns the scale and offsets from said element\r\n  */\r\n  public static getValuesFromTransformedElement(parent: HTMLElement): DragTransform {\r\n    const transformReference = document.createElement('div');\r\n    Utils.addElStyles(transformReference, {\r\n      opacity: '0',\r\n      position: 'fixed',\r\n      top: 0 + 'px',\r\n      left: 0 + 'px',\r\n      width: '1px',\r\n      height: '1px',\r\n      zIndex: '-999999',\r\n    });\r\n    parent.appendChild(transformReference);\r\n    const transformValues = transformReference.getBoundingClientRect();\r\n    parent.removeChild(transformReference);\r\n    transformReference.remove();\r\n    return {\r\n      xScale: 1 / transformValues.width,\r\n      yScale: 1 / transformValues.height,\r\n      xOffset: transformValues.left,\r\n      yOffset: transformValues.top,\r\n    }\r\n  }\r\n\r\n  /** swap the given object 2 field values */\r\n  public static swap(o: unknown, a: string, b: string): void {\r\n    if (!o) return;\r\n    const tmp = o[a]; o[a] = o[b]; o[b] = tmp;\r\n  }\r\n\r\n  /** returns true if event is inside the given element rectangle */\r\n  // Note: Safari Mac has null event.relatedTarget which causes #1684 so check if DragEvent is inside the coordinates instead\r\n  //    this.el.contains(event.relatedTarget as HTMLElement)\r\n  // public static inside(e: MouseEvent, el: HTMLElement): boolean {\r\n  //   // srcElement, toElement, target: all set to placeholder when leaving simple grid, so we can't use that (Chrome)\r\n  //   const target: HTMLElement = e.relatedTarget || (e as any).fromElement;\r\n  //   if (!target) {\r\n  //     const { bottom, left, right, top } = el.getBoundingClientRect();\r\n  //     return (e.x < right && e.x > left && e.y < bottom && e.y > top);\r\n  //   }\r\n  //   return el.contains(target);\r\n  // }\r\n\r\n  /** true if the item can be rotated (checking for prop, not space available) */\r\n  public static canBeRotated(n: GridStackNode): boolean {\r\n    return !(!n || n.w === n.h || n.locked || n.noResize || n.grid?.opts.disableResize || (n.minW && n.minW === n.maxW) || (n.minH && n.minH === n.maxH));\r\n  }\r\n}","/**\n * gridstack-engine.ts 12.1.2\n * Copyright (c) 2021-2024  Alain Dumesny - see GridStack root license\n */\n\nimport { Utils } from './utils';\nimport { GridStackNode, ColumnOptions, GridStackPosition, GridStackMoveOpts, SaveFcn, CompactOptions } from './types';\n\n/** callback to update the DOM attributes since this class is generic (no HTML or other info) for items that changed - see _notify() */\ntype OnChangeCB = (nodes: GridStackNode[]) => void;\n\n/** options used during creation - similar to GridStackOptions */\nexport interface GridStackEngineOptions {\n  column?: number;\n  maxRow?: number;\n  float?: boolean;\n  nodes?: GridStackNode[];\n  onChange?: OnChangeCB;\n}\n\n/**\n * Defines the GridStack engine that does most no DOM grid manipulation.\n * See GridStack methods and vars for descriptions.\n *\n * NOTE: values should not be modified directly - call the main GridStack API instead\n */\nexport class GridStackEngine {\n  public column: number;\n  public maxRow: number;\n  public nodes: GridStackNode[];\n  public addedNodes: GridStackNode[] = [];\n  public removedNodes: GridStackNode[] = [];\n  public batchMode: boolean;\n  public defaultColumn = 12;\n  /** @internal callback to update the DOM attributes */\n  protected onChange: OnChangeCB;\n  /** @internal */\n  protected _float: boolean;\n  /** @internal */\n  protected _prevFloat: boolean;\n  /** @internal cached layouts of difference column count so we can restore back (eg 12 -> 1 -> 12) */\n  protected _layouts?: GridStackNode[][]; // maps column # to array of values nodes\n  /** @internal set during loading (which is sorted) so item gets added AFTER collision nodes */\n  public _loading?: boolean\n  /** @internal true while we are resizing widgets during column resize to skip certain parts */\n  protected _inColumnResize?: boolean;\n  /** true when grid.load() already cached the layout and can skip out of bound caching info */\n  public skipCacheUpdate?: boolean;\n  /** @internal true if we have some items locked */\n  protected _hasLocked: boolean;\n  /** @internal unique global internal _id counter */\n  public static _idSeq = 0;\n\n  public constructor(opts: GridStackEngineOptions = {}) {\n    this.column = opts.column || this.defaultColumn;\n    if (this.column > this.defaultColumn) this.defaultColumn = this.column;\n    this.maxRow = opts.maxRow;\n    this._float = opts.float;\n    this.nodes = opts.nodes || [];\n    this.onChange = opts.onChange;\n  }\n\n  public batchUpdate(flag = true, doPack = true): GridStackEngine {\n    if (!!this.batchMode === flag) return this;\n    this.batchMode = flag;\n    if (flag) {\n      this._prevFloat = this._float;\n      this._float = true; // let things go anywhere for now... will restore and possibly reposition later\n      this.cleanNodes();\n      this.saveInitial(); // since begin update (which is called multiple times) won't do this\n    } else {\n      this._float = this._prevFloat;\n      delete this._prevFloat;\n      if (doPack) this._packNodes();\n      this._notify();\n    }\n    return this;\n  }\n\n  // use entire row for hitting area (will use bottom reverse sorted first) if we not actively moving DOWN and didn't already skip\n  protected _useEntireRowArea(node: GridStackNode, nn: GridStackPosition): boolean {\n    return (!this.float || this.batchMode && !this._prevFloat) && !this._hasLocked && (!node._moving || node._skipDown || nn.y <= node.y);\n  }\n\n  /** @internal fix collision on given 'node', going to given new location 'nn', with optional 'collide' node already found.\n   * return true if we moved. */\n  protected _fixCollisions(node: GridStackNode, nn = node, collide?: GridStackNode, opt: GridStackMoveOpts = {}): boolean {\n    this.sortNodes(-1); // from last to first, so recursive collision move items in the right order\n\n    collide = collide || this.collide(node, nn); // REAL area collide for swap and skip if none...\n    if (!collide) return false;\n\n    // swap check: if we're actively moving in gravity mode, see if we collide with an object the same size\n    if (node._moving && !opt.nested && !this.float) {\n      if (this.swap(node, collide)) return true;\n    }\n\n    // during while() collisions MAKE SURE to check entire row so larger items don't leap frog small ones (push them all down starting last in grid)\n    let area = nn;\n    if (!this._loading && this._useEntireRowArea(node, nn)) {\n      area = {x: 0, w: this.column, y: nn.y, h: nn.h};\n      collide = this.collide(node, area, opt.skip); // force new hit\n    }\n\n    let didMove = false;\n    const newOpt: GridStackMoveOpts = {nested: true, pack: false};\n    let counter = 0;\n    while (collide = collide || this.collide(node, area, opt.skip)) { // could collide with more than 1 item... so repeat for each\n      if (counter++ > this.nodes.length * 2) {\n        throw new Error(\"Infinite collide check\");\n      }\n      let moved: boolean;\n      // if colliding with a locked item OR loading (move after) OR moving down with top gravity (and collide could move up) -> skip past the collide,\n      // but remember that skip down so we only do this once (and push others otherwise).\n      if (collide.locked || this._loading || node._moving && !node._skipDown && nn.y > node.y && !this.float &&\n        // can take space we had, or before where we're going\n        (!this.collide(collide, {...collide, y: node.y}, node) || !this.collide(collide, {...collide, y: nn.y - collide.h}, node))) {\n\n        node._skipDown = (node._skipDown || nn.y > node.y);\n        const newNN = {...nn, y: collide.y + collide.h, ...newOpt};\n        // pretent we moved to where we are now so we can continue any collision checks #2492\n        moved = this._loading && Utils.samePos(node, newNN) ? true : this.moveNode(node, newNN);\n\n        if ((collide.locked || this._loading) && moved) {\n          Utils.copyPos(nn, node); // moving after lock become our new desired location\n        } else if (!collide.locked && moved && opt.pack) {\n          // we moved after and will pack: do it now and keep the original drop location, but past the old collide to see what else we might push way\n          this._packNodes();\n          nn.y = collide.y + collide.h;\n          Utils.copyPos(node, nn);\n        }\n        didMove = didMove || moved;\n      } else {\n        // move collide down *after* where we will be, ignoring where we are now (don't collide with us)\n        moved = this.moveNode(collide, {...collide, y: nn.y + nn.h, skip: node, ...newOpt});\n      }\n\n      if (!moved) return didMove; // break inf loop if we couldn't move after all (ex: maxRow, fixed)\n\n      collide = undefined;\n    }\n    return didMove;\n  }\n\n  /** return the nodes that intercept the given node. Optionally a different area can be used, as well as a second node to skip */\n  public collide(skip: GridStackNode, area = skip, skip2?: GridStackNode): GridStackNode | undefined {\n    const skipId = skip._id;\n    const skip2Id = skip2?._id;\n    return this.nodes.find(n => n._id !== skipId && n._id !== skip2Id && Utils.isIntercepted(n, area));\n  }\n  public collideAll(skip: GridStackNode, area = skip, skip2?: GridStackNode): GridStackNode[] {\n    const skipId = skip._id;\n    const skip2Id = skip2?._id;\n    return this.nodes.filter(n => n._id !== skipId && n._id !== skip2Id && Utils.isIntercepted(n, area));\n  }\n\n  /** does a pixel coverage collision based on where we started, returning the node that has the most coverage that is >50% mid line */\n  protected directionCollideCoverage(node: GridStackNode, o: GridStackMoveOpts, collides: GridStackNode[]): GridStackNode | undefined {\n    if (!o.rect || !node._rect) return;\n    const r0 = node._rect; // where started\n    const r = {...o.rect}; // where we are\n\n    // update dragged rect to show where it's coming from (above or below, etc...)\n    if (r.y > r0.y) {\n      r.h += r.y - r0.y;\n      r.y = r0.y;\n    } else {\n      r.h += r0.y - r.y;\n    }\n    if (r.x > r0.x) {\n      r.w += r.x - r0.x;\n      r.x = r0.x;\n    } else {\n      r.w += r0.x - r.x;\n    }\n\n    let collide: GridStackNode;\n    let overMax = 0.5; // need >50%\n    for (let n of collides) {\n      if (n.locked || !n._rect) {\n        break;\n      }\n      const r2 = n._rect; // overlapping target\n      let yOver = Number.MAX_VALUE, xOver = Number.MAX_VALUE;\n      // depending on which side we started from, compute the overlap % of coverage\n      // (ex: from above/below we only compute the max horizontal line coverage)\n      if (r0.y < r2.y) { // from above\n        yOver = ((r.y + r.h) - r2.y) / r2.h;\n      } else if (r0.y + r0.h > r2.y + r2.h) { // from below\n        yOver = ((r2.y + r2.h) - r.y) / r2.h;\n      }\n      if (r0.x < r2.x) { // from the left\n        xOver = ((r.x + r.w) - r2.x) / r2.w;\n      } else if (r0.x + r0.w > r2.x + r2.w) { // from the right\n        xOver = ((r2.x + r2.w) - r.x) / r2.w;\n      }\n      const over = Math.min(xOver, yOver);\n      if (over > overMax) {\n        overMax = over;\n        collide = n;\n      }\n    }\n    o.collide = collide; // save it so we don't have to find it again\n    return collide;\n  }\n\n  /** does a pixel coverage returning the node that has the most coverage by area */\n  /*\n  protected collideCoverage(r: GridStackPosition, collides: GridStackNode[]): {collide: GridStackNode, over: number} {\n    const collide: GridStackNode;\n    const overMax = 0;\n    collides.forEach(n => {\n      if (n.locked || !n._rect) return;\n      const over = Utils.areaIntercept(r, n._rect);\n      if (over > overMax) {\n        overMax = over;\n        collide = n;\n      }\n    });\n    return {collide, over: overMax};\n  }\n  */\n\n  /** called to cache the nodes pixel rectangles used for collision detection during drag */\n  public cacheRects(w: number, h: number, top: number, right: number, bottom: number, left: number): GridStackEngine\n  {\n    this.nodes.forEach(n =>\n      n._rect = {\n        y: n.y * h + top,\n        x: n.x * w + left,\n        w: n.w * w - left - right,\n        h: n.h * h - top - bottom\n      }\n    );\n    return this;\n  }\n\n  /** called to possibly swap between 2 nodes (same size or column, not locked, touching), returning true if successful */\n  public swap(a: GridStackNode, b: GridStackNode): boolean | undefined {\n    if (!b || b.locked || !a || a.locked) return false;\n\n    function _doSwap(): true { // assumes a is before b IFF they have different height (put after rather than exact swap)\n      const x = b.x, y = b.y;\n      b.x = a.x; b.y = a.y; // b -> a position\n      if (a.h != b.h) {\n        a.x = x; a.y = b.y + b.h; // a -> goes after b\n      } else if (a.w != b.w) {\n        a.x = b.x + b.w; a.y = y; // a -> goes after b\n      } else {\n        a.x = x; a.y = y; // a -> old b position\n      }\n      a._dirty = b._dirty = true;\n      return true;\n    }\n    let touching: boolean; // remember if we called it (vs undefined)\n\n    // same size and same row or column, and touching\n    if (a.w === b.w && a.h === b.h && (a.x === b.x || a.y === b.y) && (touching = Utils.isTouching(a, b)))\n      return _doSwap();\n    if (touching === false) return; // IFF ran test and fail, bail out\n\n    // check for taking same columns (but different height) and touching\n    if (a.w === b.w && a.x === b.x && (touching || (touching = Utils.isTouching(a, b)))) {\n      if (b.y < a.y) { const t = a; a = b; b = t; } // swap a <-> b vars so a is first\n      return _doSwap();\n    }\n    if (touching === false) return;\n\n    // check if taking same row (but different width) and touching\n    if (a.h === b.h && a.y === b.y && (touching || (touching = Utils.isTouching(a, b)))) {\n      if (b.x < a.x) { const t = a; a = b; b = t; } // swap a <-> b vars so a is first\n      return _doSwap();\n    }\n    return false;\n  }\n\n  public isAreaEmpty(x: number, y: number, w: number, h: number): boolean {\n    const nn: GridStackNode = {x: x || 0, y: y || 0, w: w || 1, h: h || 1};\n    return !this.collide(nn);\n  }\n\n  /** re-layout grid items to reclaim any empty space - optionally keeping the sort order exactly the same ('list' mode) vs truly finding an empty spaces */\n  public compact(layout: CompactOptions = 'compact', doSort = true): GridStackEngine {\n    if (this.nodes.length === 0) return this;\n    if (doSort) this.sortNodes();\n    const wasBatch = this.batchMode;\n    if (!wasBatch) this.batchUpdate();\n    const wasColumnResize = this._inColumnResize;\n    if (!wasColumnResize) this._inColumnResize = true; // faster addNode()\n    const copyNodes = this.nodes;\n    this.nodes = []; // pretend we have no nodes to conflict layout to start with...\n    copyNodes.forEach((n, index, list) => {\n      let after: GridStackNode;\n      if (!n.locked) {\n        n.autoPosition = true;\n        if (layout === 'list' && index) after = list[index - 1];\n      }\n      this.addNode(n, false, after); // 'false' for add event trigger\n    });\n    if (!wasColumnResize) delete this._inColumnResize;\n    if (!wasBatch) this.batchUpdate(false);\n    return this;\n  }\n\n  /** enable/disable floating widgets (default: `false`) See [example](http://gridstackjs.com/demo/float.html) */\n  public set float(val: boolean) {\n    if (this._float === val) return;\n    this._float = val || false;\n    if (!val) {\n      this._packNodes()._notify();\n    }\n  }\n\n  /** float getter method */\n  public get float(): boolean { return this._float || false; }\n\n  /** sort the nodes array from first to last, or reverse. Called during collision/placement to force an order */\n  public sortNodes(dir: 1 | -1 = 1): GridStackEngine {\n    this.nodes = Utils.sort(this.nodes, dir);\n    return this;\n  }\n\n  /** @internal called to top gravity pack the items back OR revert back to original Y positions when floating */\n  protected _packNodes(): GridStackEngine {\n    if (this.batchMode) { return this; }\n    this.sortNodes(); // first to last\n\n    if (this.float) {\n      // restore original Y pos\n      this.nodes.forEach(n => {\n        if (n._updating || n._orig === undefined || n.y === n._orig.y) return;\n        let newY = n.y;\n        while (newY > n._orig.y) {\n          --newY;\n          const collide = this.collide(n, {x: n.x, y: newY, w: n.w, h: n.h});\n          if (!collide) {\n            n._dirty = true;\n            n.y = newY;\n          }\n        }\n      });\n    } else {\n      // top gravity pack\n      this.nodes.forEach((n, i) => {\n        if (n.locked) return;\n        while (n.y > 0) {\n          const newY = i === 0 ? 0 : n.y - 1;\n          const canBeMoved = i === 0 || !this.collide(n, {x: n.x, y: newY, w: n.w, h: n.h});\n          if (!canBeMoved) break;\n          // Note: must be dirty (from last position) for GridStack::OnChange CB to update positions\n          // and move items back. The user 'change' CB should detect changes from the original\n          // starting position instead.\n          n._dirty = (n.y !== newY);\n          n.y = newY;\n        }\n      });\n    }\n    return this;\n  }\n\n  /**\n   * given a random node, makes sure it's coordinates/values are valid in the current grid\n   * @param node to adjust\n   * @param resizing if out of bound, resize down or move into the grid to fit ?\n   */\n  public prepareNode(node: GridStackNode, resizing?: boolean): GridStackNode {\n    node._id = node._id ?? GridStackEngine._idSeq++;\n\n    // make sure USER supplied id are unique in our list, else assign a new one as it will create issues during load/update/etc...\n    const id = node.id;\n    if (id) {\n      let count = 1; // append nice _n rather than some random number\n      while (this.nodes.find(n => n.id === node.id && n !== node)) {\n        node.id = id + '_' + (count++);\n      }\n    }\n\n    // if we're missing position, have the grid position us automatically (before we set them to 0,0)\n    if (node.x === undefined || node.y === undefined || node.x === null || node.y === null) {\n      node.autoPosition = true;\n    }\n\n    // assign defaults for missing required fields\n    const defaults: GridStackNode = { x: 0, y: 0, w: 1, h: 1};\n    Utils.defaults(node, defaults);\n\n    if (!node.autoPosition) { delete node.autoPosition; }\n    if (!node.noResize) { delete node.noResize; }\n    if (!node.noMove) { delete node.noMove; }\n    Utils.sanitizeMinMax(node);\n\n    // check for NaN (in case messed up strings were passed. can't do parseInt() || defaults.x above as 0 is valid #)\n    if (typeof node.x == 'string') { node.x = Number(node.x); }\n    if (typeof node.y == 'string') { node.y = Number(node.y); }\n    if (typeof node.w == 'string') { node.w = Number(node.w); }\n    if (typeof node.h == 'string') { node.h = Number(node.h); }\n    if (isNaN(node.x)) { node.x = defaults.x; node.autoPosition = true; }\n    if (isNaN(node.y)) { node.y = defaults.y; node.autoPosition = true; }\n    if (isNaN(node.w)) { node.w = defaults.w; }\n    if (isNaN(node.h)) { node.h = defaults.h; }\n\n    this.nodeBoundFix(node, resizing);\n    return node;\n  }\n\n  /** part2 of preparing a node to fit inside our grid - checks for x,y,w from grid dimensions */\n  public nodeBoundFix(node: GridStackNode, resizing?: boolean): GridStackEngine {\n\n    const before = node._orig || Utils.copyPos({}, node);\n\n    if (node.maxW) { node.w = Math.min(node.w || 1, node.maxW); }\n    if (node.maxH) { node.h = Math.min(node.h || 1, node.maxH); }\n    if (node.minW) { node.w = Math.max(node.w || 1, node.minW); }\n    if (node.minH) { node.h = Math.max(node.h || 1, node.minH); }\n\n    // if user loaded a larger than allowed widget for current # of columns,\n    // remember it's position & width so we can restore back (1 -> 12 column) #1655 #1985\n    // IFF we're not in the middle of column resizing!\n    const saveOrig = (node.x || 0) + (node.w || 1) > this.column;\n    if (saveOrig && this.column < this.defaultColumn && !this._inColumnResize && !this.skipCacheUpdate && node._id && this.findCacheLayout(node, this.defaultColumn) === -1) {\n      const copy = {...node}; // need _id + positions\n      if (copy.autoPosition || copy.x === undefined) { delete copy.x; delete copy.y; }\n      else copy.x = Math.min(this.defaultColumn - 1, copy.x);\n      copy.w = Math.min(this.defaultColumn, copy.w || 1);\n      this.cacheOneLayout(copy, this.defaultColumn);\n    }\n\n    if (node.w > this.column) {\n      node.w = this.column;\n    } else if (node.w < 1) {\n      node.w = 1;\n    }\n\n    if (this.maxRow && node.h > this.maxRow) {\n      node.h = this.maxRow;\n    } else if (node.h < 1) {\n      node.h = 1;\n    }\n\n    if (node.x < 0) {\n      node.x = 0;\n    }\n    if (node.y < 0) {\n      node.y = 0;\n    }\n\n    if (node.x + node.w > this.column) {\n      if (resizing) {\n        node.w = this.column - node.x;\n      } else {\n        node.x = this.column - node.w;\n      }\n    }\n    if (this.maxRow && node.y + node.h > this.maxRow) {\n      if (resizing) {\n        node.h = this.maxRow - node.y;\n      } else {\n        node.y = this.maxRow - node.h;\n      }\n    }\n\n    if (!Utils.samePos(node, before)) {\n      node._dirty = true;\n    }\n\n    return this;\n  }\n\n  /** returns a list of modified nodes from their original values */\n  public getDirtyNodes(verify?: boolean): GridStackNode[] {\n    // compare original x,y,w,h instead as _dirty can be a temporary state\n    if (verify) {\n      return this.nodes.filter(n => n._dirty && !Utils.samePos(n, n._orig));\n    }\n    return this.nodes.filter(n => n._dirty);\n  }\n\n  /** @internal call this to call onChange callback with dirty nodes so DOM can be updated */\n  protected _notify(removedNodes?: GridStackNode[]): GridStackEngine {\n    if (this.batchMode || !this.onChange) return this;\n    const dirtyNodes = (removedNodes || []).concat(this.getDirtyNodes());\n    this.onChange(dirtyNodes);\n    return this;\n  }\n\n  /** @internal remove dirty and last tried info */\n  public cleanNodes(): GridStackEngine {\n    if (this.batchMode) return this;\n    this.nodes.forEach(n => {\n      delete n._dirty;\n      delete n._lastTried;\n    });\n    return this;\n  }\n\n  /** @internal called to save initial position/size to track real dirty state.\n   * Note: should be called right after we call change event (so next API is can detect changes)\n   * as well as right before we start move/resize/enter (so we can restore items to prev values) */\n  public saveInitial(): GridStackEngine {\n    this.nodes.forEach(n => {\n      n._orig = Utils.copyPos({}, n);\n      delete n._dirty;\n    });\n    this._hasLocked = this.nodes.some(n => n.locked);\n    return this;\n  }\n\n  /** @internal restore all the nodes back to initial values (called when we leave) */\n  public restoreInitial(): GridStackEngine {\n    this.nodes.forEach(n => {\n      if (!n._orig || Utils.samePos(n, n._orig)) return;\n      Utils.copyPos(n, n._orig);\n      n._dirty = true;\n    });\n    this._notify();\n    return this;\n  }\n\n  /** find the first available empty spot for the given node width/height, updating the x,y attributes. return true if found.\n   * optionally you can pass your own existing node list and column count, otherwise defaults to that engine data.\n   * Optionally pass a widget to start search AFTER, meaning the order will remain the same but possibly have empty slots we skipped\n   */\n  public findEmptyPosition(node: GridStackNode, nodeList = this.nodes, column = this.column, after?: GridStackNode): boolean {\n    const start = after ? after.y * column + (after.x + after.w) : 0;\n    let found = false;\n    for (let i = start; !found; ++i) {\n      const x = i % column;\n      const y = Math.floor(i / column);\n      if (x + node.w > column) {\n        continue;\n      }\n      const box = {x, y, w: node.w, h: node.h};\n      if (!nodeList.find(n => Utils.isIntercepted(box, n))) {\n        if (node.x !== x || node.y !== y) node._dirty = true;\n        node.x = x;\n        node.y = y;\n        delete node.autoPosition;\n        found = true;\n      }\n    }\n    return found;\n  }\n\n  /** call to add the given node to our list, fixing collision and re-packing */\n  public addNode(node: GridStackNode, triggerAddEvent = false, after?: GridStackNode): GridStackNode {\n    const dup = this.nodes.find(n => n._id === node._id);\n    if (dup) return dup; // prevent inserting twice! return it instead.\n\n    // skip prepareNode if we're in middle of column resize (not new) but do check for bounds!\n    this._inColumnResize ? this.nodeBoundFix(node) : this.prepareNode(node);\n    delete node._temporaryRemoved;\n    delete node._removeDOM;\n\n    let skipCollision: boolean;\n    if (node.autoPosition && this.findEmptyPosition(node, this.nodes, this.column, after)) {\n      delete node.autoPosition; // found our slot\n      skipCollision = true;\n    }\n\n    this.nodes.push(node);\n    if (triggerAddEvent) { this.addedNodes.push(node); }\n\n    if (!skipCollision) this._fixCollisions(node);\n    if (!this.batchMode) { this._packNodes()._notify(); }\n    return node;\n  }\n\n  public removeNode(node: GridStackNode, removeDOM = true, triggerEvent = false): GridStackEngine {\n    if (!this.nodes.find(n => n._id === node._id)) {\n      // TEST console.log(`Error: GridStackEngine.removeNode() node._id=${node._id} not found!`)\n      return this;\n    }\n    if (triggerEvent) { // we wait until final drop to manually track removed items (rather than during drag)\n      this.removedNodes.push(node);\n    }\n    if (removeDOM) node._removeDOM = true; // let CB remove actual HTML (used to set _id to null, but then we loose layout info)\n    // don't use 'faster' .splice(findIndex(),1) in case node isn't in our list, or in multiple times.\n    this.nodes = this.nodes.filter(n => n._id !== node._id);\n    if (!node._isAboutToRemove) this._packNodes(); // if dragged out, no need to relayout as already done...\n    this._notify([node]);\n    return this;\n  }\n\n  public removeAll(removeDOM = true, triggerEvent = true): GridStackEngine {\n    delete this._layouts;\n    if (!this.nodes.length) return this;\n    removeDOM && this.nodes.forEach(n => n._removeDOM = true); // let CB remove actual HTML (used to set _id to null, but then we loose layout info)\n    const removedNodes = this.nodes;\n    this.removedNodes = triggerEvent ? removedNodes : [];\n    this.nodes = [];\n    return this._notify(removedNodes);\n  }\n\n  /** checks if item can be moved (layout constrain) vs moveNode(), returning true if was able to move.\n   * In more complicated cases (maxRow) it will attempt at moving the item and fixing\n   * others in a clone first, then apply those changes if still within specs. */\n  public moveNodeCheck(node: GridStackNode, o: GridStackMoveOpts): boolean {\n    // if (node.locked) return false;\n    if (!this.changedPosConstrain(node, o)) return false;\n    o.pack = true;\n\n    // simpler case: move item directly...\n    if (!this.maxRow) {\n      return this.moveNode(node, o);\n    }\n\n    // complex case: create a clone with NO maxRow (will check for out of bounds at the end)\n    let clonedNode: GridStackNode;\n    const clone = new GridStackEngine({\n      column: this.column,\n      float: this.float,\n      nodes: this.nodes.map(n => {\n        if (n._id === node._id) {\n          clonedNode = {...n};\n          return clonedNode;\n        }\n        return {...n};\n      })\n    });\n    if (!clonedNode) return false;\n\n    // check if we're covering 50% collision and could move, while still being under maxRow or at least not making it worse\n    // (case where widget was somehow added past our max #2449)\n    const canMove = clone.moveNode(clonedNode, o) && clone.getRow() <= Math.max(this.getRow(), this.maxRow);\n    // else check if we can force a swap (float=true, or different shapes) on non-resize\n    if (!canMove && !o.resizing && o.collide) {\n      const collide = o.collide.el.gridstackNode; // find the source node the clone collided with at 50%\n      if (this.swap(node, collide)) { // swaps and mark dirty\n        this._notify();\n        return true;\n      }\n    }\n    if (!canMove) return false;\n\n    // if clone was able to move, copy those mods over to us now instead of caller trying to do this all over!\n    // Note: we can't use the list directly as elements and other parts point to actual node, so copy content\n    clone.nodes.filter(n => n._dirty).forEach(c => {\n      const n = this.nodes.find(a => a._id === c._id);\n      if (!n) return;\n      Utils.copyPos(n, c);\n      n._dirty = true;\n    });\n    this._notify();\n    return true;\n  }\n\n  /** return true if can fit in grid height constrain only (always true if no maxRow) */\n  public willItFit(node: GridStackNode): boolean {\n    delete node._willFitPos;\n    if (!this.maxRow) return true;\n    // create a clone with NO maxRow and check if still within size\n    const clone = new GridStackEngine({\n      column: this.column,\n      float: this.float,\n      nodes: this.nodes.map(n => {return {...n}})\n    });\n    const n = {...node}; // clone node so we don't mod any settings on it but have full autoPosition and min/max as well! #1687\n    this.cleanupNode(n);\n    delete n.el; delete n._id; delete n.content; delete n.grid;\n    clone.addNode(n);\n    if (clone.getRow() <= this.maxRow) {\n      node._willFitPos = Utils.copyPos({}, n);\n      return true;\n    }\n    return false;\n  }\n\n  /** true if x,y or w,h are different after clamping to min/max */\n  public changedPosConstrain(node: GridStackNode, p: GridStackPosition): boolean {\n    // first make sure w,h are set for caller\n    p.w = p.w || node.w;\n    p.h = p.h || node.h;\n    if (node.x !== p.x || node.y !== p.y) return true;\n    // check constrained w,h\n    if (node.maxW) { p.w = Math.min(p.w, node.maxW); }\n    if (node.maxH) { p.h = Math.min(p.h, node.maxH); }\n    if (node.minW) { p.w = Math.max(p.w, node.minW); }\n    if (node.minH) { p.h = Math.max(p.h, node.minH); }\n    return (node.w !== p.w || node.h !== p.h);\n  }\n\n  /** return true if the passed in node was actually moved (checks for no-op and locked) */\n  public moveNode(node: GridStackNode, o: GridStackMoveOpts): boolean {\n    if (!node || /*node.locked ||*/ !o) return false;\n    let wasUndefinedPack: boolean;\n    if (o.pack === undefined && !this.batchMode) {\n      wasUndefinedPack = o.pack = true;\n    }\n\n    // constrain the passed in values and check if we're still changing our node\n    if (typeof o.x !== 'number') { o.x = node.x; }\n    if (typeof o.y !== 'number') { o.y = node.y; }\n    if (typeof o.w !== 'number') { o.w = node.w; }\n    if (typeof o.h !== 'number') { o.h = node.h; }\n    const resizing = (node.w !== o.w || node.h !== o.h);\n    const nn: GridStackNode = Utils.copyPos({}, node, true); // get min/max out first, then opt positions next\n    Utils.copyPos(nn, o);\n    this.nodeBoundFix(nn, resizing);\n    Utils.copyPos(o, nn);\n\n    if (!o.forceCollide && Utils.samePos(node, o)) return false;\n    const prevPos: GridStackPosition = Utils.copyPos({}, node);\n\n    // check if we will need to fix collision at our new location\n    const collides = this.collideAll(node, nn, o.skip);\n    let needToMove = true;\n    if (collides.length) {\n      const activeDrag = node._moving && !o.nested;\n      // check to make sure we actually collided over 50% surface area while dragging\n      let collide = activeDrag ? this.directionCollideCoverage(node, o, collides) : collides[0];\n      // if we're enabling creation of sub-grids on the fly, see if we're covering 80% of either one, if we didn't already do that\n      if (activeDrag && collide && node.grid?.opts?.subGridDynamic && !node.grid._isTemp) {\n        const over = Utils.areaIntercept(o.rect, collide._rect);\n        const a1 = Utils.area(o.rect);\n        const a2 = Utils.area(collide._rect);\n        const perc = over / (a1 < a2 ? a1 : a2);\n        if (perc > .8) {\n          collide.grid.makeSubGrid(collide.el, undefined, node);\n          collide = undefined;\n        }\n      }\n\n      if (collide) {\n        needToMove = !this._fixCollisions(node, nn, collide, o); // check if already moved...\n      } else {\n        needToMove = false; // we didn't cover >50% for a move, skip...\n        if (wasUndefinedPack) delete o.pack;\n      }\n    }\n\n    // now move (to the original ask vs the collision version which might differ) and repack things\n    if (needToMove && !Utils.samePos(node, nn)) {\n      node._dirty = true;\n      Utils.copyPos(node, nn);\n    }\n    if (o.pack) {\n      this._packNodes()\n        ._notify();\n    }\n    return !Utils.samePos(node, prevPos); // pack might have moved things back\n  }\n\n  public getRow(): number {\n    return this.nodes.reduce((row, n) => Math.max(row, n.y + n.h), 0);\n  }\n\n  public beginUpdate(node: GridStackNode): GridStackEngine {\n    if (!node._updating) {\n      node._updating = true;\n      delete node._skipDown;\n      if (!this.batchMode) this.saveInitial();\n    }\n    return this;\n  }\n\n  public endUpdate(): GridStackEngine {\n    const n = this.nodes.find(n => n._updating);\n    if (n) {\n      delete n._updating;\n      delete n._skipDown;\n    }\n    return this;\n  }\n\n  /** saves a copy of the largest column layout (eg 12 even when rendering oneColumnMode) so we don't loose orig layout,\n   * returning a list of widgets for serialization */\n  public save(saveElement = true, saveCB?: SaveFcn): GridStackNode[] {\n    // use the highest layout for any saved info so we can have full detail on reload #1849\n    const len = this._layouts?.length;\n    const layout = len && this.column !== (len - 1) ? this._layouts[len - 1] : null;\n    const list: GridStackNode[] = [];\n    this.sortNodes();\n    this.nodes.forEach(n => {\n      const wl = layout?.find(l => l._id === n._id);\n      // use layout info fields instead if set\n      const w: GridStackNode = {...n, ...(wl || {})};\n      Utils.removeInternalForSave(w, !saveElement);\n      if (saveCB) saveCB(n, w);\n      list.push(w);\n    });\n    return list;\n  }\n\n  /** @internal called whenever a node is added or moved - updates the cached layouts */\n  public layoutsNodesChange(nodes: GridStackNode[]): GridStackEngine {\n    if (!this._layouts || this._inColumnResize) return this;\n    // remove smaller layouts - we will re-generate those on the fly... larger ones need to update\n    this._layouts.forEach((layout, column) => {\n      if (!layout || column === this.column) return this;\n      if (column < this.column) {\n        this._layouts[column] = undefined;\n      }\n      else {\n        // we save the original x,y,w (h isn't cached) to see what actually changed to propagate better.\n        // NOTE: we don't need to check against out of bound scaling/moving as that will be done when using those cache values. #1785\n        const ratio = column / this.column;\n        nodes.forEach(node => {\n          if (!node._orig) return; // didn't change (newly added ?)\n          const n = layout.find(l => l._id === node._id);\n          if (!n) return; // no cache for new nodes. Will use those values.\n          // Y changed, push down same amount\n          // TODO: detect doing item 'swaps' will help instead of move (especially in 1 column mode)\n          if (n.y >= 0 && node.y !== node._orig.y) {\n            n.y += (node.y - node._orig.y);\n          }\n          // X changed, scale from new position\n          if (node.x !== node._orig.x) {\n            n.x = Math.round(node.x * ratio);\n          }\n          // width changed, scale from new width\n          if (node.w !== node._orig.w) {\n            n.w = Math.round(node.w * ratio);\n          }\n          // ...height always carries over from cache\n        });\n      }\n    });\n    return this;\n  }\n\n  /**\n   * @internal Called to scale the widget width & position up/down based on the column change.\n   * Note we store previous layouts (especially original ones) to make it possible to go\n   * from say 12 -> 1 -> 12 and get back to where we were.\n   *\n   * @param prevColumn previous number of columns\n   * @param column  new column number\n   * @param layout specify the type of re-layout that will happen (position, size, etc...).\n   * Note: items will never be outside of the current column boundaries. default (moveScale). Ignored for 1 column\n   */\n  public columnChanged(prevColumn: number, column: number, layout: ColumnOptions = 'moveScale'): GridStackEngine {\n    if (!this.nodes.length || !column || prevColumn === column) return this;\n\n    // simpler shortcuts layouts\n    const doCompact = layout === 'compact' || layout === 'list';\n    if (doCompact) {\n      this.sortNodes(1); // sort with original layout once and only once (new column will affect order otherwise)\n    }\n\n    // cache the current layout in case they want to go back (like 12 -> 1 -> 12) as it requires original data IFF we're sizing down (see below)\n    if (column < prevColumn) this.cacheLayout(this.nodes, prevColumn);\n    this.batchUpdate(); // do this EARLY as it will call saveInitial() so we can detect where we started for _dirty and collision\n    let newNodes: GridStackNode[] = [];\n    let nodes = doCompact ? this.nodes : Utils.sort(this.nodes, -1); // current column reverse sorting so we can insert last to front (limit collision)\n\n    // see if we have cached previous layout IFF we are going up in size (restore) otherwise always\n    // generate next size down from where we are (looks more natural as you gradually size down).\n    if (column > prevColumn && this._layouts) {\n      const cacheNodes = this._layouts[column] || [];\n      // ...if not, start with the largest layout (if not already there) as down-scaling is more accurate\n      // by pretending we came from that larger column by assigning those values as starting point\n      const lastIndex = this._layouts.length - 1;\n      if (!cacheNodes.length && prevColumn !== lastIndex && this._layouts[lastIndex]?.length) {\n        prevColumn = lastIndex;\n        this._layouts[lastIndex].forEach(cacheNode => {\n          const n = nodes.find(n => n._id === cacheNode._id);\n          if (n) {\n            // still current, use cache info positions\n            if (!doCompact && !cacheNode.autoPosition) {\n              n.x = cacheNode.x ?? n.x;\n              n.y = cacheNode.y ?? n.y;\n            }\n            n.w = cacheNode.w ?? n.w;\n            if (cacheNode.x == undefined || cacheNode.y === undefined) n.autoPosition = true;\n          }\n        });\n      }\n\n      // if we found cache re-use those nodes that are still current\n      cacheNodes.forEach(cacheNode => {\n        const j = nodes.findIndex(n => n._id === cacheNode._id);\n        if (j !== -1) {\n          const n = nodes[j];\n          // still current, use cache info positions\n          if (doCompact) {\n            n.w = cacheNode.w; // only w is used, and don't trim the list\n            return;\n          }\n          if (cacheNode.autoPosition || isNaN(cacheNode.x) || isNaN(cacheNode.y)) {\n            this.findEmptyPosition(cacheNode, newNodes);\n          }\n          if (!cacheNode.autoPosition) {\n            n.x = cacheNode.x ?? n.x;\n            n.y = cacheNode.y ?? n.y;\n            n.w = cacheNode.w ?? n.w;\n            newNodes.push(n);\n          }\n          nodes.splice(j, 1);\n        }\n      });\n    }\n\n    // much simpler layout that just compacts\n    if (doCompact) {\n      this.compact(layout, false);\n    } else {\n      // ...and add any extra non-cached ones\n      if (nodes.length) {\n        if (typeof layout === 'function') {\n          layout(column, prevColumn, newNodes, nodes);\n        } else {\n          const ratio = (doCompact || layout === 'none') ? 1 : column / prevColumn;\n          const move = (layout === 'move' || layout === 'moveScale');\n          const scale = (layout === 'scale' || layout === 'moveScale');\n          nodes.forEach(node => {\n            // NOTE: x + w could be outside of the grid, but addNode() below will handle that\n            node.x = (column === 1 ? 0 : (move ? Math.round(node.x * ratio) : Math.min(node.x, column - 1)));\n            node.w = ((column === 1 || prevColumn === 1) ? 1 : scale ? (Math.round(node.w * ratio) || 1) : (Math.min(node.w, column)));\n            newNodes.push(node);\n          });\n          nodes = [];\n        }\n      }\n\n      // finally re-layout them in reverse order (to get correct placement)\n      newNodes = Utils.sort(newNodes, -1);\n      this._inColumnResize = true; // prevent cache update\n      this.nodes = []; // pretend we have no nodes to start with (add() will use same structures) to simplify layout\n      newNodes.forEach(node => {\n        this.addNode(node, false); // 'false' for add event trigger\n        delete node._orig; // make sure the commit doesn't try to restore things back to original\n      });\n    }\n\n    this.nodes.forEach(n => delete n._orig); // clear _orig before batch=false so it doesn't handle float=true restore\n    this.batchUpdate(false, !doCompact);\n    delete this._inColumnResize;\n    return this;\n  }\n\n  /**\n   * call to cache the given layout internally to the given location so we can restore back when column changes size\n   * @param nodes list of nodes\n   * @param column corresponding column index to save it under\n   * @param clear if true, will force other caches to be removed (default false)\n   */\n  public cacheLayout(nodes: GridStackNode[], column: number, clear = false): GridStackEngine {\n    const copy: GridStackNode[] = [];\n    nodes.forEach((n, i) => {\n      // make sure we have an id in case this is new layout, else re-use id already set\n      if (n._id === undefined) {\n        const existing = n.id ? this.nodes.find(n2 => n2.id === n.id) : undefined; // find existing node using users id\n        n._id = existing?._id ?? GridStackEngine._idSeq++;\n      }\n      copy[i] = {x: n.x, y: n.y, w: n.w, _id: n._id} // only thing we change is x,y,w and id to find it back\n    });\n    this._layouts = clear ? [] : this._layouts || []; // use array to find larger quick\n    this._layouts[column] = copy;\n    return this;\n  }\n\n  /**\n   * call to cache the given node layout internally to the given location so we can restore back when column changes size\n   * @param node single node to cache\n   * @param column corresponding column index to save it under\n   */\n  public cacheOneLayout(n: GridStackNode, column: number): GridStackEngine {\n    n._id = n._id ?? GridStackEngine._idSeq++;\n    const l: GridStackNode = {x: n.x, y: n.y, w: n.w, _id: n._id}\n    if (n.autoPosition || n.x === undefined) { delete l.x; delete l.y; if (n.autoPosition) l.autoPosition = true; }\n    this._layouts = this._layouts || [];\n    this._layouts[column] = this._layouts[column] || [];\n    const index = this.findCacheLayout(n, column);\n    if (index === -1)\n      this._layouts[column].push(l);\n    else\n      this._layouts[column][index] = l;\n    return this;\n  }\n\n  protected findCacheLayout(n: GridStackNode, column: number): number | undefined {\n    return this._layouts?.[column]?.findIndex(l => l._id === n._id) ?? -1;\n  }\n\n  public removeNodeFromLayoutCache(n: GridStackNode) {\n    if (!this._layouts) {\n      return;\n    }\n    for (let i = 0; i < this._layouts.length; i++) {\n      const index = this.findCacheLayout(n, i);\n      if (index !== -1) {\n        this._layouts[i].splice(index, 1);\n      }\n    }\n  }\n\n  /** called to remove all internal values but the _id */\n  public cleanupNode(node: GridStackNode): GridStackEngine {\n    for (const prop in node) {\n      if (prop[0] === '_' && prop !== '_id') delete node[prop];\n    }\n    return this;\n  }\n}\n","/**\r\n * types.ts 12.1.2\r\n * Copyright (c) 2021-2024 Alain Dumesny - see GridStack root license\r\n */\r\n\r\nimport { GridStack } from './gridstack';\r\nimport { GridStackEngine } from './gridstack-engine';\r\n\r\n// default values for grid options - used during init and when saving out\r\nexport const gridDefaults: GridStackOptions = {\r\n  alwaysShowResizeHandle: 'mobile',\r\n  animate: true,\r\n  auto: true,\r\n  cellHeight: 'auto',\r\n  cellHeightThrottle: 100,\r\n  cellHeightUnit: 'px',\r\n  column: 12,\r\n  draggable: { handle: '.grid-stack-item-content', appendTo: 'body', scroll: true },\r\n  handle: '.grid-stack-item-content',\r\n  itemClass: 'grid-stack-item',\r\n  margin: 10,\r\n  marginUnit: 'px',\r\n  maxRow: 0,\r\n  minRow: 0,\r\n  placeholderClass: 'grid-stack-placeholder',\r\n  placeholderText: '',\r\n  removableOptions: { accept: 'grid-stack-item', decline: 'grid-stack-non-removable'},\r\n  resizable: { handles: 'se' },\r\n  rtl: 'auto',\r\n\r\n  // **** same as not being set ****\r\n  // disableDrag: false,\r\n  // disableResize: false,\r\n  // float: false,\r\n  // handleClass: null,\r\n  // removable: false,\r\n  // staticGrid: false,\r\n  //removable\r\n};\r\n\r\n/**\r\n * different layout options when changing # of columns, including a custom function that takes new/old column count, and array of new/old positions\r\n * Note: new list may be partially already filled if we have a cache of the layout at that size and new items were added later.\r\n * Options are:\r\n * 'list' - treat items as sorted list, keeping items (un-sized unless too big for column count) sequentially reflowing them\r\n * 'compact' - similar to list, but using compact() method which will possibly re-order items if an empty slots are available due to a larger item needing to be pushed to next row\r\n * 'moveScale' - will scale and move items by the ratio new newColumnCount / oldColumnCount\r\n * 'move' | 'scale' - will only size or move items\r\n * 'none' will leave items unchanged, unless they don't fit in column count\r\n */\r\nexport type ColumnOptions = 'list' | 'compact' | 'moveScale' | 'move' | 'scale' | 'none' |\r\n  ((column: number, oldColumn: number, nodes: GridStackNode[], oldNodes: GridStackNode[]) => void);\r\nexport type CompactOptions = 'list' | 'compact';\r\nexport type numberOrString = number | string;\r\nexport interface GridItemHTMLElement extends HTMLElement {\r\n  /** pointer to grid node instance */\r\n  gridstackNode?: GridStackNode;\r\n  /** @internal */\r\n  _gridstackNodeOrig?: GridStackNode;\r\n}\r\n\r\nexport type GridStackElement = string | HTMLElement | GridItemHTMLElement;\r\n\r\n/** specific and general event handlers for the .on() method */\r\nexport type GridStackEventHandler = (event: Event) => void;\r\nexport type GridStackElementHandler = (event: Event, el: GridItemHTMLElement) => void;\r\nexport type GridStackNodesHandler = (event: Event, nodes: GridStackNode[]) => void;\r\nexport type GridStackDroppedHandler = (event: Event, previousNode: GridStackNode, newNode: GridStackNode) => void;\r\nexport type GridStackEventHandlerCallback = GridStackEventHandler | GridStackElementHandler | GridStackNodesHandler | GridStackDroppedHandler;\r\n\r\n/** optional function called during load() to callback the user on new added/remove grid items | grids */\r\nexport type AddRemoveFcn = (parent: HTMLElement, w: GridStackWidget, add: boolean, grid: boolean) => HTMLElement | undefined;\r\n\r\n/** optional function called during save() to let the caller add additional custom data to the GridStackWidget structure that will get returned */\r\nexport type SaveFcn = (node: GridStackNode, w: GridStackWidget) => void;\r\n\r\n/** optional function called during load()/addWidget() to let the caller create custom content other than plan text */\r\nexport type RenderFcn = (el: HTMLElement, w: GridStackWidget) => void;\r\n\r\nexport type ResizeToContentFcn = (el: GridItemHTMLElement) => void;\r\n\r\n/** describes the responsive nature of the grid. NOTE: make sure to have correct extra CSS to support this. */\r\nexport interface Responsive {\r\n  /** wanted width to maintain (+-50%) to dynamically pick a column count. NOTE: make sure to have correct extra CSS to support this. */\r\n  columnWidth?: number;\r\n  /** maximum number of columns allowed (default: 12). NOTE: make sure to have correct extra CSS to support this. */\r\n  columnMax?: number;\r\n  /** explicit width:column breakpoints instead of automatic 'columnWidth'. NOTE: make sure to have correct extra CSS to support this. */\r\n  breakpoints?: Breakpoint[];\r\n  /** specify if breakpoints are for window size or grid size (default:false = grid) */\r\n  breakpointForWindow?: boolean;\r\n  /** global re-layout mode when changing columns */\r\n  layout?: ColumnOptions;\r\n}\r\n\r\nexport interface Breakpoint {\r\n  /** <= width for the breakpoint to trigger */\r\n  w?: number;\r\n  /** column count */\r\n  c: number;\r\n  /** re-layout mode if different from global one */\r\n  layout?: ColumnOptions;\r\n  /** TODO: children layout, which spells out exact locations and could omit/add some children */\r\n  // children?: GridStackWidget[];\r\n}\r\n\r\n/**\r\n * Defines the options for a Grid\r\n */\r\nexport interface GridStackOptions {\r\n  /**\r\n   * accept widgets dragged from other grids or from outside (default: `false`). Can be:\r\n   * `true` (uses `'.grid-stack-item'` class filter) or `false`,\r\n   * string for explicit class name,\r\n   * function returning a boolean. See [example](http://gridstack.github.io/gridstack.js/demo/two.html)\r\n   */\r\n  acceptWidgets?: boolean | string | ((element: Element) => boolean);\r\n\r\n  /** possible values (default: `mobile`) - does not apply to non-resizable widgets\r\n    * `false` the resizing handles are only shown while hovering over a widget\r\n    * `true` the resizing handles are always shown\r\n    * 'mobile' if running on a mobile device, default to `true` (since there is no hovering per say), else `false`.\r\n    See [example](http://gridstack.github.io/gridstack.js/demo/mobile.html) */\r\n  alwaysShowResizeHandle?: true | false | 'mobile';\r\n\r\n  /** turns animation on (default?: true) */\r\n  animate?: boolean;\r\n\r\n  /** if false gridstack will not initialize existing items (default?: true) */\r\n  auto?: boolean;\r\n\r\n  /**\r\n   * one cell height (default?: 'auto'). Can be:\r\n   *  an integer (px)\r\n   *  a string (ex: '100px', '10em', '10rem'). Note: % doesn't work right - see demo/cell-height.html\r\n   *  0, in which case the library will not generate styles for rows. Everything must be defined in your own CSS files.\r\n   *  'auto' - height will be calculated for square cells (width / column) and updated live as you resize the window - also see `cellHeightThrottle`\r\n   *  'initial' - similar to 'auto' (start at square cells) but stay that size during window resizing.\r\n   */\r\n  cellHeight?: numberOrString;\r\n\r\n  /** throttle time delay (in ms) used when cellHeight='auto' to improve performance vs usability (default?: 100).\r\n   * A value of 0 will make it instant at a cost of re-creating the CSS file at ever window resize event!\r\n   * */\r\n  cellHeightThrottle?: number;\r\n\r\n  /** (internal) unit for cellHeight (default? 'px') which is set when a string cellHeight with a unit is passed (ex: '10rem') */\r\n  cellHeightUnit?: string;\r\n\r\n  /** list of children item to create when calling load() or addGrid() */\r\n  children?: GridStackWidget[];\r\n\r\n  /** number of columns (default?: 12). Note: IF you change this, CSS also have to change. See https://github.com/gridstack/gridstack.js#change-grid-columns.\r\n   * Note: for nested grids, it is recommended to use 'auto' which will always match the container grid-item current width (in column) to keep inside and outside\r\n   * items always the same. flag is NOT supported for regular non-nested grids.\r\n   */\r\n  column?: number | 'auto';\r\n\r\n  /** responsive column layout for width:column behavior */\r\n  columnOpts?: Responsive;\r\n\r\n  /** additional class on top of '.grid-stack' (which is required for our CSS) to differentiate this instance.\r\n  Note: only used by addGrid(), else your element should have the needed class */\r\n  class?: string;\r\n\r\n  /** disallows dragging of widgets (default?: false) */\r\n  disableDrag?: boolean;\r\n\r\n  /** disallows resizing of widgets (default?: false). */\r\n  disableResize?: boolean;\r\n\r\n  /** allows to override UI draggable options. (default?: { handle?: '.grid-stack-item-content', appendTo?: 'body' }) */\r\n  draggable?: DDDragOpt;\r\n\r\n  /** let user drag nested grid items out of a parent or not (default true - not supported yet) */\r\n  //dragOut?: boolean;\r\n\r\n  /** the type of engine to create (so you can subclass) default to GridStackEngine */\r\n  engineClass?: typeof GridStackEngine;\r\n\r\n  /** enable floating widgets (default?: false) See example (http://gridstack.github.io/gridstack.js/demo/float.html) */\r\n  float?: boolean;\r\n\r\n  /** draggable handle selector (default?: '.grid-stack-item-content') */\r\n  handle?: string;\r\n\r\n  /** draggable handle class (e.g. 'grid-stack-item-content'). If set 'handle' is ignored (default?: null) */\r\n  handleClass?: string;\r\n\r\n  /** additional widget class (default?: 'grid-stack-item') */\r\n  itemClass?: string;\r\n\r\n  /** re-layout mode when we're a subgrid and we are being resized. default to 'list' */\r\n  layout?: ColumnOptions;\r\n\r\n  /** true when widgets are only created when they scroll into view (visible) */\r\n  lazyLoad?: boolean;\r\n\r\n  /**\r\n   * gap between grid item and content (default?: 10). This will set all 4 sides and support the CSS formats below\r\n   *  an integer (px)\r\n   *  a string with possible units (ex: '2em', '20px', '2rem')\r\n   *  string with space separated values (ex: '5px 10px 0 20px' for all 4 sides, or '5em 10em' for top/bottom and left/right pairs like CSS).\r\n   * Note: all sides must have same units (last one wins, default px)\r\n   */\r\n  margin?: numberOrString;\r\n\r\n  /** OLD way to optionally set each side - use margin: '5px 10px 0 20px' instead. Used internally to store each side. */\r\n  marginTop?: numberOrString;\r\n  marginRight?: numberOrString;\r\n  marginBottom?: numberOrString;\r\n  marginLeft?: numberOrString;\r\n\r\n  /** (internal) unit for margin (default? 'px') set when `margin` is set as string with unit (ex: 2rem') */\r\n  marginUnit?: string;\r\n\r\n  /** maximum rows amount. Default? is 0 which means no maximum rows */\r\n  maxRow?: number;\r\n\r\n  /** minimum rows amount. Default is `0`. You can also do this with `min-height` CSS attribute\r\n   * on the grid div in pixels, which will round to the closest row.\r\n   */\r\n  minRow?: number;\r\n\r\n  /** If you are using a nonce-based Content Security Policy, pass your nonce here and\r\n   * GridStack will add it to the <style> elements it creates. */\r\n  nonce?: string;\r\n\r\n  /** class for placeholder (default?: 'grid-stack-placeholder') */\r\n  placeholderClass?: string;\r\n\r\n  /** placeholder default content (default?: '') */\r\n  placeholderText?: string;\r\n\r\n  /** allows to override UI resizable options. (default?: { handles: 'se' }) */\r\n  resizable?: DDResizeOpt;\r\n\r\n  /**\r\n   * if true widgets could be removed by dragging outside of the grid. It could also be a selector string (ex: \".trash\"),\r\n   * in this case widgets will be removed by dropping them there (default?: false)\r\n   * See example (http://gridstack.github.io/gridstack.js/demo/two.html)\r\n   */\r\n  removable?: boolean | string;\r\n\r\n  /** allows to override UI removable options. (default?: { accept: '.grid-stack-item' }) */\r\n  removableOptions?: DDRemoveOpt;\r\n\r\n  /** fix grid number of rows. This is a shortcut of writing `minRow:N, maxRow:N`. (default `0` no constrain) */\r\n  row?: number;\r\n\r\n  /**\r\n   * if true turns grid to RTL. Possible values are true, false, 'auto' (default?: 'auto')\r\n   * See [example](http://gridstack.github.io/gridstack.js/demo/right-to-left(rtl).html)\r\n   */\r\n  rtl?: boolean | 'auto';\r\n\r\n  /** set to true if all grid items (by default, but item can also override) height should be based on content size instead of WidgetItem.h to avoid v-scrollbars.\r\n   * Note: this is still row based, not pixels, so it will use ceil(getBoundingClientRect().height / getCellHeight())\r\n   */\r\n  sizeToContent?: boolean;\r\n\r\n  /**\r\n   * makes grid static (default?: false). If `true` widgets are not movable/resizable.\r\n   * You don't even need draggable/resizable. A CSS class\r\n   * 'grid-stack-static' is also added to the element.\r\n   */\r\n  staticGrid?: boolean;\r\n\r\n  /**\r\n   * @deprecated Not used anymore, styles are now implemented with local CSS variables\r\n   */\r\n  styleInHead?: boolean;\r\n\r\n  /** list of differences in options for automatically created sub-grids under us (inside our grid-items) */\r\n  subGridOpts?: GridStackOptions;\r\n\r\n  /** enable/disable the creation of sub-grids on the fly by dragging items completely\r\n   * over others (nest) vs partially (push). Forces `DDDragOpt.pause=true` to accomplish that. */\r\n  subGridDynamic?: boolean;\r\n}\r\n\r\n/** options used during GridStackEngine.moveNode() */\r\nexport interface GridStackMoveOpts extends GridStackPosition {\r\n  /** node to skip collision */\r\n  skip?: GridStackNode;\r\n  /** do we pack (default true) */\r\n  pack?: boolean;\r\n  /** true if we are calling this recursively to prevent simple swap or coverage collision - default false*/\r\n  nested?: boolean;\r\n  /** vars to calculate other cells coordinates */\r\n  cellWidth?: number;\r\n  cellHeight?: number;\r\n  marginTop?: number;\r\n  marginBottom?: number;\r\n  marginLeft?: number;\r\n  marginRight?: number;\r\n  /** position in pixels of the currently dragged items (for overlap check) */\r\n  rect?: GridStackPosition;\r\n  /** true if we're live resizing */\r\n  resizing?: boolean;\r\n  /** best node (most coverage) we collied with */\r\n  collide?: GridStackNode;\r\n  /** for collision check even if we don't move */\r\n  forceCollide?: boolean;\r\n}\r\n\r\nexport interface GridStackPosition {\r\n  /** widget position x (default?: 0) */\r\n  x?: number;\r\n  /** widget position y (default?: 0) */\r\n  y?: number;\r\n  /** widget dimension width (default?: 1) */\r\n  w?: number;\r\n  /** widget dimension height (default?: 1) */\r\n  h?: number;\r\n}\r\n\r\n/**\r\n * GridStack Widget creation options\r\n */\r\nexport interface GridStackWidget extends GridStackPosition {\r\n  /** if true then x, y parameters will be ignored and widget will be places on the first available position (default?: false) */\r\n  autoPosition?: boolean;\r\n  /** minimum width allowed during resize/creation (default?: undefined = un-constrained) */\r\n  minW?: number;\r\n  /** maximum width allowed during resize/creation (default?: undefined = un-constrained) */\r\n  maxW?: number;\r\n  /** minimum height allowed during resize/creation (default?: undefined = un-constrained) */\r\n  minH?: number;\r\n  /** maximum height allowed during resize/creation (default?: undefined = un-constrained) */\r\n  maxH?: number;\r\n  /** prevent direct resizing by the user (default?: undefined = un-constrained) */\r\n  noResize?: boolean;\r\n  /** prevents direct moving by the user (default?: undefined = un-constrained) */\r\n  noMove?: boolean;\r\n  /** prevents being pushed by other widgets or api (default?: undefined = un-constrained), which is different from `noMove` (user action only) */\r\n  locked?: boolean;\r\n  /** value for `gs-id` stored on the widget (default?: undefined) */\r\n  id?: string;\r\n  /** html to append inside as content */\r\n  content?: string;\r\n  /** true when widgets are only created when they scroll into view (visible) */\r\n  lazyLoad?: boolean;\r\n  /** local (vs grid) override - see GridStackOptions.\r\n   * Note: This also allow you to set a maximum h value (but user changeable during normal resizing) to prevent unlimited content from taking too much space (get scrollbar) */\r\n  sizeToContent?: boolean | number;\r\n  /** local override of GridStack.resizeToContentParent that specify the class to use for the parent (actual) vs child (wanted) height */\r\n  resizeToContentParent?: string;\r\n  /** optional nested grid options and list of children, which then turns into actual instance at runtime to get options from */\r\n  subGridOpts?: GridStackOptions;\r\n}\r\n\r\n/** Drag&Drop resize options */\r\nexport interface DDResizeOpt {\r\n  /** do resize handle hide by default until mouse over ? - default: true on desktop, false on mobile*/\r\n  autoHide?: boolean;\r\n  /**\r\n   * sides where you can resize from (ex: 'e, se, s, sw, w') - default 'se' (south-east)\r\n   * Note: it is not recommended to resize from the top sides as weird side effect may occur.\r\n  */\r\n  handles?: string;\r\n}\r\n\r\n/** Drag&Drop remove options */\r\nexport interface DDRemoveOpt {\r\n  /** class that can be removed (default?: opts.itemClass) */\r\n  accept?: string;\r\n  /** class that cannot be removed (default: 'grid-stack-non-removable') */\r\n  decline?: string;\r\n}\r\n\r\n/** Drag&Drop dragging options */\r\nexport interface DDDragOpt {\r\n  /** class selector of items that can be dragged. default to '.grid-stack-item-content' */\r\n  handle?: string;\r\n  /** default to 'body' */\r\n  appendTo?: string;\r\n  /** if set (true | msec), dragging placement (collision) will only happen after a pause by the user. Note: this is Global */\r\n  pause?: boolean | number;\r\n  /** default to `true` */\r\n  scroll?: boolean;\r\n  /** prevents dragging from starting on specified elements, listed as comma separated selectors (eg: '.no-drag'). default built in is 'input,textarea,button,select,option' */\r\n  cancel?: string;\r\n  /** helper function when dropping: 'clone' or your own method */\r\n  helper?: 'clone' | ((el: HTMLElement) => HTMLElement);\r\n  /** callbacks */\r\n  start?: (event: Event, ui: DDUIData) => void;\r\n  stop?: (event: Event) => void;\r\n  drag?: (event: Event, ui: DDUIData) => void;\r\n}\r\nexport interface Size {\r\n  width: number;\r\n  height: number;\r\n}\r\nexport interface Position {\r\n  top: number;\r\n  left: number;\r\n}\r\nexport interface Rect extends Size, Position {}\r\n\r\n/** data that is passed during drag and resizing callbacks */\r\nexport interface DDUIData {\r\n  position?: Position;\r\n  size?: Size;\r\n  draggable?: HTMLElement;\r\n  /* fields not used by GridStack but sent by jq ? leave in case we go back to them...\r\n  originalPosition? : Position;\r\n  offset?: Position;\r\n  originalSize?: Size;\r\n  element?: HTMLElement[];\r\n  helper?: HTMLElement[];\r\n  originalElement?: HTMLElement[];\r\n  */\r\n}\r\n\r\n/**\r\n * internal runtime descriptions describing the widgets in the grid\r\n */\r\nexport interface GridStackNode extends GridStackWidget {\r\n  /** pointer back to HTML element */\r\n  el?: GridItemHTMLElement;\r\n  /** pointer back to parent Grid instance */\r\n  grid?: GridStack;\r\n  /** actual sub-grid instance */\r\n  subGrid?: GridStack;\r\n  /** allow delay creation when visible */\r\n  visibleObservable?: IntersectionObserver;\r\n  /** @internal internal id used to match when cloning engines or saving column layouts */\r\n  _id?: number;\r\n  /** @internal does the node attr ned to be updated due to changed x,y,w,h values */\r\n  _dirty?: boolean;\r\n  /** @internal */\r\n  _updating?: boolean;\r\n  /** @internal true when over trash/another grid so we don't bother removing drag CSS style that would animate back to old position */\r\n  _isAboutToRemove?: boolean;\r\n  /** @internal true if item came from outside of the grid -> actual item need to be moved over */\r\n  _isExternal?: boolean;\r\n  /** @internal Mouse event that's causing moving|resizing */\r\n  _event?: MouseEvent;\r\n  /** @internal moving vs resizing */\r\n  _moving?: boolean;\r\n  /** @internal is resizing? */\r\n  _resizing?: boolean;\r\n  /** @internal true if we jumped down past item below (one time jump so we don't have to totally pass it) */\r\n  _skipDown?: boolean;\r\n  /** @internal original values before a drag/size */\r\n  _orig?: GridStackPosition;\r\n  /** @internal position in pixels used during collision check  */\r\n  _rect?: GridStackPosition;\r\n  /** @internal top/left pixel location before a drag so we can detect direction of move from last position*/\r\n  _lastUiPosition?: Position;\r\n  /** @internal set on the item being dragged/resized remember the last positions we've tried (but failed) so we don't try again during drag/resize */\r\n  _lastTried?: GridStackPosition;\r\n  /** @internal position willItFit() will use to position the item */\r\n  _willFitPos?: GridStackPosition;\r\n  /** @internal last drag Y pixel position used to incrementally update V scroll bar */\r\n  _prevYPix?: number;\r\n  /** @internal true if we've remove the item from ourself (dragging out) but might revert it back (release on nothing -> goes back) */\r\n  _temporaryRemoved?: boolean;\r\n  /** @internal true if we should remove DOM element on _notify() rather than clearing _id (old way) */\r\n  _removeDOM?: boolean;\r\n  /** @internal original position/size of item if dragged from sidebar */\r\n  _sidebarOrig?: GridStackPosition;\r\n  /** @internal had drag&drop been initialized */\r\n  _initDD?: boolean;\r\n}\r\n","/**\n * dd-manager.ts 12.1.2\n * Copyright (c) 2021-2024 Alain Dumesny - see GridStack root license\n */\n\nimport { DDDraggable } from './dd-draggable';\nimport { DDDroppable } from './dd-droppable';\nimport { DDResizable } from './dd-resizable';\n\n/**\n * globals that are shared across Drag & Drop instances\n */\nexport class DDManager {\n  /** if set (true | in msec), dragging placement (collision) will only happen after a pause by the user*/\n  public static pauseDrag: boolean | number;\n\n  /** true if a mouse down event was handled */\n  public static mouseHandled: boolean;\n\n  /** item being dragged */\n  public static dragElement: DDDraggable;\n\n  /** item we are currently over as drop target */\n  public static dropElement: DDDroppable;\n\n  /** current item we're over for resizing purpose (ignore nested grid resize handles) */\n  public static overResizeElement: DDResizable;\n\n}\n","/**\n * touch.ts 12.1.2\n * Copyright (c) 2021-2024 Alain Dumesny - see GridStack root license\n */\n\nimport { DDManager } from './dd-manager';\nimport { Utils } from './utils';\n\n/**\n * Detect touch support - Windows Surface devices and other touch devices\n * should we use this instead ? (what we had for always showing resize handles)\n * /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)\n */\nexport const isTouch: boolean = typeof window !== 'undefined' && typeof document !== 'undefined' &&\n  ( 'ontouchstart' in document\n    || 'ontouchstart' in window\n    // || !!window.TouchEvent // true on Windows 10 Chrome desktop so don't use this\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n    || ((window as any).DocumentTouch && document instanceof (window as any).DocumentTouch)\n    || navigator.maxTouchPoints > 0\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n    || (navigator as any).msMaxTouchPoints > 0\n  );\n\n// interface TouchCoord {x: number, y: number};\n\nclass DDTouch {\n  public static touchHandled: boolean;\n  public static pointerLeaveTimeout: number;\n}\n\n/**\n* Get the x,y position of a touch event\n*/\n// function getTouchCoords(e: TouchEvent): TouchCoord {\n//   return {\n//     x: e.changedTouches[0].pageX,\n//     y: e.changedTouches[0].pageY\n//   };\n// }\n\n/**\n * Simulate a mouse event based on a corresponding touch event\n * @param {Object} e A touch event\n * @param {String} simulatedType The corresponding mouse event\n */\nfunction simulateMouseEvent(e: TouchEvent, simulatedType: string) {\n\n  // Ignore multi-touch events\n  if (e.touches.length > 1) return;\n\n  // Prevent \"Ignored attempt to cancel a touchmove event with cancelable=false\" errors\n  if (e.cancelable) e.preventDefault();\n\n  // Dispatch the simulated event to the target element\n  Utils.simulateMouseEvent(e.changedTouches[0], simulatedType);\n}\n\n/**\n * Simulate a mouse event based on a corresponding Pointer event\n * @param {Object} e A pointer event\n * @param {String} simulatedType The corresponding mouse event\n */\nfunction simulatePointerMouseEvent(e: PointerEvent, simulatedType: string) {\n\n  // Prevent \"Ignored attempt to cancel a touchmove event with cancelable=false\" errors\n  if (e.cancelable) e.preventDefault();\n\n  // Dispatch the simulated event to the target element\n  Utils.simulateMouseEvent(e, simulatedType);\n}\n\n\n/**\n * Handle the touchstart events\n * @param {Object} e The widget element's touchstart event\n */\nexport function touchstart(e: TouchEvent): void {\n  // Ignore the event if another widget is already being handled\n  if (DDTouch.touchHandled) return;\n  DDTouch.touchHandled = true;\n\n  // Simulate the mouse events\n  // simulateMouseEvent(e, 'mouseover');\n  // simulateMouseEvent(e, 'mousemove');\n  simulateMouseEvent(e, 'mousedown');\n}\n\n/**\n * Handle the touchmove events\n * @param {Object} e The document's touchmove event\n */\nexport function touchmove(e: TouchEvent): void {\n  // Ignore event if not handled by us\n  if (!DDTouch.touchHandled) return;\n\n  simulateMouseEvent(e, 'mousemove');\n}\n\n/**\n * Handle the touchend events\n * @param {Object} e The document's touchend event\n */\nexport function touchend(e: TouchEvent): void {\n\n  // Ignore event if not handled\n  if (!DDTouch.touchHandled) return;\n\n  // cancel delayed leave event when we release on ourself which happens BEFORE we get this!\n  if (DDTouch.pointerLeaveTimeout) {\n    window.clearTimeout(DDTouch.pointerLeaveTimeout);\n    delete DDTouch.pointerLeaveTimeout;\n  }\n\n  const wasDragging = !!DDManager.dragElement;\n\n  // Simulate the mouseup event\n  simulateMouseEvent(e, 'mouseup');\n  // simulateMouseEvent(event, 'mouseout');\n\n  // If the touch interaction did not move, it should trigger a click\n  if (!wasDragging) {\n    simulateMouseEvent(e, 'click');\n  }\n\n  // Unset the flag to allow other widgets to inherit the touch event\n  DDTouch.touchHandled = false;\n}\n\n/**\n * Note we don't get touchenter/touchleave (which are deprecated)\n * see https://stackoverflow.com/questions/27908339/js-touch-equivalent-for-mouseenter\n * so instead of PointerEvent to still get enter/leave and send the matching mouse event.\n */\nexport function pointerdown(e: PointerEvent): void {\n  // console.log(\"pointer down\")\n  if (e.pointerType === 'mouse') return;\n  (e.target as HTMLElement).releasePointerCapture(e.pointerId) // <- Important!\n}\n\nexport function pointerenter(e: PointerEvent): void {\n  // ignore the initial one we get on pointerdown on ourself\n  if (!DDManager.dragElement) {\n    // console.log('pointerenter ignored');\n    return;\n  }\n  // console.log('pointerenter');\n  if (e.pointerType === 'mouse') return;\n  simulatePointerMouseEvent(e, 'mouseenter');\n}\n\nexport function pointerleave(e: PointerEvent): void {\n  // ignore the leave on ourself we get before releasing the mouse over ourself\n  // by delaying sending the event and having the up event cancel us\n  if (!DDManager.dragElement) {\n    // console.log('pointerleave ignored');\n    return;\n  }\n  if (e.pointerType === 'mouse') return;\n  DDTouch.pointerLeaveTimeout = window.setTimeout(() => {\n    delete DDTouch.pointerLeaveTimeout;\n    // console.log('pointerleave delayed');\n    simulatePointerMouseEvent(e, 'mouseleave');\n  }, 10);\n}\n\n","/**\n * dd-resizable-handle.ts 12.1.2\n * Copyright (c) 2021-2024  Alain Dumesny - see GridStack root license\n */\n\nimport { isTouch, pointerdown, touchend, touchmove, touchstart } from './dd-touch';\nimport { GridItemHTMLElement } from './gridstack';\n\nexport interface DDResizableHandleOpt {\n  start?: (event) => void;\n  move?: (event) => void;\n  stop?: (event) => void;\n}\n\nexport class DDResizableHandle {\n  /** @internal */\n  protected el: HTMLElement;\n  /** @internal true after we've moved enough pixels to start a resize */\n  protected moving = false;\n  /** @internal */\n  protected mouseDownEvent: MouseEvent;\n  /** @internal */\n  protected static prefix = 'ui-resizable-';\n\n  constructor(protected host: GridItemHTMLElement, protected dir: string, protected option: DDResizableHandleOpt) {\n    // create var event binding so we can easily remove and still look like TS methods (unlike anonymous functions)\n    this._mouseDown = this._mouseDown.bind(this);\n    this._mouseMove = this._mouseMove.bind(this);\n    this._mouseUp = this._mouseUp.bind(this);\n    this._keyEvent = this._keyEvent.bind(this);\n\n    this._init();\n  }\n\n  /** @internal */\n  protected _init(): DDResizableHandle {\n    const el = this.el = document.createElement('div');\n    el.classList.add('ui-resizable-handle');\n    el.classList.add(`${DDResizableHandle.prefix}${this.dir}`);\n    el.style.zIndex = '100';\n    el.style.userSelect = 'none';\n    this.host.appendChild(this.el);\n    this.el.addEventListener('mousedown', this._mouseDown);\n    if (isTouch) {\n      this.el.addEventListener('touchstart', touchstart);\n      this.el.addEventListener('pointerdown', pointerdown);\n      // this.el.style.touchAction = 'none'; // not needed unlike pointerdown doc comment\n    }\n    return this;\n  }\n\n  /** call this when resize handle needs to be removed and cleaned up */\n  public destroy(): DDResizableHandle {\n    if (this.moving) this._mouseUp(this.mouseDownEvent);\n    this.el.removeEventListener('mousedown', this._mouseDown);\n    if (isTouch) {\n      this.el.removeEventListener('touchstart', touchstart);\n      this.el.removeEventListener('pointerdown', pointerdown);\n    }\n    this.host.removeChild(this.el);\n    delete this.el;\n    delete this.host;\n    return this;\n  }\n\n  /** @internal called on mouse down on us: capture move on the entire document (mouse might not stay on us) until we release the mouse */\n  protected _mouseDown(e: MouseEvent): void {\n    this.mouseDownEvent = e;\n    document.addEventListener('mousemove', this._mouseMove, { capture: true, passive: true}); // capture, not bubble\n    document.addEventListener('mouseup', this._mouseUp, true);\n    if (isTouch) {\n      this.el.addEventListener('touchmove', touchmove);\n      this.el.addEventListener('touchend', touchend);\n    }\n    e.stopPropagation();\n    e.preventDefault();\n  }\n\n  /** @internal */\n  protected _mouseMove(e: MouseEvent): void {\n    const s = this.mouseDownEvent;\n    if (this.moving) {\n      this._triggerEvent('move', e);\n    } else if (Math.abs(e.x - s.x) + Math.abs(e.y - s.y) > 2) {\n      // don't start unless we've moved at least 3 pixels\n      this.moving = true;\n      this._triggerEvent('start', this.mouseDownEvent);\n      this._triggerEvent('move', e);\n      // now track keyboard events to cancel\n      document.addEventListener('keydown', this._keyEvent);\n    }\n    e.stopPropagation();\n    // e.preventDefault(); passive = true\n  }\n\n  /** @internal */\n  protected _mouseUp(e: MouseEvent): void {\n    if (this.moving) {\n      this._triggerEvent('stop', e);\n      document.removeEventListener('keydown', this._keyEvent);\n    }\n    document.removeEventListener('mousemove', this._mouseMove, true);\n    document.removeEventListener('mouseup', this._mouseUp, true);\n    if (isTouch) {\n      this.el.removeEventListener('touchmove', touchmove);\n      this.el.removeEventListener('touchend', touchend);\n    }\n    delete this.moving;\n    delete this.mouseDownEvent;\n    e.stopPropagation();\n    e.preventDefault();\n  }\n\n  /** @internal call when keys are being pressed - use Esc to cancel */\n  protected _keyEvent(e: KeyboardEvent): void {\n    if (e.key === 'Escape') {\n      this.host.gridstackNode?.grid?.engine.restoreInitial();\n      this._mouseUp(this.mouseDownEvent);\n    }\n  }\n\n\n\n  /** @internal */\n  protected _triggerEvent(name: string, event: MouseEvent): DDResizableHandle {\n    if (this.option[name]) this.option[name](event);\n    return this;\n  }\n}\n","/**\n * dd-base-impl.ts 12.1.2\n * Copyright (c) 2021-2024  Alain Dumesny - see GridStack root license\n */\n\nexport type EventCallback = (event: Event) => boolean|void;\nexport abstract class DDBaseImplement {\n  /** returns the enable state, but you have to call enable()/disable() to change (as other things need to happen) */\n  public get disabled(): boolean   { return this._disabled; }\n\n  /** @internal */\n  protected _disabled: boolean; // initial state to differentiate from false\n  /** @internal */\n  protected _eventRegister: {\n    [eventName: string]: EventCallback;\n  } = {};\n\n  public on(event: string, callback: EventCallback): void {\n    this._eventRegister[event] = callback;\n  }\n\n  public off(event: string): void {\n    delete this._eventRegister[event];\n  }\n\n  public enable(): void {\n    this._disabled = false;\n  }\n\n  public disable(): void {\n    this._disabled = true;\n  }\n\n  public destroy(): void {\n    delete this._eventRegister;\n  }\n\n  public triggerEvent(eventName: string, event: Event): boolean|void {\n    if (!this.disabled && this._eventRegister && this._eventRegister[eventName])\n      return this._eventRegister[eventName](event);\n  }\n}\n\nexport interface HTMLElementExtendOpt<T> {\n  el: HTMLElement;\n  option: T;\n  updateOption(T): DDBaseImplement;\n}\n","/**\n * dd-resizable.ts 12.1.2\n * Copyright (c) 2021-2024  Alain Dumesny - see GridStack root license\n */\n\nimport { DDResizableHandle } from './dd-resizable-handle';\nimport { DDBaseImplement, HTMLElementExtendOpt } from './dd-base-impl';\nimport { Utils } from './utils';\nimport { DDUIData, GridItemHTMLElement, Rect, Size } from './types';\nimport { DDManager } from './dd-manager';\n\n// import { GridItemHTMLElement } from './types'; let count = 0; // TEST\n\n// TODO: merge with DDDragOpt\nexport interface DDResizableOpt {\n  autoHide?: boolean;\n  handles?: string;\n  maxHeight?: number;\n  maxHeightMoveUp?: number;\n  maxWidth?: number;\n  maxWidthMoveLeft?: number;\n  minHeight?: number;\n  minWidth?: number;\n  start?: (event: Event, ui: DDUIData) => void;\n  stop?: (event: Event) => void;\n  resize?: (event: Event, ui: DDUIData) => void;\n}\n\ninterface RectScaleReciprocal {\n  x: number;\n  y: number;\n}\n\nexport class DDResizable extends DDBaseImplement implements HTMLElementExtendOpt<DDResizableOpt> {\n  /** @internal */\n  protected handlers: DDResizableHandle[];\n  /** @internal */\n  protected originalRect: Rect;\n  /** @internal */\n  protected rectScale: RectScaleReciprocal = { x: 1, y: 1 };\n  /** @internal */\n  protected temporalRect: Rect;\n  /** @internal */\n  protected scrollY: number;\n  /** @internal */\n  protected scrolled: number;\n  /** @internal */\n  protected scrollEl: HTMLElement;\n  /** @internal */\n  protected startEvent: MouseEvent;\n  /** @internal value saved in the same order as _originStyleProp[] */\n  protected elOriginStyleVal: string[];\n  /** @internal */\n  protected parentOriginStylePosition: string;\n  /** @internal */\n  protected static _originStyleProp = ['width', 'height', 'position', 'left', 'top', 'opacity', 'zIndex'];\n  /** @internal */\n  protected sizeToContent: boolean;\n\n  // have to be public else complains for HTMLElementExtendOpt ?\n  constructor(public el: GridItemHTMLElement, public option: DDResizableOpt = {}) {\n    super();\n    // create var event binding so we can easily remove and still look like TS methods (unlike anonymous functions)\n    this._mouseOver = this._mouseOver.bind(this);\n    this._mouseOut = this._mouseOut.bind(this);\n    this.enable();\n    this._setupAutoHide(this.option.autoHide);\n    this._setupHandlers();\n  }\n\n  public on(event: 'resizestart' | 'resize' | 'resizestop', callback: (event: DragEvent) => void): void {\n    super.on(event, callback);\n  }\n\n  public off(event: 'resizestart' | 'resize' | 'resizestop'): void {\n    super.off(event);\n  }\n\n  public enable(): void {\n    super.enable();\n    this.el.classList.remove('ui-resizable-disabled');\n    this._setupAutoHide(this.option.autoHide);\n  }\n\n  public disable(): void {\n    super.disable();\n    this.el.classList.add('ui-resizable-disabled');\n    this._setupAutoHide(false);\n  }\n\n  public destroy(): void {\n    this._removeHandlers();\n    this._setupAutoHide(false);\n    delete this.el;\n    super.destroy();\n  }\n\n  public updateOption(opts: DDResizableOpt): DDResizable {\n    const updateHandles = (opts.handles && opts.handles !== this.option.handles);\n    const updateAutoHide = (opts.autoHide && opts.autoHide !== this.option.autoHide);\n    Object.keys(opts).forEach(key => this.option[key] = opts[key]);\n    if (updateHandles) {\n      this._removeHandlers();\n      this._setupHandlers();\n    }\n    if (updateAutoHide) {\n      this._setupAutoHide(this.option.autoHide);\n    }\n    return this;\n  }\n\n  /** @internal turns auto hide on/off */\n  protected _setupAutoHide(auto: boolean): DDResizable {\n    if (auto) {\n      this.el.classList.add('ui-resizable-autohide');\n      // use mouseover and not mouseenter to get better performance and track for nested cases\n      this.el.addEventListener('mouseover', this._mouseOver);\n      this.el.addEventListener('mouseout', this._mouseOut);\n    } else {\n      this.el.classList.remove('ui-resizable-autohide');\n      this.el.removeEventListener('mouseover', this._mouseOver);\n      this.el.removeEventListener('mouseout', this._mouseOut);\n      if (DDManager.overResizeElement === this) {\n        delete DDManager.overResizeElement;\n      }\n    }\n    return this;\n  }\n\n  /** @internal */\n  // eslint-disable-next-line @typescript-eslint/no-unused-vars\n  protected _mouseOver(e: Event): void {\n    // console.log(`${count++} pre-enter ${(this.el as GridItemHTMLElement).gridstackNode._id}`)\n    // already over a child, ignore. Ideally we just call e.stopPropagation() but see https://github.com/gridstack/gridstack.js/issues/2018\n    if (DDManager.overResizeElement || DDManager.dragElement) return;\n    DDManager.overResizeElement = this;\n    // console.log(`${count++} enter ${(this.el as GridItemHTMLElement).gridstackNode._id}`)\n    this.el.classList.remove('ui-resizable-autohide');\n  }\n\n  /** @internal */\n  // eslint-disable-next-line @typescript-eslint/no-unused-vars\n  protected _mouseOut(e: Event): void {\n    // console.log(`${count++} pre-leave ${(this.el as GridItemHTMLElement).gridstackNode._id}`)\n    if (DDManager.overResizeElement !== this) return;\n    delete DDManager.overResizeElement;\n    // console.log(`${count++} leave ${(this.el as GridItemHTMLElement).gridstackNode._id}`)\n    this.el.classList.add('ui-resizable-autohide');\n  }\n\n  /** @internal */\n  protected _setupHandlers(): DDResizable {\n    this.handlers = this.option.handles.split(',')\n      .map(dir => dir.trim())\n      .map(dir => new DDResizableHandle(this.el, dir, {\n        start: (event: MouseEvent) => {\n          this._resizeStart(event);\n        },\n        stop: (event: MouseEvent) => {\n          this._resizeStop(event);\n        },\n        move: (event: MouseEvent) => {\n          this._resizing(event, dir);\n        }\n      }));\n    return this;\n  }\n\n  /** @internal */\n  protected _resizeStart(event: MouseEvent): DDResizable {\n    this.sizeToContent = Utils.shouldSizeToContent(this.el.gridstackNode, true); // strick true only and not number\n    this.originalRect = this.el.getBoundingClientRect();\n    this.scrollEl = Utils.getScrollElement(this.el);\n    this.scrollY = this.scrollEl.scrollTop;\n    this.scrolled = 0;\n    this.startEvent = event;\n    this._setupHelper();\n    this._applyChange();\n    const ev = Utils.initEvent<MouseEvent>(event, { type: 'resizestart', target: this.el });\n    if (this.option.start) {\n      this.option.start(ev, this._ui());\n    }\n    this.el.classList.add('ui-resizable-resizing');\n    this.triggerEvent('resizestart', ev);\n    return this;\n  }\n\n  /** @internal */\n  protected _resizing(event: MouseEvent, dir: string): DDResizable {\n    this.scrolled = this.scrollEl.scrollTop - this.scrollY;\n    this.temporalRect = this._getChange(event, dir);\n    this._applyChange();\n    const ev = Utils.initEvent<MouseEvent>(event, { type: 'resize', target: this.el });\n    if (this.option.resize) {\n      this.option.resize(ev, this._ui());\n    }\n    this.triggerEvent('resize', ev);\n    return this;\n  }\n\n  /** @internal */\n  protected _resizeStop(event: MouseEvent): DDResizable {\n    const ev = Utils.initEvent<MouseEvent>(event, { type: 'resizestop', target: this.el });\n    // Remove style attr now, so the stop handler can rebuild style attrs\n    this._cleanHelper();\n    if (this.option.stop) {\n      this.option.stop(ev); // Note: ui() not used by gridstack so don't pass\n    }\n    this.el.classList.remove('ui-resizable-resizing');\n    this.triggerEvent('resizestop', ev);\n    delete this.startEvent;\n    delete this.originalRect;\n    delete this.temporalRect;\n    delete this.scrollY;\n    delete this.scrolled;\n    return this;\n  }\n\n  /** @internal */\n  protected _setupHelper(): DDResizable {\n    this.elOriginStyleVal = DDResizable._originStyleProp.map(prop => this.el.style[prop]);\n    this.parentOriginStylePosition = this.el.parentElement.style.position;\n\n    const parent = this.el.parentElement;\n    const dragTransform = Utils.getValuesFromTransformedElement(parent);\n    this.rectScale = {\n      x: dragTransform.xScale,\n      y: dragTransform.yScale\n    };\n\n    if (getComputedStyle(this.el.parentElement).position.match(/static/)) {\n      this.el.parentElement.style.position = 'relative';\n    }\n    this.el.style.position = 'absolute';\n    this.el.style.opacity = '0.8';\n    return this;\n  }\n\n  /** @internal */\n  protected _cleanHelper(): DDResizable {\n    DDResizable._originStyleProp.forEach((prop, i) => {\n      this.el.style[prop] = this.elOriginStyleVal[i] || null;\n    });\n    this.el.parentElement.style.position = this.parentOriginStylePosition || null;\n    return this;\n  }\n\n  /** @internal */\n  protected _getChange(event: MouseEvent, dir: string): Rect {\n    const oEvent = this.startEvent;\n    const newRect = { // Note: originalRect is a complex object, not a simple Rect, so copy out.\n      width: this.originalRect.width,\n      height: this.originalRect.height + this.scrolled,\n      left: this.originalRect.left,\n      top: this.originalRect.top - this.scrolled\n    };\n\n    const offsetX = event.clientX - oEvent.clientX;\n    const offsetY = this.sizeToContent ? 0 : event.clientY - oEvent.clientY; // prevent vert resize\n    let moveLeft: boolean;\n    let moveUp: boolean;\n\n    if (dir.indexOf('e') > -1) {\n      newRect.width += offsetX;\n    } else if (dir.indexOf('w') > -1) {\n      newRect.width -= offsetX;\n      newRect.left += offsetX;\n      moveLeft = true;\n    }\n    if (dir.indexOf('s') > -1) {\n      newRect.height += offsetY;\n    } else if (dir.indexOf('n') > -1) {\n      newRect.height -= offsetY;\n      newRect.top += offsetY\n      moveUp = true;\n    }\n    const constrain = this._constrainSize(newRect.width, newRect.height, moveLeft, moveUp);\n    if (Math.round(newRect.width) !== Math.round(constrain.width)) { // round to ignore slight round-off errors\n      if (dir.indexOf('w') > -1) {\n        newRect.left += newRect.width - constrain.width;\n      }\n      newRect.width = constrain.width;\n    }\n    if (Math.round(newRect.height) !== Math.round(constrain.height)) {\n      if (dir.indexOf('n') > -1) {\n        newRect.top += newRect.height - constrain.height;\n      }\n      newRect.height = constrain.height;\n    }\n    return newRect;\n  }\n\n  /** @internal constrain the size to the set min/max values */\n  protected _constrainSize(oWidth: number, oHeight: number, moveLeft: boolean, moveUp: boolean): Size {\n    const o = this.option;\n    const maxWidth = (moveLeft ? o.maxWidthMoveLeft : o.maxWidth) || Number.MAX_SAFE_INTEGER;\n    const minWidth = o.minWidth / this.rectScale.x || oWidth;\n    const maxHeight = (moveUp ? o.maxHeightMoveUp : o.maxHeight) || Number.MAX_SAFE_INTEGER;\n    const minHeight = o.minHeight / this.rectScale.y || oHeight;\n    const width = Math.min(maxWidth, Math.max(minWidth, oWidth));\n    const height = Math.min(maxHeight, Math.max(minHeight, oHeight));\n    return { width, height };\n  }\n\n  /** @internal */\n  protected _applyChange(): DDResizable {\n    let containmentRect = { left: 0, top: 0, width: 0, height: 0 };\n    if (this.el.style.position === 'absolute') {\n      const containmentEl = this.el.parentElement;\n      const { left, top } = containmentEl.getBoundingClientRect();\n      containmentRect = { left, top, width: 0, height: 0 };\n    }\n    if (!this.temporalRect) return this;\n    Object.keys(this.temporalRect).forEach(key => {\n      const value = this.temporalRect[key];\n      const scaleReciprocal = key === 'width' || key === 'left' ? this.rectScale.x : key === 'height' || key === 'top' ? this.rectScale.y : 1;\n      this.el.style[key] = (value - containmentRect[key]) * scaleReciprocal + 'px';\n    });\n    return this;\n  }\n\n  /** @internal */\n  protected _removeHandlers(): DDResizable {\n    this.handlers.forEach(handle => handle.destroy());\n    delete this.handlers;\n    return this;\n  }\n\n  /** @internal */\n  protected _ui = (): DDUIData => {\n    const containmentEl = this.el.parentElement;\n    const containmentRect = containmentEl.getBoundingClientRect();\n    const newRect = { // Note: originalRect is a complex object, not a simple Rect, so copy out.\n      width: this.originalRect.width,\n      height: this.originalRect.height + this.scrolled,\n      left: this.originalRect.left,\n      top: this.originalRect.top - this.scrolled\n    };\n    const rect = this.temporalRect || newRect;\n    return {\n      position: {\n        left: (rect.left - containmentRect.left) * this.rectScale.x,\n        top: (rect.top - containmentRect.top) * this.rectScale.y\n      },\n      size: {\n        width: rect.width * this.rectScale.x,\n        height: rect.height * this.rectScale.y\n      }\n      /* Gridstack ONLY needs position set above... keep around in case.\n      element: [this.el], // The object representing the element to be resized\n      helper: [], // TODO: not support yet - The object representing the helper that's being resized\n      originalElement: [this.el],// we don't wrap here, so simplify as this.el //The object representing the original element before it is wrapped\n      originalPosition: { // The position represented as { left, top } before the resizable is resized\n        left: this.originalRect.left - containmentRect.left,\n        top: this.originalRect.top - containmentRect.top\n      },\n      originalSize: { // The size represented as { width, height } before the resizable is resized\n        width: this.originalRect.width,\n        height: this.originalRect.height\n      }\n      */\n    };\n  }\n}\n","/**\n * dd-draggable.ts 12.1.2\n * Copyright (c) 2021-2024  Alain Dumesny - see GridStack root license\n */\n\nimport { DDManager } from './dd-manager';\nimport { DragTransform, Utils } from './utils';\nimport { DDBaseImplement, HTMLElementExtendOpt } from './dd-base-impl';\nimport { GridItemHTMLElement, DDUIData, GridStackNode, GridStackPosition, DDDragOpt } from './types';\nimport { DDElementHost } from './dd-element';\nimport { isTouch, touchend, touchmove, touchstart, pointerdown } from './dd-touch';\nimport { GridHTMLElement } from './gridstack';\n\ninterface DragOffset {\n  left: number;\n  top: number;\n  width: number;\n  height: number;\n  offsetLeft: number;\n  offsetTop: number;\n}\n\ninterface GridStackNodeRotate extends GridStackNode {\n  _origRotate?: GridStackPosition;\n}\n\ntype DDDragEvent = 'drag' | 'dragstart' | 'dragstop';\n\n// make sure we are not clicking on known object that handles mouseDown\nconst skipMouseDown = 'input,textarea,button,select,option,[contenteditable=\"true\"],.ui-resizable-handle';\n\n// let count = 0; // TEST\n\nexport class DDDraggable extends DDBaseImplement implements HTMLElementExtendOpt<DDDragOpt> {\n  public helper: HTMLElement; // used by GridStackDDNative\n\n  /** @internal */\n  protected mouseDownEvent: MouseEvent;\n  /** @internal */\n  protected dragOffset: DragOffset;\n  /** @internal */\n  protected dragElementOriginStyle: Array<string>;\n  /** @internal */\n  protected dragEls: HTMLElement[];\n  /** @internal true while we are dragging an item around */\n  protected dragging: boolean;\n  /** @internal last drag event */\n  protected lastDrag: DragEvent;\n  /** @internal */\n  protected parentOriginStylePosition: string;\n  /** @internal */\n  protected helperContainment: HTMLElement;\n  /** @internal properties we change during dragging, and restore back */\n  protected static originStyleProp = ['width', 'height', 'transform', 'transform-origin', 'transition', 'pointerEvents', 'position', 'left', 'top', 'minWidth', 'willChange'];\n  /** @internal pause before we call the actual drag hit collision code */\n  protected dragTimeout: number;\n  /** @internal */\n  protected dragTransform: DragTransform = {\n    xScale: 1,\n    yScale: 1,\n    xOffset: 0,\n    yOffset: 0\n  };\n\n  constructor(public el: GridItemHTMLElement, public option: DDDragOpt = {}) {\n    super();\n\n    // get the element that is actually supposed to be dragged by\n    const handleName = option?.handle?.substring(1);\n    const n = el.gridstackNode;\n    this.dragEls = !handleName || el.classList.contains(handleName) ? [el] : (n?.subGrid ? [el.querySelector(option.handle) || el] : Array.from(el.querySelectorAll(option.handle)));\n    if (this.dragEls.length === 0) {\n      this.dragEls = [el];\n    }\n    // create var event binding so we can easily remove and still look like TS methods (unlike anonymous functions)\n    this._mouseDown = this._mouseDown.bind(this);\n    this._mouseMove = this._mouseMove.bind(this);\n    this._mouseUp = this._mouseUp.bind(this);\n    this._keyEvent = this._keyEvent.bind(this);\n    this.enable();\n  }\n\n  public on(event: DDDragEvent, callback: (event: DragEvent) => void): void {\n    super.on(event, callback);\n  }\n\n  public off(event: DDDragEvent): void {\n    super.off(event);\n  }\n\n  public enable(): void {\n    if (this.disabled === false) return;\n    super.enable();\n    this.dragEls.forEach(dragEl => {\n      dragEl.addEventListener('mousedown', this._mouseDown);\n      if (isTouch) {\n        dragEl.addEventListener('touchstart', touchstart);\n        dragEl.addEventListener('pointerdown', pointerdown);\n        // dragEl.style.touchAction = 'none'; // not needed unlike pointerdown doc comment\n      }\n    });\n    this.el.classList.remove('ui-draggable-disabled');\n  }\n\n  public disable(forDestroy = false): void {\n    if (this.disabled === true) return;\n    super.disable();\n    this.dragEls.forEach(dragEl => {\n      dragEl.removeEventListener('mousedown', this._mouseDown);\n      if (isTouch) {\n        dragEl.removeEventListener('touchstart', touchstart);\n        dragEl.removeEventListener('pointerdown', pointerdown);\n      }\n    });\n    if (!forDestroy) this.el.classList.add('ui-draggable-disabled');\n  }\n\n  public destroy(): void {\n    if (this.dragTimeout) window.clearTimeout(this.dragTimeout);\n    delete this.dragTimeout;\n    if (this.mouseDownEvent) this._mouseUp(this.mouseDownEvent);\n    this.disable(true);\n    delete this.el;\n    delete this.helper;\n    delete this.option;\n    super.destroy();\n  }\n\n  public updateOption(opts: DDDragOpt): DDDraggable {\n    Object.keys(opts).forEach(key => this.option[key] = opts[key]);\n    return this;\n  }\n\n  /** @internal call when mouse goes down before a dragstart happens */\n  protected _mouseDown(e: MouseEvent): boolean {\n    // don't let more than one widget handle mouseStart\n    if (DDManager.mouseHandled) return;\n    if (e.button !== 0) return true; // only left click\n\n    // make sure we are not clicking on known object that handles mouseDown, or ones supplied by the user\n    if (!this.dragEls.find(el => el === e.target) && (e.target as HTMLElement).closest(skipMouseDown)) return true;\n    if (this.option.cancel) {\n      if ((e.target as HTMLElement).closest(this.option.cancel)) return true;\n    }\n\n    this.mouseDownEvent = e;\n    delete this.dragging;\n    delete DDManager.dragElement;\n    delete DDManager.dropElement;\n    // document handler so we can continue receiving moves as the item is 'fixed' position, and capture=true so WE get a first crack\n    document.addEventListener('mousemove', this._mouseMove, { capture: true, passive: true }); // true=capture, not bubble\n    document.addEventListener('mouseup', this._mouseUp, true);\n    if (isTouch) {\n      e.currentTarget.addEventListener('touchmove', touchmove);\n      e.currentTarget.addEventListener('touchend', touchend);\n    }\n\n    e.preventDefault();\n    // preventDefault() prevents blur event which occurs just after mousedown event.\n    // if an editable content has focus, then blur must be call\n    if (document.activeElement) (document.activeElement as HTMLElement).blur();\n\n    DDManager.mouseHandled = true;\n    return true;\n  }\n\n  /** @internal method to call actual drag event */\n  protected _callDrag(e: DragEvent): void {\n    if (!this.dragging) return;\n    const ev = Utils.initEvent<DragEvent>(e, { target: this.el, type: 'drag' });\n    if (this.option.drag) {\n      this.option.drag(ev, this.ui());\n    }\n    this.triggerEvent('drag', ev);\n  }\n\n  /** @internal called when the main page (after successful mousedown) receives a move event to drag the item around the screen */\n  protected _mouseMove(e: DragEvent): boolean {\n    // console.log(`${count++} move ${e.x},${e.y}`)\n    const s = this.mouseDownEvent;\n    this.lastDrag = e;\n\n    if (this.dragging) {\n      this._dragFollow(e);\n      // delay actual grid handling drag until we pause for a while if set\n      if (DDManager.pauseDrag) {\n        const pause = Number.isInteger(DDManager.pauseDrag) ? DDManager.pauseDrag as number : 100;\n        if (this.dragTimeout) window.clearTimeout(this.dragTimeout);\n        this.dragTimeout = window.setTimeout(() => this._callDrag(e), pause);\n      } else {\n        this._callDrag(e);\n      }\n    } else if (Math.abs(e.x - s.x) + Math.abs(e.y - s.y) > 3) {\n      /**\n       * don't start unless we've moved at least 3 pixels\n       */\n      this.dragging = true;\n      DDManager.dragElement = this;\n      // if we're dragging an actual grid item, set the current drop as the grid (to detect enter/leave)\n      const grid = this.el.gridstackNode?.grid;\n      if (grid) {\n        DDManager.dropElement = (grid.el as DDElementHost).ddElement.ddDroppable;\n      } else {\n        delete DDManager.dropElement;\n      }\n      this.helper = this._createHelper();\n      this._setupHelperContainmentStyle();\n      this.dragTransform = Utils.getValuesFromTransformedElement(this.helperContainment);\n      this.dragOffset = this._getDragOffset(e, this.el, this.helperContainment);\n      this._setupHelperStyle(e);\n\n      const ev = Utils.initEvent<DragEvent>(e, { target: this.el, type: 'dragstart' });\n      if (this.option.start) {\n        this.option.start(ev, this.ui());\n      }\n      this.triggerEvent('dragstart', ev);\n      // now track keyboard events to cancel or rotate\n      document.addEventListener('keydown', this._keyEvent);\n    }\n    // e.preventDefault(); // passive = true. OLD: was needed otherwise we get text sweep text selection as we drag around\n    return true;\n  }\n\n  /** @internal call when the mouse gets released to drop the item at current location */\n  protected _mouseUp(e: MouseEvent): void {\n    document.removeEventListener('mousemove', this._mouseMove, true);\n    document.removeEventListener('mouseup', this._mouseUp, true);\n    if (isTouch && e.currentTarget) { // destroy() during nested grid call us again wit fake _mouseUp\n      e.currentTarget.removeEventListener('touchmove', touchmove, true);\n      e.currentTarget.removeEventListener('touchend', touchend, true);\n    }\n    if (this.dragging) {\n      delete this.dragging;\n      delete (this.el.gridstackNode as GridStackNodeRotate)?._origRotate;\n      document.removeEventListener('keydown', this._keyEvent);\n\n      // reset the drop target if dragging over ourself (already parented, just moving during stop callback below)\n      if (DDManager.dropElement?.el === this.el.parentElement) {\n        delete DDManager.dropElement;\n      }\n\n      this.helperContainment.style.position = this.parentOriginStylePosition || null;\n      if (this.helper !== this.el) this.helper.remove(); // hide now\n      this._removeHelperStyle();\n\n      const ev = Utils.initEvent<DragEvent>(e, { target: this.el, type: 'dragstop' });\n      if (this.option.stop) {\n        this.option.stop(ev); // NOTE: destroy() will be called when removing item, so expect NULL ptr after!\n      }\n      this.triggerEvent('dragstop', ev);\n\n      // call the droppable method to receive the item\n      if (DDManager.dropElement) {\n        DDManager.dropElement.drop(e);\n      }\n    }\n    delete this.helper;\n    delete this.mouseDownEvent;\n    delete DDManager.dragElement;\n    delete DDManager.dropElement;\n    delete DDManager.mouseHandled;\n    e.preventDefault();\n  }\n\n  /** @internal call when keys are being pressed - use Esc to cancel, R to rotate */\n  protected _keyEvent(e: KeyboardEvent): void {\n    const n = this.el.gridstackNode as GridStackNodeRotate;\n    const grid = n?.grid || (DDManager.dropElement?.el as GridHTMLElement)?.gridstack;\n\n    if (e.key === 'Escape') {\n      if (n && n._origRotate) {\n        n._orig = n._origRotate;\n        delete n._origRotate;\n      }\n      grid?.cancelDrag();\n      this._mouseUp(this.mouseDownEvent);\n    } else if (n && grid && (e.key === 'r' || e.key === 'R')) {\n      if (!Utils.canBeRotated(n)) return;\n      n._origRotate = n._origRotate || { ...n._orig }; // store the real orig size in case we Esc after doing rotation\n      delete n._moving; // force rotate to happen (move waits for >50% coverage otherwise)\n      grid.setAnimation(false) // immediate rotate so _getDragOffset() gets the right dom size below\n        .rotate(n.el, { top: -this.dragOffset.offsetTop, left: -this.dragOffset.offsetLeft })\n        .setAnimation();\n      n._moving = true;\n      this.dragOffset = this._getDragOffset(this.lastDrag, n.el, this.helperContainment);\n      this.helper.style.width = this.dragOffset.width + 'px';\n      this.helper.style.height = this.dragOffset.height + 'px';\n      Utils.swap(n._orig, 'w', 'h');\n      delete n._rect;\n      this._mouseMove(this.lastDrag);\n    }\n  }\n\n  /** @internal create a clone copy (or user defined method) of the original drag item if set */\n  protected _createHelper(): HTMLElement {\n    let helper = this.el;\n    if (typeof this.option.helper === 'function') {\n      helper = this.option.helper(this.el);\n    } else if (this.option.helper === 'clone') {\n      helper = Utils.cloneNode(this.el);\n    }\n    if (!helper.parentElement) {\n      Utils.appendTo(helper, this.option.appendTo === 'parent' ? this.el.parentElement : this.option.appendTo);\n    }\n    this.dragElementOriginStyle = DDDraggable.originStyleProp.map(prop => this.el.style[prop]);\n    return helper;\n  }\n\n  /** @internal set the fix position of the dragged item */\n  protected _setupHelperStyle(e: DragEvent): DDDraggable {\n    this.helper.classList.add('ui-draggable-dragging');\n    // TODO: set all at once with style.cssText += ... ? https://stackoverflow.com/questions/3968593\n    const style = this.helper.style;\n    style.pointerEvents = 'none'; // needed for over items to get enter/leave\n    // style.cursor = 'move'; //  TODO: can't set with pointerEvents=none ! (no longer in CSS either as no-op)\n    style.width = this.dragOffset.width + 'px';\n    style.height = this.dragOffset.height + 'px';\n    style.willChange = 'left, top';\n    style.position = 'fixed'; // let us drag between grids by not clipping as parent .grid-stack is position: 'relative'\n    this._dragFollow(e); // now position it\n    style.transition = 'none'; // show up instantly\n    setTimeout(() => {\n      if (this.helper) {\n        style.transition = null; // recover animation\n      }\n    }, 0);\n    return this;\n  }\n\n  /** @internal restore back the original style before dragging */\n  protected _removeHelperStyle(): DDDraggable {\n    this.helper.classList.remove('ui-draggable-dragging');\n    const node = (this.helper as GridItemHTMLElement)?.gridstackNode;\n    // don't bother restoring styles if we're gonna remove anyway...\n    if (!node?._isAboutToRemove && this.dragElementOriginStyle) {\n      const helper = this.helper;\n      // don't animate, otherwise we animate offseted when switching back to 'absolute' from 'fixed'.\n      // TODO: this also removes resizing animation which doesn't have this issue, but others.\n      // Ideally both would animate ('move' would immediately restore 'absolute' and adjust coordinate to match,\n      // then trigger a delay (repaint) to restore to final dest with animate) but then we need to make sure 'resizestop'\n      // is called AFTER 'transitionend' event is received (see https://github.com/gridstack/gridstack.js/issues/2033)\n      const transition = this.dragElementOriginStyle['transition'] || null;\n      helper.style.transition = this.dragElementOriginStyle['transition'] = 'none'; // can't be NULL #1973\n      DDDraggable.originStyleProp.forEach(prop => helper.style[prop] = this.dragElementOriginStyle[prop] || null);\n      setTimeout(() => helper.style.transition = transition, 50); // recover animation from saved vars after a pause (0 isn't enough #1973)\n    }\n    delete this.dragElementOriginStyle;\n    return this;\n  }\n\n  /** @internal updates the top/left position to follow the mouse */\n  protected _dragFollow(e: DragEvent): void {\n    const containmentRect = { left: 0, top: 0 };\n    // if (this.helper.style.position === 'absolute') { // we use 'fixed'\n    //   const { left, top } = this.helperContainment.getBoundingClientRect();\n    //   containmentRect = { left, top };\n    // }\n    const style = this.helper.style;\n    const offset = this.dragOffset;\n    style.left = (e.clientX + offset.offsetLeft - containmentRect.left) * this.dragTransform.xScale + 'px';\n    style.top = (e.clientY + offset.offsetTop - containmentRect.top) * this.dragTransform.yScale + 'px';\n  }\n\n  /** @internal */\n  protected _setupHelperContainmentStyle(): DDDraggable {\n    this.helperContainment = this.helper.parentElement;\n    if (this.helper.style.position !== 'fixed') {\n      this.parentOriginStylePosition = this.helperContainment.style.position;\n      if (getComputedStyle(this.helperContainment).position.match(/static/)) {\n        this.helperContainment.style.position = 'relative';\n      }\n    }\n    return this;\n  }\n\n  /** @internal */\n  protected _getDragOffset(event: DragEvent, el: HTMLElement, parent: HTMLElement): DragOffset {\n\n    // in case ancestor has transform/perspective css properties that change the viewpoint\n    let xformOffsetX = 0;\n    let xformOffsetY = 0;\n    if (parent) {\n      xformOffsetX = this.dragTransform.xOffset;\n      xformOffsetY = this.dragTransform.yOffset;\n    }\n\n    const targetOffset = el.getBoundingClientRect();\n    return {\n      left: targetOffset.left,\n      top: targetOffset.top,\n      offsetLeft: - event.clientX + targetOffset.left - xformOffsetX,\n      offsetTop: - event.clientY + targetOffset.top - xformOffsetY,\n      width: targetOffset.width * this.dragTransform.xScale,\n      height: targetOffset.height * this.dragTransform.yScale\n    };\n  }\n\n  /** @internal TODO: set to public as called by DDDroppable! */\n  public ui(): DDUIData {\n    const containmentEl = this.el.parentElement;\n    const containmentRect = containmentEl.getBoundingClientRect();\n    const offset = this.helper.getBoundingClientRect();\n    return {\n      position: { //Current CSS position of the helper as { top, left } object\n        top: (offset.top - containmentRect.top) * this.dragTransform.yScale,\n        left: (offset.left - containmentRect.left) * this.dragTransform.xScale\n      }\n      /* not used by GridStack for now...\n      helper: [this.helper], //The object arr representing the helper that's being dragged.\n      offset: { top: offset.top, left: offset.left } // Current offset position of the helper as { top, left } object.\n      */\n    };\n  }\n}\n","/**\n * dd-droppable.ts 12.1.2\n * Copyright (c) 2021-2024  Alain Dumesny - see GridStack root license\n */\n\nimport { DDDraggable } from './dd-draggable';\nimport { DDManager } from './dd-manager';\nimport { DDBaseImplement, HTMLElementExtendOpt } from './dd-base-impl';\nimport { Utils } from './utils';\nimport { DDElementHost } from './dd-element';\nimport { isTouch, pointerenter, pointerleave } from './dd-touch';\nimport { DDUIData } from './types';\n\nexport interface DDDroppableOpt {\n  accept?: string | ((el: HTMLElement) => boolean);\n  drop?: (event: DragEvent, ui: DDUIData) => void;\n  over?: (event: DragEvent, ui: DDUIData) => void;\n  out?: (event: DragEvent, ui: DDUIData) => void;\n}\n\n// let count = 0; // TEST\n\nexport class DDDroppable extends DDBaseImplement implements HTMLElementExtendOpt<DDDroppableOpt> {\n\n  public accept: (el: HTMLElement) => boolean;\n\n  constructor(public el: HTMLElement, public option: DDDroppableOpt = {}) {\n    super();\n    // create var event binding so we can easily remove and still look like TS methods (unlike anonymous functions)\n    this._mouseEnter = this._mouseEnter.bind(this);\n    this._mouseLeave = this._mouseLeave.bind(this);\n    this.enable();\n    this._setupAccept();\n  }\n\n  public on(event: 'drop' | 'dropover' | 'dropout', callback: (event: DragEvent) => void): void {\n    super.on(event, callback);\n  }\n\n  public off(event: 'drop' | 'dropover' | 'dropout'): void {\n    super.off(event);\n  }\n\n  public enable(): void {\n    if (this.disabled === false) return;\n    super.enable();\n    this.el.classList.add('ui-droppable');\n    this.el.classList.remove('ui-droppable-disabled');\n    this.el.addEventListener('mouseenter', this._mouseEnter);\n    this.el.addEventListener('mouseleave', this._mouseLeave);\n    if (isTouch) {\n      this.el.addEventListener('pointerenter', pointerenter);\n      this.el.addEventListener('pointerleave', pointerleave);\n    }\n  }\n\n  public disable(forDestroy = false): void {\n    if (this.disabled === true) return;\n    super.disable();\n    this.el.classList.remove('ui-droppable');\n    if (!forDestroy) this.el.classList.add('ui-droppable-disabled');\n    this.el.removeEventListener('mouseenter', this._mouseEnter);\n    this.el.removeEventListener('mouseleave', this._mouseLeave);\n    if (isTouch) {\n      this.el.removeEventListener('pointerenter', pointerenter);\n      this.el.removeEventListener('pointerleave', pointerleave);\n    }\n  }\n\n  public destroy(): void {\n    this.disable(true);\n    this.el.classList.remove('ui-droppable');\n    this.el.classList.remove('ui-droppable-disabled');\n    super.destroy();\n  }\n\n  public updateOption(opts: DDDroppableOpt): DDDroppable {\n    Object.keys(opts).forEach(key => this.option[key] = opts[key]);\n    this._setupAccept();\n    return this;\n  }\n\n  /** @internal called when the cursor enters our area - prepare for a possible drop and track leaving */\n  protected _mouseEnter(e: MouseEvent): void {\n    // console.log(`${count++} Enter ${this.el.id || (this.el as GridHTMLElement).gridstack.opts.id}`); // TEST\n    if (!DDManager.dragElement) return;\n    if (!this._canDrop(DDManager.dragElement.el)) return;\n    e.preventDefault();\n    e.stopPropagation();\n\n    // make sure when we enter this, that the last one gets a leave FIRST to correctly cleanup as we don't always do\n    if (DDManager.dropElement && DDManager.dropElement !== this) {\n      DDManager.dropElement._mouseLeave(e as DragEvent, true); // calledByEnter = true\n    }\n    DDManager.dropElement = this;\n\n    const ev = Utils.initEvent<DragEvent>(e, { target: this.el, type: 'dropover' });\n    if (this.option.over) {\n      this.option.over(ev, this._ui(DDManager.dragElement))\n    }\n    this.triggerEvent('dropover', ev);\n    this.el.classList.add('ui-droppable-over');\n    // console.log('tracking'); // TEST\n  }\n\n  /** @internal called when the item is leaving our area, stop tracking if we had moving item */\n  protected _mouseLeave(e: MouseEvent, calledByEnter = false): void {\n    // console.log(`${count++} Leave ${this.el.id || (this.el as GridHTMLElement).gridstack.opts.id}`); // TEST\n    if (!DDManager.dragElement || DDManager.dropElement !== this) return;\n    e.preventDefault();\n    e.stopPropagation();\n\n    const ev = Utils.initEvent<DragEvent>(e, { target: this.el, type: 'dropout' });\n    if (this.option.out) {\n      this.option.out(ev, this._ui(DDManager.dragElement))\n    }\n    this.triggerEvent('dropout', ev);\n\n    if (DDManager.dropElement === this) {\n      delete DDManager.dropElement;\n      // console.log('not tracking'); // TEST\n\n      // if we're still over a parent droppable, send it an enter as we don't get one from leaving nested children\n      if (!calledByEnter) {\n        let parentDrop: DDDroppable;\n        let parent: DDElementHost = this.el.parentElement;\n        while (!parentDrop && parent) {\n          parentDrop = parent.ddElement?.ddDroppable;\n          parent = parent.parentElement;\n        }\n        if (parentDrop) {\n          parentDrop._mouseEnter(e);\n        }\n      }\n    }\n  }\n\n  /** item is being dropped on us - called by the drag mouseup handler - this calls the client drop event */\n  public drop(e: MouseEvent): void {\n    e.preventDefault();\n    const ev = Utils.initEvent<DragEvent>(e, { target: this.el, type: 'drop' });\n    if (this.option.drop) {\n      this.option.drop(ev, this._ui(DDManager.dragElement))\n    }\n    this.triggerEvent('drop', ev);\n  }\n\n  /** @internal true if element matches the string/method accept option */\n  protected _canDrop(el: HTMLElement): boolean {\n    return el && (!this.accept || this.accept(el));\n  }\n\n  /** @internal */\n  protected _setupAccept(): DDDroppable {\n    if (!this.option.accept) return this;\n    if (typeof this.option.accept === 'string') {\n      this.accept = (el: HTMLElement) => el.classList.contains(this.option.accept as string) || el.matches(this.option.accept as string);\n    } else {\n      this.accept = this.option.accept;\n    }\n    return this;\n  }\n\n  /** @internal */\n  protected _ui(drag: DDDraggable): DDUIData {\n    return {\n      draggable: drag.el,\n      ...drag.ui()\n    };\n  }\n}\n\n","/**\n * dd-elements.ts 12.1.2\n * Copyright (c) 2021-2024 Alain Dumesny - see GridStack root license\n */\n\nimport { DDResizable, DDResizableOpt } from './dd-resizable';\nimport { DDDragOpt, GridItemHTMLElement } from './types';\nimport { DDDraggable } from './dd-draggable';\nimport { DDDroppable, DDDroppableOpt } from './dd-droppable';\n\nexport interface DDElementHost extends GridItemHTMLElement {\n  ddElement?: DDElement;\n}\n\nexport class DDElement {\n\n  static init(el: DDElementHost): DDElement {\n    if (!el.ddElement) { el.ddElement = new DDElement(el); }\n    return el.ddElement;\n  }\n\n  public ddDraggable?: DDDraggable;\n  public ddDroppable?: DDDroppable;\n  public ddResizable?: DDResizable;\n\n  constructor(public el: DDElementHost) {}\n\n  public on(eventName: string, callback: (event: MouseEvent) => void): DDElement {\n    if (this.ddDraggable && ['drag', 'dragstart', 'dragstop'].indexOf(eventName) > -1) {\n      this.ddDraggable.on(eventName as 'drag' | 'dragstart' | 'dragstop', callback);\n    } else if (this.ddDroppable && ['drop', 'dropover', 'dropout'].indexOf(eventName) > -1) {\n      this.ddDroppable.on(eventName as 'drop' | 'dropover' | 'dropout', callback);\n    } else if (this.ddResizable && ['resizestart', 'resize', 'resizestop'].indexOf(eventName) > -1) {\n      this.ddResizable.on(eventName as 'resizestart' | 'resize' | 'resizestop', callback);\n    }\n    return this;\n  }\n\n  public off(eventName: string): DDElement {\n    if (this.ddDraggable && ['drag', 'dragstart', 'dragstop'].indexOf(eventName) > -1) {\n      this.ddDraggable.off(eventName as 'drag' | 'dragstart' | 'dragstop');\n    } else if (this.ddDroppable && ['drop', 'dropover', 'dropout'].indexOf(eventName) > -1) {\n      this.ddDroppable.off(eventName as 'drop' | 'dropover' | 'dropout');\n    } else if (this.ddResizable && ['resizestart', 'resize', 'resizestop'].indexOf(eventName) > -1) {\n      this.ddResizable.off(eventName as 'resizestart' | 'resize' | 'resizestop');\n    }\n    return this;\n  }\n\n  public setupDraggable(opts: DDDragOpt): DDElement {\n    if (!this.ddDraggable) {\n      this.ddDraggable = new DDDraggable(this.el, opts);\n    } else {\n      this.ddDraggable.updateOption(opts);\n    }\n    return this;\n  }\n\n  public cleanDraggable(): DDElement {\n    if (this.ddDraggable) {\n      this.ddDraggable.destroy();\n      delete this.ddDraggable;\n    }\n    return this;\n  }\n\n  public setupResizable(opts: DDResizableOpt): DDElement {\n    if (!this.ddResizable) {\n      this.ddResizable = new DDResizable(this.el, opts);\n    } else {\n      this.ddResizable.updateOption(opts);\n    }\n    return this;\n  }\n\n  public cleanResizable(): DDElement {\n    if (this.ddResizable) {\n      this.ddResizable.destroy();\n      delete this.ddResizable;\n    }\n    return this;\n  }\n\n  public setupDroppable(opts: DDDroppableOpt): DDElement {\n    if (!this.ddDroppable) {\n      this.ddDroppable = new DDDroppable(this.el, opts);\n    } else {\n      this.ddDroppable.updateOption(opts);\n    }\n    return this;\n  }\n\n  public cleanDroppable(): DDElement {\n    if (this.ddDroppable) {\n      this.ddDroppable.destroy();\n      delete this.ddDroppable;\n    }\n    return this;\n  }\n}\n","/*!\r\n * GridStack 12.1.2\r\n * https://gridstackjs.com/\r\n *\r\n * Copyright (c) 2021-2024  Alain Dumesny\r\n * see root license https://github.com/gridstack/gridstack.js/tree/master/LICENSE\r\n */\r\nimport { GridStackEngine } from './gridstack-engine';\r\nimport { Utils, HeightData, obsolete, DragTransform } from './utils';\r\nimport {\r\n  gridDefaults, ColumnOptions, GridItemHTMLElement, GridStackElement, GridStackEventHandlerCallback,\r\n  GridStackNode, GridStackWidget, numberOrString, DDUIData, DDDragOpt, GridStackPosition, GridStackOptions,\r\n  GridStackEventHandler, GridStackNodesHandler, AddRemoveFcn, SaveFcn, CompactOptions, GridStackMoveOpts, ResizeToContentFcn, GridStackDroppedHandler, GridStackElementHandler,\r\n  Position, RenderFcn\r\n} from './types';\r\n\r\n/*\r\n * and include D&D by default\r\n * TODO: while we could generate a gridstack-static.js at smaller size - saves about 31k (41k -> 72k)\r\n * I don't know how to generate the DD only code at the remaining 31k to delay load as code depends on Gridstack.ts\r\n * also it caused loading issues in prod - see https://github.com/gridstack/gridstack.js/issues/2039\r\n */\r\nimport { DDGridStack } from './dd-gridstack';\r\nimport { isTouch } from './dd-touch';\r\nimport { DDManager } from './dd-manager';\r\nimport { DDElementHost } from './dd-element'; /** global instance */\r\nconst dd = new DDGridStack;\r\n\r\n// export all dependent file as well to make it easier for users to just import the main file\r\nexport * from './types';\r\nexport * from './utils';\r\nexport * from './gridstack-engine';\r\nexport * from './dd-gridstack';\r\n\r\nexport interface GridHTMLElement extends HTMLElement {\r\n  gridstack?: GridStack; // grid's parent DOM element points back to grid class\r\n}\r\n/** list of possible events, or space separated list of them */\r\nexport type GridStackEvent = 'added' | 'change' | 'disable' | 'drag' | 'dragstart' | 'dragstop' | 'dropped' |\r\n  'enable' | 'removed' | 'resize' | 'resizestart' | 'resizestop' | 'resizecontent';\r\n\r\n/** Defines the coordinates of an object */\r\nexport interface MousePosition {\r\n  top: number;\r\n  left: number;\r\n}\r\n\r\n/** Defines the position of a cell inside the grid*/\r\nexport interface CellPosition {\r\n  x: number;\r\n  y: number;\r\n}\r\n\r\n// extend with internal fields we need - TODO: move other items in here\r\ninterface InternalGridStackOptions extends GridStackOptions {\r\n  _alwaysShowResizeHandle?: true | false | 'mobile'; // so we can restore for save\r\n}\r\n\r\n/**\r\n * Main gridstack class - you will need to call `GridStack.init()` first to initialize your grid.\r\n * Note: your grid elements MUST have the following classes for the CSS layout to work:\r\n * @example\r\n * <div class=\"grid-stack\">\r\n *   <div class=\"grid-stack-item\">\r\n *     <div class=\"grid-stack-item-content\">Item 1</div>\r\n *   </div>\r\n * </div>\r\n */\r\nexport class GridStack {\r\n\r\n  /**\r\n   * initializing the HTML element, or selector string, into a grid will return the grid. Calling it again will\r\n   * simply return the existing instance (ignore any passed options). There is also an initAll() version that support\r\n   * multiple grids initialization at once. Or you can use addGrid() to create the entire grid from JSON.\r\n   * @param options grid options (optional)\r\n   * @param elOrString element or CSS selector (first one used) to convert to a grid (default to '.grid-stack' class selector)\r\n   *\r\n   * @example\r\n   * const grid = GridStack.init();\r\n   *\r\n   * Note: the HTMLElement (of type GridHTMLElement) will store a `gridstack: GridStack` value that can be retrieve later\r\n   * const grid = document.querySelector('.grid-stack').gridstack;\r\n   */\r\n  public static init(options: GridStackOptions = {}, elOrString: GridStackElement = '.grid-stack'): GridStack {\r\n    if (typeof document === 'undefined') return null; // temp workaround SSR\r\n    const el = GridStack.getGridElement(elOrString);\r\n    if (!el) {\r\n      if (typeof elOrString === 'string') {\r\n        console.error('GridStack.initAll() no grid was found with selector \"' + elOrString + '\" - element missing or wrong selector ?' +\r\n          '\\nNote: \".grid-stack\" is required for proper CSS styling and drag/drop, and is the default selector.');\r\n      } else {\r\n        console.error('GridStack.init() no grid element was passed.');\r\n      }\r\n      return null;\r\n    }\r\n    if (!el.gridstack) {\r\n      el.gridstack = new GridStack(el, Utils.cloneDeep(options));\r\n    }\r\n    return el.gridstack\r\n  }\r\n\r\n  /**\r\n   * Will initialize a list of elements (given a selector) and return an array of grids.\r\n   * @param options grid options (optional)\r\n   * @param selector elements selector to convert to grids (default to '.grid-stack' class selector)\r\n   *\r\n   * @example\r\n   * const grids = GridStack.initAll();\r\n   * grids.forEach(...)\r\n   */\r\n  public static initAll(options: GridStackOptions = {}, selector = '.grid-stack'): GridStack[] {\r\n    const grids: GridStack[] = [];\r\n    if (typeof document === 'undefined') return grids; // temp workaround SSR\r\n    GridStack.getGridElements(selector).forEach(el => {\r\n      if (!el.gridstack) {\r\n        el.gridstack = new GridStack(el, Utils.cloneDeep(options));\r\n      }\r\n      grids.push(el.gridstack);\r\n    });\r\n    if (grids.length === 0) {\r\n      console.error('GridStack.initAll() no grid was found with selector \"' + selector + '\" - element missing or wrong selector ?' +\r\n        '\\nNote: \".grid-stack\" is required for proper CSS styling and drag/drop, and is the default selector.');\r\n    }\r\n    return grids;\r\n  }\r\n\r\n  /**\r\n   * call to create a grid with the given options, including loading any children from JSON structure. This will call GridStack.init(), then\r\n   * grid.load() on any passed children (recursively). Great alternative to calling init() if you want entire grid to come from\r\n   * JSON serialized data, including options.\r\n   * @param parent HTML element parent to the grid\r\n   * @param opt grids options used to initialize the grid, and list of children\r\n   */\r\n  public static addGrid(parent: HTMLElement, opt: GridStackOptions = {}): GridStack {\r\n    if (!parent) return null;\r\n\r\n    let el = parent as GridHTMLElement;\r\n    if (el.gridstack) {\r\n      // already a grid - set option and load data\r\n      const grid = el.gridstack;\r\n      if (opt) grid.opts = { ...grid.opts, ...opt };\r\n      if (opt.children !== undefined) grid.load(opt.children);\r\n      return grid;\r\n    }\r\n\r\n    // create the grid element, but check if the passed 'parent' already has grid styling and should be used instead\r\n    const parentIsGrid = parent.classList.contains('grid-stack');\r\n    if (!parentIsGrid || GridStack.addRemoveCB) {\r\n      if (GridStack.addRemoveCB) {\r\n        el = GridStack.addRemoveCB(parent, opt, true, true);\r\n      } else {\r\n        el = Utils.createDiv(['grid-stack', opt.class], parent);\r\n      }\r\n    }\r\n\r\n    // create grid class and load any children\r\n    const grid = GridStack.init(opt, el);\r\n    return grid;\r\n  }\r\n\r\n  /** call this method to register your engine instead of the default one.\r\n   * See instead `GridStackOptions.engineClass` if you only need to\r\n   * replace just one instance.\r\n   */\r\n  static registerEngine(engineClass: typeof GridStackEngine): void {\r\n    GridStack.engineClass = engineClass;\r\n  }\r\n\r\n  /**\r\n   * callback method use when new items|grids needs to be created or deleted, instead of the default\r\n   * item: <div class=\"grid-stack-item\"><div class=\"grid-stack-item-content\">w.content</div></div>\r\n   * grid: <div class=\"grid-stack\">grid content...</div>\r\n   * add = true: the returned DOM element will then be converted to a GridItemHTMLElement using makeWidget()|GridStack:init().\r\n   * add = false: the item will be removed from DOM (if not already done)\r\n   * grid = true|false for grid vs grid-items\r\n   */\r\n  public static addRemoveCB?: AddRemoveFcn;\r\n\r\n  /**\r\n   * callback during saving to application can inject extra data for each widget, on top of the grid layout properties\r\n   */\r\n  public static saveCB?: SaveFcn;\r\n\r\n  /**\r\n   * callback to create the content of widgets so the app can control how to store and restore it\r\n   * By default this lib will do 'el.textContent = w.content' forcing text only support for avoiding potential XSS issues.\r\n   */\r\n  public static renderCB?: RenderFcn = (el: HTMLElement, w: GridStackNode) => { if (el && w?.content) el.textContent = w.content; };\r\n\r\n  /** callback to use for resizeToContent instead of the built in one */\r\n  public static resizeToContentCB?: ResizeToContentFcn;\r\n  /** parent class for sizing content. defaults to '.grid-stack-item-content' */\r\n  public static resizeToContentParent = '.grid-stack-item-content';\r\n\r\n  /** scoping so users can call GridStack.Utils.sort() for example */\r\n  public static Utils = Utils;\r\n\r\n  /** scoping so users can call new GridStack.Engine(12) for example */\r\n  public static Engine = GridStackEngine;\r\n\r\n  /** engine used to implement non DOM grid functionality */\r\n  public engine: GridStackEngine;\r\n\r\n  /** point to a parent grid item if we're nested (inside a grid-item in between 2 Grids) */\r\n  public parentGridNode?: GridStackNode;\r\n\r\n  /** time to wait for animation (if enabled) to be done so content sizing can happen */\r\n  public animationDelay = 300 + 10;\r\n\r\n  protected static engineClass: typeof GridStackEngine;\r\n  protected resizeObserver: ResizeObserver;\r\n\r\n  /** @internal true if we got created by drag over gesture, so we can removed on drag out (temporary) */\r\n  public _isTemp?: boolean;\r\n\r\n  /** @internal create placeholder DIV as needed */\r\n  public get placeholder(): GridItemHTMLElement {\r\n    if (!this._placeholder) {\r\n      this._placeholder = Utils.createDiv([this.opts.placeholderClass, gridDefaults.itemClass, this.opts.itemClass]);\r\n      const placeholderChild = Utils.createDiv(['placeholder-content'], this._placeholder);\r\n      if (this.opts.placeholderText) {\r\n        placeholderChild.textContent = this.opts.placeholderText;\r\n      }\r\n    }\r\n    return this._placeholder;\r\n  }\r\n  /** @internal */\r\n  protected _placeholder: GridItemHTMLElement;\r\n  /** @internal prevent cached layouts from being updated when loading into small column layouts */\r\n  protected _ignoreLayoutsNodeChange: boolean;\r\n  /** @internal */\r\n  public _gsEventHandler = {};\r\n  /** @internal flag to keep cells square during resize */\r\n  protected _isAutoCellHeight: boolean;\r\n  /** @internal limit auto cell resizing method */\r\n  protected _sizeThrottle: () => void;\r\n  /** @internal limit auto cell resizing method */\r\n  protected prevWidth: number;\r\n  /** @internal extra row added when dragging at the bottom of the grid */\r\n  protected _extraDragRow = 0;\r\n  /** @internal true if nested grid should get column count from our width */\r\n  protected _autoColumn?: boolean;\r\n  /** @internal meant to store the scale of the active grid */\r\n  protected dragTransform: DragTransform = { xScale: 1, yScale: 1, xOffset: 0, yOffset: 0 };\r\n  protected responseLayout: ColumnOptions;\r\n  private _skipInitialResize: boolean;\r\n\r\n  /**\r\n   * Construct a grid item from the given element and options\r\n   * @param el the HTML element tied to this grid after it's been initialized\r\n   * @param opts grid options - public for classes to access, but use methods to modify!\r\n   */\r\n  public constructor(public el: GridHTMLElement, public opts: GridStackOptions = {}) {\r\n    el.gridstack = this;\r\n    this.opts = opts = opts || {}; // handles null/undefined/0\r\n\r\n    if (!el.classList.contains('grid-stack')) {\r\n      this.el.classList.add('grid-stack');\r\n    }\r\n\r\n    // if row property exists, replace minRow and maxRow instead\r\n    if (opts.row) {\r\n      opts.minRow = opts.maxRow = opts.row;\r\n      delete opts.row;\r\n    }\r\n    const rowAttr = Utils.toNumber(el.getAttribute('gs-row'));\r\n\r\n    // flag only valid in sub-grids (handled by parent, not here)\r\n    if (opts.column === 'auto') {\r\n      delete opts.column;\r\n    }\r\n    // save original setting so we can restore on save\r\n    if (opts.alwaysShowResizeHandle !== undefined) {\r\n      (opts as InternalGridStackOptions)._alwaysShowResizeHandle = opts.alwaysShowResizeHandle;\r\n    }\r\n\r\n    // cleanup responsive opts (must have columnWidth | breakpoints) then sort breakpoints by size (so we can match during resize)\r\n    const resp = opts.columnOpts;\r\n    if (resp) {\r\n      const bk = resp.breakpoints;\r\n      if (!resp.columnWidth && !bk?.length) {\r\n        delete opts.columnOpts;\r\n      } else {\r\n        resp.columnMax = resp.columnMax || 12;\r\n        if (bk?.length > 1) bk.sort((a, b) => (b.w || 0) - (a.w || 0));\r\n      }\r\n    }\r\n\r\n    // elements DOM attributes override any passed options (like CSS style) - merge the two together\r\n    const defaults: GridStackOptions = {\r\n      ...Utils.cloneDeep(gridDefaults),\r\n      column: Utils.toNumber(el.getAttribute('gs-column')) || gridDefaults.column,\r\n      minRow: rowAttr ? rowAttr : Utils.toNumber(el.getAttribute('gs-min-row')) || gridDefaults.minRow,\r\n      maxRow: rowAttr ? rowAttr : Utils.toNumber(el.getAttribute('gs-max-row')) || gridDefaults.maxRow,\r\n      staticGrid: Utils.toBool(el.getAttribute('gs-static')) || gridDefaults.staticGrid,\r\n      sizeToContent: Utils.toBool(el.getAttribute('gs-size-to-content')) || undefined,\r\n      draggable: {\r\n        handle: (opts.handleClass ? '.' + opts.handleClass : (opts.handle ? opts.handle : '')) || gridDefaults.draggable.handle,\r\n      },\r\n      removableOptions: {\r\n        accept: opts.itemClass || gridDefaults.removableOptions.accept,\r\n        decline: gridDefaults.removableOptions.decline\r\n      },\r\n    };\r\n    if (el.getAttribute('gs-animate')) { // default to true, but if set to false use that instead\r\n      defaults.animate = Utils.toBool(el.getAttribute('gs-animate'))\r\n    }\r\n\r\n    opts = Utils.defaults(opts, defaults);\r\n    this._initMargin(); // part of settings defaults...\r\n\r\n    // Now check if we're loading into !12 column mode FIRST so we don't do un-necessary work (like cellHeight = width / 12 then go 1 column)\r\n    this.checkDynamicColumn();\r\n    this._updateColumnVar(opts);\r\n\r\n    if (opts.rtl === 'auto') {\r\n      opts.rtl = (el.style.direction === 'rtl');\r\n    }\r\n    if (opts.rtl) {\r\n      this.el.classList.add('grid-stack-rtl');\r\n    }\r\n\r\n    // check if we're been nested, and if so update our style and keep pointer around (used during save)\r\n    const parentGridItem: GridItemHTMLElement = this.el.closest('.' + gridDefaults.itemClass);\r\n    const parentNode = parentGridItem?.gridstackNode;\r\n    if (parentNode) {\r\n      parentNode.subGrid = this;\r\n      this.parentGridNode = parentNode;\r\n      this.el.classList.add('grid-stack-nested');\r\n      parentNode.el.classList.add('grid-stack-sub-grid');\r\n    }\r\n\r\n    this._isAutoCellHeight = (opts.cellHeight === 'auto');\r\n    if (this._isAutoCellHeight || opts.cellHeight === 'initial') {\r\n      // make the cell content square initially (will use resize/column event to keep it square)\r\n      this.cellHeight(undefined);\r\n    } else {\r\n      // append unit if any are set\r\n      if (typeof opts.cellHeight == 'number' && opts.cellHeightUnit && opts.cellHeightUnit !== gridDefaults.cellHeightUnit) {\r\n        opts.cellHeight = opts.cellHeight + opts.cellHeightUnit;\r\n        delete opts.cellHeightUnit;\r\n      }\r\n      const val = opts.cellHeight;\r\n      delete opts.cellHeight; // force initial cellHeight() call to set the value\r\n      this.cellHeight(val);\r\n    }\r\n\r\n    // see if we need to adjust auto-hide\r\n    if (opts.alwaysShowResizeHandle === 'mobile') {\r\n      opts.alwaysShowResizeHandle = isTouch;\r\n    }\r\n\r\n    this._setStaticClass();\r\n\r\n    const engineClass = opts.engineClass || GridStack.engineClass || GridStackEngine;\r\n    this.engine = new engineClass({\r\n      column: this.getColumn(),\r\n      float: opts.float,\r\n      maxRow: opts.maxRow,\r\n      onChange: (cbNodes) => {\r\n        cbNodes.forEach(n => {\r\n          const el = n.el;\r\n          if (!el) return;\r\n          if (n._removeDOM) {\r\n            if (el) el.remove();\r\n            delete n._removeDOM;\r\n          } else {\r\n            this._writePosAttr(el, n);\r\n          }\r\n        });\r\n        this._updateContainerHeight();\r\n      }\r\n    });\r\n\r\n    if (opts.auto) {\r\n      this.batchUpdate(); // prevent in between re-layout #1535 TODO: this only set float=true, need to prevent collision check...\r\n      this.engine._loading = true; // loading collision check\r\n      this.getGridItems().forEach(el => this._prepareElement(el));\r\n      delete this.engine._loading;\r\n      this.batchUpdate(false);\r\n    }\r\n\r\n    // load any passed in children as well, which overrides any DOM layout done above\r\n    if (opts.children) {\r\n      const children = opts.children;\r\n      delete opts.children;\r\n      if (children.length) this.load(children); // don't load empty\r\n    }\r\n\r\n    this.setAnimation();\r\n\r\n    // dynamic grids require pausing during drag to detect over to nest vs push\r\n    if (opts.subGridDynamic && !DDManager.pauseDrag) DDManager.pauseDrag = true;\r\n    if (opts.draggable?.pause !== undefined) DDManager.pauseDrag = opts.draggable.pause;\r\n\r\n    this._setupRemoveDrop();\r\n    this._setupAcceptWidget();\r\n    this._updateResizeEvent();\r\n  }\r\n\r\n  private _updateColumnVar(opts: GridStackOptions = this.opts): void {\r\n    this.el.classList.add('gs-' + opts.column);\r\n    if (typeof opts.column === 'number') this.el.style.setProperty('--gs-column-width', `${100/opts.column}%`);\r\n  }\r\n\r\n  /**\r\n   * add a new widget and returns it.\r\n   *\r\n   * Widget will be always placed even if result height is more than actual grid height.\r\n   * You need to use `willItFit()` before calling addWidget for additional check.\r\n   * See also `makeWidget(el)` for DOM element.\r\n   *\r\n   * @example\r\n   * const grid = GridStack.init();\r\n   * grid.addWidget({w: 3, content: 'hello'});\r\n   *\r\n   * @param w GridStackWidget definition. used MakeWidget(el) if you have dom element instead.\r\n   */\r\n  public addWidget(w: GridStackWidget): GridItemHTMLElement {\r\n    if (typeof w === 'string') { console.error('V11: GridStack.addWidget() does not support string anymore. see #2736'); return; }\r\n    if ((w as HTMLElement).ELEMENT_NODE) { console.error('V11: GridStack.addWidget() does not support HTMLElement anymore. use makeWidget()'); return this.makeWidget(w as HTMLElement); }\r\n\r\n    let el: GridItemHTMLElement;\r\n    let node: GridStackNode = w;\r\n    node.grid = this;\r\n    if (node?.el) {\r\n      el = node.el; // re-use element stored in the node\r\n    } else if (GridStack.addRemoveCB) {\r\n      el = GridStack.addRemoveCB(this.el, w, true, false);\r\n    } else {\r\n      el = this.createWidgetDivs(node);\r\n    }\r\n\r\n    if (!el) return;\r\n\r\n    // if the caller ended up initializing the widget in addRemoveCB, or we stared with one already, skip the rest\r\n    node = el.gridstackNode;\r\n    if (node && el.parentElement === this.el && this.engine.nodes.find(n => n._id === node._id)) return el;\r\n\r\n    // Tempting to initialize the passed in opt with default and valid values, but this break knockout demos\r\n    // as the actual value are filled in when _prepareElement() calls el.getAttribute('gs-xyz') before adding the node.\r\n    // So make sure we load any DOM attributes that are not specified in passed in options (which override)\r\n    const domAttr = this._readAttr(el);\r\n    Utils.defaults(w, domAttr);\r\n    this.engine.prepareNode(w);\r\n    // this._writeAttr(el, w); why write possibly incorrect values back when makeWidget() will ?\r\n\r\n    this.el.appendChild(el);\r\n\r\n    this.makeWidget(el, w);\r\n\r\n    return el;\r\n  }\r\n\r\n  /** create the default grid item divs, and content (possibly lazy loaded) by using GridStack.renderCB() */\r\n  public createWidgetDivs(n: GridStackNode): HTMLElement {\r\n    const el = Utils.createDiv(['grid-stack-item', this.opts.itemClass]);\r\n    const cont = Utils.createDiv(['grid-stack-item-content'], el);\r\n\r\n    if (Utils.lazyLoad(n)) {\r\n      if (!n.visibleObservable) {\r\n        n.visibleObservable = new IntersectionObserver(([entry]) => { if (entry.isIntersecting) {\r\n          n.visibleObservable?.disconnect();\r\n          delete n.visibleObservable;\r\n          GridStack.renderCB(cont, n);\r\n          n.grid?.prepareDragDrop(n.el);\r\n        }});\r\n        window.setTimeout(() => n.visibleObservable?.observe(el)); // wait until callee sets position attributes\r\n      }\r\n    } else GridStack.renderCB(cont, n);\r\n\r\n    return el;\r\n  }\r\n\r\n  /**\r\n   * Convert an existing gridItem element into a sub-grid with the given (optional) options, else inherit them\r\n   * from the parent's subGrid options.\r\n   * @param el gridItem element to convert\r\n   * @param ops (optional) sub-grid options, else default to node, then parent settings, else defaults\r\n   * @param nodeToAdd (optional) node to add to the newly created sub grid (used when dragging over existing regular item)\r\n   * @param saveContent if true (default) the html inside .grid-stack-content will be saved to child widget\r\n   * @returns newly created grid\r\n   */\r\n  public makeSubGrid(el: GridItemHTMLElement, ops?: GridStackOptions, nodeToAdd?: GridStackNode, saveContent = true): GridStack {\r\n    let node = el.gridstackNode;\r\n    if (!node) {\r\n      node = this.makeWidget(el).gridstackNode;\r\n    }\r\n    if (node.subGrid?.el) return node.subGrid; // already done\r\n\r\n    // find the template subGrid stored on a parent as fallback...\r\n    let subGridTemplate: GridStackOptions; // eslint-disable-next-line @typescript-eslint/no-this-alias\r\n    let grid: GridStack = this;\r\n    while (grid && !subGridTemplate) {\r\n      subGridTemplate = grid.opts?.subGridOpts;\r\n      grid = grid.parentGridNode?.grid;\r\n    }\r\n    //... and set the create options\r\n    ops = Utils.cloneDeep({\r\n      // by default sub-grid inherit from us | parent, other than id, children, etc...\r\n      ...this.opts, id: undefined, children: undefined, column: 'auto', columnOpts: undefined, layout: 'list', subGridOpts: undefined,\r\n      ...(subGridTemplate || {}),\r\n      ...(ops || node.subGridOpts || {})\r\n    });\r\n    node.subGridOpts = ops;\r\n\r\n    // if column special case it set, remember that flag and set default\r\n    let autoColumn: boolean;\r\n    if (ops.column === 'auto') {\r\n      autoColumn = true;\r\n      ops.column = Math.max(node.w || 1, nodeToAdd?.w || 1);\r\n      delete ops.columnOpts; // driven by parent\r\n    }\r\n\r\n    // if we're converting an existing full item, move over the content to be the first sub item in the new grid\r\n    let content = node.el.querySelector('.grid-stack-item-content') as HTMLElement;\r\n    let newItem: HTMLElement;\r\n    let newItemOpt: GridStackNode;\r\n    if (saveContent) {\r\n      this._removeDD(node.el); // remove D&D since it's set on content div\r\n      newItemOpt = { ...node, x: 0, y: 0 };\r\n      Utils.removeInternalForSave(newItemOpt);\r\n      delete newItemOpt.subGridOpts;\r\n      if (node.content) {\r\n        newItemOpt.content = node.content;\r\n        delete node.content;\r\n      }\r\n      if (GridStack.addRemoveCB) {\r\n        newItem = GridStack.addRemoveCB(this.el, newItemOpt, true, false);\r\n      } else {\r\n        newItem = Utils.createDiv(['grid-stack-item']);\r\n        newItem.appendChild(content);\r\n        content = Utils.createDiv(['grid-stack-item-content'], node.el);\r\n      }\r\n      this.prepareDragDrop(node.el); // ... and restore original D&D\r\n    }\r\n\r\n    // if we're adding an additional item, make the container large enough to have them both\r\n    if (nodeToAdd) {\r\n      const w = autoColumn ? ops.column : node.w;\r\n      const h = node.h + nodeToAdd.h;\r\n      const style = node.el.style;\r\n      style.transition = 'none'; // show up instantly so we don't see scrollbar with nodeToAdd\r\n      this.update(node.el, { w, h });\r\n      setTimeout(() => style.transition = null); // recover animation\r\n    }\r\n\r\n    const subGrid = node.subGrid = GridStack.addGrid(content, ops);\r\n    if (nodeToAdd?._moving) subGrid._isTemp = true; // prevent re-nesting as we add over\r\n    if (autoColumn) subGrid._autoColumn = true;\r\n\r\n    // add the original content back as a child of hte newly created grid\r\n    if (saveContent) {\r\n      subGrid.makeWidget(newItem, newItemOpt);\r\n    }\r\n\r\n    // now add any additional node\r\n    if (nodeToAdd) {\r\n      if (nodeToAdd._moving) {\r\n        // create an artificial event even for the just created grid to receive this item\r\n        window.setTimeout(() => Utils.simulateMouseEvent(nodeToAdd._event, 'mouseenter', subGrid.el), 0);\r\n      } else {\r\n        subGrid.makeWidget(node.el, node);\r\n      }\r\n    }\r\n\r\n    // if sizedToContent, we need to re-calc the size of ourself\r\n    this.resizeToContentCheck(false, node);\r\n\r\n    return subGrid;\r\n  }\r\n\r\n  /**\r\n   * called when an item was converted into a nested grid to accommodate a dragged over item, but then item leaves - return back\r\n   * to the original grid-item. Also called to remove empty sub-grids when last item is dragged out (since re-creating is simple)\r\n   */\r\n  public removeAsSubGrid(nodeThatRemoved?: GridStackNode): void {\r\n    const pGrid = this.parentGridNode?.grid;\r\n    if (!pGrid) return;\r\n\r\n    pGrid.batchUpdate();\r\n    pGrid.removeWidget(this.parentGridNode.el, true, true);\r\n    this.engine.nodes.forEach(n => {\r\n      // migrate any children over and offsetting by our location\r\n      n.x += this.parentGridNode.x;\r\n      n.y += this.parentGridNode.y;\r\n      pGrid.makeWidget(n.el, n);\r\n    });\r\n    pGrid.batchUpdate(false);\r\n    if (this.parentGridNode) delete this.parentGridNode.subGrid;\r\n    delete this.parentGridNode;\r\n\r\n    // create an artificial event for the original grid now that this one is gone (got a leave, but won't get enter)\r\n    if (nodeThatRemoved) {\r\n      window.setTimeout(() => Utils.simulateMouseEvent(nodeThatRemoved._event, 'mouseenter', pGrid.el), 0);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * saves the current layout returning a list of widgets for serialization which might include any nested grids.\r\n   * @param saveContent if true (default) the latest html inside .grid-stack-content will be saved to GridStackWidget.content field, else it will\r\n   * be removed.\r\n   * @param saveGridOpt if true (default false), save the grid options itself, so you can call the new GridStack.addGrid()\r\n   * to recreate everything from scratch. GridStackOptions.children would then contain the widget list instead.\r\n   * @param saveCB callback for each node -> widget, so application can insert additional data to be saved into the widget data structure.\r\n   * @returns list of widgets or full grid option, including .children list of widgets\r\n   */\r\n  public save(saveContent = true, saveGridOpt = false, saveCB = GridStack.saveCB): GridStackWidget[] | GridStackOptions {\r\n    // return copied GridStackWidget (with optionally .el) we can modify at will...\r\n    const list = this.engine.save(saveContent, saveCB);\r\n\r\n    // check for HTML content and nested grids\r\n    list.forEach(n => {\r\n      if (saveContent && n.el && !n.subGrid && !saveCB) { // sub-grid are saved differently, not plain content\r\n        const itemContent = n.el.querySelector('.grid-stack-item-content');\r\n        n.content = itemContent?.innerHTML;\r\n        if (!n.content) delete n.content;\r\n      } else {\r\n        if (!saveContent && !saveCB) { delete n.content; }\r\n        // check for nested grid\r\n        if (n.subGrid?.el) {\r\n          const listOrOpt = n.subGrid.save(saveContent, saveGridOpt, saveCB);\r\n          n.subGridOpts = (saveGridOpt ? listOrOpt : { children: listOrOpt }) as GridStackOptions;\r\n          delete n.subGrid;\r\n        }\r\n      }\r\n      delete n.el;\r\n    });\r\n\r\n    // check if save entire grid options (needed for recursive) + children...\r\n    if (saveGridOpt) {\r\n      const o: InternalGridStackOptions = Utils.cloneDeep(this.opts);\r\n      // delete default values that will be recreated on launch\r\n      if (o.marginBottom === o.marginTop && o.marginRight === o.marginLeft && o.marginTop === o.marginRight) {\r\n        o.margin = o.marginTop;\r\n        delete o.marginTop; delete o.marginRight; delete o.marginBottom; delete o.marginLeft;\r\n      }\r\n      if (o.rtl === (this.el.style.direction === 'rtl')) { o.rtl = 'auto' }\r\n      if (this._isAutoCellHeight) {\r\n        o.cellHeight = 'auto'\r\n      }\r\n      if (this._autoColumn) {\r\n        o.column = 'auto';\r\n      }\r\n      const origShow = o._alwaysShowResizeHandle;\r\n      delete o._alwaysShowResizeHandle;\r\n      if (origShow !== undefined) {\r\n        o.alwaysShowResizeHandle = origShow;\r\n      } else {\r\n        delete o.alwaysShowResizeHandle;\r\n      }\r\n      Utils.removeInternalAndSame(o, gridDefaults);\r\n      o.children = list;\r\n      return o;\r\n    }\r\n\r\n    return list;\r\n  }\r\n\r\n  /**\r\n   * load the widgets from a list. This will call update() on each (matching by id) or add/remove widgets that are not there.\r\n   *\r\n   * @param items list of widgets definition to update/create\r\n   * @param addRemove boolean (default true) or callback method can be passed to control if and how missing widgets can be added/removed, giving\r\n   * the user control of insertion.\r\n   *\r\n   * @example\r\n   * see http://gridstackjs.com/demo/serialization.html\r\n   */\r\n  public load(items: GridStackWidget[], addRemove: boolean | AddRemoveFcn = GridStack.addRemoveCB || true): GridStack {\r\n    items = Utils.cloneDeep(items); // so we can mod\r\n    const column = this.getColumn();\r\n\r\n    // make sure size 1x1 (default) is present as it may need to override current sizes\r\n    items.forEach(n => { n.w = n.w || 1; n.h = n.h || 1 });\r\n\r\n    // sort items. those without coord will be appended last\r\n    items = Utils.sort(items);\r\n\r\n    this.engine.skipCacheUpdate = this._ignoreLayoutsNodeChange = true; // skip layout update\r\n\r\n    // if we're loading a layout into for example 1 column and items don't fit, make sure to save\r\n    // the original wanted layout so we can scale back up correctly #1471\r\n    let maxColumn = 0;\r\n    items.forEach(n => { maxColumn = Math.max(maxColumn, (n.x || 0) + n.w) });\r\n    if (maxColumn > this.engine.defaultColumn) this.engine.defaultColumn = maxColumn;\r\n    if (maxColumn > column) {\r\n      // if we're loading (from empty) into a smaller column, check for special responsive layout\r\n      if (this.engine.nodes.length === 0 && this.responseLayout) {\r\n        this.engine.nodes = items;\r\n        this.engine.columnChanged(maxColumn, column, this.responseLayout);\r\n        items = this.engine.nodes;\r\n        this.engine.nodes = [];\r\n        delete this.responseLayout;\r\n      } else this.engine.cacheLayout(items, maxColumn, true);\r\n    }\r\n\r\n    // if given a different callback, temporally set it as global option so creating will use it\r\n    const prevCB = GridStack.addRemoveCB;\r\n    if (typeof (addRemove) === 'function') GridStack.addRemoveCB = addRemove as AddRemoveFcn;\r\n\r\n    const removed: GridStackNode[] = [];\r\n    this.batchUpdate();\r\n\r\n    // if we are loading from empty temporarily remove animation\r\n    const blank = !this.engine.nodes.length;\r\n    const noAnim = blank && this.opts.animate;\r\n    if (noAnim) this.setAnimation(false);\r\n\r\n    // see if any items are missing from new layout and need to be removed first\r\n    if (!blank && addRemove) {\r\n      const copyNodes = [...this.engine.nodes]; // don't loop through array you modify\r\n      copyNodes.forEach(n => {\r\n        if (!n.id) return;\r\n        const item = Utils.find(items, n.id);\r\n        if (!item) {\r\n          if (GridStack.addRemoveCB) GridStack.addRemoveCB(this.el, n, false, false);\r\n          removed.push(n); // batch keep track\r\n          this.removeWidget(n.el, true, false);\r\n        }\r\n      });\r\n    }\r\n\r\n    // now add/update the widgets - starting with removing items in the new layout we will reposition\r\n    // to reduce collision and add no-coord ones at next available spot\r\n    this.engine._loading = true; // help with collision\r\n    const updateNodes: GridStackWidget[] = [];\r\n    this.engine.nodes = this.engine.nodes.filter(n => {\r\n      if (Utils.find(items, n.id)) { updateNodes.push(n); return false; } // remove if found from list\r\n      return true;\r\n    });\r\n    items.forEach(w => {\r\n      const item = Utils.find(updateNodes, w.id);\r\n      if (item) {\r\n        // if item sizes to content, re-use the exiting height so it's a better guess at the final size (same if width doesn't change)\r\n        if (Utils.shouldSizeToContent(item)) w.h = item.h;\r\n        // check if missing coord, in which case find next empty slot with new (or old if missing) sizes\r\n        this.engine.nodeBoundFix(w);\r\n        if (w.autoPosition || w.x === undefined || w.y === undefined) {\r\n          w.w = w.w || item.w;\r\n          w.h = w.h || item.h;\r\n          this.engine.findEmptyPosition(w);\r\n        }\r\n\r\n        // add back to current list BUT force a collision check if it 'appears' we didn't change to make sure we don't overlap others now\r\n        this.engine.nodes.push(item);\r\n        if (Utils.samePos(item, w) && this.engine.nodes.length > 1) {\r\n          this.moveNode(item, { ...w, forceCollide: true });\r\n          Utils.copyPos(w, item); // use possily updated values before update() is called next (no-op since already moved)\r\n        }\r\n\r\n        this.update(item.el, w);\r\n\r\n        if (w.subGridOpts?.children) { // update any sub grid as well\r\n          const sub = item.el.querySelector('.grid-stack') as GridHTMLElement;\r\n          if (sub && sub.gridstack) {\r\n            sub.gridstack.load(w.subGridOpts.children); // TODO: support updating grid options ?\r\n          }\r\n        }\r\n      } else if (addRemove) {\r\n        this.addWidget(w);\r\n      }\r\n    });\r\n\r\n    delete this.engine._loading; // done loading\r\n    this.engine.removedNodes = removed;\r\n    this.batchUpdate(false);\r\n\r\n    // after commit, clear that flag\r\n    delete this._ignoreLayoutsNodeChange;\r\n    delete this.engine.skipCacheUpdate;\r\n    prevCB ? GridStack.addRemoveCB = prevCB : delete GridStack.addRemoveCB;\r\n    if (noAnim) this.setAnimation(true, true); // delay adding animation back\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * use before calling a bunch of `addWidget()` to prevent un-necessary relayouts in between (more efficient)\r\n   * and get a single event callback. You will see no changes until `batchUpdate(false)` is called.\r\n   */\r\n  public batchUpdate(flag = true): GridStack {\r\n    this.engine.batchUpdate(flag);\r\n    if (!flag) {\r\n      this._updateContainerHeight();\r\n      this._triggerRemoveEvent();\r\n      this._triggerAddEvent();\r\n      this._triggerChangeEvent();\r\n    }\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * Gets current cell height.\r\n   */\r\n  public getCellHeight(forcePixel = false): number {\r\n    if (this.opts.cellHeight && this.opts.cellHeight !== 'auto' &&\r\n      (!forcePixel || !this.opts.cellHeightUnit || this.opts.cellHeightUnit === 'px')) {\r\n      return this.opts.cellHeight as number;\r\n    }\r\n    // do rem/em/cm/mm to px conversion\r\n    if (this.opts.cellHeightUnit === 'rem') {\r\n      return (this.opts.cellHeight as number) * parseFloat(getComputedStyle(document.documentElement).fontSize);\r\n    }\r\n    if (this.opts.cellHeightUnit === 'em') {\r\n      return (this.opts.cellHeight as number) * parseFloat(getComputedStyle(this.el).fontSize);\r\n    }\r\n    if (this.opts.cellHeightUnit === 'cm') {\r\n      // 1cm = 96px/2.54. See https://www.w3.org/TR/css-values-3/#absolute-lengths\r\n      return (this.opts.cellHeight as number) * (96 / 2.54);\r\n    }\r\n    if (this.opts.cellHeightUnit === 'mm') {\r\n      return (this.opts.cellHeight as number) * (96 / 2.54) / 10;\r\n    }\r\n    // else get first cell height\r\n    const el = this.el.querySelector('.' + this.opts.itemClass) as HTMLElement;\r\n    if (el) {\r\n      const h = Utils.toNumber(el.getAttribute('gs-h')) || 1; // since we don't write 1 anymore\r\n      return Math.round(el.offsetHeight / h);\r\n    }\r\n    // else do entire grid and # of rows (but doesn't work if min-height is the actual constrain)\r\n    const rows = parseInt(this.el.getAttribute('gs-current-row'));\r\n    return rows ? Math.round(this.el.getBoundingClientRect().height / rows) : this.opts.cellHeight as number;\r\n  }\r\n\r\n  /**\r\n   * Update current cell height - see `GridStackOptions.cellHeight` for format.\r\n   * This method rebuilds an internal CSS style sheet.\r\n   * Note: You can expect performance issues if call this method too often.\r\n   *\r\n   * @param val the cell height. If not passed (undefined), cells content will be made square (match width minus margin),\r\n   * if pass 0 the CSS will be generated by the application instead.\r\n   *\r\n   * @example\r\n   * grid.cellHeight(100); // same as 100px\r\n   * grid.cellHeight('70px');\r\n   * grid.cellHeight(grid.cellWidth() * 1.2);\r\n   */\r\n  public cellHeight(val?: numberOrString): GridStack {\r\n\r\n    // if not called internally, check if we're changing mode\r\n    if (val !== undefined) {\r\n      if (this._isAutoCellHeight !== (val === 'auto')) {\r\n        this._isAutoCellHeight = (val === 'auto');\r\n        this._updateResizeEvent();\r\n      }\r\n    }\r\n    if (val === 'initial' || val === 'auto') { val = undefined; }\r\n\r\n    // make item content be square\r\n    if (val === undefined) {\r\n      const marginDiff = - (this.opts.marginRight as number) - (this.opts.marginLeft as number)\r\n        + (this.opts.marginTop as number) + (this.opts.marginBottom as number);\r\n      val = this.cellWidth() + marginDiff;\r\n    }\r\n\r\n    const data = Utils.parseHeight(val);\r\n    if (this.opts.cellHeightUnit === data.unit && this.opts.cellHeight === data.h) {\r\n      return this;\r\n    }\r\n    this.opts.cellHeightUnit = data.unit;\r\n    this.opts.cellHeight = data.h;\r\n\r\n    // finally update var and container\r\n    this.el.style.setProperty('--gs-cell-height', `${this.opts.cellHeight}${this.opts.cellHeightUnit}`);\r\n    this._updateContainerHeight();\r\n    this.resizeToContentCheck();\r\n\r\n    return this;\r\n  }\r\n\r\n  /** Gets current cell width. */\r\n  public cellWidth(): number {\r\n    return this._widthOrContainer() / this.getColumn();\r\n  }\r\n  /** return our expected width (or parent) , and optionally of window for dynamic column check */\r\n  protected _widthOrContainer(forBreakpoint = false): number {\r\n    // use `offsetWidth` or `clientWidth` (no scrollbar) ?\r\n    // https://stackoverflow.com/questions/21064101/understanding-offsetwidth-clientwidth-scrollwidth-and-height-respectively\r\n    return forBreakpoint && this.opts.columnOpts?.breakpointForWindow ? window.innerWidth : (this.el.clientWidth || this.el.parentElement.clientWidth || window.innerWidth);\r\n  }\r\n  /** checks for dynamic column count for our current size, returning true if changed */\r\n  protected checkDynamicColumn(): boolean {\r\n    const resp = this.opts.columnOpts;\r\n    if (!resp || (!resp.columnWidth && !resp.breakpoints?.length)) return false;\r\n    const column = this.getColumn();\r\n    let newColumn = column;\r\n    const w = this._widthOrContainer(true);\r\n    if (resp.columnWidth) {\r\n      newColumn = Math.min(Math.round(w / resp.columnWidth) || 1, resp.columnMax);\r\n    } else {\r\n      // find the closest breakpoint (already sorted big to small) that matches\r\n      newColumn = resp.columnMax;\r\n      let i = 0;\r\n      while (i < resp.breakpoints.length && w <= resp.breakpoints[i].w) {\r\n        newColumn = resp.breakpoints[i++].c || column;\r\n      }\r\n    }\r\n    if (newColumn !== column) {\r\n      const bk = resp.breakpoints?.find(b => b.c === newColumn);\r\n      this.column(newColumn, bk?.layout || resp.layout);\r\n      return true;\r\n    }\r\n    return false;\r\n  }\r\n\r\n  /**\r\n   * re-layout grid items to reclaim any empty space. Options are:\r\n   * 'list' keep the widget left->right order the same, even if that means leaving an empty slot if things don't fit\r\n   * 'compact' might re-order items to fill any empty space\r\n   *\r\n   * doSort - 'false' to let you do your own sorting ahead in case you need to control a different order. (default to sort)\r\n   */\r\n  public compact(layout: CompactOptions = 'compact', doSort = true): GridStack {\r\n    this.engine.compact(layout, doSort);\r\n    this._triggerChangeEvent();\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * set the number of columns in the grid. Will update existing widgets to conform to new number of columns,\r\n   * as well as cache the original layout so you can revert back to previous positions without loss.\r\n   * @param column - Integer > 0 (default 12).\r\n   * @param layout specify the type of re-layout that will happen (position, size, etc...).\r\n   * Note: items will never be outside of the current column boundaries. default ('moveScale'). Ignored for 1 column\r\n   */\r\n  public column(column: number, layout: ColumnOptions = 'moveScale'): GridStack {\r\n    if (!column || column < 1 || this.opts.column === column) return this;\r\n\r\n    const oldColumn = this.getColumn();\r\n    this.opts.column = column;\r\n    if (!this.engine) {\r\n      // called in constructor, noting else to do but remember that breakpoint layout\r\n      this.responseLayout = layout;\r\n      return this;\r\n    }\r\n\r\n    this.engine.column = column;\r\n    this.el.classList.remove('gs-' + oldColumn);\r\n    this._updateColumnVar();\r\n\r\n    // update the items now\r\n    this.engine.columnChanged(oldColumn, column, layout);\r\n    if (this._isAutoCellHeight) this.cellHeight();\r\n\r\n    this.resizeToContentCheck(true); // wait for width resizing\r\n\r\n    // and trigger our event last...\r\n    this._ignoreLayoutsNodeChange = true; // skip layout update\r\n    this._triggerChangeEvent();\r\n    delete this._ignoreLayoutsNodeChange;\r\n\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * get the number of columns in the grid (default 12)\r\n   */\r\n  public getColumn(): number { return this.opts.column as number; }\r\n\r\n  /** returns an array of grid HTML elements (no placeholder) - used to iterate through our children in DOM order */\r\n  public getGridItems(): GridItemHTMLElement[] {\r\n    return Array.from(this.el.children)\r\n      .filter((el: HTMLElement) => el.matches('.' + this.opts.itemClass) && !el.matches('.' + this.opts.placeholderClass)) as GridItemHTMLElement[];\r\n  }\r\n\r\n  /** true if changeCB should be ignored due to column change, sizeToContent, loading, etc... which caller can ignore for dirty flag case */\r\n  public isIgnoreChangeCB(): boolean { return this._ignoreLayoutsNodeChange; }\r\n\r\n  /**\r\n   * Destroys a grid instance. DO NOT CALL any methods or access any vars after this as it will free up members.\r\n   * @param removeDOM if `false` grid and items HTML elements will not be removed from the DOM (Optional. Default `true`).\r\n   */\r\n  public destroy(removeDOM = true): GridStack {\r\n    if (!this.el) return; // prevent multiple calls\r\n    this.offAll();\r\n    this._updateResizeEvent(true);\r\n    this.setStatic(true, false); // permanently removes DD but don't set CSS class (we're going away)\r\n    this.setAnimation(false);\r\n    if (!removeDOM) {\r\n      this.removeAll(removeDOM);\r\n      this.el.removeAttribute('gs-current-row');\r\n    } else {\r\n      this.el.parentNode.removeChild(this.el);\r\n    }\r\n    if (this.parentGridNode) delete this.parentGridNode.subGrid;\r\n    delete this.parentGridNode;\r\n    delete this.opts;\r\n    delete this._placeholder?.gridstackNode;\r\n    delete this._placeholder;\r\n    delete this.engine;\r\n    delete this.el.gridstack; // remove circular dependency that would prevent a freeing\r\n    delete this.el;\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * enable/disable floating widgets (default: `false`) See [example](http://gridstackjs.com/demo/float.html)\r\n   */\r\n  public float(val: boolean): GridStack {\r\n    if (this.opts.float !== val) {\r\n      this.opts.float = this.engine.float = val;\r\n      this._triggerChangeEvent();\r\n    }\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * get the current float mode\r\n   */\r\n  public getFloat(): boolean {\r\n    return this.engine.float;\r\n  }\r\n\r\n  /**\r\n   * Get the position of the cell under a pixel on screen.\r\n   * @param position the position of the pixel to resolve in\r\n   * absolute coordinates, as an object with top and left properties\r\n   * @param useDocRelative if true, value will be based on document position vs parent position (Optional. Default false).\r\n   * Useful when grid is within `position: relative` element\r\n   *\r\n   * Returns an object with properties `x` and `y` i.e. the column and row in the grid.\r\n   */\r\n  public getCellFromPixel(position: MousePosition, useDocRelative = false): CellPosition {\r\n    const box = this.el.getBoundingClientRect();\r\n    // console.log(`getBoundingClientRect left: ${box.left} top: ${box.top} w: ${box.w} h: ${box.h}`)\r\n    let containerPos: { top: number, left: number };\r\n    if (useDocRelative) {\r\n      containerPos = { top: box.top + document.documentElement.scrollTop, left: box.left };\r\n      // console.log(`getCellFromPixel scrollTop: ${document.documentElement.scrollTop}`)\r\n    } else {\r\n      containerPos = { top: this.el.offsetTop, left: this.el.offsetLeft }\r\n      // console.log(`getCellFromPixel offsetTop: ${containerPos.left} offsetLeft: ${containerPos.top}`)\r\n    }\r\n    const relativeLeft = position.left - containerPos.left;\r\n    const relativeTop = position.top - containerPos.top;\r\n\r\n    const columnWidth = (box.width / this.getColumn());\r\n    const rowHeight = (box.height / parseInt(this.el.getAttribute('gs-current-row')));\r\n\r\n    return { x: Math.floor(relativeLeft / columnWidth), y: Math.floor(relativeTop / rowHeight) };\r\n  }\r\n\r\n  /** returns the current number of rows, which will be at least `minRow` if set */\r\n  public getRow(): number {\r\n    return Math.max(this.engine.getRow(), this.opts.minRow || 0);\r\n  }\r\n\r\n  /**\r\n   * Checks if specified area is empty.\r\n   * @param x the position x.\r\n   * @param y the position y.\r\n   * @param w the width of to check\r\n   * @param h the height of to check\r\n   */\r\n  public isAreaEmpty(x: number, y: number, w: number, h: number): boolean {\r\n    return this.engine.isAreaEmpty(x, y, w, h);\r\n  }\r\n\r\n  /**\r\n   * If you add elements to your grid by hand (or have some framework creating DOM), you have to tell gridstack afterwards to make them widgets.\r\n   * If you want gridstack to add the elements for you, use `addWidget()` instead.\r\n   * Makes the given element a widget and returns it.\r\n   * @param els widget or single selector to convert.\r\n   * @param options widget definition to use instead of reading attributes or using default sizing values\r\n   *\r\n   * @example\r\n   * const grid = GridStack.init();\r\n   * grid.el.innerHtml = '<div id=\"1\" gs-w=\"3\"></div><div id=\"2\"></div>';\r\n   * grid.makeWidget('1');\r\n   * grid.makeWidget('2', {w:2, content: 'hello'});\r\n   */\r\n  public makeWidget(els: GridStackElement, options?: GridStackWidget): GridItemHTMLElement {\r\n    const el = GridStack.getElement(els);\r\n    if (!el || el.gridstackNode) return el;\r\n    if (!el.parentElement) this.el.appendChild(el);\r\n    this._prepareElement(el, true, options);\r\n    const node = el.gridstackNode;\r\n\r\n    this._updateContainerHeight();\r\n\r\n    // see if there is a sub-grid to create\r\n    if (node.subGridOpts) {\r\n      this.makeSubGrid(el, node.subGridOpts, undefined, false); // node.subGrid will be used as option in method, no need to pass\r\n    }\r\n\r\n    // if we're adding an item into 1 column make sure\r\n    // we don't override the larger 12 column layout that was already saved. #1985\r\n    let resetIgnoreLayoutsNodeChange: boolean;\r\n    if (this.opts.column === 1 && !this._ignoreLayoutsNodeChange) {\r\n      resetIgnoreLayoutsNodeChange = this._ignoreLayoutsNodeChange = true;\r\n    }\r\n    this._triggerAddEvent();\r\n    this._triggerChangeEvent();\r\n    if (resetIgnoreLayoutsNodeChange) delete this._ignoreLayoutsNodeChange;\r\n\r\n    return el;\r\n  }\r\n\r\n  /**\r\n   * Event handler that extracts our CustomEvent data out automatically for receiving custom\r\n   * notifications (see doc for supported events)\r\n   * @param name of the event (see possible values) or list of names space separated\r\n   * @param callback function called with event and optional second/third param\r\n   * (see README documentation for each signature).\r\n   *\r\n   * @example\r\n   * grid.on('added', function(e, items) { log('added ', items)} );\r\n   * or\r\n   * grid.on('added removed change', function(e, items) { log(e.type, items)} );\r\n   *\r\n   * Note: in some cases it is the same as calling native handler and parsing the event.\r\n   * grid.el.addEventListener('added', function(event) { log('added ', event.detail)} );\r\n   *\r\n   */\r\n  public on(name: 'dropped', callback: GridStackDroppedHandler): GridStack\r\n  public on(name: 'enable' | 'disable', callback: GridStackEventHandler): GridStack\r\n  public on(name: 'change' | 'added' | 'removed' | 'resizecontent', callback: GridStackNodesHandler): GridStack\r\n  public on(name: 'resizestart' | 'resize' | 'resizestop' | 'dragstart' | 'drag' | 'dragstop', callback: GridStackElementHandler): GridStack\r\n  public on(name: string, callback: GridStackEventHandlerCallback): GridStack\r\n  public on(name: GridStackEvent | string, callback: GridStackEventHandlerCallback): GridStack {\r\n    // check for array of names being passed instead\r\n    if (name.indexOf(' ') !== -1) {\r\n      const names = name.split(' ') as GridStackEvent[];\r\n      names.forEach(name => this.on(name, callback));\r\n      return this;\r\n    }\r\n\r\n    // native CustomEvent handlers - cash the generic handlers so we can easily remove\r\n    if (name === 'change' || name === 'added' || name === 'removed' || name === 'enable' || name === 'disable') {\r\n      const noData = (name === 'enable' || name === 'disable');\r\n      if (noData) {\r\n        this._gsEventHandler[name] = (event: Event) => (callback as GridStackEventHandler)(event);\r\n      } else {\r\n        this._gsEventHandler[name] = (event: CustomEvent) => {if (event.detail) (callback as GridStackNodesHandler)(event, event.detail)};\r\n      }\r\n      this.el.addEventListener(name, this._gsEventHandler[name]);\r\n    } else if (name === 'drag' || name === 'dragstart' || name === 'dragstop' || name === 'resizestart' || name === 'resize'\r\n      || name === 'resizestop' || name === 'dropped' || name === 'resizecontent') {\r\n      // drag&drop stop events NEED to be call them AFTER we update node attributes so handle them ourself.\r\n      // do same for start event to make it easier...\r\n      this._gsEventHandler[name] = callback;\r\n    } else {\r\n      console.error('GridStack.on(' + name + ') event not supported');\r\n    }\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * unsubscribe from the 'on' event GridStackEvent\r\n   * @param name of the event (see possible values) or list of names space separated\r\n   */\r\n  public off(name: GridStackEvent | string): GridStack {\r\n    // check for array of names being passed instead\r\n    if (name.indexOf(' ') !== -1) {\r\n      const names = name.split(' ') as GridStackEvent[];\r\n      names.forEach(name => this.off(name));\r\n      return this;\r\n    }\r\n\r\n    if (name === 'change' || name === 'added' || name === 'removed' || name === 'enable' || name === 'disable') {\r\n      // remove native CustomEvent handlers\r\n      if (this._gsEventHandler[name]) {\r\n        this.el.removeEventListener(name, this._gsEventHandler[name]);\r\n      }\r\n    }\r\n    delete this._gsEventHandler[name];\r\n\r\n    return this;\r\n  }\r\n\r\n  /** remove all event handlers */\r\n  public offAll(): GridStack {\r\n    Object.keys(this._gsEventHandler).forEach((key: GridStackEvent) => this.off(key));\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * Removes widget from the grid.\r\n   * @param el  widget or selector to modify\r\n   * @param removeDOM if `false` DOM element won't be removed from the tree (Default? true).\r\n   * @param triggerEvent if `false` (quiet mode) element will not be added to removed list and no 'removed' callbacks will be called (Default? true).\r\n   */\r\n  public removeWidget(els: GridStackElement, removeDOM = true, triggerEvent = true): GridStack {\r\n    if (!els) { console.error('Error: GridStack.removeWidget(undefined) called'); return this; }\r\n\r\n    GridStack.getElements(els).forEach(el => {\r\n      if (el.parentElement && el.parentElement !== this.el) return; // not our child!\r\n      let node = el.gridstackNode;\r\n      // For Meteor support: https://github.com/gridstack/gridstack.js/pull/272\r\n      if (!node) {\r\n        node = this.engine.nodes.find(n => el === n.el);\r\n      }\r\n      if (!node) return;\r\n\r\n      if (removeDOM && GridStack.addRemoveCB) {\r\n        GridStack.addRemoveCB(this.el, node, false, false);\r\n      }\r\n\r\n      // remove our DOM data (circular link) and drag&drop permanently\r\n      delete el.gridstackNode;\r\n      this._removeDD(el);\r\n\r\n      this.engine.removeNode(node, removeDOM, triggerEvent);\r\n\r\n      if (removeDOM && el.parentElement) {\r\n        el.remove(); // in batch mode engine.removeNode doesn't call back to remove DOM\r\n      }\r\n    });\r\n    if (triggerEvent) {\r\n      this._triggerRemoveEvent();\r\n      this._triggerChangeEvent();\r\n    }\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * Removes all widgets from the grid.\r\n   * @param removeDOM if `false` DOM elements won't be removed from the tree (Default? `true`).\r\n   * @param triggerEvent if `false` (quiet mode) element will not be added to removed list and no 'removed' callbacks will be called (Default? true).\r\n   */\r\n  public removeAll(removeDOM = true, triggerEvent = true): GridStack {\r\n    // always remove our DOM data (circular link) before list gets emptied and drag&drop permanently\r\n    this.engine.nodes.forEach(n => {\r\n      if (removeDOM && GridStack.addRemoveCB) {\r\n        GridStack.addRemoveCB(this.el, n, false, false);\r\n      }\r\n      delete n.el.gridstackNode;\r\n      if (!this.opts.staticGrid) this._removeDD(n.el);\r\n    });\r\n    this.engine.removeAll(removeDOM, triggerEvent);\r\n    if (triggerEvent) this._triggerRemoveEvent();\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * Toggle the grid animation state.  Toggles the `grid-stack-animate` class.\r\n   * @param doAnimate if true the grid will animate.\r\n   * @param delay if true setting will be set on next event loop.\r\n   */\r\n  public setAnimation(doAnimate = this.opts.animate, delay?: boolean): GridStack {\r\n    if (delay) {\r\n      // delay, but check to make sure grid (opt) is still around\r\n      setTimeout(() => { if (this.opts) this.setAnimation(doAnimate) });\r\n    } else if (doAnimate) {\r\n      this.el.classList.add('grid-stack-animate');\r\n    } else {\r\n      this.el.classList.remove('grid-stack-animate');\r\n    }\r\n    this.opts.animate = doAnimate;\r\n    return this;\r\n  }\r\n\r\n  /** @internal */\r\n  private hasAnimationCSS(): boolean { return this.el.classList.contains('grid-stack-animate') }\r\n\r\n  /**\r\n   * Toggle the grid static state, which permanently removes/add Drag&Drop support, unlike disable()/enable() that just turns it off/on.\r\n   * Also toggle the grid-stack-static class.\r\n   * @param val if true the grid become static.\r\n   * @param updateClass true (default) if css class gets updated\r\n   * @param recurse true (default) if sub-grids also get updated\r\n   */\r\n  public setStatic(val: boolean, updateClass = true, recurse = true): GridStack {\r\n    if (!!this.opts.staticGrid === val) return this;\r\n    val ? this.opts.staticGrid = true : delete this.opts.staticGrid;\r\n    this._setupRemoveDrop();\r\n    this._setupAcceptWidget();\r\n    this.engine.nodes.forEach(n => {\r\n      this.prepareDragDrop(n.el); // either delete or init Drag&drop\r\n      if (n.subGrid && recurse) n.subGrid.setStatic(val, updateClass, recurse);\r\n    });\r\n    if (updateClass) { this._setStaticClass(); }\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * Updates the passed in options on the grid (similar to update(widget) for for the grid options).\r\n   * @param options PARTIAL grid options to update - only items specified will be updated.\r\n   * NOTE: not all options updating are currently supported (lot of code, unlikely to change)\r\n   */\r\n  public updateOptions(o: GridStackOptions): GridStack {\r\n    const opts = this.opts;\r\n    if (o === opts) return this; // nothing to do\r\n    if (o.acceptWidgets !== undefined) { opts.acceptWidgets = o.acceptWidgets; this._setupAcceptWidget(); }\r\n    if (o.animate !== undefined) this.setAnimation(o.animate);\r\n    if (o.cellHeight) this.cellHeight(o.cellHeight);\r\n    if (o.class !== undefined && o.class !== opts.class) { if (opts.class) this.el.classList.remove(opts.class); if (o.class) this.el.classList.add(o.class); }\r\n    // responsive column take over actual count (keep what we have now)\r\n    if (o.columnOpts) {\r\n      this.opts.columnOpts = o.columnOpts;\r\n      this.checkDynamicColumn();\r\n    } else if (o.columnOpts === null && this.opts.columnOpts) {\r\n      delete this.opts.columnOpts;\r\n      this._updateResizeEvent();\r\n    } else if (typeof(o.column) === 'number') this.column(o.column);\r\n    if (o.margin !== undefined) this.margin(o.margin);\r\n    if (o.staticGrid !== undefined) this.setStatic(o.staticGrid);\r\n    if (o.disableDrag !== undefined && !o.staticGrid) this.enableMove(!o.disableDrag);\r\n    if (o.disableResize !== undefined && !o.staticGrid) this.enableResize(!o.disableResize);\r\n    if (o.float !== undefined) this.float(o.float);\r\n    if (o.row !== undefined) { opts.minRow = opts.maxRow = opts.row = o.row; }\r\n    else {\r\n      if (o.minRow !== undefined) opts.minRow = o.minRow;\r\n      if (o.maxRow !== undefined) opts.maxRow = o.maxRow;\r\n    }\r\n    if (o.children?.length) this.load(o.children);\r\n    // TBD if we have a real need for these (more complex code)\r\n    // alwaysShowResizeHandle, draggable, handle, handleClass, itemClass, layout, placeholderClass, placeholderText, resizable, removable, row,...\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * Updates widget position/size and other info. Note: if you need to call this on all nodes, use load() instead which will update what changed.\r\n   * @param els  widget or selector of objects to modify (note: setting the same x,y for multiple items will be indeterministic and likely unwanted)\r\n   * @param opt new widget options (x,y,w,h, etc..). Only those set will be updated.\r\n   */\r\n  public update(els: GridStackElement, opt: GridStackWidget): GridStack {\r\n\r\n    GridStack.getElements(els).forEach(el => {\r\n      const n = el?.gridstackNode;\r\n      if (!n) return;\r\n      const w = {...Utils.copyPos({}, n), ...Utils.cloneDeep(opt)}; // make a copy we can modify in case they re-use it or multiple items\r\n      this.engine.nodeBoundFix(w);\r\n      delete w.autoPosition;\r\n\r\n      // move/resize widget if anything changed\r\n      const keys = ['x', 'y', 'w', 'h'];\r\n      let m: GridStackWidget;\r\n      if (keys.some(k => w[k] !== undefined && w[k] !== n[k])) {\r\n        m = {};\r\n        keys.forEach(k => {\r\n          m[k] = (w[k] !== undefined) ? w[k] : n[k];\r\n          delete w[k];\r\n        });\r\n      }\r\n      // for a move as well IFF there is any min/max fields set\r\n      if (!m && (w.minW || w.minH || w.maxW || w.maxH)) {\r\n        m = {}; // will use node position but validate values\r\n      }\r\n\r\n      // check for content changing\r\n      if (w.content !== undefined) {\r\n        const itemContent = el.querySelector('.grid-stack-item-content') as HTMLElement;\r\n        if (itemContent && itemContent.textContent !== w.content) {\r\n          n.content = w.content;\r\n          GridStack.renderCB(itemContent, w);\r\n          // restore any sub-grid back\r\n          if (n.subGrid?.el) {\r\n            itemContent.appendChild(n.subGrid.el);\r\n            n.subGrid._updateContainerHeight();\r\n          }\r\n        }\r\n        delete w.content;\r\n      }\r\n\r\n      // any remaining fields are assigned, but check for dragging changes, resize constrain\r\n      let changed = false;\r\n      let ddChanged = false;\r\n      for (const key in w) {\r\n        if (key[0] !== '_' && n[key] !== w[key]) {\r\n          n[key] = w[key];\r\n          changed = true;\r\n          ddChanged = ddChanged || (!this.opts.staticGrid && (key === 'noResize' || key === 'noMove' || key === 'locked'));\r\n        }\r\n      }\r\n      Utils.sanitizeMinMax(n);\r\n\r\n      // finally move the widget and update attr\r\n      if (m) {\r\n        const widthChanged = (m.w !== undefined && m.w !== n.w);\r\n        this.moveNode(n, m);\r\n        if (widthChanged && n.subGrid) {\r\n          // if we're animating the client size hasn't changed yet, so force a change (not exact size)\r\n          n.subGrid.onResize(this.hasAnimationCSS() ? n.w : undefined);\r\n        } else {\r\n          this.resizeToContentCheck(widthChanged, n);\r\n        }\r\n        delete n._orig; // clear out original position now that we moved #2669\r\n      }\r\n      if (m || changed) {\r\n        this._writeAttr(el, n);\r\n      }\r\n      if (ddChanged) {\r\n        this.prepareDragDrop(n.el);\r\n      }\r\n    });\r\n\r\n    return this;\r\n  }\r\n\r\n  private moveNode(n: GridStackNode, m: GridStackMoveOpts) {\r\n    const wasUpdating = n._updating;\r\n    if (!wasUpdating) this.engine.cleanNodes().beginUpdate(n);\r\n    this.engine.moveNode(n, m);\r\n    this._updateContainerHeight();\r\n    if (!wasUpdating) {\r\n      this._triggerChangeEvent();\r\n      this.engine.endUpdate();\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Updates widget height to match the content height to avoid v-scrollbar or dead space.\r\n   * Note: this assumes only 1 child under resizeToContentParent='.grid-stack-item-content' (sized to gridItem minus padding) that is at the entire content size wanted.\r\n   * @param el grid item element\r\n   * @param useNodeH set to true if GridStackNode.h should be used instead of actual container height when we don't need to wait for animation to finish to get actual DOM heights\r\n   */\r\n  public resizeToContent(el: GridItemHTMLElement) {\r\n    if (!el) return;\r\n    el.classList.remove('size-to-content-max');\r\n    if (!el.clientHeight) return; // 0 when hidden, skip\r\n    const n = el.gridstackNode;\r\n    if (!n) return;\r\n    const grid = n.grid;\r\n    if (!grid || el.parentElement !== grid.el) return; // skip if we are not inside a grid\r\n    const cell = grid.getCellHeight(true);\r\n    if (!cell) return;\r\n    let height = n.h ? n.h * cell : el.clientHeight; // getBoundingClientRect().height seem to flicker back and forth\r\n    let item: Element;\r\n    if (n.resizeToContentParent) item = el.querySelector(n.resizeToContentParent);\r\n    if (!item) item = el.querySelector(GridStack.resizeToContentParent);\r\n    if (!item) return;\r\n    const padding = el.clientHeight - item.clientHeight; // full - available height to our child (minus border, padding...)\r\n    const itemH = n.h ? n.h * cell - padding : item.clientHeight; // calculated to what cellHeight is or will become (rather than actual to prevent waiting for animation to finish)\r\n    let wantedH: number;\r\n    if (n.subGrid) {\r\n      // sub-grid - use their actual row count * their cell height, BUT append any content outside of the grid (eg: above text)\r\n      wantedH = n.subGrid.getRow() * n.subGrid.getCellHeight(true);\r\n      const subRec = n.subGrid.el.getBoundingClientRect();\r\n      const parentRec = el.getBoundingClientRect();\r\n      wantedH += subRec.top - parentRec.top;\r\n    } else if (n.subGridOpts?.children?.length) {\r\n      // not sub-grid just yet (case above) wait until we do\r\n      return;\r\n    } else {\r\n      // NOTE: clientHeight & getBoundingClientRect() is undefined for text and other leaf nodes. use <div> container!\r\n      const child = item.firstElementChild;\r\n      if (!child) {\r\n        console.error(`Error: GridStack.resizeToContent() widget id:${n.id} '${GridStack.resizeToContentParent}'.firstElementChild is null, make sure to have a div like container. Skipping sizing.`);\r\n        return;\r\n      }\r\n      wantedH = child.getBoundingClientRect().height || itemH;\r\n    }\r\n    if (itemH === wantedH) return;\r\n    height += wantedH - itemH;\r\n    let h = Math.ceil(height / cell);\r\n    // check for min/max and special sizing\r\n    const softMax = Number.isInteger(n.sizeToContent) ? n.sizeToContent as number : 0;\r\n    if (softMax && h > softMax) {\r\n      h = softMax;\r\n      el.classList.add('size-to-content-max');  // get v-scroll back\r\n    }\r\n    if (n.minH && h < n.minH) h = n.minH;\r\n    else if (n.maxH && h > n.maxH) h = n.maxH;\r\n    if (h !== n.h) {\r\n      grid._ignoreLayoutsNodeChange = true;\r\n      grid.moveNode(n, { h });\r\n      delete grid._ignoreLayoutsNodeChange;\r\n    }\r\n  }\r\n\r\n  /** call the user resize (so they can do extra work) else our build in version */\r\n  private resizeToContentCBCheck(el: GridItemHTMLElement) {\r\n    if (GridStack.resizeToContentCB) GridStack.resizeToContentCB(el);\r\n    else this.resizeToContent(el);\r\n  }\r\n\r\n  /** rotate (by swapping w & h) the passed in node - called when user press 'r' during dragging\r\n   * @param els  widget or selector of objects to modify\r\n   * @param relative optional pixel coord relative to upper/left corner to rotate around (will keep that cell under cursor)\r\n   */\r\n  public rotate(els: GridStackElement, relative?: Position): GridStack {\r\n    GridStack.getElements(els).forEach(el => {\r\n      const n = el.gridstackNode;\r\n      if (!Utils.canBeRotated(n)) return;\r\n      const rot: GridStackWidget = { w: n.h, h: n.w, minH: n.minW, minW: n.minH, maxH: n.maxW, maxW: n.maxH };\r\n      // if given an offset, adjust x/y by column/row bounds when user presses 'r' during dragging\r\n      if (relative) {\r\n        const pivotX = relative.left > 0 ? Math.floor(relative.left / this.cellWidth()) : 0;\r\n        const pivotY = relative.top > 0 ? Math.floor(relative.top / (this.opts.cellHeight as number)) : 0;\r\n        rot.x = n.x + pivotX - (n.h - (pivotY+1));\r\n        rot.y = (n.y + pivotY) - pivotX;\r\n      }\r\n      Object.keys(rot).forEach(k => { if (rot[k] === undefined) delete rot[k]; });\r\n      const _orig = n._orig;\r\n      this.update(el, rot);\r\n      n._orig = _orig; // restore as move() will delete it\r\n    });\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * Updates the margins which will set all 4 sides at once - see `GridStackOptions.margin` for format options (CSS string format of 1,2,4 values or single number).\r\n   * @param value margin value\r\n   */\r\n  public margin(value: numberOrString): GridStack {\r\n    const isMultiValue = (typeof value === 'string' && value.split(' ').length > 1);\r\n    // check if we can skip... won't check if multi values (too much hassle)\r\n    if (!isMultiValue) {\r\n      const data = Utils.parseHeight(value);\r\n      if (this.opts.marginUnit === data.unit && this.opts.margin === data.h) return;\r\n    }\r\n    // re-use existing margin handling\r\n    this.opts.margin = value;\r\n    this.opts.marginTop = this.opts.marginBottom = this.opts.marginLeft = this.opts.marginRight = undefined;\r\n    this._initMargin();\r\n\r\n    return this;\r\n  }\r\n\r\n  /** returns current margin number value (undefined if 4 sides don't match) */\r\n  public getMargin(): number { return this.opts.margin as number; }\r\n\r\n  /**\r\n   * Returns true if the height of the grid will be less than the vertical\r\n   * constraint. Always returns true if grid doesn't have height constraint.\r\n   * @param node contains x,y,w,h,auto-position options\r\n   *\r\n   * @example\r\n   * if (grid.willItFit(newWidget)) {\r\n   *   grid.addWidget(newWidget);\r\n   * } else {\r\n   *   alert('Not enough free space to place the widget');\r\n   * }\r\n   */\r\n  public willItFit(node: GridStackWidget): boolean {\r\n    // support legacy call for now\r\n    if (arguments.length > 1) {\r\n      console.warn('gridstack.ts: `willItFit(x,y,w,h,autoPosition)` is deprecated. Use `willItFit({x, y,...})`. It will be removed soon');\r\n      // eslint-disable-next-line prefer-rest-params\r\n      const a = arguments; let i = 0,\r\n        w: GridStackWidget = { x: a[i++], y: a[i++], w: a[i++], h: a[i++], autoPosition: a[i++] };\r\n      return this.willItFit(w);\r\n    }\r\n    return this.engine.willItFit(node);\r\n  }\r\n\r\n  /** @internal */\r\n  protected _triggerChangeEvent(): GridStack {\r\n    if (this.engine.batchMode) return this;\r\n    const elements = this.engine.getDirtyNodes(true); // verify they really changed\r\n    if (elements && elements.length) {\r\n      if (!this._ignoreLayoutsNodeChange) {\r\n        this.engine.layoutsNodesChange(elements);\r\n      }\r\n      this._triggerEvent('change', elements);\r\n    }\r\n    this.engine.saveInitial(); // we called, now reset initial values & dirty flags\r\n    return this;\r\n  }\r\n\r\n  /** @internal */\r\n  protected _triggerAddEvent(): GridStack {\r\n    if (this.engine.batchMode) return this;\r\n    if (this.engine.addedNodes?.length) {\r\n      if (!this._ignoreLayoutsNodeChange) {\r\n        this.engine.layoutsNodesChange(this.engine.addedNodes);\r\n      }\r\n      // prevent added nodes from also triggering 'change' event (which is called next)\r\n      this.engine.addedNodes.forEach(n => { delete n._dirty; });\r\n      const addedNodes = [...this.engine.addedNodes];\r\n      this.engine.addedNodes = [];\r\n      this._triggerEvent('added', addedNodes);\r\n    }\r\n    return this;\r\n  }\r\n\r\n  /** @internal */\r\n  public _triggerRemoveEvent(): GridStack {\r\n    if (this.engine.batchMode) return this;\r\n    if (this.engine.removedNodes?.length) {\r\n      const removedNodes = [...this.engine.removedNodes];\r\n      this.engine.removedNodes = [];\r\n      this._triggerEvent('removed', removedNodes);\r\n    }\r\n    return this;\r\n  }\r\n\r\n  /** @internal */\r\n  protected _triggerEvent(type: string, data?: GridStackNode[]): GridStack {\r\n    const event = data ? new CustomEvent(type, { bubbles: false, detail: data }) : new Event(type);\r\n    // check if we're nested, and if so call the outermost grid to trigger the event\r\n    // eslint-disable-next-line @typescript-eslint/no-this-alias\r\n    let grid: GridStack = this;\r\n    while (grid.parentGridNode) grid = grid.parentGridNode.grid;\r\n    grid.el.dispatchEvent(event);\r\n    return this;\r\n  }\r\n\r\n  /** @internal */\r\n  protected _updateContainerHeight(): GridStack {\r\n    if (!this.engine || this.engine.batchMode) return this;\r\n    const parent = this.parentGridNode;\r\n    let row = this.getRow() + this._extraDragRow; // this checks for minRow already\r\n    const cellHeight = this.opts.cellHeight as number;\r\n    const unit = this.opts.cellHeightUnit;\r\n    if (!cellHeight) return this;\r\n\r\n    // check for css min height (non nested grid). TODO: support mismatch, say: min % while unit is px.\r\n    if (!parent) {\r\n      const cssMinHeight = Utils.parseHeight(getComputedStyle(this.el)['minHeight']);\r\n      if (cssMinHeight.h > 0 && cssMinHeight.unit === unit) {\r\n        const minRow = Math.floor(cssMinHeight.h / cellHeight);\r\n        if (row < minRow) {\r\n          row = minRow;\r\n        }\r\n      }\r\n    }\r\n\r\n    this.el.setAttribute('gs-current-row', String(row));\r\n    this.el.style.removeProperty('min-height');\r\n    this.el.style.removeProperty('height');\r\n    if (row) {\r\n      // nested grids have 'insert:0' to fill the space of parent by default, but we may be taller so use min-height for possible scrollbars\r\n      this.el.style[parent ? 'minHeight' : 'height'] = row * cellHeight + unit;\r\n    }\r\n\r\n    // if we're a nested grid inside an sizeToContent item, tell it to resize itself too\r\n    if (parent && Utils.shouldSizeToContent(parent)) {\r\n      parent.grid.resizeToContentCBCheck(parent.el);\r\n    }\r\n\r\n    return this;\r\n  }\r\n\r\n  /** @internal */\r\n  protected _prepareElement(el: GridItemHTMLElement, triggerAddEvent = false, node?: GridStackNode): GridStack {\r\n    node = node || this._readAttr(el);\r\n    el.gridstackNode = node;\r\n    node.el = el;\r\n    node.grid = this;\r\n    node = this.engine.addNode(node, triggerAddEvent);\r\n\r\n    // write the dom sizes and class\r\n    this._writeAttr(el, node);\r\n    el.classList.add(gridDefaults.itemClass, this.opts.itemClass);\r\n    const sizeToContent = Utils.shouldSizeToContent(node);\r\n    sizeToContent ? el.classList.add('size-to-content') : el.classList.remove('size-to-content');\r\n    if (sizeToContent) this.resizeToContentCheck(false, node);\r\n\r\n    if (!Utils.lazyLoad(node)) this.prepareDragDrop(node.el);\r\n\r\n    return this;\r\n  }\r\n\r\n  /** @internal write position CSS vars and x,y,w,h attributes (not used for CSS but by users) back to element */\r\n  protected _writePosAttr(el: HTMLElement, n: GridStackNode): GridStack {\r\n    // Avoid overwriting the inline style of the element during drag/resize, but always update the placeholder\r\n    if ((!n._moving && !n._resizing) || this._placeholder === el) {\r\n      // width/height:1 x/y:0 is set by default in the main CSS, so no need to set inlined vars\r\n      el.style.top = n.y ? (n.y === 1 ? `var(--gs-cell-height)` : `calc(${n.y} * var(--gs-cell-height))`) : null;\r\n      el.style.left = n.x ? (n.x === 1 ? `var(--gs-column-width)` : `calc(${n.x} * var(--gs-column-width))`) : null;\r\n      el.style.width = n.w > 1 ? `calc(${n.w} * var(--gs-column-width))` : null;\r\n      el.style.height = n.h > 1 ? `calc(${n.h} * var(--gs-cell-height))` : null;\r\n    }\r\n    // NOTE: those are technically not needed anymore (v12+) as we have CSS vars for everything, but some users depends on them to render item size using CSS\r\n    n.x > 0 ? el.setAttribute('gs-x', String(n.x)) : el.removeAttribute('gs-x');\r\n    n.y > 0 ? el.setAttribute('gs-y', String(n.y)) : el.removeAttribute('gs-y');\r\n    n.w > 1 ? el.setAttribute('gs-w', String(n.w)) : el.removeAttribute('gs-w');\r\n    n.h > 1 ? el.setAttribute('gs-h', String(n.h)) : el.removeAttribute('gs-h');\r\n    return this;\r\n  }\r\n\r\n  /** @internal call to write any default attributes back to element */\r\n  protected _writeAttr(el: HTMLElement, node: GridStackNode): GridStack {\r\n    if (!node) return this;\r\n    this._writePosAttr(el, node);\r\n\r\n    const attrs /*: GridStackWidget but strings */ = { // remaining attributes\r\n      // autoPosition: 'gs-auto-position', // no need to write out as already in node and doesn't affect CSS\r\n      noResize: 'gs-no-resize',\r\n      noMove: 'gs-no-move',\r\n      locked: 'gs-locked',\r\n      id: 'gs-id',\r\n      sizeToContent: 'gs-size-to-content',\r\n    };\r\n    for (const key in attrs) {\r\n      if (node[key]) { // 0 is valid for x,y only but done above already and not in list anyway\r\n        el.setAttribute(attrs[key], String(node[key]));\r\n      } else {\r\n        el.removeAttribute(attrs[key]);\r\n      }\r\n    }\r\n    return this;\r\n  }\r\n\r\n  /** @internal call to read any default attributes from element */\r\n  protected _readAttr(el: HTMLElement, clearDefaultAttr = true): GridStackWidget {\r\n    const n: GridStackNode = {};\r\n    n.x = Utils.toNumber(el.getAttribute('gs-x'));\r\n    n.y = Utils.toNumber(el.getAttribute('gs-y'));\r\n    n.w = Utils.toNumber(el.getAttribute('gs-w'));\r\n    n.h = Utils.toNumber(el.getAttribute('gs-h'));\r\n    n.autoPosition = Utils.toBool(el.getAttribute('gs-auto-position'));\r\n    n.noResize = Utils.toBool(el.getAttribute('gs-no-resize'));\r\n    n.noMove = Utils.toBool(el.getAttribute('gs-no-move'));\r\n    n.locked = Utils.toBool(el.getAttribute('gs-locked'));\r\n    const attr = el.getAttribute('gs-size-to-content');\r\n    if (attr) {\r\n      if (attr === 'true' || attr === 'false') n.sizeToContent = Utils.toBool(attr);\r\n      else n.sizeToContent = parseInt(attr, 10);\r\n    }\r\n    n.id = el.getAttribute('gs-id');\r\n\r\n    // read but never written out\r\n    n.maxW = Utils.toNumber(el.getAttribute('gs-max-w'));\r\n    n.minW = Utils.toNumber(el.getAttribute('gs-min-w'));\r\n    n.maxH = Utils.toNumber(el.getAttribute('gs-max-h'));\r\n    n.minH = Utils.toNumber(el.getAttribute('gs-min-h'));\r\n\r\n    // v8.x optimization to reduce un-needed attr that don't render or are default CSS\r\n    if (clearDefaultAttr) {\r\n      if (n.w === 1) el.removeAttribute('gs-w');\r\n      if (n.h === 1) el.removeAttribute('gs-h');\r\n      if (n.maxW) el.removeAttribute('gs-max-w');\r\n      if (n.minW) el.removeAttribute('gs-min-w');\r\n      if (n.maxH) el.removeAttribute('gs-max-h');\r\n      if (n.minH) el.removeAttribute('gs-min-h');\r\n    }\r\n\r\n    // remove any key not found (null or false which is default, unless sizeToContent=false override)\r\n    for (const key in n) {\r\n      if (!n.hasOwnProperty(key)) return;\r\n      if (!n[key] && n[key] !== 0 && key !== 'gs-size-to-content') { // 0 can be valid value (x,y only really)\r\n        delete n[key];\r\n      }\r\n    }\r\n\r\n    return n;\r\n  }\r\n\r\n  /** @internal */\r\n  protected _setStaticClass(): GridStack {\r\n    const classes = ['grid-stack-static'];\r\n\r\n    if (this.opts.staticGrid) {\r\n      this.el.classList.add(...classes);\r\n      this.el.setAttribute('gs-static', 'true');\r\n    } else {\r\n      this.el.classList.remove(...classes);\r\n      this.el.removeAttribute('gs-static');\r\n\r\n    }\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * called when we are being resized - check if the one Column Mode needs to be turned on/off\r\n   * and remember the prev columns we used, or get our count from parent, as well as check for cellHeight==='auto' (square)\r\n   * or `sizeToContent` gridItem options.\r\n   */\r\n  public onResize(clientWidth = this.el?.clientWidth): GridStack {\r\n    if (!clientWidth) return; // return if we're gone or no size yet (will get called again)\r\n    if (this.prevWidth === clientWidth) return; // no-op\r\n    this.prevWidth = clientWidth\r\n    // console.log('onResize ', clientWidth);\r\n\r\n    this.batchUpdate();\r\n\r\n    // see if we're nested and take our column count from our parent....\r\n    let columnChanged = false;\r\n    if (this._autoColumn && this.parentGridNode) {\r\n      if (this.opts.column !== this.parentGridNode.w) {\r\n        this.column(this.parentGridNode.w, this.opts.layout || 'list');\r\n        columnChanged = true;\r\n      }\r\n    } else {\r\n      // else check for dynamic column\r\n      columnChanged = this.checkDynamicColumn();\r\n    }\r\n\r\n    // make the cells content square again\r\n    if (this._isAutoCellHeight) this.cellHeight();\r\n\r\n    // update any nested grids, or items size\r\n    this.engine.nodes.forEach(n => {\r\n      if (n.subGrid) n.subGrid.onResize()\r\n    });\r\n\r\n    if (!this._skipInitialResize) this.resizeToContentCheck(columnChanged); // wait for anim of column changed (DOM reflow before we can size correctly)\r\n    delete this._skipInitialResize;\r\n\r\n    this.batchUpdate(false);\r\n\r\n    return this;\r\n  }\r\n\r\n  /** resizes content for given node (or all) if shouldSizeToContent() is true */\r\n  private resizeToContentCheck(delay = false, n: GridStackNode = undefined) {\r\n    if (!this.engine) return; // we've been deleted in between!\r\n\r\n    // update any gridItem height with sizeToContent, but wait for DOM $animation_speed to settle if we changed column count\r\n    // TODO: is there a way to know what the final (post animation) size of the content will be so we can animate the column width and height together rather than sequentially ?\r\n    if (delay && this.hasAnimationCSS()) return setTimeout(() => this.resizeToContentCheck(false, n), this.animationDelay);\r\n\r\n    if (n) {\r\n      if (Utils.shouldSizeToContent(n)) this.resizeToContentCBCheck(n.el);\r\n    } else if (this.engine.nodes.some(n => Utils.shouldSizeToContent(n))) {\r\n      const nodes = [...this.engine.nodes]; // in case order changes while resizing one\r\n      this.batchUpdate();\r\n      nodes.forEach(n => {\r\n        if (Utils.shouldSizeToContent(n)) this.resizeToContentCBCheck(n.el);\r\n      });\r\n      this._ignoreLayoutsNodeChange = true; // loop through each node will set/reset around each move, so set it here again\r\n      this.batchUpdate(false);\r\n      this._ignoreLayoutsNodeChange = false;\r\n    }\r\n    // call this regardless of shouldSizeToContent because widget might need to stretch to take available space after a resize\r\n    if (this._gsEventHandler['resizecontent']) this._gsEventHandler['resizecontent'](null, n ? [n] : this.engine.nodes);\r\n  }\r\n\r\n  /** add or remove the grid element size event handler */\r\n  protected _updateResizeEvent(forceRemove = false): GridStack {\r\n    // only add event if we're not nested (parent will call us) and we're auto sizing cells or supporting dynamic column (i.e. doing work)\r\n    // or supporting new sizeToContent option.\r\n    const trackSize = !this.parentGridNode && (this._isAutoCellHeight || this.opts.sizeToContent || this.opts.columnOpts\r\n      || this.engine.nodes.find(n => n.sizeToContent));\r\n\r\n    if (!forceRemove && trackSize && !this.resizeObserver) {\r\n      this._sizeThrottle = Utils.throttle(() => this.onResize(), this.opts.cellHeightThrottle);\r\n      this.resizeObserver = new ResizeObserver(() => this._sizeThrottle());\r\n      this.resizeObserver.observe(this.el);\r\n      this._skipInitialResize = true; // makeWidget will originally have called on startup\r\n    } else if ((forceRemove || !trackSize) && this.resizeObserver) {\r\n      this.resizeObserver.disconnect();\r\n      delete this.resizeObserver;\r\n      delete this._sizeThrottle;\r\n    }\r\n\r\n    return this;\r\n  }\r\n\r\n  /** @internal convert a potential selector into actual element */\r\n  public static getElement(els: GridStackElement = '.grid-stack-item'): GridItemHTMLElement { return Utils.getElement(els) }\r\n  /** @internal */\r\n  public static getElements(els: GridStackElement = '.grid-stack-item'): GridItemHTMLElement[] { return Utils.getElements(els) }\r\n  /** @internal */\r\n  public static getGridElement(els: GridStackElement): GridHTMLElement { return GridStack.getElement(els) }\r\n  /** @internal */\r\n  public static getGridElements(els: string): GridHTMLElement[] { return Utils.getElements(els) }\r\n\r\n  /** @internal initialize margin top/bottom/left/right and units */\r\n  protected _initMargin(): GridStack {\r\n    let data: HeightData;\r\n    let margin = 0;\r\n\r\n    // support passing multiple values like CSS (ex: '5px 10px 0 20px')\r\n    let margins: string[] = [];\r\n    if (typeof this.opts.margin === 'string') {\r\n      margins = this.opts.margin.split(' ')\r\n    }\r\n    if (margins.length === 2) { // top/bot, left/right like CSS\r\n      this.opts.marginTop = this.opts.marginBottom = margins[0];\r\n      this.opts.marginLeft = this.opts.marginRight = margins[1];\r\n    } else if (margins.length === 4) { // Clockwise like CSS\r\n      this.opts.marginTop = margins[0];\r\n      this.opts.marginRight = margins[1];\r\n      this.opts.marginBottom = margins[2];\r\n      this.opts.marginLeft = margins[3];\r\n    } else {\r\n      data = Utils.parseHeight(this.opts.margin);\r\n      this.opts.marginUnit = data.unit;\r\n      margin = this.opts.margin = data.h;\r\n    }\r\n\r\n    // see if top/bottom/left/right need to be set as well\r\n    const keys = ['marginTop', 'marginRight', 'marginBottom', 'marginLeft'];\r\n    keys.forEach(k => {\r\n      if (this.opts[k] === undefined) {\r\n        this.opts[k] = margin;\r\n      } else {\r\n        data = Utils.parseHeight(this.opts[k]);\r\n        this.opts[k] = data.h;\r\n        delete this.opts.margin;\r\n      }\r\n    });\r\n    this.opts.marginUnit = data.unit; // in case side were spelled out, use those units instead...\r\n    if (this.opts.marginTop === this.opts.marginBottom && this.opts.marginLeft === this.opts.marginRight && this.opts.marginTop === this.opts.marginRight) {\r\n      this.opts.margin = this.opts.marginTop; // makes it easier to check for no-ops in setMargin()\r\n    }\r\n\r\n    // finally Update the CSS margin variables (inside the cell height) */\r\n    const style = this.el.style;\r\n    style.setProperty('--gs-item-margin-top', `${this.opts.marginTop}${this.opts.marginUnit}`);\r\n    style.setProperty('--gs-item-margin-bottom', `${this.opts.marginBottom}${this.opts.marginUnit}`);\r\n    style.setProperty('--gs-item-margin-right', `${this.opts.marginRight}${this.opts.marginUnit}`);\r\n    style.setProperty('--gs-item-margin-left', `${this.opts.marginLeft}${this.opts.marginUnit}`);\r\n\r\n    return this;\r\n  }\r\n\r\n  static GDRev = '12.1.2';\r\n\r\n  /* ===========================================================================================\r\n   * drag&drop methods that used to be stubbed out and implemented in dd-gridstack.ts\r\n   * but caused loading issues in prod - see https://github.com/gridstack/gridstack.js/issues/2039\r\n   * ===========================================================================================\r\n   */\r\n\r\n  /** get the global (but static to this code) DD implementation */\r\n  public static getDD(): DDGridStack {\r\n    return dd;\r\n  }\r\n\r\n  /**\r\n   * call to setup dragging in from the outside (say toolbar), by specifying the class selection and options.\r\n   * Called during GridStack.init() as options, but can also be called directly (last param are used) in case the toolbar\r\n   * is dynamically create and needs to be set later.\r\n   * @param dragIn string selector (ex: '.sidebar-item') or list of dom elements\r\n   * @param dragInOptions options - see DDDragOpt. (default: {handle: '.grid-stack-item-content', appendTo: 'body'}\r\n   * @param widgets GridStackWidget def to assign to each element which defines what to create on drop\r\n   * @param root optional root which defaults to document (for shadow dom pass the parent HTMLDocument)\r\n   */\r\n  public static setupDragIn(dragIn?: string | HTMLElement[], dragInOptions?: DDDragOpt, widgets?: GridStackWidget[], root: HTMLElement | Document = document): void {\r\n    if (dragInOptions?.pause !== undefined) {\r\n      DDManager.pauseDrag = dragInOptions.pause;\r\n    }\r\n\r\n    dragInOptions = { appendTo: 'body', helper: 'clone', ...(dragInOptions || {}) }; // default to handle:undefined = drag by the whole item\r\n    const els = (typeof dragIn === 'string') ? Utils.getElements(dragIn, root) : dragIn;\r\n    els.forEach((el, i) => {\r\n      if (!dd.isDraggable(el)) dd.dragIn(el, dragInOptions);\r\n      if (widgets?.[i]) (el as GridItemHTMLElement).gridstackNode = widgets[i];\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Enables/Disables dragging by the user of specific grid element. If you want all items, and have it affect future items, use enableMove() instead. No-op for static grids.\r\n   * IF you are looking to prevent an item from moving (due to being pushed around by another during collision) use locked property instead.\r\n   * @param els widget or selector to modify.\r\n   * @param val if true widget will be draggable, assuming the parent grid isn't noMove or static.\r\n   */\r\n  public movable(els: GridStackElement, val: boolean): GridStack {\r\n    if (this.opts.staticGrid) return this; // can't move a static grid!\r\n    GridStack.getElements(els).forEach(el => {\r\n      const n = el.gridstackNode;\r\n      if (!n) return;\r\n      val ? delete n.noMove : n.noMove = true;\r\n      this.prepareDragDrop(n.el); // init DD if need be, and adjust\r\n    });\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * Enables/Disables user resizing of specific grid element. If you want all items, and have it affect future items, use enableResize() instead. No-op for static grids.\r\n   * @param els  widget or selector to modify\r\n   * @param val  if true widget will be resizable, assuming the parent grid isn't noResize or static.\r\n   */\r\n  public resizable(els: GridStackElement, val: boolean): GridStack {\r\n    if (this.opts.staticGrid) return this; // can't resize a static grid!\r\n    GridStack.getElements(els).forEach(el => {\r\n      const n = el.gridstackNode;\r\n      if (!n) return;\r\n      val ? delete n.noResize : n.noResize = true;\r\n      this.prepareDragDrop(n.el); // init DD if need be, and adjust\r\n    });\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * Temporarily disables widgets moving/resizing.\r\n   * If you want a more permanent way (which freezes up resources) use `setStatic(true)` instead.\r\n   * Note: no-op for static grid\r\n   * This is a shortcut for:\r\n   * @example\r\n   *  grid.enableMove(false);\r\n   *  grid.enableResize(false);\r\n   * @param recurse true (default) if sub-grids also get updated\r\n   */\r\n  public disable(recurse = true): GridStack {\r\n    if (this.opts.staticGrid) return;\r\n    this.enableMove(false, recurse);\r\n    this.enableResize(false, recurse);\r\n    this._triggerEvent('disable');\r\n    return this;\r\n  }\r\n  /**\r\n   * Re-enables widgets moving/resizing - see disable().\r\n   * Note: no-op for static grid.\r\n   * This is a shortcut for:\r\n   * @example\r\n   *  grid.enableMove(true);\r\n   *  grid.enableResize(true);\r\n   * @param recurse true (default) if sub-grids also get updated\r\n   */\r\n  public enable(recurse = true): GridStack {\r\n    if (this.opts.staticGrid) return;\r\n    this.enableMove(true, recurse);\r\n    this.enableResize(true, recurse);\r\n    this._triggerEvent('enable');\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * Enables/disables widget moving. No-op for static grids, and locally defined items still overrule\r\n   * @param recurse true (default) if sub-grids also get updated\r\n   */\r\n  public enableMove(doEnable: boolean, recurse = true): GridStack {\r\n    if (this.opts.staticGrid) return this; // can't move a static grid!\r\n    doEnable ? delete this.opts.disableDrag : this.opts.disableDrag = true; // FIRST before we update children as grid overrides #1658\r\n    this.engine.nodes.forEach(n => {\r\n      this.prepareDragDrop(n.el);\r\n      if (n.subGrid && recurse) n.subGrid.enableMove(doEnable, recurse);\r\n    });\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * Enables/disables widget resizing. No-op for static grids.\r\n   * @param recurse true (default) if sub-grids also get updated\r\n   */\r\n  public enableResize(doEnable: boolean, recurse = true): GridStack {\r\n    if (this.opts.staticGrid) return this; // can't size a static grid!\r\n    doEnable ? delete this.opts.disableResize : this.opts.disableResize = true; // FIRST before we update children as grid overrides #1658\r\n    this.engine.nodes.forEach(n => {\r\n      this.prepareDragDrop(n.el);\r\n      if (n.subGrid && recurse) n.subGrid.enableResize(doEnable, recurse);\r\n    });\r\n    return this;\r\n  }\r\n\r\n  /** @internal call when drag (and drop) needs to be cancelled (Esc key) */\r\n  public cancelDrag() {\r\n    const n = this._placeholder?.gridstackNode;\r\n    if (!n) return;\r\n    if (n._isExternal) {\r\n      // remove any newly inserted nodes (from outside)\r\n      n._isAboutToRemove = true;\r\n      this.engine.removeNode(n);\r\n    } else if (n._isAboutToRemove) {\r\n      // restore any temp removed (dragged over trash)\r\n      GridStack._itemRemoving(n.el, false);\r\n    }\r\n\r\n    this.engine.restoreInitial();\r\n  }\r\n\r\n  /** @internal removes any drag&drop present (called during destroy) */\r\n  protected _removeDD(el: DDElementHost): GridStack {\r\n    dd.draggable(el, 'destroy').resizable(el, 'destroy');\r\n    if (el.gridstackNode) {\r\n      delete el.gridstackNode._initDD; // reset our DD init flag\r\n    }\r\n    delete el.ddElement;\r\n    return this;\r\n  }\r\n\r\n  /** @internal called to add drag over to support widgets being added externally */\r\n  protected _setupAcceptWidget(): GridStack {\r\n\r\n    // check if we need to disable things\r\n    if (this.opts.staticGrid || (!this.opts.acceptWidgets && !this.opts.removable)) {\r\n      dd.droppable(this.el, 'destroy');\r\n      return this;\r\n    }\r\n\r\n    // vars shared across all methods\r\n    let cellHeight: number, cellWidth: number;\r\n\r\n    const onDrag = (event: DragEvent, el: GridItemHTMLElement, helper: GridItemHTMLElement) => {\r\n      helper = helper || el;\r\n      const node = helper.gridstackNode;\r\n      if (!node) return;\r\n\r\n      // if the element is being dragged from outside, scale it down to match the grid's scale\r\n      // and slightly adjust its position relative to the mouse\r\n      if (!node.grid?.el) {\r\n        // this scales the helper down\r\n        helper.style.transform = `scale(${1 / this.dragTransform.xScale},${1 / this.dragTransform.yScale})`;\r\n        // this makes it so that the helper is well positioned relative to the mouse after scaling\r\n        const helperRect = helper.getBoundingClientRect();\r\n        helper.style.left = helperRect.x + (this.dragTransform.xScale - 1) * (event.clientX - helperRect.x) / this.dragTransform.xScale + 'px';\r\n        helper.style.top = helperRect.y + (this.dragTransform.yScale - 1) * (event.clientY - helperRect.y) / this.dragTransform.yScale + 'px';\r\n        helper.style.transformOrigin = `0px 0px`\r\n      }\r\n\r\n      let { top, left } = helper.getBoundingClientRect();\r\n      const rect = this.el.getBoundingClientRect();\r\n      left -= rect.left;\r\n      top -= rect.top;\r\n      const ui: DDUIData = {\r\n        position: {\r\n          top: top * this.dragTransform.xScale,\r\n          left: left * this.dragTransform.yScale\r\n        }\r\n      };\r\n\r\n      if (node._temporaryRemoved) {\r\n        node.x = Math.max(0, Math.round(left / cellWidth));\r\n        node.y = Math.max(0, Math.round(top / cellHeight));\r\n        delete node.autoPosition;\r\n        this.engine.nodeBoundFix(node);\r\n\r\n        // don't accept *initial* location if doesn't fit #1419 (locked drop region, or can't grow), but maybe try if it will go somewhere\r\n        if (!this.engine.willItFit(node)) {\r\n          node.autoPosition = true; // ignore x,y and try for any slot...\r\n          if (!this.engine.willItFit(node)) {\r\n            dd.off(el, 'drag'); // stop calling us\r\n            return; // full grid or can't grow\r\n          }\r\n          if (node._willFitPos) {\r\n            // use the auto position instead #1687\r\n            Utils.copyPos(node, node._willFitPos);\r\n            delete node._willFitPos;\r\n          }\r\n        }\r\n\r\n        // re-use the existing node dragging method\r\n        this._onStartMoving(helper, event, ui, node, cellWidth, cellHeight);\r\n      } else {\r\n        // re-use the existing node dragging that does so much of the collision detection\r\n        this._dragOrResize(helper, event, ui, node, cellWidth, cellHeight);\r\n      }\r\n    }\r\n\r\n    dd.droppable(this.el, {\r\n      accept: (el: GridItemHTMLElement) => {\r\n        const node: GridStackNode = el.gridstackNode || this._readAttr(el, false);\r\n        // set accept drop to true on ourself (which we ignore) so we don't get \"can't drop\" icon in HTML5 mode while moving\r\n        if (node?.grid === this) return true;\r\n        if (!this.opts.acceptWidgets) return false;\r\n        // check for accept method or class matching\r\n        let canAccept = true;\r\n        if (typeof this.opts.acceptWidgets === 'function') {\r\n          canAccept = this.opts.acceptWidgets(el);\r\n        } else {\r\n          const selector = (this.opts.acceptWidgets === true ? '.grid-stack-item' : this.opts.acceptWidgets as string);\r\n          canAccept = el.matches(selector);\r\n        }\r\n        // finally check to make sure we actually have space left #1571 #2633\r\n        if (canAccept && node && this.opts.maxRow) {\r\n          const n = { w: node.w, h: node.h, minW: node.minW, minH: node.minH }; // only width/height matters and autoPosition\r\n          canAccept = this.engine.willItFit(n);\r\n        }\r\n        return canAccept;\r\n      }\r\n    })\r\n      /**\r\n       * entering our grid area\r\n       */\r\n      .on(this.el, 'dropover', (event: Event, el: GridItemHTMLElement, helper: GridItemHTMLElement) => {\r\n        // console.log(`over ${this.el.gridstack.opts.id} ${count++}`); // TEST\r\n        let node = helper?.gridstackNode || el.gridstackNode;\r\n        // ignore drop enter on ourself (unless we temporarily removed) which happens on a simple drag of our item\r\n        if (node?.grid === this && !node._temporaryRemoved) {\r\n          // delete node._added; // reset this to track placeholder again in case we were over other grid #1484 (dropout doesn't always clear)\r\n          return false; // prevent parent from receiving msg (which may be a grid as well)\r\n        }\r\n\r\n        // If sidebar item, restore the sidebar node size to ensure consistent behavior when dragging between grids\r\n        if (node?._sidebarOrig) {\r\n          node.w = node._sidebarOrig.w;\r\n          node.h = node._sidebarOrig.h;\r\n        }\r\n\r\n        // fix #1578 when dragging fast, we may not get a leave on the previous grid so force one now\r\n        if (node?.grid && node.grid !== this && !node._temporaryRemoved) {\r\n          // console.log('dropover without leave'); // TEST\r\n          const otherGrid = node.grid;\r\n          otherGrid._leave(el, helper);\r\n        }\r\n        helper = helper || el;\r\n\r\n        // cache cell dimensions (which don't change), position can animate if we removed an item in otherGrid that affects us...\r\n        cellWidth = this.cellWidth();\r\n        cellHeight = this.getCellHeight(true);\r\n\r\n        // sidebar items: load any element attributes if we don't have a node on first enter from the sidebar\r\n        if (!node) {\r\n          const attr = helper.getAttribute('data-gs-widget') || helper.getAttribute('gridstacknode'); // TBD: temp support for old V11.0.0 attribute\r\n          if (attr) {\r\n            try {\r\n              node = JSON.parse(attr);\r\n            } catch (error) {\r\n              console.error(\"Gridstack dropover: Bad JSON format: \", attr);\r\n            }\r\n            helper.removeAttribute('data-gs-widget');\r\n            helper.removeAttribute('gridstacknode');\r\n          }\r\n          if (!node) node = this._readAttr(helper); // used to pass false for #2354, but now we clone top level node\r\n          // On first grid enter from sidebar, set the initial sidebar item size properties for the node\r\n          node._sidebarOrig = { w: node.w, h: node.h }\r\n        }\r\n        if (!node.grid) { // sidebar item\r\n          if (!node.el) node = {...node}; // clone first time we're coming from sidebar (since 'clone' doesn't copy vars)\r\n          node._isExternal = true;\r\n          helper.gridstackNode = node;\r\n        }\r\n\r\n        // calculate the grid size based on element outer size\r\n        const w = node.w || Math.round(helper.offsetWidth / cellWidth) || 1;\r\n        const h = node.h || Math.round(helper.offsetHeight / cellHeight) || 1;\r\n\r\n        // if the item came from another grid, make a copy and save the original info in case we go back there\r\n        if (node.grid && node.grid !== this) {\r\n          // copy the node original values (min/max/id/etc...) but override width/height/other flags which are this grid specific\r\n          // console.log('dropover cloning node'); // TEST\r\n          if (!el._gridstackNodeOrig) el._gridstackNodeOrig = node; // shouldn't have multiple nested!\r\n          el.gridstackNode = node = { ...node, w, h, grid: this };\r\n          delete node.x;\r\n          delete node.y;\r\n          this.engine.cleanupNode(node)\r\n            .nodeBoundFix(node);\r\n          // restore some internal fields we need after clearing them all\r\n          node._initDD =\r\n            node._isExternal =  // DOM needs to be re-parented on a drop\r\n            node._temporaryRemoved = true; // so it can be inserted onDrag below\r\n        } else {\r\n          node.w = w;\r\n          node.h = h;\r\n          node._temporaryRemoved = true; // so we can insert it\r\n        }\r\n\r\n        // clear any marked for complete removal (Note: don't check _isAboutToRemove as that is cleared above - just do it)\r\n        GridStack._itemRemoving(node.el, false);\r\n\r\n        dd.on(el, 'drag', onDrag);\r\n        // make sure this is called at least once when going fast #1578\r\n        onDrag(event as DragEvent, el, helper);\r\n        return false; // prevent parent from receiving msg (which may be a grid as well)\r\n      })\r\n      /**\r\n       * Leaving our grid area...\r\n       */\r\n      .on(this.el, 'dropout', (event, el: GridItemHTMLElement, helper: GridItemHTMLElement) => {\r\n        // console.log(`out ${this.el.gridstack.opts.id} ${count++}`); // TEST\r\n        const node = helper?.gridstackNode || el.gridstackNode;\r\n        if (!node) return false;\r\n        // fix #1578 when dragging fast, we might get leave after other grid gets enter (which calls us to clean)\r\n        // so skip this one if we're not the active grid really..\r\n        if (!node.grid || node.grid === this) {\r\n          this._leave(el, helper);\r\n          // if we were created as temporary nested grid, go back to before state\r\n          if (this._isTemp) {\r\n            this.removeAsSubGrid(node);\r\n          }\r\n        }\r\n        return false; // prevent parent from receiving msg (which may be grid as well)\r\n      })\r\n      /**\r\n       * end - releasing the mouse\r\n       */\r\n      .on(this.el, 'drop', (event, el: GridItemHTMLElement, helper: GridItemHTMLElement) => {\r\n        const node = helper?.gridstackNode || el.gridstackNode;\r\n        // ignore drop on ourself from ourself that didn't come from the outside - dragend will handle the simple move instead\r\n        if (node?.grid === this && !node._isExternal) return false;\r\n\r\n        const wasAdded = !!this.placeholder.parentElement; // skip items not actually added to us because of constrains, but do cleanup #1419\r\n        const wasSidebar = el !== helper;\r\n        this.placeholder.remove();\r\n        delete this.placeholder.gridstackNode;\r\n\r\n        // disable animation when replacing a placeholder (already positioned) with actual content\r\n        if (wasAdded && this.opts.animate) {\r\n          this.setAnimation(false);\r\n          this.setAnimation(true, true); // delay adding back\r\n        }\r\n\r\n        // notify previous grid of removal\r\n        // console.log('drop delete _gridstackNodeOrig') // TEST\r\n        const origNode = el._gridstackNodeOrig;\r\n        delete el._gridstackNodeOrig;\r\n        if (wasAdded && origNode?.grid && origNode.grid !== this) {\r\n          const oGrid = origNode.grid;\r\n          oGrid.engine.removeNodeFromLayoutCache(origNode);\r\n          oGrid.engine.removedNodes.push(origNode);\r\n          oGrid._triggerRemoveEvent()._triggerChangeEvent();\r\n          // if it's an empty sub-grid that got auto-created, nuke it\r\n          if (oGrid.parentGridNode && !oGrid.engine.nodes.length && oGrid.opts.subGridDynamic) {\r\n            oGrid.removeAsSubGrid();\r\n          }\r\n        }\r\n\r\n        if (!node) return false;\r\n\r\n        // use existing placeholder node as it's already in our list with drop location\r\n        if (wasAdded) {\r\n          this.engine.cleanupNode(node); // removes all internal _xyz values\r\n          node.grid = this;\r\n        }\r\n        delete node.grid?._isTemp;\r\n        dd.off(el, 'drag');\r\n        // if we made a copy insert that instead of the original (sidebar item)\r\n        if (helper !== el) {\r\n          helper.remove();\r\n          el = helper;\r\n        } else {\r\n          el.remove(); // reduce flicker as we change depth here, and size further down\r\n        }\r\n        this._removeDD(el);\r\n        if (!wasAdded) return false;\r\n        const subGrid = node.subGrid?.el?.gridstack; // set when actual sub-grid present\r\n        Utils.copyPos(node, this._readAttr(this.placeholder)); // placeholder values as moving VERY fast can throw things off #1578\r\n        Utils.removePositioningStyles(el);\r\n\r\n        // give the user a chance to alter the widget that will get inserted if new sidebar item\r\n        if (wasSidebar && (node.content || node.subGridOpts || GridStack.addRemoveCB)) {\r\n          delete node.el;\r\n          el = this.addWidget(node);\r\n        } else {\r\n          this._prepareElement(el, true, node);\r\n          this.el.appendChild(el);\r\n          // resizeToContent is skipped in _prepareElement() until node is visible (clientHeight=0) so call it now\r\n          this.resizeToContentCheck(false, node);\r\n          if (subGrid) {\r\n            subGrid.parentGridNode = node;\r\n          }\r\n          this._updateContainerHeight();\r\n        }\r\n        this.engine.addedNodes.push(node);\r\n        this._triggerAddEvent();\r\n        this._triggerChangeEvent();\r\n\r\n        this.engine.endUpdate();\r\n        if (this._gsEventHandler['dropped']) {\r\n          this._gsEventHandler['dropped']({ ...event, type: 'dropped' }, origNode && origNode.grid ? origNode : undefined, node);\r\n        }\r\n\r\n        return false; // prevent parent from receiving msg (which may be grid as well)\r\n      });\r\n    return this;\r\n  }\r\n\r\n  /** @internal mark item for removal */\r\n  private static _itemRemoving(el: GridItemHTMLElement, remove: boolean) {\r\n    if (!el) return;\r\n    const node = el ? el.gridstackNode : undefined;\r\n    if (!node?.grid || el.classList.contains(node.grid.opts.removableOptions.decline)) return;\r\n    remove ? node._isAboutToRemove = true : delete node._isAboutToRemove;\r\n    remove ? el.classList.add('grid-stack-item-removing') : el.classList.remove('grid-stack-item-removing');\r\n  }\r\n\r\n  /** @internal called to setup a trash drop zone if the user specifies it */\r\n  protected _setupRemoveDrop(): GridStack {\r\n    if (typeof this.opts.removable !== 'string') return this;\r\n    const trashEl = document.querySelector(this.opts.removable) as HTMLElement;\r\n    if (!trashEl) return this;\r\n\r\n    // only register ONE static drop-over/dropout callback for the 'trash', and it will\r\n    // update the passed in item and parent grid because the '.trash' is a shared resource anyway,\r\n    // and Native DD only has 1 event CB (having a list and technically a per grid removableOptions complicates things greatly)\r\n    if (!this.opts.staticGrid && !dd.isDroppable(trashEl)) {\r\n      dd.droppable(trashEl, this.opts.removableOptions)\r\n        .on(trashEl, 'dropover', (event, el) => GridStack._itemRemoving(el, true))\r\n        .on(trashEl, 'dropout', (event, el) => GridStack._itemRemoving(el, false));\r\n    }\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * prepares the element for drag&drop - this is normally called by makeWidget() unless are are delay loading\r\n   * @param el GridItemHTMLElement of the widget\r\n   * @param [force=false]\r\n   * */\r\n  public prepareDragDrop(el: GridItemHTMLElement, force = false): GridStack {\r\n    const node = el?.gridstackNode;\r\n    if (!node) return;\r\n    const noMove = node.noMove || this.opts.disableDrag;\r\n    const noResize = node.noResize || this.opts.disableResize;\r\n\r\n    // check for disabled grid first\r\n    const disable = this.opts.staticGrid || (noMove && noResize);\r\n    if (force || disable) {\r\n      if (node._initDD) {\r\n        this._removeDD(el); // nukes everything instead of just disable, will add some styles back next\r\n        delete node._initDD;\r\n      }\r\n      if (disable) el.classList.add('ui-draggable-disabled', 'ui-resizable-disabled'); // add styles one might depend on #1435\r\n      if (!force) return this;\r\n    }\r\n\r\n    if (!node._initDD) {\r\n      // variables used/cashed between the 3 start/move/end methods, in addition to node passed above\r\n      let cellWidth: number;\r\n      let cellHeight: number;\r\n\r\n      /** called when item starts moving/resizing */\r\n      const onStartMoving = (event: Event, ui: DDUIData) => {\r\n        // trigger any 'dragstart' / 'resizestart' manually\r\n        this.triggerEvent(event, event.target as GridItemHTMLElement);\r\n        cellWidth = this.cellWidth();\r\n        cellHeight = this.getCellHeight(true); // force pixels for calculations\r\n\r\n        this._onStartMoving(el, event, ui, node, cellWidth, cellHeight);\r\n      }\r\n\r\n      /** called when item is being dragged/resized */\r\n      const dragOrResize = (event: MouseEvent, ui: DDUIData) => {\r\n        this._dragOrResize(el, event, ui, node, cellWidth, cellHeight);\r\n      }\r\n\r\n      /** called when the item stops moving/resizing */\r\n      const onEndMoving = (event: Event) => {\r\n        this.placeholder.remove();\r\n        delete this.placeholder.gridstackNode;\r\n        delete node._moving;\r\n        delete node._resizing;\r\n        delete node._event;\r\n        delete node._lastTried;\r\n        const widthChanged = node.w !== node._orig.w;\r\n\r\n        // if the item has moved to another grid, we're done here\r\n        const target: GridItemHTMLElement = event.target as GridItemHTMLElement;\r\n        if (!target.gridstackNode || target.gridstackNode.grid !== this) return;\r\n\r\n        node.el = target;\r\n\r\n        if (node._isAboutToRemove) {\r\n          const grid = el.gridstackNode.grid;\r\n          if (grid._gsEventHandler[event.type]) {\r\n            grid._gsEventHandler[event.type](event, target);\r\n          }\r\n          grid.engine.nodes.push(node); // temp add it back so we can proper remove it next\r\n          grid.removeWidget(el, true, true);\r\n        } else {\r\n          Utils.removePositioningStyles(target);\r\n          if (node._temporaryRemoved) {\r\n            // got removed - restore item back to before dragging position\r\n            Utils.copyPos(node, node._orig);// @ts-ignore\r\n            this._writePosAttr(target, node);\r\n            this.engine.addNode(node);\r\n          } else {\r\n            // move to new placeholder location\r\n            this._writePosAttr(target, node);\r\n          }\r\n          this.triggerEvent(event, target);\r\n        }\r\n        // @ts-ignore\r\n        this._extraDragRow = 0;// @ts-ignore\r\n        this._updateContainerHeight();// @ts-ignore\r\n        this._triggerChangeEvent();\r\n\r\n        this.engine.endUpdate();\r\n\r\n        if (event.type === 'resizestop') {\r\n          if (Number.isInteger(node.sizeToContent)) node.sizeToContent = node.h; // new soft limit\r\n          this.resizeToContentCheck(widthChanged, node); // wait for width animation if changed\r\n        }\r\n      }\r\n\r\n      dd.draggable(el, {\r\n        start: onStartMoving,\r\n        stop: onEndMoving,\r\n        drag: dragOrResize\r\n      }).resizable(el, {\r\n        start: onStartMoving,\r\n        stop: onEndMoving,\r\n        resize: dragOrResize\r\n      });\r\n      node._initDD = true; // we've set DD support now\r\n    }\r\n\r\n    // finally fine tune move vs resize by disabling any part...\r\n    dd.draggable(el, noMove ? 'disable' : 'enable')\r\n      .resizable(el, noResize ? 'disable' : 'enable');\r\n\r\n    return this;\r\n  }\r\n\r\n  /** @internal handles actual drag/resize start */\r\n  protected _onStartMoving(el: GridItemHTMLElement, event: Event, ui: DDUIData, node: GridStackNode, cellWidth: number, cellHeight: number): void {\r\n    this.engine.cleanNodes()\r\n      .beginUpdate(node);\r\n    // @ts-ignore\r\n    this._writePosAttr(this.placeholder, node)\r\n    this.el.appendChild(this.placeholder);\r\n    this.placeholder.gridstackNode = node;\r\n    // console.log('_onStartMoving placeholder') // TEST\r\n\r\n    // if the element is inside a grid, it has already been scaled\r\n    // we can use that as a scale reference\r\n    if (node.grid?.el) {\r\n      this.dragTransform = Utils.getValuesFromTransformedElement(el);\r\n    }\r\n    // if the element is being dragged from outside (not from any grid)\r\n    // we use the grid as the transformation reference, since the helper is not subject to transformation\r\n    else if (this.placeholder && this.placeholder.closest('.grid-stack')) {\r\n      const gridEl = this.placeholder.closest('.grid-stack') as HTMLElement;\r\n      this.dragTransform = Utils.getValuesFromTransformedElement(gridEl);\r\n    }\r\n    // Fallback\r\n    else {\r\n      this.dragTransform = {\r\n        xScale: 1,\r\n        xOffset: 0,\r\n        yScale: 1,\r\n        yOffset: 0,\r\n      }\r\n    }\r\n\r\n    node.el = this.placeholder;\r\n    node._lastUiPosition = ui.position;\r\n    node._prevYPix = ui.position.top;\r\n    node._moving = (event.type === 'dragstart'); // 'dropover' are not initially moving so they can go exactly where they enter (will push stuff out of the way)\r\n    node._resizing = (event.type === 'resizestart');\r\n    delete node._lastTried;\r\n\r\n    if (event.type === 'dropover' && node._temporaryRemoved) {\r\n      // console.log('engine.addNode x=' + node.x); // TEST\r\n      this.engine.addNode(node); // will add, fix collisions, update attr and clear _temporaryRemoved\r\n      node._moving = true; // AFTER, mark as moving object (wanted fix location before)\r\n    }\r\n\r\n    // set the min/max resize info taking into account the column count and position (so we don't resize outside the grid)\r\n    this.engine.cacheRects(cellWidth, cellHeight, this.opts.marginTop as number, this.opts.marginRight as number, this.opts.marginBottom as number, this.opts.marginLeft as number);\r\n    if (event.type === 'resizestart') {\r\n      const colLeft = this.getColumn() - node.x;\r\n      const rowLeft = (this.opts.maxRow || Number.MAX_SAFE_INTEGER) - node.y;\r\n      dd.resizable(el, 'option', 'minWidth', cellWidth * Math.min(node.minW || 1, colLeft))\r\n        .resizable(el, 'option', 'minHeight', cellHeight * Math.min(node.minH || 1, rowLeft))\r\n        .resizable(el, 'option', 'maxWidth', cellWidth * Math.min(node.maxW || Number.MAX_SAFE_INTEGER, colLeft))\r\n        .resizable(el, 'option', 'maxWidthMoveLeft', cellWidth * Math.min(node.maxW || Number.MAX_SAFE_INTEGER, node.x+node.w))\r\n        .resizable(el, 'option', 'maxHeight', cellHeight * Math.min(node.maxH || Number.MAX_SAFE_INTEGER, rowLeft))\r\n        .resizable(el, 'option', 'maxHeightMoveUp', cellHeight * Math.min(node.maxH || Number.MAX_SAFE_INTEGER, node.y+node.h));\r\n    }\r\n  }\r\n\r\n  /** @internal handles actual drag/resize */\r\n  protected _dragOrResize(el: GridItemHTMLElement, event: MouseEvent, ui: DDUIData, node: GridStackNode, cellWidth: number, cellHeight: number): void {\r\n    const p = { ...node._orig }; // could be undefined (_isExternal) which is ok (drag only set x,y and w,h will default to node value)\r\n    let resizing: boolean;\r\n    let mLeft = this.opts.marginLeft as number,\r\n      mRight = this.opts.marginRight as number,\r\n      mTop = this.opts.marginTop as number,\r\n      mBottom = this.opts.marginBottom as number;\r\n\r\n    // if margins (which are used to pass mid point by) are large relative to cell height/width, reduce them down #1855\r\n    const mHeight = Math.round(cellHeight * 0.1),\r\n      mWidth = Math.round(cellWidth * 0.1);\r\n    mLeft = Math.min(mLeft, mWidth);\r\n    mRight = Math.min(mRight, mWidth);\r\n    mTop = Math.min(mTop, mHeight);\r\n    mBottom = Math.min(mBottom, mHeight);\r\n\r\n    if (event.type === 'drag') {\r\n      if (node._temporaryRemoved) return; // handled by dropover\r\n      const distance = ui.position.top - node._prevYPix;\r\n      node._prevYPix = ui.position.top;\r\n      if (this.opts.draggable.scroll !== false) {\r\n        Utils.updateScrollPosition(el, ui.position, distance);\r\n      }\r\n\r\n      // get new position taking into account the margin in the direction we are moving! (need to pass mid point by margin)\r\n      const left = ui.position.left + (ui.position.left > node._lastUiPosition.left ? -mRight : mLeft);\r\n      const top = ui.position.top + (ui.position.top > node._lastUiPosition.top ? -mBottom : mTop);\r\n      p.x = Math.round(left / cellWidth);\r\n      p.y = Math.round(top / cellHeight);\r\n\r\n      // @ts-ignore// if we're at the bottom hitting something else, grow the grid so cursor doesn't leave when trying to place below others\r\n      const prev = this._extraDragRow;\r\n      if (this.engine.collide(node, p)) {\r\n        const row = this.getRow();\r\n        let extra = Math.max(0, (p.y + node.h) - row);\r\n        if (this.opts.maxRow && row + extra > this.opts.maxRow) {\r\n          extra = Math.max(0, this.opts.maxRow - row);\r\n        }// @ts-ignore\r\n        this._extraDragRow = extra;// @ts-ignore\r\n      } else this._extraDragRow = 0;// @ts-ignore\r\n      if (this._extraDragRow !== prev) this._updateContainerHeight();\r\n\r\n      if (node.x === p.x && node.y === p.y) return; // skip same\r\n      // DON'T skip one we tried as we might have failed because of coverage <50% before\r\n      // if (node._lastTried && node._lastTried.x === x && node._lastTried.y === y) return;\r\n    } else if (event.type === 'resize') {\r\n      if (p.x < 0) return;\r\n      // Scrolling page if needed\r\n      Utils.updateScrollResize(event, el, cellHeight);\r\n\r\n      // get new size\r\n      p.w = Math.round((ui.size.width - mLeft) / cellWidth);\r\n      p.h = Math.round((ui.size.height - mTop) / cellHeight);\r\n      if (node.w === p.w && node.h === p.h) return;\r\n      if (node._lastTried && node._lastTried.w === p.w && node._lastTried.h === p.h) return; // skip one we tried (but failed)\r\n\r\n      // if we size on left/top side this might move us, so get possible new position as well\r\n      const left = ui.position.left + mLeft;\r\n      const top = ui.position.top + mTop;\r\n      p.x = Math.round(left / cellWidth);\r\n      p.y = Math.round(top / cellHeight);\r\n\r\n      resizing = true;\r\n    }\r\n\r\n    node._event = event;\r\n    node._lastTried = p; // set as last tried (will nuke if we go there)\r\n    const rect: GridStackPosition = { // screen pix of the dragged box\r\n      x: ui.position.left + mLeft,\r\n      y: ui.position.top + mTop,\r\n      w: (ui.size ? ui.size.width : node.w * cellWidth) - mLeft - mRight,\r\n      h: (ui.size ? ui.size.height : node.h * cellHeight) - mTop - mBottom\r\n    };\r\n    if (this.engine.moveNodeCheck(node, { ...p, cellWidth, cellHeight, rect, resizing })) {\r\n      node._lastUiPosition = ui.position;\r\n      this.engine.cacheRects(cellWidth, cellHeight, mTop, mRight, mBottom, mLeft);\r\n      delete node._skipDown;\r\n      if (resizing && node.subGrid) node.subGrid.onResize();\r\n      this._extraDragRow = 0;// @ts-ignore\r\n      this._updateContainerHeight();\r\n\r\n      const target = event.target as GridItemHTMLElement;// @ts-ignore\r\n      // Do not write sidebar item attributes back to the original sidebar el\r\n      if (!node._sidebarOrig) {\r\n        this._writePosAttr(target, node);\r\n      }\r\n      this.triggerEvent(event, target);\r\n    }\r\n  }\r\n\r\n  /** call given event callback on our main top-most grid (if we're nested) */\r\n  protected triggerEvent(event: Event, target: GridItemHTMLElement) {\r\n    // eslint-disable-next-line @typescript-eslint/no-this-alias\r\n    let grid: GridStack = this;\r\n    while (grid.parentGridNode) grid = grid.parentGridNode.grid;\r\n    if (grid._gsEventHandler[event.type]) {\r\n      grid._gsEventHandler[event.type](event, target);\r\n    }\r\n  }\r\n\r\n  /** @internal called when item leaving our area by either cursor dropout event\r\n   * or shape is outside our boundaries. remove it from us, and mark temporary if this was\r\n   * our item to start with else restore prev node values from prev grid it came from.\r\n   */\r\n  protected _leave(el: GridItemHTMLElement, helper?: GridItemHTMLElement): void {\r\n    helper = helper || el;\r\n    const node = helper.gridstackNode;\r\n    if (!node) return;\r\n\r\n    // remove the scale of the helper on leave\r\n    helper.style.transform = helper.style.transformOrigin = null;\r\n    dd.off(el, 'drag'); // no need to track while being outside\r\n\r\n    // this gets called when cursor leaves and shape is outside, so only do this once\r\n    if (node._temporaryRemoved) return;\r\n    node._temporaryRemoved = true;\r\n\r\n    this.engine.removeNode(node); // remove placeholder as well, otherwise it's a sign node is not in our list, which is a bigger issue\r\n    node.el = node._isExternal && helper ? helper : el; // point back to real item being dragged\r\n    const sidebarOrig = node._sidebarOrig;\r\n    if (node._isExternal) this.engine.cleanupNode(node);\r\n    // Restore sidebar item initial size info to stay consistent when dragging between multiple grids\r\n    node._sidebarOrig = sidebarOrig;\r\n\r\n    if (this.opts.removable === true) { // boolean vs a class string\r\n      // item leaving us and we are supposed to remove on leave (no need to drag onto trash) mark it so\r\n      GridStack._itemRemoving(el, true);\r\n    }\r\n\r\n    // finally if item originally came from another grid, but left us, restore things back to prev info\r\n    if (el._gridstackNodeOrig) {\r\n      // console.log('leave delete _gridstackNodeOrig') // TEST\r\n      el.gridstackNode = el._gridstackNodeOrig;\r\n      delete el._gridstackNodeOrig;\r\n    } else if (node._isExternal) {\r\n      // item came from outside restore all nodes back to original\r\n      this.engine.restoreInitial();\r\n    }\r\n  }\r\n\r\n  // legacy method removed\r\n  public commit(): GridStack { obsolete(this, this.batchUpdate(false), 'commit', 'batchUpdate', '5.2'); return this; }\r\n}\r\n","/**\r\n * dd-gridstack.ts 12.1.2\r\n * Copyright (c) 2021-2024 Alain Dumesny - see GridStack root license\r\n */\r\n\r\n/* eslint-disable @typescript-eslint/no-unused-vars */\r\nimport { GridItemHTMLElement, GridStackElement, DDDragOpt } from './types';\r\nimport { Utils } from './utils';\r\nimport { DDManager } from './dd-manager';\r\nimport { DDElement, DDElementHost } from './dd-element';\r\nimport { GridHTMLElement } from './gridstack';\r\n\r\n/** Drag&Drop drop options */\r\nexport type DDDropOpt = {\r\n  /** function or class type that this grid will accept as dropped items (see GridStackOptions.acceptWidgets) */\r\n  accept?: (el: GridItemHTMLElement) => boolean;\r\n}\r\n\r\n/** drag&drop options currently called from the main code, but others can be passed in grid options */\r\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\r\nexport type DDOpts = 'enable' | 'disable' | 'destroy' | 'option' | string | any;\r\nexport type DDKey = 'minWidth' | 'minHeight' | 'maxWidth' | 'maxHeight' | 'maxHeightMoveUp' | 'maxWidthMoveLeft';\r\nexport type DDValue = number | string;\r\n\r\n/** drag&drop events callbacks */\r\nexport type DDCallback = (event: Event, arg2: GridItemHTMLElement, helper?: GridItemHTMLElement) => void;\r\n\r\n// let count = 0; // TEST\r\n\r\n/**\r\n * HTML Native Mouse and Touch Events Drag and Drop functionality.\r\n */\r\nexport class DDGridStack {\r\n\r\n  public resizable(el: GridItemHTMLElement, opts: DDOpts, key?: DDKey, value?: DDValue): DDGridStack {\r\n    this._getDDElements(el, opts).forEach(dEl => {\r\n      if (opts === 'disable' || opts === 'enable') {\r\n        dEl.ddResizable && dEl.ddResizable[opts](); // can't create DD as it requires options for setupResizable()\r\n      } else if (opts === 'destroy') {\r\n        dEl.ddResizable && dEl.cleanResizable();\r\n      } else if (opts === 'option') {\r\n        dEl.setupResizable({ [key]: value });\r\n      } else {\r\n        const n = dEl.el.gridstackNode;\r\n        const grid = n.grid;\r\n        let handles = dEl.el.getAttribute('gs-resize-handles') || grid.opts.resizable.handles || 'e,s,se';\r\n        if (handles === 'all') handles = 'n,e,s,w,se,sw,ne,nw';\r\n        // NOTE: keep the resize handles as e,w don't have enough space (10px) to show resize corners anyway. limit during drag instead\r\n        // restrict vertical resize if height is done to match content anyway... odd to have it spring back\r\n        // if (Utils.shouldSizeToContent(n, true)) {\r\n        //   const doE = handles.indexOf('e') !== -1;\r\n        //   const doW = handles.indexOf('w') !== -1;\r\n        //   handles = doE ? (doW ? 'e,w' : 'e') : (doW ? 'w' : '');\r\n        // }\r\n        const autoHide = !grid.opts.alwaysShowResizeHandle;\r\n        dEl.setupResizable({\r\n          ...grid.opts.resizable,\r\n          ...{ handles, autoHide },\r\n          ...{\r\n            start: opts.start,\r\n            stop: opts.stop,\r\n            resize: opts.resize\r\n          }\r\n        });\r\n      }\r\n    });\r\n    return this;\r\n  }\r\n\r\n  public draggable(el: GridItemHTMLElement, opts: DDOpts, key?: DDKey, value?: DDValue): DDGridStack {\r\n    this._getDDElements(el, opts).forEach(dEl => {\r\n      if (opts === 'disable' || opts === 'enable') {\r\n        dEl.ddDraggable && dEl.ddDraggable[opts](); // can't create DD as it requires options for setupDraggable()\r\n      } else if (opts === 'destroy') {\r\n        dEl.ddDraggable && dEl.cleanDraggable();\r\n      } else if (opts === 'option') {\r\n        dEl.setupDraggable({ [key]: value });\r\n      } else {\r\n        const grid = dEl.el.gridstackNode.grid;\r\n        dEl.setupDraggable({\r\n          ...grid.opts.draggable,\r\n          ...{\r\n            // containment: (grid.parentGridNode && grid.opts.dragOut === false) ? grid.el.parentElement : (grid.opts.draggable.containment || null),\r\n            start: opts.start,\r\n            stop: opts.stop,\r\n            drag: opts.drag\r\n          }\r\n        });\r\n      }\r\n    });\r\n    return this;\r\n  }\r\n\r\n  public dragIn(el: GridStackElement, opts: DDDragOpt): DDGridStack {\r\n    this._getDDElements(el).forEach(dEl => dEl.setupDraggable(opts));\r\n    return this;\r\n  }\r\n\r\n  public droppable(el: GridItemHTMLElement, opts: DDOpts | DDDropOpt, key?: DDKey, value?: DDValue): DDGridStack {\r\n    if (typeof opts.accept === 'function' && !opts._accept) {\r\n      opts._accept = opts.accept;\r\n      opts.accept = (el) => opts._accept(el);\r\n    }\r\n    this._getDDElements(el, opts).forEach(dEl => {\r\n      if (opts === 'disable' || opts === 'enable') {\r\n        dEl.ddDroppable && dEl.ddDroppable[opts]();\r\n      } else if (opts === 'destroy') {\r\n        dEl.ddDroppable && dEl.cleanDroppable();\r\n      } else if (opts === 'option') {\r\n        dEl.setupDroppable({ [key]: value });\r\n      } else {\r\n        dEl.setupDroppable(opts);\r\n      }\r\n    });\r\n    return this;\r\n  }\r\n\r\n  /** true if element is droppable */\r\n  public isDroppable(el: DDElementHost): boolean {\r\n    return !!(el?.ddElement?.ddDroppable && !el.ddElement.ddDroppable.disabled);\r\n  }\r\n\r\n  /** true if element is draggable */\r\n  public isDraggable(el: DDElementHost): boolean {\r\n    return !!(el?.ddElement?.ddDraggable && !el.ddElement.ddDraggable.disabled);\r\n  }\r\n\r\n  /** true if element is draggable */\r\n  public isResizable(el: DDElementHost): boolean {\r\n    return !!(el?.ddElement?.ddResizable && !el.ddElement.ddResizable.disabled);\r\n  }\r\n\r\n  public on(el: GridItemHTMLElement, name: string, callback: DDCallback): DDGridStack {\r\n    this._getDDElements(el).forEach(dEl =>\r\n      dEl.on(name, (event: Event) => {\r\n        callback(\r\n          event,\r\n          DDManager.dragElement ? DDManager.dragElement.el : event.target as GridItemHTMLElement,\r\n          DDManager.dragElement ? DDManager.dragElement.helper : null)\r\n      })\r\n    );\r\n    return this;\r\n  }\r\n\r\n  public off(el: GridItemHTMLElement, name: string): DDGridStack {\r\n    this._getDDElements(el).forEach(dEl => dEl.off(name));\r\n    return this;\r\n  }\r\n\r\n  /** @internal returns a list of DD elements, creating them on the fly by default unless option is to destroy or disable */\r\n  protected _getDDElements(els: GridStackElement, opts?: DDOpts): DDElement[] {\r\n    // don't force create if we're going to destroy it, unless it's a grid which is used as drop target for it's children\r\n    const create = (els as GridHTMLElement).gridstack ||  opts !== 'destroy' && opts !== 'disable';\r\n    const hosts = Utils.getElements(els) as DDElementHost[];\r\n    if (!hosts.length) return [];\r\n    const list = hosts.map(e => e.ddElement || (create ? DDElement.init(e) : null)).filter(d => d); // remove nulls\r\n    return list;\r\n  }\r\n}\r\n"],"names":["root","factory","exports","module","define","amd","self","__webpack_require__","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","Utils","getElements","els","document","doc","undefined","isNaN","el","getElementById","list","querySelectorAll","length","Array","from","getElement","substring","querySelector","lazyLoad","n","grid","opts","createDiv","classes","parent","createElement","forEach","c","classList","add","appendChild","shouldSizeToContent","strict","sizeToContent","isIntercepted","a","b","y","h","x","w","isTouching","areaIntercept","x0","x1","y0","y1","area","sort","nodes","dir","und","diffY","find","id","toBool","v","toLowerCase","Boolean","toNumber","value","Number","parseHeight","val","unit","match","Error","parseFloat","defaults","target","sources","source","this","same","keys","copyPos","doMinMax","minW","minH","maxW","maxH","samePos","sanitizeMinMax","node","removeInternalAndSame","aVal","bVal","removeInternalForSave","removeEl","autoPosition","noResize","noMove","locked","throttle","func","delay","isWaiting","args","setTimeout","removePositioningStyles","style","position","removeProperty","left","top","width","height","getScrollElement","scrollingElement","documentElement","getComputedStyle","test","overflow","overflowY","parentElement","updateScrollPosition","distance","rect","getBoundingClientRect","innerHeightOrClientHeight","window","innerHeight","clientHeight","bottom","offsetDiffDown","offsetDiffUp","scrollEl","prevScroll","scrollTop","offsetHeight","Math","abs","updateScrollResize","event","offsetTop","pointerPosY","clientY","scrollBy","behavior","clone","cloneDeep","skipFields","ret","k","cloneNode","removeAttribute","appendTo","parentNode","addElStyles","styles","s","isArray","initEvent","e","info","evt","type","button","which","buttons","bubbles","cancelable","p","simulateMouseEvent","simulatedType","me","simulatedEvent","MouseEvent","composed","view","detail","screenX","screenY","clientX","ctrlKey","altKey","shiftKey","metaKey","relatedTarget","dispatchEvent","getValuesFromTransformedElement","transformReference","opacity","zIndex","transformValues","removeChild","remove","xScale","yScale","xOffset","yOffset","swap","tmp","canBeRotated","disableResize","GridStackEngine","addedNodes","removedNodes","defaultColumn","column","maxRow","_float","float","onChange","batchUpdate","flag","doPack","batchMode","_prevFloat","cleanNodes","saveInitial","_packNodes","_notify","_useEntireRowArea","nn","_hasLocked","_moving","_skipDown","_fixCollisions","collide","opt","sortNodes","nested","_loading","skip","didMove","newOpt","pack","counter","moved","newNN","moveNode","skip2","skipId","_id","skip2Id","collideAll","filter","directionCollideCoverage","collides","_rect","r0","r","overMax","r2","yOver","MAX_VALUE","xOver","over","min","cacheRects","right","_doSwap","_dirty","touching","t","isAreaEmpty","compact","layout","doSort","wasBatch","wasColumnResize","_inColumnResize","copyNodes","index","after","addNode","_updating","_orig","newY","i","prepareNode","resizing","_idSeq","count","nodeBoundFix","before","max","skipCacheUpdate","findCacheLayout","copy","cacheOneLayout","getDirtyNodes","verify","dirtyNodes","concat","_lastTried","some","restoreInitial","findEmptyPosition","nodeList","found","floor","box","triggerAddEvent","dup","skipCollision","_temporaryRemoved","_removeDOM","push","removeNode","removeDOM","triggerEvent","_isAboutToRemove","removeAll","_layouts","moveNodeCheck","changedPosConstrain","clonedNode","map","canMove","getRow","gridstackNode","willItFit","_willFitPos","cleanupNode","content","wasUndefinedPack","forceCollide","prevPos","needToMove","activeDrag","subGridDynamic","_isTemp","a1","a2","makeSubGrid","reduce","row","beginUpdate","endUpdate","save","saveElement","saveCB","len","wl","l","layoutsNodesChange","ratio","round","columnChanged","prevColumn","doCompact","cacheLayout","newNodes","cacheNodes","lastIndex","cacheNode","j","findIndex","splice","move","scale","clear","existing","n2","removeNodeFromLayoutCache","gridDefaults","alwaysShowResizeHandle","animate","auto","cellHeight","cellHeightThrottle","cellHeightUnit","draggable","handle","scroll","itemClass","margin","marginUnit","minRow","placeholderClass","placeholderText","removableOptions","accept","decline","resizable","handles","rtl","DDManager","isTouch","DocumentTouch","navigator","maxTouchPoints","msMaxTouchPoints","DDTouch","touches","preventDefault","changedTouches","simulatePointerMouseEvent","touchstart","touchHandled","touchmove","touchend","pointerLeaveTimeout","clearTimeout","wasDragging","dragElement","pointerdown","pointerType","releasePointerCapture","pointerId","pointerenter","pointerleave","DDResizableHandle","constructor","host","option","moving","_mouseDown","bind","_mouseMove","_mouseUp","_keyEvent","_init","prefix","userSelect","addEventListener","destroy","mouseDownEvent","removeEventListener","capture","passive","stopPropagation","_triggerEvent","engine","name","DDBaseImplement","_eventRegister","disabled","_disabled","on","callback","off","enable","disable","eventName","DDResizable","super","rectScale","_ui","containmentRect","newRect","originalRect","scrolled","temporalRect","size","_mouseOver","_mouseOut","_setupAutoHide","autoHide","_setupHandlers","_removeHandlers","updateOption","updateHandles","updateAutoHide","overResizeElement","handlers","split","trim","start","_resizeStart","stop","_resizeStop","_resizing","scrollY","startEvent","_setupHelper","_applyChange","ev","_getChange","resize","_cleanHelper","elOriginStyleVal","_originStyleProp","parentOriginStylePosition","dragTransform","oEvent","offsetX","offsetY","moveLeft","moveUp","indexOf","constrain","_constrainSize","oWidth","oHeight","maxWidth","maxWidthMoveLeft","MAX_SAFE_INTEGER","minWidth","maxHeight","maxHeightMoveUp","minHeight","containmentEl","scaleReciprocal","DDDraggable","handleName","dragEls","contains","subGrid","dragEl","forDestroy","dragTimeout","helper","mouseHandled","closest","cancel","dragging","dropElement","currentTarget","activeElement","blur","_callDrag","drag","ui","lastDrag","_dragFollow","pauseDrag","pause","isInteger","ddElement","ddDroppable","_createHelper","_setupHelperContainmentStyle","helperContainment","dragOffset","_getDragOffset","_setupHelperStyle","_origRotate","_removeHelperStyle","drop","gridstack","cancelDrag","setAnimation","rotate","offsetLeft","dragElementOriginStyle","originStyleProp","pointerEvents","willChange","transition","offset","xformOffsetX","xformOffsetY","targetOffset","DDDroppable","_mouseEnter","_mouseLeave","_setupAccept","_canDrop","calledByEnter","out","parentDrop","matches","DDElement","init","ddDraggable","ddResizable","setupDraggable","cleanDraggable","setupResizable","cleanResizable","setupDroppable","cleanDroppable","dd","_getDDElements","dEl","getAttribute","dragIn","droppable","_accept","isDroppable","isDraggable","isResizable","create","hosts","d","GridStack","options","elOrString","getGridElement","console","error","initAll","selector","grids","getGridElements","addGrid","children","load","addRemoveCB","class","registerEngine","engineClass","placeholder","_placeholder","placeholderChild","textContent","animationDelay","_gsEventHandler","_extraDragRow","rowAttr","_alwaysShowResizeHandle","resp","columnOpts","bk","breakpoints","columnWidth","columnMax","staticGrid","handleClass","_initMargin","checkDynamicColumn","_updateColumnVar","direction","parentGridItem","parentGridNode","_isAutoCellHeight","_setStaticClass","getColumn","cbNodes","_writePosAttr","_updateContainerHeight","getGridItems","_prepareElement","_setupRemoveDrop","_setupAcceptWidget","_updateResizeEvent","setProperty","addWidget","ELEMENT_NODE","makeWidget","createWidgetDivs","domAttr","_readAttr","cont","visibleObservable","IntersectionObserver","entry","isIntersecting","disconnect","renderCB","prepareDragDrop","observe","ops","nodeToAdd","saveContent","subGridTemplate","autoColumn","subGridOpts","newItem","newItemOpt","_removeDD","update","_autoColumn","_event","resizeToContentCheck","removeAsSubGrid","nodeThatRemoved","pGrid","removeWidget","saveGridOpt","itemContent","innerHTML","listOrOpt","marginBottom","marginTop","marginRight","marginLeft","origShow","items","addRemove","_ignoreLayoutsNodeChange","maxColumn","responseLayout","prevCB","removed","blank","noAnim","updateNodes","item","sub","_triggerRemoveEvent","_triggerAddEvent","_triggerChangeEvent","getCellHeight","forcePixel","fontSize","rows","parseInt","marginDiff","cellWidth","data","_widthOrContainer","forBreakpoint","breakpointForWindow","innerWidth","clientWidth","newColumn","oldColumn","isIgnoreChangeCB","offAll","setStatic","getFloat","getCellFromPixel","useDocRelative","containerPos","relativeLeft","relativeTop","rowHeight","resetIgnoreLayoutsNodeChange","noData","doAnimate","hasAnimationCSS","updateClass","recurse","updateOptions","acceptWidgets","disableDrag","enableMove","enableResize","m","changed","ddChanged","widthChanged","onResize","_writeAttr","wasUpdating","resizeToContent","cell","resizeToContentParent","padding","itemH","wantedH","subRec","parentRec","child","firstElementChild","ceil","softMax","resizeToContentCBCheck","resizeToContentCB","relative","rot","pivotX","pivotY","getMargin","arguments","warn","elements","CustomEvent","Event","cssMinHeight","setAttribute","String","attrs","clearDefaultAttr","attr","prevWidth","_skipInitialResize","forceRemove","trackSize","resizeObserver","_sizeThrottle","ResizeObserver","margins","getDD","setupDragIn","dragInOptions","widgets","movable","doEnable","_isExternal","_itemRemoving","_initDD","removable","onDrag","transform","helperRect","transformOrigin","_onStartMoving","_dragOrResize","canAccept","_sidebarOrig","_leave","JSON","parse","offsetWidth","_gridstackNodeOrig","wasAdded","wasSidebar","origNode","oGrid","trashEl","force","onStartMoving","dragOrResize","onEndMoving","gridEl","_lastUiPosition","_prevYPix","colLeft","rowLeft","mLeft","mRight","mTop","mBottom","mHeight","mWidth","prev","extra","sidebarOrig","commit","Engine","GDRev"],"sourceRoot":""}
\ No newline at end of file
diff --git a/node_modules/gridstack/dist/gridstack.css b/node_modules/gridstack/dist/gridstack.css
new file mode 100644
index 000000000..f0b4243ba
--- /dev/null
+++ b/node_modules/gridstack/dist/gridstack.css
@@ -0,0 +1,174 @@
+/**
+ * gridstack SASS styles 12.1.2
+ * Copyright (c) 2021-2024 Alain Dumesny - see GridStack root license
+ */
+.grid-stack {
+  position: relative;
+}
+
+.grid-stack-rtl {
+  direction: ltr;
+}
+.grid-stack-rtl > .grid-stack-item {
+  direction: rtl;
+}
+
+.grid-stack-placeholder > .placeholder-content {
+  background-color: rgba(0, 0, 0, 0.1);
+  margin: 0;
+  position: absolute;
+  width: auto;
+  z-index: 0 !important;
+}
+
+.grid-stack > .grid-stack-item {
+  position: absolute;
+  padding: 0;
+  top: 0;
+  left: 0;
+  width: var(--gs-column-width);
+  height: var(--gs-cell-height);
+}
+.grid-stack > .grid-stack-item > .grid-stack-item-content {
+  margin: 0;
+  position: absolute;
+  width: auto;
+  overflow-x: hidden;
+  overflow-y: auto;
+}
+.grid-stack > .grid-stack-item.size-to-content:not(.size-to-content-max) > .grid-stack-item-content {
+  overflow-y: hidden;
+}
+
+.grid-stack > .grid-stack-item > .grid-stack-item-content,
+.grid-stack > .grid-stack-placeholder > .placeholder-content {
+  top: var(--gs-item-margin-top);
+  right: var(--gs-item-margin-right);
+  bottom: var(--gs-item-margin-bottom);
+  left: var(--gs-item-margin-left);
+}
+
+.grid-stack-item > .ui-resizable-handle {
+  position: absolute;
+  font-size: 0.1px;
+  display: block;
+  -ms-touch-action: none;
+  touch-action: none;
+}
+.grid-stack-item.ui-resizable-disabled > .ui-resizable-handle, .grid-stack-item.ui-resizable-autohide > .ui-resizable-handle {
+  display: none;
+}
+.grid-stack-item > .ui-resizable-ne,
+.grid-stack-item > .ui-resizable-nw,
+.grid-stack-item > .ui-resizable-se,
+.grid-stack-item > .ui-resizable-sw {
+  background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="%23666" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 20 20"><path d="m10 3 2 2H8l2-2v14l-2-2h4l-2 2"/></svg>');
+  background-repeat: no-repeat;
+  background-position: center;
+}
+.grid-stack-item > .ui-resizable-ne {
+  transform: rotate(45deg);
+}
+.grid-stack-item > .ui-resizable-sw {
+  transform: rotate(45deg);
+}
+.grid-stack-item > .ui-resizable-nw {
+  transform: rotate(-45deg);
+}
+.grid-stack-item > .ui-resizable-se {
+  transform: rotate(-45deg);
+}
+.grid-stack-item > .ui-resizable-nw {
+  cursor: nw-resize;
+  width: 20px;
+  height: 20px;
+  top: var(--gs-item-margin-top);
+  left: var(--gs-item-margin-left);
+}
+.grid-stack-item > .ui-resizable-n {
+  cursor: n-resize;
+  height: 10px;
+  top: var(--gs-item-margin-top);
+  left: 25px;
+  right: 25px;
+}
+.grid-stack-item > .ui-resizable-ne {
+  cursor: ne-resize;
+  width: 20px;
+  height: 20px;
+  top: var(--gs-item-margin-top);
+  right: var(--gs-item-margin-right);
+}
+.grid-stack-item > .ui-resizable-e {
+  cursor: e-resize;
+  width: 10px;
+  top: 15px;
+  bottom: 15px;
+  right: var(--gs-item-margin-right);
+}
+.grid-stack-item > .ui-resizable-se {
+  cursor: se-resize;
+  width: 20px;
+  height: 20px;
+  bottom: var(--gs-item-margin-bottom);
+  right: var(--gs-item-margin-right);
+}
+.grid-stack-item > .ui-resizable-s {
+  cursor: s-resize;
+  height: 10px;
+  left: 25px;
+  bottom: var(--gs-item-margin-bottom);
+  right: 25px;
+}
+.grid-stack-item > .ui-resizable-sw {
+  cursor: sw-resize;
+  width: 20px;
+  height: 20px;
+  bottom: var(--gs-item-margin-bottom);
+  left: var(--gs-item-margin-left);
+}
+.grid-stack-item > .ui-resizable-w {
+  cursor: w-resize;
+  width: 10px;
+  top: 15px;
+  bottom: 15px;
+  left: var(--gs-item-margin-left);
+}
+.grid-stack-item.ui-draggable-dragging > .ui-resizable-handle {
+  display: none !important;
+}
+.grid-stack-item.ui-draggable-dragging {
+  will-change: left, top;
+}
+.grid-stack-item.ui-resizable-resizing {
+  will-change: width, height;
+}
+
+.ui-draggable-dragging,
+.ui-resizable-resizing {
+  z-index: 10000;
+}
+.ui-draggable-dragging > .grid-stack-item-content,
+.ui-resizable-resizing > .grid-stack-item-content {
+  box-shadow: 1px 4px 6px rgba(0, 0, 0, 0.2);
+  opacity: 0.8;
+}
+
+.grid-stack-animate,
+.grid-stack-animate .grid-stack-item {
+  transition: left 0.3s, top 0.3s, height 0.3s, width 0.3s;
+}
+
+.grid-stack-animate .grid-stack-item.ui-draggable-dragging,
+.grid-stack-animate .grid-stack-item.ui-resizable-resizing,
+.grid-stack-animate .grid-stack-item.grid-stack-placeholder {
+  transition: left 0s, top 0s, height 0s, width 0s;
+}
+
+.grid-stack > .grid-stack-item[gs-y="0"] {
+  top: 0px;
+}
+
+.grid-stack > .grid-stack-item[gs-x="0"] {
+  left: 0%;
+}
\ No newline at end of file
diff --git a/node_modules/gridstack/dist/gridstack.min.css b/node_modules/gridstack/dist/gridstack.min.css
new file mode 100644
index 000000000..cd22fa125
--- /dev/null
+++ b/node_modules/gridstack/dist/gridstack.min.css
@@ -0,0 +1 @@
+.grid-stack{position:relative}.grid-stack-rtl{direction:ltr}.grid-stack-rtl>.grid-stack-item{direction:rtl}.grid-stack-placeholder>.placeholder-content{background-color:rgba(0,0,0,.1);margin:0;position:absolute;width:auto;z-index:0!important}.grid-stack>.grid-stack-item{position:absolute;padding:0;top:0;left:0;width:var(--gs-column-width);height:var(--gs-cell-height)}.grid-stack>.grid-stack-item>.grid-stack-item-content{margin:0;position:absolute;width:auto;overflow-x:hidden;overflow-y:auto}.grid-stack>.grid-stack-item.size-to-content:not(.size-to-content-max)>.grid-stack-item-content{overflow-y:hidden}.grid-stack>.grid-stack-item>.grid-stack-item-content,.grid-stack>.grid-stack-placeholder>.placeholder-content{top:var(--gs-item-margin-top);right:var(--gs-item-margin-right);bottom:var(--gs-item-margin-bottom);left:var(--gs-item-margin-left)}.grid-stack-item>.ui-resizable-handle{position:absolute;font-size:.1px;display:block;-ms-touch-action:none;touch-action:none}.grid-stack-item.ui-resizable-autohide>.ui-resizable-handle,.grid-stack-item.ui-resizable-disabled>.ui-resizable-handle{display:none}.grid-stack-item>.ui-resizable-ne,.grid-stack-item>.ui-resizable-nw,.grid-stack-item>.ui-resizable-se,.grid-stack-item>.ui-resizable-sw{background-image:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="%23666" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 20 20"><path d="m10 3 2 2H8l2-2v14l-2-2h4l-2 2"/></svg>');background-repeat:no-repeat;background-position:center}.grid-stack-item>.ui-resizable-ne{transform:rotate(45deg)}.grid-stack-item>.ui-resizable-sw{transform:rotate(45deg)}.grid-stack-item>.ui-resizable-nw{transform:rotate(-45deg)}.grid-stack-item>.ui-resizable-se{transform:rotate(-45deg)}.grid-stack-item>.ui-resizable-nw{cursor:nw-resize;width:20px;height:20px;top:var(--gs-item-margin-top);left:var(--gs-item-margin-left)}.grid-stack-item>.ui-resizable-n{cursor:n-resize;height:10px;top:var(--gs-item-margin-top);left:25px;right:25px}.grid-stack-item>.ui-resizable-ne{cursor:ne-resize;width:20px;height:20px;top:var(--gs-item-margin-top);right:var(--gs-item-margin-right)}.grid-stack-item>.ui-resizable-e{cursor:e-resize;width:10px;top:15px;bottom:15px;right:var(--gs-item-margin-right)}.grid-stack-item>.ui-resizable-se{cursor:se-resize;width:20px;height:20px;bottom:var(--gs-item-margin-bottom);right:var(--gs-item-margin-right)}.grid-stack-item>.ui-resizable-s{cursor:s-resize;height:10px;left:25px;bottom:var(--gs-item-margin-bottom);right:25px}.grid-stack-item>.ui-resizable-sw{cursor:sw-resize;width:20px;height:20px;bottom:var(--gs-item-margin-bottom);left:var(--gs-item-margin-left)}.grid-stack-item>.ui-resizable-w{cursor:w-resize;width:10px;top:15px;bottom:15px;left:var(--gs-item-margin-left)}.grid-stack-item.ui-draggable-dragging>.ui-resizable-handle{display:none!important}.grid-stack-item.ui-draggable-dragging{will-change:left,top}.grid-stack-item.ui-resizable-resizing{will-change:width,height}.ui-draggable-dragging,.ui-resizable-resizing{z-index:10000}.ui-draggable-dragging>.grid-stack-item-content,.ui-resizable-resizing>.grid-stack-item-content{box-shadow:1px 4px 6px rgba(0,0,0,.2);opacity:.8}.grid-stack-animate,.grid-stack-animate .grid-stack-item{transition:left .3s,top .3s,height .3s,width .3s}.grid-stack-animate .grid-stack-item.grid-stack-placeholder,.grid-stack-animate .grid-stack-item.ui-draggable-dragging,.grid-stack-animate .grid-stack-item.ui-resizable-resizing{transition:left 0s,top 0s,height 0s,width 0s}.grid-stack>.grid-stack-item[gs-y="0"]{top:0}.grid-stack>.grid-stack-item[gs-x="0"]{left:0}
\ No newline at end of file
diff --git a/package.json b/package.json
new file mode 100644
index 000000000..b4178f97d
--- /dev/null
+++ b/package.json
@@ -0,0 +1,25 @@
+{
+  "name": "gridstack",
+  "version": "0.0.2",
+  "description": "website for gridstack.js",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/gridstack/gridstack.js.git"
+  },
+  "scripts": {
+    "reset": "rm -rf dist node_modules coverage && yarn",
+    "format:fix": "prettier ./index.html ./src --write ./demo/index.html"
+  },
+  "license": "MIT",
+  "bugs": {
+    "url": "https://github.com/gridstack/gridstack.js/issues"
+  },
+  "homepage": "http://gridstackjs.com",
+  "dependencies": {
+    "gridstack": "12.1.2"
+  },
+  "devDependencies": {
+    "prettier": "3.2.5"
+  },
+  "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
+}
diff --git a/src/scripts/fetch-latest-github-release.js b/src/scripts/fetch-latest-github-release.js
new file mode 100644
index 000000000..41c1e08dd
--- /dev/null
+++ b/src/scripts/fetch-latest-github-release.js
@@ -0,0 +1,26 @@
+document.addEventListener('DOMContentLoaded', () => {
+  const repoOwner = 'gridstack' // Replace with the GitHub username or organization
+  const repoName = 'gridstack.js' // Replace with the repository name
+
+  // GitHub API URL for the latest release
+  const apiUrl = `https://api.github.com/repos/${repoOwner}/${repoName}/releases/latest`
+
+  // Fetch the latest release data from the GitHub API
+  fetch(apiUrl)
+    .then((response) => {
+      if (!response.ok) {
+        throw new Error(`Network response was not ok ${response.statusText}`)
+      }
+      return response.json()
+    })
+    .then((data) => {
+      // Update the content of the <span> element with id "release-version"
+      const releaseVersionElement = document.getElementById('release-version')
+      releaseVersionElement.textContent = data.name
+    })
+    .catch((error) => {
+      console.error('There was a problem with the fetch operation:', error)
+      const releaseVersionElement = document.getElementById('release-version')
+      releaseVersionElement.textContent = 'Error loading release'
+    })
+})
diff --git a/src/styles/globals.css b/src/styles/globals.css
new file mode 100644
index 000000000..63a228c01
--- /dev/null
+++ b/src/styles/globals.css
@@ -0,0 +1,148 @@
+:root {
+  --white: #ffffff;
+  --black: #000000;
+  --transparent: transparent;
+  --blue-500: #3498db; /* Example blue color */
+  --indigo-300: #6574cd; /* Example indigo color */
+  --blue-300: #6cb2eb; /* Example light blue color */
+  --violet-200: #a779e9; /* Example violet color */
+  --blue-400: #3490dc; /* Another example blue color */
+
+  --tw-gray-50: #f9fafb;
+  --tw-gray-100: #f3f4f6;
+  --tw-gray-200: #e5e7eb;
+  --tw-gray-300: #d1d5db;
+  --tw-gray-400: #9ca3af;
+  --tw-gray-500: #6b7280;
+  --tw-gray-600: #4b5563;
+  --tw-gray-700: #374151;
+  --tw-gray-800: #1f2937;
+  --tw-gray-900: #111827;
+  --tw-gray-950: #030712;
+
+  --tw-indigo-50: #eef2ff;
+  --tw-indigo-100: #e0e7ff;
+  --tw-indigo-200: #c7d2fe;
+  --tw-indigo-300: #a5b4fc;
+  --tw-indigo-400: #818cf8;
+  --tw-indigo-500: #6366f1;
+  --tw-indigo-600: #4f46e5;
+  --tw-indigo-700: #4338ca;
+  --tw-indigo-800: #3730a3;
+  --tw-indigo-900: #312e81;
+  --tw-indigo-950: #1e1b4b;
+}
+@keyframes auroraAnimation {
+  0% {
+    background-position:
+      0% 50%,
+      50% 50%;
+  }
+  50% {
+    background-position:
+      100% 50%,
+      50% 50%;
+  }
+  100% {
+    background-position:
+      0% 50%,
+      50% 50%;
+  }
+}
+.gradient-background {
+  animation: auroraAnimation 100s linear infinite;
+  position: absolute;
+  top: 0px;
+  right: 0px;
+  bottom: 0px;
+  left: 0px;
+  background-image: repeating-linear-gradient(
+      100deg,
+      var(--white) 0%,
+      var(--white) 7%,
+      var(--transparent) 10%,
+      var(--transparent) 12%,
+      var(--white) 16%
+    ),
+    repeating-linear-gradient(
+      100deg,
+      var(--blue-500) 10%,
+      var(--indigo-300) 15%,
+      var(--blue-300) 20%,
+      var(--violet-200) 25%,
+      var(--blue-400) 30%
+    );
+  mask-image: linear-gradient(to top, transparent, black);
+  background-size: 300%, 200%;
+  background-position:
+    50% 50%,
+    50% 50%;
+  filter: blur(10px) invert(1);
+  opacity: 0.3;
+  pointer-events: none;
+  will-change: transform;
+}
+
+.gradient-background::after {
+  content: '';
+  position: absolute;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  background-image: repeating-linear-gradient(
+      100deg,
+      var(--white) 0%,
+      var(--white) 7%,
+      var(--transparent) 12%,
+      var(--transparent) 20%,
+      var(--white) 30%
+    ),
+    repeating-linear-gradient(
+      100deg,
+      var(--blue-500) 10%,
+      var(--indigo-300) 15%,
+      var(--blue-300) 20%,
+      var(--violet-200) 25%,
+      var(--blue-400) 30%
+    );
+  background-size: 200%, 100%;
+  background-attachment: fixed;
+  mix-blend-mode: difference;
+}
+/* End gradient header */
+section {
+  padding: 0 2rem;
+}
+.font-lexend {
+  font-family: 'Lexend', sans-serif;
+}
+/* Grid style */
+
+.grid-stack-item {
+  border-radius: 8px;
+  cursor: pointer;
+}
+.grid-stack-item-content {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  background-color: white;
+  border-radius: 8px;
+  text-align: center;
+}
+
+/* End grid style */
+.card {
+  background: none;
+}
+.grid-stack-item-removing {
+  opacity: 0.8;
+  filter: blur(5px);
+}
+
+@media all and (max-width: 575px) {
+  #hero {
+    margin-top: 32px;
+  }
+}
diff --git a/src/styles/highlight.css b/src/styles/highlight.css
new file mode 100644
index 000000000..4d5b25bc6
--- /dev/null
+++ b/src/styles/highlight.css
@@ -0,0 +1,78 @@
+/* Highlight.JS Custom theme */
+
+.hljs {
+  display: block;
+  overflow-x: auto;
+  padding: 0.5em;
+  color: #767c85;
+  background: #282c34;
+}
+
+.hljs-comment,
+.hljs-quote {
+  color: #5c6370;
+  font-style: italic;
+}
+
+.hljs-doctag,
+.hljs-keyword,
+.hljs-formula {
+  color: #b03fd3;
+}
+
+.hljs-section,
+.hljs-name,
+.hljs-selector-tag,
+.hljs-deletion,
+.hljs-subst {
+  color: #e06c75;
+}
+
+.hljs-literal {
+  color: #56b6c2;
+}
+
+.hljs-string,
+.hljs-regexp,
+.hljs-addition,
+.hljs-attribute,
+.hljs-meta-string {
+  color: #5f9f31;
+}
+
+.hljs-built_in,
+.hljs-class .hljs-title {
+  color: #cb9e4b;
+}
+
+.hljs-attr,
+.hljs-variable,
+.hljs-template-variable,
+.hljs-type,
+.hljs-selector-class,
+.hljs-selector-attr,
+.hljs-selector-pseudo,
+.hljs-number {
+  color: #b87c43;
+}
+
+.hljs-symbol,
+.hljs-bullet,
+.hljs-link,
+.hljs-meta,
+.hljs-selector-id,
+.hljs-title {
+  color: #389aea;
+}
+
+.hljs-emphasis {
+  font-style: italic;
+}
+
+.hljs-strong {
+  font-weight: bold;
+}
+
+.hljs-link {
+  text-decoration: underline;
+}
diff --git a/tailwind.config.js b/tailwind.config.js
new file mode 100644
index 000000000..4754414f5
--- /dev/null
+++ b/tailwind.config.js
@@ -0,0 +1,6 @@
+/** @type {import('tailwindcss').Config} */
+module.exports = {
+  theme: {
+    
+  },
+}
diff --git a/yarn-error.log b/yarn-error.log
new file mode 100644
index 000000000..8d1bc605a
--- /dev/null
+++ b/yarn-error.log
@@ -0,0 +1,7018 @@
+Arguments: 
+  C:\Program Files\nodejs\node.exe C:\Program Files (x86)\Yarn\bin\yarn.js
+
+PATH: 
+  C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\WINDOWS\System32\OpenSSH\;C:\ProgramData\chocolatey\bin;C:\Program Files\PostgreSQL\12\bin;C:\bin;C:\bin\cygwin\bin;C:\bin\apache-maven-3.1.1\bin;C:\Program Files (x86)\GtkSharp\2.12\bin;C:\Program Files\PostgreSQL\10\bin;C:\Program Files\Java\jdk1.8.0_73\bin;C:\bin\gradle-6.2.1\bin;C:\Users\adumesny\AppData\Roaming\nvm;C:\Program Files\nodejs;C:\Program Files\Git\cmd;C:\Program Files (x86)\Yarn\bin\;C:\Program Files\TortoiseGit\bin;C:\Users\adumesny\AppData\Local\Microsoft\WindowsApps;C:\Users\adumesny\AppData\Local\GitHubDesktop\bin;C:\Users\adumesny\AppData\Roaming\nvm;C:\Program Files\nodejs;C:\Program Files (x86)\GitHub CLI\;C:\Users\adumesny\AppData\Local\Programs\Microsoft VS Code\bin;C:\Users\adumesny\AppData\Local\Microsoft\WindowsApps;C:\Users\adumesny\AppData\Local\Yarn\bin
+
+Yarn version: 
+  1.22.15
+
+Node version: 
+  14.15.4
+
+Platform: 
+  win32 x64
+
+Trace: 
+  Error: EPERM: operation not permitted, open 'C:\depot\gridstack.js\node_modules\.bin\karma.cmd'
+
+npm manifest: 
+  {
+    "name": "gridstack",
+    "version": "5.0.0-dev",
+    "description": "TypeScript/JS lib for dashboard layout and creation, no external dependencies, with many wrappers (React, Angular, Vue, Ember, knockout...)",
+    "main": "./dist/gridstack.js",
+    "types": "./dist/gridstack.d.ts",
+    "repository": {
+      "type": "git",
+      "url": "git+https://github.com/gridstack/gridstack.js.git"
+    },
+    "funding": [
+      {
+        "type": "paypal",
+        "url": "https://www.paypal.me/alaind831"
+      },
+      {
+        "type": "venmo",
+        "url": "https://www.venmo.com/adumesny"
+      }
+    ],
+    "scripts": {
+      "build": "yarn --no-progress && rm -rf dist/* && grunt && yarn build:es6 && yarn build:es5 && yarn doc",
+      "build:es6": "webpack && tsc --stripInternal",
+      "build:es5": "webpack --config es5/webpack.config.js && tsc --stripInternal --project es5/tsconfig.json",
+      "w": "rm -rf dist/* && grunt && webpack",
+      "t": "rm -rf dist/* && grunt && tsc --stripInternal",
+      "doc": "doctoc ./README.md && doctoc ./doc/README.md && doctoc ./doc/CHANGES.md",
+      "test": "yarn lint && karma start karma.conf.js",
+      "lint": "tsc --noEmit && eslint src/*.ts",
+      "reset": "rm -rf dist node_modules",
+      "prepublishOnly": "yarn build"
+    },
+    "keywords": [
+      "Typescript",
+      "gridstack.js",
+      "grid",
+      "gridster",
+      "layout",
+      "responsive",
+      "dashboard",
+      "resize",
+      "drag&drop",
+      "widgets",
+      "Angular",
+      "React",
+      "Vue",
+      "JavaScript"
+    ],
+    "author": "Pavel Reznikov <pashka.reznikov@gmail.com>",
+    "contributors": [
+      "Dylan Weiss <dylan.weiss@gmail.com> (https://dylandreams.com)",
+      "Alain Dumesny <alaind831+github@gmail.com> (https://github.com/adumesny)"
+    ],
+    "license": "see GridStack root license",
+    "bugs": {
+      "url": "https://github.com/gridstack/gridstack.js/issues"
+    },
+    "homepage": "http://gridstack.github.io/gridstack.js/",
+    "devDependencies": {
+      "@types/jasmine": "^3.5.9",
+      "@types/jquery": "^3.5.14",
+      "@types/jqueryui": "^1.12.16",
+      "@typescript-eslint/eslint-plugin": "^4.6.0",
+      "@typescript-eslint/parser": "^4.6.0",
+      "connect": "^3.7.0",
+      "core-js": "^3.6.4",
+      "coveralls": "^3.0.9",
+      "doctoc": "^1.4.0",
+      "eslint": "^7.14",
+      "grunt": "^1.0.4",
+      "grunt-cli": "^1.3.2",
+      "grunt-contrib-connect": "^3.0.0",
+      "grunt-contrib-copy": "^1.0.0",
+      "grunt-contrib-cssmin": "^3.0.0",
+      "grunt-contrib-uglify": "^5.0.0",
+      "grunt-contrib-watch": "^1.1.0",
+      "grunt-eslint": "^23.0.0",
+      "grunt-protractor-runner": "^5.0.0",
+      "grunt-protractor-webdriver": "^0.2.5",
+      "grunt-sass": "3.1.0",
+      "jasmine-core": "^3.5.0",
+      "karma": "^6",
+      "karma-chrome-launcher": "^3.1.0",
+      "karma-cli": "^2.0.0",
+      "karma-jasmine": "^4.0.1",
+      "karma-typescript": "4.1.1",
+      "protractor": "^7.0.0",
+      "puppeteer": "^5.4.1",
+      "sass": "^1.42.1",
+      "serve-static": "^1.14.1",
+      "ts-loader": "^8.0.7",
+      "typescript": "^3.7",
+      "webpack": "^5.3.2",
+      "webpack-cli": "^4.6.0"
+    }
+  }
+
+yarn manifest: 
+  No manifest
+
+Lockfile: 
+  # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+  # yarn lockfile v1
+  
+  
+  "@babel/code-frame@7.12.11":
+    version "7.12.11"
+    resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f"
+    integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==
+    dependencies:
+      "@babel/highlight" "^7.10.4"
+  
+  "@babel/helper-validator-identifier@^7.12.11":
+    version "7.12.11"
+    resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz#c9a1f021917dcb5ccf0d4e453e399022981fc9ed"
+    integrity sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==
+  
+  "@babel/highlight@^7.10.4":
+    version "7.13.10"
+    resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.13.10.tgz#a8b2a66148f5b27d666b15d81774347a731d52d1"
+    integrity sha512-5aPpe5XQPzflQrFwL1/QoeHkP2MsA4JCntcXHRhEsdsfPVkvPi2w7Qix4iV7t5S/oC9OodGrggd8aco1g3SZFg==
+    dependencies:
+      "@babel/helper-validator-identifier" "^7.12.11"
+      chalk "^2.0.0"
+      js-tokens "^4.0.0"
+  
+  "@discoveryjs/json-ext@^0.5.0":
+    version "0.5.2"
+    resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.2.tgz#8f03a22a04de437254e8ce8cc84ba39689288752"
+    integrity sha512-HyYEUDeIj5rRQU2Hk5HTB2uHsbRQpF70nvMhVzi+VJR0X+xNEhjPui4/kBf3VeH/wqD28PT4sVOm8qqLjBrSZg==
+  
+  "@eslint/eslintrc@^0.4.0":
+    version "0.4.0"
+    resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.0.tgz#99cc0a0584d72f1df38b900fb062ba995f395547"
+    integrity sha512-2ZPCc+uNbjV5ERJr+aKSPRwZgKd2z11x0EgLvb1PURmUrn9QNRXFqje0Ldq454PfAVyaJYyrDvvIKSFP4NnBog==
+    dependencies:
+      ajv "^6.12.4"
+      debug "^4.1.1"
+      espree "^7.3.0"
+      globals "^12.1.0"
+      ignore "^4.0.6"
+      import-fresh "^3.2.1"
+      js-yaml "^3.13.1"
+      minimatch "^3.0.4"
+      strip-json-comments "^3.1.1"
+  
+  "@nodelib/fs.scandir@2.1.4":
+    version "2.1.4"
+    resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz#d4b3549a5db5de2683e0c1071ab4f140904bbf69"
+    integrity sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==
+    dependencies:
+      "@nodelib/fs.stat" "2.0.4"
+      run-parallel "^1.1.9"
+  
+  "@nodelib/fs.stat@2.0.4", "@nodelib/fs.stat@^2.0.2":
+    version "2.0.4"
+    resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz#a3f2dd61bab43b8db8fa108a121cfffe4c676655"
+    integrity sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==
+  
+  "@nodelib/fs.walk@^1.2.3":
+    version "1.2.6"
+    resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz#cce9396b30aa5afe9e3756608f5831adcb53d063"
+    integrity sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==
+    dependencies:
+      "@nodelib/fs.scandir" "2.1.4"
+      fastq "^1.6.0"
+  
+  "@socket.io/base64-arraybuffer@~1.0.2":
+    version "1.0.2"
+    resolved "https://registry.yarnpkg.com/@socket.io/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz#568d9beae00b0d835f4f8c53fd55714986492e61"
+    integrity sha512-dOlCBKnDw4iShaIsH/bxujKTM18+2TOAsYz+KSc11Am38H4q5Xw8Bbz97ZYdrVNM+um3p7w86Bvvmcn9q+5+eQ==
+  
+  "@textlint/ast-node-types@^4.0.3":
+    version "4.4.2"
+    resolved "https://registry.yarnpkg.com/@textlint/ast-node-types/-/ast-node-types-4.4.2.tgz#d3fda5c9086baba04bc75440039ccf18415c8446"
+    integrity sha512-m5brKbI7UY/Q8sbIZ7z1KB8ls04nRILshz5fPQ4EZ04jL19qrrUHJR8A6nK3vJ/GelkDWl4I0VDYSAjLEFQV8g==
+  
+  "@textlint/markdown-to-ast@~6.0.9":
+    version "6.0.9"
+    resolved "https://registry.yarnpkg.com/@textlint/markdown-to-ast/-/markdown-to-ast-6.0.9.tgz#e7c89e5ad15d17dcd8e5a62758358936827658fa"
+    integrity sha512-hfAWBvTeUGh5t5kTn2U3uP3qOSM1BSrxzl1jF3nn0ywfZXpRBZr5yRjXnl4DzIYawCtZOshmRi/tI3/x4TE1jQ==
+    dependencies:
+      "@textlint/ast-node-types" "^4.0.3"
+      debug "^2.1.3"
+      remark-frontmatter "^1.2.0"
+      remark-parse "^5.0.0"
+      structured-source "^3.0.2"
+      traverse "^0.6.6"
+      unified "^6.1.6"
+  
+  "@types/component-emitter@^1.2.10":
+    version "1.2.11"
+    resolved "https://registry.yarnpkg.com/@types/component-emitter/-/component-emitter-1.2.11.tgz#50d47d42b347253817a39709fef03ce66a108506"
+    integrity sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ==
+  
+  "@types/cookie@^0.4.1":
+    version "0.4.1"
+    resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.4.1.tgz#bfd02c1f2224567676c1545199f87c3a861d878d"
+    integrity sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==
+  
+  "@types/cors@^2.8.12":
+    version "2.8.12"
+    resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.12.tgz#6b2c510a7ad7039e98e7b8d3d6598f4359e5c080"
+    integrity sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==
+  
+  "@types/eslint-scope@^3.7.0":
+    version "3.7.0"
+    resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.0.tgz#4792816e31119ebd506902a482caec4951fabd86"
+    integrity sha512-O/ql2+rrCUe2W2rs7wMR+GqPRcgB6UiqN5RhrR5xruFlY7l9YLMn0ZkDzjoHLeiFkR8MCQZVudUuuvQ2BLC9Qw==
+    dependencies:
+      "@types/eslint" "*"
+      "@types/estree" "*"
+  
+  "@types/eslint@*":
+    version "7.2.9"
+    resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-7.2.9.tgz#5d26eadbb6d04a225967176399a18eff622da982"
+    integrity sha512-SdAAXZNvWfhtf3X3y1cbbCZhP3xyPh7mfTvzV6CgfWc/ZhiHpyr9bVroe2/RCHIf7gczaNcprhaBLsx0CCJHQA==
+    dependencies:
+      "@types/estree" "*"
+      "@types/json-schema" "*"
+  
+  "@types/estree@*":
+    version "0.0.47"
+    resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.47.tgz#d7a51db20f0650efec24cd04994f523d93172ed4"
+    integrity sha512-c5ciR06jK8u9BstrmJyO97m+klJrrhCf9u3rLu3DEAJBirxRqSCvDQoYKmxuYwQI5SZChAWu+tq9oVlGRuzPAg==
+  
+  "@types/estree@^0.0.46":
+    version "0.0.46"
+    resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.46.tgz#0fb6bfbbeabd7a30880504993369c4bf1deab1fe"
+    integrity sha512-laIjwTQaD+5DukBZaygQ79K1Z0jb1bPEMRrkXSLjtCcZm+abyp5YbrqpSLzD42FwWW6gK/aS4NYpJ804nG2brg==
+  
+  "@types/jasmine@^3.5.9":
+    version "3.6.9"
+    resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-3.6.9.tgz#8785870f87839b7d91b45d7b226380f28dee5d9f"
+    integrity sha512-B53NIwMj/AO0O+xfSWLYmKB0Mo6TYxfv2Mk8/c1T2w/e38t55iaPR6p7pHXTTtqfTmevPK3i8T1YweYFTZlxDw==
+  
+  "@types/jquery@*", "@types/jquery@^3.5.1":
+    version "3.5.5"
+    resolved "https://registry.yarnpkg.com/@types/jquery/-/jquery-3.5.5.tgz#2c63f47c9c8d96693d272f5453602afd8338c903"
+    integrity sha512-6RXU9Xzpc6vxNrS6FPPapN1SxSHgQ336WC6Jj/N8q30OiaBZ00l1GBgeP7usjVZPivSkGUfL1z/WW6TX989M+w==
+    dependencies:
+      "@types/sizzle" "*"
+  
+  "@types/jqueryui@^1.12.13":
+    version "1.12.15"
+    resolved "https://registry.yarnpkg.com/@types/jqueryui/-/jqueryui-1.12.15.tgz#401732371c6fcbace711b609590b9e343f8f6bab"
+    integrity sha512-993YPaPj06yrUB1GOLZukmryIbA+blkrUzF+TZfP0BkLFnz+JA6H1pde4FtxYpDilgt9o/iPYEpN2KT0MMTNfg==
+    dependencies:
+      "@types/jquery" "*"
+  
+  "@types/json-schema@*", "@types/json-schema@^7.0.3", "@types/json-schema@^7.0.6":
+    version "7.0.7"
+    resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.7.tgz#98a993516c859eb0d5c4c8f098317a9ea68db9ad"
+    integrity sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==
+  
+  "@types/node@*":
+    version "14.14.37"
+    resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.37.tgz#a3dd8da4eb84a996c36e331df98d82abd76b516e"
+    integrity sha512-XYmBiy+ohOR4Lh5jE379fV2IU+6Jn4g5qASinhitfyO71b/sCo6MKsMLF5tc7Zf2CE8hViVQyYSobJNke8OvUw==
+  
+  "@types/node@>=10.0.0":
+    version "17.0.17"
+    resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.17.tgz#a8ddf6e0c2341718d74ee3dc413a13a042c45a0c"
+    integrity sha512-e8PUNQy1HgJGV3iU/Bp2+D/DXh3PYeyli8LgIwsQcs1Ar1LoaWHSIT6Rw+H2rNJmiq6SNWiDytfx8+gYj7wDHw==
+  
+  "@types/q@^0.0.32":
+    version "0.0.32"
+    resolved "https://registry.yarnpkg.com/@types/q/-/q-0.0.32.tgz#bd284e57c84f1325da702babfc82a5328190c0c5"
+    integrity sha1-vShOV8hPEyXacCur/IKlMoGQwMU=
+  
+  "@types/selenium-webdriver@^3.0.0":
+    version "3.0.17"
+    resolved "https://registry.yarnpkg.com/@types/selenium-webdriver/-/selenium-webdriver-3.0.17.tgz#50bea0c3c2acc31c959c5b1e747798b3b3d06d4b"
+    integrity sha512-tGomyEuzSC1H28y2zlW6XPCaDaXFaD6soTdb4GNdmte2qfHtrKqhy0ZFs4r/1hpazCfEZqeTSRLvSasmEx89uw==
+  
+  "@types/sizzle@*":
+    version "2.3.2"
+    resolved "https://registry.yarnpkg.com/@types/sizzle/-/sizzle-2.3.2.tgz#a811b8c18e2babab7d542b3365887ae2e4d9de47"
+    integrity sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg==
+  
+  "@types/yauzl@^2.9.1":
+    version "2.9.1"
+    resolved "https://registry.yarnpkg.com/@types/yauzl/-/yauzl-2.9.1.tgz#d10f69f9f522eef3cf98e30afb684a1e1ec923af"
+    integrity sha512-A1b8SU4D10uoPjwb0lnHmmu8wZhR9d+9o2PKBQT2jU5YPTKsxac6M2qGAdY7VcL+dHHhARVUDmeg0rOrcd9EjA==
+    dependencies:
+      "@types/node" "*"
+  
+  "@typescript-eslint/eslint-plugin@^4.6.0":
+    version "4.21.0"
+    resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.21.0.tgz#3fce2bfa76d95c00ac4f33dff369cb593aab8878"
+    integrity sha512-FPUyCPKZbVGexmbCFI3EQHzCZdy2/5f+jv6k2EDljGdXSRc0cKvbndd2nHZkSLqCNOPk0jB6lGzwIkglXcYVsQ==
+    dependencies:
+      "@typescript-eslint/experimental-utils" "4.21.0"
+      "@typescript-eslint/scope-manager" "4.21.0"
+      debug "^4.1.1"
+      functional-red-black-tree "^1.0.1"
+      lodash "^4.17.15"
+      regexpp "^3.0.0"
+      semver "^7.3.2"
+      tsutils "^3.17.1"
+  
+  "@typescript-eslint/experimental-utils@4.21.0":
+    version "4.21.0"
+    resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.21.0.tgz#0b0bb7c15d379140a660c003bdbafa71ae9134b6"
+    integrity sha512-cEbgosW/tUFvKmkg3cU7LBoZhvUs+ZPVM9alb25XvR0dal4qHL3SiUqHNrzoWSxaXA9gsifrYrS1xdDV6w/gIA==
+    dependencies:
+      "@types/json-schema" "^7.0.3"
+      "@typescript-eslint/scope-manager" "4.21.0"
+      "@typescript-eslint/types" "4.21.0"
+      "@typescript-eslint/typescript-estree" "4.21.0"
+      eslint-scope "^5.0.0"
+      eslint-utils "^2.0.0"
+  
+  "@typescript-eslint/parser@^4.6.0":
+    version "4.21.0"
+    resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.21.0.tgz#a227fc2af4001668c3e3f7415d4feee5093894c1"
+    integrity sha512-eyNf7QmE5O/l1smaQgN0Lj2M/1jOuNg2NrBm1dqqQN0sVngTLyw8tdCbih96ixlhbF1oINoN8fDCyEH9SjLeIA==
+    dependencies:
+      "@typescript-eslint/scope-manager" "4.21.0"
+      "@typescript-eslint/types" "4.21.0"
+      "@typescript-eslint/typescript-estree" "4.21.0"
+      debug "^4.1.1"
+  
+  "@typescript-eslint/scope-manager@4.21.0":
+    version "4.21.0"
+    resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.21.0.tgz#c81b661c4b8af1ec0c010d847a8f9ab76ab95b4d"
+    integrity sha512-kfOjF0w1Ix7+a5T1knOw00f7uAP9Gx44+OEsNQi0PvvTPLYeXJlsCJ4tYnDj5PQEYfpcgOH5yBlw7K+UEI9Agw==
+    dependencies:
+      "@typescript-eslint/types" "4.21.0"
+      "@typescript-eslint/visitor-keys" "4.21.0"
+  
+  "@typescript-eslint/types@4.21.0":
+    version "4.21.0"
+    resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.21.0.tgz#abdc3463bda5d31156984fa5bc316789c960edef"
+    integrity sha512-+OQaupjGVVc8iXbt6M1oZMwyKQNehAfLYJJ3SdvnofK2qcjfor9pEM62rVjBknhowTkh+2HF+/KdRAc/wGBN2w==
+  
+  "@typescript-eslint/typescript-estree@4.21.0":
+    version "4.21.0"
+    resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.21.0.tgz#3817bd91857beeaeff90f69f1f112ea58d350b0a"
+    integrity sha512-ZD3M7yLaVGVYLw4nkkoGKumb7Rog7QID9YOWobFDMQKNl+vPxqVIW/uDk+MDeGc+OHcoG2nJ2HphwiPNajKw3w==
+    dependencies:
+      "@typescript-eslint/types" "4.21.0"
+      "@typescript-eslint/visitor-keys" "4.21.0"
+      debug "^4.1.1"
+      globby "^11.0.1"
+      is-glob "^4.0.1"
+      semver "^7.3.2"
+      tsutils "^3.17.1"
+  
+  "@typescript-eslint/visitor-keys@4.21.0":
+    version "4.21.0"
+    resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.21.0.tgz#990a9acdc124331f5863c2cf21c88ba65233cd8d"
+    integrity sha512-dH22dROWGi5Z6p+Igc8bLVLmwy7vEe8r+8c+raPQU0LxgogPUrRAtRGtvBWmlr9waTu3n+QLt/qrS/hWzk1x5w==
+    dependencies:
+      "@typescript-eslint/types" "4.21.0"
+      eslint-visitor-keys "^2.0.0"
+  
+  "@webassemblyjs/ast@1.11.0":
+    version "1.11.0"
+    resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.0.tgz#a5aa679efdc9e51707a4207139da57920555961f"
+    integrity sha512-kX2W49LWsbthrmIRMbQZuQDhGtjyqXfEmmHyEi4XWnSZtPmxY0+3anPIzsnRb45VH/J55zlOfWvZuY47aJZTJg==
+    dependencies:
+      "@webassemblyjs/helper-numbers" "1.11.0"
+      "@webassemblyjs/helper-wasm-bytecode" "1.11.0"
+  
+  "@webassemblyjs/floating-point-hex-parser@1.11.0":
+    version "1.11.0"
+    resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.0.tgz#34d62052f453cd43101d72eab4966a022587947c"
+    integrity sha512-Q/aVYs/VnPDVYvsCBL/gSgwmfjeCb4LW8+TMrO3cSzJImgv8lxxEPM2JA5jMrivE7LSz3V+PFqtMbls3m1exDA==
+  
+  "@webassemblyjs/helper-api-error@1.11.0":
+    version "1.11.0"
+    resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.0.tgz#aaea8fb3b923f4aaa9b512ff541b013ffb68d2d4"
+    integrity sha512-baT/va95eXiXb2QflSx95QGT5ClzWpGaa8L7JnJbgzoYeaA27FCvuBXU758l+KXWRndEmUXjP0Q5fibhavIn8w==
+  
+  "@webassemblyjs/helper-buffer@1.11.0":
+    version "1.11.0"
+    resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.0.tgz#d026c25d175e388a7dbda9694e91e743cbe9b642"
+    integrity sha512-u9HPBEl4DS+vA8qLQdEQ6N/eJQ7gT7aNvMIo8AAWvAl/xMrcOSiI2M0MAnMCy3jIFke7bEee/JwdX1nUpCtdyA==
+  
+  "@webassemblyjs/helper-numbers@1.11.0":
+    version "1.11.0"
+    resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.0.tgz#7ab04172d54e312cc6ea4286d7d9fa27c88cd4f9"
+    integrity sha512-DhRQKelIj01s5IgdsOJMKLppI+4zpmcMQ3XboFPLwCpSNH6Hqo1ritgHgD0nqHeSYqofA6aBN/NmXuGjM1jEfQ==
+    dependencies:
+      "@webassemblyjs/floating-point-hex-parser" "1.11.0"
+      "@webassemblyjs/helper-api-error" "1.11.0"
+      "@xtuc/long" "4.2.2"
+  
+  "@webassemblyjs/helper-wasm-bytecode@1.11.0":
+    version "1.11.0"
+    resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.0.tgz#85fdcda4129902fe86f81abf7e7236953ec5a4e1"
+    integrity sha512-MbmhvxXExm542tWREgSFnOVo07fDpsBJg3sIl6fSp9xuu75eGz5lz31q7wTLffwL3Za7XNRCMZy210+tnsUSEA==
+  
+  "@webassemblyjs/helper-wasm-section@1.11.0":
+    version "1.11.0"
+    resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.0.tgz#9ce2cc89300262509c801b4af113d1ca25c1a75b"
+    integrity sha512-3Eb88hcbfY/FCukrg6i3EH8H2UsD7x8Vy47iVJrP967A9JGqgBVL9aH71SETPx1JrGsOUVLo0c7vMCN22ytJew==
+    dependencies:
+      "@webassemblyjs/ast" "1.11.0"
+      "@webassemblyjs/helper-buffer" "1.11.0"
+      "@webassemblyjs/helper-wasm-bytecode" "1.11.0"
+      "@webassemblyjs/wasm-gen" "1.11.0"
+  
+  "@webassemblyjs/ieee754@1.11.0":
+    version "1.11.0"
+    resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.0.tgz#46975d583f9828f5d094ac210e219441c4e6f5cf"
+    integrity sha512-KXzOqpcYQwAfeQ6WbF6HXo+0udBNmw0iXDmEK5sFlmQdmND+tr773Ti8/5T/M6Tl/413ArSJErATd8In3B+WBA==
+    dependencies:
+      "@xtuc/ieee754" "^1.2.0"
+  
+  "@webassemblyjs/leb128@1.11.0":
+    version "1.11.0"
+    resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.0.tgz#f7353de1df38aa201cba9fb88b43f41f75ff403b"
+    integrity sha512-aqbsHa1mSQAbeeNcl38un6qVY++hh8OpCOzxhixSYgbRfNWcxJNJQwe2rezK9XEcssJbbWIkblaJRwGMS9zp+g==
+    dependencies:
+      "@xtuc/long" "4.2.2"
+  
+  "@webassemblyjs/utf8@1.11.0":
+    version "1.11.0"
+    resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.0.tgz#86e48f959cf49e0e5091f069a709b862f5a2cadf"
+    integrity sha512-A/lclGxH6SpSLSyFowMzO/+aDEPU4hvEiooCMXQPcQFPPJaYcPQNKGOCLUySJsYJ4trbpr+Fs08n4jelkVTGVw==
+  
+  "@webassemblyjs/wasm-edit@1.11.0":
+    version "1.11.0"
+    resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.0.tgz#ee4a5c9f677046a210542ae63897094c2027cb78"
+    integrity sha512-JHQ0damXy0G6J9ucyKVXO2j08JVJ2ntkdJlq1UTiUrIgfGMmA7Ik5VdC/L8hBK46kVJgujkBIoMtT8yVr+yVOQ==
+    dependencies:
+      "@webassemblyjs/ast" "1.11.0"
+      "@webassemblyjs/helper-buffer" "1.11.0"
+      "@webassemblyjs/helper-wasm-bytecode" "1.11.0"
+      "@webassemblyjs/helper-wasm-section" "1.11.0"
+      "@webassemblyjs/wasm-gen" "1.11.0"
+      "@webassemblyjs/wasm-opt" "1.11.0"
+      "@webassemblyjs/wasm-parser" "1.11.0"
+      "@webassemblyjs/wast-printer" "1.11.0"
+  
+  "@webassemblyjs/wasm-gen@1.11.0":
+    version "1.11.0"
+    resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.0.tgz#3cdb35e70082d42a35166988dda64f24ceb97abe"
+    integrity sha512-BEUv1aj0WptCZ9kIS30th5ILASUnAPEvE3tVMTrItnZRT9tXCLW2LEXT8ezLw59rqPP9klh9LPmpU+WmRQmCPQ==
+    dependencies:
+      "@webassemblyjs/ast" "1.11.0"
+      "@webassemblyjs/helper-wasm-bytecode" "1.11.0"
+      "@webassemblyjs/ieee754" "1.11.0"
+      "@webassemblyjs/leb128" "1.11.0"
+      "@webassemblyjs/utf8" "1.11.0"
+  
+  "@webassemblyjs/wasm-opt@1.11.0":
+    version "1.11.0"
+    resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.0.tgz#1638ae188137f4bb031f568a413cd24d32f92978"
+    integrity sha512-tHUSP5F4ywyh3hZ0+fDQuWxKx3mJiPeFufg+9gwTpYp324mPCQgnuVKwzLTZVqj0duRDovnPaZqDwoyhIO8kYg==
+    dependencies:
+      "@webassemblyjs/ast" "1.11.0"
+      "@webassemblyjs/helper-buffer" "1.11.0"
+      "@webassemblyjs/wasm-gen" "1.11.0"
+      "@webassemblyjs/wasm-parser" "1.11.0"
+  
+  "@webassemblyjs/wasm-parser@1.11.0":
+    version "1.11.0"
+    resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.0.tgz#3e680b8830d5b13d1ec86cc42f38f3d4a7700754"
+    integrity sha512-6L285Sgu9gphrcpDXINvm0M9BskznnzJTE7gYkjDbxET28shDqp27wpruyx3C2S/dvEwiigBwLA1cz7lNUi0kw==
+    dependencies:
+      "@webassemblyjs/ast" "1.11.0"
+      "@webassemblyjs/helper-api-error" "1.11.0"
+      "@webassemblyjs/helper-wasm-bytecode" "1.11.0"
+      "@webassemblyjs/ieee754" "1.11.0"
+      "@webassemblyjs/leb128" "1.11.0"
+      "@webassemblyjs/utf8" "1.11.0"
+  
+  "@webassemblyjs/wast-printer@1.11.0":
+    version "1.11.0"
+    resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.0.tgz#680d1f6a5365d6d401974a8e949e05474e1fab7e"
+    integrity sha512-Fg5OX46pRdTgB7rKIUojkh9vXaVN6sGYCnEiJN1GYkb0RPwShZXp6KTDqmoMdQPKhcroOXh3fEzmkWmCYaKYhQ==
+    dependencies:
+      "@webassemblyjs/ast" "1.11.0"
+      "@xtuc/long" "4.2.2"
+  
+  "@webpack-cli/configtest@^1.0.2":
+    version "1.0.2"
+    resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-1.0.2.tgz#2a20812bfb3a2ebb0b27ee26a52eeb3e3f000836"
+    integrity sha512-3OBzV2fBGZ5TBfdW50cha1lHDVf9vlvRXnjpVbJBa20pSZQaSkMJZiwA8V2vD9ogyeXn8nU5s5A6mHyf5jhMzA==
+  
+  "@webpack-cli/info@^1.2.3":
+    version "1.2.3"
+    resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-1.2.3.tgz#ef819d10ace2976b6d134c7c823a3e79ee31a92c"
+    integrity sha512-lLek3/T7u40lTqzCGpC6CAbY6+vXhdhmwFRxZLMnRm6/sIF/7qMpT8MocXCRQfz0JAh63wpbXLMnsQ5162WS7Q==
+    dependencies:
+      envinfo "^7.7.3"
+  
+  "@webpack-cli/serve@^1.3.1":
+    version "1.3.1"
+    resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-1.3.1.tgz#911d1b3ff4a843304b9c3bacf67bb34672418441"
+    integrity sha512-0qXvpeYO6vaNoRBI52/UsbcaBydJCggoBBnIo/ovQQdn6fug0BgwsjorV1hVS7fMqGVTZGcVxv8334gjmbj5hw==
+  
+  "@xtuc/ieee754@^1.2.0":
+    version "1.2.0"
+    resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790"
+    integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==
+  
+  "@xtuc/long@4.2.2":
+    version "4.2.2"
+    resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d"
+    integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==
+  
+  abbrev@1:
+    version "1.1.1"
+    resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
+    integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==
+  
+  abbrev@1.0.x:
+    version "1.0.9"
+    resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135"
+    integrity sha1-kbR5JYinc4wl813W9jdSovh3YTU=
+  
+  accepts@~1.3.4:
+    version "1.3.7"
+    resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd"
+    integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==
+    dependencies:
+      mime-types "~2.1.24"
+      negotiator "0.6.2"
+  
+  acorn-jsx@^5.3.1:
+    version "5.3.1"
+    resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b"
+    integrity sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==
+  
+  acorn-walk@^6.1.1:
+    version "6.2.0"
+    resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.2.0.tgz#123cb8f3b84c2171f1f7fb252615b1c78a6b1a8c"
+    integrity sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==
+  
+  acorn@^6.0.5:
+    version "6.4.2"
+    resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6"
+    integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==
+  
+  acorn@^7.4.0:
+    version "7.4.1"
+    resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
+    integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
+  
+  acorn@^8.0.4:
+    version "8.1.0"
+    resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.1.0.tgz#52311fd7037ae119cbb134309e901aa46295b3fe"
+    integrity sha512-LWCF/Wn0nfHOmJ9rzQApGnxnvgfROzGilS8936rqN/lfcYkY9MYZzdMqN+2NJ4SlTc+m5HiSa+kNfDtI64dwUA==
+  
+  adm-zip@^0.4.9:
+    version "0.4.16"
+    resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.16.tgz#cf4c508fdffab02c269cbc7f471a875f05570365"
+    integrity sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==
+  
+  agent-base@5:
+    version "5.1.1"
+    resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-5.1.1.tgz#e8fb3f242959db44d63be665db7a8e739537a32c"
+    integrity sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g==
+  
+  agent-base@^4.3.0:
+    version "4.3.0"
+    resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee"
+    integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==
+    dependencies:
+      es6-promisify "^5.0.0"
+  
+  ajv-keywords@^3.5.2:
+    version "3.5.2"
+    resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d"
+    integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==
+  
+  ajv@^6.10.0, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5:
+    version "6.12.6"
+    resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
+    integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
+    dependencies:
+      fast-deep-equal "^3.1.1"
+      fast-json-stable-stringify "^2.0.0"
+      json-schema-traverse "^0.4.1"
+      uri-js "^4.2.2"
+  
+  ajv@^8.0.1:
+    version "8.1.0"
+    resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.1.0.tgz#45d5d3d36c7cdd808930cc3e603cf6200dbeb736"
+    integrity sha512-B/Sk2Ix7A36fs/ZkuGLIR86EdjbgR6fsAcbx9lOP/QBSXujDNbVmIS/U4Itz5k8fPFDeVZl/zQ/gJW4Jrq6XjQ==
+    dependencies:
+      fast-deep-equal "^3.1.1"
+      json-schema-traverse "^1.0.0"
+      require-from-string "^2.0.2"
+      uri-js "^4.2.2"
+  
+  amdefine@>=0.0.4:
+    version "1.0.1"
+    resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5"
+    integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=
+  
+  anchor-markdown-header@^0.5.5:
+    version "0.5.7"
+    resolved "https://registry.yarnpkg.com/anchor-markdown-header/-/anchor-markdown-header-0.5.7.tgz#045063d76e6a1f9cd327a57a0126aa0fdec371a7"
+    integrity sha1-BFBj125qH5zTJ6V6ASaqD97Dcac=
+    dependencies:
+      emoji-regex "~6.1.0"
+  
+  ansi-colors@^1.0.1:
+    version "1.1.0"
+    resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-1.1.0.tgz#6374b4dd5d4718ff3ce27a671a3b1cad077132a9"
+    integrity sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==
+    dependencies:
+      ansi-wrap "^0.1.0"
+  
+  ansi-colors@^4.1.1:
+    version "4.1.1"
+    resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348"
+    integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==
+  
+  ansi-regex@^2.0.0:
+    version "2.1.1"
+    resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
+    integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8=
+  
+  ansi-regex@^3.0.0:
+    version "3.0.0"
+    resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
+    integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=
+  
+  ansi-regex@^5.0.0:
+    version "5.0.0"
+    resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75"
+    integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==
+  
+  ansi-styles@^2.2.1:
+    version "2.2.1"
+    resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
+    integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=
+  
+  ansi-styles@^3.2.1:
+    version "3.2.1"
+    resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
+    integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
+    dependencies:
+      color-convert "^1.9.0"
+  
+  ansi-styles@^4.0.0, ansi-styles@^4.1.0:
+    version "4.3.0"
+    resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
+    integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
+    dependencies:
+      color-convert "^2.0.1"
+  
+  ansi-wrap@^0.1.0:
+    version "0.1.0"
+    resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf"
+    integrity sha1-qCJQ3bABXponyoLoLqYDu/pF768=
+  
+  anymatch@~3.1.2:
+    version "3.1.2"
+    resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716"
+    integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==
+    dependencies:
+      normalize-path "^3.0.0"
+      picomatch "^2.0.4"
+  
+  argparse@^1.0.7:
+    version "1.0.10"
+    resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
+    integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==
+    dependencies:
+      sprintf-js "~1.0.2"
+  
+  arr-diff@^4.0.0:
+    version "4.0.0"
+    resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520"
+    integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=
+  
+  arr-flatten@^1.1.0:
+    version "1.1.0"
+    resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1"
+    integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==
+  
+  arr-union@^3.1.0:
+    version "3.1.0"
+    resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4"
+    integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=
+  
+  array-each@^1.0.1:
+    version "1.0.1"
+    resolved "https://registry.yarnpkg.com/array-each/-/array-each-1.0.1.tgz#a794af0c05ab1752846ee753a1f211a05ba0c44f"
+    integrity sha1-p5SvDAWrF1KEbudTofIRoFugxE8=
+  
+  array-filter@^1.0.0:
+    version "1.0.0"
+    resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-1.0.0.tgz#baf79e62e6ef4c2a4c0b831232daffec251f9d83"
+    integrity sha1-uveeYubvTCpMC4MSMtr/7CUfnYM=
+  
+  array-find-index@^1.0.1:
+    version "1.0.2"
+    resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1"
+    integrity sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=
+  
+  array-slice@^1.0.0:
+    version "1.1.0"
+    resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-1.1.0.tgz#e368ea15f89bc7069f7ffb89aec3a6c7d4ac22d4"
+    integrity sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==
+  
+  array-union@^1.0.1:
+    version "1.0.2"
+    resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39"
+    integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=
+    dependencies:
+      array-uniq "^1.0.1"
+  
+  array-union@^2.1.0:
+    version "2.1.0"
+    resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d"
+    integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==
+  
+  array-uniq@^1.0.1:
+    version "1.0.3"
+    resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6"
+    integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=
+  
+  array-unique@^0.3.2:
+    version "0.3.2"
+    resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428"
+    integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=
+  
+  arrify@^1.0.0:
+    version "1.0.1"
+    resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
+    integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=
+  
+  asn1.js@^5.2.0:
+    version "5.4.1"
+    resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07"
+    integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==
+    dependencies:
+      bn.js "^4.0.0"
+      inherits "^2.0.1"
+      minimalistic-assert "^1.0.0"
+      safer-buffer "^2.1.0"
+  
+  asn1@~0.2.3:
+    version "0.2.4"
+    resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136"
+    integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==
+    dependencies:
+      safer-buffer "~2.1.0"
+  
+  assert-plus@1.0.0, assert-plus@^1.0.0:
+    version "1.0.0"
+    resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
+    integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=
+  
+  assert@1.4.1:
+    version "1.4.1"
+    resolved "https://registry.yarnpkg.com/assert/-/assert-1.4.1.tgz#99912d591836b5a6f5b345c0f07eefc08fc65d91"
+    integrity sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=
+    dependencies:
+      util "0.10.3"
+  
+  assert@^2.0.0:
+    version "2.0.0"
+    resolved "https://registry.yarnpkg.com/assert/-/assert-2.0.0.tgz#95fc1c616d48713510680f2eaf2d10dd22e02d32"
+    integrity sha512-se5Cd+js9dXJnu6Ag2JFc00t+HmHOen+8Q+L7O9zI0PqQXr20uk2J0XQqMxZEeo5U50o8Nvmmx7dZrl+Ufr35A==
+    dependencies:
+      es6-object-assign "^1.1.0"
+      is-nan "^1.2.1"
+      object-is "^1.0.1"
+      util "^0.12.0"
+  
+  assign-symbols@^1.0.0:
+    version "1.0.0"
+    resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367"
+    integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=
+  
+  astral-regex@^2.0.0:
+    version "2.0.0"
+    resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31"
+    integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==
+  
+  async-limiter@~1.0.0:
+    version "1.0.1"
+    resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd"
+    integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==
+  
+  async@1.x, async@~1.5.2:
+    version "1.5.2"
+    resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
+    integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=
+  
+  async@^2.6.0, async@^2.6.2:
+    version "2.6.3"
+    resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff"
+    integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==
+    dependencies:
+      lodash "^4.17.14"
+  
+  async@^3.0.1, async@^3.2.0:
+    version "3.2.0"
+    resolved "https://registry.yarnpkg.com/async/-/async-3.2.0.tgz#b3a2685c5ebb641d3de02d161002c60fc9f85720"
+    integrity sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==
+  
+  asynckit@^0.4.0:
+    version "0.4.0"
+    resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
+    integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
+  
+  atob@^2.1.2:
+    version "2.1.2"
+    resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
+    integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
+  
+  available-typed-arrays@^1.0.2:
+    version "1.0.2"
+    resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.2.tgz#6b098ca9d8039079ee3f77f7b783c4480ba513f5"
+    integrity sha512-XWX3OX8Onv97LMk/ftVyBibpGwY5a8SmuxZPzeOxqmuEqUCOM9ZE+uIaD1VNJ5QnvU2UQusvmKbuM1FR8QWGfQ==
+    dependencies:
+      array-filter "^1.0.0"
+  
+  aws-sign2@~0.7.0:
+    version "0.7.0"
+    resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
+    integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=
+  
+  aws4@^1.8.0:
+    version "1.11.0"
+    resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59"
+    integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==
+  
+  bail@^1.0.0:
+    version "1.0.5"
+    resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.5.tgz#b6fa133404a392cbc1f8c4bf63f5953351e7a776"
+    integrity sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ==
+  
+  balanced-match@^1.0.0:
+    version "1.0.2"
+    resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
+    integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
+  
+  base64-js@^1.3.1:
+    version "1.5.1"
+    resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
+    integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
+  
+  base64id@2.0.0, base64id@~2.0.0:
+    version "2.0.0"
+    resolved "https://registry.yarnpkg.com/base64id/-/base64id-2.0.0.tgz#2770ac6bc47d312af97a8bf9a634342e0cd25cb6"
+    integrity sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==
+  
+  base@^0.11.1:
+    version "0.11.2"
+    resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f"
+    integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==
+    dependencies:
+      cache-base "^1.0.1"
+      class-utils "^0.3.5"
+      component-emitter "^1.2.1"
+      define-property "^1.0.0"
+      isobject "^3.0.1"
+      mixin-deep "^1.2.0"
+      pascalcase "^0.1.1"
+  
+  basic-auth@~2.0.1:
+    version "2.0.1"
+    resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-2.0.1.tgz#b998279bf47ce38344b4f3cf916d4679bbf51e3a"
+    integrity sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==
+    dependencies:
+      safe-buffer "5.1.2"
+  
+  batch@0.6.1:
+    version "0.6.1"
+    resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16"
+    integrity sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=
+  
+  bcrypt-pbkdf@^1.0.0:
+    version "1.0.2"
+    resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e"
+    integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=
+    dependencies:
+      tweetnacl "^0.14.3"
+  
+  big.js@^5.2.2:
+    version "5.2.2"
+    resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328"
+    integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==
+  
+  binary-extensions@^2.0.0:
+    version "2.2.0"
+    resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
+    integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
+  
+  bl@^4.0.3:
+    version "4.1.0"
+    resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a"
+    integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==
+    dependencies:
+      buffer "^5.5.0"
+      inherits "^2.0.4"
+      readable-stream "^3.4.0"
+  
+  blocking-proxy@^1.0.0:
+    version "1.0.1"
+    resolved "https://registry.yarnpkg.com/blocking-proxy/-/blocking-proxy-1.0.1.tgz#81d6fd1fe13a4c0d6957df7f91b75e98dac40cb2"
+    integrity sha512-KE8NFMZr3mN2E0HcvCgRtX7DjhiIQrwle+nSVJVC/yqFb9+xznHl2ZcoBp2L9qzkI4t4cBFJ1efXF8Dwi132RA==
+    dependencies:
+      minimist "^1.2.0"
+  
+  bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9:
+    version "4.12.0"
+    resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88"
+    integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==
+  
+  bn.js@^5.0.0, bn.js@^5.1.1:
+    version "5.2.0"
+    resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.0.tgz#358860674396c6997771a9d051fcc1b57d4ae002"
+    integrity sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==
+  
+  body-parser@^1.19.0:
+    version "1.19.1"
+    resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.1.tgz#1499abbaa9274af3ecc9f6f10396c995943e31d4"
+    integrity sha512-8ljfQi5eBk8EJfECMrgqNGWPEY5jWP+1IzkzkGdFFEwFQZZyaZ21UqdaHktgiMlH0xLHqIFtE/u2OYE5dOtViA==
+    dependencies:
+      bytes "3.1.1"
+      content-type "~1.0.4"
+      debug "2.6.9"
+      depd "~1.1.2"
+      http-errors "1.8.1"
+      iconv-lite "0.4.24"
+      on-finished "~2.3.0"
+      qs "6.9.6"
+      raw-body "2.4.2"
+      type-is "~1.6.18"
+  
+  body@^5.1.0:
+    version "5.1.0"
+    resolved "https://registry.yarnpkg.com/body/-/body-5.1.0.tgz#e4ba0ce410a46936323367609ecb4e6553125069"
+    integrity sha1-5LoM5BCkaTYyM2dgnstOZVMSUGk=
+    dependencies:
+      continuable-cache "^0.3.1"
+      error "^7.0.0"
+      raw-body "~1.1.0"
+      safe-json-parse "~1.0.1"
+  
+  boundary@^1.0.1:
+    version "1.0.1"
+    resolved "https://registry.yarnpkg.com/boundary/-/boundary-1.0.1.tgz#4d67dc2602c0cc16dd9bce7ebf87e948290f5812"
+    integrity sha1-TWfcJgLAzBbdm85+v4fpSCkPWBI=
+  
+  brace-expansion@^1.1.7:
+    version "1.1.11"
+    resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
+    integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
+    dependencies:
+      balanced-match "^1.0.0"
+      concat-map "0.0.1"
+  
+  braces@^2.3.1:
+    version "2.3.2"
+    resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729"
+    integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==
+    dependencies:
+      arr-flatten "^1.1.0"
+      array-unique "^0.3.2"
+      extend-shallow "^2.0.1"
+      fill-range "^4.0.0"
+      isobject "^3.0.1"
+      repeat-element "^1.1.2"
+      snapdragon "^0.8.1"
+      snapdragon-node "^2.0.1"
+      split-string "^3.0.2"
+      to-regex "^3.0.1"
+  
+  braces@^3.0.1, braces@^3.0.2, braces@~3.0.2:
+    version "3.0.2"
+    resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
+    integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
+    dependencies:
+      fill-range "^7.0.1"
+  
+  brorand@^1.0.1, brorand@^1.1.0:
+    version "1.1.0"
+    resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f"
+    integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=
+  
+  browser-resolve@^1.11.3:
+    version "1.11.3"
+    resolved "https://registry.yarnpkg.com/browser-resolve/-/browser-resolve-1.11.3.tgz#9b7cbb3d0f510e4cb86bdbd796124d28b5890af6"
+    integrity sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==
+    dependencies:
+      resolve "1.1.7"
+  
+  browserify-aes@^1.0.0, browserify-aes@^1.0.4:
+    version "1.2.0"
+    resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48"
+    integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==
+    dependencies:
+      buffer-xor "^1.0.3"
+      cipher-base "^1.0.0"
+      create-hash "^1.1.0"
+      evp_bytestokey "^1.0.3"
+      inherits "^2.0.1"
+      safe-buffer "^5.0.1"
+  
+  browserify-cipher@^1.0.0:
+    version "1.0.1"
+    resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0"
+    integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==
+    dependencies:
+      browserify-aes "^1.0.4"
+      browserify-des "^1.0.0"
+      evp_bytestokey "^1.0.0"
+  
+  browserify-des@^1.0.0:
+    version "1.0.2"
+    resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c"
+    integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==
+    dependencies:
+      cipher-base "^1.0.1"
+      des.js "^1.0.0"
+      inherits "^2.0.1"
+      safe-buffer "^5.1.2"
+  
+  browserify-rsa@^4.0.0, browserify-rsa@^4.0.1:
+    version "4.1.0"
+    resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.1.0.tgz#b2fd06b5b75ae297f7ce2dc651f918f5be158c8d"
+    integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==
+    dependencies:
+      bn.js "^5.0.0"
+      randombytes "^2.0.1"
+  
+  browserify-sign@^4.0.0:
+    version "4.2.1"
+    resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.1.tgz#eaf4add46dd54be3bb3b36c0cf15abbeba7956c3"
+    integrity sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==
+    dependencies:
+      bn.js "^5.1.1"
+      browserify-rsa "^4.0.1"
+      create-hash "^1.2.0"
+      create-hmac "^1.1.7"
+      elliptic "^6.5.3"
+      inherits "^2.0.4"
+      parse-asn1 "^5.1.5"
+      readable-stream "^3.6.0"
+      safe-buffer "^5.2.0"
+  
+  browserify-zlib@^0.2.0:
+    version "0.2.0"
+    resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f"
+    integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==
+    dependencies:
+      pako "~1.0.5"
+  
+  browserslist@^4.14.5:
+    version "4.16.6"
+    resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.6.tgz#d7901277a5a88e554ed305b183ec9b0c08f66fa2"
+    integrity sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==
+    dependencies:
+      caniuse-lite "^1.0.30001219"
+      colorette "^1.2.2"
+      electron-to-chromium "^1.3.723"
+      escalade "^3.1.1"
+      node-releases "^1.1.71"
+  
+  browserstack@^1.5.1:
+    version "1.6.1"
+    resolved "https://registry.yarnpkg.com/browserstack/-/browserstack-1.6.1.tgz#e051f9733ec3b507659f395c7a4765a1b1e358b3"
+    integrity sha512-GxtFjpIaKdbAyzHfFDKixKO8IBT7wR3NjbzrGc78nNs/Ciys9wU3/nBtsqsWv5nDSrdI5tz0peKuzCPuNXNUiw==
+    dependencies:
+      https-proxy-agent "^2.2.1"
+  
+  buffer-crc32@~0.2.3:
+    version "0.2.13"
+    resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
+    integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=
+  
+  buffer-from@^1.0.0:
+    version "1.1.1"
+    resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
+    integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
+  
+  buffer-xor@^1.0.3:
+    version "1.0.3"
+    resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9"
+    integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=
+  
+  buffer@^5.2.1, buffer@^5.5.0:
+    version "5.7.1"
+    resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0"
+    integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==
+    dependencies:
+      base64-js "^1.3.1"
+      ieee754 "^1.1.13"
+  
+  builtin-status-codes@^3.0.0:
+    version "3.0.0"
+    resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
+    integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=
+  
+  bytes@1:
+    version "1.0.0"
+    resolved "https://registry.yarnpkg.com/bytes/-/bytes-1.0.0.tgz#3569ede8ba34315fab99c3e92cb04c7220de1fa8"
+    integrity sha1-NWnt6Lo0MV+rmcPpLLBMciDeH6g=
+  
+  bytes@3.1.1:
+    version "3.1.1"
+    resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.1.tgz#3f018291cb4cbad9accb6e6970bca9c8889e879a"
+    integrity sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg==
+  
+  cache-base@^1.0.1:
+    version "1.0.1"
+    resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2"
+    integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==
+    dependencies:
+      collection-visit "^1.0.0"
+      component-emitter "^1.2.1"
+      get-value "^2.0.6"
+      has-value "^1.0.0"
+      isobject "^3.0.1"
+      set-value "^2.0.0"
+      to-object-path "^0.3.0"
+      union-value "^1.0.0"
+      unset-value "^1.0.0"
+  
+  call-bind@^1.0.0, call-bind@^1.0.2:
+    version "1.0.2"
+    resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c"
+    integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==
+    dependencies:
+      function-bind "^1.1.1"
+      get-intrinsic "^1.0.2"
+  
+  callsites@^3.0.0:
+    version "3.1.0"
+    resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
+    integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
+  
+  camelcase-keys@^2.0.0:
+    version "2.1.0"
+    resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7"
+    integrity sha1-MIvur/3ygRkFHvodkyITyRuPkuc=
+    dependencies:
+      camelcase "^2.0.0"
+      map-obj "^1.0.0"
+  
+  camelcase@^2.0.0:
+    version "2.1.1"
+    resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f"
+    integrity sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=
+  
+  camelcase@^5.0.0:
+    version "5.3.1"
+    resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
+    integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
+  
+  caniuse-lite@^1.0.30001219:
+    version "1.0.30001230"
+    resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001230.tgz#8135c57459854b2240b57a4a6786044bdc5a9f71"
+    integrity sha512-5yBd5nWCBS+jWKTcHOzXwo5xzcj4ePE/yjtkZyUV1BTUmrBaA9MRGC+e7mxnqXSA90CmCA8L3eKLaSUkt099IQ==
+  
+  caseless@~0.12.0:
+    version "0.12.0"
+    resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
+    integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=
+  
+  chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3:
+    version "1.1.3"
+    resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
+    integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=
+    dependencies:
+      ansi-styles "^2.2.1"
+      escape-string-regexp "^1.0.2"
+      has-ansi "^2.0.0"
+      strip-ansi "^3.0.0"
+      supports-color "^2.0.0"
+  
+  chalk@^2.0.0, chalk@^2.4.1:
+    version "2.4.2"
+    resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
+    integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
+    dependencies:
+      ansi-styles "^3.2.1"
+      escape-string-regexp "^1.0.5"
+      supports-color "^5.3.0"
+  
+  chalk@^4.0.0, chalk@^4.1.0, chalk@~4.1.0:
+    version "4.1.0"
+    resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a"
+    integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==
+    dependencies:
+      ansi-styles "^4.1.0"
+      supports-color "^7.1.0"
+  
+  character-entities-legacy@^1.0.0:
+    version "1.1.4"
+    resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz#94bc1845dce70a5bb9d2ecc748725661293d8fc1"
+    integrity sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==
+  
+  character-entities@^1.0.0:
+    version "1.2.4"
+    resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-1.2.4.tgz#e12c3939b7eaf4e5b15e7ad4c5e28e1d48c5b16b"
+    integrity sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==
+  
+  character-reference-invalid@^1.0.0:
+    version "1.1.4"
+    resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz#083329cda0eae272ab3dbbf37e9a382c13af1560"
+    integrity sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==
+  
+  "chokidar@>=3.0.0 <4.0.0", chokidar@^3.5.1:
+    version "3.5.3"
+    resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd"
+    integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==
+    dependencies:
+      anymatch "~3.1.2"
+      braces "~3.0.2"
+      glob-parent "~5.1.2"
+      is-binary-path "~2.1.0"
+      is-glob "~4.0.1"
+      normalize-path "~3.0.0"
+      readdirp "~3.6.0"
+    optionalDependencies:
+      fsevents "~2.3.2"
+  
+  chownr@^1.1.1:
+    version "1.1.4"
+    resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b"
+    integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==
+  
+  chrome-trace-event@^1.0.2:
+    version "1.0.3"
+    resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac"
+    integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==
+  
+  cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3:
+    version "1.0.4"
+    resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de"
+    integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==
+    dependencies:
+      inherits "^2.0.1"
+      safe-buffer "^5.0.1"
+  
+  class-utils@^0.3.5:
+    version "0.3.6"
+    resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463"
+    integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==
+    dependencies:
+      arr-union "^3.1.0"
+      define-property "^0.2.5"
+      isobject "^3.0.0"
+      static-extend "^0.1.1"
+  
+  clean-css@~4.2.1:
+    version "4.2.3"
+    resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.3.tgz#507b5de7d97b48ee53d84adb0160ff6216380f78"
+    integrity sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA==
+    dependencies:
+      source-map "~0.6.0"
+  
+  cliui@^4.0.0:
+    version "4.1.0"
+    resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49"
+    integrity sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==
+    dependencies:
+      string-width "^2.1.1"
+      strip-ansi "^4.0.0"
+      wrap-ansi "^2.0.0"
+  
+  cliui@^6.0.0:
+    version "6.0.0"
+    resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1"
+    integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==
+    dependencies:
+      string-width "^4.2.0"
+      strip-ansi "^6.0.0"
+      wrap-ansi "^6.2.0"
+  
+  cliui@^7.0.2:
+    version "7.0.4"
+    resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f"
+    integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==
+    dependencies:
+      string-width "^4.2.0"
+      strip-ansi "^6.0.0"
+      wrap-ansi "^7.0.0"
+  
+  clone-deep@^4.0.1:
+    version "4.0.1"
+    resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387"
+    integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==
+    dependencies:
+      is-plain-object "^2.0.4"
+      kind-of "^6.0.2"
+      shallow-clone "^3.0.0"
+  
+  clone@^1.0.2:
+    version "1.0.4"
+    resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e"
+    integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4=
+  
+  code-point-at@^1.0.0:
+    version "1.1.0"
+    resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
+    integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=
+  
+  collapse-white-space@^1.0.2:
+    version "1.0.6"
+    resolved "https://registry.yarnpkg.com/collapse-white-space/-/collapse-white-space-1.0.6.tgz#e63629c0016665792060dbbeb79c42239d2c5287"
+    integrity sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ==
+  
+  collection-visit@^1.0.0:
+    version "1.0.0"
+    resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0"
+    integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=
+    dependencies:
+      map-visit "^1.0.0"
+      object-visit "^1.0.0"
+  
+  color-convert@^1.9.0:
+    version "1.9.3"
+    resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
+    integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
+    dependencies:
+      color-name "1.1.3"
+  
+  color-convert@^2.0.1:
+    version "2.0.1"
+    resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
+    integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
+    dependencies:
+      color-name "~1.1.4"
+  
+  color-name@1.1.3:
+    version "1.1.3"
+    resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
+    integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
+  
+  color-name@~1.1.4:
+    version "1.1.4"
+    resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
+    integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
+  
+  colorette@^1.2.1, colorette@^1.2.2:
+    version "1.2.2"
+    resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.2.tgz#cbcc79d5e99caea2dbf10eb3a26fd8b3e6acfa94"
+    integrity sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==
+  
+  colors@1.4.0:
+    version "1.4.0"
+    resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78"
+    integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==
+  
+  colors@~1.1.2:
+    version "1.1.2"
+    resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63"
+    integrity sha1-FopHAXVran9RoSzgyXv6KMCE7WM=
+  
+  combine-source-map@^0.8.0:
+    version "0.8.0"
+    resolved "https://registry.yarnpkg.com/combine-source-map/-/combine-source-map-0.8.0.tgz#a58d0df042c186fcf822a8e8015f5450d2d79a8b"
+    integrity sha1-pY0N8ELBhvz4IqjoAV9UUNLXmos=
+    dependencies:
+      convert-source-map "~1.1.0"
+      inline-source-map "~0.6.0"
+      lodash.memoize "~3.0.3"
+      source-map "~0.5.3"
+  
+  combined-stream@^1.0.6, combined-stream@~1.0.6:
+    version "1.0.8"
+    resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
+    integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
+    dependencies:
+      delayed-stream "~1.0.0"
+  
+  commander@^2.20.0:
+    version "2.20.3"
+    resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
+    integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
+  
+  commander@^7.0.0:
+    version "7.2.0"
+    resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7"
+    integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==
+  
+  component-emitter@^1.2.1, component-emitter@~1.3.0:
+    version "1.3.0"
+    resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0"
+    integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==
+  
+  concat-map@0.0.1:
+    version "0.0.1"
+    resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
+    integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
+  
+  connect-livereload@^0.6.1:
+    version "0.6.1"
+    resolved "https://registry.yarnpkg.com/connect-livereload/-/connect-livereload-0.6.1.tgz#1ac0c8bb9d9cfd5b28b629987a56a9239db9baaa"
+    integrity sha512-3R0kMOdL7CjJpU66fzAkCe6HNtd3AavCS4m+uW4KtJjrdGPT0SQEZieAYd+cm+lJoBznNQ4lqipYWkhBMgk00g==
+  
+  connect@^3.7.0:
+    version "3.7.0"
+    resolved "https://registry.yarnpkg.com/connect/-/connect-3.7.0.tgz#5d49348910caa5e07a01800b030d0c35f20484f8"
+    integrity sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==
+    dependencies:
+      debug "2.6.9"
+      finalhandler "1.1.2"
+      parseurl "~1.3.3"
+      utils-merge "1.0.1"
+  
+  console-browserify@^1.1.0:
+    version "1.2.0"
+    resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336"
+    integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==
+  
+  constants-browserify@^1.0.0:
+    version "1.0.0"
+    resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75"
+    integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=
+  
+  content-type@~1.0.4:
+    version "1.0.4"
+    resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
+    integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
+  
+  continuable-cache@^0.3.1:
+    version "0.3.1"
+    resolved "https://registry.yarnpkg.com/continuable-cache/-/continuable-cache-0.3.1.tgz#bd727a7faed77e71ff3985ac93351a912733ad0f"
+    integrity sha1-vXJ6f67XfnH/OYWskzUakSczrQ8=
+  
+  convert-source-map@^1.6.0:
+    version "1.7.0"
+    resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442"
+    integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==
+    dependencies:
+      safe-buffer "~5.1.1"
+  
+  convert-source-map@~1.1.0:
+    version "1.1.3"
+    resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.1.3.tgz#4829c877e9fe49b3161f3bf3673888e204699860"
+    integrity sha1-SCnId+n+SbMWHzvzZziI4gRpmGA=
+  
+  cookie@~0.4.1:
+    version "0.4.2"
+    resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432"
+    integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==
+  
+  copy-descriptor@^0.1.0:
+    version "0.1.1"
+    resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d"
+    integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=
+  
+  core-js@^3.6.4:
+    version "3.10.1"
+    resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.10.1.tgz#e683963978b6806dcc6c0a4a8bd4ab0bdaf3f21a"
+    integrity sha512-pwCxEXnj27XG47mu7SXAwhLP3L5CrlvCB91ANUkIz40P27kUcvNfSdvyZJ9CLHiVoKSp+TTChMQMSKQEH/IQxA==
+  
+  core-util-is@1.0.2, core-util-is@~1.0.0:
+    version "1.0.2"
+    resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
+    integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
+  
+  cors@~2.8.5:
+    version "2.8.5"
+    resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29"
+    integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==
+    dependencies:
+      object-assign "^4"
+      vary "^1"
+  
+  coveralls@^3.0.9:
+    version "3.1.0"
+    resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-3.1.0.tgz#13c754d5e7a2dd8b44fe5269e21ca394fb4d615b"
+    integrity sha512-sHxOu2ELzW8/NC1UP5XVLbZDzO4S3VxfFye3XYCznopHy02YjNkHcj5bKaVw2O7hVaBdBjEdQGpie4II1mWhuQ==
+    dependencies:
+      js-yaml "^3.13.1"
+      lcov-parse "^1.0.0"
+      log-driver "^1.2.7"
+      minimist "^1.2.5"
+      request "^2.88.2"
+  
+  create-ecdh@^4.0.0:
+    version "4.0.4"
+    resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e"
+    integrity sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==
+    dependencies:
+      bn.js "^4.1.0"
+      elliptic "^6.5.3"
+  
+  create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0:
+    version "1.2.0"
+    resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196"
+    integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==
+    dependencies:
+      cipher-base "^1.0.1"
+      inherits "^2.0.1"
+      md5.js "^1.3.4"
+      ripemd160 "^2.0.1"
+      sha.js "^2.4.0"
+  
+  create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7:
+    version "1.1.7"
+    resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff"
+    integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==
+    dependencies:
+      cipher-base "^1.0.3"
+      create-hash "^1.1.0"
+      inherits "^2.0.1"
+      ripemd160 "^2.0.0"
+      safe-buffer "^5.0.1"
+      sha.js "^2.4.8"
+  
+  cross-spawn@^6.0.0:
+    version "6.0.5"
+    resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
+    integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==
+    dependencies:
+      nice-try "^1.0.4"
+      path-key "^2.0.1"
+      semver "^5.5.0"
+      shebang-command "^1.2.0"
+      which "^1.2.9"
+  
+  cross-spawn@^7.0.2, cross-spawn@^7.0.3:
+    version "7.0.3"
+    resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
+    integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
+    dependencies:
+      path-key "^3.1.0"
+      shebang-command "^2.0.0"
+      which "^2.0.1"
+  
+  crypto-browserify@^3.12.0:
+    version "3.12.0"
+    resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec"
+    integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==
+    dependencies:
+      browserify-cipher "^1.0.0"
+      browserify-sign "^4.0.0"
+      create-ecdh "^4.0.0"
+      create-hash "^1.1.0"
+      create-hmac "^1.1.0"
+      diffie-hellman "^5.0.0"
+      inherits "^2.0.1"
+      pbkdf2 "^3.0.3"
+      public-encrypt "^4.0.0"
+      randombytes "^2.0.0"
+      randomfill "^1.0.3"
+  
+  currently-unhandled@^0.4.1:
+    version "0.4.1"
+    resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea"
+    integrity sha1-mI3zP+qxke95mmE2nddsF635V+o=
+    dependencies:
+      array-find-index "^1.0.1"
+  
+  custom-event@~1.0.0:
+    version "1.0.1"
+    resolved "https://registry.yarnpkg.com/custom-event/-/custom-event-1.0.1.tgz#5d02a46850adf1b4a317946a3928fccb5bfd0425"
+    integrity sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=
+  
+  dashdash@^1.12.0:
+    version "1.14.1"
+    resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
+    integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=
+    dependencies:
+      assert-plus "^1.0.0"
+  
+  date-format@^2.0.0:
+    version "2.1.0"
+    resolved "https://registry.yarnpkg.com/date-format/-/date-format-2.1.0.tgz#31d5b5ea211cf5fd764cd38baf9d033df7e125cf"
+    integrity sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA==
+  
+  date-format@^4.0.3:
+    version "4.0.3"
+    resolved "https://registry.yarnpkg.com/date-format/-/date-format-4.0.3.tgz#f63de5dc08dc02efd8ef32bf2a6918e486f35873"
+    integrity sha512-7P3FyqDcfeznLZp2b+OMitV9Sz2lUnsT87WaTat9nVwqsBkTzPG3lPLNwW3en6F4pHUiWzr6vb8CLhjdK9bcxQ==
+  
+  dateformat@^1.0.6:
+    version "1.0.12"
+    resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-1.0.12.tgz#9f124b67594c937ff706932e4a642cca8dbbfee9"
+    integrity sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=
+    dependencies:
+      get-stdin "^4.0.1"
+      meow "^3.3.0"
+  
+  dateformat@~3.0.3:
+    version "3.0.3"
+    resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae"
+    integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==
+  
+  debug@2.6.9, debug@^2.1.3, debug@^2.2.0, debug@^2.3.3:
+    version "2.6.9"
+    resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
+    integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
+    dependencies:
+      ms "2.0.0"
+  
+  debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1:
+    version "4.3.1"
+    resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee"
+    integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==
+    dependencies:
+      ms "2.1.2"
+  
+  debug@^3.1.0, debug@^3.2.6:
+    version "3.2.7"
+    resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a"
+    integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==
+    dependencies:
+      ms "^2.1.1"
+  
+  debug@^4.3.3, debug@~4.3.1, debug@~4.3.2:
+    version "4.3.3"
+    resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664"
+    integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==
+    dependencies:
+      ms "2.1.2"
+  
+  decamelize@^1.1.2, decamelize@^1.2.0:
+    version "1.2.0"
+    resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
+    integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
+  
+  decode-uri-component@^0.2.0:
+    version "0.2.0"
+    resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
+    integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=
+  
+  deep-is@^0.1.3, deep-is@~0.1.3:
+    version "0.1.3"
+    resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
+    integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=
+  
+  defaults@^1.0.3:
+    version "1.0.3"
+    resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d"
+    integrity sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=
+    dependencies:
+      clone "^1.0.2"
+  
+  define-properties@^1.1.3:
+    version "1.1.3"
+    resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
+    integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==
+    dependencies:
+      object-keys "^1.0.12"
+  
+  define-property@^0.2.5:
+    version "0.2.5"
+    resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116"
+    integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=
+    dependencies:
+      is-descriptor "^0.1.0"
+  
+  define-property@^1.0.0:
+    version "1.0.0"
+    resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6"
+    integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY=
+    dependencies:
+      is-descriptor "^1.0.0"
+  
+  define-property@^2.0.2:
+    version "2.0.2"
+    resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d"
+    integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==
+    dependencies:
+      is-descriptor "^1.0.2"
+      isobject "^3.0.1"
+  
+  del@^2.2.0:
+    version "2.2.2"
+    resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8"
+    integrity sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=
+    dependencies:
+      globby "^5.0.0"
+      is-path-cwd "^1.0.0"
+      is-path-in-cwd "^1.0.0"
+      object-assign "^4.0.1"
+      pify "^2.0.0"
+      pinkie-promise "^2.0.0"
+      rimraf "^2.2.8"
+  
+  delayed-stream@~1.0.0:
+    version "1.0.0"
+    resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
+    integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk=
+  
+  depd@~1.1.2:
+    version "1.1.2"
+    resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
+    integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=
+  
+  depd@~2.0.0:
+    version "2.0.0"
+    resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df"
+    integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==
+  
+  des.js@^1.0.0:
+    version "1.0.1"
+    resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843"
+    integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==
+    dependencies:
+      inherits "^2.0.1"
+      minimalistic-assert "^1.0.0"
+  
+  destroy@~1.0.4:
+    version "1.0.4"
+    resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
+    integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=
+  
+  detect-file@^1.0.0:
+    version "1.0.0"
+    resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7"
+    integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=
+  
+  devtools-protocol@0.0.818844:
+    version "0.0.818844"
+    resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.818844.tgz#d1947278ec85b53e4c8ca598f607a28fa785ba9e"
+    integrity sha512-AD1hi7iVJ8OD0aMLQU5VK0XH9LDlA1+BcPIgrAxPfaibx2DbWucuyOhc4oyQCbnvDDO68nN6/LcKfqTP343Jjg==
+  
+  di@^0.0.1:
+    version "0.0.1"
+    resolved "https://registry.yarnpkg.com/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c"
+    integrity sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=
+  
+  diff@^4.0.1:
+    version "4.0.2"
+    resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d"
+    integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==
+  
+  diffie-hellman@^5.0.0:
+    version "5.0.3"
+    resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875"
+    integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==
+    dependencies:
+      bn.js "^4.1.0"
+      miller-rabin "^4.0.0"
+      randombytes "^2.0.0"
+  
+  dir-glob@^3.0.1:
+    version "3.0.1"
+    resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f"
+    integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==
+    dependencies:
+      path-type "^4.0.0"
+  
+  doctoc@^1.4.0:
+    version "1.4.0"
+    resolved "https://registry.yarnpkg.com/doctoc/-/doctoc-1.4.0.tgz#3115aa61d0a92f0abb0672036918ea904f5b9e02"
+    integrity sha512-8IAq3KdMkxhXCUF+xdZxdJxwuz8N2j25sMgqiu4U4JWluN9tRKMlAalxGASszQjlZaBprdD2YfXpL3VPWUD4eg==
+    dependencies:
+      "@textlint/markdown-to-ast" "~6.0.9"
+      anchor-markdown-header "^0.5.5"
+      htmlparser2 "~3.9.2"
+      minimist "~1.2.0"
+      underscore "~1.8.3"
+      update-section "^0.3.0"
+  
+  doctrine@^3.0.0:
+    version "3.0.0"
+    resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961"
+    integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==
+    dependencies:
+      esutils "^2.0.2"
+  
+  dom-serialize@^2.2.1:
+    version "2.2.1"
+    resolved "https://registry.yarnpkg.com/dom-serialize/-/dom-serialize-2.2.1.tgz#562ae8999f44be5ea3076f5419dcd59eb43ac95b"
+    integrity sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=
+    dependencies:
+      custom-event "~1.0.0"
+      ent "~2.2.0"
+      extend "^3.0.0"
+      void-elements "^2.0.0"
+  
+  dom-serializer@0:
+    version "0.2.2"
+    resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51"
+    integrity sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==
+    dependencies:
+      domelementtype "^2.0.1"
+      entities "^2.0.0"
+  
+  domain-browser@^1.2.0:
+    version "1.2.0"
+    resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda"
+    integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==
+  
+  domelementtype@1, domelementtype@^1.3.0:
+    version "1.3.1"
+    resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f"
+    integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==
+  
+  domelementtype@^2.0.1:
+    version "2.2.0"
+    resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.2.0.tgz#9a0b6c2782ed6a1c7323d42267183df9bd8b1d57"
+    integrity sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==
+  
+  domhandler@^2.3.0:
+    version "2.4.2"
+    resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803"
+    integrity sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==
+    dependencies:
+      domelementtype "1"
+  
+  domutils@^1.5.1:
+    version "1.7.0"
+    resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a"
+    integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==
+    dependencies:
+      dom-serializer "0"
+      domelementtype "1"
+  
+  duplexer@^0.1.1:
+    version "0.1.2"
+    resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6"
+    integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==
+  
+  duplexify@^3.5.1:
+    version "3.7.1"
+    resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309"
+    integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==
+    dependencies:
+      end-of-stream "^1.0.0"
+      inherits "^2.0.1"
+      readable-stream "^2.0.0"
+      stream-shift "^1.0.0"
+  
+  ecc-jsbn@~0.1.1:
+    version "0.1.2"
+    resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9"
+    integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=
+    dependencies:
+      jsbn "~0.1.0"
+      safer-buffer "^2.1.0"
+  
+  ee-first@1.1.1:
+    version "1.1.1"
+    resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
+    integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
+  
+  electron-to-chromium@^1.3.723:
+    version "1.3.739"
+    resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.739.tgz#f07756aa92cabd5a6eec6f491525a64fe62f98b9"
+    integrity sha512-+LPJVRsN7hGZ9EIUUiWCpO7l4E3qBYHNadazlucBfsXBbccDFNKUBAgzE68FnkWGJPwD/AfKhSzL+G+Iqb8A4A==
+  
+  elliptic@^6.5.3:
+    version "6.5.4"
+    resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb"
+    integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==
+    dependencies:
+      bn.js "^4.11.9"
+      brorand "^1.1.0"
+      hash.js "^1.0.0"
+      hmac-drbg "^1.0.1"
+      inherits "^2.0.4"
+      minimalistic-assert "^1.0.1"
+      minimalistic-crypto-utils "^1.0.1"
+  
+  emoji-regex@^8.0.0:
+    version "8.0.0"
+    resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
+    integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
+  
+  emoji-regex@~6.1.0:
+    version "6.1.3"
+    resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-6.1.3.tgz#ec79a3969b02d2ecf2b72254279bf99bc7a83932"
+    integrity sha1-7HmjlpsC0uzytyJUJ5v5m8eoOTI=
+  
+  emojis-list@^3.0.0:
+    version "3.0.0"
+    resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78"
+    integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==
+  
+  encodeurl@~1.0.2:
+    version "1.0.2"
+    resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
+    integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=
+  
+  end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.1:
+    version "1.4.4"
+    resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
+    integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==
+    dependencies:
+      once "^1.4.0"
+  
+  engine.io-parser@~5.0.0:
+    version "5.0.3"
+    resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-5.0.3.tgz#ca1f0d7b11e290b4bfda251803baea765ed89c09"
+    integrity sha512-BtQxwF27XUNnSafQLvDi0dQ8s3i6VgzSoQMJacpIcGNrlUdfHSKbgm3jmjCVvQluGzqwujQMPAoMai3oYSTurg==
+    dependencies:
+      "@socket.io/base64-arraybuffer" "~1.0.2"
+  
+  engine.io@~6.1.0:
+    version "6.1.2"
+    resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-6.1.2.tgz#e7b9d546d90c62246ffcba4d88594be980d3855a"
+    integrity sha512-v/7eGHxPvO2AWsksyx2PUsQvBafuvqs0jJJQ0FdmJG1b9qIvgSbqDRGwNhfk2XHaTTbTXiC4quRE8Q9nRjsrQQ==
+    dependencies:
+      "@types/cookie" "^0.4.1"
+      "@types/cors" "^2.8.12"
+      "@types/node" ">=10.0.0"
+      accepts "~1.3.4"
+      base64id "2.0.0"
+      cookie "~0.4.1"
+      cors "~2.8.5"
+      debug "~4.3.1"
+      engine.io-parser "~5.0.0"
+      ws "~8.2.3"
+  
+  enhanced-resolve@^4.0.0:
+    version "4.5.0"
+    resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz#2f3cfd84dbe3b487f18f2db2ef1e064a571ca5ec"
+    integrity sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==
+    dependencies:
+      graceful-fs "^4.1.2"
+      memory-fs "^0.5.0"
+      tapable "^1.0.0"
+  
+  enhanced-resolve@^5.7.0:
+    version "5.7.0"
+    resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.7.0.tgz#525c5d856680fbd5052de453ac83e32049958b5c"
+    integrity sha512-6njwt/NsZFUKhM6j9U8hzVyD4E4r0x7NQzhTCbcWOJ0IQjNSAoalWmb0AE51Wn+fwan5qVESWi7t2ToBxs9vrw==
+    dependencies:
+      graceful-fs "^4.2.4"
+      tapable "^2.2.0"
+  
+  enquirer@^2.3.5, enquirer@^2.3.6:
+    version "2.3.6"
+    resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d"
+    integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==
+    dependencies:
+      ansi-colors "^4.1.1"
+  
+  ent@~2.2.0:
+    version "2.2.0"
+    resolved "https://registry.yarnpkg.com/ent/-/ent-2.2.0.tgz#e964219325a21d05f44466a2f686ed6ce5f5dd1d"
+    integrity sha1-6WQhkyWiHQX0RGai9obtbOX13R0=
+  
+  entities@^1.1.1:
+    version "1.1.2"
+    resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56"
+    integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==
+  
+  entities@^2.0.0:
+    version "2.2.0"
+    resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55"
+    integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==
+  
+  envinfo@^7.7.3:
+    version "7.8.1"
+    resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.8.1.tgz#06377e3e5f4d379fea7ac592d5ad8927e0c4d475"
+    integrity sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==
+  
+  errno@^0.1.3:
+    version "0.1.8"
+    resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f"
+    integrity sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==
+    dependencies:
+      prr "~1.0.1"
+  
+  error-ex@^1.2.0:
+    version "1.3.2"
+    resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
+    integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==
+    dependencies:
+      is-arrayish "^0.2.1"
+  
+  error@^7.0.0:
+    version "7.2.1"
+    resolved "https://registry.yarnpkg.com/error/-/error-7.2.1.tgz#eab21a4689b5f684fc83da84a0e390de82d94894"
+    integrity sha512-fo9HBvWnx3NGUKMvMwB/CBCMMrfEJgbDTVDEkPygA3Bdd3lM1OyCd+rbQ8BwnpF6GdVeOLDNmyL4N5Bg80ZvdA==
+    dependencies:
+      string-template "~0.2.1"
+  
+  es-abstract@^1.18.0-next.1, es-abstract@^1.18.0-next.2:
+    version "1.18.0"
+    resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.0.tgz#ab80b359eecb7ede4c298000390bc5ac3ec7b5a4"
+    integrity sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw==
+    dependencies:
+      call-bind "^1.0.2"
+      es-to-primitive "^1.2.1"
+      function-bind "^1.1.1"
+      get-intrinsic "^1.1.1"
+      has "^1.0.3"
+      has-symbols "^1.0.2"
+      is-callable "^1.2.3"
+      is-negative-zero "^2.0.1"
+      is-regex "^1.1.2"
+      is-string "^1.0.5"
+      object-inspect "^1.9.0"
+      object-keys "^1.1.1"
+      object.assign "^4.1.2"
+      string.prototype.trimend "^1.0.4"
+      string.prototype.trimstart "^1.0.4"
+      unbox-primitive "^1.0.0"
+  
+  es-module-lexer@^0.4.0:
+    version "0.4.1"
+    resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.4.1.tgz#dda8c6a14d8f340a24e34331e0fab0cb50438e0e"
+    integrity sha512-ooYciCUtfw6/d2w56UVeqHPcoCFAiJdz5XOkYpv/Txl1HMUozpXjz/2RIQgqwKdXNDPSF1W7mJCFse3G+HDyAA==
+  
+  es-to-primitive@^1.2.1:
+    version "1.2.1"
+    resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a"
+    integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==
+    dependencies:
+      is-callable "^1.1.4"
+      is-date-object "^1.0.1"
+      is-symbol "^1.0.2"
+  
+  es6-object-assign@^1.1.0:
+    version "1.1.0"
+    resolved "https://registry.yarnpkg.com/es6-object-assign/-/es6-object-assign-1.1.0.tgz#c2c3582656247c39ea107cb1e6652b6f9f24523c"
+    integrity sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw=
+  
+  es6-promise@^4.0.3:
+    version "4.2.8"
+    resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a"
+    integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==
+  
+  es6-promisify@^5.0.0:
+    version "5.0.0"
+    resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203"
+    integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=
+    dependencies:
+      es6-promise "^4.0.3"
+  
+  escalade@^3.1.1:
+    version "3.1.1"
+    resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
+    integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==
+  
+  escape-html@~1.0.3:
+    version "1.0.3"
+    resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
+    integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=
+  
+  escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
+    version "1.0.5"
+    resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
+    integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
+  
+  escodegen@1.8.x:
+    version "1.8.1"
+    resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.8.1.tgz#5a5b53af4693110bebb0867aa3430dd3b70a1018"
+    integrity sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=
+    dependencies:
+      esprima "^2.7.1"
+      estraverse "^1.9.1"
+      esutils "^2.0.2"
+      optionator "^0.8.1"
+    optionalDependencies:
+      source-map "~0.2.0"
+  
+  eslint-scope@^5.0.0, eslint-scope@^5.1.1:
+    version "5.1.1"
+    resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c"
+    integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==
+    dependencies:
+      esrecurse "^4.3.0"
+      estraverse "^4.1.1"
+  
+  eslint-utils@^2.0.0, eslint-utils@^2.1.0:
+    version "2.1.0"
+    resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27"
+    integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==
+    dependencies:
+      eslint-visitor-keys "^1.1.0"
+  
+  eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0:
+    version "1.3.0"
+    resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e"
+    integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==
+  
+  eslint-visitor-keys@^2.0.0:
+    version "2.0.0"
+    resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8"
+    integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==
+  
+  eslint@^7.0.0, eslint@^7.14:
+    version "7.24.0"
+    resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.24.0.tgz#2e44fa62d93892bfdb100521f17345ba54b8513a"
+    integrity sha512-k9gaHeHiFmGCDQ2rEfvULlSLruz6tgfA8DEn+rY9/oYPFFTlz55mM/Q/Rij1b2Y42jwZiK3lXvNTw6w6TXzcKQ==
+    dependencies:
+      "@babel/code-frame" "7.12.11"
+      "@eslint/eslintrc" "^0.4.0"
+      ajv "^6.10.0"
+      chalk "^4.0.0"
+      cross-spawn "^7.0.2"
+      debug "^4.0.1"
+      doctrine "^3.0.0"
+      enquirer "^2.3.5"
+      eslint-scope "^5.1.1"
+      eslint-utils "^2.1.0"
+      eslint-visitor-keys "^2.0.0"
+      espree "^7.3.1"
+      esquery "^1.4.0"
+      esutils "^2.0.2"
+      file-entry-cache "^6.0.1"
+      functional-red-black-tree "^1.0.1"
+      glob-parent "^5.0.0"
+      globals "^13.6.0"
+      ignore "^4.0.6"
+      import-fresh "^3.0.0"
+      imurmurhash "^0.1.4"
+      is-glob "^4.0.0"
+      js-yaml "^3.13.1"
+      json-stable-stringify-without-jsonify "^1.0.1"
+      levn "^0.4.1"
+      lodash "^4.17.21"
+      minimatch "^3.0.4"
+      natural-compare "^1.4.0"
+      optionator "^0.9.1"
+      progress "^2.0.0"
+      regexpp "^3.1.0"
+      semver "^7.2.1"
+      strip-ansi "^6.0.0"
+      strip-json-comments "^3.1.0"
+      table "^6.0.4"
+      text-table "^0.2.0"
+      v8-compile-cache "^2.0.3"
+  
+  espree@^7.3.0, espree@^7.3.1:
+    version "7.3.1"
+    resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.1.tgz#f2df330b752c6f55019f8bd89b7660039c1bbbb6"
+    integrity sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==
+    dependencies:
+      acorn "^7.4.0"
+      acorn-jsx "^5.3.1"
+      eslint-visitor-keys "^1.3.0"
+  
+  esprima@2.7.x, esprima@^2.7.1:
+    version "2.7.3"
+    resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581"
+    integrity sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=
+  
+  esprima@^4.0.0:
+    version "4.0.1"
+    resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
+    integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
+  
+  esquery@^1.4.0:
+    version "1.4.0"
+    resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5"
+    integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==
+    dependencies:
+      estraverse "^5.1.0"
+  
+  esrecurse@^4.3.0:
+    version "4.3.0"
+    resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921"
+    integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==
+    dependencies:
+      estraverse "^5.2.0"
+  
+  estraverse@^1.9.1:
+    version "1.9.3"
+    resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44"
+    integrity sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=
+  
+  estraverse@^4.1.1:
+    version "4.3.0"
+    resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d"
+    integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==
+  
+  estraverse@^5.1.0, estraverse@^5.2.0:
+    version "5.2.0"
+    resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880"
+    integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==
+  
+  esutils@^2.0.2:
+    version "2.0.3"
+    resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
+    integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
+  
+  etag@~1.8.1:
+    version "1.8.1"
+    resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
+    integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=
+  
+  eventemitter2@~0.4.13:
+    version "0.4.14"
+    resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-0.4.14.tgz#8f61b75cde012b2e9eb284d4545583b5643b61ab"
+    integrity sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas=
+  
+  eventemitter3@^4.0.0:
+    version "4.0.7"
+    resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f"
+    integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==
+  
+  events@1.1.1:
+    version "1.1.1"
+    resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924"
+    integrity sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=
+  
+  events@^3.0.0, events@^3.2.0:
+    version "3.3.0"
+    resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400"
+    integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==
+  
+  evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3:
+    version "1.0.3"
+    resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02"
+    integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==
+    dependencies:
+      md5.js "^1.3.4"
+      safe-buffer "^5.1.1"
+  
+  execa@^1.0.0:
+    version "1.0.0"
+    resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8"
+    integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==
+    dependencies:
+      cross-spawn "^6.0.0"
+      get-stream "^4.0.0"
+      is-stream "^1.1.0"
+      npm-run-path "^2.0.0"
+      p-finally "^1.0.0"
+      signal-exit "^3.0.0"
+      strip-eof "^1.0.0"
+  
+  execa@^5.0.0:
+    version "5.0.0"
+    resolved "https://registry.yarnpkg.com/execa/-/execa-5.0.0.tgz#4029b0007998a841fbd1032e5f4de86a3c1e3376"
+    integrity sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ==
+    dependencies:
+      cross-spawn "^7.0.3"
+      get-stream "^6.0.0"
+      human-signals "^2.1.0"
+      is-stream "^2.0.0"
+      merge-stream "^2.0.0"
+      npm-run-path "^4.0.1"
+      onetime "^5.1.2"
+      signal-exit "^3.0.3"
+      strip-final-newline "^2.0.0"
+  
+  exit@^0.1.2, exit@~0.1.1, exit@~0.1.2:
+    version "0.1.2"
+    resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c"
+    integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=
+  
+  expand-brackets@^2.1.4:
+    version "2.1.4"
+    resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622"
+    integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI=
+    dependencies:
+      debug "^2.3.3"
+      define-property "^0.2.5"
+      extend-shallow "^2.0.1"
+      posix-character-classes "^0.1.0"
+      regex-not "^1.0.0"
+      snapdragon "^0.8.1"
+      to-regex "^3.0.1"
+  
+  expand-tilde@^2.0.0, expand-tilde@^2.0.2:
+    version "2.0.2"
+    resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502"
+    integrity sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=
+    dependencies:
+      homedir-polyfill "^1.0.1"
+  
+  extend-shallow@^2.0.1:
+    version "2.0.1"
+    resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f"
+    integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=
+    dependencies:
+      is-extendable "^0.1.0"
+  
+  extend-shallow@^3.0.0, extend-shallow@^3.0.2:
+    version "3.0.2"
+    resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8"
+    integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=
+    dependencies:
+      assign-symbols "^1.0.0"
+      is-extendable "^1.0.1"
+  
+  extend@^3.0.0, extend@^3.0.2, extend@~3.0.2:
+    version "3.0.2"
+    resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
+    integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
+  
+  extglob@^2.0.4:
+    version "2.0.4"
+    resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543"
+    integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==
+    dependencies:
+      array-unique "^0.3.2"
+      define-property "^1.0.0"
+      expand-brackets "^2.1.4"
+      extend-shallow "^2.0.1"
+      fragment-cache "^0.2.1"
+      regex-not "^1.0.0"
+      snapdragon "^0.8.1"
+      to-regex "^3.0.1"
+  
+  extract-zip@^2.0.0:
+    version "2.0.1"
+    resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a"
+    integrity sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==
+    dependencies:
+      debug "^4.1.1"
+      get-stream "^5.1.0"
+      yauzl "^2.10.0"
+    optionalDependencies:
+      "@types/yauzl" "^2.9.1"
+  
+  extsprintf@1.3.0:
+    version "1.3.0"
+    resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05"
+    integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=
+  
+  extsprintf@^1.2.0:
+    version "1.4.0"
+    resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f"
+    integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8=
+  
+  fast-deep-equal@^3.1.1:
+    version "3.1.3"
+    resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
+    integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
+  
+  fast-glob@^3.1.1:
+    version "3.2.5"
+    resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.5.tgz#7939af2a656de79a4f1901903ee8adcaa7cb9661"
+    integrity sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==
+    dependencies:
+      "@nodelib/fs.stat" "^2.0.2"
+      "@nodelib/fs.walk" "^1.2.3"
+      glob-parent "^5.1.0"
+      merge2 "^1.3.0"
+      micromatch "^4.0.2"
+      picomatch "^2.2.1"
+  
+  fast-json-stable-stringify@^2.0.0:
+    version "2.1.0"
+    resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
+    integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
+  
+  fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6:
+    version "2.0.6"
+    resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
+    integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=
+  
+  fastest-levenshtein@^1.0.12:
+    version "1.0.12"
+    resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz#9990f7d3a88cc5a9ffd1f1745745251700d497e2"
+    integrity sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==
+  
+  fastq@^1.6.0:
+    version "1.11.0"
+    resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.11.0.tgz#bb9fb955a07130a918eb63c1f5161cc32a5d0858"
+    integrity sha512-7Eczs8gIPDrVzT+EksYBcupqMyxSHXXrHOLRRxU2/DicV8789MRBRR8+Hc2uWzUupOs4YS4JzBmBxjjCVBxD/g==
+    dependencies:
+      reusify "^1.0.4"
+  
+  fault@^1.0.1:
+    version "1.0.4"
+    resolved "https://registry.yarnpkg.com/fault/-/fault-1.0.4.tgz#eafcfc0a6d214fc94601e170df29954a4f842f13"
+    integrity sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA==
+    dependencies:
+      format "^0.2.0"
+  
+  faye-websocket@~0.10.0:
+    version "0.10.0"
+    resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.10.0.tgz#4e492f8d04dfb6f89003507f6edbf2d501e7c6f4"
+    integrity sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=
+    dependencies:
+      websocket-driver ">=0.5.1"
+  
+  fd-slicer@~1.1.0:
+    version "1.1.0"
+    resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e"
+    integrity sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=
+    dependencies:
+      pend "~1.2.0"
+  
+  figures@^1.0.1:
+    version "1.7.0"
+    resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e"
+    integrity sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=
+    dependencies:
+      escape-string-regexp "^1.0.5"
+      object-assign "^4.1.0"
+  
+  file-entry-cache@^6.0.1:
+    version "6.0.1"
+    resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027"
+    integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==
+    dependencies:
+      flat-cache "^3.0.4"
+  
+  file-sync-cmp@^0.1.0:
+    version "0.1.1"
+    resolved "https://registry.yarnpkg.com/file-sync-cmp/-/file-sync-cmp-0.1.1.tgz#a5e7a8ffbfa493b43b923bbd4ca89a53b63b612b"
+    integrity sha1-peeo/7+kk7Q7kju9TKiaU7Y7YSs=
+  
+  fill-range@^4.0.0:
+    version "4.0.0"
+    resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7"
+    integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=
+    dependencies:
+      extend-shallow "^2.0.1"
+      is-number "^3.0.0"
+      repeat-string "^1.6.1"
+      to-regex-range "^2.1.0"
+  
+  fill-range@^7.0.1:
+    version "7.0.1"
+    resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
+    integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
+    dependencies:
+      to-regex-range "^5.0.1"
+  
+  finalhandler@1.1.2:
+    version "1.1.2"
+    resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d"
+    integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==
+    dependencies:
+      debug "2.6.9"
+      encodeurl "~1.0.2"
+      escape-html "~1.0.3"
+      on-finished "~2.3.0"
+      parseurl "~1.3.3"
+      statuses "~1.5.0"
+      unpipe "~1.0.0"
+  
+  find-up@^1.0.0:
+    version "1.1.2"
+    resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f"
+    integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=
+    dependencies:
+      path-exists "^2.0.0"
+      pinkie-promise "^2.0.0"
+  
+  find-up@^3.0.0:
+    version "3.0.0"
+    resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73"
+    integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==
+    dependencies:
+      locate-path "^3.0.0"
+  
+  find-up@^4.0.0, find-up@^4.1.0:
+    version "4.1.0"
+    resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19"
+    integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==
+    dependencies:
+      locate-path "^5.0.0"
+      path-exists "^4.0.0"
+  
+  findup-sync@^2.0.0:
+    version "2.0.0"
+    resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-2.0.0.tgz#9326b1488c22d1a6088650a86901b2d9a90a2cbc"
+    integrity sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=
+    dependencies:
+      detect-file "^1.0.0"
+      is-glob "^3.1.0"
+      micromatch "^3.0.4"
+      resolve-dir "^1.0.1"
+  
+  findup-sync@^4.0.0:
+    version "4.0.0"
+    resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-4.0.0.tgz#956c9cdde804052b881b428512905c4a5f2cdef0"
+    integrity sha512-6jvvn/12IC4quLBL1KNokxC7wWTvYncaVUYSoxWw7YykPLuRrnv4qdHcSOywOI5RpkOVGeQRtWM8/q+G6W6qfQ==
+    dependencies:
+      detect-file "^1.0.0"
+      is-glob "^4.0.0"
+      micromatch "^4.0.2"
+      resolve-dir "^1.0.1"
+  
+  findup-sync@~0.3.0:
+    version "0.3.0"
+    resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-0.3.0.tgz#37930aa5d816b777c03445e1966cc6790a4c0b16"
+    integrity sha1-N5MKpdgWt3fANEXhlmzGeQpMCxY=
+    dependencies:
+      glob "~5.0.0"
+  
+  fined@^1.0.1, fined@^1.2.0:
+    version "1.2.0"
+    resolved "https://registry.yarnpkg.com/fined/-/fined-1.2.0.tgz#d00beccf1aa2b475d16d423b0238b713a2c4a37b"
+    integrity sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==
+    dependencies:
+      expand-tilde "^2.0.2"
+      is-plain-object "^2.0.3"
+      object.defaults "^1.1.0"
+      object.pick "^1.2.0"
+      parse-filepath "^1.0.1"
+  
+  flagged-respawn@^1.0.0, flagged-respawn@^1.0.1:
+    version "1.0.1"
+    resolved "https://registry.yarnpkg.com/flagged-respawn/-/flagged-respawn-1.0.1.tgz#e7de6f1279ddd9ca9aac8a5971d618606b3aab41"
+    integrity sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==
+  
+  flat-cache@^3.0.4:
+    version "3.0.4"
+    resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11"
+    integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==
+    dependencies:
+      flatted "^3.1.0"
+      rimraf "^3.0.2"
+  
+  flatted@^2.0.0:
+    version "2.0.2"
+    resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138"
+    integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==
+  
+  flatted@^3.1.0:
+    version "3.1.1"
+    resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.1.tgz#c4b489e80096d9df1dfc97c79871aea7c617c469"
+    integrity sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==
+  
+  flatted@^3.2.4:
+    version "3.2.5"
+    resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.5.tgz#76c8584f4fc843db64702a6bd04ab7a8bd666da3"
+    integrity sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==
+  
+  follow-redirects@^1.0.0:
+    version "1.14.8"
+    resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.8.tgz#016996fb9a11a100566398b1c6839337d7bfa8fc"
+    integrity sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==
+  
+  for-in@^1.0.1, for-in@^1.0.2:
+    version "1.0.2"
+    resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
+    integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=
+  
+  for-own@^1.0.0:
+    version "1.0.0"
+    resolved "https://registry.yarnpkg.com/for-own/-/for-own-1.0.0.tgz#c63332f415cedc4b04dbfe70cf836494c53cb44b"
+    integrity sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=
+    dependencies:
+      for-in "^1.0.1"
+  
+  foreach@^2.0.5:
+    version "2.0.5"
+    resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99"
+    integrity sha1-C+4AUBiusmDQo6865ljdATbsG5k=
+  
+  forever-agent@~0.6.1:
+    version "0.6.1"
+    resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
+    integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=
+  
+  form-data@~2.3.2:
+    version "2.3.3"
+    resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"
+    integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==
+    dependencies:
+      asynckit "^0.4.0"
+      combined-stream "^1.0.6"
+      mime-types "^2.1.12"
+  
+  format@^0.2.0:
+    version "0.2.2"
+    resolved "https://registry.yarnpkg.com/format/-/format-0.2.2.tgz#d6170107e9efdc4ed30c9dc39016df942b5cb58b"
+    integrity sha1-1hcBB+nv3E7TDJ3DkBbflCtctYs=
+  
+  fragment-cache@^0.2.1:
+    version "0.2.1"
+    resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19"
+    integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=
+    dependencies:
+      map-cache "^0.2.2"
+  
+  fresh@0.5.2:
+    version "0.5.2"
+    resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
+    integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=
+  
+  fs-constants@^1.0.0:
+    version "1.0.0"
+    resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad"
+    integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==
+  
+  fs-extra@^10.0.0:
+    version "10.0.0"
+    resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.0.0.tgz#9ff61b655dde53fb34a82df84bb214ce802e17c1"
+    integrity sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==
+    dependencies:
+      graceful-fs "^4.2.0"
+      jsonfile "^6.0.1"
+      universalify "^2.0.0"
+  
+  fs-extra@^7.0.1:
+    version "7.0.1"
+    resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9"
+    integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==
+    dependencies:
+      graceful-fs "^4.1.2"
+      jsonfile "^4.0.0"
+      universalify "^0.1.0"
+  
+  fs.realpath@^1.0.0:
+    version "1.0.0"
+    resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
+    integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
+  
+  fsevents@~2.3.2:
+    version "2.3.2"
+    resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
+    integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
+  
+  function-bind@^1.1.1:
+    version "1.1.1"
+    resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
+    integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
+  
+  functional-red-black-tree@^1.0.1:
+    version "1.0.1"
+    resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"
+    integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=
+  
+  gaze@^1.1.0:
+    version "1.1.3"
+    resolved "https://registry.yarnpkg.com/gaze/-/gaze-1.1.3.tgz#c441733e13b927ac8c0ff0b4c3b033f28812924a"
+    integrity sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==
+    dependencies:
+      globule "^1.0.0"
+  
+  get-caller-file@^1.0.1:
+    version "1.0.3"
+    resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a"
+    integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==
+  
+  get-caller-file@^2.0.1, get-caller-file@^2.0.5:
+    version "2.0.5"
+    resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
+    integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
+  
+  get-intrinsic@^1.0.2, get-intrinsic@^1.1.1:
+    version "1.1.1"
+    resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6"
+    integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==
+    dependencies:
+      function-bind "^1.1.1"
+      has "^1.0.3"
+      has-symbols "^1.0.1"
+  
+  get-stdin@^4.0.1:
+    version "4.0.1"
+    resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe"
+    integrity sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=
+  
+  get-stream@^4.0.0:
+    version "4.1.0"
+    resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5"
+    integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==
+    dependencies:
+      pump "^3.0.0"
+  
+  get-stream@^5.1.0:
+    version "5.2.0"
+    resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3"
+    integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==
+    dependencies:
+      pump "^3.0.0"
+  
+  get-stream@^6.0.0:
+    version "6.0.0"
+    resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.0.tgz#3e0012cb6827319da2706e601a1583e8629a6718"
+    integrity sha512-A1B3Bh1UmL0bidM/YX2NsCOTnGJePL9rO/M+Mw3m9f2gUpfokS0hi5Eah0WSUEWZdZhIZtMjkIYS7mDfOqNHbg==
+  
+  get-value@^2.0.3, get-value@^2.0.6:
+    version "2.0.6"
+    resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28"
+    integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=
+  
+  getobject@~0.1.0:
+    version "0.1.0"
+    resolved "https://registry.yarnpkg.com/getobject/-/getobject-0.1.0.tgz#047a449789fa160d018f5486ed91320b6ec7885c"
+    integrity sha1-BHpEl4n6Fg0Bj1SG7ZEyC27HiFw=
+  
+  getpass@^0.1.1:
+    version "0.1.7"
+    resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
+    integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=
+    dependencies:
+      assert-plus "^1.0.0"
+  
+  glob-parent@^5.0.0, glob-parent@^5.1.0, glob-parent@~5.1.2:
+    version "5.1.2"
+    resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
+    integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
+    dependencies:
+      is-glob "^4.0.1"
+  
+  glob-to-regexp@^0.4.1:
+    version "0.4.1"
+    resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e"
+    integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==
+  
+  glob@^5.0.15, glob@~5.0.0:
+    version "5.0.15"
+    resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1"
+    integrity sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=
+    dependencies:
+      inflight "^1.0.4"
+      inherits "2"
+      minimatch "2 || 3"
+      once "^1.3.0"
+      path-is-absolute "^1.0.0"
+  
+  glob@^7.0.3, glob@^7.0.6, glob@^7.1.3, glob@^7.1.7:
+    version "7.2.0"
+    resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023"
+    integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==
+    dependencies:
+      fs.realpath "^1.0.0"
+      inflight "^1.0.4"
+      inherits "2"
+      minimatch "^3.0.4"
+      once "^1.3.0"
+      path-is-absolute "^1.0.0"
+  
+  glob@~7.1.1, glob@~7.1.6:
+    version "7.1.6"
+    resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
+    integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
+    dependencies:
+      fs.realpath "^1.0.0"
+      inflight "^1.0.4"
+      inherits "2"
+      minimatch "^3.0.4"
+      once "^1.3.0"
+      path-is-absolute "^1.0.0"
+  
+  global-modules@^1.0.0:
+    version "1.0.0"
+    resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea"
+    integrity sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==
+    dependencies:
+      global-prefix "^1.0.1"
+      is-windows "^1.0.1"
+      resolve-dir "^1.0.0"
+  
+  global-prefix@^1.0.1:
+    version "1.0.2"
+    resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-1.0.2.tgz#dbf743c6c14992593c655568cb66ed32c0122ebe"
+    integrity sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=
+    dependencies:
+      expand-tilde "^2.0.2"
+      homedir-polyfill "^1.0.1"
+      ini "^1.3.4"
+      is-windows "^1.0.1"
+      which "^1.2.14"
+  
+  globals@^12.1.0:
+    version "12.4.0"
+    resolved "https://registry.yarnpkg.com/globals/-/globals-12.4.0.tgz#a18813576a41b00a24a97e7f815918c2e19925f8"
+    integrity sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==
+    dependencies:
+      type-fest "^0.8.1"
+  
+  globals@^13.6.0:
+    version "13.8.0"
+    resolved "https://registry.yarnpkg.com/globals/-/globals-13.8.0.tgz#3e20f504810ce87a8d72e55aecf8435b50f4c1b3"
+    integrity sha512-rHtdA6+PDBIjeEvA91rpqzEvk/k3/i7EeNQiryiWuJH0Hw9cpyJMAt2jtbAwUaRdhD+573X4vWw6IcjKPasi9Q==
+    dependencies:
+      type-fest "^0.20.2"
+  
+  globby@^11.0.1:
+    version "11.0.3"
+    resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.3.tgz#9b1f0cb523e171dd1ad8c7b2a9fb4b644b9593cb"
+    integrity sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg==
+    dependencies:
+      array-union "^2.1.0"
+      dir-glob "^3.0.1"
+      fast-glob "^3.1.1"
+      ignore "^5.1.4"
+      merge2 "^1.3.0"
+      slash "^3.0.0"
+  
+  globby@^5.0.0:
+    version "5.0.0"
+    resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d"
+    integrity sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=
+    dependencies:
+      array-union "^1.0.1"
+      arrify "^1.0.0"
+      glob "^7.0.3"
+      object-assign "^4.0.1"
+      pify "^2.0.0"
+      pinkie-promise "^2.0.0"
+  
+  globule@^1.0.0:
+    version "1.3.2"
+    resolved "https://registry.yarnpkg.com/globule/-/globule-1.3.2.tgz#d8bdd9e9e4eef8f96e245999a5dee7eb5d8529c4"
+    integrity sha512-7IDTQTIu2xzXkT+6mlluidnWo+BypnbSoEVVQCGfzqnl5Ik8d3e1d4wycb8Rj9tWW+Z39uPWsdlquqiqPCd/pA==
+    dependencies:
+      glob "~7.1.1"
+      lodash "~4.17.10"
+      minimatch "~3.0.2"
+  
+  graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.6:
+    version "4.2.9"
+    resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96"
+    integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==
+  
+  grunt-cli@^1.3.2:
+    version "1.4.2"
+    resolved "https://registry.yarnpkg.com/grunt-cli/-/grunt-cli-1.4.2.tgz#8a83dcc89ebd92d278ccd6014105011cffc71165"
+    integrity sha512-wsu6BZh7KCnfeaSkDrKIAvOlqGKxNRTZjc8xfZlvxCByQIqUfZ31kh5uHpPnhQ4NdVgvaWaVxa1LUbVU80nACw==
+    dependencies:
+      grunt-known-options "~1.1.1"
+      interpret "~1.1.0"
+      liftup "~3.0.1"
+      nopt "~4.0.1"
+      v8flags "~3.2.0"
+  
+  grunt-cli@~1.3.2:
+    version "1.3.2"
+    resolved "https://registry.yarnpkg.com/grunt-cli/-/grunt-cli-1.3.2.tgz#60f12d12c1b5aae94ae3469c6b5fe24e960014e8"
+    integrity sha512-8OHDiZZkcptxVXtMfDxJvmN7MVJNE8L/yIcPb4HB7TlyFD1kDvjHrb62uhySsU14wJx9ORMnTuhRMQ40lH/orQ==
+    dependencies:
+      grunt-known-options "~1.1.0"
+      interpret "~1.1.0"
+      liftoff "~2.5.0"
+      nopt "~4.0.1"
+      v8flags "~3.1.1"
+  
+  grunt-contrib-connect@^3.0.0:
+    version "3.0.0"
+    resolved "https://registry.yarnpkg.com/grunt-contrib-connect/-/grunt-contrib-connect-3.0.0.tgz#720e9ef39f976b804baf994345c2f6ecfdf3b264"
+    integrity sha512-L1GXk6PqDP/meX0IOX1MByBvOph6h8Pvx4/iBIYD7dpokVCAAQPR/IIV1jkTONEM09xig/Y8/y3R9Fqc8U3HSA==
+    dependencies:
+      async "^3.2.0"
+      connect "^3.7.0"
+      connect-livereload "^0.6.1"
+      morgan "^1.10.0"
+      node-http2 "^4.0.1"
+      opn "^6.0.0"
+      portscanner "^2.2.0"
+      serve-index "^1.9.1"
+      serve-static "^1.14.1"
+  
+  grunt-contrib-copy@^1.0.0:
+    version "1.0.0"
+    resolved "https://registry.yarnpkg.com/grunt-contrib-copy/-/grunt-contrib-copy-1.0.0.tgz#7060c6581e904b8ab0d00f076e0a8f6e3e7c3573"
+    integrity sha1-cGDGWB6QS4qw0A8HbgqPbj58NXM=
+    dependencies:
+      chalk "^1.1.1"
+      file-sync-cmp "^0.1.0"
+  
+  grunt-contrib-cssmin@^3.0.0:
+    version "3.0.0"
+    resolved "https://registry.yarnpkg.com/grunt-contrib-cssmin/-/grunt-contrib-cssmin-3.0.0.tgz#1767c0a062f4b7353c5adcadc52dcff7197d4d89"
+    integrity sha512-eXpooYmVGKMs/xV7DzTLgJFPVOfMuawPD3x0JwhlH0mumq2NtH3xsxaHxp1Y3NKxp0j0tRhFS6kSBRsz6TuTGg==
+    dependencies:
+      chalk "^2.4.1"
+      clean-css "~4.2.1"
+      maxmin "^2.1.0"
+  
+  grunt-contrib-uglify@^5.0.0:
+    version "5.0.1"
+    resolved "https://registry.yarnpkg.com/grunt-contrib-uglify/-/grunt-contrib-uglify-5.0.1.tgz#d1eeccafdfedc27353e5f610415d18340c568c51"
+    integrity sha512-T/aXZ4WIpAtoswZqb6HROKg7uq9QbKwl+lUuOwK4eoFj3tFv9/a/oMyd3/qvetV29Pbf8P1YYda1gDwZppr60A==
+    dependencies:
+      chalk "^2.4.1"
+      maxmin "^2.1.0"
+      uglify-js "^3.13.3"
+      uri-path "^1.0.0"
+  
+  grunt-contrib-watch@^1.1.0:
+    version "1.1.0"
+    resolved "https://registry.yarnpkg.com/grunt-contrib-watch/-/grunt-contrib-watch-1.1.0.tgz#c143ca5b824b288a024b856639a5345aedb78ed4"
+    integrity sha512-yGweN+0DW5yM+oo58fRu/XIRrPcn3r4tQx+nL7eMRwjpvk+rQY6R8o94BPK0i2UhTg9FN21hS+m8vR8v9vXfeg==
+    dependencies:
+      async "^2.6.0"
+      gaze "^1.1.0"
+      lodash "^4.17.10"
+      tiny-lr "^1.1.1"
+  
+  grunt-eslint@^23.0.0:
+    version "23.0.0"
+    resolved "https://registry.yarnpkg.com/grunt-eslint/-/grunt-eslint-23.0.0.tgz#47c804613c59646b2cfa402eb8d301e55b206bcf"
+    integrity sha512-QqHSAiGF08EVD7YlD4OSRWuLRaDvpsRdTptwy9WaxUXE+03mCLVA/lEaR6SHWehF7oUwIqCEjaNONeeeWlB4LQ==
+    dependencies:
+      chalk "^4.0.0"
+      eslint "^7.0.0"
+  
+  grunt-known-options@~1.1.0, grunt-known-options@~1.1.1:
+    version "1.1.1"
+    resolved "https://registry.yarnpkg.com/grunt-known-options/-/grunt-known-options-1.1.1.tgz#6cc088107bd0219dc5d3e57d91923f469059804d"
+    integrity sha512-cHwsLqoighpu7TuYj5RonnEuxGVFnztcUqTqp5rXFGYL4OuPFofwC4Ycg7n9fYwvK6F5WbYgeVOwph9Crs2fsQ==
+  
+  grunt-legacy-log-utils@~2.1.0:
+    version "2.1.0"
+    resolved "https://registry.yarnpkg.com/grunt-legacy-log-utils/-/grunt-legacy-log-utils-2.1.0.tgz#49a8c7dc74051476dcc116c32faf9db8646856ef"
+    integrity sha512-lwquaPXJtKQk0rUM1IQAop5noEpwFqOXasVoedLeNzaibf/OPWjKYvvdqnEHNmU+0T0CaReAXIbGo747ZD+Aaw==
+    dependencies:
+      chalk "~4.1.0"
+      lodash "~4.17.19"
+  
+  grunt-legacy-log@~3.0.0:
+    version "3.0.0"
+    resolved "https://registry.yarnpkg.com/grunt-legacy-log/-/grunt-legacy-log-3.0.0.tgz#1c6eaf92371ea415af31ea84ce50d434ef6d39c4"
+    integrity sha512-GHZQzZmhyq0u3hr7aHW4qUH0xDzwp2YXldLPZTCjlOeGscAOWWPftZG3XioW8MasGp+OBRIu39LFx14SLjXRcA==
+    dependencies:
+      colors "~1.1.2"
+      grunt-legacy-log-utils "~2.1.0"
+      hooker "~0.2.3"
+      lodash "~4.17.19"
+  
+  grunt-legacy-util@~2.0.0:
+    version "2.0.0"
+    resolved "https://registry.yarnpkg.com/grunt-legacy-util/-/grunt-legacy-util-2.0.0.tgz#34d20f2a26c6adebfe9a9bdc8823f7016b0369c3"
+    integrity sha512-ZEmYFB44bblwPE2oz3q3ygfF6hseQja9tx8I3UZIwbUik32FMWewA+d1qSFicMFB+8dNXDkh35HcDCWlpRsGlA==
+    dependencies:
+      async "~1.5.2"
+      exit "~0.1.1"
+      getobject "~0.1.0"
+      hooker "~0.2.3"
+      lodash "~4.17.20"
+      underscore.string "~3.3.5"
+      which "~1.3.0"
+  
+  grunt-protractor-runner@^5.0.0:
+    version "5.0.0"
+    resolved "https://registry.yarnpkg.com/grunt-protractor-runner/-/grunt-protractor-runner-5.0.0.tgz#862d43c2ba0f82ad9364e861dc4aa79b0e6426c1"
+    integrity sha1-hi1DwroPgq2TZOhh3Eqnmw5kJsE=
+    dependencies:
+      protractor "^5.0.0"
+      split "~1.0.0"
+      through2 "~2.0.0"
+  
+  grunt-protractor-webdriver@^0.2.5:
+    version "0.2.5"
+    resolved "https://registry.yarnpkg.com/grunt-protractor-webdriver/-/grunt-protractor-webdriver-0.2.5.tgz#bd6808b257013c0e6137e86847ee67c322bff65f"
+    integrity sha1-vWgIslcBPA5hN+hoR+5nwyK/9l8=
+    dependencies:
+      split "^1.0.0"
+  
+  grunt-sass@3.1.0:
+    version "3.1.0"
+    resolved "https://registry.yarnpkg.com/grunt-sass/-/grunt-sass-3.1.0.tgz#a5936cc2a80ec08092d9f31c101dc307d1e4f71c"
+    integrity sha512-90s27H7FoCDcA8C8+R0GwC+ntYD3lG6S/jqcavWm3bn9RiJTmSfOvfbFa1PXx4NbBWuiGQMLfQTj/JvvqT5w6A==
+  
+  grunt@^1.0.4:
+    version "1.3.0"
+    resolved "https://registry.yarnpkg.com/grunt/-/grunt-1.3.0.tgz#55db6ccd80c6fb53722e496f680620a2e681f809"
+    integrity sha512-6ILlMXv11/4cxuhSMfSU+SfvbxrPuqZrAtLN64+tZpQ3DAKfSQPQHRbTjSbdtxfyQhGZPtN0bDZJ/LdCM5WXXA==
+    dependencies:
+      dateformat "~3.0.3"
+      eventemitter2 "~0.4.13"
+      exit "~0.1.2"
+      findup-sync "~0.3.0"
+      glob "~7.1.6"
+      grunt-cli "~1.3.2"
+      grunt-known-options "~1.1.0"
+      grunt-legacy-log "~3.0.0"
+      grunt-legacy-util "~2.0.0"
+      iconv-lite "~0.4.13"
+      js-yaml "~3.14.0"
+      minimatch "~3.0.4"
+      mkdirp "~1.0.4"
+      nopt "~3.0.6"
+      rimraf "~3.0.2"
+  
+  gzip-size@^3.0.0:
+    version "3.0.0"
+    resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-3.0.0.tgz#546188e9bdc337f673772f81660464b389dce520"
+    integrity sha1-VGGI6b3DN/Zzdy+BZgRks4nc5SA=
+    dependencies:
+      duplexer "^0.1.1"
+  
+  handlebars@^4.0.1:
+    version "4.7.7"
+    resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1"
+    integrity sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==
+    dependencies:
+      minimist "^1.2.5"
+      neo-async "^2.6.0"
+      source-map "^0.6.1"
+      wordwrap "^1.0.0"
+    optionalDependencies:
+      uglify-js "^3.1.4"
+  
+  har-schema@^2.0.0:
+    version "2.0.0"
+    resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
+    integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=
+  
+  har-validator@~5.1.3:
+    version "5.1.5"
+    resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd"
+    integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==
+    dependencies:
+      ajv "^6.12.3"
+      har-schema "^2.0.0"
+  
+  has-ansi@^2.0.0:
+    version "2.0.0"
+    resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
+    integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=
+    dependencies:
+      ansi-regex "^2.0.0"
+  
+  has-bigints@^1.0.1:
+    version "1.0.1"
+    resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113"
+    integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==
+  
+  has-flag@^1.0.0:
+    version "1.0.0"
+    resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa"
+    integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=
+  
+  has-flag@^3.0.0:
+    version "3.0.0"
+    resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
+    integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
+  
+  has-flag@^4.0.0:
+    version "4.0.0"
+    resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
+    integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
+  
+  has-symbols@^1.0.1, has-symbols@^1.0.2:
+    version "1.0.2"
+    resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423"
+    integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==
+  
+  has-value@^0.3.1:
+    version "0.3.1"
+    resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f"
+    integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=
+    dependencies:
+      get-value "^2.0.3"
+      has-values "^0.1.4"
+      isobject "^2.0.0"
+  
+  has-value@^1.0.0:
+    version "1.0.0"
+    resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177"
+    integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=
+    dependencies:
+      get-value "^2.0.6"
+      has-values "^1.0.0"
+      isobject "^3.0.0"
+  
+  has-values@^0.1.4:
+    version "0.1.4"
+    resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771"
+    integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E=
+  
+  has-values@^1.0.0:
+    version "1.0.0"
+    resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f"
+    integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=
+    dependencies:
+      is-number "^3.0.0"
+      kind-of "^4.0.0"
+  
+  has@^1.0.3:
+    version "1.0.3"
+    resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
+    integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
+    dependencies:
+      function-bind "^1.1.1"
+  
+  hash-base@^3.0.0:
+    version "3.1.0"
+    resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33"
+    integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==
+    dependencies:
+      inherits "^2.0.4"
+      readable-stream "^3.6.0"
+      safe-buffer "^5.2.0"
+  
+  hash.js@^1.0.0, hash.js@^1.0.3:
+    version "1.1.7"
+    resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42"
+    integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==
+    dependencies:
+      inherits "^2.0.3"
+      minimalistic-assert "^1.0.1"
+  
+  hmac-drbg@^1.0.1:
+    version "1.0.1"
+    resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1"
+    integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=
+    dependencies:
+      hash.js "^1.0.3"
+      minimalistic-assert "^1.0.0"
+      minimalistic-crypto-utils "^1.0.1"
+  
+  homedir-polyfill@^1.0.1:
+    version "1.0.3"
+    resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8"
+    integrity sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==
+    dependencies:
+      parse-passwd "^1.0.0"
+  
+  hooker@~0.2.3:
+    version "0.2.3"
+    resolved "https://registry.yarnpkg.com/hooker/-/hooker-0.2.3.tgz#b834f723cc4a242aa65963459df6d984c5d3d959"
+    integrity sha1-uDT3I8xKJCqmWWNFnfbZhMXT2Vk=
+  
+  hosted-git-info@^2.1.4:
+    version "2.8.9"
+    resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9"
+    integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==
+  
+  htmlparser2@~3.9.2:
+    version "3.9.2"
+    resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.9.2.tgz#1bdf87acca0f3f9e53fa4fcceb0f4b4cbb00b338"
+    integrity sha1-G9+HrMoPP55T+k/M6w9LTLsAszg=
+    dependencies:
+      domelementtype "^1.3.0"
+      domhandler "^2.3.0"
+      domutils "^1.5.1"
+      entities "^1.1.1"
+      inherits "^2.0.1"
+      readable-stream "^2.0.2"
+  
+  http-errors@1.8.1:
+    version "1.8.1"
+    resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.1.tgz#7c3f28577cbc8a207388455dbd62295ed07bd68c"
+    integrity sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==
+    dependencies:
+      depd "~1.1.2"
+      inherits "2.0.4"
+      setprototypeof "1.2.0"
+      statuses ">= 1.5.0 < 2"
+      toidentifier "1.0.1"
+  
+  http-errors@~1.6.2:
+    version "1.6.3"
+    resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d"
+    integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=
+    dependencies:
+      depd "~1.1.2"
+      inherits "2.0.3"
+      setprototypeof "1.1.0"
+      statuses ">= 1.4.0 < 2"
+  
+  http-errors@~1.7.2:
+    version "1.7.3"
+    resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06"
+    integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==
+    dependencies:
+      depd "~1.1.2"
+      inherits "2.0.4"
+      setprototypeof "1.1.1"
+      statuses ">= 1.5.0 < 2"
+      toidentifier "1.0.0"
+  
+  http-parser-js@>=0.5.1:
+    version "0.5.3"
+    resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.3.tgz#01d2709c79d41698bb01d4decc5e9da4e4a033d9"
+    integrity sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg==
+  
+  http-proxy@^1.18.1:
+    version "1.18.1"
+    resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549"
+    integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==
+    dependencies:
+      eventemitter3 "^4.0.0"
+      follow-redirects "^1.0.0"
+      requires-port "^1.0.0"
+  
+  http-signature@~1.2.0:
+    version "1.2.0"
+    resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
+    integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=
+    dependencies:
+      assert-plus "^1.0.0"
+      jsprim "^1.2.2"
+      sshpk "^1.7.0"
+  
+  https-browserify@0.0.1:
+    version "0.0.1"
+    resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-0.0.1.tgz#3f91365cabe60b77ed0ebba24b454e3e09d95a82"
+    integrity sha1-P5E2XKvmC3ftDruiS0VOPgnZWoI=
+  
+  https-browserify@^1.0.0:
+    version "1.0.0"
+    resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73"
+    integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=
+  
+  https-proxy-agent@^2.2.1:
+    version "2.2.4"
+    resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b"
+    integrity sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==
+    dependencies:
+      agent-base "^4.3.0"
+      debug "^3.1.0"
+  
+  https-proxy-agent@^4.0.0:
+    version "4.0.0"
+    resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz#702b71fb5520a132a66de1f67541d9e62154d82b"
+    integrity sha512-zoDhWrkR3of1l9QAL8/scJZyLu8j/gBkcwcaQOZh7Gyh/+uJQzGVETdgT30akuwkpL8HTRfssqI3BZuV18teDg==
+    dependencies:
+      agent-base "5"
+      debug "4"
+  
+  human-signals@^2.1.0:
+    version "2.1.0"
+    resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0"
+    integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==
+  
+  iconv-lite@0.4.24, iconv-lite@~0.4.13:
+    version "0.4.24"
+    resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
+    integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
+    dependencies:
+      safer-buffer ">= 2.1.2 < 3"
+  
+  ieee754@^1.1.13:
+    version "1.2.1"
+    resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
+    integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
+  
+  ignore@^4.0.6:
+    version "4.0.6"
+    resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc"
+    integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==
+  
+  ignore@^5.1.4:
+    version "5.1.8"
+    resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57"
+    integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==
+  
+  immediate@~3.0.5:
+    version "3.0.6"
+    resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b"
+    integrity sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=
+  
+  import-fresh@^3.0.0, import-fresh@^3.2.1:
+    version "3.3.0"
+    resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b"
+    integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==
+    dependencies:
+      parent-module "^1.0.0"
+      resolve-from "^4.0.0"
+  
+  import-local@^3.0.2:
+    version "3.0.2"
+    resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.0.2.tgz#a8cfd0431d1de4a2199703d003e3e62364fa6db6"
+    integrity sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA==
+    dependencies:
+      pkg-dir "^4.2.0"
+      resolve-cwd "^3.0.0"
+  
+  imurmurhash@^0.1.4:
+    version "0.1.4"
+    resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
+    integrity sha1-khi5srkoojixPcT7a21XbyMUU+o=
+  
+  indent-string@^2.1.0:
+    version "2.1.0"
+    resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80"
+    integrity sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=
+    dependencies:
+      repeating "^2.0.0"
+  
+  inflight@^1.0.4:
+    version "1.0.6"
+    resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
+    integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=
+    dependencies:
+      once "^1.3.0"
+      wrappy "1"
+  
+  inherits@2, inherits@2.0.4, inherits@^2.0.0, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3:
+    version "2.0.4"
+    resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
+    integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
+  
+  inherits@2.0.1:
+    version "2.0.1"
+    resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1"
+    integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=
+  
+  inherits@2.0.3:
+    version "2.0.3"
+    resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
+    integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
+  
+  ini@^1.3.4:
+    version "1.3.8"
+    resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c"
+    integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==
+  
+  inline-source-map@~0.6.0:
+    version "0.6.2"
+    resolved "https://registry.yarnpkg.com/inline-source-map/-/inline-source-map-0.6.2.tgz#f9393471c18a79d1724f863fa38b586370ade2a5"
+    integrity sha1-+Tk0ccGKedFyT4Y/o4tYY3Ct4qU=
+    dependencies:
+      source-map "~0.5.3"
+  
+  interpret@^2.2.0:
+    version "2.2.0"
+    resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9"
+    integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==
+  
+  interpret@~1.1.0:
+    version "1.1.0"
+    resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614"
+    integrity sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=
+  
+  invert-kv@^2.0.0:
+    version "2.0.0"
+    resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02"
+    integrity sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==
+  
+  is-absolute@^1.0.0:
+    version "1.0.0"
+    resolved "https://registry.yarnpkg.com/is-absolute/-/is-absolute-1.0.0.tgz#395e1ae84b11f26ad1795e73c17378e48a301576"
+    integrity sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==
+    dependencies:
+      is-relative "^1.0.0"
+      is-windows "^1.0.1"
+  
+  is-accessor-descriptor@^0.1.6:
+    version "0.1.6"
+    resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6"
+    integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=
+    dependencies:
+      kind-of "^3.0.2"
+  
+  is-accessor-descriptor@^1.0.0:
+    version "1.0.0"
+    resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656"
+    integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==
+    dependencies:
+      kind-of "^6.0.0"
+  
+  is-alphabetical@^1.0.0:
+    version "1.0.4"
+    resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-1.0.4.tgz#9e7d6b94916be22153745d184c298cbf986a686d"
+    integrity sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==
+  
+  is-alphanumerical@^1.0.0:
+    version "1.0.4"
+    resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz#7eb9a2431f855f6b1ef1a78e326df515696c4dbf"
+    integrity sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==
+    dependencies:
+      is-alphabetical "^1.0.0"
+      is-decimal "^1.0.0"
+  
+  is-arguments@^1.0.4:
+    version "1.1.0"
+    resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.0.tgz#62353031dfbee07ceb34656a6bde59efecae8dd9"
+    integrity sha512-1Ij4lOMPl/xB5kBDn7I+b2ttPMKa8szhEIrXDuXQD/oe3HJLTLhqhgGspwgyGd6MOywBUqVvYicF72lkgDnIHg==
+    dependencies:
+      call-bind "^1.0.0"
+  
+  is-arrayish@^0.2.1:
+    version "0.2.1"
+    resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
+    integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=
+  
+  is-bigint@^1.0.1:
+    version "1.0.1"
+    resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.1.tgz#6923051dfcbc764278540b9ce0e6b3213aa5ebc2"
+    integrity sha512-J0ELF4yHFxHy0cmSxZuheDOz2luOdVvqjwmEcj8H/L1JHeuEDSDbeRP+Dk9kFVk5RTFzbucJ2Kb9F7ixY2QaCg==
+  
+  is-binary-path@~2.1.0:
+    version "2.1.0"
+    resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09"
+    integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==
+    dependencies:
+      binary-extensions "^2.0.0"
+  
+  is-boolean-object@^1.1.0:
+    version "1.1.0"
+    resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.0.tgz#e2aaad3a3a8fca34c28f6eee135b156ed2587ff0"
+    integrity sha512-a7Uprx8UtD+HWdyYwnD1+ExtTgqQtD2k/1yJgtXP6wnMm8byhkoTZRl+95LLThpzNZJ5aEvi46cdH+ayMFRwmA==
+    dependencies:
+      call-bind "^1.0.0"
+  
+  is-buffer@^1.1.4, is-buffer@^1.1.5:
+    version "1.1.6"
+    resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
+    integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
+  
+  is-callable@^1.1.4, is-callable@^1.2.3:
+    version "1.2.3"
+    resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.3.tgz#8b1e0500b73a1d76c70487636f368e519de8db8e"
+    integrity sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==
+  
+  is-core-module@^2.2.0:
+    version "2.2.0"
+    resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.2.0.tgz#97037ef3d52224d85163f5597b2b63d9afed981a"
+    integrity sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==
+    dependencies:
+      has "^1.0.3"
+  
+  is-data-descriptor@^0.1.4:
+    version "0.1.4"
+    resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56"
+    integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=
+    dependencies:
+      kind-of "^3.0.2"
+  
+  is-data-descriptor@^1.0.0:
+    version "1.0.0"
+    resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7"
+    integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==
+    dependencies:
+      kind-of "^6.0.0"
+  
+  is-date-object@^1.0.1:
+    version "1.0.2"
+    resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e"
+    integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==
+  
+  is-decimal@^1.0.0:
+    version "1.0.4"
+    resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.4.tgz#65a3a5958a1c5b63a706e1b333d7cd9f630d3fa5"
+    integrity sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==
+  
+  is-descriptor@^0.1.0:
+    version "0.1.6"
+    resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca"
+    integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==
+    dependencies:
+      is-accessor-descriptor "^0.1.6"
+      is-data-descriptor "^0.1.4"
+      kind-of "^5.0.0"
+  
+  is-descriptor@^1.0.0, is-descriptor@^1.0.2:
+    version "1.0.2"
+    resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec"
+    integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==
+    dependencies:
+      is-accessor-descriptor "^1.0.0"
+      is-data-descriptor "^1.0.0"
+      kind-of "^6.0.2"
+  
+  is-extendable@^0.1.0, is-extendable@^0.1.1:
+    version "0.1.1"
+    resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89"
+    integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=
+  
+  is-extendable@^1.0.1:
+    version "1.0.1"
+    resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4"
+    integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==
+    dependencies:
+      is-plain-object "^2.0.4"
+  
+  is-extglob@^2.1.0, is-extglob@^2.1.1:
+    version "2.1.1"
+    resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
+    integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=
+  
+  is-finite@^1.0.0:
+    version "1.1.0"
+    resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.1.0.tgz#904135c77fb42c0641d6aa1bcdbc4daa8da082f3"
+    integrity sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==
+  
+  is-fullwidth-code-point@^1.0.0:
+    version "1.0.0"
+    resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb"
+    integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs=
+    dependencies:
+      number-is-nan "^1.0.0"
+  
+  is-fullwidth-code-point@^2.0.0:
+    version "2.0.0"
+    resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
+    integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=
+  
+  is-fullwidth-code-point@^3.0.0:
+    version "3.0.0"
+    resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
+    integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
+  
+  is-generator-function@^1.0.7:
+    version "1.0.8"
+    resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.8.tgz#dfb5c2b120e02b0a8d9d2c6806cd5621aa922f7b"
+    integrity sha512-2Omr/twNtufVZFr1GhxjOMFPAj2sjc/dKaIqBhvo4qciXfJmITGH6ZGd8eZYNHza8t1y0e01AuqRhJwfWp26WQ==
+  
+  is-glob@^3.1.0:
+    version "3.1.0"
+    resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a"
+    integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=
+    dependencies:
+      is-extglob "^2.1.0"
+  
+  is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1:
+    version "4.0.1"
+    resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc"
+    integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==
+    dependencies:
+      is-extglob "^2.1.1"
+  
+  is-hexadecimal@^1.0.0:
+    version "1.0.4"
+    resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz#cc35c97588da4bd49a8eedd6bc4082d44dcb23a7"
+    integrity sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==
+  
+  is-nan@^1.2.1:
+    version "1.3.2"
+    resolved "https://registry.yarnpkg.com/is-nan/-/is-nan-1.3.2.tgz#043a54adea31748b55b6cd4e09aadafa69bd9e1d"
+    integrity sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==
+    dependencies:
+      call-bind "^1.0.0"
+      define-properties "^1.1.3"
+  
+  is-negative-zero@^2.0.1:
+    version "2.0.1"
+    resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24"
+    integrity sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==
+  
+  is-number-like@^1.0.3:
+    version "1.0.8"
+    resolved "https://registry.yarnpkg.com/is-number-like/-/is-number-like-1.0.8.tgz#2e129620b50891042e44e9bbbb30593e75cfbbe3"
+    integrity sha512-6rZi3ezCyFcn5L71ywzz2bS5b2Igl1En3eTlZlvKjpz1n3IZLAYMbKYAIQgFmEu0GENg92ziU/faEOA/aixjbA==
+    dependencies:
+      lodash.isfinite "^3.3.2"
+  
+  is-number-object@^1.0.4:
+    version "1.0.4"
+    resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.4.tgz#36ac95e741cf18b283fc1ddf5e83da798e3ec197"
+    integrity sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==
+  
+  is-number@^3.0.0:
+    version "3.0.0"
+    resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195"
+    integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=
+    dependencies:
+      kind-of "^3.0.2"
+  
+  is-number@^7.0.0:
+    version "7.0.0"
+    resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
+    integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
+  
+  is-path-cwd@^1.0.0:
+    version "1.0.0"
+    resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d"
+    integrity sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=
+  
+  is-path-in-cwd@^1.0.0:
+    version "1.0.1"
+    resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz#5ac48b345ef675339bd6c7a48a912110b241cf52"
+    integrity sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==
+    dependencies:
+      is-path-inside "^1.0.0"
+  
+  is-path-inside@^1.0.0:
+    version "1.0.1"
+    resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036"
+    integrity sha1-jvW33lBDej/cprToZe96pVy0gDY=
+    dependencies:
+      path-is-inside "^1.0.1"
+  
+  is-plain-obj@^1.1.0:
+    version "1.1.0"
+    resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e"
+    integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4=
+  
+  is-plain-object@^2.0.3, is-plain-object@^2.0.4:
+    version "2.0.4"
+    resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677"
+    integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==
+    dependencies:
+      isobject "^3.0.1"
+  
+  is-regex@^1.1.2:
+    version "1.1.2"
+    resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.2.tgz#81c8ebde4db142f2cf1c53fc86d6a45788266251"
+    integrity sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==
+    dependencies:
+      call-bind "^1.0.2"
+      has-symbols "^1.0.1"
+  
+  is-relative@^1.0.0:
+    version "1.0.0"
+    resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-1.0.0.tgz#a1bb6935ce8c5dba1e8b9754b9b2dcc020e2260d"
+    integrity sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==
+    dependencies:
+      is-unc-path "^1.0.0"
+  
+  is-stream@^1.1.0:
+    version "1.1.0"
+    resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
+    integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ=
+  
+  is-stream@^2.0.0:
+    version "2.0.0"
+    resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3"
+    integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==
+  
+  is-string@^1.0.5:
+    version "1.0.5"
+    resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.5.tgz#40493ed198ef3ff477b8c7f92f644ec82a5cd3a6"
+    integrity sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==
+  
+  is-symbol@^1.0.2, is-symbol@^1.0.3:
+    version "1.0.3"
+    resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937"
+    integrity sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==
+    dependencies:
+      has-symbols "^1.0.1"
+  
+  is-typed-array@^1.1.3:
+    version "1.1.5"
+    resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.5.tgz#f32e6e096455e329eb7b423862456aa213f0eb4e"
+    integrity sha512-S+GRDgJlR3PyEbsX/Fobd9cqpZBuvUS+8asRqYDMLCb2qMzt1oz5m5oxQCxOgUDxiWsOVNi4yaF+/uvdlHlYug==
+    dependencies:
+      available-typed-arrays "^1.0.2"
+      call-bind "^1.0.2"
+      es-abstract "^1.18.0-next.2"
+      foreach "^2.0.5"
+      has-symbols "^1.0.1"
+  
+  is-typedarray@~1.0.0:
+    version "1.0.0"
+    resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
+    integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
+  
+  is-unc-path@^1.0.0:
+    version "1.0.0"
+    resolved "https://registry.yarnpkg.com/is-unc-path/-/is-unc-path-1.0.0.tgz#d731e8898ed090a12c352ad2eaed5095ad322c9d"
+    integrity sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==
+    dependencies:
+      unc-path-regex "^0.1.2"
+  
+  is-utf8@^0.2.0:
+    version "0.2.1"
+    resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
+    integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=
+  
+  is-whitespace-character@^1.0.0:
+    version "1.0.4"
+    resolved "https://registry.yarnpkg.com/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz#0858edd94a95594c7c9dd0b5c174ec6e45ee4aa7"
+    integrity sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w==
+  
+  is-windows@^1.0.1, is-windows@^1.0.2:
+    version "1.0.2"
+    resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d"
+    integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==
+  
+  is-word-character@^1.0.0:
+    version "1.0.4"
+    resolved "https://registry.yarnpkg.com/is-word-character/-/is-word-character-1.0.4.tgz#ce0e73216f98599060592f62ff31354ddbeb0230"
+    integrity sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA==
+  
+  is-wsl@^1.1.0:
+    version "1.1.0"
+    resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d"
+    integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=
+  
+  isarray@1.0.0, isarray@~1.0.0:
+    version "1.0.0"
+    resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
+    integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
+  
+  isbinaryfile@^4.0.8:
+    version "4.0.8"
+    resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-4.0.8.tgz#5d34b94865bd4946633ecc78a026fc76c5b11fcf"
+    integrity sha512-53h6XFniq77YdW+spoRrebh0mnmTxRPTlcuIArO57lmMdq4uBKFKaeTjnb92oYWrSn/LVL+LT+Hap2tFQj8V+w==
+  
+  isexe@^2.0.0:
+    version "2.0.0"
+    resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
+    integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=
+  
+  isobject@^2.0.0:
+    version "2.1.0"
+    resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89"
+    integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=
+    dependencies:
+      isarray "1.0.0"
+  
+  isobject@^3.0.0, isobject@^3.0.1:
+    version "3.0.1"
+    resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df"
+    integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8=
+  
+  isstream@~0.1.2:
+    version "0.1.2"
+    resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
+    integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
+  
+  istanbul@0.4.5, istanbul@^0.4.0:
+    version "0.4.5"
+    resolved "https://registry.yarnpkg.com/istanbul/-/istanbul-0.4.5.tgz#65c7d73d4c4da84d4f3ac310b918fb0b8033733b"
+    integrity sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=
+    dependencies:
+      abbrev "1.0.x"
+      async "1.x"
+      escodegen "1.8.x"
+      esprima "2.7.x"
+      glob "^5.0.15"
+      handlebars "^4.0.1"
+      js-yaml "3.x"
+      mkdirp "0.5.x"
+      nopt "3.x"
+      once "1.x"
+      resolve "1.1.x"
+      supports-color "^3.1.0"
+      which "^1.1.1"
+      wordwrap "^1.0.0"
+  
+  jasmine-core@^3.5.0, jasmine-core@^3.6.0:
+    version "3.7.1"
+    resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-3.7.1.tgz#0401327f6249eac993d47bbfa18d4e8efacfb561"
+    integrity sha512-DH3oYDS/AUvvr22+xUBW62m1Xoy7tUlY1tsxKEJvl5JeJ7q8zd1K5bUwiOxdH+erj6l2vAMM3hV25Xs9/WrmuQ==
+  
+  jasmine-core@~2.8.0:
+    version "2.8.0"
+    resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-2.8.0.tgz#bcc979ae1f9fd05701e45e52e65d3a5d63f1a24e"
+    integrity sha1-vMl5rh+f0FcB5F5S5l06XWPxok4=
+  
+  jasmine@2.8.0:
+    version "2.8.0"
+    resolved "https://registry.yarnpkg.com/jasmine/-/jasmine-2.8.0.tgz#6b089c0a11576b1f16df11b80146d91d4e8b8a3e"
+    integrity sha1-awicChFXax8W3xG4AUbZHU6Lij4=
+    dependencies:
+      exit "^0.1.2"
+      glob "^7.0.6"
+      jasmine-core "~2.8.0"
+  
+  jasminewd2@^2.1.0:
+    version "2.2.0"
+    resolved "https://registry.yarnpkg.com/jasminewd2/-/jasminewd2-2.2.0.tgz#e37cf0b17f199cce23bea71b2039395246b4ec4e"
+    integrity sha1-43zwsX8ZnM4jvqcbIDk5Uka07E4=
+  
+  jest-worker@^26.6.2:
+    version "26.6.2"
+    resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed"
+    integrity sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==
+    dependencies:
+      "@types/node" "*"
+      merge-stream "^2.0.0"
+      supports-color "^7.0.0"
+  
+  js-tokens@^4.0.0:
+    version "4.0.0"
+    resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
+    integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
+  
+  js-yaml@3.x, js-yaml@^3.13.1, js-yaml@~3.14.0:
+    version "3.14.1"
+    resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537"
+    integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==
+    dependencies:
+      argparse "^1.0.7"
+      esprima "^4.0.0"
+  
+  jsbn@~0.1.0:
+    version "0.1.1"
+    resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
+    integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM=
+  
+  json-parse-better-errors@^1.0.2:
+    version "1.0.2"
+    resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9"
+    integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==
+  
+  json-schema-traverse@^0.4.1:
+    version "0.4.1"
+    resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
+    integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
+  
+  json-schema-traverse@^1.0.0:
+    version "1.0.0"
+    resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2"
+    integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==
+  
+  json-schema@0.2.3:
+    version "0.2.3"
+    resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
+    integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=
+  
+  json-stable-stringify-without-jsonify@^1.0.1:
+    version "1.0.1"
+    resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651"
+    integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=
+  
+  json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1:
+    version "5.0.1"
+    resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
+    integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=
+  
+  json5@^2.1.2:
+    version "2.2.0"
+    resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3"
+    integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==
+    dependencies:
+      minimist "^1.2.5"
+  
+  jsonfile@^4.0.0:
+    version "4.0.0"
+    resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"
+    integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=
+    optionalDependencies:
+      graceful-fs "^4.1.6"
+  
+  jsonfile@^6.0.1:
+    version "6.1.0"
+    resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae"
+    integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==
+    dependencies:
+      universalify "^2.0.0"
+    optionalDependencies:
+      graceful-fs "^4.1.6"
+  
+  jsprim@^1.2.2:
+    version "1.4.1"
+    resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2"
+    integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=
+    dependencies:
+      assert-plus "1.0.0"
+      extsprintf "1.3.0"
+      json-schema "0.2.3"
+      verror "1.10.0"
+  
+  jszip@^3.1.3:
+    version "3.7.1"
+    resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.7.1.tgz#bd63401221c15625a1228c556ca8a68da6fda3d9"
+    integrity sha512-ghL0tz1XG9ZEmRMcEN2vt7xabrDdqHHeykgARpmZ0BiIctWxM47Vt63ZO2dnp4QYt/xJVLLy5Zv1l/xRdh2byg==
+    dependencies:
+      lie "~3.3.0"
+      pako "~1.0.2"
+      readable-stream "~2.3.6"
+      set-immediate-shim "~1.0.1"
+  
+  karma-chrome-launcher@^3.1.0:
+    version "3.1.0"
+    resolved "https://registry.yarnpkg.com/karma-chrome-launcher/-/karma-chrome-launcher-3.1.0.tgz#805a586799a4d05f4e54f72a204979f3f3066738"
+    integrity sha512-3dPs/n7vgz1rxxtynpzZTvb9y/GIaW8xjAwcIGttLbycqoFtI7yo1NGnQi6oFTherRE+GIhCAHZC4vEqWGhNvg==
+    dependencies:
+      which "^1.2.1"
+  
+  karma-cli@^2.0.0:
+    version "2.0.0"
+    resolved "https://registry.yarnpkg.com/karma-cli/-/karma-cli-2.0.0.tgz#481548d28661af4cc68f3d8e09708f17d2cba931"
+    integrity sha512-1Kb28UILg1ZsfqQmeELbPzuEb5C6GZJfVIk0qOr8LNYQuYWmAaqP16WpbpKEjhejDrDYyYOwwJXSZO6u7q5Pvw==
+    dependencies:
+      resolve "^1.3.3"
+  
+  karma-coverage@^1.1.1:
+    version "1.1.2"
+    resolved "https://registry.yarnpkg.com/karma-coverage/-/karma-coverage-1.1.2.tgz#cc09dceb589a83101aca5fe70c287645ef387689"
+    integrity sha512-eQawj4Cl3z/CjxslYy9ariU4uDh7cCNFZHNWXWRpl0pNeblY/4wHR7M7boTYXWrn9bY0z2pZmr11eKje/S/hIw==
+    dependencies:
+      dateformat "^1.0.6"
+      istanbul "^0.4.0"
+      lodash "^4.17.0"
+      minimatch "^3.0.0"
+      source-map "^0.5.1"
+  
+  karma-jasmine@^4.0.1:
+    version "4.0.1"
+    resolved "https://registry.yarnpkg.com/karma-jasmine/-/karma-jasmine-4.0.1.tgz#b99e073b6d99a5196fc4bffc121b89313b0abd82"
+    integrity sha512-h8XDAhTiZjJKzfkoO1laMH+zfNlra+dEQHUAjpn5JV1zCPtOIVWGQjLBrqhnzQa/hrU2XrZwSyBa6XjEBzfXzw==
+    dependencies:
+      jasmine-core "^3.6.0"
+  
+  karma-typescript@4.1.1:
+    version "4.1.1"
+    resolved "https://registry.yarnpkg.com/karma-typescript/-/karma-typescript-4.1.1.tgz#2b37164e31f23397cf35774fb436e3a7e7f78a29"
+    integrity sha512-NiGt3Lh8pxKY6hSW4mBV7X45zfB+EA4ezVMNN/vnzLvN+du0UoEc8lTAhrD/DMrjKP3wDlpabku652svRyguXg==
+    dependencies:
+      acorn "^6.0.5"
+      acorn-walk "^6.1.1"
+      assert "^2.0.0"
+      async "^3.0.1"
+      browser-resolve "^1.11.3"
+      browserify-zlib "^0.2.0"
+      buffer "^5.2.1"
+      combine-source-map "^0.8.0"
+      console-browserify "^1.1.0"
+      constants-browserify "^1.0.0"
+      convert-source-map "^1.6.0"
+      crypto-browserify "^3.12.0"
+      diff "^4.0.1"
+      domain-browser "^1.2.0"
+      events "^3.0.0"
+      glob "^7.1.3"
+      https-browserify "^1.0.0"
+      istanbul "0.4.5"
+      json-stringify-safe "^5.0.1"
+      karma-coverage "^1.1.1"
+      lodash "^4.17.11"
+      log4js "^4.0.1"
+      minimatch "^3.0.4"
+      os-browserify "^0.3.0"
+      pad "^3.2.0"
+      path-browserify "^1.0.0"
+      process "^0.11.10"
+      punycode "^2.1.1"
+      querystring-es3 "^0.2.1"
+      readable-stream "^3.1.1"
+      remap-istanbul "^0.13.0"
+      source-map "^0.7.3"
+      stream-browserify "^2.0.2"
+      stream-http "^3.0.0"
+      string_decoder "^1.2.0"
+      timers-browserify "^2.0.10"
+      tmp "^0.1.0"
+      tty-browserify "^0.0.1"
+      url "^0.11.0"
+      util "^0.12.0"
+      vm-browserify "1.1.0"
+  
+  karma@^6:
+    version "6.3.14"
+    resolved "https://registry.yarnpkg.com/karma/-/karma-6.3.14.tgz#1ed57a489249b9260bc604325ae333766d4cddc9"
+    integrity sha512-SDFoU5F4LdosEiUVWUDRPCV/C1zQRNtIakx7rWkigf7R4sxGADlSEeOma4S1f/js7YAzvqLW92ByoiQptg+8oQ==
+    dependencies:
+      body-parser "^1.19.0"
+      braces "^3.0.2"
+      chokidar "^3.5.1"
+      colors "1.4.0"
+      connect "^3.7.0"
+      di "^0.0.1"
+      dom-serialize "^2.2.1"
+      glob "^7.1.7"
+      graceful-fs "^4.2.6"
+      http-proxy "^1.18.1"
+      isbinaryfile "^4.0.8"
+      lodash "^4.17.21"
+      log4js "^6.4.1"
+      mime "^2.5.2"
+      minimatch "^3.0.4"
+      qjobs "^1.2.0"
+      range-parser "^1.2.1"
+      rimraf "^3.0.2"
+      socket.io "^4.2.0"
+      source-map "^0.6.1"
+      tmp "^0.2.1"
+      ua-parser-js "^0.7.30"
+      yargs "^16.1.1"
+  
+  kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0:
+    version "3.2.2"
+    resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64"
+    integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=
+    dependencies:
+      is-buffer "^1.1.5"
+  
+  kind-of@^4.0.0:
+    version "4.0.0"
+    resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57"
+    integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc=
+    dependencies:
+      is-buffer "^1.1.5"
+  
+  kind-of@^5.0.0:
+    version "5.1.0"
+    resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d"
+    integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==
+  
+  kind-of@^6.0.0, kind-of@^6.0.2:
+    version "6.0.3"
+    resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd"
+    integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==
+  
+  lcid@^2.0.0:
+    version "2.0.0"
+    resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf"
+    integrity sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==
+    dependencies:
+      invert-kv "^2.0.0"
+  
+  lcov-parse@^1.0.0:
+    version "1.0.0"
+    resolved "https://registry.yarnpkg.com/lcov-parse/-/lcov-parse-1.0.0.tgz#eb0d46b54111ebc561acb4c408ef9363bdc8f7e0"
+    integrity sha1-6w1GtUER68VhrLTECO+TY73I9+A=
+  
+  levn@^0.4.1:
+    version "0.4.1"
+    resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade"
+    integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==
+    dependencies:
+      prelude-ls "^1.2.1"
+      type-check "~0.4.0"
+  
+  levn@~0.3.0:
+    version "0.3.0"
+    resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee"
+    integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=
+    dependencies:
+      prelude-ls "~1.1.2"
+      type-check "~0.3.2"
+  
+  lie@~3.3.0:
+    version "3.3.0"
+    resolved "https://registry.yarnpkg.com/lie/-/lie-3.3.0.tgz#dcf82dee545f46074daf200c7c1c5a08e0f40f6a"
+    integrity sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==
+    dependencies:
+      immediate "~3.0.5"
+  
+  liftoff@~2.5.0:
+    version "2.5.0"
+    resolved "https://registry.yarnpkg.com/liftoff/-/liftoff-2.5.0.tgz#2009291bb31cea861bbf10a7c15a28caf75c31ec"
+    integrity sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=
+    dependencies:
+      extend "^3.0.0"
+      findup-sync "^2.0.0"
+      fined "^1.0.1"
+      flagged-respawn "^1.0.0"
+      is-plain-object "^2.0.4"
+      object.map "^1.0.0"
+      rechoir "^0.6.2"
+      resolve "^1.1.7"
+  
+  liftup@~3.0.1:
+    version "3.0.1"
+    resolved "https://registry.yarnpkg.com/liftup/-/liftup-3.0.1.tgz#1cb81aff0f368464ed3a5f1a7286372d6b1a60ce"
+    integrity sha512-yRHaiQDizWSzoXk3APcA71eOI/UuhEkNN9DiW2Tt44mhYzX4joFoCZlxsSOF7RyeLlfqzFLQI1ngFq3ggMPhOw==
+    dependencies:
+      extend "^3.0.2"
+      findup-sync "^4.0.0"
+      fined "^1.2.0"
+      flagged-respawn "^1.0.1"
+      is-plain-object "^2.0.4"
+      object.map "^1.0.1"
+      rechoir "^0.7.0"
+      resolve "^1.19.0"
+  
+  livereload-js@^2.3.0:
+    version "2.4.0"
+    resolved "https://registry.yarnpkg.com/livereload-js/-/livereload-js-2.4.0.tgz#447c31cf1ea9ab52fc20db615c5ddf678f78009c"
+    integrity sha512-XPQH8Z2GDP/Hwz2PCDrh2mth4yFejwA1OZ/81Ti3LgKyhDcEjsSsqFWZojHG0va/duGd+WyosY7eXLDoOyqcPw==
+  
+  load-json-file@^1.0.0:
+    version "1.1.0"
+    resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"
+    integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=
+    dependencies:
+      graceful-fs "^4.1.2"
+      parse-json "^2.2.0"
+      pify "^2.0.0"
+      pinkie-promise "^2.0.0"
+      strip-bom "^2.0.0"
+  
+  loader-runner@^4.2.0:
+    version "4.2.0"
+    resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.2.0.tgz#d7022380d66d14c5fb1d496b89864ebcfd478384"
+    integrity sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==
+  
+  loader-utils@^2.0.0:
+    version "2.0.0"
+    resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.0.tgz#e4cace5b816d425a166b5f097e10cd12b36064b0"
+    integrity sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==
+    dependencies:
+      big.js "^5.2.2"
+      emojis-list "^3.0.0"
+      json5 "^2.1.2"
+  
+  locate-path@^3.0.0:
+    version "3.0.0"
+    resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e"
+    integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==
+    dependencies:
+      p-locate "^3.0.0"
+      path-exists "^3.0.0"
+  
+  locate-path@^5.0.0:
+    version "5.0.0"
+    resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0"
+    integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==
+    dependencies:
+      p-locate "^4.1.0"
+  
+  lodash.clonedeep@^4.5.0:
+    version "4.5.0"
+    resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef"
+    integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=
+  
+  lodash.flatten@^4.4.0:
+    version "4.4.0"
+    resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f"
+    integrity sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=
+  
+  lodash.isfinite@^3.3.2:
+    version "3.3.2"
+    resolved "https://registry.yarnpkg.com/lodash.isfinite/-/lodash.isfinite-3.3.2.tgz#fb89b65a9a80281833f0b7478b3a5104f898ebb3"
+    integrity sha1-+4m2WpqAKBgz8LdHizpRBPiY67M=
+  
+  lodash.memoize@~3.0.3:
+    version "3.0.4"
+    resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-3.0.4.tgz#2dcbd2c287cbc0a55cc42328bd0c736150d53e3f"
+    integrity sha1-LcvSwofLwKVcxCMovQxzYVDVPj8=
+  
+  lodash.truncate@^4.4.2:
+    version "4.4.2"
+    resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193"
+    integrity sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=
+  
+  lodash@^4.17.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.21, lodash@~4.17.10, lodash@~4.17.19, lodash@~4.17.20:
+    version "4.17.21"
+    resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
+    integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
+  
+  log-driver@^1.2.7:
+    version "1.2.7"
+    resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.7.tgz#63b95021f0702fedfa2c9bb0a24e7797d71871d8"
+    integrity sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==
+  
+  log4js@^4.0.1:
+    version "4.5.1"
+    resolved "https://registry.yarnpkg.com/log4js/-/log4js-4.5.1.tgz#e543625e97d9e6f3e6e7c9fc196dd6ab2cae30b5"
+    integrity sha512-EEEgFcE9bLgaYUKuozyFfytQM2wDHtXn4tAN41pkaxpNjAykv11GVdeI4tHtmPWW4Xrgh9R/2d7XYghDVjbKKw==
+    dependencies:
+      date-format "^2.0.0"
+      debug "^4.1.1"
+      flatted "^2.0.0"
+      rfdc "^1.1.4"
+      streamroller "^1.0.6"
+  
+  log4js@^6.4.1:
+    version "6.4.1"
+    resolved "https://registry.yarnpkg.com/log4js/-/log4js-6.4.1.tgz#9d3a8bf2c31c1e213fe3fc398a6053f7a2bc53e8"
+    integrity sha512-iUiYnXqAmNKiIZ1XSAitQ4TmNs8CdZYTAWINARF3LjnsLN8tY5m0vRwd6uuWj/yNY0YHxeZodnbmxKFUOM2rMg==
+    dependencies:
+      date-format "^4.0.3"
+      debug "^4.3.3"
+      flatted "^3.2.4"
+      rfdc "^1.3.0"
+      streamroller "^3.0.2"
+  
+  loud-rejection@^1.0.0:
+    version "1.6.0"
+    resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f"
+    integrity sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=
+    dependencies:
+      currently-unhandled "^0.4.1"
+      signal-exit "^3.0.0"
+  
+  lru-cache@^6.0.0:
+    version "6.0.0"
+    resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
+    integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==
+    dependencies:
+      yallist "^4.0.0"
+  
+  make-iterator@^1.0.0:
+    version "1.0.1"
+    resolved "https://registry.yarnpkg.com/make-iterator/-/make-iterator-1.0.1.tgz#29b33f312aa8f547c4a5e490f56afcec99133ad6"
+    integrity sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==
+    dependencies:
+      kind-of "^6.0.2"
+  
+  map-age-cleaner@^0.1.1:
+    version "0.1.3"
+    resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a"
+    integrity sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==
+    dependencies:
+      p-defer "^1.0.0"
+  
+  map-cache@^0.2.0, map-cache@^0.2.2:
+    version "0.2.2"
+    resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf"
+    integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=
+  
+  map-obj@^1.0.0, map-obj@^1.0.1:
+    version "1.0.1"
+    resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d"
+    integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=
+  
+  map-visit@^1.0.0:
+    version "1.0.0"
+    resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f"
+    integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=
+    dependencies:
+      object-visit "^1.0.0"
+  
+  markdown-escapes@^1.0.0:
+    version "1.0.4"
+    resolved "https://registry.yarnpkg.com/markdown-escapes/-/markdown-escapes-1.0.4.tgz#c95415ef451499d7602b91095f3c8e8975f78535"
+    integrity sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg==
+  
+  maxmin@^2.1.0:
+    version "2.1.0"
+    resolved "https://registry.yarnpkg.com/maxmin/-/maxmin-2.1.0.tgz#4d3b220903d95eee7eb7ac7fa864e72dc09a3166"
+    integrity sha1-TTsiCQPZXu5+t6x/qGTnLcCaMWY=
+    dependencies:
+      chalk "^1.0.0"
+      figures "^1.0.1"
+      gzip-size "^3.0.0"
+      pretty-bytes "^3.0.0"
+  
+  md5.js@^1.3.4:
+    version "1.3.5"
+    resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f"
+    integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==
+    dependencies:
+      hash-base "^3.0.0"
+      inherits "^2.0.1"
+      safe-buffer "^5.1.2"
+  
+  media-typer@0.3.0:
+    version "0.3.0"
+    resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
+    integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=
+  
+  mem@^4.0.0:
+    version "4.3.0"
+    resolved "https://registry.yarnpkg.com/mem/-/mem-4.3.0.tgz#461af497bc4ae09608cdb2e60eefb69bff744178"
+    integrity sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==
+    dependencies:
+      map-age-cleaner "^0.1.1"
+      mimic-fn "^2.0.0"
+      p-is-promise "^2.0.0"
+  
+  memory-fs@^0.5.0:
+    version "0.5.0"
+    resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.5.0.tgz#324c01288b88652966d161db77838720845a8e3c"
+    integrity sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==
+    dependencies:
+      errno "^0.1.3"
+      readable-stream "^2.0.1"
+  
+  meow@^3.3.0:
+    version "3.7.0"
+    resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb"
+    integrity sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=
+    dependencies:
+      camelcase-keys "^2.0.0"
+      decamelize "^1.1.2"
+      loud-rejection "^1.0.0"
+      map-obj "^1.0.1"
+      minimist "^1.1.3"
+      normalize-package-data "^2.3.4"
+      object-assign "^4.0.1"
+      read-pkg-up "^1.0.1"
+      redent "^1.0.0"
+      trim-newlines "^1.0.0"
+  
+  merge-stream@^2.0.0:
+    version "2.0.0"
+    resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
+    integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==
+  
+  merge2@^1.3.0:
+    version "1.4.1"
+    resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
+    integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
+  
+  micromatch@^3.0.4:
+    version "3.1.10"
+    resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23"
+    integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==
+    dependencies:
+      arr-diff "^4.0.0"
+      array-unique "^0.3.2"
+      braces "^2.3.1"
+      define-property "^2.0.2"
+      extend-shallow "^3.0.2"
+      extglob "^2.0.4"
+      fragment-cache "^0.2.1"
+      kind-of "^6.0.2"
+      nanomatch "^1.2.9"
+      object.pick "^1.3.0"
+      regex-not "^1.0.0"
+      snapdragon "^0.8.1"
+      to-regex "^3.0.2"
+  
+  micromatch@^4.0.0, micromatch@^4.0.2:
+    version "4.0.4"
+    resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9"
+    integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==
+    dependencies:
+      braces "^3.0.1"
+      picomatch "^2.2.3"
+  
+  miller-rabin@^4.0.0:
+    version "4.0.1"
+    resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d"
+    integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==
+    dependencies:
+      bn.js "^4.0.0"
+      brorand "^1.0.1"
+  
+  mime-db@1.47.0:
+    version "1.47.0"
+    resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.47.0.tgz#8cb313e59965d3c05cfbf898915a267af46a335c"
+    integrity sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==
+  
+  mime-types@^2.1.12, mime-types@^2.1.27, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24:
+    version "2.1.30"
+    resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.30.tgz#6e7be8b4c479825f85ed6326695db73f9305d62d"
+    integrity sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==
+    dependencies:
+      mime-db "1.47.0"
+  
+  mime@1.6.0:
+    version "1.6.0"
+    resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
+    integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
+  
+  mime@^2.5.2:
+    version "2.6.0"
+    resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367"
+    integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==
+  
+  mimic-fn@^2.0.0, mimic-fn@^2.1.0:
+    version "2.1.0"
+    resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
+    integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
+  
+  minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1:
+    version "1.0.1"
+    resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7"
+    integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==
+  
+  minimalistic-crypto-utils@^1.0.1:
+    version "1.0.1"
+    resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a"
+    integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=
+  
+  "minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.4, minimatch@~3.0.2, minimatch@~3.0.4:
+    version "3.0.4"
+    resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
+    integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
+    dependencies:
+      brace-expansion "^1.1.7"
+  
+  minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5, minimist@~1.2.0:
+    version "1.2.5"
+    resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
+    integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
+  
+  mixin-deep@^1.2.0:
+    version "1.3.2"
+    resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566"
+    integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==
+    dependencies:
+      for-in "^1.0.2"
+      is-extendable "^1.0.1"
+  
+  mkdirp-classic@^0.5.2:
+    version "0.5.3"
+    resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113"
+    integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==
+  
+  mkdirp@0.5.x:
+    version "0.5.5"
+    resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def"
+    integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==
+    dependencies:
+      minimist "^1.2.5"
+  
+  mkdirp@~1.0.4:
+    version "1.0.4"
+    resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
+    integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
+  
+  morgan@^1.10.0:
+    version "1.10.0"
+    resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.10.0.tgz#091778abc1fc47cd3509824653dae1faab6b17d7"
+    integrity sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==
+    dependencies:
+      basic-auth "~2.0.1"
+      debug "2.6.9"
+      depd "~2.0.0"
+      on-finished "~2.3.0"
+      on-headers "~1.0.2"
+  
+  ms@2.0.0:
+    version "2.0.0"
+    resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
+    integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
+  
+  ms@2.1.1:
+    version "2.1.1"
+    resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
+    integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
+  
+  ms@2.1.2:
+    version "2.1.2"
+    resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
+    integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
+  
+  ms@^2.1.1:
+    version "2.1.3"
+    resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
+    integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
+  
+  nanomatch@^1.2.9:
+    version "1.2.13"
+    resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119"
+    integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==
+    dependencies:
+      arr-diff "^4.0.0"
+      array-unique "^0.3.2"
+      define-property "^2.0.2"
+      extend-shallow "^3.0.2"
+      fragment-cache "^0.2.1"
+      is-windows "^1.0.2"
+      kind-of "^6.0.2"
+      object.pick "^1.3.0"
+      regex-not "^1.0.0"
+      snapdragon "^0.8.1"
+      to-regex "^3.0.1"
+  
+  natural-compare@^1.4.0:
+    version "1.4.0"
+    resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
+    integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=
+  
+  negotiator@0.6.2:
+    version "0.6.2"
+    resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb"
+    integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==
+  
+  neo-async@^2.6.0, neo-async@^2.6.2:
+    version "2.6.2"
+    resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f"
+    integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==
+  
+  nice-try@^1.0.4:
+    version "1.0.5"
+    resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
+    integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
+  
+  node-fetch@^2.6.1:
+    version "2.6.7"
+    resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad"
+    integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==
+    dependencies:
+      whatwg-url "^5.0.0"
+  
+  node-http2@^4.0.1:
+    version "4.0.1"
+    resolved "https://registry.yarnpkg.com/node-http2/-/node-http2-4.0.1.tgz#164ff53b5dd22c84f0af142b877c5eaeb6809959"
+    integrity sha1-Fk/1O13SLITwrxQrh3xerraAmVk=
+    dependencies:
+      assert "1.4.1"
+      events "1.1.1"
+      https-browserify "0.0.1"
+      setimmediate "^1.0.5"
+      stream-browserify "2.0.1"
+      timers-browserify "2.0.2"
+      url "^0.11.0"
+      websocket-stream "^5.0.1"
+  
+  node-releases@^1.1.71:
+    version "1.1.72"
+    resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.72.tgz#14802ab6b1039a79a0c7d662b610a5bbd76eacbe"
+    integrity sha512-LLUo+PpH3dU6XizX3iVoubUNheF/owjXCZZ5yACDxNnPtgFuludV1ZL3ayK1kVep42Rmm0+R9/Y60NQbZ2bifw==
+  
+  nopt@3.x, nopt@~3.0.6:
+    version "3.0.6"
+    resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9"
+    integrity sha1-xkZdvwirzU2zWTF/eaxopkayj/k=
+    dependencies:
+      abbrev "1"
+  
+  nopt@~4.0.1:
+    version "4.0.3"
+    resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.3.tgz#a375cad9d02fd921278d954c2254d5aa57e15e48"
+    integrity sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==
+    dependencies:
+      abbrev "1"
+      osenv "^0.1.4"
+  
+  normalize-package-data@^2.3.2, normalize-package-data@^2.3.4:
+    version "2.5.0"
+    resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8"
+    integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==
+    dependencies:
+      hosted-git-info "^2.1.4"
+      resolve "^1.10.0"
+      semver "2 || 3 || 4 || 5"
+      validate-npm-package-license "^3.0.1"
+  
+  normalize-path@^3.0.0, normalize-path@~3.0.0:
+    version "3.0.0"
+    resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
+    integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
+  
+  npm-run-path@^2.0.0:
+    version "2.0.2"
+    resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f"
+    integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=
+    dependencies:
+      path-key "^2.0.0"
+  
+  npm-run-path@^4.0.1:
+    version "4.0.1"
+    resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea"
+    integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==
+    dependencies:
+      path-key "^3.0.0"
+  
+  number-is-nan@^1.0.0:
+    version "1.0.1"
+    resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
+    integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=
+  
+  oauth-sign@~0.9.0:
+    version "0.9.0"
+    resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
+    integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
+  
+  object-assign@^4, object-assign@^4.0.1, object-assign@^4.1.0:
+    version "4.1.1"
+    resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
+    integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
+  
+  object-copy@^0.1.0:
+    version "0.1.0"
+    resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c"
+    integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw=
+    dependencies:
+      copy-descriptor "^0.1.0"
+      define-property "^0.2.5"
+      kind-of "^3.0.3"
+  
+  object-inspect@^1.9.0:
+    version "1.9.0"
+    resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.9.0.tgz#c90521d74e1127b67266ded3394ad6116986533a"
+    integrity sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw==
+  
+  object-is@^1.0.1:
+    version "1.1.5"
+    resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac"
+    integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==
+    dependencies:
+      call-bind "^1.0.2"
+      define-properties "^1.1.3"
+  
+  object-keys@^1.0.12, object-keys@^1.1.1:
+    version "1.1.1"
+    resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
+    integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==
+  
+  object-visit@^1.0.0:
+    version "1.0.1"
+    resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb"
+    integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=
+    dependencies:
+      isobject "^3.0.0"
+  
+  object.assign@^4.1.2:
+    version "4.1.2"
+    resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940"
+    integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==
+    dependencies:
+      call-bind "^1.0.0"
+      define-properties "^1.1.3"
+      has-symbols "^1.0.1"
+      object-keys "^1.1.1"
+  
+  object.defaults@^1.1.0:
+    version "1.1.0"
+    resolved "https://registry.yarnpkg.com/object.defaults/-/object.defaults-1.1.0.tgz#3a7f868334b407dea06da16d88d5cd29e435fecf"
+    integrity sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=
+    dependencies:
+      array-each "^1.0.1"
+      array-slice "^1.0.0"
+      for-own "^1.0.0"
+      isobject "^3.0.0"
+  
+  object.map@^1.0.0, object.map@^1.0.1:
+    version "1.0.1"
+    resolved "https://registry.yarnpkg.com/object.map/-/object.map-1.0.1.tgz#cf83e59dc8fcc0ad5f4250e1f78b3b81bd801d37"
+    integrity sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=
+    dependencies:
+      for-own "^1.0.0"
+      make-iterator "^1.0.0"
+  
+  object.pick@^1.2.0, object.pick@^1.3.0:
+    version "1.3.0"
+    resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747"
+    integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=
+    dependencies:
+      isobject "^3.0.1"
+  
+  on-finished@~2.3.0:
+    version "2.3.0"
+    resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947"
+    integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=
+    dependencies:
+      ee-first "1.1.1"
+  
+  on-headers@~1.0.2:
+    version "1.0.2"
+    resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f"
+    integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==
+  
+  once@1.x, once@^1.3.0, once@^1.3.1, once@^1.4.0:
+    version "1.4.0"
+    resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
+    integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
+    dependencies:
+      wrappy "1"
+  
+  onetime@^5.1.2:
+    version "5.1.2"
+    resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e"
+    integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==
+    dependencies:
+      mimic-fn "^2.1.0"
+  
+  opn@^6.0.0:
+    version "6.0.0"
+    resolved "https://registry.yarnpkg.com/opn/-/opn-6.0.0.tgz#3c5b0db676d5f97da1233d1ed42d182bc5a27d2d"
+    integrity sha512-I9PKfIZC+e4RXZ/qr1RhgyCnGgYX0UEIlXgWnCOVACIvFgaC9rz6Won7xbdhoHrd8IIhV7YEpHjreNUNkqCGkQ==
+    dependencies:
+      is-wsl "^1.1.0"
+  
+  optionator@^0.8.1:
+    version "0.8.3"
+    resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495"
+    integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==
+    dependencies:
+      deep-is "~0.1.3"
+      fast-levenshtein "~2.0.6"
+      levn "~0.3.0"
+      prelude-ls "~1.1.2"
+      type-check "~0.3.2"
+      word-wrap "~1.2.3"
+  
+  optionator@^0.9.1:
+    version "0.9.1"
+    resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499"
+    integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==
+    dependencies:
+      deep-is "^0.1.3"
+      fast-levenshtein "^2.0.6"
+      levn "^0.4.1"
+      prelude-ls "^1.2.1"
+      type-check "^0.4.0"
+      word-wrap "^1.2.3"
+  
+  os-browserify@^0.3.0:
+    version "0.3.0"
+    resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27"
+    integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=
+  
+  os-homedir@^1.0.0:
+    version "1.0.2"
+    resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
+    integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M=
+  
+  os-locale@^3.0.0:
+    version "3.1.0"
+    resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a"
+    integrity sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==
+    dependencies:
+      execa "^1.0.0"
+      lcid "^2.0.0"
+      mem "^4.0.0"
+  
+  os-tmpdir@^1.0.0, os-tmpdir@~1.0.1:
+    version "1.0.2"
+    resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
+    integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
+  
+  osenv@^0.1.4:
+    version "0.1.5"
+    resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410"
+    integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==
+    dependencies:
+      os-homedir "^1.0.0"
+      os-tmpdir "^1.0.0"
+  
+  p-defer@^1.0.0:
+    version "1.0.0"
+    resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c"
+    integrity sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=
+  
+  p-finally@^1.0.0:
+    version "1.0.0"
+    resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
+    integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=
+  
+  p-is-promise@^2.0.0:
+    version "2.1.0"
+    resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.1.0.tgz#918cebaea248a62cf7ffab8e3bca8c5f882fc42e"
+    integrity sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==
+  
+  p-limit@^2.0.0, p-limit@^2.2.0:
+    version "2.3.0"
+    resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1"
+    integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==
+    dependencies:
+      p-try "^2.0.0"
+  
+  p-limit@^3.1.0:
+    version "3.1.0"
+    resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b"
+    integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==
+    dependencies:
+      yocto-queue "^0.1.0"
+  
+  p-locate@^3.0.0:
+    version "3.0.0"
+    resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4"
+    integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==
+    dependencies:
+      p-limit "^2.0.0"
+  
+  p-locate@^4.1.0:
+    version "4.1.0"
+    resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07"
+    integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==
+    dependencies:
+      p-limit "^2.2.0"
+  
+  p-try@^2.0.0:
+    version "2.2.0"
+    resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
+    integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
+  
+  pad@^3.2.0:
+    version "3.2.0"
+    resolved "https://registry.yarnpkg.com/pad/-/pad-3.2.0.tgz#be7a1d1cb6757049b4ad5b70e71977158fea95d1"
+    integrity sha512-2u0TrjcGbOjBTJpyewEl4hBO3OeX5wWue7eIFPzQTg6wFSvoaHcBTTUY5m+n0hd04gmTCPuY0kCpVIVuw5etwg==
+    dependencies:
+      wcwidth "^1.0.1"
+  
+  pako@~1.0.2, pako@~1.0.5:
+    version "1.0.11"
+    resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf"
+    integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==
+  
+  parent-module@^1.0.0:
+    version "1.0.1"
+    resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2"
+    integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==
+    dependencies:
+      callsites "^3.0.0"
+  
+  parse-asn1@^5.0.0, parse-asn1@^5.1.5:
+    version "5.1.6"
+    resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4"
+    integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==
+    dependencies:
+      asn1.js "^5.2.0"
+      browserify-aes "^1.0.0"
+      evp_bytestokey "^1.0.0"
+      pbkdf2 "^3.0.3"
+      safe-buffer "^5.1.1"
+  
+  parse-entities@^1.1.0:
+    version "1.2.2"
+    resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-1.2.2.tgz#c31bf0f653b6661354f8973559cb86dd1d5edf50"
+    integrity sha512-NzfpbxW/NPrzZ/yYSoQxyqUZMZXIdCfE0OIN4ESsnptHJECoUk3FZktxNuzQf4tjt5UEopnxpYJbvYuxIFDdsg==
+    dependencies:
+      character-entities "^1.0.0"
+      character-entities-legacy "^1.0.0"
+      character-reference-invalid "^1.0.0"
+      is-alphanumerical "^1.0.0"
+      is-decimal "^1.0.0"
+      is-hexadecimal "^1.0.0"
+  
+  parse-filepath@^1.0.1:
+    version "1.0.2"
+    resolved "https://registry.yarnpkg.com/parse-filepath/-/parse-filepath-1.0.2.tgz#a632127f53aaf3d15876f5872f3ffac763d6c891"
+    integrity sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=
+    dependencies:
+      is-absolute "^1.0.0"
+      map-cache "^0.2.0"
+      path-root "^0.1.1"
+  
+  parse-json@^2.2.0:
+    version "2.2.0"
+    resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9"
+    integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=
+    dependencies:
+      error-ex "^1.2.0"
+  
+  parse-passwd@^1.0.0:
+    version "1.0.0"
+    resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6"
+    integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=
+  
+  parseurl@~1.3.2, parseurl@~1.3.3:
+    version "1.3.3"
+    resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
+    integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==
+  
+  pascalcase@^0.1.1:
+    version "0.1.1"
+    resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14"
+    integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=
+  
+  path-browserify@^1.0.0:
+    version "1.0.1"
+    resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd"
+    integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==
+  
+  path-exists@^2.0.0:
+    version "2.1.0"
+    resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b"
+    integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=
+    dependencies:
+      pinkie-promise "^2.0.0"
+  
+  path-exists@^3.0.0:
+    version "3.0.0"
+    resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"
+    integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=
+  
+  path-exists@^4.0.0:
+    version "4.0.0"
+    resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
+    integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
+  
+  path-is-absolute@^1.0.0:
+    version "1.0.1"
+    resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
+    integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
+  
+  path-is-inside@^1.0.1:
+    version "1.0.2"
+    resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53"
+    integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=
+  
+  path-key@^2.0.0, path-key@^2.0.1:
+    version "2.0.1"
+    resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
+    integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=
+  
+  path-key@^3.0.0, path-key@^3.1.0:
+    version "3.1.1"
+    resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
+    integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
+  
+  path-parse@^1.0.6:
+    version "1.0.7"
+    resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
+    integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
+  
+  path-root-regex@^0.1.0:
+    version "0.1.2"
+    resolved "https://registry.yarnpkg.com/path-root-regex/-/path-root-regex-0.1.2.tgz#bfccdc8df5b12dc52c8b43ec38d18d72c04ba96d"
+    integrity sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=
+  
+  path-root@^0.1.1:
+    version "0.1.1"
+    resolved "https://registry.yarnpkg.com/path-root/-/path-root-0.1.1.tgz#9a4a6814cac1c0cd73360a95f32083c8ea4745b7"
+    integrity sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=
+    dependencies:
+      path-root-regex "^0.1.0"
+  
+  path-type@^1.0.0:
+    version "1.1.0"
+    resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441"
+    integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=
+    dependencies:
+      graceful-fs "^4.1.2"
+      pify "^2.0.0"
+      pinkie-promise "^2.0.0"
+  
+  path-type@^4.0.0:
+    version "4.0.0"
+    resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
+    integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
+  
+  pbkdf2@^3.0.3:
+    version "3.1.2"
+    resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075"
+    integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==
+    dependencies:
+      create-hash "^1.1.2"
+      create-hmac "^1.1.4"
+      ripemd160 "^2.0.1"
+      safe-buffer "^5.0.1"
+      sha.js "^2.4.8"
+  
+  pend@~1.2.0:
+    version "1.2.0"
+    resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50"
+    integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA=
+  
+  performance-now@^2.1.0:
+    version "2.1.0"
+    resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
+    integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
+  
+  picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3:
+    version "2.2.3"
+    resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.3.tgz#465547f359ccc206d3c48e46a1bcb89bf7ee619d"
+    integrity sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg==
+  
+  pify@^2.0.0:
+    version "2.3.0"
+    resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
+    integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw=
+  
+  pinkie-promise@^2.0.0:
+    version "2.0.1"
+    resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa"
+    integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o=
+    dependencies:
+      pinkie "^2.0.0"
+  
+  pinkie@^2.0.0:
+    version "2.0.4"
+    resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
+    integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA=
+  
+  pkg-dir@^4.2.0:
+    version "4.2.0"
+    resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3"
+    integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==
+    dependencies:
+      find-up "^4.0.0"
+  
+  plugin-error@^1.0.1:
+    version "1.0.1"
+    resolved "https://registry.yarnpkg.com/plugin-error/-/plugin-error-1.0.1.tgz#77016bd8919d0ac377fdcdd0322328953ca5781c"
+    integrity sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==
+    dependencies:
+      ansi-colors "^1.0.1"
+      arr-diff "^4.0.0"
+      arr-union "^3.1.0"
+      extend-shallow "^3.0.2"
+  
+  portscanner@^2.2.0:
+    version "2.2.0"
+    resolved "https://registry.yarnpkg.com/portscanner/-/portscanner-2.2.0.tgz#6059189b3efa0965c9d96a56b958eb9508411cf1"
+    integrity sha512-IFroCz/59Lqa2uBvzK3bKDbDDIEaAY8XJ1jFxcLWTqosrsc32//P4VuSB2vZXoHiHqOmx8B5L5hnKOxL/7FlPw==
+    dependencies:
+      async "^2.6.0"
+      is-number-like "^1.0.3"
+  
+  posix-character-classes@^0.1.0:
+    version "0.1.1"
+    resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab"
+    integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=
+  
+  prelude-ls@^1.2.1:
+    version "1.2.1"
+    resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
+    integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==
+  
+  prelude-ls@~1.1.2:
+    version "1.1.2"
+    resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
+    integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=
+  
+  pretty-bytes@^3.0.0:
+    version "3.0.1"
+    resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-3.0.1.tgz#27d0008d778063a0b4811bb35c79f1bd5d5fbccf"
+    integrity sha1-J9AAjXeAY6C0gRuzXHnxvV1fvM8=
+    dependencies:
+      number-is-nan "^1.0.0"
+  
+  process-nextick-args@~2.0.0:
+    version "2.0.1"
+    resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
+    integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
+  
+  process@^0.11.10:
+    version "0.11.10"
+    resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
+    integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI=
+  
+  progress@^2.0.0, progress@^2.0.1:
+    version "2.0.3"
+    resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
+    integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==
+  
+  protractor@^5.0.0:
+    version "5.4.4"
+    resolved "https://registry.yarnpkg.com/protractor/-/protractor-5.4.4.tgz#b241466aaf83b76bc2c58df67deb9a5cdfc61529"
+    integrity sha512-BaL4vePgu3Vfa/whvTUAlgaCAId4uNSGxIFSCXMgj7LMYENPWLp85h5RBi9pdpX/bWQ8SF6flP7afmi2TC4eHw==
+    dependencies:
+      "@types/q" "^0.0.32"
+      "@types/selenium-webdriver" "^3.0.0"
+      blocking-proxy "^1.0.0"
+      browserstack "^1.5.1"
+      chalk "^1.1.3"
+      glob "^7.0.3"
+      jasmine "2.8.0"
+      jasminewd2 "^2.1.0"
+      q "1.4.1"
+      saucelabs "^1.5.0"
+      selenium-webdriver "3.6.0"
+      source-map-support "~0.4.0"
+      webdriver-js-extender "2.1.0"
+      webdriver-manager "^12.0.6"
+      yargs "^12.0.5"
+  
+  protractor@^7.0.0:
+    version "7.0.0"
+    resolved "https://registry.yarnpkg.com/protractor/-/protractor-7.0.0.tgz#c3e263608bd72e2c2dc802b11a772711a4792d03"
+    integrity sha512-UqkFjivi4GcvUQYzqGYNe0mLzfn5jiLmO8w9nMhQoJRLhy2grJonpga2IWhI6yJO30LibWXJJtA4MOIZD2GgZw==
+    dependencies:
+      "@types/q" "^0.0.32"
+      "@types/selenium-webdriver" "^3.0.0"
+      blocking-proxy "^1.0.0"
+      browserstack "^1.5.1"
+      chalk "^1.1.3"
+      glob "^7.0.3"
+      jasmine "2.8.0"
+      jasminewd2 "^2.1.0"
+      q "1.4.1"
+      saucelabs "^1.5.0"
+      selenium-webdriver "3.6.0"
+      source-map-support "~0.4.0"
+      webdriver-js-extender "2.1.0"
+      webdriver-manager "^12.1.7"
+      yargs "^15.3.1"
+  
+  proxy-from-env@^1.0.0:
+    version "1.1.0"
+    resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
+    integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
+  
+  prr@~1.0.1:
+    version "1.0.1"
+    resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
+    integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY=
+  
+  psl@^1.1.28:
+    version "1.8.0"
+    resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24"
+    integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==
+  
+  public-encrypt@^4.0.0:
+    version "4.0.3"
+    resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0"
+    integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==
+    dependencies:
+      bn.js "^4.1.0"
+      browserify-rsa "^4.0.0"
+      create-hash "^1.1.0"
+      parse-asn1 "^5.0.0"
+      randombytes "^2.0.1"
+      safe-buffer "^5.1.2"
+  
+  pump@^3.0.0:
+    version "3.0.0"
+    resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64"
+    integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==
+    dependencies:
+      end-of-stream "^1.1.0"
+      once "^1.3.1"
+  
+  punycode@1.3.2:
+    version "1.3.2"
+    resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d"
+    integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=
+  
+  punycode@^2.1.0, punycode@^2.1.1:
+    version "2.1.1"
+    resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
+    integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
+  
+  puppeteer@^5.4.1:
+    version "5.5.0"
+    resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-5.5.0.tgz#331a7edd212ca06b4a556156435f58cbae08af00"
+    integrity sha512-OM8ZvTXAhfgFA7wBIIGlPQzvyEETzDjeRa4mZRCRHxYL+GNH5WAuYUQdja3rpWZvkX/JKqmuVgbsxDNsDFjMEg==
+    dependencies:
+      debug "^4.1.0"
+      devtools-protocol "0.0.818844"
+      extract-zip "^2.0.0"
+      https-proxy-agent "^4.0.0"
+      node-fetch "^2.6.1"
+      pkg-dir "^4.2.0"
+      progress "^2.0.1"
+      proxy-from-env "^1.0.0"
+      rimraf "^3.0.2"
+      tar-fs "^2.0.0"
+      unbzip2-stream "^1.3.3"
+      ws "^7.2.3"
+  
+  q@1.4.1:
+    version "1.4.1"
+    resolved "https://registry.yarnpkg.com/q/-/q-1.4.1.tgz#55705bcd93c5f3673530c2c2cbc0c2b3addc286e"
+    integrity sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=
+  
+  q@^1.4.1:
+    version "1.5.1"
+    resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
+    integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=
+  
+  qjobs@^1.2.0:
+    version "1.2.0"
+    resolved "https://registry.yarnpkg.com/qjobs/-/qjobs-1.2.0.tgz#c45e9c61800bd087ef88d7e256423bdd49e5d071"
+    integrity sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==
+  
+  qs@6.9.6:
+    version "6.9.6"
+    resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.6.tgz#26ed3c8243a431b2924aca84cc90471f35d5a0ee"
+    integrity sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ==
+  
+  qs@^6.4.0:
+    version "6.10.1"
+    resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.1.tgz#4931482fa8d647a5aab799c5271d2133b981fb6a"
+    integrity sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==
+    dependencies:
+      side-channel "^1.0.4"
+  
+  qs@~6.5.2:
+    version "6.5.2"
+    resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
+    integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==
+  
+  querystring-es3@^0.2.1:
+    version "0.2.1"
+    resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73"
+    integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=
+  
+  querystring@0.2.0:
+    version "0.2.0"
+    resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620"
+    integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=
+  
+  queue-microtask@^1.2.2:
+    version "1.2.3"
+    resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
+    integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
+  
+  randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0:
+    version "2.1.0"
+    resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
+    integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==
+    dependencies:
+      safe-buffer "^5.1.0"
+  
+  randomfill@^1.0.3:
+    version "1.0.4"
+    resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458"
+    integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==
+    dependencies:
+      randombytes "^2.0.5"
+      safe-buffer "^5.1.0"
+  
+  range-parser@^1.2.1, range-parser@~1.2.1:
+    version "1.2.1"
+    resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
+    integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==
+  
+  raw-body@2.4.2:
+    version "2.4.2"
+    resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.2.tgz#baf3e9c21eebced59dd6533ac872b71f7b61cb32"
+    integrity sha512-RPMAFUJP19WIet/99ngh6Iv8fzAbqum4Li7AD6DtGaW2RpMB/11xDoalPiJMTbu6I3hkbMVkATvZrqb9EEqeeQ==
+    dependencies:
+      bytes "3.1.1"
+      http-errors "1.8.1"
+      iconv-lite "0.4.24"
+      unpipe "1.0.0"
+  
+  raw-body@~1.1.0:
+    version "1.1.7"
+    resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-1.1.7.tgz#1d027c2bfa116acc6623bca8f00016572a87d425"
+    integrity sha1-HQJ8K/oRasxmI7yo8AAWVyqH1CU=
+    dependencies:
+      bytes "1"
+      string_decoder "0.10"
+  
+  read-pkg-up@^1.0.1:
+    version "1.0.1"
+    resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02"
+    integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=
+    dependencies:
+      find-up "^1.0.0"
+      read-pkg "^1.0.0"
+  
+  read-pkg@^1.0.0:
+    version "1.1.0"
+    resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28"
+    integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=
+    dependencies:
+      load-json-file "^1.0.0"
+      normalize-package-data "^2.3.2"
+      path-type "^1.0.0"
+  
+  "readable-stream@2 || 3", readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0:
+    version "3.6.0"
+    resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
+    integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
+    dependencies:
+      inherits "^2.0.3"
+      string_decoder "^1.1.1"
+      util-deprecate "^1.0.1"
+  
+  readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.3.3, readable-stream@~2.3.6:
+    version "2.3.7"
+    resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
+    integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
+    dependencies:
+      core-util-is "~1.0.0"
+      inherits "~2.0.3"
+      isarray "~1.0.0"
+      process-nextick-args "~2.0.0"
+      safe-buffer "~5.1.1"
+      string_decoder "~1.1.1"
+      util-deprecate "~1.0.1"
+  
+  readdirp@~3.6.0:
+    version "3.6.0"
+    resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"
+    integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==
+    dependencies:
+      picomatch "^2.2.1"
+  
+  rechoir@^0.6.2:
+    version "0.6.2"
+    resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384"
+    integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=
+    dependencies:
+      resolve "^1.1.6"
+  
+  rechoir@^0.7.0:
+    version "0.7.0"
+    resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.7.0.tgz#32650fd52c21ab252aa5d65b19310441c7e03aca"
+    integrity sha512-ADsDEH2bvbjltXEP+hTIAmeFekTFK0V2BTxMkok6qILyAJEXV0AFfoWcAq4yfll5VdIMd/RVXq0lR+wQi5ZU3Q==
+    dependencies:
+      resolve "^1.9.0"
+  
+  redent@^1.0.0:
+    version "1.0.0"
+    resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde"
+    integrity sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=
+    dependencies:
+      indent-string "^2.1.0"
+      strip-indent "^1.0.1"
+  
+  regex-not@^1.0.0, regex-not@^1.0.2:
+    version "1.0.2"
+    resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c"
+    integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==
+    dependencies:
+      extend-shallow "^3.0.2"
+      safe-regex "^1.1.0"
+  
+  regexpp@^3.0.0, regexpp@^3.1.0:
+    version "3.1.0"
+    resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2"
+    integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==
+  
+  remap-istanbul@^0.13.0:
+    version "0.13.0"
+    resolved "https://registry.yarnpkg.com/remap-istanbul/-/remap-istanbul-0.13.0.tgz#a529dfd080bb760f5274e3671c9c065f29923ed1"
+    integrity sha512-rS5ZpVAx3fGtKZkiBe1esXg5mKYbgW9iz8kkADFt3p6lo3NsBBUX1q6SwdhwUtYCGnr7nK6gRlbYK3i8R0jbRA==
+    dependencies:
+      istanbul "0.4.5"
+      minimatch "^3.0.4"
+      plugin-error "^1.0.1"
+      source-map "0.6.1"
+      through2 "3.0.0"
+  
+  remark-frontmatter@^1.2.0:
+    version "1.3.3"
+    resolved "https://registry.yarnpkg.com/remark-frontmatter/-/remark-frontmatter-1.3.3.tgz#67ec63c89da5a84bb793ecec166e11b4eb47af10"
+    integrity sha512-fM5eZPBvu2pVNoq3ZPW22q+5Ativ1oLozq2qYt9I2oNyxiUd/tDl0iLLntEVAegpZIslPWg1brhcP1VsaSVUag==
+    dependencies:
+      fault "^1.0.1"
+      xtend "^4.0.1"
+  
+  remark-parse@^5.0.0:
+    version "5.0.0"
+    resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-5.0.0.tgz#4c077f9e499044d1d5c13f80d7a98cf7b9285d95"
+    integrity sha512-b3iXszZLH1TLoyUzrATcTQUZrwNl1rE70rVdSruJFlDaJ9z5aMkhrG43Pp68OgfHndL/ADz6V69Zow8cTQu+JA==
+    dependencies:
+      collapse-white-space "^1.0.2"
+      is-alphabetical "^1.0.0"
+      is-decimal "^1.0.0"
+      is-whitespace-character "^1.0.0"
+      is-word-character "^1.0.0"
+      markdown-escapes "^1.0.0"
+      parse-entities "^1.1.0"
+      repeat-string "^1.5.4"
+      state-toggle "^1.0.0"
+      trim "0.0.1"
+      trim-trailing-lines "^1.0.0"
+      unherit "^1.0.4"
+      unist-util-remove-position "^1.0.0"
+      vfile-location "^2.0.0"
+      xtend "^4.0.1"
+  
+  repeat-element@^1.1.2:
+    version "1.1.4"
+    resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.4.tgz#be681520847ab58c7568ac75fbfad28ed42d39e9"
+    integrity sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==
+  
+  repeat-string@^1.5.4, repeat-string@^1.6.1:
+    version "1.6.1"
+    resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637"
+    integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc=
+  
+  repeating@^2.0.0:
+    version "2.0.1"
+    resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda"
+    integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=
+    dependencies:
+      is-finite "^1.0.0"
+  
+  replace-ext@1.0.0:
+    version "1.0.0"
+    resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb"
+    integrity sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=
+  
+  request@^2.87.0, request@^2.88.2:
+    version "2.88.2"
+    resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3"
+    integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==
+    dependencies:
+      aws-sign2 "~0.7.0"
+      aws4 "^1.8.0"
+      caseless "~0.12.0"
+      combined-stream "~1.0.6"
+      extend "~3.0.2"
+      forever-agent "~0.6.1"
+      form-data "~2.3.2"
+      har-validator "~5.1.3"
+      http-signature "~1.2.0"
+      is-typedarray "~1.0.0"
+      isstream "~0.1.2"
+      json-stringify-safe "~5.0.1"
+      mime-types "~2.1.19"
+      oauth-sign "~0.9.0"
+      performance-now "^2.1.0"
+      qs "~6.5.2"
+      safe-buffer "^5.1.2"
+      tough-cookie "~2.5.0"
+      tunnel-agent "^0.6.0"
+      uuid "^3.3.2"
+  
+  require-directory@^2.1.1:
+    version "2.1.1"
+    resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
+    integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I=
+  
+  require-from-string@^2.0.2:
+    version "2.0.2"
+    resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909"
+    integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==
+  
+  require-main-filename@^1.0.1:
+    version "1.0.1"
+    resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1"
+    integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=
+  
+  require-main-filename@^2.0.0:
+    version "2.0.0"
+    resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b"
+    integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==
+  
+  requires-port@^1.0.0:
+    version "1.0.0"
+    resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
+    integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=
+  
+  resolve-cwd@^3.0.0:
+    version "3.0.0"
+    resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d"
+    integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==
+    dependencies:
+      resolve-from "^5.0.0"
+  
+  resolve-dir@^1.0.0, resolve-dir@^1.0.1:
+    version "1.0.1"
+    resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43"
+    integrity sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=
+    dependencies:
+      expand-tilde "^2.0.0"
+      global-modules "^1.0.0"
+  
+  resolve-from@^4.0.0:
+    version "4.0.0"
+    resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
+    integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
+  
+  resolve-from@^5.0.0:
+    version "5.0.0"
+    resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69"
+    integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==
+  
+  resolve-url@^0.2.1:
+    version "0.2.1"
+    resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
+    integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=
+  
+  resolve@1.1.7, resolve@1.1.x:
+    version "1.1.7"
+    resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
+    integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=
+  
+  resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.19.0, resolve@^1.3.3, resolve@^1.9.0:
+    version "1.20.0"
+    resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975"
+    integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==
+    dependencies:
+      is-core-module "^2.2.0"
+      path-parse "^1.0.6"
+  
+  ret@~0.1.10:
+    version "0.1.15"
+    resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc"
+    integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==
+  
+  reusify@^1.0.4:
+    version "1.0.4"
+    resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
+    integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
+  
+  rfdc@^1.1.4, rfdc@^1.3.0:
+    version "1.3.0"
+    resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b"
+    integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==
+  
+  rimraf@^2.2.8, rimraf@^2.5.2, rimraf@^2.5.4, rimraf@^2.6.3:
+    version "2.7.1"
+    resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
+    integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==
+    dependencies:
+      glob "^7.1.3"
+  
+  rimraf@^3.0.0, rimraf@^3.0.2, rimraf@~3.0.2:
+    version "3.0.2"
+    resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
+    integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
+    dependencies:
+      glob "^7.1.3"
+  
+  ripemd160@^2.0.0, ripemd160@^2.0.1:
+    version "2.0.2"
+    resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c"
+    integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==
+    dependencies:
+      hash-base "^3.0.0"
+      inherits "^2.0.1"
+  
+  run-parallel@^1.1.9:
+    version "1.2.0"
+    resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee"
+    integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==
+    dependencies:
+      queue-microtask "^1.2.2"
+  
+  safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
+    version "5.1.2"
+    resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
+    integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
+  
+  safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0:
+    version "5.2.1"
+    resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
+    integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
+  
+  safe-json-parse@~1.0.1:
+    version "1.0.1"
+    resolved "https://registry.yarnpkg.com/safe-json-parse/-/safe-json-parse-1.0.1.tgz#3e76723e38dfdda13c9b1d29a1e07ffee4b30b57"
+    integrity sha1-PnZyPjjf3aE8mx0poeB//uSzC1c=
+  
+  safe-regex@^1.1.0:
+    version "1.1.0"
+    resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e"
+    integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4=
+    dependencies:
+      ret "~0.1.10"
+  
+  "safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
+    version "2.1.2"
+    resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
+    integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
+  
+  sass@^1.42.1:
+    version "1.42.1"
+    resolved "https://registry.yarnpkg.com/sass/-/sass-1.42.1.tgz#5ab17bebc1cb1881ad2e0c9a932c66ad64e441e2"
+    integrity sha512-/zvGoN8B7dspKc5mC6HlaygyCBRvnyzzgD5khiaCfglWztY99cYoiTUksVx11NlnemrcfH5CEaCpsUKoW0cQqg==
+    dependencies:
+      chokidar ">=3.0.0 <4.0.0"
+  
+  saucelabs@^1.5.0:
+    version "1.5.0"
+    resolved "https://registry.yarnpkg.com/saucelabs/-/saucelabs-1.5.0.tgz#9405a73c360d449b232839919a86c396d379fd9d"
+    integrity sha512-jlX3FGdWvYf4Q3LFfFWS1QvPg3IGCGWxIc8QBFdPTbpTJnt/v17FHXYVAn7C8sHf1yUXo2c7yIM0isDryfYtHQ==
+    dependencies:
+      https-proxy-agent "^2.2.1"
+  
+  sax@>=0.6.0:
+    version "1.2.4"
+    resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
+    integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
+  
+  schema-utils@^3.0.0:
+    version "3.0.0"
+    resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.0.0.tgz#67502f6aa2b66a2d4032b4279a2944978a0913ef"
+    integrity sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==
+    dependencies:
+      "@types/json-schema" "^7.0.6"
+      ajv "^6.12.5"
+      ajv-keywords "^3.5.2"
+  
+  selenium-webdriver@3.6.0, selenium-webdriver@^3.0.1:
+    version "3.6.0"
+    resolved "https://registry.yarnpkg.com/selenium-webdriver/-/selenium-webdriver-3.6.0.tgz#2ba87a1662c020b8988c981ae62cb2a01298eafc"
+    integrity sha512-WH7Aldse+2P5bbFBO4Gle/nuQOdVwpHMTL6raL3uuBj/vPG07k6uzt3aiahu352ONBr5xXh0hDlM3LhtXPOC4Q==
+    dependencies:
+      jszip "^3.1.3"
+      rimraf "^2.5.4"
+      tmp "0.0.30"
+      xml2js "^0.4.17"
+  
+  "semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.5.0:
+    version "5.7.1"
+    resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
+    integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
+  
+  semver@^7.2.1, semver@^7.3.2, semver@^7.3.4:
+    version "7.3.5"
+    resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7"
+    integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==
+    dependencies:
+      lru-cache "^6.0.0"
+  
+  send@0.17.1:
+    version "0.17.1"
+    resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8"
+    integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==
+    dependencies:
+      debug "2.6.9"
+      depd "~1.1.2"
+      destroy "~1.0.4"
+      encodeurl "~1.0.2"
+      escape-html "~1.0.3"
+      etag "~1.8.1"
+      fresh "0.5.2"
+      http-errors "~1.7.2"
+      mime "1.6.0"
+      ms "2.1.1"
+      on-finished "~2.3.0"
+      range-parser "~1.2.1"
+      statuses "~1.5.0"
+  
+  serialize-javascript@^5.0.1:
+    version "5.0.1"
+    resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-5.0.1.tgz#7886ec848049a462467a97d3d918ebb2aaf934f4"
+    integrity sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==
+    dependencies:
+      randombytes "^2.1.0"
+  
+  serve-index@^1.9.1:
+    version "1.9.1"
+    resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239"
+    integrity sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=
+    dependencies:
+      accepts "~1.3.4"
+      batch "0.6.1"
+      debug "2.6.9"
+      escape-html "~1.0.3"
+      http-errors "~1.6.2"
+      mime-types "~2.1.17"
+      parseurl "~1.3.2"
+  
+  serve-static@^1.14.1:
+    version "1.14.1"
+    resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9"
+    integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==
+    dependencies:
+      encodeurl "~1.0.2"
+      escape-html "~1.0.3"
+      parseurl "~1.3.3"
+      send "0.17.1"
+  
+  set-blocking@^2.0.0:
+    version "2.0.0"
+    resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
+    integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc=
+  
+  set-immediate-shim@~1.0.1:
+    version "1.0.1"
+    resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61"
+    integrity sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=
+  
+  set-value@^2.0.0, set-value@^2.0.1:
+    version "2.0.1"
+    resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b"
+    integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==
+    dependencies:
+      extend-shallow "^2.0.1"
+      is-extendable "^0.1.1"
+      is-plain-object "^2.0.3"
+      split-string "^3.0.1"
+  
+  setimmediate@^1.0.4, setimmediate@^1.0.5:
+    version "1.0.5"
+    resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
+    integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=
+  
+  setprototypeof@1.1.0:
+    version "1.1.0"
+    resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656"
+    integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==
+  
+  setprototypeof@1.1.1:
+    version "1.1.1"
+    resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683"
+    integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==
+  
+  setprototypeof@1.2.0:
+    version "1.2.0"
+    resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424"
+    integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==
+  
+  sha.js@^2.4.0, sha.js@^2.4.8:
+    version "2.4.11"
+    resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7"
+    integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==
+    dependencies:
+      inherits "^2.0.1"
+      safe-buffer "^5.0.1"
+  
+  shallow-clone@^3.0.0:
+    version "3.0.1"
+    resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3"
+    integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==
+    dependencies:
+      kind-of "^6.0.2"
+  
+  shebang-command@^1.2.0:
+    version "1.2.0"
+    resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
+    integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=
+    dependencies:
+      shebang-regex "^1.0.0"
+  
+  shebang-command@^2.0.0:
+    version "2.0.0"
+    resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"
+    integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==
+    dependencies:
+      shebang-regex "^3.0.0"
+  
+  shebang-regex@^1.0.0:
+    version "1.0.0"
+    resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
+    integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=
+  
+  shebang-regex@^3.0.0:
+    version "3.0.0"
+    resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
+    integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
+  
+  side-channel@^1.0.4:
+    version "1.0.4"
+    resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf"
+    integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==
+    dependencies:
+      call-bind "^1.0.0"
+      get-intrinsic "^1.0.2"
+      object-inspect "^1.9.0"
+  
+  signal-exit@^3.0.0, signal-exit@^3.0.3:
+    version "3.0.3"
+    resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c"
+    integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==
+  
+  slash@^3.0.0:
+    version "3.0.0"
+    resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
+    integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
+  
+  slice-ansi@^4.0.0:
+    version "4.0.0"
+    resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b"
+    integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==
+    dependencies:
+      ansi-styles "^4.0.0"
+      astral-regex "^2.0.0"
+      is-fullwidth-code-point "^3.0.0"
+  
+  snapdragon-node@^2.0.1:
+    version "2.1.1"
+    resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b"
+    integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==
+    dependencies:
+      define-property "^1.0.0"
+      isobject "^3.0.0"
+      snapdragon-util "^3.0.1"
+  
+  snapdragon-util@^3.0.1:
+    version "3.0.1"
+    resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2"
+    integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==
+    dependencies:
+      kind-of "^3.2.0"
+  
+  snapdragon@^0.8.1:
+    version "0.8.2"
+    resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d"
+    integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==
+    dependencies:
+      base "^0.11.1"
+      debug "^2.2.0"
+      define-property "^0.2.5"
+      extend-shallow "^2.0.1"
+      map-cache "^0.2.2"
+      source-map "^0.5.6"
+      source-map-resolve "^0.5.0"
+      use "^3.1.0"
+  
+  socket.io-adapter@~2.3.3:
+    version "2.3.3"
+    resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-2.3.3.tgz#4d6111e4d42e9f7646e365b4f578269821f13486"
+    integrity sha512-Qd/iwn3VskrpNO60BeRyCyr8ZWw9CPZyitW4AQwmRZ8zCiyDiL+znRnWX6tDHXnWn1sJrM1+b6Mn6wEDJJ4aYQ==
+  
+  socket.io-parser@~4.0.4:
+    version "4.0.4"
+    resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.0.4.tgz#9ea21b0d61508d18196ef04a2c6b9ab630f4c2b0"
+    integrity sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g==
+    dependencies:
+      "@types/component-emitter" "^1.2.10"
+      component-emitter "~1.3.0"
+      debug "~4.3.1"
+  
+  socket.io@^4.2.0:
+    version "4.4.1"
+    resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.4.1.tgz#cd6de29e277a161d176832bb24f64ee045c56ab8"
+    integrity sha512-s04vrBswdQBUmuWJuuNTmXUVJhP0cVky8bBDhdkf8y0Ptsu7fKU2LuLbts9g+pdmAdyMMn8F/9Mf1/wbtUN0fg==
+    dependencies:
+      accepts "~1.3.4"
+      base64id "~2.0.0"
+      debug "~4.3.2"
+      engine.io "~6.1.0"
+      socket.io-adapter "~2.3.3"
+      socket.io-parser "~4.0.4"
+  
+  source-list-map@^2.0.1:
+    version "2.0.1"
+    resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34"
+    integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==
+  
+  source-map-resolve@^0.5.0:
+    version "0.5.3"
+    resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a"
+    integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==
+    dependencies:
+      atob "^2.1.2"
+      decode-uri-component "^0.2.0"
+      resolve-url "^0.2.1"
+      source-map-url "^0.4.0"
+      urix "^0.1.0"
+  
+  source-map-support@~0.4.0:
+    version "0.4.18"
+    resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f"
+    integrity sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==
+    dependencies:
+      source-map "^0.5.6"
+  
+  source-map-support@~0.5.19:
+    version "0.5.19"
+    resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61"
+    integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==
+    dependencies:
+      buffer-from "^1.0.0"
+      source-map "^0.6.0"
+  
+  source-map-url@^0.4.0:
+    version "0.4.1"
+    resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56"
+    integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==
+  
+  source-map@0.6.1, source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0:
+    version "0.6.1"
+    resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
+    integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
+  
+  source-map@^0.5.1, source-map@^0.5.6, source-map@~0.5.3:
+    version "0.5.7"
+    resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
+    integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
+  
+  source-map@^0.7.3, source-map@~0.7.2:
+    version "0.7.3"
+    resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383"
+    integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==
+  
+  source-map@~0.2.0:
+    version "0.2.0"
+    resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d"
+    integrity sha1-2rc/vPwrqBm03gO9b26qSBZLP50=
+    dependencies:
+      amdefine ">=0.0.4"
+  
+  spdx-correct@^3.0.0:
+    version "3.1.1"
+    resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9"
+    integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==
+    dependencies:
+      spdx-expression-parse "^3.0.0"
+      spdx-license-ids "^3.0.0"
+  
+  spdx-exceptions@^2.1.0:
+    version "2.3.0"
+    resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d"
+    integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==
+  
+  spdx-expression-parse@^3.0.0:
+    version "3.0.1"
+    resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679"
+    integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==
+    dependencies:
+      spdx-exceptions "^2.1.0"
+      spdx-license-ids "^3.0.0"
+  
+  spdx-license-ids@^3.0.0:
+    version "3.0.7"
+    resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.7.tgz#e9c18a410e5ed7e12442a549fbd8afa767038d65"
+    integrity sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ==
+  
+  split-string@^3.0.1, split-string@^3.0.2:
+    version "3.1.0"
+    resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2"
+    integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==
+    dependencies:
+      extend-shallow "^3.0.0"
+  
+  split@^1.0.0, split@~1.0.0:
+    version "1.0.1"
+    resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9"
+    integrity sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==
+    dependencies:
+      through "2"
+  
+  sprintf-js@^1.0.3:
+    version "1.1.2"
+    resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.2.tgz#da1765262bf8c0f571749f2ad6c26300207ae673"
+    integrity sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==
+  
+  sprintf-js@~1.0.2:
+    version "1.0.3"
+    resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
+    integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
+  
+  sshpk@^1.7.0:
+    version "1.16.1"
+    resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877"
+    integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==
+    dependencies:
+      asn1 "~0.2.3"
+      assert-plus "^1.0.0"
+      bcrypt-pbkdf "^1.0.0"
+      dashdash "^1.12.0"
+      ecc-jsbn "~0.1.1"
+      getpass "^0.1.1"
+      jsbn "~0.1.0"
+      safer-buffer "^2.0.2"
+      tweetnacl "~0.14.0"
+  
+  state-toggle@^1.0.0:
+    version "1.0.3"
+    resolved "https://registry.yarnpkg.com/state-toggle/-/state-toggle-1.0.3.tgz#e123b16a88e143139b09c6852221bc9815917dfe"
+    integrity sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ==
+  
+  static-extend@^0.1.1:
+    version "0.1.2"
+    resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6"
+    integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=
+    dependencies:
+      define-property "^0.2.5"
+      object-copy "^0.1.0"
+  
+  "statuses@>= 1.4.0 < 2", "statuses@>= 1.5.0 < 2", statuses@~1.5.0:
+    version "1.5.0"
+    resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
+    integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=
+  
+  stream-browserify@2.0.1:
+    version "2.0.1"
+    resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.1.tgz#66266ee5f9bdb9940a4e4514cafb43bb71e5c9db"
+    integrity sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=
+    dependencies:
+      inherits "~2.0.1"
+      readable-stream "^2.0.2"
+  
+  stream-browserify@^2.0.2:
+    version "2.0.2"
+    resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b"
+    integrity sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==
+    dependencies:
+      inherits "~2.0.1"
+      readable-stream "^2.0.2"
+  
+  stream-http@^3.0.0:
+    version "3.1.1"
+    resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-3.1.1.tgz#0370a8017cf8d050b9a8554afe608f043eaff564"
+    integrity sha512-S7OqaYu0EkFpgeGFb/NPOoPLxFko7TPqtEeFg5DXPB4v/KETHG0Ln6fRFrNezoelpaDKmycEmmZ81cC9DAwgYg==
+    dependencies:
+      builtin-status-codes "^3.0.0"
+      inherits "^2.0.4"
+      readable-stream "^3.6.0"
+      xtend "^4.0.2"
+  
+  stream-shift@^1.0.0:
+    version "1.0.1"
+    resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d"
+    integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==
+  
+  streamroller@^1.0.6:
+    version "1.0.6"
+    resolved "https://registry.yarnpkg.com/streamroller/-/streamroller-1.0.6.tgz#8167d8496ed9f19f05ee4b158d9611321b8cacd9"
+    integrity sha512-3QC47Mhv3/aZNFpDDVO44qQb9gwB9QggMEE0sQmkTAwBVYdBRWISdsywlkfm5II1Q5y/pmrHflti/IgmIzdDBg==
+    dependencies:
+      async "^2.6.2"
+      date-format "^2.0.0"
+      debug "^3.2.6"
+      fs-extra "^7.0.1"
+      lodash "^4.17.14"
+  
+  streamroller@^3.0.2:
+    version "3.0.2"
+    resolved "https://registry.yarnpkg.com/streamroller/-/streamroller-3.0.2.tgz#30418d0eee3d6c93ec897f892ed098e3a81e68b7"
+    integrity sha512-ur6y5S5dopOaRXBuRIZ1u6GC5bcEXHRZKgfBjfCglMhmIf+roVCECjvkEYzNQOXIN2/JPnkMPW/8B3CZoKaEPA==
+    dependencies:
+      date-format "^4.0.3"
+      debug "^4.1.1"
+      fs-extra "^10.0.0"
+  
+  string-template@~0.2.1:
+    version "0.2.1"
+    resolved "https://registry.yarnpkg.com/string-template/-/string-template-0.2.1.tgz#42932e598a352d01fc22ec3367d9d84eec6c9add"
+    integrity sha1-QpMuWYo1LQH8IuwzZ9nYTuxsmt0=
+  
+  string-width@^1.0.1:
+    version "1.0.2"
+    resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
+    integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=
+    dependencies:
+      code-point-at "^1.0.0"
+      is-fullwidth-code-point "^1.0.0"
+      strip-ansi "^3.0.0"
+  
+  string-width@^2.0.0, string-width@^2.1.1:
+    version "2.1.1"
+    resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
+    integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==
+    dependencies:
+      is-fullwidth-code-point "^2.0.0"
+      strip-ansi "^4.0.0"
+  
+  string-width@^4.1.0, string-width@^4.2.0:
+    version "4.2.2"
+    resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.2.tgz#dafd4f9559a7585cfba529c6a0a4f73488ebd4c5"
+    integrity sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==
+    dependencies:
+      emoji-regex "^8.0.0"
+      is-fullwidth-code-point "^3.0.0"
+      strip-ansi "^6.0.0"
+  
+  string.prototype.trimend@^1.0.4:
+    version "1.0.4"
+    resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz#e75ae90c2942c63504686c18b287b4a0b1a45f80"
+    integrity sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==
+    dependencies:
+      call-bind "^1.0.2"
+      define-properties "^1.1.3"
+  
+  string.prototype.trimstart@^1.0.4:
+    version "1.0.4"
+    resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz#b36399af4ab2999b4c9c648bd7a3fb2bb26feeed"
+    integrity sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==
+    dependencies:
+      call-bind "^1.0.2"
+      define-properties "^1.1.3"
+  
+  string_decoder@0.10:
+    version "0.10.31"
+    resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
+    integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=
+  
+  string_decoder@^1.1.1, string_decoder@^1.2.0:
+    version "1.3.0"
+    resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e"
+    integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
+    dependencies:
+      safe-buffer "~5.2.0"
+  
+  string_decoder@~1.1.1:
+    version "1.1.1"
+    resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
+    integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
+    dependencies:
+      safe-buffer "~5.1.0"
+  
+  strip-ansi@^3.0.0, strip-ansi@^3.0.1:
+    version "3.0.1"
+    resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
+    integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=
+    dependencies:
+      ansi-regex "^2.0.0"
+  
+  strip-ansi@^4.0.0:
+    version "4.0.0"
+    resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f"
+    integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8=
+    dependencies:
+      ansi-regex "^3.0.0"
+  
+  strip-ansi@^6.0.0:
+    version "6.0.0"
+    resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532"
+    integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==
+    dependencies:
+      ansi-regex "^5.0.0"
+  
+  strip-bom@^2.0.0:
+    version "2.0.0"
+    resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e"
+    integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=
+    dependencies:
+      is-utf8 "^0.2.0"
+  
+  strip-eof@^1.0.0:
+    version "1.0.0"
+    resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
+    integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=
+  
+  strip-final-newline@^2.0.0:
+    version "2.0.0"
+    resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad"
+    integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==
+  
+  strip-indent@^1.0.1:
+    version "1.0.1"
+    resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2"
+    integrity sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=
+    dependencies:
+      get-stdin "^4.0.1"
+  
+  strip-json-comments@^3.1.0, strip-json-comments@^3.1.1:
+    version "3.1.1"
+    resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
+    integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
+  
+  structured-source@^3.0.2:
+    version "3.0.2"
+    resolved "https://registry.yarnpkg.com/structured-source/-/structured-source-3.0.2.tgz#dd802425e0f53dc4a6e7aca3752901a1ccda7af5"
+    integrity sha1-3YAkJeD1PcSm56yjdSkBoczaevU=
+    dependencies:
+      boundary "^1.0.1"
+  
+  supports-color@^2.0.0:
+    version "2.0.0"
+    resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
+    integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=
+  
+  supports-color@^3.1.0:
+    version "3.2.3"
+    resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6"
+    integrity sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=
+    dependencies:
+      has-flag "^1.0.0"
+  
+  supports-color@^5.3.0:
+    version "5.5.0"
+    resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
+    integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
+    dependencies:
+      has-flag "^3.0.0"
+  
+  supports-color@^7.0.0, supports-color@^7.1.0:
+    version "7.2.0"
+    resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
+    integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
+    dependencies:
+      has-flag "^4.0.0"
+  
+  table@^6.0.4:
+    version "6.0.9"
+    resolved "https://registry.yarnpkg.com/table/-/table-6.0.9.tgz#790a12bf1e09b87b30e60419bafd6a1fd85536fb"
+    integrity sha512-F3cLs9a3hL1Z7N4+EkSscsel3z55XT950AvB05bwayrNg5T1/gykXtigioTAjbltvbMSJvvhFCbnf6mX+ntnJQ==
+    dependencies:
+      ajv "^8.0.1"
+      is-boolean-object "^1.1.0"
+      is-number-object "^1.0.4"
+      is-string "^1.0.5"
+      lodash.clonedeep "^4.5.0"
+      lodash.flatten "^4.4.0"
+      lodash.truncate "^4.4.2"
+      slice-ansi "^4.0.0"
+      string-width "^4.2.0"
+  
+  tapable@^1.0.0:
+    version "1.1.3"
+    resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2"
+    integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==
+  
+  tapable@^2.1.1, tapable@^2.2.0:
+    version "2.2.0"
+    resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.0.tgz#5c373d281d9c672848213d0e037d1c4165ab426b"
+    integrity sha512-FBk4IesMV1rBxX2tfiK8RAmogtWn53puLOQlvO8XuwlgxcYbP4mVPS9Ph4aeamSyyVjOl24aYWAuc8U5kCVwMw==
+  
+  tar-fs@^2.0.0:
+    version "2.1.1"
+    resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.1.tgz#489a15ab85f1f0befabb370b7de4f9eb5cbe8784"
+    integrity sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==
+    dependencies:
+      chownr "^1.1.1"
+      mkdirp-classic "^0.5.2"
+      pump "^3.0.0"
+      tar-stream "^2.1.4"
+  
+  tar-stream@^2.1.4:
+    version "2.2.0"
+    resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287"
+    integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==
+    dependencies:
+      bl "^4.0.3"
+      end-of-stream "^1.4.1"
+      fs-constants "^1.0.0"
+      inherits "^2.0.3"
+      readable-stream "^3.1.1"
+  
+  terser-webpack-plugin@^5.1.1:
+    version "5.1.1"
+    resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.1.1.tgz#7effadee06f7ecfa093dbbd3e9ab23f5f3ed8673"
+    integrity sha512-5XNNXZiR8YO6X6KhSGXfY0QrGrCRlSwAEjIIrlRQR4W8nP69TaJUlh3bkuac6zzgspiGPfKEHcY295MMVExl5Q==
+    dependencies:
+      jest-worker "^26.6.2"
+      p-limit "^3.1.0"
+      schema-utils "^3.0.0"
+      serialize-javascript "^5.0.1"
+      source-map "^0.6.1"
+      terser "^5.5.1"
+  
+  terser@^5.5.1:
+    version "5.6.1"
+    resolved "https://registry.yarnpkg.com/terser/-/terser-5.6.1.tgz#a48eeac5300c0a09b36854bf90d9c26fb201973c"
+    integrity sha512-yv9YLFQQ+3ZqgWCUk+pvNJwgUTdlIxUk1WTN+RnaFJe2L7ipG2csPT0ra2XRm7Cs8cxN7QXmK1rFzEwYEQkzXw==
+    dependencies:
+      commander "^2.20.0"
+      source-map "~0.7.2"
+      source-map-support "~0.5.19"
+  
+  text-table@^0.2.0:
+    version "0.2.0"
+    resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
+    integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=
+  
+  through2@3.0.0:
+    version "3.0.0"
+    resolved "https://registry.yarnpkg.com/through2/-/through2-3.0.0.tgz#468b461df9cd9fcc170f22ebf6852e467e578ff2"
+    integrity sha512-8B+sevlqP4OiCjonI1Zw03Sf8PuV1eRsYQgLad5eonILOdyeRsY27A/2Ze8IlvlMvq31OH+3fz/styI7Ya62yQ==
+    dependencies:
+      readable-stream "2 || 3"
+      xtend "~4.0.1"
+  
+  through2@~2.0.0:
+    version "2.0.5"
+    resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd"
+    integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==
+    dependencies:
+      readable-stream "~2.3.6"
+      xtend "~4.0.1"
+  
+  through@2, through@^2.3.8:
+    version "2.3.8"
+    resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
+    integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=
+  
+  timers-browserify@2.0.2:
+    version "2.0.2"
+    resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.2.tgz#ab4883cf597dcd50af211349a00fbca56ac86b86"
+    integrity sha1-q0iDz1l9zVCvIRNJoA+8pWrIa4Y=
+    dependencies:
+      setimmediate "^1.0.4"
+  
+  timers-browserify@^2.0.10:
+    version "2.0.12"
+    resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.12.tgz#44a45c11fbf407f34f97bccd1577c652361b00ee"
+    integrity sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==
+    dependencies:
+      setimmediate "^1.0.4"
+  
+  tiny-lr@^1.1.1:
+    version "1.1.1"
+    resolved "https://registry.yarnpkg.com/tiny-lr/-/tiny-lr-1.1.1.tgz#9fa547412f238fedb068ee295af8b682c98b2aab"
+    integrity sha512-44yhA3tsaRoMOjQQ+5v5mVdqef+kH6Qze9jTpqtVufgYjYt08zyZAwNwwVBj3i1rJMnR52IxOW0LK0vBzgAkuA==
+    dependencies:
+      body "^5.1.0"
+      debug "^3.1.0"
+      faye-websocket "~0.10.0"
+      livereload-js "^2.3.0"
+      object-assign "^4.1.0"
+      qs "^6.4.0"
+  
+  tmp@0.0.30:
+    version "0.0.30"
+    resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.30.tgz#72419d4a8be7d6ce75148fd8b324e593a711c2ed"
+    integrity sha1-ckGdSovn1s51FI/YsyTlk6cRwu0=
+    dependencies:
+      os-tmpdir "~1.0.1"
+  
+  tmp@^0.1.0:
+    version "0.1.0"
+    resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.1.0.tgz#ee434a4e22543082e294ba6201dcc6eafefa2877"
+    integrity sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw==
+    dependencies:
+      rimraf "^2.6.3"
+  
+  tmp@^0.2.1:
+    version "0.2.1"
+    resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14"
+    integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==
+    dependencies:
+      rimraf "^3.0.0"
+  
+  to-object-path@^0.3.0:
+    version "0.3.0"
+    resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af"
+    integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=
+    dependencies:
+      kind-of "^3.0.2"
+  
+  to-regex-range@^2.1.0:
+    version "2.1.1"
+    resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38"
+    integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=
+    dependencies:
+      is-number "^3.0.0"
+      repeat-string "^1.6.1"
+  
+  to-regex-range@^5.0.1:
+    version "5.0.1"
+    resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
+    integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
+    dependencies:
+      is-number "^7.0.0"
+  
+  to-regex@^3.0.1, to-regex@^3.0.2:
+    version "3.0.2"
+    resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce"
+    integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==
+    dependencies:
+      define-property "^2.0.2"
+      extend-shallow "^3.0.2"
+      regex-not "^1.0.2"
+      safe-regex "^1.1.0"
+  
+  toidentifier@1.0.0:
+    version "1.0.0"
+    resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
+    integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
+  
+  toidentifier@1.0.1:
+    version "1.0.1"
+    resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35"
+    integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==
+  
+  tough-cookie@~2.5.0:
+    version "2.5.0"
+    resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
+    integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==
+    dependencies:
+      psl "^1.1.28"
+      punycode "^2.1.1"
+  
+  tr46@~0.0.3:
+    version "0.0.3"
+    resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
+    integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=
+  
+  traverse@^0.6.6:
+    version "0.6.6"
+    resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.6.6.tgz#cbdf560fd7b9af632502fed40f918c157ea97137"
+    integrity sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=
+  
+  trim-newlines@^1.0.0:
+    version "1.0.0"
+    resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613"
+    integrity sha1-WIeWa7WCpFA6QetST301ARgVphM=
+  
+  trim-trailing-lines@^1.0.0:
+    version "1.1.4"
+    resolved "https://registry.yarnpkg.com/trim-trailing-lines/-/trim-trailing-lines-1.1.4.tgz#bd4abbec7cc880462f10b2c8b5ce1d8d1ec7c2c0"
+    integrity sha512-rjUWSqnfTNrjbB9NQWfPMH/xRK1deHeGsHoVfpxJ++XeYXE0d6B1En37AHfw3jtfTU7dzMzZL2jjpe8Qb5gLIQ==
+  
+  trim@0.0.1:
+    version "0.0.1"
+    resolved "https://registry.yarnpkg.com/trim/-/trim-0.0.1.tgz#5858547f6b290757ee95cccc666fb50084c460dd"
+    integrity sha1-WFhUf2spB1fulczMZm+1AITEYN0=
+  
+  trough@^1.0.0:
+    version "1.0.5"
+    resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.5.tgz#b8b639cefad7d0bb2abd37d433ff8293efa5f406"
+    integrity sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==
+  
+  ts-loader@^8.0.7:
+    version "8.1.0"
+    resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-8.1.0.tgz#d6292487df279c7cc79b6d3b70bb9d31682b693e"
+    integrity sha512-YiQipGGAFj2zBfqLhp28yUvPP9jUGqHxRzrGYuc82Z2wM27YIHbElXiaZDc93c3x0mz4zvBmS6q/DgExpdj37A==
+    dependencies:
+      chalk "^4.1.0"
+      enhanced-resolve "^4.0.0"
+      loader-utils "^2.0.0"
+      micromatch "^4.0.0"
+      semver "^7.3.4"
+  
+  tslib@^1.8.1:
+    version "1.14.1"
+    resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
+    integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
+  
+  tsutils@^3.17.1:
+    version "3.21.0"
+    resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623"
+    integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==
+    dependencies:
+      tslib "^1.8.1"
+  
+  tty-browserify@^0.0.1:
+    version "0.0.1"
+    resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.1.tgz#3f05251ee17904dfd0677546670db9651682b811"
+    integrity sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==
+  
+  tunnel-agent@^0.6.0:
+    version "0.6.0"
+    resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd"
+    integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=
+    dependencies:
+      safe-buffer "^5.0.1"
+  
+  tweetnacl@^0.14.3, tweetnacl@~0.14.0:
+    version "0.14.5"
+    resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
+    integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=
+  
+  type-check@^0.4.0, type-check@~0.4.0:
+    version "0.4.0"
+    resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1"
+    integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==
+    dependencies:
+      prelude-ls "^1.2.1"
+  
+  type-check@~0.3.2:
+    version "0.3.2"
+    resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72"
+    integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=
+    dependencies:
+      prelude-ls "~1.1.2"
+  
+  type-fest@^0.20.2:
+    version "0.20.2"
+    resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4"
+    integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==
+  
+  type-fest@^0.8.1:
+    version "0.8.1"
+    resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d"
+    integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==
+  
+  type-is@~1.6.18:
+    version "1.6.18"
+    resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
+    integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==
+    dependencies:
+      media-typer "0.3.0"
+      mime-types "~2.1.24"
+  
+  typescript@^3.7:
+    version "3.9.9"
+    resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.9.tgz#e69905c54bc0681d0518bd4d587cc6f2d0b1a674"
+    integrity sha512-kdMjTiekY+z/ubJCATUPlRDl39vXYiMV9iyeMuEuXZh2we6zz80uovNN2WlAxmmdE/Z/YQe+EbOEXB5RHEED3w==
+  
+  ua-parser-js@^0.7.30:
+    version "0.7.31"
+    resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.31.tgz#649a656b191dffab4f21d5e053e27ca17cbff5c6"
+    integrity sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ==
+  
+  uglify-js@^3.1.4, uglify-js@^3.13.3:
+    version "3.13.3"
+    resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.13.3.tgz#ce72a1ad154348ea2af61f50933c76cc8802276e"
+    integrity sha512-otIc7O9LyxpUcQoXzj2hL4LPWKklO6LJWoJUzNa8A17Xgi4fOeDC8FBDOLHnC/Slo1CQgsZMcM6as0M76BZaig==
+  
+  ultron@~1.1.0:
+    version "1.1.1"
+    resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c"
+    integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==
+  
+  unbox-primitive@^1.0.0:
+    version "1.0.1"
+    resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471"
+    integrity sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==
+    dependencies:
+      function-bind "^1.1.1"
+      has-bigints "^1.0.1"
+      has-symbols "^1.0.2"
+      which-boxed-primitive "^1.0.2"
+  
+  unbzip2-stream@^1.3.3:
+    version "1.4.3"
+    resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz#b0da04c4371311df771cdc215e87f2130991ace7"
+    integrity sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==
+    dependencies:
+      buffer "^5.2.1"
+      through "^2.3.8"
+  
+  unc-path-regex@^0.1.2:
+    version "0.1.2"
+    resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa"
+    integrity sha1-5z3T17DXxe2G+6xrCufYxqadUPo=
+  
+  underscore.string@~3.3.5:
+    version "3.3.5"
+    resolved "https://registry.yarnpkg.com/underscore.string/-/underscore.string-3.3.5.tgz#fc2ad255b8bd309e239cbc5816fd23a9b7ea4023"
+    integrity sha512-g+dpmgn+XBneLmXXo+sGlW5xQEt4ErkS3mgeN2GFbremYeMBSJKr9Wf2KJplQVaiPY/f7FN6atosWYNm9ovrYg==
+    dependencies:
+      sprintf-js "^1.0.3"
+      util-deprecate "^1.0.2"
+  
+  underscore@~1.8.3:
+    version "1.8.3"
+    resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.8.3.tgz#4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022"
+    integrity sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=
+  
+  unherit@^1.0.4:
+    version "1.1.3"
+    resolved "https://registry.yarnpkg.com/unherit/-/unherit-1.1.3.tgz#6c9b503f2b41b262330c80e91c8614abdaa69c22"
+    integrity sha512-Ft16BJcnapDKp0+J/rqFC3Rrk6Y/Ng4nzsC028k2jdDII/rdZ7Wd3pPT/6+vIIxRagwRc9K0IUX0Ra4fKvw+WQ==
+    dependencies:
+      inherits "^2.0.0"
+      xtend "^4.0.0"
+  
+  unified@^6.1.6:
+    version "6.2.0"
+    resolved "https://registry.yarnpkg.com/unified/-/unified-6.2.0.tgz#7fbd630f719126d67d40c644b7e3f617035f6dba"
+    integrity sha512-1k+KPhlVtqmG99RaTbAv/usu85fcSRu3wY8X+vnsEhIxNP5VbVIDiXnLqyKIG+UMdyTg0ZX9EI6k2AfjJkHPtA==
+    dependencies:
+      bail "^1.0.0"
+      extend "^3.0.0"
+      is-plain-obj "^1.1.0"
+      trough "^1.0.0"
+      vfile "^2.0.0"
+      x-is-string "^0.1.0"
+  
+  union-value@^1.0.0:
+    version "1.0.1"
+    resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847"
+    integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==
+    dependencies:
+      arr-union "^3.1.0"
+      get-value "^2.0.6"
+      is-extendable "^0.1.1"
+      set-value "^2.0.1"
+  
+  unist-util-is@^3.0.0:
+    version "3.0.0"
+    resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-3.0.0.tgz#d9e84381c2468e82629e4a5be9d7d05a2dd324cd"
+    integrity sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A==
+  
+  unist-util-remove-position@^1.0.0:
+    version "1.1.4"
+    resolved "https://registry.yarnpkg.com/unist-util-remove-position/-/unist-util-remove-position-1.1.4.tgz#ec037348b6102c897703eee6d0294ca4755a2020"
+    integrity sha512-tLqd653ArxJIPnKII6LMZwH+mb5q+n/GtXQZo6S6csPRs5zB0u79Yw8ouR3wTw8wxvdJFhpP6Y7jorWdCgLO0A==
+    dependencies:
+      unist-util-visit "^1.1.0"
+  
+  unist-util-stringify-position@^1.0.0, unist-util-stringify-position@^1.1.1:
+    version "1.1.2"
+    resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz#3f37fcf351279dcbca7480ab5889bb8a832ee1c6"
+    integrity sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ==
+  
+  unist-util-visit-parents@^2.0.0:
+    version "2.1.2"
+    resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz#25e43e55312166f3348cae6743588781d112c1e9"
+    integrity sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g==
+    dependencies:
+      unist-util-is "^3.0.0"
+  
+  unist-util-visit@^1.1.0:
+    version "1.4.1"
+    resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-1.4.1.tgz#4724aaa8486e6ee6e26d7ff3c8685960d560b1e3"
+    integrity sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw==
+    dependencies:
+      unist-util-visit-parents "^2.0.0"
+  
+  universalify@^0.1.0:
+    version "0.1.2"
+    resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
+    integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
+  
+  universalify@^2.0.0:
+    version "2.0.0"
+    resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717"
+    integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==
+  
+  unpipe@1.0.0, unpipe@~1.0.0:
+    version "1.0.0"
+    resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
+    integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=
+  
+  unset-value@^1.0.0:
+    version "1.0.0"
+    resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559"
+    integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=
+    dependencies:
+      has-value "^0.3.1"
+      isobject "^3.0.0"
+  
+  update-section@^0.3.0:
+    version "0.3.3"
+    resolved "https://registry.yarnpkg.com/update-section/-/update-section-0.3.3.tgz#458f17820d37820dc60e20b86d94391b00123158"
+    integrity sha1-RY8Xgg03gg3GDiC4bZQ5GwASMVg=
+  
+  uri-js@^4.2.2:
+    version "4.4.1"
+    resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
+    integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==
+    dependencies:
+      punycode "^2.1.0"
+  
+  uri-path@^1.0.0:
+    version "1.0.0"
+    resolved "https://registry.yarnpkg.com/uri-path/-/uri-path-1.0.0.tgz#9747f018358933c31de0fccfd82d138e67262e32"
+    integrity sha1-l0fwGDWJM8Md4PzP2C0TjmcmLjI=
+  
+  urix@^0.1.0:
+    version "0.1.0"
+    resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72"
+    integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=
+  
+  url@^0.11.0:
+    version "0.11.0"
+    resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1"
+    integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=
+    dependencies:
+      punycode "1.3.2"
+      querystring "0.2.0"
+  
+  use@^3.1.0:
+    version "3.1.1"
+    resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f"
+    integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==
+  
+  util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1:
+    version "1.0.2"
+    resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
+    integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
+  
+  util@0.10.3:
+    version "0.10.3"
+    resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9"
+    integrity sha1-evsa/lCAUkZInj23/g7TeTNqwPk=
+    dependencies:
+      inherits "2.0.1"
+  
+  util@^0.12.0:
+    version "0.12.3"
+    resolved "https://registry.yarnpkg.com/util/-/util-0.12.3.tgz#971bb0292d2cc0c892dab7c6a5d37c2bec707888"
+    integrity sha512-I8XkoQwE+fPQEhy9v012V+TSdH2kp9ts29i20TaaDUXsg7x/onePbhFJUExBfv/2ay1ZOp/Vsm3nDlmnFGSAog==
+    dependencies:
+      inherits "^2.0.3"
+      is-arguments "^1.0.4"
+      is-generator-function "^1.0.7"
+      is-typed-array "^1.1.3"
+      safe-buffer "^5.1.2"
+      which-typed-array "^1.1.2"
+  
+  utils-merge@1.0.1:
+    version "1.0.1"
+    resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
+    integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=
+  
+  uuid@^3.3.2:
+    version "3.4.0"
+    resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
+    integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
+  
+  v8-compile-cache@^2.0.3, v8-compile-cache@^2.2.0:
+    version "2.3.0"
+    resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee"
+    integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==
+  
+  v8flags@~3.1.1:
+    version "3.1.3"
+    resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-3.1.3.tgz#fc9dc23521ca20c5433f81cc4eb9b3033bb105d8"
+    integrity sha512-amh9CCg3ZxkzQ48Mhcb8iX7xpAfYJgePHxWMQCBWECpOSqJUXgY26ncA61UTV0BkPqfhcy6mzwCIoP4ygxpW8w==
+    dependencies:
+      homedir-polyfill "^1.0.1"
+  
+  v8flags@~3.2.0:
+    version "3.2.0"
+    resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-3.2.0.tgz#b243e3b4dfd731fa774e7492128109a0fe66d656"
+    integrity sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==
+    dependencies:
+      homedir-polyfill "^1.0.1"
+  
+  validate-npm-package-license@^3.0.1:
+    version "3.0.4"
+    resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a"
+    integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==
+    dependencies:
+      spdx-correct "^3.0.0"
+      spdx-expression-parse "^3.0.0"
+  
+  vary@^1:
+    version "1.1.2"
+    resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
+    integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=
+  
+  verror@1.10.0:
+    version "1.10.0"
+    resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400"
+    integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=
+    dependencies:
+      assert-plus "^1.0.0"
+      core-util-is "1.0.2"
+      extsprintf "^1.2.0"
+  
+  vfile-location@^2.0.0:
+    version "2.0.6"
+    resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-2.0.6.tgz#8a274f39411b8719ea5728802e10d9e0dff1519e"
+    integrity sha512-sSFdyCP3G6Ka0CEmN83A2YCMKIieHx0EDaj5IDP4g1pa5ZJ4FJDvpO0WODLxo4LUX4oe52gmSCK7Jw4SBghqxA==
+  
+  vfile-message@^1.0.0:
+    version "1.1.1"
+    resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-1.1.1.tgz#5833ae078a1dfa2d96e9647886cd32993ab313e1"
+    integrity sha512-1WmsopSGhWt5laNir+633LszXvZ+Z/lxveBf6yhGsqnQIhlhzooZae7zV6YVM1Sdkw68dtAW3ow0pOdPANugvA==
+    dependencies:
+      unist-util-stringify-position "^1.1.1"
+  
+  vfile@^2.0.0:
+    version "2.3.0"
+    resolved "https://registry.yarnpkg.com/vfile/-/vfile-2.3.0.tgz#e62d8e72b20e83c324bc6c67278ee272488bf84a"
+    integrity sha512-ASt4mBUHcTpMKD/l5Q+WJXNtshlWxOogYyGYYrg4lt/vuRjC1EFQtlAofL5VmtVNIZJzWYFJjzGWZ0Gw8pzW1w==
+    dependencies:
+      is-buffer "^1.1.4"
+      replace-ext "1.0.0"
+      unist-util-stringify-position "^1.0.0"
+      vfile-message "^1.0.0"
+  
+  vm-browserify@1.1.0:
+    version "1.1.0"
+    resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.0.tgz#bd76d6a23323e2ca8ffa12028dc04559c75f9019"
+    integrity sha512-iq+S7vZJE60yejDYM0ek6zg308+UZsdtPExWP9VZoCFCz1zkJoXFnAX7aZfd/ZwrkidzdUZL0C/ryW+JwAiIGw==
+  
+  void-elements@^2.0.0:
+    version "2.0.1"
+    resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec"
+    integrity sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=
+  
+  watchpack@^2.0.0:
+    version "2.1.1"
+    resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.1.1.tgz#e99630550fca07df9f90a06056987baa40a689c7"
+    integrity sha512-Oo7LXCmc1eE1AjyuSBmtC3+Wy4HcV8PxWh2kP6fOl8yTlNS7r0K9l1ao2lrrUza7V39Y3D/BbJgY8VeSlc5JKw==
+    dependencies:
+      glob-to-regexp "^0.4.1"
+      graceful-fs "^4.1.2"
+  
+  wcwidth@^1.0.1:
+    version "1.0.1"
+    resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8"
+    integrity sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=
+    dependencies:
+      defaults "^1.0.3"
+  
+  webdriver-js-extender@2.1.0:
+    version "2.1.0"
+    resolved "https://registry.yarnpkg.com/webdriver-js-extender/-/webdriver-js-extender-2.1.0.tgz#57d7a93c00db4cc8d556e4d3db4b5db0a80c3bb7"
+    integrity sha512-lcUKrjbBfCK6MNsh7xaY2UAUmZwe+/ib03AjVOpFobX4O7+83BUveSrLfU0Qsyb1DaKJdQRbuU+kM9aZ6QUhiQ==
+    dependencies:
+      "@types/selenium-webdriver" "^3.0.0"
+      selenium-webdriver "^3.0.1"
+  
+  webdriver-manager@^12.0.6, webdriver-manager@^12.1.7:
+    version "12.1.8"
+    resolved "https://registry.yarnpkg.com/webdriver-manager/-/webdriver-manager-12.1.8.tgz#5e70e73eaaf53a0767d5745270addafbc5905fd4"
+    integrity sha512-qJR36SXG2VwKugPcdwhaqcLQOD7r8P2Xiv9sfNbfZrKBnX243iAkOueX1yAmeNgIKhJ3YAT/F2gq6IiEZzahsg==
+    dependencies:
+      adm-zip "^0.4.9"
+      chalk "^1.1.1"
+      del "^2.2.0"
+      glob "^7.0.3"
+      ini "^1.3.4"
+      minimist "^1.2.0"
+      q "^1.4.1"
+      request "^2.87.0"
+      rimraf "^2.5.2"
+      semver "^5.3.0"
+      xml2js "^0.4.17"
+  
+  webidl-conversions@^3.0.0:
+    version "3.0.1"
+    resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
+    integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=
+  
+  webpack-cli@^4.6.0:
+    version "4.6.0"
+    resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-4.6.0.tgz#27ae86bfaec0cf393fcfd58abdc5a229ad32fd16"
+    integrity sha512-9YV+qTcGMjQFiY7Nb1kmnupvb1x40lfpj8pwdO/bom+sQiP4OBMKjHq29YQrlDWDPZO9r/qWaRRywKaRDKqBTA==
+    dependencies:
+      "@discoveryjs/json-ext" "^0.5.0"
+      "@webpack-cli/configtest" "^1.0.2"
+      "@webpack-cli/info" "^1.2.3"
+      "@webpack-cli/serve" "^1.3.1"
+      colorette "^1.2.1"
+      commander "^7.0.0"
+      enquirer "^2.3.6"
+      execa "^5.0.0"
+      fastest-levenshtein "^1.0.12"
+      import-local "^3.0.2"
+      interpret "^2.2.0"
+      rechoir "^0.7.0"
+      v8-compile-cache "^2.2.0"
+      webpack-merge "^5.7.3"
+  
+  webpack-merge@^5.7.3:
+    version "5.7.3"
+    resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.7.3.tgz#2a0754e1877a25a8bbab3d2475ca70a052708213"
+    integrity sha512-6/JUQv0ELQ1igjGDzHkXbVDRxkfA57Zw7PfiupdLFJYrgFqY5ZP8xxbpp2lU3EPwYx89ht5Z/aDkD40hFCm5AA==
+    dependencies:
+      clone-deep "^4.0.1"
+      wildcard "^2.0.0"
+  
+  webpack-sources@^2.1.1:
+    version "2.2.0"
+    resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-2.2.0.tgz#058926f39e3d443193b6c31547229806ffd02bac"
+    integrity sha512-bQsA24JLwcnWGArOKUxYKhX3Mz/nK1Xf6hxullKERyktjNMC4x8koOeaDNTA2fEJ09BdWLbM/iTW0ithREUP0w==
+    dependencies:
+      source-list-map "^2.0.1"
+      source-map "^0.6.1"
+  
+  webpack@^5.3.2:
+    version "5.31.2"
+    resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.31.2.tgz#40d9b9d15b7d76af73d3f1cae895b82613a544d6"
+    integrity sha512-0bCQe4ybo7T5Z0SC5axnIAH+1WuIdV4FwLYkaAlLtvfBhIx8bPS48WHTfiRZS1VM+pSiYt7e/rgLs3gLrH82lQ==
+    dependencies:
+      "@types/eslint-scope" "^3.7.0"
+      "@types/estree" "^0.0.46"
+      "@webassemblyjs/ast" "1.11.0"
+      "@webassemblyjs/wasm-edit" "1.11.0"
+      "@webassemblyjs/wasm-parser" "1.11.0"
+      acorn "^8.0.4"
+      browserslist "^4.14.5"
+      chrome-trace-event "^1.0.2"
+      enhanced-resolve "^5.7.0"
+      es-module-lexer "^0.4.0"
+      eslint-scope "^5.1.1"
+      events "^3.2.0"
+      glob-to-regexp "^0.4.1"
+      graceful-fs "^4.2.4"
+      json-parse-better-errors "^1.0.2"
+      loader-runner "^4.2.0"
+      mime-types "^2.1.27"
+      neo-async "^2.6.2"
+      schema-utils "^3.0.0"
+      tapable "^2.1.1"
+      terser-webpack-plugin "^5.1.1"
+      watchpack "^2.0.0"
+      webpack-sources "^2.1.1"
+  
+  websocket-driver@>=0.5.1:
+    version "0.7.4"
+    resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760"
+    integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==
+    dependencies:
+      http-parser-js ">=0.5.1"
+      safe-buffer ">=5.1.0"
+      websocket-extensions ">=0.1.1"
+  
+  websocket-extensions@>=0.1.1:
+    version "0.1.4"
+    resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42"
+    integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==
+  
+  websocket-stream@^5.0.1:
+    version "5.5.2"
+    resolved "https://registry.yarnpkg.com/websocket-stream/-/websocket-stream-5.5.2.tgz#49d87083d96839f0648f5513bbddd581f496b8a2"
+    integrity sha512-8z49MKIHbGk3C4HtuHWDtYX8mYej1wWabjthC/RupM9ngeukU4IWoM46dgth1UOS/T4/IqgEdCDJuMe2039OQQ==
+    dependencies:
+      duplexify "^3.5.1"
+      inherits "^2.0.1"
+      readable-stream "^2.3.3"
+      safe-buffer "^5.1.2"
+      ws "^3.2.0"
+      xtend "^4.0.0"
+  
+  whatwg-url@^5.0.0:
+    version "5.0.0"
+    resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"
+    integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0=
+    dependencies:
+      tr46 "~0.0.3"
+      webidl-conversions "^3.0.0"
+  
+  which-boxed-primitive@^1.0.2:
+    version "1.0.2"
+    resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6"
+    integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==
+    dependencies:
+      is-bigint "^1.0.1"
+      is-boolean-object "^1.1.0"
+      is-number-object "^1.0.4"
+      is-string "^1.0.5"
+      is-symbol "^1.0.3"
+  
+  which-module@^2.0.0:
+    version "2.0.0"
+    resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
+    integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=
+  
+  which-typed-array@^1.1.2:
+    version "1.1.4"
+    resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.4.tgz#8fcb7d3ee5adf2d771066fba7cf37e32fe8711ff"
+    integrity sha512-49E0SpUe90cjpoc7BOJwyPHRqSAd12c10Qm2amdEZrJPCY2NDxaW01zHITrem+rnETY3dwrbH3UUrUwagfCYDA==
+    dependencies:
+      available-typed-arrays "^1.0.2"
+      call-bind "^1.0.0"
+      es-abstract "^1.18.0-next.1"
+      foreach "^2.0.5"
+      function-bind "^1.1.1"
+      has-symbols "^1.0.1"
+      is-typed-array "^1.1.3"
+  
+  which@^1.1.1, which@^1.2.1, which@^1.2.14, which@^1.2.9, which@~1.3.0:
+    version "1.3.1"
+    resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
+    integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==
+    dependencies:
+      isexe "^2.0.0"
+  
+  which@^2.0.1:
+    version "2.0.2"
+    resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
+    integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==
+    dependencies:
+      isexe "^2.0.0"
+  
+  wildcard@^2.0.0:
+    version "2.0.0"
+    resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec"
+    integrity sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==
+  
+  word-wrap@^1.2.3, word-wrap@~1.2.3:
+    version "1.2.3"
+    resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
+    integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==
+  
+  wordwrap@^1.0.0:
+    version "1.0.0"
+    resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"
+    integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=
+  
+  wrap-ansi@^2.0.0:
+    version "2.1.0"
+    resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85"
+    integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=
+    dependencies:
+      string-width "^1.0.1"
+      strip-ansi "^3.0.1"
+  
+  wrap-ansi@^6.2.0:
+    version "6.2.0"
+    resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53"
+    integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==
+    dependencies:
+      ansi-styles "^4.0.0"
+      string-width "^4.1.0"
+      strip-ansi "^6.0.0"
+  
+  wrap-ansi@^7.0.0:
+    version "7.0.0"
+    resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
+    integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
+    dependencies:
+      ansi-styles "^4.0.0"
+      string-width "^4.1.0"
+      strip-ansi "^6.0.0"
+  
+  wrappy@1:
+    version "1.0.2"
+    resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
+    integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
+  
+  ws@^3.2.0:
+    version "3.3.3"
+    resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2"
+    integrity sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==
+    dependencies:
+      async-limiter "~1.0.0"
+      safe-buffer "~5.1.0"
+      ultron "~1.1.0"
+  
+  ws@^7.2.3:
+    version "7.4.4"
+    resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.4.tgz#383bc9742cb202292c9077ceab6f6047b17f2d59"
+    integrity sha512-Qm8k8ojNQIMx7S+Zp8u/uHOx7Qazv3Yv4q68MiWWWOJhiwG5W3x7iqmRtJo8xxrciZUY4vRxUTJCKuRnF28ZZw==
+  
+  ws@~8.2.3:
+    version "8.2.3"
+    resolved "https://registry.yarnpkg.com/ws/-/ws-8.2.3.tgz#63a56456db1b04367d0b721a0b80cae6d8becbba"
+    integrity sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==
+  
+  x-is-string@^0.1.0:
+    version "0.1.0"
+    resolved "https://registry.yarnpkg.com/x-is-string/-/x-is-string-0.1.0.tgz#474b50865af3a49a9c4657f05acd145458f77d82"
+    integrity sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI=
+  
+  xml2js@^0.4.17:
+    version "0.4.23"
+    resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.23.tgz#a0c69516752421eb2ac758ee4d4ccf58843eac66"
+    integrity sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==
+    dependencies:
+      sax ">=0.6.0"
+      xmlbuilder "~11.0.0"
+  
+  xmlbuilder@~11.0.0:
+    version "11.0.1"
+    resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3"
+    integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==
+  
+  xtend@^4.0.0, xtend@^4.0.1, xtend@^4.0.2, xtend@~4.0.1:
+    version "4.0.2"
+    resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
+    integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
+  
+  "y18n@^3.2.1 || ^4.0.0", y18n@^4.0.0:
+    version "4.0.3"
+    resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf"
+    integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==
+  
+  y18n@^5.0.5:
+    version "5.0.8"
+    resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
+    integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==
+  
+  yallist@^4.0.0:
+    version "4.0.0"
+    resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
+    integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
+  
+  yargs-parser@^11.1.1:
+    version "11.1.1"
+    resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-11.1.1.tgz#879a0865973bca9f6bab5cbdf3b1c67ec7d3bcf4"
+    integrity sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==
+    dependencies:
+      camelcase "^5.0.0"
+      decamelize "^1.2.0"
+  
+  yargs-parser@^18.1.2:
+    version "18.1.3"
+    resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0"
+    integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==
+    dependencies:
+      camelcase "^5.0.0"
+      decamelize "^1.2.0"
+  
+  yargs-parser@^20.2.2:
+    version "20.2.9"
+    resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee"
+    integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==
+  
+  yargs@^12.0.5:
+    version "12.0.5"
+    resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.5.tgz#05f5997b609647b64f66b81e3b4b10a368e7ad13"
+    integrity sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==
+    dependencies:
+      cliui "^4.0.0"
+      decamelize "^1.2.0"
+      find-up "^3.0.0"
+      get-caller-file "^1.0.1"
+      os-locale "^3.0.0"
+      require-directory "^2.1.1"
+      require-main-filename "^1.0.1"
+      set-blocking "^2.0.0"
+      string-width "^2.0.0"
+      which-module "^2.0.0"
+      y18n "^3.2.1 || ^4.0.0"
+      yargs-parser "^11.1.1"
+  
+  yargs@^15.3.1:
+    version "15.4.1"
+    resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8"
+    integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==
+    dependencies:
+      cliui "^6.0.0"
+      decamelize "^1.2.0"
+      find-up "^4.1.0"
+      get-caller-file "^2.0.1"
+      require-directory "^2.1.1"
+      require-main-filename "^2.0.0"
+      set-blocking "^2.0.0"
+      string-width "^4.2.0"
+      which-module "^2.0.0"
+      y18n "^4.0.0"
+      yargs-parser "^18.1.2"
+  
+  yargs@^16.1.1:
+    version "16.2.0"
+    resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66"
+    integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==
+    dependencies:
+      cliui "^7.0.2"
+      escalade "^3.1.1"
+      get-caller-file "^2.0.5"
+      require-directory "^2.1.1"
+      string-width "^4.2.0"
+      y18n "^5.0.5"
+      yargs-parser "^20.2.2"
+  
+  yauzl@^2.10.0:
+    version "2.10.0"
+    resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9"
+    integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=
+    dependencies:
+      buffer-crc32 "~0.2.3"
+      fd-slicer "~1.1.0"
+  
+  yocto-queue@^0.1.0:
+    version "0.1.0"
+    resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
+    integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
diff --git a/yarn.lock b/yarn.lock
new file mode 100644
index 000000000..395d76f97
--- /dev/null
+++ b/yarn.lock
@@ -0,0 +1,13 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+gridstack@12.1.2:
+  version "12.1.2"
+  resolved "https://registry.yarnpkg.com/gridstack/-/gridstack-12.1.2.tgz#784f6d55873bb48fa9230c1284f769c9fbf785a8"
+  integrity sha512-IC1mkm5xonhAnftwIxsG+B3bawxC61ciKWEvX15ExpVQPbNVN7O9aZZhM7Y/eE4JaIR8PXrdkjd12gMnwNYRLQ==
+
+prettier@3.2.5:
+  version "3.2.5"
+  resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.2.5.tgz#e52bc3090586e824964a8813b09aba6233b28368"
+  integrity sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==
