[
  {
    "path": ".codesandbox/ci.json",
    "content": "{\n  \"sandboxes\": [\"react\", \"o104x95y86\"]\n}\n"
  },
  {
    "path": ".editorconfig",
    "content": "# editorconfig.org\nroot = true\n\n[*]\ncharset = utf-8\nindent_size = 2\nindent_style = space\ninsert_final_newline = true\ntrim_trailing_whitespace = true\n\n# Markdown syntax specifies that trailing whitespaces can be meaningful,\n# so let’s not trim those. e.g. 2 trailing spaces = linebreak (<br />)\n# See https://daringfireball.net/projects/markdown/syntax#p\n[*.md]\ntrim_trailing_whitespace = false\n"
  },
  {
    "path": ".eslintrc.json",
    "content": "{\n  \"extends\": [\"plugin:shopify/react\", \"plugin:prettier/recommended\"],\n  \"rules\": {\n    \"no-process-env\": \"off\",\n    \"no-lonely-if\": \"off\",\n    \"no-undefined\": \"off\",\n    \"no-param-reassign\": \"off\",\n    \"no-mixed-operators\": \"off\",\n    \"no-misleading-character-class\": \"off\",\n    \"require-atomic-updates\": \"off\",\n    \"prefer-object-spread\": \"off\",\n    \"lines-around-comment\": \"off\",\n    \"function-paren-newline\": \"off\",\n    \"promise/catch-or-return\": \"off\",\n    \"react/forbid-prop-types\": \"off\",\n    \"react/jsx-filename-extension\": \"off\",\n    \"react/no-unused-prop-types\": \"off\",\n    \"react/no-string-refs\": 1,\n    \"react/no-deprecated\": 1,\n    \"shopify/binary-assignment-parens\": \"off\",\n    \"sort-class-members/sort-class-members\": \"off\"\n  }\n}\n"
  },
  {
    "path": ".gitignore",
    "content": "*.DS_Store\nnode_modules\ndist\nstyles.min.css\nstyles.min.css.map\ncoverage\nnpm-debug.log\n"
  },
  {
    "path": ".npmignore",
    "content": ".github\n.babelrc\ncoverage\nsrc\ntest\n.*\n*.md\ncodecov.yml\n.travis.yml\n"
  },
  {
    "path": ".prettierrc",
    "content": "{\n  \"arrowParens\": \"always\",\n  \"bracketSpacing\": false,\n  \"singleQuote\": true,\n  \"trailingComma\": \"all\"\n}\n"
  },
  {
    "path": ".storybook/config.js",
    "content": "import {addParameters, configure} from '@storybook/react';\nimport theme from './theme';\n\naddParameters({\n  options: {\n    showAddonPanel: false,\n    theme,\n  },\n});\n\nfunction loadStories() {\n  require('../src/.stories/index.js');\n}\n\nconfigure(loadStories, module);\n"
  },
  {
    "path": ".storybook/manager-head.html",
    "content": "<link\n  href=\"https://fonts.googleapis.com/css?family=Roboto:400,500,700\"\n  rel=\"stylesheet\"\n/>\n<link\n  rel=\"icon\"\n  type=\"image/png\"\n  sizes=\"32x32\"\n  href=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAC/VBMVEUAAAAUcP8ea/8Ldf8iav8gav8TcP8nZ/8rZv8xY/83Yf88Xv84YP80Yv9AXf9GWv9PVv9DXP9cUP9WU/9fT/9aUf9jTv9nTP9tSf9zR/95RP8sav92Rv99Qv+CQP+DQP9xSf+GP/+XOP+UOP+ZNv+rLv+fNP+jMv+nL/+oMP+uLf+0K//NIP+4Kf+9J/+/Jv/LIf/BJf/UHf8cbP8dbP8dbP8cbP8hav8hav8hav8hav8iav8laP8kaf8jaf8jaf8jaf8laP8maP8rZv8rZv8rZv8rZv8rZv8xY/80Zf+kvv+gu/+gu/+gu/+gu/+2zf8wYv8xY/8xY/82Yf85Y/+1u/+wuP+wuP+wuP+wuP/My/81YP83Yf83Yf88Xv88Xv88Xv88Xv88Xv9CXP9DW/9FW/9FW/9FW/9DW/9CXP9GWv9HWv9HWv9HWv9HWv9GWv9LWP9KWP9KWP9JWP9JWf9IWf9dUP9bUf9aUf9aUf9ZUv9ZUv9eUP9dUP9cUP9cUP9dUP9eUP9jTv9iTv9hT/9fT/9fT/9fT/9hTv9iTv9nTP9nTP9nTP9nTP9nTP9tSf9tSf9sRf+jw/+gu/+gu/+gu/+gu/+kxv9sRv9tSf9zR/9zR/9xQ/+2vv+yt/+yt/+yt/+yt/+4wf9xRP9zR/95RP95RP95RP95RP95RP99Q/9+Qv9/Qf+AQf+AQf9/Qf9+Qv+CQP+DQP+DQP+DQP+DQP+CQP+DQP+DQP+GP/+HPv+IPv+UOf+VOP+VOP+VOP+VOP+ZNv+YN/+YN/+YN/+YN/+ZNv+dNf+cNf+aNv+aNv+aNv+cNf+dNP+jMv+jMv+jMv+jMv+iMv+oMP+oM/+fwf+gu/+gu/+gu/+gu/+e2/+oLv+oMP+oMP+uLf+uMf+xvP+xt/+xt/+xt/+xt/+x0/+uLP+uLf+uLf+0K/+0K/+0K/+0K/+0K/+5KP+7KP+8J/+8J/+8J/+6KP+5KP+9J/++Jv++Jv++Jv+9J//DJP/CJP/CJP/DJP////88deaDAAAA/nRSTlMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGCgkETbLEnyPhs36AgdKS90iGtAT2SG6sqaqVEoK0BPZHYpqYmYYPgrQE90aEtATpnl9iY8ScY8nX1rgxARAXFRUKAREaGxwPU87b2sNGDsWiV1lYtcMX01V02hfTUkGioKGeLnHaF9NRQaKgoZ4ucdoW01d22gq4woiJzrI2qL28mywCBQYHAwEQFxYLY8nX1rgx6Z5fYmPEnPdGhLQE9kdimpiZhg+CtAT2SG6sqaqVEoK0BPdIhrQE4bN+gIHSkk2yxJ8jBgoJBCSYEg0AAAABYktHRP7SAMJTAAAAB3RJTUUH4wMMFAwxtzZCfgAAAaVJREFUOMtjYCAEGI1NTDGBiakZEzNEgbmFJVZgZc3CClZgY2tnjwU4ODqxsYMVOLtwYLGYg8PVzR0i4eHp5e2DDnz9/AMCgzjBCoJDQsPC0UFEZFR0TCwXWEFcPDcWK3i4ExKTIBLJKalpWEB6RiYvH1hBVnZOLhaQk5fPzw9WUFBYBALFJWigVEAQyUqhsvIKNFBZBQLVwmB5EdGa2rp6LKCuoRGsQKypuaW1DQto7+gEKxDv6u4RxxaT4r19YFqif8LESZOnoIOp06bPmAlWIDlr9py58+ajgwULFy1eAlYgtXTZcilpTBtkpFasBDNkV61es3YdNrB+A1iBnPzGTZu3YAGbt26DmKWguH0HGti5CwR2KzLs2bsPBPajgwNKyhDNBw8dPoIFHD56TEUFrOD4iZOnsIDTZ86qqoEVnDuvjiUINdQvXLwEkbh85eq16+jgxs1bt+/c1QQruHf/wcNH6ODxk6fPnr/QAit4+UobixXa2q/fvIVIvHv/4SMW8OnzFx1dsIKv375jBT9+6umDFRj8+v0HE/z+89fQiGDGBwMAfwKLipcveMIAAAAldEVYdGRhdGU6Y3JlYXRlADIwMTktMDMtMTJUMjA6MTI6NDkrMDE6MDD6OZKaAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE5LTAzLTEyVDIwOjEyOjQ5KzAxOjAwi2QqJgAAAFd6VFh0UmF3IHByb2ZpbGUgdHlwZSBpcHRjAAB4nOPyDAhxVigoyk/LzEnlUgADIwsuYwsTIxNLkxQDEyBEgDTDZAMjs1Qgy9jUyMTMxBzEB8uASKBKLgDqFxF08kI1lQAAAABJRU5ErkJggg==\"\n/>\n<link\n  rel=\"icon\"\n  type=\"image/png\"\n  sizes=\"16x16\"\n  href=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAABmFBMVEUgav8JfP8AAAAnaP8uZP85X/9BXP9jTv9qSv92Rf99Qv+eNP+lMf+xLP+4Kf+/Jv/jFP8fa/8fa/8fa/8jaf8eaP8dZ/8dZ/8gaP8kaf8oZ/8yaP+Tsf+YtP+YtP+ZtP+Ao/8sZP8uZP8+Yv+lsv+otf+otP+otf+So/85X/85X/9EW/9EV/9DV/9DV/9DV/9EWf9EW/8/Xf9JWf9IWf9IWf9OVv9SVf9SVf9XU/9cUf9bUf9bUf9jTv9gT/9cTv9bTP9bTP9bTP9cTv9gT/9qSv9qTP+esf+it/+it/+iuP+aqf9qS/92Rf93Rv+mo/+qrP+qrP+inP92Rf98Q/+AQf+BPv+APP+BPP+BPP+BPv+AQf+WOP+XN/+XN/+TOf+PO/+PO/+KPf+DQP+EP/+FP/+bNf+YM/+YMv+YMv+ZNP+bNf+fNP+lNv+jsf+jtf+jtf+jmv+lMP+lMf+xMf+vp/+vrP+vrP+vrf+wkP+yKv+xLP+7J/++I/++Iv++Iv+9JP+7KP+3Kf/AJf/AJv+/Jv/AJf/////NvskwAAAAh3RSTlMAAAAAAAAAAAAAAAAAAAAAAA4aCZOEgYKJdQaVTmBfYD2DEpJEVlVVNoITmoJ/fn2FegYRHx4uQUAtISEQDoWBfH1+g5Iffz9YV1g9lB6CRl9eRZYLfYaBgoOIiBEfHic0MyAUFAiagn9+hnsHkkRWVTaCE5VOYF9gPYMSk4SBgol1Bg4aGgk3BSnTAAAAAWJLR0SH+9kLywAAAAd0SU1FB+MDDBQMMbc2Qn4AAADJSURBVBjTYxAUQgBhBkYmBhFRMXEIEJOQlGJmYpCWkZWDAHkFRSUWJgZlFVU1CFDX0NRiZWLQ1tHV04cAA0MjNiYGYxNTM3MLCLC0srZhYGK3tbN3gABHJ2cXBiYOVzd3D08I8PL2YWDi9PXzDwiEgICgYAYmrpDQsHAIiIiMimaIiY2LT4CAxKTklFSGtPSMjEwIyMrO4WZiyM3LL4CCwqJiHiaGktKycgioqKyq5mViqKmtq4eAuobGJj4mhuaWVhhoaeMXYAIAHs1DWNndumoAAAAldEVYdGRhdGU6Y3JlYXRlADIwMTktMDMtMTJUMjA6MTI6NDkrMDE6MDD6OZKaAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE5LTAzLTEyVDIwOjEyOjQ5KzAxOjAwi2QqJgAAAFd6VFh0UmF3IHByb2ZpbGUgdHlwZSBpcHRjAAB4nOPyDAhxVigoyk/LzEnlUgADIwsuYwsTIxNLkxQDEyBEgDTDZAMjs1Qgy9jUyMTMxBzEB8uASKBKLgDqFxF08kI1lQAAAABJRU5ErkJggg==\"\n/>\n<link\n  rel=\"mask-icon\"\n  href=\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/Pgo8IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDIwMDEwOTA0Ly9FTiIKICJodHRwOi8vd3d3LnczLm9yZy9UUi8yMDAxL1JFQy1TVkctMjAwMTA5MDQvRFREL3N2ZzEwLmR0ZCI+CjxzdmcgdmVyc2lvbj0iMS4wIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiB3aWR0aD0iNjEyLjAwMDAwMHB0IiBoZWlnaHQ9IjYxMi4wMDAwMDBwdCIgdmlld0JveD0iMCAwIDYxMi4wMDAwMDAgNjEyLjAwMDAwMCIKIHByZXNlcnZlQXNwZWN0UmF0aW89InhNaWRZTWlkIG1lZXQiPgo8bWV0YWRhdGE+CkNyZWF0ZWQgYnkgcG90cmFjZSAxLjExLCB3cml0dGVuIGJ5IFBldGVyIFNlbGluZ2VyIDIwMDEtMjAxMwo8L21ldGFkYXRhPgo8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLjAwMDAwMCw2MTIuMDAwMDAwKSBzY2FsZSgwLjEwMDAwMCwtMC4xMDAwMDApIgpmaWxsPSIjMDAwMDAwIiBzdHJva2U9Im5vbmUiPgo8cGF0aCBkPSJNMjUxIDU2ODQgYy0xMDMgLTM2IC0xNzEgLTEwMCAtMjIwIC0yMDMgbC0yNiAtNTYgLTIgLTQ1MCBjLTIgLTM5OQowIC00NTYgMTUgLTUwMSAzMyAtOTkgMTAwIC0xNzcgMTkyIC0yMjIgbDU1IC0yNyAyMTk1IDAgMjE5NSAwIDU1IDI4IGM3MSAzNQoxMjMgODQgMTU5IDE1MCAzMCA1MyA1MiAxMzMgNTEgMTc3IC0xIDE0IC0xIDE4OSAtMSAzOTAgMSA0MTAgMCA0MjcgLTIzIDQ5MAotMzUgOTUgLTk1IDE2MiAtMTg2IDIwNyBsLTU1IDI4IC0yMTgwIDIgYy0xOTQ5IDIgLTIxODUgMSAtMjIyNCAtMTN6IG00MzY2Ci0yNDMgYzE4IC03IDM4IC0yOCA0OSAtNTAgMTkgLTM2IDIwIC02MiAxOSAtNDM4IDAgLTQzNyAxIC00MjkgLTYxIC00NjkgLTI0Ci0xNiAtMTgxIC0xNyAtMjE2NCAtMTcgLTE5ODQgMCAtMjE0MCAxIC0yMTY0IDE3IC02MiA0MCAtNjEgMzIgLTYyIDQ2OCAwIDQ0NAoxIDQ1MSA2MyA0ODQgMzUgMTkgOTEgMTkgMjE2NCAxOCAxNjQ2IC0xIDIxMzQgLTQgMjE1NiAtMTN6Ii8+CjxwYXRoIGQ9Ik00NDAgNTA2MyBjMCAtMjEgMCAtNTggMCAtODMgLTEgLTI1IC0xIC02MiAtMSAtODIgbDEgLTM4IDE5NzQgMApjMTA4NiAwIDE5NzcgMyAxOTc5IDggNiA4IDEwIDExMSA4IDE4NSBsLTEgNDcgLTE5ODAgMCAtMTk4MSAwIDEgLTM3eiIvPgo8cGF0aCBkPSJNMTQwMyAzODAxIGMtMjkgLTExIC02MSAtMjUgLTcxIC0zMyAtNDAgLTI4IC05MiAtNzggLTkyIC04OCAwIC01Ci00IC0xMCAtOCAtMTAgLTEyIDAgLTUwIC04OCAtNjIgLTE0MyAtMTEgLTQ5IC0xNCAtNzkyIC01IC04NzcgMTMgLTEwOCAxMDAKLTIyNyAyMDUgLTI3OCBsNTUgLTI3IDIxNzUgLTMgYzIxNDcgLTIgMjE3NSAtMiAyMjM0IDE4IDEyOSA0MyAyMjAgMTU1IDI0MgoyOTggMyAyMCA3IDM4IDkgNDAgMSAyIC0xIDE5IC01IDM4IC00IDE4IC01IDM0IC0xIDM0IDMgMCA1IDI0IDMgNTIgLTEgMjkgLTMKNjAgLTMgNjggMCA4IDAgNjIgMCAxMjAgMCA1OCAwIDExMiAxIDEyMCAwIDggMCAzNSAtMSA2MCAtMSAyNSAtMSA1MiAwIDYwIDQKODEgLTEgMjQ4IC05IDI4NSAtMjUgMTEzIC0xMTcgMjIyIC0yMjEgMjYzIGwtNTQgMjEgLTIxNzAgMCBjLTIwOTQgMCAtMjE3MiAwCi0yMjIyIC0xOHogbTQzODAgLTI0NCBjNjMgLTQxIDYyIC0zMiA2MiAtNDc2IDEgLTM5MyAwIC00MDUgLTIwIC00MzUgLTQzIC02NAoxMjUgLTYwIC0yMjExIC02MCAtMTk5MiAwIC0yMTMzIDEgLTIxNTggMTcgLTYyIDQxIC02MSAzMiAtNjEgNDcyIC0xIDQyMSAwCjQyOSA0NSA0NzAgMTIgMTAgNDAgMjEgNjMgMjQgMjMgMyA5OTAgNiAyMTQ4IDYgMTk3NCAtMSAyMTA4IC0yIDIxMzIgLTE4eiIvPgo8cGF0aCBkPSJNMzU1MyAzMTgyIGwtMTkxMyAtMiAwIC0xMjAgMCAtMTIwIDE5NzQgMCBjMTE3MCAwIDE5NzcgNCAxOTgwIDkgNgo5IDkgOTggNyAxOTAgLTEgMzggLTMgNDMgLTIxIDM4IC0xMSAtMyAtMjIgLTIgLTI1IDMgLTMgNCAtMjAgNCAtMzkgMCAtMTkgLTQKLTM4IC01IC00MyAtMSAtNCAzIC04NjkgNSAtMTkyMCAzeiIvPgo8cGF0aCBkPSJNMjQxIDE4ODAgYy03MSAtMjYgLTEzMiAtNzQgLTE3NSAtMTM4IC02NiAtMTAwIC02NyAtMTEyIC02NCAtNjA2CmwzIC00NDEgMzMgLTY3IGMzOSAtNzkgOTcgLTEzOSAxNzIgLTE3NiBsNTUgLTI3IDIxOTUgMCAyMTk1IDAgNTUgMjggYzQ5IDI1Cjg2IDU0IDEzNCAxMDggMjQgMjcgNTMgOTIgNjUgMTQ3IDEyIDU5IDE3IDgyMyA2IDg4OCAtMjAgMTExIC0xMDQgMjIyIC0yMDUKMjcyIGwtNTUgMjcgLTIxODAgMiBjLTIxMzAgMiAtMjE4MSAyIC0yMjM0IC0xN3ogbTQzODMgLTI0NCBjNjIgLTQwIDYxIC0zMgo2MiAtNDY5IDAgLTQzNyAwIC00MzcgLTU5IC00ODEgLTI2IC0xOSAtNjEgLTE5IC0yMTY2IC0xOSAtMjAwNiAwIC0yMTQxIDEKLTIxNjYgMTcgLTYyIDQwIC02MSAzNSAtNjAgNDgzIGwwIDQwOSAzMiAzNCBjMjMgMjUgNDMgMzUgNzUgMzkgMjMgMyA5OTEgNgoyMTUwIDUgMTk1MiAtMSAyMTA4IC0yIDIxMzIgLTE4eiIvPgo8cGF0aCBkPSJNNDQwIDEyMjMgYzAgLTIxIDAgLTU4IDAgLTgzIC0xIC0yNSAtMSAtNjIgLTEgLTgyIGwxIC0zOCAxOTc0IDAKYzEwODYgMCAxOTc3IDMgMTk3OSA4IDYgOCAxMCAxMTEgOCAxODUgbC0xIDQ3IC0xOTgwIDAgLTE5ODEgMCAxIC0zN3oiLz4KPC9nPgo8L3N2Zz4K\"\n  color=\"#5bbad5\"\n/>\n<style>\n  nav span {\n    font-size: 14px;\n  }\n</style>\n"
  },
  {
    "path": ".storybook/theme.js",
    "content": "import {create} from '@storybook/theming';\n\nexport default create({\n  base: 'light',\n\n  colorSecondary: '#9276ff',\n\n  // UI\n  appBg: 'white',\n  appContentBg: '#f9f9f9',\n  appBorderColor: 'grey',\n  appBorderRadius: 4,\n\n  // Typography\n  fontBase: '\"Roboto\", Helvetica Neue, Helvetica, Arial, sans-serif',\n  fontCode: 'monospace',\n\n  // Text colors\n  textColor: '#364149',\n  textInverseColor: 'rgba(255,255,255,0.9)',\n\n  // Toolbar default and active colors\n  barTextColor: '#FFF',\n  barSelectedColor: '#FFF',\n  barBg: '#9276ff',\n\n  // Form colors\n  inputBg: 'white',\n  inputBorder: '#efefef',\n  inputTextColor: '#364149',\n  inputBorderRadius: 0,\n\n  brandTitle: 'React Sortable HOC',\n  brandUrl: 'https://github.com/clauderic/react-sortable-hoc',\n  brandImage:\n    'https://user-images.githubusercontent.com/1416436/54170652-dfd59d80-444d-11e9-9c51-658638c0454b.png',\n});\n"
  },
  {
    "path": ".storybook/webpack.config.js",
    "content": "module.exports = {\n  module: {\n    rules: [\n      {\n        test: /(\\.scss)$/,\n        use: [\n          'style-loader',\n          {\n            loader: 'css-loader',\n            options: {\n              modules: true,\n              localIdentName: '[name]__[local]',\n            },\n          },\n          {\n            loader: 'postcss-loader',\n            options: {\n              plugins: [require('autoprefixer')],\n            },\n          },\n          'sass-loader',\n        ],\n      },\n      {\n        test: /(\\.css)$/,\n        use: ['style-loader', 'css-loader'],\n      },\n    ],\n  },\n};\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: node_js\nnode_js:\n  - 10\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Change Log\n\nAll notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.\n\n<a name=\"2.0.0\"></a>\n\n# [2.0.0](https://github.com/clauderic/react-sortable-hoc/compare/v1.11.0...v2.0.0) (2021-03-18)\n\n### Bug Fixes\n\n- Fixed React strict mode warnings by upgrading to new React context API and removing legacy refs ([#624](https://github.com/clauderic/react-sortable-hoc/pull/624)). Since the new context API was introduced in React ^16.3.0, the peer dependencies had to be upgraded accordingly.\n- Check if event is cancellable before calling `event.preventDefault()` [#752](https://github.com/clauderic/react-sortable-hoc/pull/752).\n- Fix touch events being lost by listening to event.target on mobile [#586](https://github.com/clauderic/react-sortable-hoc/pull/586).\n- Added `disableAutoscroll` prop to PropType definitions [#755](https://github.com/clauderic/react-sortable-hoc/pull/755).\n\n### Dependencies\n\n- Updated minimum peer dependencies for `react` and `react-dom` to ^16.3.0. Added ^17.0.0 to list of supported peer dependencies.\n\n<a name=\"1.11.0\"></a>\n\n# [1.11.0](https://github.com/clauderic/react-sortable-hoc/compare/v1.10.1...v1.11.0) (2020-01-20)\n\n### Bug Fixes\n\n- clear autoscroller when autoscroll is disabled ([#604](https://github.com/clauderic/react-sortable-hoc/issues/604)) ([3fd83f9](https://github.com/clauderic/react-sortable-hoc/commit/3fd83f9))\n- Fix UMD path ([#611](https://github.com/clauderic/react-sortable-hoc/pull/611)) ([f61331d](https://github.com/clauderic/react-sortable-hoc/commit/f61331d))\n\n### Features\n\n- Add CSS Grid grid-gap support ([#657](https://github.com/clauderic/react-sortable-hoc/issues/657)) ([4efcaa2](https://github.com/clauderic/react-sortable-hoc/commit/4efcaa2))\n\n<a name=\"1.10.1\"></a>\n\n## [1.10.1](https://github.com/clauderic/react-sortable-hoc/compare/v1.10.0...v1.10.1) (2019-08-22)\n\n### Bug Fixes\n\n- PropType definition for keyCodes was incorrect ([eaf5070](https://github.com/clauderic/react-sortable-hoc/commit/eaf5070))\n\n<a name=\"1.10.0\"></a>\n\n# [1.10.0](https://github.com/clauderic/react-sortable-hoc/compare/v1.9.1...v1.10.0) (2019-08-22)\n\n### Bug Fixes\n\n- don't spread the keysToOmit parameter in omit util ([#563](https://github.com/clauderic/react-sortable-hoc/issues/563)) ([1c69772](https://github.com/clauderic/react-sortable-hoc/commit/1c69772))\n- Fix broken UMD build ([#587](https://github.com/clauderic/react-sortable-hoc/issues/587)) ([6cb7750](https://github.com/clauderic/react-sortable-hoc/commit/6cb7750))\n- remove browser field with umd bundle ([#541](https://github.com/clauderic/react-sortable-hoc/issues/541)) ([d3b30fd](https://github.com/clauderic/react-sortable-hoc/commit/d3b30fd)\n\n### Features\n\n- Add keyCodes prop to configure the keyboard shortcuts ([#588](https://github.com/clauderic/react-sortable-hoc/issues/588)) ([4c6d8dd](https://github.com/clauderic/react-sortable-hoc/commit/4c6d8dd))\n\n<a name=\"1.9.1\"></a>\n\n## [1.9.1](https://github.com/clauderic/react-sortable-hoc/compare/v1.9.0...v1.9.1) (2019-04-24)\n\n### Bug Fixes\n\n- do not copy canvas context if it has neither width nor height ([#530](https://github.com/clauderic/react-sortable-hoc/issues/530)) ([3808437](https://github.com/clauderic/react-sortable-hoc/commit/3808437))\n- pass isKeySorting to onSortOver and updateBeforeSortStart handler props ([#531](https://github.com/clauderic/react-sortable-hoc/issues/531)) ([763fd33](https://github.com/clauderic/react-sortable-hoc/commit/763fd33)\n\n<a name=\"1.9.0\"></a>\n\n# [1.9.0](https://github.com/clauderic/react-sortable-hoc/compare/v1.8.3...v1.9.0) (2019-04-23)\n\n### Bug Fixes\n\n- issue with radio input name collision when cloning helper ([5337c97](https://github.com/clauderic/react-sortable-hoc/commit/5337c97))\n\n### Features\n\n- add support for keyboard sorting ([#501](https://github.com/clauderic/react-sortable-hoc/issues/501)) ([439b92f](https://github.com/clauderic/react-sortable-hoc/commit/439b92f))\n- prevent sort start on contentEditable target ([d64c8cf](https://github.com/clauderic/react-sortable-hoc/commit/d64c8cf))\n\n<a name=\"1.8.3\"></a>\n\n## [1.8.3](https://github.com/clauderic/react-sortable-hoc/compare/v1.8.2...v1.8.3) (2019-03-20)\n\n### Bug Fixes\n\n- issue with windowAsScrollContainer and translation offsets ([0391e62](https://github.com/clauderic/react-sortable-hoc/commit/0391e62))\n\n### Features\n\n- Add disableAutoscroll prop ([#484](https://github.com/clauderic/react-sortable-hoc/issues/484)) ([7845e76](https://github.com/clauderic/react-sortable-hoc/commit/7845e76))\n- added helperContainer prop ([286eff4](https://github.com/clauderic/react-sortable-hoc/commit/286eff4))\n- allow helperContainer prop to be a function returning an HTMLElement ([#489](https://github.com/clauderic/react-sortable-hoc/issues/489)) ([f4a9b4a](https://github.com/clauderic/react-sortable-hoc/commit/f4a9b4a))\n- Detect scroll container automatically ([#507](https://github.com/clauderic/react-sortable-hoc/issues/507)) ([6572921](https://github.com/clauderic/react-sortable-hoc/commit/6572921))\n\n<a name=\"1.8.2\"></a>\n\n## [1.8.2](https://github.com/clauderic/react-sortable-hoc/compare/v1.8.1...v1.8.2) (2019-03-19)\n\n### Bug Fixes\n\n- issue with getComputedStyle and getScrollingParent ([b104249](https://github.com/clauderic/react-sortable-hoc/commit/b104249))\n\n<a name=\"1.8.1\"></a>\n\n## [1.8.1](https://github.com/clauderic/react-sortable-hoc/compare/v1.8.0...v1.8.1) (2019-03-18)\n\n### Bug Fixes\n\n- issue with cloning canvas context of dragged items ([#512](https://github.com/clauderic/react-sortable-hoc/issues/512)) ([4df34ad](https://github.com/clauderic/react-sortable-hoc/commit/4df34ad))\n\n<a name=\"1.8.0\"></a>\n\n# [1.8.0](https://github.com/clauderic/react-sortable-hoc/compare/v1.1.0...v1.8.0) (2019-03-18)\n\n### Bug Fixes\n\n- added prop-types to peerDependencies ([0e855c5](https://github.com/clauderic/react-sortable-hoc/commit/0e855c5))\n- copy canvas content into cloned node ([43ad122](https://github.com/clauderic/react-sortable-hoc/commit/43ad122))\n- get updated index after updateBeforeSortStart ([4471a0a](https://github.com/clauderic/react-sortable-hoc/commit/4471a0a))\n- helperContainer PropType definition broke server-side rendering ([#471](https://github.com/clauderic/react-sortable-hoc/issues/471)) ([c0eef97](https://github.com/clauderic/react-sortable-hoc/commit/c0eef97))\n- lock axis story should not use lockToContainerEdges ([db1d3a9](https://github.com/clauderic/react-sortable-hoc/commit/db1d3a9))\n- omit disableAutoscroll prop ([#502](https://github.com/clauderic/react-sortable-hoc/issues/502)) ([e994e73](https://github.com/clauderic/react-sortable-hoc/commit/e994e73))\n- omit spreading helperContainer prop ([#497](https://github.com/clauderic/react-sortable-hoc/issues/497)) ([12bafdf](https://github.com/clauderic/react-sortable-hoc/commit/12bafdf))\n- overflow bug while dragging an item upwards in a grid ([1a2c87e](https://github.com/clauderic/react-sortable-hoc/commit/1a2c87e))\n- replace process.env.NODE_ENV in UMD builds ([16135df](https://github.com/clauderic/react-sortable-hoc/commit/16135df))\n- update helperContainer prop type definition ([#491](https://github.com/clauderic/react-sortable-hoc/issues/491)) ([fd30383](https://github.com/clauderic/react-sortable-hoc/commit/fd30383))\n- updated the behaviour of disabled elements ([bd3d041](https://github.com/clauderic/react-sortable-hoc/commit/bd3d041))\n- virtualized collection grid bug ([a57975c](https://github.com/clauderic/react-sortable-hoc/commit/a57975c))\n\n### Features\n\n- Add disableAutoscroll prop ([#484](https://github.com/clauderic/react-sortable-hoc/issues/484)) ([7845e76](https://github.com/clauderic/react-sortable-hoc/commit/7845e76))\n- added helperContainer prop ([286eff4](https://github.com/clauderic/react-sortable-hoc/commit/286eff4))\n- allow helperContainer prop to be a function returning an HTMLElement ([#489](https://github.com/clauderic/react-sortable-hoc/issues/489)) ([f4a9b4a](https://github.com/clauderic/react-sortable-hoc/commit/f4a9b4a))\n- Detect scroll container automatically ([#507](https://github.com/clauderic/react-sortable-hoc/issues/507)) ([6572921](https://github.com/clauderic/react-sortable-hoc/commit/6572921))\n\n<a name=\"1.7.1\"></a>\n\n## [1.7.1](https://github.com/clauderic/react-sortable-hoc/compare/v1.1.0...v1.7.1) (2019-03-06)\n\n### Bug Fixes\n\n- updated the behaviour of disabled elements ([bd3d041](https://github.com/clauderic/react-sortable-hoc/commit/bd3d041))\n\n<a name=\"1.7.0\"></a>\n\n# [1.7.0](https://github.com/clauderic/react-sortable-hoc/compare/v1.1.0...v1.7.0) (2019-03-06)\n\n### Bug Fixes\n\n- updated the behaviour of disabled elements ([bd3d041](https://github.com/clauderic/react-sortable-hoc/commit/bd3d041))\n\n<a name=\"1.6.1\"></a>\n\n## [1.6.1](https://github.com/clauderic/react-sortable-hoc/compare/v1.6.0...v1.6.1) (2019-02-11)\n\n### Bug Fixes\n\n- omit disableAutoscroll prop ([#502](https://github.com/clauderic/react-sortable-hoc/issues/502)) ([e994e73](https://github.com/clauderic/react-sortable-hoc/commit/e994e73))\n\n<a name=\"1.6.0\"></a>\n\n# [1.6.0](https://github.com/clauderic/react-sortable-hoc/compare/v1.5.3...v1.6.0) (2019-02-07)\n\n### Features\n\n- Add disableAutoscroll prop ([#484](https://github.com/clauderic/react-sortable-hoc/issues/484)) ([7845e76](https://github.com/clauderic/react-sortable-hoc/commit/7845e76))\n\n<a name=\"1.5.4\"></a>\n\n## [1.5.4](https://github.com/clauderic/react-sortable-hoc/compare/v1.5.3...v1.5.4) (2019-02-07)\n\n### Bug Fixes\n\n- overflow bug while dragging an item upwards in a grid ([1a2c87e](https://github.com/clauderic/react-sortable-hoc/commit/1a2c87e))\n- virtualized collection grid bug ([a57975c](https://github.com/clauderic/react-sortable-hoc/commit/a57975c))\n\n<a name=\"1.5.3\"></a>\n\n## [1.5.3](https://github.com/clauderic/react-sortable-hoc/compare/v1.1.0...v1.5.3) (2019-01-25)\n\n### Bug Fixes\n\n- omit spreading helperContainer prop on WrappedComponent ([#497](https://github.com/clauderic/react-sortable-hoc/issues/497)) ([12bafdf](https://github.com/clauderic/react-sortable-hoc/commit/12bafdf))\n\n<a name=\"1.5.2\"></a>\n\n## [1.5.2](https://github.com/clauderic/react-sortable-hoc/compare/v1.5.1...v1.5.2) (2019-01-22)\n\n### Bug Fixes\n\n- invalid helperContainer PropType definition ([#493](https://github.com/clauderic/react-sortable-hoc/issues/493)) ([dc1d18f](https://github.com/clauderic/react-sortable-hoc/commit/dc1d18f))\n\n<a name=\"1.5.1\"></a>\n\n## [1.5.1](https://github.com/clauderic/react-sortable-hoc/compare/v1.5.0...v1.5.1) (2019-01-22)\n\n### Bug Fixes\n\n- update helperContainer prop type definition ([#491](https://github.com/clauderic/react-sortable-hoc/issues/491)) ([fd30383](https://github.com/clauderic/react-sortable-hoc/commit/fd30383))\n\n<a name=\"1.5.0\"></a>\n\n# [1.5.0](https://github.com/clauderic/react-sortable-hoc/compare/v1.4.0...v1.5.0) (2019-01-22)\n\n### Features\n\n- allow helperContainer prop to be a function returning an HTMLElement ([f4a9b4a](https://github.com/clauderic/react-sortable-hoc/commit/f4a9b4a))\n\n<a name=\"1.4.0\"></a>\n\n# [1.4.0](https://github.com/clauderic/react-sortable-hoc/compare/v1.3.0...v1.4.0) (2019-01-10)\n\n### Bug Fixes\n\n- Fix CommonJS and UMD builds by using Rollup and Babel to generate the bundles ([#474](https://github.com/clauderic/react-sortable-hoc/issues/474))\n\n<a name=\"1.3.0\"></a>\n\n# [1.3.0](https://github.com/clauderic/react-sortable-hoc/compare/v1.2.0...v1.3.0) (2019-01-08)\n\n### Bug Fixes\n\n- helperContainer PropType definition broke server-side rendering ([#471](https://github.com/clauderic/react-sortable-hoc/issues/471)) ([c0eef97](https://github.com/clauderic/react-sortable-hoc/commit/c0eef97))\n\n<a name=\"1.2.0\"></a>\n\n# [1.2.0](https://github.com/clauderic/react-sortable-hoc/compare/v1.1.0...v1.2.0) (2019-01-08)\n\n### Features\n\n- added helperContainer prop ([286eff4](https://github.com/clauderic/react-sortable-hoc/commit/286eff4))\n\n<a name=\"1.1.0\"></a>\n\n# [1.1.0](https://github.com/clauderic/react-sortable-hoc/compare/v1.0.0...v1.1.0) (2019-01-07)\n\n### Features\n\n- added updateBeforeSortStart prop ([162857b](https://github.com/clauderic/react-sortable-hoc/commit/162857b))\n\n<a name=\"1.0.0\"></a>\n\n# [1.0.0](https://github.com/clauderic/react-sortable-hoc/compare/v0.8.4...v1.0.0) (2019-01-07)\n\n### BREAKING CHANGES\n\n- The UMD release no longer includes babel-polyfill, you will need to include your own polyfills in order to support older browsers.\n\n# 0.8.4\n\n- Fix a bug when you use SortableHandle and distance prop [#447](https://github.com/clauderic/react-sortable-hoc/pull/447)\n\n# 0.8.3\n\n- Fix: TouchEvent is undefined in certain browsers, such as Safari [#382](https://github.com/clauderic/react-sortable-hoc/issues/382)\n\n# 0.8.1\n\n- Fix scrolling issues on mobile with anchor tag elements [#380](https://github.com/clauderic/react-sortable-hoc/pull/380)\n- Update TypeScript type definition for ContainerGetter to accept Promises that return HTMLElements\n\n# 0.8.0\n\n- Allow `getContainer` to return a promise. This is useful when the container node is rendered by a parent component, since `componentDidMount` fires backwards (from child to parent) [#155](https://github.com/clauderic/react-sortable-hoc/pull/155/)\n\n# 0.7.4\n\n- Fix typo in getLockPixelOffset helper\n\n# 0.7.3\n\n- Fix issues with distance and pressThreshold props on mobile [#378](https://github.com/clauderic/react-sortable-hoc/pull/378)\n\n# 0.7.2\n\n- Fix issues with TypeScript type definitions\n\n# 0.7.1\n\n- Provide TypeScript type definitions out of the box [#377](https://github.com/clauderic/react-sortable-hoc/pull/377)\n- Fix potential issues with calling `removeEventListeners` on `componentWillUnmount` if the container node has already unmounted [#376](https://github.com/clauderic/react-sortable-hoc/pull/376)\n\n# 0.7.0\n\n- [Breaking change] Removed lodash dependency. For users wishing to support Internet Explorer, a [polyfill](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find#Polyfill) for Array.prototype.find will be required\n- Added `onSortOver` prop that gets invoked when sorting over an element [#278](https://github.com/clauderic/react-sortable-hoc/pull/278)\n- Fix `useWindowAsScrollContainer` [#306](https://github.com/clauderic/react-sortable-hoc/pull/306)\n\n# 0.6.8\n\nUpdate react and react-dom peerdependency requirements for React 16+ [#283](https://github.com/clauderic/react-sortable-hoc/pull/283). Thanks [@jnsdls](https://github.com/jnsdls)!\n\n# 0.6.7\n\nFixes issues with Jest Snapshot testing trying to serialize the `window` object and running out of memory [#249](https://github.com/clauderic/react-sortable-hoc/issues/249). Thanks [@cameronmcefee](https://github.com/cameronmcefee)!\n\n# 0.6.6\n\nFixes an issue with Internet Explorer 11 introduced in `0.6.5` [#248](https://github.com/clauderic/react-sortable-hoc/pull/248). Thanks [@humiston](https://github.com/humiston)!\n\n# 0.6.5\n\nFixes the position of the sortable helper when the page is scrolled [#213](https://github.com/clauderic/react-sortable-hoc/pull/213)\n\n# 0.6.4\n\nFix: when cloning the element that is being sorted, we no longer update the value of cloned file inputs [#232](https://github.com/clauderic/react-sortable-hoc/pull/232)\n\n# 0.6.3\n\nFixes issues caused by a disabled SortableElement being moved when `distance` is set to a value other than `0`\n\n# 0.6.2\n\nUse `prop-types` package for PropType validation for compatibility with React ^15.5\n\n# 0.6.1\n\nTweak: default to `pointerEvents: none` on sortable helper, this way the underlying view can still be scrolled using the trackpad/mousewheel while sorting [#160](https://github.com/clauderic/react-sortable-hoc/pull/160)\n\n# 0.6.0\n\nFeature: added `pressThreshold` prop to make `pressDelay` fault tolerant [#159](https://github.com/clauderic/react-sortable-hoc/pull/159)\n\n# 0.5.0\n\nTweak: `button` elements are now included in the default `shouldCancelStart` implementation [#142](https://github.com/clauderic/react-sortable-hoc/pull/142).\nFix: Omit `getHelperDimensions` before passing down props in `SortableContainer`\n\n# 0.4.12\n\nFix: This release fixes some issues caused by the `onSortEnd` callback being invoked before `setState` [#82](https://github.com/clauderic/react-sortable-hoc/issues/82).\n\n# 0.4.10\n\nFix: This version fixes issues with nested `SortableContainer` elements using drag handles from also dragging their parent [#112](https://github.com/clauderic/react-sortable-hoc/issues/112), #127(https://github.com/clauderic/react-sortable-hoc/pull/127). Thanks [@DeadHeadRussell](https://github.com/DeadHeadRussell)!\n\n# 0.4.9\n\nFix: This release fixes a bug introduced in `0.4.8` caused by calling the `forEach` method directly on a NodeList, which is undefined in a number of browsers [#125](https://github.com/clauderic/react-sortable-hoc/issues/125)\n\n# 0.4.8\n\nFix: Added logic to ensure that `select`, `input` and `textarea` fields in `SortableElement` always retain their `value` when the element is cloned (this happens when sorting begins) [#122](https://github.com/clauderic/react-sortable-hoc/issues/122) [#123](https://github.com/clauderic/react-sortable-hoc/pull/123). Thanks [@tomasztomys](https://github.com/tomasztomys)!\n\n# 0.4.7\n\nFix: This release fixes a bug in Firefox caused by active anchor tags preventing mousemove events from being fired [#118](https://github.com/clauderic/react-sortable-hoc/issues/118)\n\n# 0.4.5\n\nFix: getHelperDimensions height was not being used (Thanks [@SMenigat](https://github.com/SMenigat)!)\n\n# 0.4.4\n\nTweak: cherry-picking lodash methods instead of importing the entire bundle (slipped by in a PR, thanks for pointing this out [@arackaf](https://github.com/arackaf)!)\n\n# 0.4.3\n\nFixes an edge-case bug in Firefox where window.getComputedStyle() returns null inside an iframe with `display: none` [#106](https://github.com/clauderic/react-sortable-hoc/pull/106). Thanks [@funnel-mark](https://github.com/funnel-mark)!\n\n# 0.4.2\n\nFixes an issue when attempting to sort items while rapidly moving the mouse. By setting an immediate timer, we move the cancel event to the tail of the timer queue, and ensure that it is fired after the pressTimer [#80](https://github.com/clauderic/react-sortable-hoc/pull/80). Thanks [@v0lkan](https://github.com/v0lkan)!\n\n# 0.4.0\n\n- Fix a timing issue in Chrome caused by setTimeout [#71](https://github.com/clauderic/react-sortable-hoc/pull/71)\n- Private props are no longer passed down to the wrapped component [#98](https://github.com/clauderic/react-sortable-hoc/pull/98)\n\n# 0.3.0\n\nAdded grid support for elements of equal widths / heights [#4](https://github.com/clauderic/react-sortable-hoc/issues/4) [#86](https://github.com/clauderic/react-sortable-hoc/pull/86). Huge shout-out to [@richmeij](https://github.com/richmeij) for making this happen!\n\n# 0.2.0\n\nAdd a `getHelperDimensions` prop to control SortableHelper size [#83](https://github.com/clauderic/react-sortable-hoc/issues/83). Thanks [@nervetattoo](https://github.com/nervetattoo)!\n\n# 0.1.1\n\nAdded `touchCancel` listener to properly handle canceled touches [#73](https://github.com/clauderic/react-sortable-hoc/pull/73)\n\n# 0.1.0\n\n- Force `box-sizing: border-box` on sortable helper [#67](https://github.com/clauderic/react-sortable-hoc/issues/67)\n- Support changing an item's collection prop on the fly [#66](https://github.com/clauderic/react-sortable-hoc/pull/66)\n\n# 0.0.11\n\nUtilize babel-plugin-transform-runtime to utilize `babelHelpers` without them being required in application code [#45](https://github.com/clauderic/react-sortable-hoc/issues/45)\n\n# 0.0.10\n\nThe `arrayMove` helper no longer mutates the array, it now returns a new array [#61](https://github.com/clauderic/react-sortable-hoc/issues/61)\n\n# 0.0.9\n\nServer-side rendering bugfix: safeguard against `document` being undefined [#59](https://github.com/clauderic/react-sortable-hoc/pull/59)\n\n# 0.0.8\n\n- Added `distance` prop ([#35](https://github.com/clauderic/react-sortable-hoc/issues/35))\n- Added a `shouldCancelStart` ([#47](https://github.com/clauderic/react-sortable-hoc/issues/47), [#36](https://github.com/clauderic/react-sortable-hoc/issues/36), [#41](https://github.com/clauderic/react-sortable-hoc/issues/41)) prop to programatically cancel sorting before it begins.\n- Prevent right click from causing sort start ([#46](https://github.com/clauderic/react-sortable-hoc/issues/46))\n\n# 0.0.7\n\nFixes server-side rendering (window undefined) ([#39](https://github.com/clauderic/react-sortable-hoc/issues/39))\n\n# 0.0.6\n\n- Added support for a custom container ([#37](https://github.com/clauderic/react-sortable-hoc/issues/37))\n- Fix changing disable property while receiving props ([#34](https://github.com/clauderic/react-sortable-hoc/issues/34))\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2016, Claudéric Demers\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "> **Warning**\n>\n> This library is **no longer actively maintained**. It will continue to receive critical security updates, but there are no new features planned.\n> In future versions of React, the [`findDOMNode`](https://reactjs.org/docs/react-dom.html#finddomnode) method will be deprecated. This method is a critical piece of the architecture of `react-sortable-hoc`, and the library will stop working in the future when that method is removed from `react-dom`.\n>\n> All development efforts have been redirected towards [**@dnd-kit**](https://github.com/clauderic/dnd-kit). It provides feature parity, built with a modern and extensible architecture, supports complex use-cases and has accessibility features built-in. New consumers are strongly encouraged to adopt **@dnd-kit** instead of adopting `react-sortable-hoc`.\n\n<a href=\"https://github.com/clauderic/dnd-kit\"><img alt=\"Visit @dnd-kit github repository\" src=\".github/assets/dnd-kit-banner.svg\" /></a>\n\n# <img src=\".github/assets/react-sortable-hoc-logo.png\" width=\"400\" alt=\"React Sortable HOC\" />\n\n> A set of higher-order components to turn any list into an animated, accessible and touch-friendly sortable list\n\n[![npm version](https://img.shields.io/npm/v/react-sortable-hoc.svg)](https://www.npmjs.com/package/react-sortable-hoc)\n[![npm downloads](https://img.shields.io/npm/dm/react-sortable-hoc.svg)](https://www.npmjs.com/package/react-sortable-hoc)\n[![license](https://img.shields.io/github/license/mashape/apistatus.svg?maxAge=2592000)](https://github.com/clauderic/react-sortable-hoc/blob/master/LICENSE)\n[![Gitter](https://badges.gitter.im/clauderic/react-sortable-hoc.svg)](https://gitter.im/clauderic/react-sortable-hoc)\n![gzip size](http://img.badgesize.io/https://npmcdn.com/react-sortable-hoc/dist/react-sortable-hoc.umd.min.js?compression=gzip)\n\n### Examples available here: <a href=\"#\">http://clauderic.github.io/react-sortable-hoc/</a>\n\n## Features\n\n- **Higher Order Components** – Integrates with your existing components\n- **Drag handle, auto-scrolling, locked axis, events, and more!**\n- **Suuuper smooth animations** – Chasing the 60FPS dream 🌈\n- **Works with virtualization libraries: [react-virtualized](https://github.com/bvaughn/react-virtualized/), [react-tiny-virtual-list](https://github.com/clauderic/react-tiny-virtual-list), [react-infinite](https://github.com/seatgeek/react-infinite), etc.**\n- **Horizontal lists, vertical lists, or a grid** ↔ ↕ ⤡\n- **Touch support** 👌\n- **Accessible: supports keyboard sorting**\n\n## Installation\n\nUsing [npm](https://www.npmjs.com/package/react-sortable-hoc):\n\n    $ npm install react-sortable-hoc --save\n\nThen, using a module bundler that supports either CommonJS or ES2015 modules, such as [webpack](https://github.com/webpack/webpack):\n\n```js\n// Using an ES6 transpiler like Babel\nimport {SortableContainer, SortableElement} from 'react-sortable-hoc';\n\n// Not using an ES6 transpiler\nvar Sortable = require('react-sortable-hoc');\nvar SortableContainer = Sortable.SortableContainer;\nvar SortableElement = Sortable.SortableElement;\n```\n\nAlternatively, an UMD build is also available:\n\n```html\n<script src=\"react-sortable-hoc/dist/react-sortable-hoc.umd.js\"></script>\n```\n\n## Usage\n\n### Basic Example\n\n```js\nimport React, {Component} from 'react';\nimport {render} from 'react-dom';\nimport {SortableContainer, SortableElement} from 'react-sortable-hoc';\nimport arrayMove from 'array-move';\n\nconst SortableItem = SortableElement(({value}) => <li>{value}</li>);\n\nconst SortableList = SortableContainer(({items}) => {\n  return (\n    <ul>\n      {items.map((value, index) => (\n        <SortableItem key={`item-${value}`} index={index} value={value} />\n      ))}\n    </ul>\n  );\n});\n\nclass SortableComponent extends Component {\n  state = {\n    items: ['Item 1', 'Item 2', 'Item 3', 'Item 4', 'Item 5', 'Item 6'],\n  };\n  onSortEnd = ({oldIndex, newIndex}) => {\n    this.setState(({items}) => ({\n      items: arrayMove(items, oldIndex, newIndex),\n    }));\n  };\n  render() {\n    return <SortableList items={this.state.items} onSortEnd={this.onSortEnd} />;\n  }\n}\n\nrender(<SortableComponent />, document.getElementById('root'));\n```\n\nThat's it! React Sortable does not come with any styles by default, since it's meant to enhance your existing components.\n\nMore code examples are available [here](https://github.com/clauderic/react-sortable-hoc/blob/master/examples/).\n\n## Why should I use this?\n\nThere are already a number of great Drag & Drop libraries out there (for instance, [react-dnd](https://github.com/gaearon/react-dnd/) is fantastic). If those libraries fit your needs, you should definitely give them a try first. However, most of those libraries rely on the HTML5 Drag & Drop API, which has some severe limitations. For instance, things rapidly become tricky if you need to support touch devices, if you need to lock dragging to an axis, or want to animate the nodes as they're being sorted. React Sortable HOC aims to provide a simple set of higher-order components to fill those gaps. If you're looking for a dead-simple, mobile-friendly way to add sortable functionality to your lists, then you're in the right place.\n\n### Prop Types\n\n#### SortableContainer HOC\n\n| Property                          | Type                                                      | Default                                                                                                                                                                  | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                            |\n| :-------------------------------- | :-------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| axis                              | String                                                    | `y`                                                                                                                                                                      | Items can be sorted horizontally, vertically or in a grid. Possible values: `x`, `y` or `xy`                                                                                                                                                                                                                                                                                                                                                                           |\n| lockAxis                          | String                                                    |                                                                                                                                                                          | If you'd like, you can lock movement to an axis while sorting. This is not something that is possible with HTML5 Drag & Drop. Possible values: `x` or `y`.                                                                                                                                                                                                                                                                                                             |\n| helperClass                       | String                                                    |                                                                                                                                                                          | You can provide a class you'd like to add to the sortable helper to add some styles to it                                                                                                                                                                                                                                                                                                                                                                              |\n| transitionDuration                | Number                                                    | `300`                                                                                                                                                                    | The duration of the transition when elements shift positions. Set this to `0` if you'd like to disable transitions                                                                                                                                                                                                                                                                                                                                                     |\n| keyboardSortingTransitionDuration | Number                                                    | `transitionDuration`                                                                                                                                                     | The duration of the transition when the helper is shifted during keyboard sorting. Set this to `0` if you'd like to disable transitions for the keyboard sorting helper. Defaults to the value set for `transitionDuration` if undefined                                                                                                                                                                                                                               |\n| keyCodes                          | Array<Number>                                             | `{`<br/>&nbsp;&nbsp;`lift: [32],`<br/>&nbsp;&nbsp;`drop: [32],`<br/>&nbsp;&nbsp;`cancel: [27],`<br/>&nbsp;&nbsp;`up: [38, 37],`<br/>&nbsp;&nbsp;`down: [40, 39]`<br/>`}` | An object containing an array of keycodes for each keyboard-accessible action.                                                                                                                                                                                                                                                                                                                                                                                         |\n| pressDelay                        | Number                                                    | `0`                                                                                                                                                                      | If you'd like elements to only become sortable after being pressed for a certain time, change this property. A good sensible default value for mobile is `200`. Cannot be used in conjunction with the `distance` prop.                                                                                                                                                                                                                                                |\n| pressThreshold                    | Number                                                    | `5`                                                                                                                                                                      | Number of pixels of movement to tolerate before ignoring a press event.                                                                                                                                                                                                                                                                                                                                                                                                |\n| distance                          | Number                                                    | `0`                                                                                                                                                                      | If you'd like elements to only become sortable after being dragged a certain number of pixels. Cannot be used in conjunction with the `pressDelay` prop.                                                                                                                                                                                                                                                                                                               |\n| shouldCancelStart                 | Function                                                  | [Function](https://github.com/clauderic/react-sortable-hoc/blob/master/src/SortableContainer/index.js#L48)                                                               | This function is invoked before sorting begins, and can be used to programatically cancel sorting before it begins. By default, it will cancel sorting if the event target is either an `input`, `textarea`, `select`, `option`, or `button`.                                                                                                                                                                                                                          |\n| updateBeforeSortStart             | Function                                                  |                                                                                                                                                                          | This function is invoked before sorting begins. It can return a promise, allowing you to run asynchronous updates (such as `setState`) before sorting begins. `function({node, index, collection, isKeySorting}, event)`                                                                                                                                                                                                                                               |\n| onSortStart                       | Function                                                  |                                                                                                                                                                          | Callback that is invoked when sorting begins. `function({node, index, collection, isKeySorting}, event)`                                                                                                                                                                                                                                                                                                                                                               |\n| onSortMove                        | Function                                                  |                                                                                                                                                                          | Callback that is invoked during sorting as the cursor moves. `function(event)`                                                                                                                                                                                                                                                                                                                                                                                         |\n| onSortOver                        | Function                                                  |                                                                                                                                                                          | Callback that is invoked when moving over an item. `function({index, oldIndex, newIndex, collection, isKeySorting}, e)`                                                                                                                                                                                                                                                                                                                                                |\n| onSortEnd                         | Function                                                  |                                                                                                                                                                          | Callback that is invoked when sorting ends. `function({oldIndex, newIndex, collection, isKeySorting}, e)`                                                                                                                                                                                                                                                                                                                                                              |\n| useDragHandle                     | Boolean                                                   | `false`                                                                                                                                                                  | If you're using the `SortableHandle` HOC, set this to `true`                                                                                                                                                                                                                                                                                                                                                                                                           |\n| useWindowAsScrollContainer        | Boolean                                                   | `false`                                                                                                                                                                  | If you want, you can set the `window` as the scrolling container                                                                                                                                                                                                                                                                                                                                                                                                       |\n| hideSortableGhost                 | Boolean                                                   | `true`                                                                                                                                                                   | Whether to auto-hide the ghost element. By default, as a convenience, React Sortable List will automatically hide the element that is currently being sorted. Set this to false if you would like to apply your own styling.                                                                                                                                                                                                                                           |\n| lockToContainerEdges              | Boolean                                                   | `false`                                                                                                                                                                  | You can lock movement of the sortable element to it's parent `SortableContainer`                                                                                                                                                                                                                                                                                                                                                                                       |\n| lockOffset                        | `OffsetValue`\\* &#124; [`OffsetValue`\\*, `OffsetValue`\\*] | `\"50%\"`                                                                                                                                                                  | When`lockToContainerEdges`is set to`true`, this controls the offset distance between the sortable helper and the top/bottom edges of it's parent`SortableContainer`. Percentage values are relative to the height of the item currently being sorted. If you wish to specify different behaviours for locking to the _top_ of the container vs the _bottom_, you may also pass in an`array`(For example:`[\"0%\", \"100%\"]`).                                             |\n| getContainer                      | Function                                                  |                                                                                                                                                                          | Optional function to return the scrollable container element. This property defaults to the `SortableContainer` element itself or (if `useWindowAsScrollContainer` is true) the window. Use this function to specify a custom container object (eg this is useful for integrating with certain 3rd party components such as `FlexTable`). This function is passed a single parameter (the `wrappedInstance` React element) and it is expected to return a DOM element. |\n| getHelperDimensions               | Function                                                  | [Function](https://github.com/clauderic/react-sortable-hoc/blob/master/src/SortableContainer/index.js#L74-L77)                                                           | Optional `function({node, index, collection})` that should return the computed dimensions of the SortableHelper. See [default implementation](https://github.com/clauderic/react-sortable-hoc/blob/master/src/SortableContainer/defaultGetHelperDimensions.js) for more details                                                                                                                                                                                        |\n| helperContainer                   | HTMLElement &#124; Function                               | `document.body`                                                                                                                                                          | By default, the cloned sortable helper is appended to the document body. Use this prop to specify a different container for the sortable clone to be appended to. Accepts an `HTMLElement` or a function returning an `HTMLElement` that will be invoked before right before sorting begins                                                                                                                                                                            |\n| disableAutoscroll                 | Boolean                                                   | `false`                                                                                                                                                                  | Disables autoscrolling while dragging                                                                                                                                                                                                                                                                                                                                                                                                                                  |\n\n\\* `OffsetValue` can either be a finite `Number` or a `String` made up of a number and a unit (`px` or `%`).\nExamples: `10` (which is the same as `\"10px\"`), `\"50%\"`\n\n#### SortableElement HOC\n\n| Property   | Type             | Default | Required? | Description                                                                                                                                                                                                                               |\n| :--------- | :--------------- | :------ | :-------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| index      | Number           |         |     ✓     | This is the element's sortableIndex within it's collection. This prop is required.                                                                                                                                                        |\n| collection | Number or String | `0`     |           | The collection the element is part of. This is useful if you have multiple groups of sortable elements within the same `SortableContainer`. [Example](http://clauderic.github.io/react-sortable-hoc/#/basic-configuration/multiple-lists) |\n| disabled   | Boolean          | `false` |           | Whether the element should be sortable or not                                                                                                                                                                                             |\n\n## FAQ\n\n### Running Examples\n\nIn root folder, run the following commands to launch React Storybook:\n\n```\n$ npm install\n$ npm start\n```\n\n### Accessibility\n\nReact Sortable HOC supports keyboard sorting out of the box. To enable it, make sure your `SortableElement` or `SortableHandle` is focusable. This can be done by setting `tabIndex={0}` on the outermost HTML node rendered by the component you're enhancing with `SortableElement` or `SortableHandle`.\n\nOnce an item is focused/tabbed to, pressing `SPACE` picks it up, `ArrowUp` or `ArrowLeft` moves it one place backward in the list, `ArrowDown` or `ArrowRight` moves items one place forward in the list, pressing `SPACE` again drops the item in its new position. Pressing `ESC` before the item is dropped will cancel the sort operations.\n\n### Grid support\n\nNeed to sort items in a grid? We've got you covered! Just set the `axis` prop to `xy`. Grid support is currently limited to a setup where all the cells in the grid have the same width and height, though we're working hard to get variable width support in the near future.\n\n### Item disappearing when sorting / CSS issues\n\nUpon sorting, `react-sortable-hoc` creates a clone of the element you are sorting (the _sortable-helper_) and appends it to the end of the `<body>` tag. The original element will still be in-place to preserve its position in the DOM until the end of the drag (with inline-styling to make it invisible). If the _sortable-helper_ gets messed up from a CSS standpoint, consider that maybe your selectors to the draggable item are dependent on a parent element which isn't present anymore (again, since the _sortable-helper_ is at the end of the `<body>`). This can also be a `z-index` issue, for example, when using `react-sortable-hoc` within a Bootstrap modal, you'll need to increase the `z-index` of the SortableHelper so it is displayed on top of the modal (see [#87](https://github.com/clauderic/react-sortable-hoc/issues/87) for more details).\n\n### Click events being swallowed\n\nBy default, `react-sortable-hoc` is triggered immediately on `mousedown`. If you'd like to prevent this behaviour, there are a number of strategies readily available. You can use the `distance` prop to set a minimum distance (in pixels) to be dragged before sorting is enabled. You can also use the `pressDelay` prop to add a delay before sorting is enabled. Alternatively, you can also use the [SortableHandle](https://github.com/clauderic/react-sortable-hoc/blob/master/src/SortableHandle/index.js) HOC.\n\n### Wrapper props not passed down to wrapped Component\n\nAll props for `SortableContainer` and `SortableElement` listed above are intentionally consumed by the wrapper component and are **not** passed down to the wrapped component. To make them available pass down the desired prop again with a different name. E.g.:\n\n```js\nconst SortableItem = SortableElement(({value, sortIndex}) => (\n  <li>\n    {value} - #{sortIndex}\n  </li>\n));\n\nconst SortableList = SortableContainer(({items}) => {\n  return (\n    <ul>\n      {items.map((value, index) => (\n        <SortableItem\n          key={`item-${index}`}\n          index={index}\n          sortIndex={index}\n          value={value}\n        />\n      ))}\n    </ul>\n  );\n});\n```\n\n## Dependencies\n\nReact Sortable HOC only depends on [invariant](https://github.com/zertosh/invariant). It has the following peerDependencies: `react`, `react-dom`\n\n## Reporting Issues\n\nIf believe you've found an issue, please [report it](https://github.com/clauderic/react-sortable-hoc/issues) along with any relevant details to reproduce it. The easiest way to do so is to fork the `react-sortable-hoc` basic setup sandbox on [CodeSandbox](https://codesandbox.io/s/o104x95y86):\n\n[![Edit on CodeSandbox](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/react-sortable-hoc-starter-o104x95y86)\n\n## Asking for help\n\nPlease do not use the issue tracker for personal support requests. Instead, use [Gitter](https://gitter.im/clauderic/react-sortable-hoc) or StackOverflow.\n\n## Contributions\n\nYes please! Feature requests / pull requests are welcome.\n"
  },
  {
    "path": "examples/.eslintrc.json",
    "content": "{\n  \"rules\": {\n    \"import/no-unresolved\": \"off\",\n    \"react/prop-types\": \"off\",\n    \"react/no-array-index-key\": \"off\"\n  }\n}\n"
  },
  {
    "path": "examples/basic.js",
    "content": "import React, {Component} from 'react';\nimport {render} from 'react-dom';\nimport {sortableContainer, sortableElement} from 'react-sortable-hoc';\nimport arrayMove from 'array-move';\n\nconst SortableItem = sortableElement(({value}) => <li>{value}</li>);\n\nconst SortableContainer = sortableContainer(({children}) => {\n  return <ul>{children}</ul>;\n});\n\nclass App extends Component {\n  state = {\n    items: ['Item 1', 'Item 2', 'Item 3', 'Item 4', 'Item 5', 'Item 6'],\n  };\n\n  onSortEnd = ({oldIndex, newIndex}) => {\n    this.setState(({items}) => ({\n      items: arrayMove(items, oldIndex, newIndex),\n    }));\n  };\n\n  render() {\n    const {items} = this.state;\n\n    return (\n      <SortableContainer onSortEnd={this.onSortEnd}>\n        {items.map((value, index) => (\n          <SortableItem key={`item-${value}`} index={index} value={value} />\n        ))}\n      </SortableContainer>\n    );\n  }\n}\n\nrender(<App />, document.getElementById('root'));\n"
  },
  {
    "path": "examples/collections.js",
    "content": "import React, {Component} from 'react';\nimport {render} from 'react-dom';\nimport {sortableContainer, sortableElement} from 'react-sortable-hoc';\nimport arrayMove from 'array-move';\n\nconst SortableItem = sortableElement(({value}) => <li>{value}</li>);\n\nconst SortableContainer = sortableContainer(({children}) => {\n  return <div>{children}</div>;\n});\n\nclass App extends Component {\n  state = {\n    collections: [[0, 1, 2], [0, 1, 2, 3, 4], [0, 1, 2]],\n  };\n\n  onSortEnd = ({oldIndex, newIndex, collection}) => {\n    this.setState(({collections}) => {\n      const newCollections = [...collections];\n\n      newCollections[collection] = arrayMove(\n        collections[collection],\n        oldIndex,\n        newIndex,\n      );\n\n      return {collections: newCollections};\n    });\n  };\n\n  render() {\n    const {collections} = this.state;\n\n    return (\n      <SortableContainer onSortEnd={this.onSortEnd}>\n        {collections.map((items, index) => (\n          <React.Fragment key={index}>\n            <strong>LIST {index}</strong>\n            <ul>\n              {items.map((item, i) => (\n                <SortableItem\n                  key={item}\n                  value={`Item ${item}`}\n                  index={i}\n                  collection={index}\n                />\n              ))}\n            </ul>\n          </React.Fragment>\n        ))}\n      </SortableContainer>\n    );\n  }\n}\n\nrender(<App />, document.getElementById('root'));\n"
  },
  {
    "path": "examples/drag-handle.js",
    "content": "import React, {Component} from 'react';\nimport {render} from 'react-dom';\nimport {\n  sortableContainer,\n  sortableElement,\n  sortableHandle,\n} from 'react-sortable-hoc';\nimport arrayMove from 'array-move';\n\nconst DragHandle = sortableHandle(() => <span>::</span>);\n\nconst SortableItem = sortableElement(({value}) => (\n  <li>\n    <DragHandle />\n    {value}\n  </li>\n));\n\nconst SortableContainer = sortableContainer(({children}) => {\n  return <ul>{children}</ul>;\n});\n\nclass App extends Component {\n  state = {\n    items: ['Item 1', 'Item 2', 'Item 3', 'Item 4', 'Item 5', 'Item 6'],\n  };\n\n  onSortEnd = ({oldIndex, newIndex}) => {\n    this.setState(({items}) => ({\n      items: arrayMove(items, oldIndex, newIndex),\n    }));\n  };\n\n  render() {\n    const {items} = this.state;\n\n    return (\n      <SortableContainer onSortEnd={this.onSortEnd} useDragHandle>\n        {items.map((value, index) => (\n          <SortableItem key={`item-${value}`} index={index} value={value} />\n        ))}\n      </SortableContainer>\n    );\n  }\n}\n\nrender(<App />, document.getElementById('root'));\n"
  },
  {
    "path": "examples/react-infinite.js",
    "content": "import React, {Component} from 'react';\nimport {render} from 'react-dom';\nimport {sortableContainer, sortableElement} from 'react-sortable-hoc';\nimport arrayMove from 'array-move';\nimport Infinite from 'react-infinite';\n\nconst SortableItem = sortableElement(({height, value}) => {\n  return <li style={{height}}>{value}</li>;\n});\n\nconst SortableInfiniteList = sortableContainer(({items}) => {\n  return (\n    <Infinite\n      containerHeight={600}\n      elementHeight={items.map(({height}) => height)}\n    >\n      {items.map(({value, height}, index) => (\n        <SortableItem\n          key={`item-${value}`}\n          index={index}\n          value={value}\n          height={height}\n        />\n      ))}\n    </Infinite>\n  );\n});\n\nclass App extends Component {\n  state = {\n    items: [\n      {value: 'Item 1', height: 89},\n      {value: 'Item 2', height: 59},\n      {value: 'Item 3', height: 130},\n      {value: 'Item 4', height: 59},\n      {value: 'Item 5', height: 200},\n      {value: 'Item 6', height: 150},\n    ],\n  };\n\n  onSortEnd = ({oldIndex, newIndex}) => {\n    this.setState(({items}) => ({\n      items: arrayMove(items, oldIndex, newIndex),\n    }));\n  };\n\n  render() {\n    const {items} = this.state;\n\n    return <SortableInfiniteList items={items} onSortEnd={this.onSortEnd} />;\n  }\n}\n\nrender(<App />, document.getElementById('root'));\n"
  },
  {
    "path": "examples/react-virtualized-table-columns.js",
    "content": "import React, {Component} from 'react';\nimport {render} from 'react-dom';\nimport {Table, Column} from 'react-virtualized';\nimport {sortableContainer, sortableElement} from 'react-sortable-hoc';\nimport arrayMove from 'array-move';\nimport 'react-virtualized/styles.css';\n\nconst ROW_HEIGHT = 30;\nconst HEADER_ROW_HEIGHT = 20;\nconst COL_WIDTH = 100;\n\nconst SortableHeader = sortableElement(({children, ...props}) =>\n  React.cloneElement(children, props),\n);\n\nconst SortableHeaderRowRenderer = sortableContainer(\n  ({className, columns, style}) => (\n    <div className={className} role=\"row\" style={style}>\n      {React.Children.map(columns, (column, index) => (\n        <SortableHeader index={index}>{column}</SortableHeader>\n      ))}\n    </div>\n  ),\n);\n\nclass TableWithSortableColumns extends Component {\n  state = {\n    cols: [\n      {dataKey: 'col1', label: 'Column 1'},\n      {dataKey: 'col2', label: 'Column 2'},\n      {dataKey: 'col3', label: 'Column 3'},\n    ],\n    rows: [\n      {col1: 'row1 col1', col2: 'row1 col2', col3: 'row1 col3'},\n      {col1: 'row2 col1', col2: 'row2 col2', col3: 'row2 col3'},\n      {col1: 'row3 col1', col2: 'row3 col2', col3: 'row3 col3'},\n    ],\n  };\n\n  onSortEnd = ({oldIndex, newIndex}) => {\n    this.setState(({cols}) => ({\n      cols: arrayMove(cols, oldIndex, newIndex),\n    }));\n  };\n\n  getRow = ({index}) => {\n    const {rows} = this.state;\n    return rows[index];\n  };\n\n  renderHeaderRow = (params) => {\n    return (\n      <SortableHeaderRowRenderer\n        {...params}\n        axis=\"x\"\n        lockAxis=\"x\"\n        onSortEnd={this.onSortEnd}\n      />\n    );\n  };\n\n  render() {\n    const {rows, cols} = this.state;\n\n    return (\n      <Table\n        width={COL_WIDTH * rows.length}\n        height={HEADER_ROW_HEIGHT + ROW_HEIGHT * rows.length}\n        headerHeight={ROW_HEIGHT}\n        rowHeight={ROW_HEIGHT}\n        rowCount={rows.length}\n        rowGetter={this.getRow}\n        headerRowRenderer={this.renderHeaderRow}\n      >\n        {cols.map((col) => (\n          <Column {...col} key={col.dataKey} width={COL_WIDTH} />\n        ))}\n      </Table>\n    );\n  }\n}\n\nrender(<TableWithSortableColumns />, document.getElementById('root'));\n"
  },
  {
    "path": "examples/react-virtualized.js",
    "content": "import React, {Component} from 'react';\nimport {render} from 'react-dom';\nimport {sortableContainer, sortableElement} from 'react-sortable-hoc';\nimport arrayMove from 'array-move';\nimport {List} from 'react-virtualized';\n\nconst SortableItem = sortableElement(({value}) => {\n  return <li>{value}</li>;\n});\n\nclass VirtualList extends Component {\n  renderRow = ({index}) => {\n    const {items} = this.props;\n    const {value} = items[index];\n\n    return <SortableItem index={index} value={value} />;\n  };\n\n  getRowHeight = ({index}) => {\n    const {items} = this.props;\n    return items[index].height;\n  };\n\n  render() {\n    const {items, getRef} = this.props;\n\n    return (\n      <List\n        ref={getRef}\n        rowHeight={this.getRowHeight}\n        rowRenderer={this.renderRow}\n        rowCount={items.length}\n        width={400}\n        height={600}\n      />\n    );\n  }\n}\n\nconst SortableVirtualList = sortableContainer(VirtualList);\n\nclass App extends Component {\n  state = {\n    items: [\n      {value: 'Item 1', height: 89},\n      {value: 'Item 2', height: 59},\n      {value: 'Item 3', height: 130},\n      {value: 'Item 4', height: 59},\n      {value: 'Item 5', height: 200},\n      {value: 'Item 6', height: 150},\n    ],\n  };\n\n  registerListRef = (listInstance) => {\n    this.List = listInstance;\n  };\n\n  onSortEnd = ({oldIndex, newIndex}) => {\n    if (oldIndex === newIndex) {\n      return;\n    }\n\n    const {items} = this.state;\n\n    this.setState({\n      items: arrayMove(items, oldIndex, newIndex),\n    });\n\n    // We need to inform React Virtualized that the items have changed heights\n    // This can either be done by imperatively calling the recomputeRowHeights and\n    // forceUpdate instance methods on the `List` ref, or by passing an additional prop\n    // to List that changes whenever the order changes to force it to re-render\n    this.List.recomputeRowHeights();\n    this.List.forceUpdate();\n  };\n\n  render() {\n    const {items} = this.state;\n\n    return (\n      <SortableVirtualList\n        getRef={this.registerListRef}\n        items={items}\n        onSortEnd={this.onSortEnd}\n      />\n    );\n  }\n}\n\nrender(<App />, document.getElementById('root'));\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"react-sortable-hoc\",\n  \"version\": \"2.0.0\",\n  \"description\": \"Set of higher-order components to turn any list into a sortable, touch-friendly, animated list\",\n  \"author\": {\n    \"name\": \"Clauderic Demers\",\n    \"email\": \"me@ced.io\"\n  },\n  \"user\": \"clauderic\",\n  \"homepage\": \"https://github.com/clauderic/react-sortable-hoc\",\n  \"source\": \"src/index.js\",\n  \"main\": \"dist/react-sortable-hoc.js\",\n  \"umd:main\": \"dist/react-sortable-hoc.umd.js\",\n  \"module\": \"dist/react-sortable-hoc.esm.js\",\n  \"jsnext:main\": \"dist/react-sortable-hoc.esm.js\",\n  \"types\": \"types/index.d.ts\",\n  \"license\": \"MIT\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/clauderic/react-sortable-hoc.git\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/clauderic/react-sortable-hoc/issues\"\n  },\n  \"keywords\": [\n    \"react\",\n    \"reactjs\",\n    \"react-component\",\n    \"sortable\",\n    \"sortable-list\",\n    \"list\",\n    \"sortable list\",\n    \"smooth\",\n    \"animated\",\n    \"hoc\",\n    \"higher-order\",\n    \"component\"\n  ],\n  \"scripts\": {\n    \"start\": \"start-storybook -p 9001 -c .storybook\",\n    \"build\": \"rollup -c\",\n    \"test\": \"eslint src/** --ext .js --quiet\",\n    \"release\": \"standard-version --no-verify\"\n  },\n  \"husky\": {\n    \"hooks\": {\n      \"pre-commit\": \"pretty-quick --staged\"\n    }\n  },\n  \"dependencies\": {\n    \"@babel/runtime\": \"^7.13.0\",\n    \"invariant\": \"^2.2.4\",\n    \"prop-types\": \"^15.5.7\"\n  },\n  \"peerDependencies\": {\n    \"prop-types\": \"^15.5.7\",\n    \"react\": \"^16.3.0 || ^17.0.0\",\n    \"react-dom\": \"^16.3.0 || ^17.0.0\"\n  },\n  \"devDependencies\": {\n    \"@babel/core\": \"^7.2.2\",\n    \"@babel/plugin-proposal-class-properties\": \"^7.2.3\",\n    \"@babel/plugin-transform-runtime\": \"^7.2.0\",\n    \"@babel/preset-env\": \"^7.2.3\",\n    \"@babel/preset-react\": \"^7.0.0\",\n    \"@storybook/addon-options\": \"^5.1.11\",\n    \"@storybook/react\": \"^5.1.11\",\n    \"@storybook/theming\": \"^5.1.11\",\n    \"array-move\": \"^1.0.0\",\n    \"autoprefixer\": \"^6.3.6\",\n    \"babel-loader\": \"^8.0.5\",\n    \"babel-plugin-transform-async-to-promises\": \"^0.8.4\",\n    \"classnames\": \"^2.2.5\",\n    \"css-loader\": \"^2.1.0\",\n    \"eslint\": \"^6.2.1\",\n    \"eslint-config-prettier\": \"^6.1.0\",\n    \"eslint-plugin-prettier\": \"^3.1.0\",\n    \"eslint-plugin-shopify\": \"^30.0.1\",\n    \"extract-text-webpack-plugin\": \"^1.0.1\",\n    \"html-webpack-plugin\": \"^2.16.1\",\n    \"husky\": \"^3.0.4\",\n    \"lodash\": \"^4.12.0\",\n    \"node-sass\": \"^4.11.0\",\n    \"postcss\": \"^7.0.7\",\n    \"postcss-loader\": \"^3.0.0\",\n    \"prettier\": \"^1.18.2\",\n    \"pretty-quick\": \"^1.11.1\",\n    \"react\": \"^16.7.0\",\n    \"react-addons-pure-render-mixin\": \"^15.0.2\",\n    \"react-addons-shallow-compare\": \"^15.1.0\",\n    \"react-addons-test-utils\": \"^15.1.0\",\n    \"react-dom\": \"^16.7.0\",\n    \"react-infinite\": \"^0.13.0\",\n    \"react-inspector\": \"^3.0.2\",\n    \"react-tiny-virtual-list\": \"^2.0.1\",\n    \"react-virtualized\": \"^9.2.2\",\n    \"react-window\": \"^1.6.2\",\n    \"rollup\": \"^1.0.0\",\n    \"rollup-plugin-babel\": \"^4.2.0\",\n    \"rollup-plugin-commonjs\": \"^9.2.0\",\n    \"rollup-plugin-filesize\": \"^6.0.0\",\n    \"rollup-plugin-node-resolve\": \"^4.0.0\",\n    \"rollup-plugin-replace\": \"^2.1.0\",\n    \"rollup-plugin-uglify\": \"^6.0.0\",\n    \"sass-loader\": \"^7.1.0\",\n    \"standard-version\": \"^4.4.0\",\n    \"style-loader\": \"^0.23.1\"\n  }\n}\n"
  },
  {
    "path": "rollup.config.js",
    "content": "import replace from 'rollup-plugin-replace';\nimport resolve from 'rollup-plugin-node-resolve';\nimport commonjs from 'rollup-plugin-commonjs';\nimport babel from 'rollup-plugin-babel';\nimport filesize from 'rollup-plugin-filesize';\nimport {uglify} from 'rollup-plugin-uglify';\nimport pkg from './package.json';\n\nconst external = (id) => !id.startsWith('.') && !id.startsWith('/');\n\nconst babelConfig = (\n  {useESModules, targets} = {\n    useESModules: true,\n    targets: {browsers: 'last 2 versions'},\n  },\n) => ({\n  comments: false,\n  runtimeHelpers: true,\n  presets: [\n    '@babel/preset-react',\n    [\n      '@babel/preset-env',\n      {\n        targets,\n      },\n    ],\n  ],\n  plugins: [\n    '@babel/plugin-proposal-class-properties',\n    ['@babel/transform-runtime', {useESModules, regenerator: false}],\n    ['babel-plugin-transform-async-to-promises', {inlineHelpers: true}],\n  ],\n  exclude: 'node_modules/**',\n});\n\nconst umdConfig = ({minify} = {}) => ({\n  input: pkg.source,\n  external: ['react', 'react-dom', 'prop-types'],\n  output: {\n    name: 'SortableHOC',\n    file: minify ? pkg[\"umd:main\"].replace('.js', '.min.js') : pkg[\"umd:main\"],\n    format: 'umd',\n    globals: {\n      react: 'React',\n      'react-dom': 'ReactDOM',\n      'prop-types': 'PropTypes',\n    },\n  },\n  plugins: [\n    resolve(),\n    babel(\n      babelConfig({\n        targets: {browsers: ['last 2 versions', 'safari >= 7']},\n      }),\n    ),\n    replace({\n      'process.env.NODE_ENV': JSON.stringify(\n        minify ? 'production' : 'development',\n      ),\n    }),\n    commonjs(),\n    minify ? uglify() : { },\n    filesize(),\n  ],\n});\n\nconst rollupConfig = [\n  // Browser-friendly UMD builds\n  umdConfig(),\n  umdConfig({minify: true}),\n\n  // CommonJS\n  {\n    input: pkg.source,\n    external,\n    output: [{file: pkg.main, format: 'cjs'}],\n    plugins: [resolve(), babel(babelConfig({useESModules: false})), filesize()],\n  },\n\n  // ES module\n  {\n    input: pkg.source,\n    external,\n    output: [{file: pkg.module, format: 'esm'}],\n    plugins: [resolve(), babel(babelConfig()), filesize()],\n  },\n];\n\nexport default rollupConfig;\n"
  },
  {
    "path": "src/.stories/Storybook.scss",
    "content": "@import url(https://fonts.googleapis.com/css?family=Montserrat:400);\n\n$focusedOutlineColor: #4c9ffe;\n\n.root {\n  display: flex;\n  height: 100%;\n  box-sizing: border-box;\n  flex-direction: column;\n  justify-content: center;\n  align-items: center;\n}\n\n// Base styles\n.list {\n  width: 400px;\n  height: 600px;\n  overflow: auto;\n  -webkit-overflow-scrolling: touch;\n  border: 1px solid #999;\n}\n\n.item {\n  position: relative;\n  border-bottom: 1px solid #999;\n\n  cursor: grab;\n  touch-action: manipulation;\n\n  &.sorting {\n    pointer-events: none;\n  }\n}\n\n.containsDragHandle {\n  cursor: default;\n}\n\n// Stylized\n.stylizedList {\n  position: relative;\n  z-index: 0;\n  background-color: #f3f3f3;\n  border: 1px solid #efefef;\n  border-radius: 3px;\n  outline: none;\n}\n\n.stylizedItem {\n  display: flex;\n  align-items: center;\n  width: 100%;\n  padding: 0 20px;\n  background-color: #fff;\n  border-bottom: 1px solid #efefef;\n  box-sizing: border-box;\n  user-select: none;\n  outline: none;\n\n  color: #333;\n  font-weight: 400;\n\n  &:focus:not(.containsDragHandle) {\n    text-indent: -2px;\n    border: 2px solid $focusedOutlineColor;\n  }\n}\n\n.disabled {\n  cursor: not-allowed;\n  opacity: 0.5;\n}\n\n// Drag handle\n.handleWrapper {\n  width: 18px;\n  height: 18px;\n  outline: none;\n}\n\n.handle {\n  display: block;\n  width: 18px;\n  height: 18px;\n  margin-right: 20px;\n  overflow: hidden;\n\n  > svg {\n    opacity: 0.3;\n  }\n\n  cursor: grab;\n}\n\n// Horizontal list\n.horizontalList {\n  display: flex;\n  width: 600px;\n  height: 300px;\n  white-space: nowrap;\n}\n\n.horizontalItem {\n  display: flex;\n  flex-shrink: 0;\n  align-items: center;\n  justify-content: center;\n  width: 200px;\n  border-right: 1px solid #efefef;\n  border-bottom: 0;\n}\n\n// Grid\n.grid {\n  display: grid;\n  height: 130 * 3px + 20px;\n  grid-gap: 10px;\n  grid-template-columns: auto auto auto auto;\n  width: auto;\n  white-space: nowrap;\n  border: 0;\n  background-color: transparent;\n}\n\n.gridItem {\n  width: 130px;\n  height: 130px;\n  padding: 0;\n  border: none;\n  background-color: transparent;\n\n  .wrapper {\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    width: 100%;\n    height: 100%;\n    background-color: #fff;\n    transform: scale(1);\n    font-size: 28px;\n\n    span {\n      display: none;\n    }\n  }\n}\n\n.gridVariableSized {\n  .gridItem {\n    &[data-index='0'] {\n      width: auto !important;\n      height: auto !important;\n      grid-column-end: span 2;\n      grid-row-end: span 2;\n    }\n\n    &.sorting {\n      .wrapper {\n        transition: transform 150ms ease-in-out;\n      }\n    }\n  }\n}\n\n.gridItemVariableSized {\n  &[data-index='0'] {\n    .wrapper {\n      font-size: 56px;\n    }\n  }\n}\n\n// Nested\n.category {\n  height: auto;\n\n  .categoryHeader {\n    display: flex;\n    flex-flow: row nowrap;\n    align-items: center;\n    padding: 10px 14px;\n    background: #f9f9f9;\n    border-bottom: 1px solid #efefef;\n    user-select: none;\n  }\n\n  .categoryList {\n    height: auto;\n  }\n}\n\n// Divider\n.divider {\n  padding: 10px 20px;\n  background: #f9f9f9;\n  border-bottom: 1px solid #efefef;\n  text-transform: uppercase;\n  font-size: 14px;\n  color: #333;\n}\n\n// Helper styles\n.helper {\n  box-shadow: 0 5px 5px -5px rgba(0, 0, 0, 0.2),\n    0 -5px 5px -5px rgba(0, 0, 0, 0.2);\n\n  cursor: grabbing;\n}\n\n.stylizedHelper {\n  &:not(.gridItem),\n  &.gridItem .wrapper {\n    border: 1px solid #efefef;\n    box-shadow: 0 5px 5px -5px rgba(0, 0, 0, 0.2);\n    background-color: rgba(255, 255, 255, 0.9);\n    border-radius: 3px;\n\n    &.horizontalItem {\n      cursor: col-resize;\n    }\n\n    &:focus {\n      box-shadow: 0 0px 5px 1px $focusedOutlineColor;\n    }\n  }\n\n  &.gridItem .wrapper {\n    transition: transform 150ms ease-in-out;\n  }\n}\n\n.shrinkedHelper {\n  height: 20px !important;\n}\n\n:global {\n  body {\n    font-family: 'Montserrat', 'Helvetica Neue', 'Helvetica', arial, sans-serif;\n    -webkit-font-smoothing: antialiased;\n    -moz-osx-font-smoothing: grayscale;\n    background-color: rgba(#f4f5f9, 0.7);\n  }\n  html,\n  body,\n  #root {\n    height: 100%;\n    margin: 0;\n  }\n}\n"
  },
  {
    "path": "src/.stories/grouping-items/Item/Item.js",
    "content": "import React from 'react';\nimport classNames from 'classnames';\nimport {sortableElement} from '../../../../src';\n\nimport styles from './Item.scss';\n\nconst ENTER_KEY = 13;\n\nfunction Item(props) {\n  const {\n    dragging,\n    sorting,\n    onClick,\n    selected,\n    selectedItemsCount,\n    value,\n  } = props;\n  const shouldRenderItemCountBadge = dragging && selectedItemsCount > 1;\n\n  return (\n    <div\n      className={classNames(\n        styles.Item,\n        selected && !dragging && styles.selected,\n        dragging && styles.dragging,\n        sorting && styles.sorting,\n      )}\n      onClick={() => onClick(value)}\n      onKeyPress={(event) => {\n        if (event.which === ENTER_KEY) {\n          onClick(value);\n        }\n      }}\n      tabIndex={0}\n    >\n      Item {value}\n      {shouldRenderItemCountBadge ? <Badge count={selectedItemsCount} /> : null}\n    </div>\n  );\n}\n\nfunction Badge(props) {\n  return <div className={styles.Badge}>{props.count}</div>;\n}\n\nexport default sortableElement(Item);\n"
  },
  {
    "path": "src/.stories/grouping-items/Item/Item.scss",
    "content": "$color: #333;\n$white: #fff;\n$backgroundColor: $white;\n\n$boxShadow: 0 5px 5px -5px rgba(0, 0, 0, 0.2);\n\n$fontWeight-regular: 400;\n$fontWeight-bold: 600;\n\n$borderRadius: 3px;\n$borderWidth: 1px;\n$borderColor: #efefef;\n\n$selectedColor: $white;\n$selectedBackgroundColor: rgba(216, 232, 251, 0.9);\n$selectedBorderColor: #bbcee8;\n\n$badgeColor: $white;\n$badgeBackgroundColor: #f75959;\n$badgeBorderColor: #da4553;\n\n$focusedOutlineColor: #4c9ffe;\n\n.Item {\n  display: flex;\n  align-items: center;\n  width: 100%;\n  height: 59px;\n  padding: 0 20px;\n  background-color: $backgroundColor;\n  border-bottom: $borderWidth solid #efefef;\n  box-sizing: border-box;\n  user-select: none;\n  outline: none;\n\n  color: $color;\n  font-weight: $fontWeight-regular;\n\n  cursor: grab;\n\n  &:last-child {\n    border-bottom: none;\n  }\n\n  &.selected {\n    background: $selectedBackgroundColor;\n    border-bottom-color: $selectedBorderColor;\n\n    &:focus {\n      border-bottom-color: $focusedOutlineColor;\n    }\n  }\n\n  &.sorting {\n    pointer-events: none;\n  }\n\n  &.dragging {\n    border-radius: $borderRadius;\n    border: $borderWidth solid #efefef;\n    box-shadow: $boxShadow;\n\n    &:focus {\n      box-shadow: 0 0px 5px 1px $focusedOutlineColor;\n    }\n  }\n\n  &:focus {\n    text-indent: -2px;\n    border: 2px solid $focusedOutlineColor;\n  }\n}\n\n.Badge {\n  position: absolute;\n  top: -8px;\n  right: -8px;\n  padding: 0.35em 0.5em;\n  border-radius: 0.3rem;\n\n  color: $badgeColor;\n  font-size: 0.8em;\n  font-weight: $fontWeight-bold;\n  background-color: $badgeBackgroundColor;\n  border: $borderWidth solid $badgeBorderColor;\n}\n"
  },
  {
    "path": "src/.stories/grouping-items/Item/index.js",
    "content": "import Item from './Item';\n\nexport default Item;\n"
  },
  {
    "path": "src/.stories/grouping-items/List/List.js",
    "content": "import React from 'react';\nimport {sortableContainer} from '../../../../src';\n\nimport Item from '../Item';\n\nimport styles from './List.scss';\n\nfunction List({items, isSorting, selectedItems, sortingItemKey, onItemSelect}) {\n  return (\n    <div className={styles.List}>\n      {items.map((value, index) => {\n        const isSelected = selectedItems.includes(value);\n        const itemIsBeingDragged = sortingItemKey === value;\n\n        return (\n          <Item\n            key={`item-${value}`}\n            selected={isSelected}\n            dragging={itemIsBeingDragged}\n            sorting={isSorting}\n            index={index}\n            value={value}\n            onClick={onItemSelect}\n            selectedItemsCount={selectedItems.length}\n          />\n        );\n      })}\n    </div>\n  );\n}\n\nexport default sortableContainer(List);\n"
  },
  {
    "path": "src/.stories/grouping-items/List/List.scss",
    "content": "$backgroundColor: #f3f3f3;\n$borderColor: #efefef;\n$borderWidth: 1px;\n\n.List {\n  position: relative;\n  width: 400px;\n  height: 600px;\n  overflow: auto;\n  -webkit-overflow-scrolling: touch;\n  z-index: 0;\n  background-color: $backgroundColor;\n  border: $borderWidth solid $borderColor;\n  border-radius: 3px;\n  outline: none;\n}\n"
  },
  {
    "path": "src/.stories/grouping-items/List/index.js",
    "content": "import List from './List';\n\nexport default List;\n"
  },
  {
    "path": "src/.stories/grouping-items/index.js",
    "content": "import React from 'react';\nimport arrayMove from 'array-move';\nimport {generateItems} from './utils';\n\nimport SortableList from './List';\n\nclass GroupedItems extends React.Component {\n  state = {\n    selectedItems: [],\n    items: generateItems(50),\n  };\n\n  render() {\n    const {items, isSorting, selectedItems, sortingItemKey} = this.state;\n\n    return (\n      <SortableList\n        items={items.filter(this.filterItems)}\n        isSorting={isSorting}\n        sortingItemKey={sortingItemKey}\n        selectedItems={selectedItems}\n        onItemSelect={this.handleItemSelect}\n        shouldCancelStart={this.handleShouldCancelStart}\n        updateBeforeSortStart={this.handleUpdateBeforeSortStart}\n        onSortStart={this.handleSortStart}\n        onSortEnd={this.handleSortEnd}\n        distance={3}\n      />\n    );\n  }\n\n  filterItems = (value) => {\n    const {selectedItems, sortingItemKey, isSorting} = this.state;\n\n    // Do not hide the ghost of the element currently being sorted\n    if (sortingItemKey === value) {\n      return true;\n    }\n\n    // Hide the other items that are selected\n    if (isSorting && selectedItems.includes(value)) {\n      return false;\n    }\n\n    // Do not hide any other items\n    return true;\n  };\n\n  handleUpdateBeforeSortStart = ({index}) => {\n    return new Promise((resolve) =>\n      this.setState(\n        ({items}) => ({\n          sortingItemKey: items[index],\n          isSorting: true,\n        }),\n        resolve,\n      ),\n    );\n  };\n\n  handleSortStart() {\n    document.body.style.cursor = 'grabbing';\n  }\n\n  handleSortEnd = ({oldIndex, newIndex}) => {\n    const {selectedItems} = this.state;\n    let newItems;\n\n    if (selectedItems.length) {\n      const items = this.state.items.filter(\n        (value) => !selectedItems.includes(value),\n      );\n\n      newItems = [\n        ...items.slice(0, newIndex),\n        ...selectedItems,\n        ...items.slice(newIndex, items.length),\n      ];\n    } else {\n      newItems = arrayMove(this.state.items, oldIndex, newIndex);\n    }\n\n    this.setState({\n      items: newItems,\n      isSorting: false,\n      sortingItemKey: null,\n      selectedItems: [],\n    });\n\n    document.body.style.cursor = '';\n  };\n\n  handleItemSelect = (item) => {\n    this.setState(({selectedItems}) => {\n      if (selectedItems.includes(item)) {\n        return {\n          selectedItems: selectedItems.filter((value) => value !== item),\n        };\n      }\n\n      return {\n        selectedItems: [...selectedItems, item],\n      };\n    });\n  };\n\n  handleShouldCancelStart = (event) => {\n    const {items, selectedItems} = this.state;\n    const item = items[event.target.sortableInfo.index];\n\n    // Never cancel start if there are no selected items\n    if (!selectedItems.length) {\n      return false;\n    }\n\n    // If there are selected items, we want to cancel sorting\n    // from starting when dragging elements that are not selected\n    return !selectedItems.includes(item);\n  };\n}\n\nexport default GroupedItems;\n"
  },
  {
    "path": "src/.stories/grouping-items/utils.js",
    "content": "export function generateItems(length) {\n  return Array.from(Array(length), (_, index) => index.toString());\n}\n"
  },
  {
    "path": "src/.stories/index.js",
    "content": "import React, {Component} from 'react';\nimport PropTypes from 'prop-types';\nimport ReactDOM from 'react-dom';\nimport {storiesOf} from '@storybook/react';\nimport style from './Storybook.scss';\nimport {SortableContainer, SortableElement, SortableHandle} from '../index';\nimport arrayMove from 'array-move';\nimport VirtualList from 'react-tiny-virtual-list';\nimport {FixedSizeList, VariableSizeList} from 'react-window';\nimport {defaultTableRowRenderer, Column, Table, List} from 'react-virtualized';\nimport '!style-loader!css-loader!react-virtualized/styles.css';\nimport Infinite from 'react-infinite';\nimport range from 'lodash/range';\nimport random from 'lodash/random';\nimport classNames from 'classnames';\n\nimport GroupedItems from './grouping-items';\nimport InteractiveElements from './interactive-elements-stress-test';\n\nfunction getItems(count, height) {\n  var heights = [65, 110, 140, 65, 90, 65];\n  return range(count).map((value) => {\n    return {\n      value,\n      height: height == null ? heights[random(0, heights.length - 1)] : height,\n    };\n  });\n}\n\nconst Handle = SortableHandle(({tabIndex}) => (\n  <div className={style.handle} tabIndex={tabIndex}>\n    <svg viewBox=\"0 0 50 50\">\n      <path\n        d=\"M 0 7.5 L 0 12.5 L 50 12.5 L 50 7.5 L 0 7.5 z M 0 22.5 L 0 27.5 L 50 27.5 L 50 22.5 L 0 22.5 z M 0 37.5 L 0 42.5 L 50 42.5 L 50 37.5 L 0 37.5 z\"\n        color=\"#000\"\n      />\n    </svg>\n  </div>\n));\n\nconst Item = SortableElement(\n  ({\n    tabbable,\n    className,\n    isDisabled,\n    height,\n    style: propStyle,\n    shouldUseDragHandle,\n    value,\n    itemIndex,\n    isSorting,\n  }) => {\n    const bodyTabIndex = tabbable && !shouldUseDragHandle ? 0 : -1;\n    const handleTabIndex = tabbable && shouldUseDragHandle ? 0 : -1;\n\n    return (\n      <div\n        className={classNames(\n          className,\n          isDisabled && style.disabled,\n          isSorting && style.sorting,\n          shouldUseDragHandle && style.containsDragHandle,\n        )}\n        style={{\n          height,\n          ...propStyle,\n        }}\n        tabIndex={bodyTabIndex}\n        data-index={itemIndex}\n      >\n        {shouldUseDragHandle && <Handle tabIndex={handleTabIndex} />}\n        <div className={style.wrapper}>\n          <span>Item</span> {value}\n        </div>\n      </div>\n    );\n  },\n);\n\nconst SortableList = SortableContainer(\n  ({\n    className,\n    items,\n    disabledItems = [],\n    itemClass,\n    isSorting,\n    shouldUseDragHandle,\n    type,\n  }) => {\n    return (\n      <div className={className}>\n        {items.map(({value, height}, index) => {\n          const disabled = disabledItems.includes(value);\n\n          return (\n            <Item\n              tabbable\n              key={`item-${value}`}\n              disabled={disabled}\n              isDisabled={disabled}\n              className={itemClass}\n              index={index}\n              itemIndex={index}\n              value={value}\n              height={height}\n              shouldUseDragHandle={shouldUseDragHandle}\n              type={type}\n              isSorting={isSorting}\n            />\n          );\n        })}\n      </div>\n    );\n  },\n);\n\nclass SortableListWithCustomContainer extends React.Component {\n  state = {\n    container: null,\n  };\n\n  render() {\n    const {container} = this.state;\n\n    return (\n      <div id=\"CustomHelperContainer\" ref={this.setContainerNode}>\n        <SortableList {...this.props} helperContainer={container} />\n      </div>\n    );\n  }\n\n  setContainerNode = (node) => {\n    this.setState({container: node});\n  };\n}\n\nconst Category = SortableElement((props) => {\n  const tabIndex = props.tabbable ? 0 : -1;\n\n  return (\n    <div className={style.category}>\n      <div className={style.categoryHeader}>\n        <Handle tabIndex={tabIndex} />\n        <span>Category {props.value}</span>\n      </div>\n      <ListWrapper\n        component={SortableList}\n        className={style.categoryList}\n        items={getItems(3, 59)}\n        shouldUseDragHandle={true}\n        helperClass={style.stylizedHelper}\n      />\n    </div>\n  );\n});\n\nclass ListWrapper extends Component {\n  state = {\n    items: this.props.items,\n    isSorting: false,\n  };\n\n  static propTypes = {\n    items: PropTypes.array,\n    className: PropTypes.string,\n    itemClass: PropTypes.string,\n    width: PropTypes.number,\n    height: PropTypes.number,\n    onSortStart: PropTypes.func,\n    onSortEnd: PropTypes.func,\n    component: PropTypes.func,\n    shouldUseDragHandle: PropTypes.bool,\n    disabledItems: PropTypes.arrayOf(PropTypes.string),\n  };\n\n  static defaultProps = {\n    className: classNames(style.list, style.stylizedList),\n    itemClass: classNames(style.item, style.stylizedItem),\n    width: 400,\n    height: 600,\n  };\n\n  onSortStart = (sortEvent, nativeEvent) => {\n    const {onSortStart} = this.props;\n    this.setState({isSorting: true});\n\n    document.body.style.cursor = 'grabbing';\n\n    if (onSortStart) {\n      onSortStart(sortEvent, nativeEvent, this.refs.component);\n    }\n  };\n\n  onSortEnd = (sortEvent, nativeEvent) => {\n    const {onSortEnd} = this.props;\n    const {oldIndex, newIndex} = sortEvent;\n    const {items} = this.state;\n\n    this.setState({\n      items: arrayMove(items, oldIndex, newIndex),\n      isSorting: false,\n    });\n\n    document.body.style.cursor = '';\n\n    if (onSortEnd) {\n      onSortEnd(sortEvent, nativeEvent, this.refs.component);\n    }\n  };\n\n  render() {\n    const Component = this.props.component;\n    const {items, isSorting} = this.state;\n    const props = {\n      isSorting,\n      items,\n      onSortEnd: this.onSortEnd,\n      onSortStart: this.onSortStart,\n      ref: 'component',\n      useDragHandle: this.props.shouldUseDragHandle,\n    };\n\n    return <Component {...this.props} {...props} />;\n  }\n}\n\nconst SortableReactWindow = (Component) =>\n  SortableContainer(\n    class ReactWindowList extends React.Component {\n      render() {\n        const {className, items, itemHeight, height, width} = this.props;\n\n        return (\n          <Component\n            ref=\"VirtualList\"\n            className={classNames(className, style.isSorting)}\n            itemSize={\n              itemHeight == null ? (index) => items[index].height : itemHeight\n            }\n            itemCount={items.length}\n            width={width}\n            height={height}\n            children={this.renderRow}\n          />\n        );\n      }\n\n      renderRow = ({index, style}) => {\n        const {items, itemClass, isSorting} = this.props;\n        const {value, height} = items[index];\n\n        return (\n          <Item\n            tabbable\n            key={value}\n            index={index}\n            className={itemClass}\n            value={value}\n            height={height}\n            style={style}\n            isSorting={isSorting}\n          />\n        );\n      };\n    },\n    {withRef: true},\n  );\n\nconst SortableVirtualList = SortableContainer(\n  ({className, items, height, width, itemHeight, itemClass, isSorting}) => {\n    return (\n      <VirtualList\n        className={className}\n        itemSize={(index) => items[index].height}\n        estimatedItemSize={itemHeight}\n        renderItem={({index, style}) => {\n          const {value, height} = items[index];\n          return (\n            <Item\n              tabbable\n              key={value}\n              index={index}\n              className={itemClass}\n              value={value}\n              height={height}\n              style={style}\n              isSorting={isSorting}\n            />\n          );\n        }}\n        itemCount={items.length}\n        width={width}\n        height={height}\n      />\n    );\n  },\n);\n\n// Function components cannot have refs, so we'll be using a class for React Virtualized\nclass VirtualizedListWrapper extends Component {\n  render() {\n    const {\n      className,\n      items,\n      height,\n      width,\n      itemHeight,\n      itemClass,\n      isSorting,\n    } = this.props;\n    return (\n      <List\n        ref=\"VirtualList\"\n        className={className}\n        rowHeight={({index}) => items[index].height}\n        estimatedRowSize={itemHeight}\n        rowRenderer={({index, style}) => {\n          const {value, height} = items[index];\n          return (\n            <Item\n              tabbable\n              key={value}\n              index={index}\n              className={itemClass}\n              value={value}\n              height={height}\n              style={style}\n              isSorting={isSorting}\n            />\n          );\n        }}\n        rowCount={items.length}\n        width={width}\n        height={height}\n      />\n    );\n  }\n}\n\nconst SortableVirtualizedList = SortableContainer(VirtualizedListWrapper, {\n  withRef: true,\n});\nconst SortableTable = SortableContainer(Table, {withRef: true});\nconst SortableRowRenderer = SortableElement(defaultTableRowRenderer);\n\nclass TableWrapper extends Component {\n  static propTypes = {\n    items: PropTypes.array,\n    className: PropTypes.string,\n    helperClass: PropTypes.string,\n    itemClass: PropTypes.string,\n    width: PropTypes.number,\n    height: PropTypes.number,\n    itemHeight: PropTypes.number,\n    onSortEnd: PropTypes.func,\n  };\n  render() {\n    const {\n      className,\n      height,\n      helperClass,\n      itemClass,\n      itemHeight,\n      items,\n      onSortEnd,\n      width,\n    } = this.props;\n\n    return (\n      <SortableTable\n        getContainer={(wrappedInstance) =>\n          ReactDOM.findDOMNode(wrappedInstance.Grid)\n        }\n        gridClassName={className}\n        headerHeight={itemHeight}\n        height={height}\n        helperClass={helperClass}\n        onSortEnd={onSortEnd}\n        rowClassName={itemClass}\n        rowCount={items.length}\n        rowGetter={({index}) => items[index]}\n        rowHeight={itemHeight}\n        rowRenderer={(props) => <SortableRowRenderer {...props} />}\n        width={width}\n      >\n        <Column label=\"Index\" dataKey=\"value\" width={100} />\n        <Column label=\"Height\" dataKey=\"height\" width={width - 100} />\n      </SortableTable>\n    );\n  }\n}\n\nconst SortableInfiniteList = SortableContainer(\n  ({className, items, itemClass, isSorting}) => {\n    return (\n      <Infinite\n        className={className}\n        containerHeight={600}\n        elementHeight={items.map(({height}) => height)}\n        // for react-infinite, a larger preload is better for keyboard sorting\n        preloadBatchSize={Infinite.containerHeightScaleFactor(2)}\n        preloadAdditionalHeight={Infinite.containerHeightScaleFactor(2)}\n      >\n        {items.map(({value, height}, index) => (\n          <Item\n            tabbable\n            key={`item-${index}`}\n            className={itemClass}\n            index={index}\n            value={value}\n            height={height}\n            isSorting={isSorting}\n          />\n        ))}\n      </Infinite>\n    );\n  },\n);\n\nconst ShrinkingSortableList = SortableContainer(\n  ({className, isSorting, items, itemClass, shouldUseDragHandle}) => {\n    return (\n      <div className={className}>\n        {items.map(({value, height}, index) => (\n          <Item\n            tabbable\n            key={`item-${value}`}\n            className={itemClass}\n            index={index}\n            value={value}\n            height={isSorting ? 20 : height}\n            shouldUseDragHandle={shouldUseDragHandle}\n            isSorting={isSorting}\n          />\n        ))}\n      </div>\n    );\n  },\n);\n\nconst NestedSortableList = SortableContainer(\n  ({className, items, isSorting}) => {\n    return (\n      <div className={className}>\n        {items.map((value, index) => (\n          <Category\n            tabbable\n            key={`category-${value}`}\n            index={index}\n            value={value}\n          />\n        ))}\n      </div>\n    );\n  },\n);\n\nstoriesOf('General | Layout / Vertical list', module)\n  .add('Basic setup', () => {\n    return (\n      <div className={style.root}>\n        <ListWrapper\n          component={SortableList}\n          items={getItems(50, 59)}\n          helperClass={style.stylizedHelper}\n        />\n      </div>\n    );\n  })\n  .add('Variable heights', () => {\n    return (\n      <div className={style.root}>\n        <ListWrapper\n          component={SortableList}\n          items={getItems(50)}\n          helperClass={style.stylizedHelper}\n        />\n      </div>\n    );\n  })\n  .add('Nested Lists', () => {\n    return (\n      <div className={style.root}>\n        <ListWrapper\n          component={NestedSortableList}\n          items={range(4)}\n          shouldUseDragHandle={true}\n          helperClass={style.stylizedHelper}\n        />\n      </div>\n    );\n  });\n\nstoriesOf('General | Layout / Horizontal list', module).add(\n  'Basic setup',\n  () => {\n    return (\n      <div className={style.root}>\n        <ListWrapper\n          component={SortableList}\n          axis={'x'}\n          items={getItems(50, 300)}\n          helperClass={style.stylizedHelper}\n          className={classNames(\n            style.list,\n            style.stylizedList,\n            style.horizontalList,\n          )}\n          itemClass={classNames(style.stylizedItem, style.horizontalItem)}\n        />\n      </div>\n    );\n  },\n);\n\nstoriesOf('General | Layout / Grid', module)\n  .add('Basic setup', () => {\n    const transformOrigin = {\n      x: 0,\n      y: 0,\n    };\n\n    return (\n      <div className={style.root}>\n        <ListWrapper\n          component={SortableList}\n          axis={'xy'}\n          items={getItems(10, false)}\n          helperClass={style.stylizedHelper}\n          className={classNames(style.list, style.stylizedList, style.grid)}\n          itemClass={classNames(style.stylizedItem, style.gridItem)}\n        />\n      </div>\n    );\n  })\n  .add('Large first item', () => {\n    return (\n      <div className={style.root}>\n        <ListWrapper\n          component={SortableList}\n          axis={'xy'}\n          items={getItems(9, false)}\n          helperClass={style.stylizedHelper}\n          className={classNames(\n            style.list,\n            style.stylizedList,\n            style.grid,\n            style.gridVariableSized,\n          )}\n          itemClass={classNames(\n            style.stylizedItem,\n            style.gridItem,\n            style.gridItemVariableSized,\n          )}\n          onSortStart={({node, helper}, event) => {\n            const nodeBoundingClientRect = node.getBoundingClientRect();\n            const helperWrapperNode = helper.childNodes[0];\n            const transformOrigin = {\n              x:\n                ((event.clientX - nodeBoundingClientRect.left) /\n                  nodeBoundingClientRect.width) *\n                100,\n              y:\n                ((event.clientY - nodeBoundingClientRect.top) /\n                  nodeBoundingClientRect.height) *\n                100,\n            };\n\n            helperWrapperNode.style.transformOrigin = `${transformOrigin.x}% ${transformOrigin.y}%`;\n          }}\n          onSortOver={({nodes, newIndex, index, helper}) => {\n            const finalNodes = arrayMove(nodes, index, newIndex);\n            const oldNode = nodes[index].node;\n            const newNode = nodes[newIndex].node;\n            const helperScale = newNode.offsetWidth / oldNode.offsetWidth;\n            const helperWrapperNode = helper.childNodes[0];\n\n            helperWrapperNode.style.transform = `scale(${helperScale})`;\n\n            finalNodes.forEach(({node}, i) => {\n              const oldNode = nodes[i].node;\n              const scale = oldNode.offsetWidth / node.offsetWidth;\n              const wrapperNode = node.querySelector(`.${style.wrapper}`);\n\n              wrapperNode.style.transform = `scale(${scale})`;\n              wrapperNode.style.transformOrigin =\n                newIndex > i ? '0 0' : '100% 0';\n            });\n          }}\n          onSortEnd={({nodes}) => {\n            nodes.forEach(({node}) => {\n              const wrapperNode = node.querySelector(`.${style.wrapper}`);\n\n              wrapperNode.style.transform = '';\n            });\n          }}\n        />\n      </div>\n    );\n  });\n\nstoriesOf('General | Configuration / Options', module)\n  .add('Drag handle', () => {\n    return (\n      <div className={style.root}>\n        <ListWrapper\n          component={SortableList}\n          shouldUseDragHandle={true}\n          items={getItems(50, 59)}\n          helperClass={style.stylizedHelper}\n        />\n      </div>\n    );\n  })\n  .add('Disabled items', () => {\n    return (\n      <div className={style.root}>\n        <ListWrapper\n          component={SortableList}\n          items={getItems(10, 59)}\n          helperClass={style.stylizedHelper}\n          disabledItems={[2, 3, 7]}\n        />\n      </div>\n    );\n  })\n  .add('Press delay (200ms)', () => {\n    return (\n      <div className={style.root}>\n        <ListWrapper\n          component={SortableList}\n          items={getItems(50, 59)}\n          pressDelay={200}\n          helperClass={style.stylizedHelper}\n        />\n      </div>\n    );\n  })\n  .add('Distance (20px)', () => {\n    return (\n      <div className={style.root}>\n        <ListWrapper\n          component={SortableList}\n          items={getItems(50, 50)}\n          distance={20}\n          helperClass={style.stylizedHelper}\n        />\n      </div>\n    );\n  })\n  .add('Lock axis', () => {\n    return (\n      <div className={style.root}>\n        <ListWrapper\n          component={SortableList}\n          items={getItems(50)}\n          helperClass={style.stylizedHelper}\n          lockAxis={'y'}\n          lockOffset={['0%', '100%']}\n        />\n      </div>\n    );\n  })\n  .add('Window as scroll container', () => {\n    return (\n      <ListWrapper\n        component={SortableList}\n        items={getItems(50, 59)}\n        className=\"\"\n        useWindowAsScrollContainer={true}\n        helperClass={style.stylizedHelper}\n      />\n    );\n  })\n  .add('Custom sortable helper container', () => {\n    return (\n      <div className={style.root}>\n        <ListWrapper\n          component={SortableListWithCustomContainer}\n          items={getItems(50, 59)}\n          helperClass={style.stylizedHelper}\n        />\n      </div>\n    );\n  });\n\nstoriesOf('General | Configuration / Customization', module)\n  .add('Minimal styling', () => {\n    return (\n      <div className={style.root}>\n        <ListWrapper\n          component={SortableList}\n          items={getItems(50)}\n          className={style.list}\n          itemClass={style.item}\n          helperClass={style.helper}\n        />\n      </div>\n    );\n  })\n  .add('Transition duration', () => {\n    return (\n      <div className={style.root}>\n        <ListWrapper\n          component={SortableList}\n          items={getItems(50, 59)}\n          transitionDuration={450}\n          helperClass={style.stylizedHelper}\n        />\n      </div>\n    );\n  })\n  .add('Disable transitions', () => {\n    return (\n      <div className={style.root}>\n        <ListWrapper\n          component={SortableList}\n          items={getItems(50, 59)}\n          transitionDuration={0}\n          helperClass={style.stylizedHelper}\n        />\n      </div>\n    );\n  });\n\nstoriesOf(\n  'Advanced examples | Virtualization libraries / react-tiny-virtual-list',\n  module,\n)\n  .add('Basic setup', () => {\n    return (\n      <div className={style.root}>\n        <ListWrapper\n          component={SortableVirtualList}\n          items={getItems(500, 59)}\n          itemHeight={59}\n          helperClass={style.stylizedHelper}\n        />\n      </div>\n    );\n  })\n  .add('Variable heights', () => {\n    return (\n      <div className={style.root}>\n        <ListWrapper\n          component={SortableVirtualList}\n          items={getItems(500)}\n          itemHeight={89}\n          helperClass={style.stylizedHelper}\n        />\n      </div>\n    );\n  });\n\nstoriesOf('Advanced examples | Virtualization libraries / react-window', module)\n  .add('Basic setup', () => {\n    return (\n      <div className={style.root}>\n        <ListWrapper\n          component={SortableReactWindow(FixedSizeList)}\n          items={getItems(500, 59)}\n          itemHeight={59}\n          helperClass={style.stylizedHelper}\n          onSortEnd={(_sortEvent, _nativeEvent, ref) => {\n            // We need to inform React Window that the order of the items has changed\n            const instance = ref.getWrappedInstance();\n            const list = instance.refs.VirtualList;\n\n            list.forceUpdate();\n          }}\n        />\n      </div>\n    );\n  })\n  .add('Variable heights', () => {\n    return (\n      <div className={style.root}>\n        <ListWrapper\n          component={SortableReactWindow(VariableSizeList)}\n          items={getItems(500)}\n          helperClass={style.stylizedHelper}\n          onSortEnd={(_sortEvent, _nativeEvent, ref) => {\n            // We need to inform React Window that the item heights have changed\n            const instance = ref.getWrappedInstance();\n            const list = instance.refs.VirtualList;\n\n            list.resetAfterIndex(0);\n          }}\n        />\n      </div>\n    );\n  });\n\nstoriesOf(\n  'Advanced examples | Virtualization libraries / react-virtualized',\n  module,\n)\n  .add('Basic setup', () => {\n    return (\n      <div className={style.root}>\n        <ListWrapper\n          component={SortableVirtualizedList}\n          items={getItems(500, 59)}\n          itemHeight={59}\n          helperClass={style.stylizedHelper}\n        />\n      </div>\n    );\n  })\n  .add('Variable heights', () => {\n    return (\n      <div className={style.root}>\n        <ListWrapper\n          component={SortableVirtualizedList}\n          items={getItems(500)}\n          itemHeight={89}\n          helperClass={style.stylizedHelper}\n          onSortEnd={(_sortEvent, _nativeEvent, ref) => {\n            // We need to inform React Virtualized that the item heights have changed\n            const instance = ref.getWrappedInstance();\n            const list = instance.refs.VirtualList;\n\n            list.recomputeRowHeights();\n            instance.forceUpdate();\n          }}\n        />\n      </div>\n    );\n  })\n  .add('Table', () => {\n    return (\n      <div className={style.root}>\n        <ListWrapper\n          component={TableWrapper}\n          items={getItems(500, 50)}\n          itemHeight={50}\n          helperClass={style.stylizedHelper}\n        />\n      </div>\n    );\n  });\n\nstoriesOf(\n  'Advanced examples | Virtualization libraries / react-infinite',\n  module,\n)\n  .add('Basic setup', () => {\n    return (\n      <div className={style.root}>\n        <ListWrapper\n          component={SortableInfiniteList}\n          items={getItems(500, 59)}\n          helperClass={style.stylizedHelper}\n        />\n      </div>\n    );\n  })\n  .add('Variable heights', () => {\n    return (\n      <div className={style.root}>\n        <ListWrapper\n          component={SortableInfiniteList}\n          items={getItems(500)}\n          helperClass={style.stylizedHelper}\n        />\n      </div>\n    );\n  });\n\nstoriesOf('Advanced examples | Re-rendering before sorting', module)\n  .add('Grouping items', () => (\n    <div className={style.root}>\n      <GroupedItems />\n    </div>\n  ))\n  .add('Elements that shrink', () => {\n    const getHelperDimensions = ({node}) => ({\n      height: 20,\n      width: node.offsetWidth,\n    });\n    return (\n      <div className={style.root}>\n        <ListWrapper\n          component={ShrinkingSortableList}\n          items={getItems(50)}\n          helperClass={style.shrinkedHelper}\n          getHelperDimensions={getHelperDimensions}\n        />\n      </div>\n    );\n  });\n\nstoriesOf('Stress Testing | Nested elements', module).add(\n  'Interactive elements',\n  () => (\n    <div className={style.root}>\n      <InteractiveElements />\n    </div>\n  ),\n);\n"
  },
  {
    "path": "src/.stories/interactive-elements-stress-test/Item/Item.js",
    "content": "import React from 'react';\nimport {sortableElement} from '../../../../src';\n\nimport styles from './Item.scss';\n\nfunction Item(props) {\n  const {children} = props;\n\n  return (\n    <div className={styles.root} tabIndex={0}>\n      {children}\n    </div>\n  );\n}\n\nexport default sortableElement(Item);\n"
  },
  {
    "path": "src/.stories/interactive-elements-stress-test/Item/Item.scss",
    "content": "$color: #333;\n$white: #fff;\n$backgroundColor: $white;\n\n$padding: 20px;\n\n$boxShadow: 0 5px 5px -5px rgba(0, 0, 0, 0.2);\n\n$fontWeight-regular: 400;\n$fontWeight-bold: 600;\n\n$borderRadius: 3px;\n$borderWidth: 1px;\n$borderColor: #efefef;\n\n$focusedOutlineColor: #4c9ffe;\n\n.root {\n  display: block;\n  width: 250px;\n  padding: $padding;\n  background-color: $backgroundColor;\n  border-bottom: $borderWidth solid #efefef;\n  box-sizing: border-box;\n  user-select: none;\n\n  color: $color;\n  font-family: sans-serif;\n  font-weight: $fontWeight-regular;\n\n  > * {\n    display: block;\n    width: 100%;\n    font-size: 14px;\n  }\n\n  > input,\n  > textarea {\n    padding: 5px;\n    border: 1px solid #e0e0e0;\n    box-sizing: border-box;\n  }\n\n  label {\n    input {\n      margin-right: 0.5em;\n    }\n  }\n\n  &:focus {\n    outline: none;\n    padding: $padding - 2px;\n    padding-bottom: $padding - 1px;\n    border: 2px solid $focusedOutlineColor;\n  }\n\n  &.dragging {\n    &:focus {\n      box-shadow: 0 0px 5px 1px $focusedOutlineColor;\n    }\n  }\n}\n"
  },
  {
    "path": "src/.stories/interactive-elements-stress-test/Item/index.js",
    "content": "import Item from './Item';\n\nexport default Item;\n"
  },
  {
    "path": "src/.stories/interactive-elements-stress-test/List.js",
    "content": "import React from 'react';\nimport {sortableContainer} from '../../../src';\n\nimport Item from './Item';\n\nfunction List({items}) {\n  return (\n    <div>\n      {items.map(([key, children], index) => {\n        return (\n          <Item key={key} index={index}>\n            {children}\n          </Item>\n        );\n      })}\n    </div>\n  );\n}\n\nexport default sortableContainer(List);\n"
  },
  {
    "path": "src/.stories/interactive-elements-stress-test/index.js",
    "content": "import React from 'react';\nimport arrayMove from 'array-move';\n\nimport SortableList from './List';\nimport ItemStyles from './Item/Item.scss';\n\nconst items = {\n  input: <input placeholder=\"Regular text input\" />,\n  textarea: <textarea placeholder=\"Textarea input\" />,\n  select: (\n    <select>\n      <option>Option 1</option>\n      <option>Option 2</option>\n      <option>Option 3</option>\n    </select>\n  ),\n  checkbox: (\n    <>\n      <label>\n        <input type=\"checkbox\" name=\"checkbox\" />\n        Checkbox 1\n      </label>\n      <label>\n        <input type=\"checkbox\" name=\"checkbox\" />\n        Checkbox 2\n      </label>\n    </>\n  ),\n  radio: (\n    <>\n      <label>\n        <input type=\"radio\" name=\"option\" />\n        Option 1\n      </label>\n      <label>\n        <input type=\"radio\" name=\"option\" />\n        Option 2\n      </label>\n    </>\n  ),\n  range: <input type=\"range\" min=\"1\" max=\"100\" />,\n  contentEditable: (\n    <div\n      contentEditable\n      dangerouslySetInnerHTML={{\n        __html: 'Lorem ipsum <strong>dolor sit</strong> amet',\n      }}\n    />\n  ),\n};\n\nexport default class InteractiveElements extends React.Component {\n  state = {\n    items: Object.entries(items),\n  };\n\n  render() {\n    return (\n      <SortableList\n        // The distance prop isn't strictly required for this example, but it is recommended\n        // to set it to a low value for sortable items with nested interactive elements\n        // such as clickable labels for checkbox / radio inputs\n        distance={2}\n        items={this.state.items}\n        onSortEnd={this.onSortEnd}\n        helperClass={ItemStyles.dragging}\n      />\n    );\n  }\n\n  onSortEnd = ({oldIndex, newIndex}) => {\n    if (oldIndex === newIndex) {\n      return;\n    }\n\n    this.setState(({items}) => ({\n      items: arrayMove(items, oldIndex, newIndex),\n    }));\n  };\n}\n"
  },
  {
    "path": "src/AutoScroller/index.js",
    "content": "export default class AutoScroller {\n  constructor(container, onScrollCallback) {\n    this.container = container;\n    this.onScrollCallback = onScrollCallback;\n  }\n\n  clear() {\n    if (this.interval == null) {\n      return;\n    }\n\n    clearInterval(this.interval);\n    this.interval = null;\n  }\n\n  update({translate, minTranslate, maxTranslate, width, height}) {\n    const direction = {\n      x: 0,\n      y: 0,\n    };\n    const speed = {\n      x: 1,\n      y: 1,\n    };\n    const acceleration = {\n      x: 10,\n      y: 10,\n    };\n\n    const {\n      scrollTop,\n      scrollLeft,\n      scrollHeight,\n      scrollWidth,\n      clientHeight,\n      clientWidth,\n    } = this.container;\n\n    const isTop = scrollTop === 0;\n    const isBottom = scrollHeight - scrollTop - clientHeight === 0;\n    const isLeft = scrollLeft === 0;\n    const isRight = scrollWidth - scrollLeft - clientWidth === 0;\n\n    if (translate.y >= maxTranslate.y - height / 2 && !isBottom) {\n      // Scroll Down\n      direction.y = 1;\n      speed.y =\n        acceleration.y *\n        Math.abs((maxTranslate.y - height / 2 - translate.y) / height);\n    } else if (translate.x >= maxTranslate.x - width / 2 && !isRight) {\n      // Scroll Right\n      direction.x = 1;\n      speed.x =\n        acceleration.x *\n        Math.abs((maxTranslate.x - width / 2 - translate.x) / width);\n    } else if (translate.y <= minTranslate.y + height / 2 && !isTop) {\n      // Scroll Up\n      direction.y = -1;\n      speed.y =\n        acceleration.y *\n        Math.abs((translate.y - height / 2 - minTranslate.y) / height);\n    } else if (translate.x <= minTranslate.x + width / 2 && !isLeft) {\n      // Scroll Left\n      direction.x = -1;\n      speed.x =\n        acceleration.x *\n        Math.abs((translate.x - width / 2 - minTranslate.x) / width);\n    }\n\n    if (this.interval) {\n      this.clear();\n      this.isAutoScrolling = false;\n    }\n\n    if (direction.x !== 0 || direction.y !== 0) {\n      this.interval = setInterval(() => {\n        this.isAutoScrolling = true;\n        const offset = {\n          left: speed.x * direction.x,\n          top: speed.y * direction.y,\n        };\n        this.container.scrollTop += offset.top;\n        this.container.scrollLeft += offset.left;\n\n        this.onScrollCallback(offset);\n      }, 5);\n    }\n  }\n}\n"
  },
  {
    "path": "src/Manager/index.js",
    "content": "export default class Manager {\n  refs = {};\n\n  add(collection, ref) {\n    if (!this.refs[collection]) {\n      this.refs[collection] = [];\n    }\n\n    this.refs[collection].push(ref);\n  }\n\n  remove(collection, ref) {\n    const index = this.getIndex(collection, ref);\n\n    if (index !== -1) {\n      this.refs[collection].splice(index, 1);\n    }\n  }\n\n  isActive() {\n    return this.active;\n  }\n\n  getActive() {\n    return this.refs[this.active.collection].find(\n      // eslint-disable-next-line eqeqeq\n      ({node}) => node.sortableInfo.index == this.active.index,\n    );\n  }\n\n  getIndex(collection, ref) {\n    return this.refs[collection].indexOf(ref);\n  }\n\n  getOrderedRefs(collection = this.active.collection) {\n    return this.refs[collection].sort(sortByIndex);\n  }\n}\n\nfunction sortByIndex(\n  {\n    node: {\n      sortableInfo: {index: index1},\n    },\n  },\n  {\n    node: {\n      sortableInfo: {index: index2},\n    },\n  },\n) {\n  return index1 - index2;\n}\n"
  },
  {
    "path": "src/SortableContainer/defaultGetHelperDimensions.js",
    "content": "export default function defaultGetHelperDimensions({node}) {\n  return {\n    height: node.offsetHeight,\n    width: node.offsetWidth,\n  };\n}\n"
  },
  {
    "path": "src/SortableContainer/defaultShouldCancelStart.js",
    "content": "import {NodeType, closest} from '../utils';\n\nexport default function defaultShouldCancelStart(event) {\n  // Cancel sorting if the event target is an `input`, `textarea`, `select` or `option`\n  const interactiveElements = [\n    NodeType.Input,\n    NodeType.Textarea,\n    NodeType.Select,\n    NodeType.Option,\n    NodeType.Button,\n  ];\n\n  if (interactiveElements.indexOf(event.target.tagName) !== -1) {\n    // Return true to cancel sorting\n    return true;\n  }\n\n  if (closest(event.target, (el) => el.contentEditable === 'true')) {\n    return true;\n  }\n\n  return false;\n}\n"
  },
  {
    "path": "src/SortableContainer/index.js",
    "content": "import * as React from 'react';\nimport {findDOMNode} from 'react-dom';\nimport invariant from 'invariant';\n\nimport Manager from '../Manager';\nimport {isSortableHandle} from '../SortableHandle';\n\nimport {\n  cloneNode,\n  closest,\n  events,\n  getScrollingParent,\n  getContainerGridGap,\n  getEdgeOffset,\n  getElementMargin,\n  getLockPixelOffsets,\n  getPosition,\n  isTouchEvent,\n  limit,\n  NodeType,\n  omit,\n  provideDisplayName,\n  setInlineStyles,\n  setTransitionDuration,\n  setTranslate3d,\n  getTargetIndex,\n  getScrollAdjustedBoundingClientRect,\n} from '../utils';\n\nimport AutoScroller from '../AutoScroller';\nimport {\n  defaultProps,\n  omittedProps,\n  propTypes,\n  validateProps,\n  defaultKeyCodes,\n} from './props';\n\nexport const SortableContext = React.createContext({\n  manager: {},\n});\n\nexport default function sortableContainer(\n  WrappedComponent,\n  config = {withRef: false},\n) {\n  return class WithSortableContainer extends React.Component {\n    constructor(props) {\n      super(props);\n      const manager = new Manager();\n\n      validateProps(props);\n\n      this.manager = manager;\n      this.wrappedInstance = React.createRef();\n      this.sortableContextValue = {manager};\n      this.events = {\n        end: this.handleEnd,\n        move: this.handleMove,\n        start: this.handleStart,\n      };\n    }\n\n    state = {};\n\n    static displayName = provideDisplayName('sortableList', WrappedComponent);\n    static defaultProps = defaultProps;\n    static propTypes = propTypes;\n\n    componentDidMount() {\n      const {useWindowAsScrollContainer} = this.props;\n      const container = this.getContainer();\n\n      Promise.resolve(container).then((containerNode) => {\n        this.container = containerNode;\n        this.document = this.container.ownerDocument || document;\n\n        /*\n         *  Set our own default rather than using defaultProps because Jest\n         *  snapshots will serialize window, causing a RangeError\n         *  https://github.com/clauderic/react-sortable-hoc/issues/249\n         */\n        const contentWindow =\n          this.props.contentWindow || this.document.defaultView || window;\n\n        this.contentWindow =\n          typeof contentWindow === 'function' ? contentWindow() : contentWindow;\n\n        this.scrollContainer = useWindowAsScrollContainer\n          ? this.document.scrollingElement || this.document.documentElement\n          : getScrollingParent(this.container) || this.container;\n\n        this.autoScroller = new AutoScroller(\n          this.scrollContainer,\n          this.onAutoScroll,\n        );\n\n        Object.keys(this.events).forEach((key) =>\n          events[key].forEach((eventName) =>\n            this.container.addEventListener(eventName, this.events[key], false),\n          ),\n        );\n\n        this.container.addEventListener('keydown', this.handleKeyDown);\n      });\n    }\n\n    componentWillUnmount() {\n      if (this.helper && this.helper.parentNode) {\n        this.helper.parentNode.removeChild(this.helper);\n      }\n      if (!this.container) {\n        return;\n      }\n\n      Object.keys(this.events).forEach((key) =>\n        events[key].forEach((eventName) =>\n          this.container.removeEventListener(eventName, this.events[key]),\n        ),\n      );\n      this.container.removeEventListener('keydown', this.handleKeyDown);\n    }\n\n    handleStart = (event) => {\n      const {distance, shouldCancelStart} = this.props;\n\n      if (event.button === 2 || shouldCancelStart(event)) {\n        return;\n      }\n\n      this.touched = true;\n      this.position = getPosition(event);\n\n      const node = closest(event.target, (el) => el.sortableInfo != null);\n\n      if (\n        node &&\n        node.sortableInfo &&\n        this.nodeIsChild(node) &&\n        !this.state.sorting\n      ) {\n        const {useDragHandle} = this.props;\n        const {index, collection, disabled} = node.sortableInfo;\n\n        if (disabled) {\n          return;\n        }\n\n        if (useDragHandle && !closest(event.target, isSortableHandle)) {\n          return;\n        }\n\n        this.manager.active = {collection, index};\n\n        /*\n         * Fixes a bug in Firefox where the :active state of anchor tags\n         * prevent subsequent 'mousemove' events from being fired\n         * (see https://github.com/clauderic/react-sortable-hoc/issues/118)\n         */\n        if (!isTouchEvent(event) && event.target.tagName === NodeType.Anchor) {\n          event.preventDefault();\n        }\n\n        if (!distance) {\n          if (this.props.pressDelay === 0) {\n            this.handlePress(event);\n          } else {\n            this.pressTimer = setTimeout(\n              () => this.handlePress(event),\n              this.props.pressDelay,\n            );\n          }\n        }\n      }\n    };\n\n    nodeIsChild = (node) => {\n      return node.sortableInfo.manager === this.manager;\n    };\n\n    handleMove = (event) => {\n      const {distance, pressThreshold} = this.props;\n\n      if (\n        !this.state.sorting &&\n        this.touched &&\n        !this._awaitingUpdateBeforeSortStart\n      ) {\n        const position = getPosition(event);\n        const delta = {\n          x: this.position.x - position.x,\n          y: this.position.y - position.y,\n        };\n        const combinedDelta = Math.abs(delta.x) + Math.abs(delta.y);\n\n        this.delta = delta;\n\n        if (!distance && (!pressThreshold || combinedDelta >= pressThreshold)) {\n          clearTimeout(this.cancelTimer);\n          this.cancelTimer = setTimeout(this.cancel, 0);\n        } else if (\n          distance &&\n          combinedDelta >= distance &&\n          this.manager.isActive()\n        ) {\n          this.handlePress(event);\n        }\n      }\n    };\n\n    handleEnd = () => {\n      this.touched = false;\n      this.cancel();\n    };\n\n    cancel = () => {\n      const {distance} = this.props;\n      const {sorting} = this.state;\n\n      if (!sorting) {\n        if (!distance) {\n          clearTimeout(this.pressTimer);\n        }\n        this.manager.active = null;\n      }\n    };\n\n    handlePress = async (event) => {\n      const active = this.manager.getActive();\n\n      if (active) {\n        const {\n          axis,\n          getHelperDimensions,\n          helperClass,\n          hideSortableGhost,\n          updateBeforeSortStart,\n          onSortStart,\n          useWindowAsScrollContainer,\n        } = this.props;\n        const {node, collection} = active;\n        const {isKeySorting} = this.manager;\n\n        if (typeof updateBeforeSortStart === 'function') {\n          this._awaitingUpdateBeforeSortStart = true;\n\n          try {\n            const {index} = node.sortableInfo;\n            await updateBeforeSortStart(\n              {collection, index, node, isKeySorting},\n              event,\n            );\n          } finally {\n            this._awaitingUpdateBeforeSortStart = false;\n          }\n        }\n\n        // Need to get the latest value for `index` in case it changes during `updateBeforeSortStart`\n        const {index} = node.sortableInfo;\n        const margin = getElementMargin(node);\n        const gridGap = getContainerGridGap(this.container);\n        const containerBoundingRect = this.scrollContainer.getBoundingClientRect();\n        const dimensions = getHelperDimensions({index, node, collection});\n\n        this.node = node;\n        this.margin = margin;\n        this.gridGap = gridGap;\n        this.width = dimensions.width;\n        this.height = dimensions.height;\n        this.marginOffset = {\n          x: this.margin.left + this.margin.right + this.gridGap.x,\n          y: Math.max(this.margin.top, this.margin.bottom, this.gridGap.y),\n        };\n        this.boundingClientRect = node.getBoundingClientRect();\n        this.containerBoundingRect = containerBoundingRect;\n        this.index = index;\n        this.newIndex = index;\n\n        this.axis = {\n          x: axis.indexOf('x') >= 0,\n          y: axis.indexOf('y') >= 0,\n        };\n        this.offsetEdge = getEdgeOffset(node, this.container);\n\n        if (isKeySorting) {\n          this.initialOffset = getPosition({\n            ...event,\n            pageX: this.boundingClientRect.left,\n            pageY: this.boundingClientRect.top,\n          });\n        } else {\n          this.initialOffset = getPosition(event);\n        }\n\n        this.initialScroll = {\n          left: this.scrollContainer.scrollLeft,\n          top: this.scrollContainer.scrollTop,\n        };\n\n        this.initialWindowScroll = {\n          left: window.pageXOffset,\n          top: window.pageYOffset,\n        };\n\n        this.helper = this.helperContainer.appendChild(cloneNode(node));\n\n        setInlineStyles(this.helper, {\n          boxSizing: 'border-box',\n          height: `${this.height}px`,\n          left: `${this.boundingClientRect.left - margin.left}px`,\n          pointerEvents: 'none',\n          position: 'fixed',\n          top: `${this.boundingClientRect.top - margin.top}px`,\n          width: `${this.width}px`,\n        });\n\n        if (isKeySorting) {\n          this.helper.focus();\n        }\n\n        if (hideSortableGhost) {\n          this.sortableGhost = node;\n\n          setInlineStyles(node, {\n            opacity: 0,\n            visibility: 'hidden',\n          });\n        }\n\n        this.minTranslate = {};\n        this.maxTranslate = {};\n\n        if (isKeySorting) {\n          const {\n            top: containerTop,\n            left: containerLeft,\n            width: containerWidth,\n            height: containerHeight,\n          } = useWindowAsScrollContainer\n            ? {\n                top: 0,\n                left: 0,\n                width: this.contentWindow.innerWidth,\n                height: this.contentWindow.innerHeight,\n              }\n            : this.containerBoundingRect;\n          const containerBottom = containerTop + containerHeight;\n          const containerRight = containerLeft + containerWidth;\n\n          if (this.axis.x) {\n            this.minTranslate.x = containerLeft - this.boundingClientRect.left;\n            this.maxTranslate.x =\n              containerRight - (this.boundingClientRect.left + this.width);\n          }\n\n          if (this.axis.y) {\n            this.minTranslate.y = containerTop - this.boundingClientRect.top;\n            this.maxTranslate.y =\n              containerBottom - (this.boundingClientRect.top + this.height);\n          }\n        } else {\n          if (this.axis.x) {\n            this.minTranslate.x =\n              (useWindowAsScrollContainer ? 0 : containerBoundingRect.left) -\n              this.boundingClientRect.left -\n              this.width / 2;\n            this.maxTranslate.x =\n              (useWindowAsScrollContainer\n                ? this.contentWindow.innerWidth\n                : containerBoundingRect.left + containerBoundingRect.width) -\n              this.boundingClientRect.left -\n              this.width / 2;\n          }\n\n          if (this.axis.y) {\n            this.minTranslate.y =\n              (useWindowAsScrollContainer ? 0 : containerBoundingRect.top) -\n              this.boundingClientRect.top -\n              this.height / 2;\n            this.maxTranslate.y =\n              (useWindowAsScrollContainer\n                ? this.contentWindow.innerHeight\n                : containerBoundingRect.top + containerBoundingRect.height) -\n              this.boundingClientRect.top -\n              this.height / 2;\n          }\n        }\n\n        if (helperClass) {\n          helperClass\n            .split(' ')\n            .forEach((className) => this.helper.classList.add(className));\n        }\n\n        this.listenerNode = event.touches ? event.target : this.contentWindow;\n\n        if (isKeySorting) {\n          this.listenerNode.addEventListener('wheel', this.handleKeyEnd, true);\n          this.listenerNode.addEventListener(\n            'mousedown',\n            this.handleKeyEnd,\n            true,\n          );\n          this.listenerNode.addEventListener('keydown', this.handleKeyDown);\n        } else {\n          events.move.forEach((eventName) =>\n            this.listenerNode.addEventListener(\n              eventName,\n              this.handleSortMove,\n              false,\n            ),\n          );\n          events.end.forEach((eventName) =>\n            this.listenerNode.addEventListener(\n              eventName,\n              this.handleSortEnd,\n              false,\n            ),\n          );\n        }\n\n        this.setState({\n          sorting: true,\n          sortingIndex: index,\n        });\n\n        if (onSortStart) {\n          onSortStart(\n            {\n              node,\n              index,\n              collection,\n              isKeySorting,\n              nodes: this.manager.getOrderedRefs(),\n              helper: this.helper,\n            },\n            event,\n          );\n        }\n\n        if (isKeySorting) {\n          // Readjust positioning in case re-rendering occurs onSortStart\n          this.keyMove(0);\n        }\n      }\n    };\n\n    handleSortMove = (event) => {\n      const {onSortMove} = this.props;\n\n      // Prevent scrolling on mobile\n      if (typeof event.preventDefault === 'function' && event.cancelable) {\n        event.preventDefault();\n      }\n\n      this.updateHelperPosition(event);\n      this.animateNodes();\n      this.autoscroll();\n\n      if (onSortMove) {\n        onSortMove(event);\n      }\n    };\n\n    handleSortEnd = (event) => {\n      const {hideSortableGhost, onSortEnd} = this.props;\n      const {\n        active: {collection},\n        isKeySorting,\n      } = this.manager;\n      const nodes = this.manager.getOrderedRefs();\n\n      // Remove the event listeners if the node is still in the DOM\n      if (this.listenerNode) {\n        if (isKeySorting) {\n          this.listenerNode.removeEventListener(\n            'wheel',\n            this.handleKeyEnd,\n            true,\n          );\n          this.listenerNode.removeEventListener(\n            'mousedown',\n            this.handleKeyEnd,\n            true,\n          );\n          this.listenerNode.removeEventListener('keydown', this.handleKeyDown);\n        } else {\n          events.move.forEach((eventName) =>\n            this.listenerNode.removeEventListener(\n              eventName,\n              this.handleSortMove,\n            ),\n          );\n          events.end.forEach((eventName) =>\n            this.listenerNode.removeEventListener(\n              eventName,\n              this.handleSortEnd,\n            ),\n          );\n        }\n      }\n\n      // Remove the helper from the DOM\n      this.helper.parentNode.removeChild(this.helper);\n\n      if (hideSortableGhost && this.sortableGhost) {\n        setInlineStyles(this.sortableGhost, {\n          opacity: '',\n          visibility: '',\n        });\n      }\n\n      for (let i = 0, len = nodes.length; i < len; i++) {\n        const node = nodes[i];\n        const el = node.node;\n\n        // Clear the cached offset/boundingClientRect\n        node.edgeOffset = null;\n        node.boundingClientRect = null;\n\n        // Remove the transforms / transitions\n        setTranslate3d(el, null);\n        setTransitionDuration(el, null);\n        node.translate = null;\n      }\n\n      // Stop autoscroll\n      this.autoScroller.clear();\n\n      // Update manager state\n      this.manager.active = null;\n      this.manager.isKeySorting = false;\n\n      this.setState({\n        sorting: false,\n        sortingIndex: null,\n      });\n\n      if (typeof onSortEnd === 'function') {\n        onSortEnd(\n          {\n            collection,\n            newIndex: this.newIndex,\n            oldIndex: this.index,\n            isKeySorting,\n            nodes,\n          },\n          event,\n        );\n      }\n\n      this.touched = false;\n    };\n\n    updateHelperPosition(event) {\n      const {\n        lockAxis,\n        lockOffset,\n        lockToContainerEdges,\n        transitionDuration,\n        keyboardSortingTransitionDuration = transitionDuration,\n      } = this.props;\n      const {isKeySorting} = this.manager;\n      const {ignoreTransition} = event;\n\n      const offset = getPosition(event);\n      const translate = {\n        x: offset.x - this.initialOffset.x,\n        y: offset.y - this.initialOffset.y,\n      };\n\n      // Adjust for window scroll\n      translate.y -= window.pageYOffset - this.initialWindowScroll.top;\n      translate.x -= window.pageXOffset - this.initialWindowScroll.left;\n\n      this.translate = translate;\n\n      if (lockToContainerEdges) {\n        const [minLockOffset, maxLockOffset] = getLockPixelOffsets({\n          height: this.height,\n          lockOffset,\n          width: this.width,\n        });\n        const minOffset = {\n          x: this.width / 2 - minLockOffset.x,\n          y: this.height / 2 - minLockOffset.y,\n        };\n        const maxOffset = {\n          x: this.width / 2 - maxLockOffset.x,\n          y: this.height / 2 - maxLockOffset.y,\n        };\n\n        translate.x = limit(\n          this.minTranslate.x + minOffset.x,\n          this.maxTranslate.x - maxOffset.x,\n          translate.x,\n        );\n        translate.y = limit(\n          this.minTranslate.y + minOffset.y,\n          this.maxTranslate.y - maxOffset.y,\n          translate.y,\n        );\n      }\n\n      if (lockAxis === 'x') {\n        translate.y = 0;\n      } else if (lockAxis === 'y') {\n        translate.x = 0;\n      }\n\n      if (\n        isKeySorting &&\n        keyboardSortingTransitionDuration &&\n        !ignoreTransition\n      ) {\n        setTransitionDuration(this.helper, keyboardSortingTransitionDuration);\n      }\n\n      setTranslate3d(this.helper, translate);\n    }\n\n    animateNodes() {\n      const {transitionDuration, hideSortableGhost, onSortOver} = this.props;\n      const {containerScrollDelta, windowScrollDelta} = this;\n      const nodes = this.manager.getOrderedRefs();\n      const sortingOffset = {\n        left:\n          this.offsetEdge.left + this.translate.x + containerScrollDelta.left,\n        top: this.offsetEdge.top + this.translate.y + containerScrollDelta.top,\n      };\n      const {isKeySorting} = this.manager;\n\n      const prevIndex = this.newIndex;\n      this.newIndex = null;\n\n      for (let i = 0, len = nodes.length; i < len; i++) {\n        const {node} = nodes[i];\n        const {index} = node.sortableInfo;\n        const width = node.offsetWidth;\n        const height = node.offsetHeight;\n        const offset = {\n          height: this.height > height ? height / 2 : this.height / 2,\n          width: this.width > width ? width / 2 : this.width / 2,\n        };\n\n        // For keyboard sorting, we want user input to dictate the position of the nodes\n        const mustShiftBackward =\n          isKeySorting && (index > this.index && index <= prevIndex);\n        const mustShiftForward =\n          isKeySorting && (index < this.index && index >= prevIndex);\n\n        const translate = {\n          x: 0,\n          y: 0,\n        };\n        let {edgeOffset} = nodes[i];\n\n        // If we haven't cached the node's offsetTop / offsetLeft value\n        if (!edgeOffset) {\n          edgeOffset = getEdgeOffset(node, this.container);\n          nodes[i].edgeOffset = edgeOffset;\n          // While we're at it, cache the boundingClientRect, used during keyboard sorting\n          if (isKeySorting) {\n            nodes[i].boundingClientRect = getScrollAdjustedBoundingClientRect(\n              node,\n              containerScrollDelta,\n            );\n          }\n        }\n\n        // Get a reference to the next and previous node\n        const nextNode = i < nodes.length - 1 && nodes[i + 1];\n        const prevNode = i > 0 && nodes[i - 1];\n\n        // Also cache the next node's edge offset if needed.\n        // We need this for calculating the animation in a grid setup\n        if (nextNode && !nextNode.edgeOffset) {\n          nextNode.edgeOffset = getEdgeOffset(nextNode.node, this.container);\n          if (isKeySorting) {\n            nextNode.boundingClientRect = getScrollAdjustedBoundingClientRect(\n              nextNode.node,\n              containerScrollDelta,\n            );\n          }\n        }\n\n        // If the node is the one we're currently animating, skip it\n        if (index === this.index) {\n          if (hideSortableGhost) {\n            /*\n             * With windowing libraries such as `react-virtualized`, the sortableGhost\n             * node may change while scrolling down and then back up (or vice-versa),\n             * so we need to update the reference to the new node just to be safe.\n             */\n            this.sortableGhost = node;\n\n            setInlineStyles(node, {\n              opacity: 0,\n              visibility: 'hidden',\n            });\n          }\n          continue;\n        }\n\n        if (transitionDuration) {\n          setTransitionDuration(node, transitionDuration);\n        }\n\n        if (this.axis.x) {\n          if (this.axis.y) {\n            // Calculations for a grid setup\n            if (\n              mustShiftForward ||\n              (index < this.index &&\n                ((sortingOffset.left + windowScrollDelta.left - offset.width <=\n                  edgeOffset.left &&\n                  sortingOffset.top + windowScrollDelta.top <=\n                    edgeOffset.top + offset.height) ||\n                  sortingOffset.top + windowScrollDelta.top + offset.height <=\n                    edgeOffset.top))\n            ) {\n              // If the current node is to the left on the same row, or above the node that's being dragged\n              // then move it to the right\n              translate.x = this.width + this.marginOffset.x;\n              if (\n                edgeOffset.left + translate.x >\n                this.containerBoundingRect.width - offset.width * 2\n              ) {\n                // If it moves passed the right bounds, then animate it to the first position of the next row.\n                // We just use the offset of the next node to calculate where to move, because that node's original position\n                // is exactly where we want to go\n                if (nextNode) {\n                  translate.x = nextNode.edgeOffset.left - edgeOffset.left;\n                  translate.y = nextNode.edgeOffset.top - edgeOffset.top;\n                }\n              }\n              if (this.newIndex === null) {\n                this.newIndex = index;\n              }\n            } else if (\n              mustShiftBackward ||\n              (index > this.index &&\n                ((sortingOffset.left + windowScrollDelta.left + offset.width >=\n                  edgeOffset.left &&\n                  sortingOffset.top + windowScrollDelta.top + offset.height >=\n                    edgeOffset.top) ||\n                  sortingOffset.top + windowScrollDelta.top + offset.height >=\n                    edgeOffset.top + height))\n            ) {\n              // If the current node is to the right on the same row, or below the node that's being dragged\n              // then move it to the left\n              translate.x = -(this.width + this.marginOffset.x);\n              if (\n                edgeOffset.left + translate.x <\n                this.containerBoundingRect.left + offset.width\n              ) {\n                // If it moves passed the left bounds, then animate it to the last position of the previous row.\n                // We just use the offset of the previous node to calculate where to move, because that node's original position\n                // is exactly where we want to go\n                if (prevNode) {\n                  translate.x = prevNode.edgeOffset.left - edgeOffset.left;\n                  translate.y = prevNode.edgeOffset.top - edgeOffset.top;\n                }\n              }\n              this.newIndex = index;\n            }\n          } else {\n            if (\n              mustShiftBackward ||\n              (index > this.index &&\n                sortingOffset.left + windowScrollDelta.left + offset.width >=\n                  edgeOffset.left)\n            ) {\n              translate.x = -(this.width + this.marginOffset.x);\n              this.newIndex = index;\n            } else if (\n              mustShiftForward ||\n              (index < this.index &&\n                sortingOffset.left + windowScrollDelta.left <=\n                  edgeOffset.left + offset.width)\n            ) {\n              translate.x = this.width + this.marginOffset.x;\n\n              if (this.newIndex == null) {\n                this.newIndex = index;\n              }\n            }\n          }\n        } else if (this.axis.y) {\n          if (\n            mustShiftBackward ||\n            (index > this.index &&\n              sortingOffset.top + windowScrollDelta.top + offset.height >=\n                edgeOffset.top)\n          ) {\n            translate.y = -(this.height + this.marginOffset.y);\n            this.newIndex = index;\n          } else if (\n            mustShiftForward ||\n            (index < this.index &&\n              sortingOffset.top + windowScrollDelta.top <=\n                edgeOffset.top + offset.height)\n          ) {\n            translate.y = this.height + this.marginOffset.y;\n            if (this.newIndex == null) {\n              this.newIndex = index;\n            }\n          }\n        }\n\n        setTranslate3d(node, translate);\n        nodes[i].translate = translate;\n      }\n\n      if (this.newIndex == null) {\n        this.newIndex = this.index;\n      }\n\n      if (isKeySorting) {\n        // If keyboard sorting, we want the user input to dictate index, not location of the helper\n        this.newIndex = prevIndex;\n      }\n\n      const oldIndex = isKeySorting ? this.prevIndex : prevIndex;\n      if (onSortOver && this.newIndex !== oldIndex) {\n        onSortOver({\n          collection: this.manager.active.collection,\n          index: this.index,\n          newIndex: this.newIndex,\n          oldIndex,\n          isKeySorting,\n          nodes,\n          helper: this.helper,\n        });\n      }\n    }\n\n    autoscroll = () => {\n      const {disableAutoscroll} = this.props;\n      const {isKeySorting} = this.manager;\n\n      if (disableAutoscroll) {\n        this.autoScroller.clear();\n        return;\n      }\n\n      if (isKeySorting) {\n        const translate = {...this.translate};\n        let scrollX = 0;\n        let scrollY = 0;\n\n        if (this.axis.x) {\n          translate.x = Math.min(\n            this.maxTranslate.x,\n            Math.max(this.minTranslate.x, this.translate.x),\n          );\n          scrollX = this.translate.x - translate.x;\n        }\n\n        if (this.axis.y) {\n          translate.y = Math.min(\n            this.maxTranslate.y,\n            Math.max(this.minTranslate.y, this.translate.y),\n          );\n          scrollY = this.translate.y - translate.y;\n        }\n\n        this.translate = translate;\n        setTranslate3d(this.helper, this.translate);\n        this.scrollContainer.scrollLeft += scrollX;\n        this.scrollContainer.scrollTop += scrollY;\n\n        return;\n      }\n\n      this.autoScroller.update({\n        height: this.height,\n        maxTranslate: this.maxTranslate,\n        minTranslate: this.minTranslate,\n        translate: this.translate,\n        width: this.width,\n      });\n    };\n\n    onAutoScroll = (offset) => {\n      this.translate.x += offset.left;\n      this.translate.y += offset.top;\n\n      this.animateNodes();\n    };\n\n    getWrappedInstance() {\n      invariant(\n        config.withRef,\n        'To access the wrapped instance, you need to pass in {withRef: true} as the second argument of the SortableContainer() call',\n      );\n\n      return this.wrappedInstance.current;\n    }\n\n    getContainer() {\n      const {getContainer} = this.props;\n\n      if (typeof getContainer !== 'function') {\n        return findDOMNode(this);\n      }\n\n      return getContainer(\n        config.withRef ? this.getWrappedInstance() : undefined,\n      );\n    }\n\n    handleKeyDown = (event) => {\n      const {keyCode} = event;\n      const {shouldCancelStart, keyCodes: customKeyCodes = {}} = this.props;\n\n      const keyCodes = {\n        ...defaultKeyCodes,\n        ...customKeyCodes,\n      };\n\n      if (\n        (this.manager.active && !this.manager.isKeySorting) ||\n        (!this.manager.active &&\n          (!keyCodes.lift.includes(keyCode) ||\n            shouldCancelStart(event) ||\n            !this.isValidSortingTarget(event)))\n      ) {\n        return;\n      }\n\n      event.stopPropagation();\n      event.preventDefault();\n\n      if (keyCodes.lift.includes(keyCode) && !this.manager.active) {\n        this.keyLift(event);\n      } else if (keyCodes.drop.includes(keyCode) && this.manager.active) {\n        this.keyDrop(event);\n      } else if (keyCodes.cancel.includes(keyCode)) {\n        this.newIndex = this.manager.active.index;\n        this.keyDrop(event);\n      } else if (keyCodes.up.includes(keyCode)) {\n        this.keyMove(-1);\n      } else if (keyCodes.down.includes(keyCode)) {\n        this.keyMove(1);\n      }\n    };\n\n    keyLift = (event) => {\n      const {target} = event;\n      const node = closest(target, (el) => el.sortableInfo != null);\n      const {index, collection} = node.sortableInfo;\n\n      this.initialFocusedNode = target;\n\n      this.manager.isKeySorting = true;\n      this.manager.active = {\n        index,\n        collection,\n      };\n\n      this.handlePress(event);\n    };\n\n    keyMove = (shift) => {\n      const nodes = this.manager.getOrderedRefs();\n      const {index: lastIndex} = nodes[nodes.length - 1].node.sortableInfo;\n      const newIndex = this.newIndex + shift;\n      const prevIndex = this.newIndex;\n\n      if (newIndex < 0 || newIndex > lastIndex) {\n        return;\n      }\n\n      this.prevIndex = prevIndex;\n      this.newIndex = newIndex;\n\n      const targetIndex = getTargetIndex(\n        this.newIndex,\n        this.prevIndex,\n        this.index,\n      );\n      const target = nodes.find(\n        ({node}) => node.sortableInfo.index === targetIndex,\n      );\n      const {node: targetNode} = target;\n\n      const scrollDelta = this.containerScrollDelta;\n      const targetBoundingClientRect =\n        target.boundingClientRect ||\n        getScrollAdjustedBoundingClientRect(targetNode, scrollDelta);\n      const targetTranslate = target.translate || {x: 0, y: 0};\n\n      const targetPosition = {\n        top: targetBoundingClientRect.top + targetTranslate.y - scrollDelta.top,\n        left:\n          targetBoundingClientRect.left + targetTranslate.x - scrollDelta.left,\n      };\n\n      const shouldAdjustForSize = prevIndex < newIndex;\n      const sizeAdjustment = {\n        x:\n          shouldAdjustForSize && this.axis.x\n            ? targetNode.offsetWidth - this.width\n            : 0,\n        y:\n          shouldAdjustForSize && this.axis.y\n            ? targetNode.offsetHeight - this.height\n            : 0,\n      };\n\n      this.handleSortMove({\n        pageX: targetPosition.left + sizeAdjustment.x,\n        pageY: targetPosition.top + sizeAdjustment.y,\n        ignoreTransition: shift === 0,\n      });\n    };\n\n    keyDrop = (event) => {\n      this.handleSortEnd(event);\n\n      if (this.initialFocusedNode) {\n        this.initialFocusedNode.focus();\n      }\n    };\n\n    handleKeyEnd = (event) => {\n      if (this.manager.active) {\n        this.keyDrop(event);\n      }\n    };\n\n    isValidSortingTarget = (event) => {\n      const {useDragHandle} = this.props;\n      const {target} = event;\n      const node = closest(target, (el) => el.sortableInfo != null);\n\n      return (\n        node &&\n        node.sortableInfo &&\n        !node.sortableInfo.disabled &&\n        (useDragHandle ? isSortableHandle(target) : target.sortableInfo)\n      );\n    };\n\n    render() {\n      const ref = config.withRef ? this.wrappedInstance : null;\n\n      return (\n        <SortableContext.Provider value={this.sortableContextValue}>\n          <WrappedComponent ref={ref} {...omit(this.props, omittedProps)} />\n        </SortableContext.Provider>\n      );\n    }\n\n    get helperContainer() {\n      const {helperContainer} = this.props;\n\n      if (typeof helperContainer === 'function') {\n        return helperContainer();\n      }\n\n      return this.props.helperContainer || this.document.body;\n    }\n\n    get containerScrollDelta() {\n      const {useWindowAsScrollContainer} = this.props;\n\n      if (useWindowAsScrollContainer) {\n        return {left: 0, top: 0};\n      }\n\n      return {\n        left: this.scrollContainer.scrollLeft - this.initialScroll.left,\n        top: this.scrollContainer.scrollTop - this.initialScroll.top,\n      };\n    }\n\n    get windowScrollDelta() {\n      return {\n        left: this.contentWindow.pageXOffset - this.initialWindowScroll.left,\n        top: this.contentWindow.pageYOffset - this.initialWindowScroll.top,\n      };\n    }\n  };\n}\n"
  },
  {
    "path": "src/SortableContainer/props.js",
    "content": "import PropTypes from 'prop-types';\nimport invariant from 'invariant';\n\nimport {KEYCODE} from '../utils';\nimport defaultGetHelperDimensions from './defaultGetHelperDimensions';\nimport defaultShouldCancelStart from './defaultShouldCancelStart';\n\nexport const propTypes = {\n  axis: PropTypes.oneOf(['x', 'y', 'xy']),\n  contentWindow: PropTypes.any,\n  disableAutoscroll: PropTypes.bool,\n  distance: PropTypes.number,\n  getContainer: PropTypes.func,\n  getHelperDimensions: PropTypes.func,\n  helperClass: PropTypes.string,\n  helperContainer: PropTypes.oneOfType([\n    PropTypes.func,\n    typeof HTMLElement === 'undefined'\n      ? PropTypes.any\n      : PropTypes.instanceOf(HTMLElement),\n  ]),\n  hideSortableGhost: PropTypes.bool,\n  keyboardSortingTransitionDuration: PropTypes.number,\n  lockAxis: PropTypes.string,\n  lockOffset: PropTypes.oneOfType([\n    PropTypes.number,\n    PropTypes.string,\n    PropTypes.arrayOf(\n      PropTypes.oneOfType([PropTypes.number, PropTypes.string]),\n    ),\n  ]),\n  lockToContainerEdges: PropTypes.bool,\n  onSortEnd: PropTypes.func,\n  onSortMove: PropTypes.func,\n  onSortOver: PropTypes.func,\n  onSortStart: PropTypes.func,\n  pressDelay: PropTypes.number,\n  pressThreshold: PropTypes.number,\n  keyCodes: PropTypes.shape({\n    lift: PropTypes.arrayOf(PropTypes.number),\n    drop: PropTypes.arrayOf(PropTypes.number),\n    cancel: PropTypes.arrayOf(PropTypes.number),\n    up: PropTypes.arrayOf(PropTypes.number),\n    down: PropTypes.arrayOf(PropTypes.number),\n  }),\n  shouldCancelStart: PropTypes.func,\n  transitionDuration: PropTypes.number,\n  updateBeforeSortStart: PropTypes.func,\n  useDragHandle: PropTypes.bool,\n  useWindowAsScrollContainer: PropTypes.bool,\n};\n\nexport const defaultKeyCodes = {\n  lift: [KEYCODE.SPACE],\n  drop: [KEYCODE.SPACE],\n  cancel: [KEYCODE.ESC],\n  up: [KEYCODE.UP, KEYCODE.LEFT],\n  down: [KEYCODE.DOWN, KEYCODE.RIGHT],\n};\n\nexport const defaultProps = {\n  axis: 'y',\n  disableAutoscroll: false,\n  distance: 0,\n  getHelperDimensions: defaultGetHelperDimensions,\n  hideSortableGhost: true,\n  lockOffset: '50%',\n  lockToContainerEdges: false,\n  pressDelay: 0,\n  pressThreshold: 5,\n  keyCodes: defaultKeyCodes,\n  shouldCancelStart: defaultShouldCancelStart,\n  transitionDuration: 300,\n  useWindowAsScrollContainer: false,\n};\n\nexport const omittedProps = Object.keys(propTypes);\n\nexport function validateProps(props) {\n  invariant(\n    !(props.distance && props.pressDelay),\n    'Attempted to set both `pressDelay` and `distance` on SortableContainer, you may only use one or the other, not both at the same time.',\n  );\n}\n"
  },
  {
    "path": "src/SortableElement/index.js",
    "content": "import * as React from 'react';\nimport PropTypes from 'prop-types';\nimport {findDOMNode} from 'react-dom';\nimport invariant from 'invariant';\nimport {SortableContext} from '../SortableContainer';\n\nimport {provideDisplayName, omit} from '../utils';\n\nconst propTypes = {\n  index: PropTypes.number.isRequired,\n  collection: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),\n  disabled: PropTypes.bool,\n};\n\nconst omittedProps = Object.keys(propTypes);\n\nexport default function sortableElement(\n  WrappedComponent,\n  config = {withRef: false},\n) {\n  return class WithSortableElement extends React.Component {\n    static displayName = provideDisplayName(\n      'sortableElement',\n      WrappedComponent,\n    );\n\n    static contextType = SortableContext;\n\n    static propTypes = propTypes;\n\n    static defaultProps = {\n      collection: 0,\n    };\n\n    componentDidMount() {\n      this.register();\n    }\n\n    componentDidUpdate(prevProps) {\n      if (this.node) {\n        if (prevProps.index !== this.props.index) {\n          this.node.sortableInfo.index = this.props.index;\n        }\n\n        if (prevProps.disabled !== this.props.disabled) {\n          this.node.sortableInfo.disabled = this.props.disabled;\n        }\n      }\n\n      if (prevProps.collection !== this.props.collection) {\n        this.unregister(prevProps.collection);\n        this.register();\n      }\n    }\n\n    componentWillUnmount() {\n      this.unregister();\n    }\n\n    register() {\n      const {collection, disabled, index} = this.props;\n      const node = findDOMNode(this);\n\n      node.sortableInfo = {\n        collection,\n        disabled,\n        index,\n        manager: this.context.manager,\n      };\n\n      this.node = node;\n      this.ref = {node};\n\n      this.context.manager.add(collection, this.ref);\n    }\n\n    unregister(collection = this.props.collection) {\n      this.context.manager.remove(collection, this.ref);\n    }\n\n    getWrappedInstance() {\n      invariant(\n        config.withRef,\n        'To access the wrapped instance, you need to pass in {withRef: true} as the second argument of the SortableElement() call',\n      );\n      return this.wrappedInstance.current;\n    }\n\n    wrappedInstance = React.createRef();\n\n    render() {\n      const ref = config.withRef ? this.wrappedInstance : null;\n\n      return <WrappedComponent ref={ref} {...omit(this.props, omittedProps)} />;\n    }\n  };\n}\n"
  },
  {
    "path": "src/SortableHandle/index.js",
    "content": "import * as React from 'react';\nimport {findDOMNode} from 'react-dom';\nimport invariant from 'invariant';\n\nimport {provideDisplayName} from '../utils';\n\nexport default function sortableHandle(\n  WrappedComponent,\n  config = {withRef: false},\n) {\n  return class WithSortableHandle extends React.Component {\n    static displayName = provideDisplayName('sortableHandle', WrappedComponent);\n\n    componentDidMount() {\n      const node = findDOMNode(this);\n      node.sortableHandle = true;\n    }\n\n    getWrappedInstance() {\n      invariant(\n        config.withRef,\n        'To access the wrapped instance, you need to pass in {withRef: true} as the second argument of the SortableHandle() call',\n      );\n      return this.wrappedInstance.current;\n    }\n\n    wrappedInstance = React.createRef();\n\n    render() {\n      const ref = config.withRef ? this.wrappedInstance : null;\n\n      return <WrappedComponent ref={ref} {...this.props} />;\n    }\n  };\n}\n\nexport function isSortableHandle(node) {\n  return node.sortableHandle != null;\n}\n"
  },
  {
    "path": "src/index.js",
    "content": "export {default as SortableContainer} from './SortableContainer';\nexport {default as SortableElement} from './SortableElement';\nexport {default as SortableHandle} from './SortableHandle';\n\nexport {default as sortableContainer} from './SortableContainer';\nexport {default as sortableElement} from './SortableElement';\nexport {default as sortableHandle} from './SortableHandle';\n\nexport {arrayMove} from './utils';\n"
  },
  {
    "path": "src/utils.js",
    "content": "/* global process */\nimport invariant from 'invariant';\n\nexport function arrayMove(array, from, to) {\n  // Will be deprecated soon. Consumers should install 'array-move' instead\n  // https://www.npmjs.com/package/array-move\n\n  if (process.env.NODE_ENV !== 'production') {\n    if (typeof console !== 'undefined') {\n      // eslint-disable-next-line no-console\n      console.warn(\n        \"Deprecation warning: arrayMove will no longer be exported by 'react-sortable-hoc' in the next major release. Please install the `array-move` package locally instead. https://www.npmjs.com/package/array-move\",\n      );\n    }\n  }\n\n  array = array.slice();\n  array.splice(to < 0 ? array.length + to : to, 0, array.splice(from, 1)[0]);\n\n  return array;\n}\n\nexport function omit(obj, keysToOmit) {\n  return Object.keys(obj).reduce((acc, key) => {\n    if (keysToOmit.indexOf(key) === -1) {\n      acc[key] = obj[key];\n    }\n\n    return acc;\n  }, {});\n}\n\nexport const events = {\n  end: ['touchend', 'touchcancel', 'mouseup'],\n  move: ['touchmove', 'mousemove'],\n  start: ['touchstart', 'mousedown'],\n};\n\nexport const vendorPrefix = (function() {\n  if (typeof window === 'undefined' || typeof document === 'undefined') {\n    // Server environment\n    return '';\n  }\n\n  // fix for: https://bugzilla.mozilla.org/show_bug.cgi?id=548397\n  // window.getComputedStyle() returns null inside an iframe with display: none\n  // in this case return an array with a fake mozilla style in it.\n  const styles = window.getComputedStyle(document.documentElement, '') || [\n    '-moz-hidden-iframe',\n  ];\n  const pre = (Array.prototype.slice\n    .call(styles)\n    .join('')\n    .match(/-(moz|webkit|ms)-/) ||\n    (styles.OLink === '' && ['', 'o']))[1];\n\n  switch (pre) {\n    case 'ms':\n      return 'ms';\n    default:\n      return pre && pre.length ? pre[0].toUpperCase() + pre.substr(1) : '';\n  }\n})();\n\nexport function setInlineStyles(node, styles) {\n  Object.keys(styles).forEach((key) => {\n    node.style[key] = styles[key];\n  });\n}\n\nexport function setTranslate3d(node, translate) {\n  node.style[`${vendorPrefix}Transform`] =\n    translate == null ? '' : `translate3d(${translate.x}px,${translate.y}px,0)`;\n}\n\nexport function setTransitionDuration(node, duration) {\n  node.style[`${vendorPrefix}TransitionDuration`] =\n    duration == null ? '' : `${duration}ms`;\n}\n\nexport function closest(el, fn) {\n  while (el) {\n    if (fn(el)) {\n      return el;\n    }\n\n    el = el.parentNode;\n  }\n\n  return null;\n}\n\nexport function limit(min, max, value) {\n  return Math.max(min, Math.min(value, max));\n}\n\nfunction getPixelValue(stringValue) {\n  if (stringValue.substr(-2) === 'px') {\n    return parseFloat(stringValue);\n  }\n\n  return 0;\n}\n\nexport function getElementMargin(element) {\n  const style = window.getComputedStyle(element);\n\n  return {\n    bottom: getPixelValue(style.marginBottom),\n    left: getPixelValue(style.marginLeft),\n    right: getPixelValue(style.marginRight),\n    top: getPixelValue(style.marginTop),\n  };\n}\n\nexport function provideDisplayName(prefix, Component) {\n  const componentName = Component.displayName || Component.name;\n\n  return componentName ? `${prefix}(${componentName})` : prefix;\n}\n\nexport function getScrollAdjustedBoundingClientRect(node, scrollDelta) {\n  const boundingClientRect = node.getBoundingClientRect();\n\n  return {\n    top: boundingClientRect.top + scrollDelta.top,\n    left: boundingClientRect.left + scrollDelta.left,\n  };\n}\n\nexport function getPosition(event) {\n  if (event.touches && event.touches.length) {\n    return {\n      x: event.touches[0].pageX,\n      y: event.touches[0].pageY,\n    };\n  } else if (event.changedTouches && event.changedTouches.length) {\n    return {\n      x: event.changedTouches[0].pageX,\n      y: event.changedTouches[0].pageY,\n    };\n  } else {\n    return {\n      x: event.pageX,\n      y: event.pageY,\n    };\n  }\n}\n\nexport function isTouchEvent(event) {\n  return (\n    (event.touches && event.touches.length) ||\n    (event.changedTouches && event.changedTouches.length)\n  );\n}\n\nexport function getEdgeOffset(node, parent, offset = {left: 0, top: 0}) {\n  if (!node) {\n    return undefined;\n  }\n\n  // Get the actual offsetTop / offsetLeft value, no matter how deep the node is nested\n  const nodeOffset = {\n    left: offset.left + node.offsetLeft,\n    top: offset.top + node.offsetTop,\n  };\n\n  if (node.parentNode === parent) {\n    return nodeOffset;\n  }\n\n  return getEdgeOffset(node.parentNode, parent, nodeOffset);\n}\n\nexport function getTargetIndex(newIndex, prevIndex, oldIndex) {\n  if (newIndex < oldIndex && newIndex > prevIndex) {\n    return newIndex - 1;\n  } else if (newIndex > oldIndex && newIndex < prevIndex) {\n    return newIndex + 1;\n  } else {\n    return newIndex;\n  }\n}\n\nexport function getLockPixelOffset({lockOffset, width, height}) {\n  let offsetX = lockOffset;\n  let offsetY = lockOffset;\n  let unit = 'px';\n\n  if (typeof lockOffset === 'string') {\n    const match = /^[+-]?\\d*(?:\\.\\d*)?(px|%)$/.exec(lockOffset);\n\n    invariant(\n      match !== null,\n      'lockOffset value should be a number or a string of a ' +\n        'number followed by \"px\" or \"%\". Given %s',\n      lockOffset,\n    );\n\n    offsetX = parseFloat(lockOffset);\n    offsetY = parseFloat(lockOffset);\n    unit = match[1];\n  }\n\n  invariant(\n    isFinite(offsetX) && isFinite(offsetY),\n    'lockOffset value should be a finite. Given %s',\n    lockOffset,\n  );\n\n  if (unit === '%') {\n    offsetX = (offsetX * width) / 100;\n    offsetY = (offsetY * height) / 100;\n  }\n\n  return {\n    x: offsetX,\n    y: offsetY,\n  };\n}\n\nexport function getLockPixelOffsets({height, width, lockOffset}) {\n  const offsets = Array.isArray(lockOffset)\n    ? lockOffset\n    : [lockOffset, lockOffset];\n\n  invariant(\n    offsets.length === 2,\n    'lockOffset prop of SortableContainer should be a single ' +\n      'value or an array of exactly two values. Given %s',\n    lockOffset,\n  );\n\n  const [minLockOffset, maxLockOffset] = offsets;\n\n  return [\n    getLockPixelOffset({height, lockOffset: minLockOffset, width}),\n    getLockPixelOffset({height, lockOffset: maxLockOffset, width}),\n  ];\n}\n\nfunction isScrollable(el) {\n  const computedStyle = window.getComputedStyle(el);\n  const overflowRegex = /(auto|scroll)/;\n  const properties = ['overflow', 'overflowX', 'overflowY'];\n\n  return properties.find((property) =>\n    overflowRegex.test(computedStyle[property]),\n  );\n}\n\nexport function getScrollingParent(el) {\n  if (!(el instanceof HTMLElement)) {\n    return null;\n  } else if (isScrollable(el)) {\n    return el;\n  } else {\n    return getScrollingParent(el.parentNode);\n  }\n}\n\nexport function getContainerGridGap(element) {\n  const style = window.getComputedStyle(element);\n\n  if (style.display === 'grid') {\n    return {\n      x: getPixelValue(style.gridColumnGap),\n      y: getPixelValue(style.gridRowGap),\n    };\n  }\n\n  return {x: 0, y: 0};\n}\n\nexport const KEYCODE = {\n  TAB: 9,\n  ESC: 27,\n  SPACE: 32,\n  LEFT: 37,\n  UP: 38,\n  RIGHT: 39,\n  DOWN: 40,\n};\n\nexport const NodeType = {\n  Anchor: 'A',\n  Button: 'BUTTON',\n  Canvas: 'CANVAS',\n  Input: 'INPUT',\n  Option: 'OPTION',\n  Textarea: 'TEXTAREA',\n  Select: 'SELECT',\n};\n\nexport function cloneNode(node) {\n  const selector = 'input, textarea, select, canvas, [contenteditable]';\n  const fields = node.querySelectorAll(selector);\n  const clonedNode = node.cloneNode(true);\n  const clonedFields = [...clonedNode.querySelectorAll(selector)];\n\n  clonedFields.forEach((field, i) => {\n    if (field.type !== 'file') {\n      field.value = fields[i].value;\n    }\n\n    // Fixes an issue with original radio buttons losing their value once the\n    // clone is inserted in the DOM, as radio button `name` attributes must be unique\n    if (field.type === 'radio' && field.name) {\n      field.name = `__sortableClone__${field.name}`;\n    }\n\n    if (\n      field.tagName === NodeType.Canvas &&\n      fields[i].width > 0 &&\n      fields[i].height > 0\n    ) {\n      const destCtx = field.getContext('2d');\n      destCtx.drawImage(fields[i], 0, 0);\n    }\n  });\n\n  return clonedNode;\n}\n"
  },
  {
    "path": "types/index.d.ts",
    "content": "import * as React from 'react';\n\nexport type Axis = 'x' | 'y' | 'xy';\n\nexport type Offset = number | string;\n\nexport interface SortStart {\n  node: Element;\n  index: number;\n  collection: Offset;\n  isKeySorting: boolean;\n  nodes: HTMLElement[];\n  helper: HTMLElement;\n}\n\nexport interface SortOver {\n  index: number;\n  oldIndex: number;\n  newIndex: number;\n  collection: Offset;\n  isKeySorting: boolean;\n  nodes: HTMLElement[];\n  helper: HTMLElement;\n}\n\nexport interface SortEnd {\n  oldIndex: number;\n  newIndex: number;\n  collection: Offset;\n  isKeySorting: boolean;\n  nodes: HTMLElement[];\n}\n\nexport type SortEvent = React.MouseEvent<any> | React.TouchEvent<any>;\n\nexport type SortEventWithTag = SortEvent & {\n  target: {\n    tagName: string;\n  };\n};\n\nexport type SortStartHandler = (sort: SortStart, event: SortEvent) => void;\n\nexport type SortMoveHandler = (event: SortEvent) => void;\n\nexport type SortEndHandler = (sort: SortEnd, event: SortEvent) => void;\n\nexport type SortOverHandler = (sort: SortOver, event: SortEvent) => void;\n\nexport type ContainerGetter = (\n  element: React.ReactElement<any>,\n) => HTMLElement | Promise<HTMLElement>;\n\nexport type HelperContainerGetter = () => HTMLElement;\n\nexport interface Dimensions {\n  width: number;\n  height: number;\n}\n\nexport interface SortableContainerProps {\n  axis?: Axis;\n  lockAxis?: Axis;\n  helperClass?: string;\n  transitionDuration?: number;\n  keyboardSortingTransitionDuration?: number;\n  keyCodes?: {\n    lift?: number[];\n    drop?: number[];\n    cancel?: number[];\n    up?: number[];\n    down?: number[];\n  };\n  pressDelay?: number;\n  pressThreshold?: number;\n  distance?: number;\n  shouldCancelStart?: (event: SortEvent | SortEventWithTag) => boolean;\n  updateBeforeSortStart?: SortStartHandler;\n  onSortStart?: SortStartHandler;\n  onSortMove?: SortMoveHandler;\n  onSortEnd?: SortEndHandler;\n  onSortOver?: SortOverHandler;\n  useDragHandle?: boolean;\n  useWindowAsScrollContainer?: boolean;\n  hideSortableGhost?: boolean;\n  lockToContainerEdges?: boolean;\n  lockOffset?: Offset | [Offset, Offset];\n  getContainer?: ContainerGetter;\n  getHelperDimensions?: (sort: SortStart) => Dimensions;\n  helperContainer?: HTMLElement | HelperContainerGetter;\n  disableAutoscroll?: boolean;\n}\n\nexport interface SortableElementProps {\n  index: number;\n  collection?: Offset;\n  disabled?: boolean;\n}\n\nexport interface Config {\n  withRef: boolean;\n}\n\nexport type WrappedComponentFactory<P> = (props: P) => JSX.Element;\n\nexport type WrappedComponent<P> =\n  | React.ComponentClass<P>\n  | React.SFC<P>\n  | WrappedComponentFactory<P>;\n\nexport function SortableContainer<P>(\n  wrappedComponent: WrappedComponent<P>,\n  config?: Config,\n): React.ComponentClass<P & SortableContainerProps>;\n\nexport function SortableElement<P>(\n  wrappedComponent: WrappedComponent<P>,\n  config?: Config,\n): React.ComponentClass<P & SortableElementProps>;\n\nexport function SortableHandle<P>(\n  wrappedComponent: WrappedComponent<P>,\n  config?: Config,\n): React.ComponentClass<P>;\n\nexport function arrayMove<T>(\n  collection: T[],\n  previousIndex: number,\n  newIndex: number,\n): T[];\n"
  }
]