diff --git a/package-lock.json b/package-lock.json
index 70ce929..805293e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -7320,6 +7320,39 @@
"node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0"
}
},
+ "node_modules/babel-plugin-jsx-dom-expressions": {
+ "version": "0.35.4",
+ "resolved": "https://registry.npmjs.org/babel-plugin-jsx-dom-expressions/-/babel-plugin-jsx-dom-expressions-0.35.4.tgz",
+ "integrity": "sha512-Ab8W+36+XcNpyb644K537MtuhZRssgE3hmZD/08a1Z99Xfnd38tR2BZaDl7yEQvvHrb46N+eje2YjIg4VGAfVQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-module-imports": "7.16.0",
+ "@babel/plugin-syntax-jsx": "^7.16.5",
+ "@babel/types": "^7.16.0",
+ "html-entities": "2.3.2"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/babel-plugin-jsx-dom-expressions/node_modules/@babel/helper-module-imports": {
+ "version": "7.16.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.0.tgz",
+ "integrity": "sha512-kkH7sWzKPq0xt3H1n+ghb4xEMP8k0U7XV3kkB+ZGy69kDk2ySFW1qPi06sjKzFY3t1j6XbJSqr4mF9L7CYVyhg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.16.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/babel-plugin-jsx-dom-expressions/node_modules/html-entities": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.2.tgz",
+ "integrity": "sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==",
+ "dev": true
+ },
"node_modules/babel-plugin-polyfill-corejs2": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.3.tgz",
@@ -7407,6 +7440,18 @@
"@babel/core": "^7.0.0"
}
},
+ "node_modules/babel-preset-solid": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/babel-preset-solid/-/babel-preset-solid-1.6.1.tgz",
+ "integrity": "sha512-Ji/cvYUE2BROsA3zOhaqKjuAEo6YAkmw8ZE11QsMtSEcWJ1rCFC829qWb5FLPl3UymVxh68+dpScPDtyyr/rdA==",
+ "dev": true,
+ "dependencies": {
+ "babel-plugin-jsx-dom-expressions": "^0.35.2"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
"node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
@@ -17636,6 +17681,34 @@
"node": ">= 0.10.0"
}
},
+ "node_modules/merge-anything": {
+ "version": "5.0.4",
+ "resolved": "https://registry.npmjs.org/merge-anything/-/merge-anything-5.0.4.tgz",
+ "integrity": "sha512-YFsDeY5A9SLXhL21Qn15wCWewRUW6wMTxQF4SuPe9bNdr1wsjiE44Rp8FQUTCtwO0WLdlKiFzhAVE5tlf857Tg==",
+ "dev": true,
+ "dependencies": {
+ "is-what": "^4.1.7",
+ "ts-toolbelt": "^9.6.0"
+ },
+ "engines": {
+ "node": ">=12.13"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mesqueeb"
+ }
+ },
+ "node_modules/merge-anything/node_modules/is-what": {
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.7.tgz",
+ "integrity": "sha512-DBVOQNiPKnGMxRMLIYSwERAS5MVY1B7xYiGnpgctsOFvVDz9f9PFXXxMcTOHuoqYp4NK9qFYQaIC1NRRxLMpBQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=12.13"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mesqueeb"
+ }
+ },
"node_modules/merge-descriptors": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
@@ -19278,6 +19351,10 @@
"resolved": "packages/overlayscrollbars-react",
"link": true
},
+ "node_modules/overlayscrollbars-solid": {
+ "resolved": "packages/overlayscrollbars-solid",
+ "link": true
+ },
"node_modules/overlayscrollbars-svelte": {
"resolved": "packages/overlayscrollbars-svelte",
"link": true
@@ -24369,6 +24446,200 @@
}
}
},
+ "node_modules/solid-js": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.6.1.tgz",
+ "integrity": "sha512-i8OmR419Hr0918Or6sm1ET/cgmxTtAB7Bdz/UwhZ7G2THixrvVSO3jd+C7YqMKKfVwmf8PJ2gUSbKE8NKv28GA==",
+ "dev": true,
+ "dependencies": {
+ "csstype": "^3.1.0"
+ }
+ },
+ "node_modules/solid-refresh": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/solid-refresh/-/solid-refresh-0.4.1.tgz",
+ "integrity": "sha512-v3tD/OXQcUyXLrWjPW1dXZyeWwP7/+GQNs8YTL09GBq+5FguA6IejJWUvJDrLIA4M0ho9/5zK2e9n+uy+4488g==",
+ "dev": true,
+ "dependencies": {
+ "@babel/generator": "^7.18.2",
+ "@babel/helper-module-imports": "^7.16.7",
+ "@babel/types": "^7.18.4"
+ },
+ "peerDependencies": {
+ "solid-js": "^1.3"
+ }
+ },
+ "node_modules/solid-testing-library": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/solid-testing-library/-/solid-testing-library-0.5.0.tgz",
+ "integrity": "sha512-vr4Ke9Dq3bUFLaXOcN8/IVn2e9Q37w4vdmoIOmFBIPs7iCJX9IxuC0IdQqK8nzBZMQqceijkfyCE3Qc407KmaA==",
+ "dev": true,
+ "dependencies": {
+ "@testing-library/dom": "^8.19.0"
+ },
+ "engines": {
+ "node": ">= 14"
+ },
+ "peerDependencies": {
+ "solid-js": ">=1.0.0"
+ }
+ },
+ "node_modules/solid-testing-library/node_modules/@testing-library/dom": {
+ "version": "8.19.0",
+ "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.19.0.tgz",
+ "integrity": "sha512-6YWYPPpxG3e/xOo6HIWwB/58HukkwIVTOaZ0VwdMVjhRUX/01E4FtQbck9GazOOj7MXHc5RBzMrU86iBJHbI+A==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/runtime": "^7.12.5",
+ "@types/aria-query": "^4.2.0",
+ "aria-query": "^5.0.0",
+ "chalk": "^4.1.0",
+ "dom-accessibility-api": "^0.5.9",
+ "lz-string": "^1.4.4",
+ "pretty-format": "^27.0.2"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/solid-testing-library/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/solid-testing-library/node_modules/aria-query": {
+ "version": "5.1.3",
+ "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz",
+ "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==",
+ "dev": true,
+ "dependencies": {
+ "deep-equal": "^2.0.5"
+ }
+ },
+ "node_modules/solid-testing-library/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/solid-testing-library/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/solid-testing-library/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/solid-testing-library/node_modules/deep-equal": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.1.0.tgz",
+ "integrity": "sha512-2pxgvWu3Alv1PoWEyVg7HS8YhGlUFUV7N5oOvfL6d+7xAmLSemMwv/c8Zv/i9KFzxV5Kt5CAvQc70fLwVuf4UA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "es-get-iterator": "^1.1.2",
+ "get-intrinsic": "^1.1.3",
+ "is-arguments": "^1.1.1",
+ "is-date-object": "^1.0.5",
+ "is-regex": "^1.1.4",
+ "isarray": "^2.0.5",
+ "object-is": "^1.1.5",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.4",
+ "regexp.prototype.flags": "^1.4.3",
+ "side-channel": "^1.0.4",
+ "which-boxed-primitive": "^1.0.2",
+ "which-collection": "^1.0.1",
+ "which-typed-array": "^1.1.8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/solid-testing-library/node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/solid-testing-library/node_modules/isarray": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
+ "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
+ "dev": true
+ },
+ "node_modules/solid-testing-library/node_modules/pretty-format": {
+ "version": "27.5.1",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz",
+ "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^5.0.1",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^17.0.1"
+ },
+ "engines": {
+ "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
+ }
+ },
+ "node_modules/solid-testing-library/node_modules/pretty-format/node_modules/ansi-styles": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/solid-testing-library/node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/sorcery": {
"version": "0.10.0",
"resolved": "https://registry.npmjs.org/sorcery/-/sorcery-0.10.0.tgz",
@@ -25924,6 +26195,12 @@
"tree-kill": "cli.js"
}
},
+ "node_modules/ts-toolbelt": {
+ "version": "9.6.0",
+ "resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-9.6.0.tgz",
+ "integrity": "sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w==",
+ "dev": true
+ },
"node_modules/tsconfig-paths": {
"version": "3.14.1",
"resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz",
@@ -26445,6 +26722,24 @@
}
}
},
+ "node_modules/vite-plugin-solid": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/vite-plugin-solid/-/vite-plugin-solid-2.4.0.tgz",
+ "integrity": "sha512-Rr+t2sr9TWIvH16yzBZzx6O9YSpYAvcwKUMPqbi/4iU3mRumXQ4O10i1XGtQIynC7U3XwJsMzAJigDFGbiJBiw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/core": "^7.18.6",
+ "@babel/preset-typescript": "^7.18.6",
+ "babel-preset-solid": "^1.4.6",
+ "merge-anything": "^5.0.2",
+ "solid-refresh": "^0.4.1",
+ "vitefu": "^0.1.1"
+ },
+ "peerDependencies": {
+ "solid-js": "^1.3.17",
+ "vite": "^3.0.0"
+ }
+ },
"node_modules/vite/node_modules/resolve": {
"version": "1.22.1",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
@@ -26477,6 +26772,20 @@
"fsevents": "~2.3.2"
}
},
+ "node_modules/vitefu": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-0.1.1.tgz",
+ "integrity": "sha512-HClD14fjMJ+NQgXBqT3dC3RdO/+Chayil+cCPYZKY3kT+KcJomKzrdgzfCHJkIL2L0OAY+VPvrSW615iPtc7ag==",
+ "dev": true,
+ "peerDependencies": {
+ "vite": "^3.0.0"
+ },
+ "peerDependenciesMeta": {
+ "vite": {
+ "optional": true
+ }
+ }
+ },
"node_modules/vitest": {
"version": "0.24.3",
"resolved": "https://registry.npmjs.org/vitest/-/vitest-0.24.3.tgz",
@@ -29548,6 +29857,26 @@
"resolved": "packages/overlayscrollbars/dist",
"link": true
},
+ "packages/overlayscrollbars-solid": {
+ "version": "0.4.0",
+ "license": "MIT",
+ "devDependencies": {
+ "overlayscrollbars": "file:./../overlayscrollbars/dist",
+ "solid-js": "^1.5.1",
+ "solid-testing-library": "^0.5.0",
+ "typescript": "^4.8.2",
+ "vite": "^3.0.9",
+ "vite-plugin-solid": "^2.3.0"
+ },
+ "peerDependencies": {
+ "overlayscrollbars": "^2.0.0",
+ "solid-js": "^1.5.1"
+ }
+ },
+ "packages/overlayscrollbars-solid/node_modules/overlayscrollbars": {
+ "resolved": "packages/overlayscrollbars/dist",
+ "link": true
+ },
"packages/overlayscrollbars-svelte": {
"version": "0.4.0",
"devDependencies": {
@@ -35174,6 +35503,35 @@
"@types/babel__traverse": "^7.0.6"
}
},
+ "babel-plugin-jsx-dom-expressions": {
+ "version": "0.35.4",
+ "resolved": "https://registry.npmjs.org/babel-plugin-jsx-dom-expressions/-/babel-plugin-jsx-dom-expressions-0.35.4.tgz",
+ "integrity": "sha512-Ab8W+36+XcNpyb644K537MtuhZRssgE3hmZD/08a1Z99Xfnd38tR2BZaDl7yEQvvHrb46N+eje2YjIg4VGAfVQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-module-imports": "7.16.0",
+ "@babel/plugin-syntax-jsx": "^7.16.5",
+ "@babel/types": "^7.16.0",
+ "html-entities": "2.3.2"
+ },
+ "dependencies": {
+ "@babel/helper-module-imports": {
+ "version": "7.16.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.0.tgz",
+ "integrity": "sha512-kkH7sWzKPq0xt3H1n+ghb4xEMP8k0U7XV3kkB+ZGy69kDk2ySFW1qPi06sjKzFY3t1j6XbJSqr4mF9L7CYVyhg==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.16.0"
+ }
+ },
+ "html-entities": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.2.tgz",
+ "integrity": "sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==",
+ "dev": true
+ }
+ }
+ },
"babel-plugin-polyfill-corejs2": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.3.tgz",
@@ -35242,6 +35600,15 @@
"babel-preset-current-node-syntax": "^1.0.0"
}
},
+ "babel-preset-solid": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/babel-preset-solid/-/babel-preset-solid-1.6.1.tgz",
+ "integrity": "sha512-Ji/cvYUE2BROsA3zOhaqKjuAEo6YAkmw8ZE11QsMtSEcWJ1rCFC829qWb5FLPl3UymVxh68+dpScPDtyyr/rdA==",
+ "dev": true,
+ "requires": {
+ "babel-plugin-jsx-dom-expressions": "^0.35.2"
+ }
+ },
"balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
@@ -42945,6 +43312,24 @@
"integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==",
"dev": true
},
+ "merge-anything": {
+ "version": "5.0.4",
+ "resolved": "https://registry.npmjs.org/merge-anything/-/merge-anything-5.0.4.tgz",
+ "integrity": "sha512-YFsDeY5A9SLXhL21Qn15wCWewRUW6wMTxQF4SuPe9bNdr1wsjiE44Rp8FQUTCtwO0WLdlKiFzhAVE5tlf857Tg==",
+ "dev": true,
+ "requires": {
+ "is-what": "^4.1.7",
+ "ts-toolbelt": "^9.6.0"
+ },
+ "dependencies": {
+ "is-what": {
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.7.tgz",
+ "integrity": "sha512-DBVOQNiPKnGMxRMLIYSwERAS5MVY1B7xYiGnpgctsOFvVDz9f9PFXXxMcTOHuoqYp4NK9qFYQaIC1NRRxLMpBQ==",
+ "dev": true
+ }
+ }
+ },
"merge-descriptors": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
@@ -45346,6 +45731,22 @@
}
}
},
+ "overlayscrollbars-solid": {
+ "version": "file:packages/overlayscrollbars-solid",
+ "requires": {
+ "overlayscrollbars": "file:../overlayscrollbars/dist",
+ "solid-js": "^1.5.1",
+ "solid-testing-library": "^0.5.0",
+ "typescript": "^4.8.2",
+ "vite": "^3.0.9",
+ "vite-plugin-solid": "^2.3.0"
+ },
+ "dependencies": {
+ "overlayscrollbars": {
+ "version": "file:packages/overlayscrollbars/dist"
+ }
+ }
+ },
"overlayscrollbars-svelte": {
"version": "file:packages/overlayscrollbars-svelte",
"requires": {
@@ -49296,6 +49697,159 @@
}
}
},
+ "solid-js": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.6.1.tgz",
+ "integrity": "sha512-i8OmR419Hr0918Or6sm1ET/cgmxTtAB7Bdz/UwhZ7G2THixrvVSO3jd+C7YqMKKfVwmf8PJ2gUSbKE8NKv28GA==",
+ "dev": true,
+ "requires": {
+ "csstype": "^3.1.0"
+ }
+ },
+ "solid-refresh": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/solid-refresh/-/solid-refresh-0.4.1.tgz",
+ "integrity": "sha512-v3tD/OXQcUyXLrWjPW1dXZyeWwP7/+GQNs8YTL09GBq+5FguA6IejJWUvJDrLIA4M0ho9/5zK2e9n+uy+4488g==",
+ "dev": true,
+ "requires": {
+ "@babel/generator": "^7.18.2",
+ "@babel/helper-module-imports": "^7.16.7",
+ "@babel/types": "^7.18.4"
+ }
+ },
+ "solid-testing-library": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/solid-testing-library/-/solid-testing-library-0.5.0.tgz",
+ "integrity": "sha512-vr4Ke9Dq3bUFLaXOcN8/IVn2e9Q37w4vdmoIOmFBIPs7iCJX9IxuC0IdQqK8nzBZMQqceijkfyCE3Qc407KmaA==",
+ "dev": true,
+ "requires": {
+ "@testing-library/dom": "^8.19.0"
+ },
+ "dependencies": {
+ "@testing-library/dom": {
+ "version": "8.19.0",
+ "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.19.0.tgz",
+ "integrity": "sha512-6YWYPPpxG3e/xOo6HIWwB/58HukkwIVTOaZ0VwdMVjhRUX/01E4FtQbck9GazOOj7MXHc5RBzMrU86iBJHbI+A==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/runtime": "^7.12.5",
+ "@types/aria-query": "^4.2.0",
+ "aria-query": "^5.0.0",
+ "chalk": "^4.1.0",
+ "dom-accessibility-api": "^0.5.9",
+ "lz-string": "^1.4.4",
+ "pretty-format": "^27.0.2"
+ }
+ },
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
+ },
+ "aria-query": {
+ "version": "5.1.3",
+ "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz",
+ "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==",
+ "dev": true,
+ "requires": {
+ "deep-equal": "^2.0.5"
+ }
+ },
+ "chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "deep-equal": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.1.0.tgz",
+ "integrity": "sha512-2pxgvWu3Alv1PoWEyVg7HS8YhGlUFUV7N5oOvfL6d+7xAmLSemMwv/c8Zv/i9KFzxV5Kt5CAvQc70fLwVuf4UA==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "es-get-iterator": "^1.1.2",
+ "get-intrinsic": "^1.1.3",
+ "is-arguments": "^1.1.1",
+ "is-date-object": "^1.0.5",
+ "is-regex": "^1.1.4",
+ "isarray": "^2.0.5",
+ "object-is": "^1.1.5",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.4",
+ "regexp.prototype.flags": "^1.4.3",
+ "side-channel": "^1.0.4",
+ "which-boxed-primitive": "^1.0.2",
+ "which-collection": "^1.0.1",
+ "which-typed-array": "^1.1.8"
+ }
+ },
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true
+ },
+ "isarray": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
+ "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
+ "dev": true
+ },
+ "pretty-format": {
+ "version": "27.5.1",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz",
+ "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^5.0.1",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^17.0.1"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
+ "dev": true
+ }
+ }
+ },
+ "supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ }
+ }
+ },
"sorcery": {
"version": "0.10.0",
"resolved": "https://registry.npmjs.org/sorcery/-/sorcery-0.10.0.tgz",
@@ -50461,6 +51015,12 @@
"integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==",
"dev": true
},
+ "ts-toolbelt": {
+ "version": "9.6.0",
+ "resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-9.6.0.tgz",
+ "integrity": "sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w==",
+ "dev": true
+ },
"tsconfig-paths": {
"version": "3.14.1",
"resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz",
@@ -50863,6 +51423,27 @@
}
}
},
+ "vite-plugin-solid": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/vite-plugin-solid/-/vite-plugin-solid-2.4.0.tgz",
+ "integrity": "sha512-Rr+t2sr9TWIvH16yzBZzx6O9YSpYAvcwKUMPqbi/4iU3mRumXQ4O10i1XGtQIynC7U3XwJsMzAJigDFGbiJBiw==",
+ "dev": true,
+ "requires": {
+ "@babel/core": "^7.18.6",
+ "@babel/preset-typescript": "^7.18.6",
+ "babel-preset-solid": "^1.4.6",
+ "merge-anything": "^5.0.2",
+ "solid-refresh": "^0.4.1",
+ "vitefu": "^0.1.1"
+ }
+ },
+ "vitefu": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-0.1.1.tgz",
+ "integrity": "sha512-HClD14fjMJ+NQgXBqT3dC3RdO/+Chayil+cCPYZKY3kT+KcJomKzrdgzfCHJkIL2L0OAY+VPvrSW615iPtc7ag==",
+ "dev": true,
+ "requires": {}
+ },
"vitest": {
"version": "0.24.3",
"resolved": "https://registry.npmjs.org/vitest/-/vitest-0.24.3.tgz",
diff --git a/package.json b/package.json
index 0ca554e..3818256 100644
--- a/package.json
+++ b/package.json
@@ -68,6 +68,7 @@
"test:vue": "npm run test --workspace=overlayscrollbars-vue",
"test:ngx": "npm run test --workspace=overlayscrollbars-ngx",
"test:svelte": "npm run test --workspace=overlayscrollbars-svelte",
+ "test:solid": "npm run test --workspace=overlayscrollbars-solid",
"e2e": "run-s e2e:*",
"e2e:os": "npm run e2e --workspace=overlayscrollbars",
"e2e:os:dev": "npm run e2e:dev --workspace=overlayscrollbars",
@@ -77,6 +78,7 @@
"build:vue": "npm run build --workspace=overlayscrollbars-vue",
"build:ngx": "npm run build --workspace=overlayscrollbars-ngx",
"build:svelte": "npm run build --workspace=overlayscrollbars-svelte",
+ "build:solid": "npm run build --workspace=overlayscrollbars-solid",
"example:react": "npm run build:react && cd examples/react && npm i && npm run start",
"example:vue": "npm run build:vue && cd examples/vue && npm i && npm run dev",
"example:ngx": "npm run build:ngx && cd examples/angular && npm i && npm run start",
diff --git a/packages/overlayscrollbars-solid/.gitignore b/packages/overlayscrollbars-solid/.gitignore
new file mode 100644
index 0000000..6c8bc50
--- /dev/null
+++ b/packages/overlayscrollbars-solid/.gitignore
@@ -0,0 +1,8 @@
+# Compiled output
+/dist
+
+# Node
+/node_modules
+
+# Miscellaneous
+/.coverage
diff --git a/packages/overlayscrollbars-solid/CHANGELOG.md b/packages/overlayscrollbars-solid/CHANGELOG.md
new file mode 100644
index 0000000..a21d9a6
--- /dev/null
+++ b/packages/overlayscrollbars-solid/CHANGELOG.md
@@ -0,0 +1,6 @@
+# Changelog
+
+## 0.4.0
+
+The component was created.
+Depends on `OverlayScrollbars` version `^2.0.0` and `Solid` version `^1.5.1`.
diff --git a/packages/overlayscrollbars-solid/README.md b/packages/overlayscrollbars-solid/README.md
new file mode 100644
index 0000000..4a94f4e
--- /dev/null
+++ b/packages/overlayscrollbars-solid/README.md
@@ -0,0 +1,167 @@
+
+

+

+
+
+
+
+ [](https://github.com/KingSora/OverlayScrollbars)
+ [](https://github.com/solidjs/solid)
+ [](https://www.npmjs.com/package/overlayscrollbars-solid)
+ [](https://www.npmjs.com/package/overlayscrollbars-solid)
+ [](#)
+
+
+
+# OverlayScrollbars for Solid
+
+This is the official OverlayScrollbars Solid wrapper.
+
+## Installation
+
+```sh
+npm install overlayscrollbars-solid
+```
+
+## Peer Dependencies
+
+OverlayScrollbars for Solid has the following **peer dependencies**:
+
+- The vanilla JavaScript library: [overlayscrollbars](https://www.npmjs.com/package/overlayscrollbars)
+
+```
+npm install overlayscrollbars
+```
+
+- The Solid framework: [solid-js](https://www.npmjs.com/package/solid-js)
+
+```
+npm install solid-js
+```
+
+## Usage
+
+The first step is to import the CSS file into your app:
+```ts
+import 'overlayscrollbars/overlayscrollbars.css';
+```
+
+> __Note__: In older node versions use `'overlayscrollbars/styles/overlayscrollbars.css'` as the import path for the CSS file.
+
+## Component
+
+The main entry point is the `OverlayScrollbarsComponent` which can be used in your application as a component:
+
+```jsx
+import { OverlayScrollbarsComponent } from "overlayscrollbars-solid";
+
+// ...
+
+
+ example content
+
+```
+
+### Properties
+
+It has three optional properties: `element`, `options` and `events`.
+
+- `element`: accepts a `string` which represents the tag of the root element.
+- `options`: accepts an `object` which represents the OverlayScrollbars options.
+- `events`: accepts an `object` which represents the OverlayScrollbars events.
+
+```jsx
+// example usage
+ { /* ... */ } }}
+/>
+```
+
+### Ref
+
+The `ref` of the `OverlayScrollbarsComponent` will give you an object with which you can access the OverlayScrollbars `instance` and the root `element` of the component.
+The ref object has two properties:
+
+- `osInstance`: a function which returns the OverlayScrollbars instance.
+- `getElement`: a function which returns the root element.
+
+```jsx
+// example usage
+import type { OverlayScrollbarsComponentRef } from 'overlayscrollbars-solid';
+
+const Component = () => {
+ let ref: OverlayScrollbarsComponentRef | undefined;
+
+ return (ref = r)} />
+}
+```
+
+## Primitive
+
+In case the `OverlayScrollbarsComponent` is not enough, you can also use the `createOverlayScrollbars` primitive:
+
+```jsx
+import { createOverlayScrollbars } from "overlayscrollbars-solid";
+
+// example usage
+const Component = () => {
+ let div;
+ const [params, setParams] = createStore({ options, events });
+ const [initialize, instance] = useOverlayScrollbars(params);
+
+ /**
+ * or:
+ *
+ * const [params, setParams] = createSignal<{
+ * options?: PartialOptions;
+ * events?: EventListeners;
+ * }>({});
+ * const [initialize, instance] = createOverlayScrollbars(params);
+ *
+ * or:
+ *
+ * const [options, setOptions] = createSignal();
+ * const [events, setEvents] = createSignal();
+ * const [initialize, instance] = createOverlayScrollbars({
+ * options,
+ * events,
+ * });
+ *
+ */
+
+ onMount(() => {
+ initialize({ target: div });
+ });
+
+ onCleanup(() => {
+ instance().destroy();
+ });
+
+ return
+}
+```
+
+The primitive is for advanced usage and lets you control the whole initialization process. This is useful if you want to integrate it with other plugins.
+
+### Parameters
+
+Parameters are optional and similar to the `OverlayScrollbarsComponent`.
+Its an `object` with two optional properties:
+
+- `options`: accepts an `object` which represents the OverlayScrollbars options.
+- `events`: accepts an `object` which represents the OverlayScrollbars events.
+
+> __Note__: The object can be a normal, `store` or `signal` object. This also applies to the `options` and `events` fields.
+
+### Return
+
+The `createOverlayScrollbars` primitive returns a `tuple` with two values:
+
+- The first value is the `initialization` function, it takes one argument which is the `InitializationTarget` and returns the OverlayScrollbars instance.
+- The second value is a function which returns the current OverlayScrollbars instance or `null` if not initialized.
+
+## License
+
+MIT
diff --git a/packages/overlayscrollbars-solid/logo.svg b/packages/overlayscrollbars-solid/logo.svg
new file mode 100644
index 0000000..025aa30
--- /dev/null
+++ b/packages/overlayscrollbars-solid/logo.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/packages/overlayscrollbars-solid/package.json b/packages/overlayscrollbars-solid/package.json
new file mode 100644
index 0000000..64f2159
--- /dev/null
+++ b/packages/overlayscrollbars-solid/package.json
@@ -0,0 +1,49 @@
+{
+ "name": "overlayscrollbars-solid",
+ "private": true,
+ "version": "0.4.0",
+ "description": "OverlayScrollbars for Solid.",
+ "author": "Rene Haas | KingSora",
+ "license": "MIT",
+ "homepage": "https://kingsora.github.io/OverlayScrollbars",
+ "bugs": "https://github.com/KingSora/OverlayScrollbars/issues",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/KingSora/OverlayScrollbars.git",
+ "directory": "packages/overlayscrollbars-solid"
+ },
+ "keywords": [
+ "overlayscrollbars",
+ "solid",
+ "solidjs",
+ "component",
+ "hook",
+ "hooks",
+ "primitive",
+ "styleable",
+ "scrollbar",
+ "scrollbars",
+ "scroll"
+ ],
+ "main": "./src/overlayscrollbars-solid.ts",
+ "module": "./src/overlayscrollbars-solid.ts",
+ "types": "./src/overlayscrollbars-solid.ts",
+ "peerDependencies": {
+ "overlayscrollbars": "^2.0.0",
+ "solid-js": "^1.5.1"
+ },
+ "devDependencies": {
+ "overlayscrollbars": "file:./../overlayscrollbars/dist",
+ "solid-js": "^1.5.1",
+ "solid-testing-library": "^0.5.0",
+ "typescript": "^4.8.2",
+ "vite": "^3.0.9",
+ "vite-plugin-solid": "^2.3.0"
+ },
+ "scripts": {
+ "build": "run-p build-js build-types",
+ "test": "vitest run --coverage",
+ "build-js": "vite build",
+ "build-types": "vue-tsc --emitDeclarationOnly -p tsconfig.types.json --composite false"
+ }
+}
diff --git a/packages/overlayscrollbars-solid/src/OverlayScrollbarsComponent.tsx b/packages/overlayscrollbars-solid/src/OverlayScrollbarsComponent.tsx
new file mode 100644
index 0000000..01e9c80
--- /dev/null
+++ b/packages/overlayscrollbars-solid/src/OverlayScrollbarsComponent.tsx
@@ -0,0 +1,100 @@
+import {
+ mergeProps,
+ splitProps,
+ children,
+ onCleanup,
+ createEffect,
+ createRenderEffect,
+ createSignal,
+} from 'solid-js';
+import { Dynamic } from 'solid-js/web';
+import type { JSX, ParentProps, ComponentProps, Ref } from 'solid-js';
+import type { OverlayScrollbars, PartialOptions, EventListeners } from 'overlayscrollbars';
+import { createOverlayScrollbars } from './createOverlayScrollbars';
+
+type InferGeneric = T extends JSX.HTMLAttributes ? G : never;
+
+export type OverlayScrollbarsComponentProps = Omit<
+ ComponentProps,
+ 'ref'
+> &
+ ParentProps<{
+ /** Tag of the root element. */
+ element?: T;
+ /** OverlayScrollbars options. */
+ options?: PartialOptions | false | null;
+ /** OverlayScrollbars events. */
+ events?: EventListeners | false | null;
+ /** OverlayScrollbarsComponent ref. */
+ ref?: Exclude[, OverlayScrollbarsComponentRef>;
+ }>;
+
+export interface OverlayScrollbarsComponentRef {
+ /** Returns the OverlayScrollbars instance or null if not initialized. */
+ osInstance(): OverlayScrollbars | null;
+ /** Returns the root element. */
+ getElement(): InferGeneric | null;
+}
+
+export const OverlayScrollbarsComponent = (
+ props: OverlayScrollbarsComponentProps
+) => {
+ const [finalProps, other] = splitProps(
+ mergeProps({ element: 'div' }, props as OverlayScrollbarsComponentProps),
+ ['element', 'options', 'events', 'ref', 'children']
+ );
+ const [elementRef, setElementRef] = createSignal();
+ const [childrenRef, setChildrenRef] = createSignal();
+ const [initialize, instance] = createOverlayScrollbars(finalProps);
+
+ createEffect(() => {
+ const currElement = elementRef();
+ const currChildrenElement = childrenRef();
+
+ if (currElement && currChildrenElement) {
+ const osInstance = initialize({
+ target: currElement,
+ elements: {
+ viewport: currChildrenElement,
+ content: currChildrenElement,
+ },
+ });
+
+ onCleanup(() => {
+ osInstance.destroy();
+ });
+ }
+ });
+
+ createRenderEffect(() => {
+ finalProps.ref?.({
+ osInstance: instance,
+ getElement: () =>
+ /* c8 ignore next */
+ elementRef() || null,
+ });
+ });
+
+ onCleanup(() => {
+ instance()?.destroy();
+ });
+
+ return (
+ {
+ setElementRef(ref);
+ }}
+ {...other}
+ >
+ ] {
+ setChildrenRef(ref);
+ }}
+ >
+ {children(() => finalProps.children)}
+
+
+ );
+};
diff --git a/packages/overlayscrollbars-solid/src/createOverlayScrollbars.ts b/packages/overlayscrollbars-solid/src/createOverlayScrollbars.ts
new file mode 100644
index 0000000..3293511
--- /dev/null
+++ b/packages/overlayscrollbars-solid/src/createOverlayScrollbars.ts
@@ -0,0 +1,70 @@
+import { createRenderEffect } from 'solid-js';
+import { OverlayScrollbars } from 'overlayscrollbars';
+import type { Accessor } from 'solid-js';
+import type { Store } from 'solid-js/store';
+import type { InitializationTarget } from 'overlayscrollbars';
+import type {
+ OverlayScrollbarsComponentProps,
+ OverlayScrollbarsComponentRef,
+} from './OverlayScrollbarsComponent';
+
+export interface CreateOverlayScrollbarsParams {
+ /** OverlayScrollbars options. */
+ options?:
+ | OverlayScrollbarsComponentProps['options']
+ | Accessor;
+ /** OverlayScrollbars events. */
+ events?:
+ | OverlayScrollbarsComponentProps['events']
+ | Accessor;
+}
+
+export type CreateOverlayScrollbarsInitialization = (
+ target: InitializationTarget
+) => OverlayScrollbars;
+
+export type CreateOverlayScrollbarsInstance = () => ReturnType<
+ OverlayScrollbarsComponentRef['osInstance']
+>;
+
+const isAccessor = (obj: any): obj is Accessor => typeof obj === 'function';
+const unwrapAccessor = (obj: Accessor | T): T => (isAccessor(obj) ? obj() : obj);
+
+export const createOverlayScrollbars = (
+ params?:
+ | CreateOverlayScrollbarsParams
+ | Accessor
+ | Store
+): [CreateOverlayScrollbarsInitialization, CreateOverlayScrollbarsInstance] => {
+ let instance: OverlayScrollbars | null = null;
+ let options: OverlayScrollbarsComponentProps['options'];
+ let events: OverlayScrollbarsComponentProps['events'];
+
+ createRenderEffect(() => {
+ options = unwrapAccessor(unwrapAccessor(params)?.options);
+
+ if (OverlayScrollbars.valid(instance)) {
+ instance.options(options || {}, true);
+ }
+ });
+
+ createRenderEffect(() => {
+ events = unwrapAccessor(unwrapAccessor(params)?.events);
+
+ if (OverlayScrollbars.valid(instance)) {
+ instance.on(events || {}, true);
+ }
+ });
+
+ return [
+ (target: InitializationTarget): OverlayScrollbars => {
+ // if already initialized return the current instance
+ if (OverlayScrollbars.valid(instance)) {
+ return instance;
+ }
+
+ return (instance = OverlayScrollbars(target, options || {}, events || {}));
+ },
+ () => instance,
+ ];
+};
diff --git a/packages/overlayscrollbars-solid/src/overlayscrollbars-solid.ts b/packages/overlayscrollbars-solid/src/overlayscrollbars-solid.ts
new file mode 100644
index 0000000..5a2961e
--- /dev/null
+++ b/packages/overlayscrollbars-solid/src/overlayscrollbars-solid.ts
@@ -0,0 +1,2 @@
+export * from './OverlayScrollbarsComponent';
+export * from './createOverlayScrollbars';
diff --git a/packages/overlayscrollbars-solid/test/OverlayScrollbarsComponent.test.tsx b/packages/overlayscrollbars-solid/test/OverlayScrollbarsComponent.test.tsx
new file mode 100644
index 0000000..587c9cb
--- /dev/null
+++ b/packages/overlayscrollbars-solid/test/OverlayScrollbarsComponent.test.tsx
@@ -0,0 +1,395 @@
+import { describe, test, afterEach, expect, vitest } from 'vitest';
+import { createSignal, createEffect } from 'solid-js';
+import { render, screen, cleanup, fireEvent } from 'solid-testing-library';
+import userEvent from '@testing-library/user-event';
+import { OverlayScrollbars } from 'overlayscrollbars';
+import { OverlayScrollbarsComponent } from '~/overlayscrollbars-solid';
+import type { OverlayScrollbarsComponentRef } from '~/overlayscrollbars-solid';
+
+const createTestComponent =
+ (props: any = {}) =>
+ () => {
+ let ref: OverlayScrollbarsComponentRef | undefined;
+ const [element, setElement]: any = createSignal(props.element || 'div');
+ const [options, setOptions]: any = createSignal(props.options);
+ const [events, setEvents]: any = createSignal(props.events);
+ const [className, setClassName]: any = createSignal(props.className);
+ const [style, setStyle]: any = createSignal(props.style);
+
+ createEffect(() => {
+ props?.getRef?.(ref);
+ });
+
+ return (
+ <>
+ (ref = r)}
+ />
+
+ >
+ );
+ };
+
+/**
+ * rerender doesn't exist... so I am faking it with custom event...
+ */
+describe('OverlayScrollbarsComponent', () => {
+ afterEach(() => cleanup());
+
+ describe('correct rendering', () => {
+ test('correct root element with instance', () => {
+ const elementA = 'code';
+ const elementB = 'span';
+ let osInstance;
+ const { container } = render(createTestComponent());
+
+ expect(container).not.toBeEmptyDOMElement();
+ expect(container.querySelector('div')).toBe(container.firstElementChild); // default is div
+
+ expect(OverlayScrollbars.valid(osInstance)).toBe(false);
+ osInstance = OverlayScrollbars(container.firstElementChild as HTMLElement);
+ expect(osInstance).toBeDefined();
+ expect(OverlayScrollbars.valid(osInstance)).toBe(true);
+
+ fireEvent(
+ screen.getByText('props'),
+ new CustomEvent('osProps', {
+ detail: { element: elementA },
+ })
+ );
+
+ expect(container.querySelector(elementA)).toBe(container.firstElementChild);
+
+ expect(OverlayScrollbars.valid(osInstance)).toBe(false); // prev instance is destroyed
+ osInstance = OverlayScrollbars(container.firstElementChild as HTMLElement);
+ expect(osInstance).toBeDefined();
+ expect(OverlayScrollbars.valid(osInstance)).toBe(true);
+
+ fireEvent(
+ screen.getByText('props'),
+ new CustomEvent('osProps', {
+ detail: { element: elementB },
+ })
+ );
+
+ expect(container.querySelector(elementB)).toBe(container.firstElementChild);
+
+ expect(OverlayScrollbars.valid(osInstance)).toBe(false); // prev instance is destroyed
+ osInstance = OverlayScrollbars(container.firstElementChild as HTMLElement);
+ expect(osInstance).toBeDefined();
+ expect(OverlayScrollbars.valid(osInstance)).toBe(true);
+ });
+
+ test('data-overlayscrollbars-initialize', async () => {
+ const { container } = render(() => );
+
+ expect(container.querySelector('[data-overlayscrollbars-initialize]')).toBeTruthy();
+ });
+
+ test('children', () => {
+ const { container } = render(() => (
+
+ hello solid
+
+ ));
+ expect(screen.getByText(/hello/)).toBeInTheDocument();
+ expect(screen.getByText(/solid/)).toBeInTheDocument();
+ expect(screen.getByText(/solid/).parentElement).not.toBe(container.firstElementChild);
+ });
+
+ test('dynamic children', async () => {
+ render(() => {
+ const [elements, setElements] = createSignal(1);
+ return (
+ <>
+
+ {elements() === 0 ? 'empty' : null}
+ {[...Array(elements()).keys()].map((i) => (
+ {i}
+ ))}
+
+
+
+ >
+ );
+ });
+
+ const addBtn = screen.getByText('add');
+ const removeBtn = screen.getByText('remove');
+ const initialElement = screen.getByText('0');
+ expect(initialElement).toBeInTheDocument();
+
+ const initialElementParent = initialElement.parentElement;
+ expect(initialElementParent).toBeInTheDocument();
+
+ userEvent.click(addBtn);
+ expect((await screen.findByText('1')).parentElement).toBe(initialElementParent);
+
+ userEvent.click(removeBtn);
+ userEvent.click(removeBtn);
+ expect(await screen.findByText('empty')).toBe(initialElementParent);
+ });
+
+ test('className', () => {
+ const { container } = render(
+ createTestComponent({
+ className: 'overlay scrollbars',
+ })
+ );
+
+ expect(container.firstElementChild).toHaveClass('overlay', 'scrollbars');
+
+ fireEvent(
+ screen.getByText('props'),
+ new CustomEvent('osProps', {
+ detail: { className: 'overlay scrollbars solid' },
+ })
+ );
+
+ expect(container.firstElementChild).toHaveClass('overlay', 'scrollbars', 'solid');
+ });
+
+ test('style', () => {
+ const { container } = render(
+ createTestComponent({
+ style: { width: '22px' },
+ })
+ );
+
+ expect(container.firstElementChild).toHaveStyle({ width: '22px' });
+
+ fireEvent(
+ screen.getByText('props'),
+ new CustomEvent('osProps', {
+ detail: { style: { height: '33px' } },
+ })
+ );
+
+ expect(container.firstElementChild).toHaveStyle({ height: '33px' });
+ });
+ });
+
+ test('ref', () => {
+ let osRef: OverlayScrollbarsComponentRef | undefined;
+ const { container } = render(
+ createTestComponent({
+ getRef(ref: any) {
+ osRef = ref;
+ },
+ })
+ );
+
+ expect(osRef).toBeTruthy();
+
+ const { osInstance, getElement } = osRef!;
+ expect(osInstance).toBeTypeOf('function');
+ expect(getElement).toBeTypeOf('function');
+ expect(OverlayScrollbars.valid(osInstance())).toBe(true);
+ expect(getElement()).toBe(container.firstElementChild);
+ });
+
+ test('options', () => {
+ let osRef: OverlayScrollbarsComponentRef | undefined;
+ render(
+ createTestComponent({
+ options: { paddingAbsolute: true, overflow: { y: 'hidden' } },
+ getRef(ref: any) {
+ osRef = ref;
+ },
+ })
+ );
+
+ const instance = osRef!.osInstance()!;
+
+ const opts = instance.options();
+ expect(opts.paddingAbsolute).toBe(true);
+ expect(opts.overflow.y).toBe('hidden');
+
+ fireEvent(
+ screen.getByText('props'),
+ new CustomEvent('osProps', {
+ detail: {
+ options: { overflow: { x: 'hidden' } },
+ },
+ })
+ );
+
+ const newOpts = instance.options();
+ expect(newOpts.paddingAbsolute).toBe(false); //switches back to default because its not specified in the new options
+ expect(newOpts.overflow.x).toBe('hidden');
+ expect(newOpts.overflow.y).toBe('scroll'); //switches back to default because its not specified in the new options
+
+ // instance didn't change
+ expect(instance).toBe(osRef!.osInstance());
+
+ fireEvent(
+ screen.getByText('props'),
+ new CustomEvent('osProps', {
+ detail: {
+ element: 'span',
+ options: { overflow: { x: 'hidden', y: 'hidden' } },
+ },
+ })
+ );
+
+ const newElementInstance = osRef!.osInstance()!;
+ const newElementNewOpts = newElementInstance.options();
+ expect(newElementInstance).not.toBe(instance);
+ expect(newElementNewOpts.paddingAbsolute).toBe(false);
+ expect(newElementNewOpts.overflow.x).toBe('hidden');
+ expect(newElementNewOpts.overflow.y).toBe('hidden');
+
+ // reset options with `undefined`, `null`, `false` or `{}`
+ fireEvent(
+ screen.getByText('props'),
+ new CustomEvent('osProps', {
+ detail: {
+ options: undefined,
+ },
+ })
+ );
+
+ const clearedOpts = newElementInstance.options();
+ expect(osRef!.osInstance()).toBe(newElementInstance);
+ expect(clearedOpts.paddingAbsolute).toBe(false);
+ expect(clearedOpts.overflow.x).toBe('scroll');
+ expect(clearedOpts.overflow.y).toBe('scroll');
+ });
+
+ test('events', () => {
+ const onUpdatedInitial = vitest.fn();
+ const onUpdated = vitest.fn();
+ let osRef: OverlayScrollbarsComponentRef | undefined;
+ render(
+ createTestComponent({
+ events: { updated: onUpdatedInitial },
+ getRef: (ref: any) => {
+ osRef = ref;
+ },
+ })
+ );
+
+ const instance = osRef!.osInstance()!;
+
+ expect(onUpdatedInitial).toHaveBeenCalledTimes(1);
+
+ fireEvent(
+ screen.getByText('props'),
+ new CustomEvent('osProps', {
+ detail: {
+ events: { updated: onUpdated },
+ },
+ })
+ );
+ expect(onUpdated).not.toHaveBeenCalled();
+
+ instance.update(true);
+ expect(onUpdatedInitial).toHaveBeenCalledTimes(1);
+ expect(onUpdated).toHaveBeenCalledTimes(1);
+
+ fireEvent(
+ screen.getByText('props'),
+ new CustomEvent('osProps', {
+ detail: {
+ events: { updated: [onUpdated, onUpdatedInitial] },
+ },
+ })
+ );
+
+ instance.update(true);
+ expect(onUpdatedInitial).toHaveBeenCalledTimes(2);
+ expect(onUpdated).toHaveBeenCalledTimes(2);
+
+ // unregister with `[]`, `null` or `undefined`
+ fireEvent(
+ screen.getByText('props'),
+ new CustomEvent('osProps', {
+ detail: {
+ events: { updated: null },
+ },
+ })
+ );
+
+ instance.update(true);
+ expect(onUpdatedInitial).toHaveBeenCalledTimes(2);
+ expect(onUpdated).toHaveBeenCalledTimes(2);
+
+ // instance didn't change
+ expect(instance).toBe(osRef!.osInstance());
+
+ fireEvent(
+ screen.getByText('props'),
+ new CustomEvent('osProps', {
+ detail: { element: 'span', events: { updated: [onUpdated, onUpdatedInitial] } },
+ })
+ );
+
+ const newElementInstance = osRef!.osInstance()!;
+ expect(newElementInstance).not.toBe(instance);
+ expect(onUpdatedInitial).toHaveBeenCalledTimes(3);
+ expect(onUpdated).toHaveBeenCalledTimes(3);
+
+ // reset events with `undefined`, `null`, `false` or `{}`
+ fireEvent(
+ screen.getByText('props'),
+ new CustomEvent('osProps', {
+ detail: { element: 'span', events: undefined },
+ })
+ );
+
+ newElementInstance.update(true);
+ expect(newElementInstance).toBe(osRef!.osInstance());
+ expect(onUpdatedInitial).toHaveBeenCalledTimes(3);
+ expect(onUpdated).toHaveBeenCalledTimes(3);
+ });
+
+ test('destroy', () => {
+ let osRef: OverlayScrollbarsComponentRef | undefined;
+ const { unmount } = render(
+ createTestComponent({
+ getRef(ref: any) {
+ osRef = ref;
+ },
+ })
+ );
+ const { osInstance } = osRef!;
+
+ expect(OverlayScrollbars.valid(osInstance())).toBe(true);
+
+ unmount();
+
+ expect(osInstance()).toBeDefined();
+ expect(OverlayScrollbars.valid(osInstance())).toBe(false);
+ });
+});
diff --git a/packages/overlayscrollbars-solid/test/createOverlayScrollbars.test.tsx b/packages/overlayscrollbars-solid/test/createOverlayScrollbars.test.tsx
new file mode 100644
index 0000000..65be463
--- /dev/null
+++ b/packages/overlayscrollbars-solid/test/createOverlayScrollbars.test.tsx
@@ -0,0 +1,186 @@
+import { describe, test, afterEach, expect, vitest } from 'vitest';
+import { createSignal, createEffect, onMount } from 'solid-js';
+import { createStore } from 'solid-js/store';
+import { render, screen, cleanup } from 'solid-testing-library';
+import userEvent from '@testing-library/user-event';
+import { createOverlayScrollbars } from '~/overlayscrollbars-solid';
+import type { OverlayScrollbars, PartialOptions, EventListeners } from 'overlayscrollbars';
+
+describe('OverlayScrollbarsComponent', () => {
+ afterEach(() => cleanup());
+
+ test('re-initialization', () => {
+ const Test = () => {
+ let instanceRef: OverlayScrollbars | null = null;
+ const [initialize, instance] = createOverlayScrollbars();
+ return (
+ <>
+
+ >
+ );
+ };
+
+ render(Test);
+
+ const initializeBtn = screen.getByRole('button');
+ userEvent.click(initializeBtn);
+ // taking snapshot here wouldn't be equal because of "tabindex" attribute of the viewport element
+ userEvent.click(initializeBtn);
+ const snapshot = initializeBtn.innerHTML;
+ userEvent.click(initializeBtn);
+
+ expect(snapshot).toBe(initializeBtn.innerHTML);
+ });
+
+ test('params store', () => {
+ let osInstance: OverlayScrollbars;
+ const onUpdated = vitest.fn();
+ render(() => {
+ let div: HTMLDivElement;
+ const [params, setParams] = createStore<{
+ options?: PartialOptions;
+ events?: EventListeners;
+ }>({});
+ const [initialize, instance] = createOverlayScrollbars(params);
+
+ onMount(() => {
+ osInstance = initialize({ target: div! });
+ });
+
+ createEffect(() => {
+ if (params.events?.updated) {
+ instance()?.update(true);
+ }
+ });
+
+ return () => (
+ <>
+
+
+ >
+ );
+ });
+
+ expect(onUpdated).not.toHaveBeenCalled();
+
+ const triggerBtn = screen.getByRole('button');
+ userEvent.click(triggerBtn);
+
+ expect(onUpdated).toHaveBeenCalledTimes(1);
+ expect(osInstance!.options().paddingAbsolute).toBe(true);
+ });
+
+ test('params signal', () => {
+ let osInstance: OverlayScrollbars;
+ const onUpdated = vitest.fn();
+ render(() => {
+ let div: HTMLDivElement;
+ const [params, setParams] = createSignal<{
+ options?: PartialOptions;
+ events?: EventListeners;
+ }>({});
+ const [initialize, instance] = createOverlayScrollbars(params);
+
+ onMount(() => {
+ osInstance = initialize({ target: div! });
+ });
+
+ createEffect(() => {
+ if (params().events?.updated) {
+ instance()?.update(true);
+ }
+ });
+
+ return () => (
+ <>
+
+
+ >
+ );
+ });
+
+ expect(onUpdated).not.toHaveBeenCalled();
+
+ const triggerBtn = screen.getByRole('button');
+ userEvent.click(triggerBtn);
+
+ expect(onUpdated).toHaveBeenCalledTimes(1);
+ expect(osInstance!.options().paddingAbsolute).toBe(true);
+ });
+
+ test('params fields signal', async () => {
+ let osInstance: OverlayScrollbars;
+ const onUpdated = vitest.fn();
+ render(() => {
+ let div: HTMLDivElement;
+ const [options, setOptions] = createSignal();
+ const [events, setEvents] = createSignal();
+ const [initialize, instance] = createOverlayScrollbars({
+ options,
+ events,
+ });
+
+ onMount(() => {
+ osInstance = initialize({ target: div! });
+ });
+
+ createEffect(() => {
+ if (events()?.updated) {
+ instance()?.update(true);
+ }
+ });
+
+ return () => (
+ <>
+
+
+ >
+ );
+ });
+
+ expect(onUpdated).not.toHaveBeenCalled();
+
+ const triggerBtn = screen.getByRole('button');
+ userEvent.click(triggerBtn);
+
+ expect(onUpdated).toHaveBeenCalledTimes(1);
+ expect(osInstance!.options().paddingAbsolute).toBe(true);
+ });
+});
diff --git a/packages/overlayscrollbars-solid/tsconfig.json b/packages/overlayscrollbars-solid/tsconfig.json
new file mode 100644
index 0000000..3f6ca9d
--- /dev/null
+++ b/packages/overlayscrollbars-solid/tsconfig.json
@@ -0,0 +1,18 @@
+{
+ "extends": "@~local/tsconfig",
+ "compilerOptions": {
+ "strict": true,
+ "target": "ESNext",
+ "module": "ESNext",
+ "moduleResolution": "node",
+ "allowSyntheticDefaultImports": true,
+ "esModuleInterop": true,
+ "jsx": "preserve",
+ "jsxImportSource": "solid-js",
+ "types": ["vite/client", "jest", "@testing-library/jest-dom"],
+ "isolatedModules": true,
+ "paths": {
+ "~/*": ["./src/*"]
+ }
+ }
+}
diff --git a/packages/overlayscrollbars-solid/tsconfig.types.json b/packages/overlayscrollbars-solid/tsconfig.types.json
new file mode 100644
index 0000000..aeec63a
--- /dev/null
+++ b/packages/overlayscrollbars-solid/tsconfig.types.json
@@ -0,0 +1,9 @@
+{
+ "extends": "./tsconfig.json",
+ "compilerOptions": {
+ "rootDir": "./src/",
+ "outDir": "./dist/types",
+ "declaration": true
+ },
+ "include": ["src/**/*"]
+}
\ No newline at end of file
diff --git a/packages/overlayscrollbars-solid/vite.config.js b/packages/overlayscrollbars-solid/vite.config.js
new file mode 100644
index 0000000..643b825
--- /dev/null
+++ b/packages/overlayscrollbars-solid/vite.config.js
@@ -0,0 +1,62 @@
+import { resolve } from 'node:path';
+import { defineConfig } from 'vite';
+import { esbuildResolve } from 'rollup-plugin-esbuild-resolve';
+import solidPlugin from 'vite-plugin-solid';
+import rollupPluginPackageJson from '@~local/rollup/plugin/packageJson';
+import rollupPluginCopy from '@~local/rollup/plugin/copy';
+
+export default defineConfig({
+ build: {
+ sourcemap: true,
+ outDir: 'dist',
+ lib: {
+ formats: ['es', 'cjs'],
+ entry: resolve(__dirname, 'src/overlayscrollbars-solid.ts'),
+ name: 'OverlayScrollbarsSolid',
+ fileName: (format) => `overlayscrollbars-solid.${format}.js`,
+ },
+ rollupOptions: {
+ external: ['solid-js', 'solid-js/web', 'solid-js/store', 'overlayscrollbars'],
+ output: {
+ globals: {
+ overlayscrollbars: 'OverlayScrollbarsGlobal',
+ },
+ },
+ plugins: [
+ rollupPluginCopy({ paths: ['README.md', 'CHANGELOG.md'] }),
+ rollupPluginPackageJson({
+ json: ({
+ name,
+ version,
+ description,
+ author,
+ license,
+ homepage,
+ bugs,
+ repository,
+ keywords,
+ peerDependencies,
+ }) => {
+ return {
+ name,
+ version,
+ description,
+ author,
+ license,
+ homepage,
+ bugs,
+ repository,
+ keywords,
+ main: 'overlayscrollbars-vue.cjs.js',
+ module: 'overlayscrollbars-vue.es.js',
+ types: 'types/overlayscrollbars-vue.d.ts',
+ peerDependencies,
+ sideEffects: false,
+ };
+ },
+ }),
+ ],
+ },
+ },
+ plugins: [esbuildResolve(), solidPlugin()],
+});
diff --git a/packages/overlayscrollbars-solid/vitest.config.js b/packages/overlayscrollbars-solid/vitest.config.js
new file mode 100644
index 0000000..bb12a57
--- /dev/null
+++ b/packages/overlayscrollbars-solid/vitest.config.js
@@ -0,0 +1,20 @@
+import { mergeConfig } from 'vite';
+import vitestConfig from '@~local/config/vitest';
+import viteConfig from './vite.config';
+
+export default mergeConfig(
+ {
+ ...viteConfig,
+ resolve: {
+ conditions: ['development', 'browser'],
+ },
+ },
+ {
+ test: {
+ ...vitestConfig.test,
+ deps: {
+ inline: [/solid-testing-library/],
+ },
+ },
+ }
+);
diff --git a/packages/overlayscrollbars-svelte/test/OverlayScrollbarsComponent.test.ts b/packages/overlayscrollbars-svelte/test/OverlayScrollbarsComponent.test.ts
index 25ff18f..d5e01d3 100644
--- a/packages/overlayscrollbars-svelte/test/OverlayScrollbarsComponent.test.ts
+++ b/packages/overlayscrollbars-svelte/test/OverlayScrollbarsComponent.test.ts
@@ -3,7 +3,7 @@ import { cleanup, render, screen, fireEvent } from '@testing-library/svelte';
import userEvent from '@testing-library/user-event';
import { OverlayScrollbars } from 'overlayscrollbars';
import { OverlayScrollbarsComponent } from '~/index'; // eslint-disable-line import/named
-import type { OverlayScrollbarsComponentRef } from '~/index'; // eslint-disable-line import/named
+import type { OverlayScrollbarsComponentRef } from '~/OverlayScrollbarsComponent.types'; // eslint-disable-line import/named
import Test from './Test.svelte';
/**