diff --git a/.eslintrc b/.eslintrc index 207c8f7..b2a1041 100644 --- a/.eslintrc +++ b/.eslintrc @@ -45,9 +45,12 @@ "ignoreVoid": true } ], - "@typescript-eslint/no-explicit-any": "warn", "@typescript-eslint/no-unused-vars": "warn", - "@typescript-eslint/explicit-function-return-type": "warn", + "@typescript-eslint/explicit-function-return-type": [ + "warn", { + "allowExpressions": true + } + ], "@typescript-eslint/interface-name-prefix": "off", "@typescript-eslint/no-empty-function": "off", "@typescript-eslint/no-empty-interface": "off", @@ -85,11 +88,18 @@ "allowEmptyCatch": true } ], - "no-void": "off", "no-extra-boolean-cast": "off", "no-undef-init": "error", "prefer-const": "off", "simple-import-sort/exports": "warn", "simple-import-sort/imports": "warn" - } -} \ No newline at end of file + }, + "overrides": [ + { + "files": ["*.tsx"], + "rules": { + "@typescript-eslint/no-unused-vars": "off" + } + } + ] +} diff --git a/package-lock.json b/package-lock.json index aa9a310..c7bc8fa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,20 @@ { - "name": "@rbxts/tina", + "name": "tina", "version": "1.0.0", "lockfileVersion": 2, "requires": true, "packages": { "": { - "name": "@rbxts/tina", + "name": "tina", "version": "1.0.0", "license": "ISC", "dependencies": { "@eslint/github-action": "^0.1.0", + "@rbxts/roact": "^1.4.4-ts.0", + "@rbxts/roact-hooked": "^2.1.3", + "@rbxts/roact-rodux-hooked": "^1.1.3", + "@rbxts/rodux": "^3.0.0-ts.3", + "@rbxts/rowind-mini": "^1.0.0", "@rbxts/services": "^1.5.1", "roblox-ts": "^2.0.4" }, @@ -524,11 +529,119 @@ "integrity": "sha512-kRdXA7RzIUnLrQhjvVLQ//9Nwfndlui43Frqg3k8xrPVz+QJNIqzwx6LHLSwq4c1OBZpYcGgUWIQJkuKxwlskA==", "dev": true }, + "node_modules/@rbxts/flipper": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@rbxts/flipper/-/flipper-2.0.1.tgz", + "integrity": "sha512-kxb5AZizP05XSmo3waS/QkcfNMD5b6HX4gGwyHOyBow260R5MIT4L/ZUPLvleXXyb9b67X4NVmHoac1tPXOLNA==" + }, + "node_modules/@rbxts/log": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/@rbxts/log/-/log-0.6.3.tgz", + "integrity": "sha512-YZpDvjL7yif9aYuNAkuM9vnegcwQmOwX0CfvGfWvrzCpmARY4Ey2pTMhoEgxKo36HcdPPi3aLxmcuvn0NHrPPg==", + "dependencies": { + "@rbxts/message-templates": "^0.3.1" + } + }, + "node_modules/@rbxts/maid": { + "version": "1.0.0-ts.1", + "resolved": "https://registry.npmjs.org/@rbxts/maid/-/maid-1.0.0-ts.1.tgz", + "integrity": "sha512-nm4eucrDE5NnpkHJaaZvMwFJjk9YLAXrLYyA/MWXHI8vr7jeGHmex1N2b90ewa9KqeH+RiWlkXmj2xBALonC4Q==" + }, + "node_modules/@rbxts/message-templates": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@rbxts/message-templates/-/message-templates-0.3.2.tgz", + "integrity": "sha512-79onYskH3pgrBT73Zs+biQ31vAVvupKQaxGNWGjyGsxwNhO2YaN/qkut0bvOshaGa+ZzqAXApRVrN8ifIMPiMQ==" + }, + "node_modules/@rbxts/net": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@rbxts/net/-/net-3.0.3.tgz", + "integrity": "sha512-sceVEOU+XcFZm7STWTUWzk9IZmdTC7WljSzzJAdMxbbCOxa0f39cfk29RwadI6UxTYb39qLPY36sDEPNWZ1pMw==" + }, + "node_modules/@rbxts/object-utils": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@rbxts/object-utils/-/object-utils-1.0.4.tgz", + "integrity": "sha512-dLLhf022ipV+9i910sOE7kl9losKHoon0WgeerHqVMQA5EYsLUsVT2AxhJuhk8MiDn5oJ2GiFofE/LadY9TpJQ==" + }, + "node_modules/@rbxts/roact": { + "version": "1.4.4-ts.0", + "resolved": "https://registry.npmjs.org/@rbxts/roact/-/roact-1.4.4-ts.0.tgz", + "integrity": "sha512-gn9mBoGG/Clzgv2kyOvLNVd9dh5t6z+jukC3ITv2HnfPqvf/sMbz/VMaBoiB7t5umuiIe0LjW0ctZrkrS+uTOA==" + }, + "node_modules/@rbxts/roact-hooked": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@rbxts/roact-hooked/-/roact-hooked-2.1.3.tgz", + "integrity": "sha512-CPwpNknhqBnDJF86ekZasRfPjpnQ/7YdlpKl7RlnGkBOaknOVjie6NvHT1slKJDkCFK5Vb3VreE3uNehAtOubQ==", + "peerDependencies": { + "@rbxts/roact": "*" + } + }, + "node_modules/@rbxts/roact-hooks": { + "version": "0.3.0-ts.2", + "resolved": "https://registry.npmjs.org/@rbxts/roact-hooks/-/roact-hooks-0.3.0-ts.2.tgz", + "integrity": "sha512-k8rbqVAp9ZCIJ5EG/dY/UoQsN66o8s/Yc8GvDRqXkacGbf8u0In0ktyatXE3QZUljFf5IUyiBZuaSbbqGdnDfg==" + }, + "node_modules/@rbxts/roact-rodux-hooked": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@rbxts/roact-rodux-hooked/-/roact-rodux-hooked-1.1.3.tgz", + "integrity": "sha512-Ino1CQmbkvn3WwQa74IKjfKeHm3Pr51CJNvV5KLeuzyrevKaJbjntYMu6gnALCJmmA4zsH309TOl0j69RHBA7A==", + "peerDependencies": { + "@rbxts/roact": "*", + "@rbxts/roact-hooked": "^2.0.0" + } + }, + "node_modules/@rbxts/rodux": { + "version": "3.0.0-ts.3", + "resolved": "https://registry.npmjs.org/@rbxts/rodux/-/rodux-3.0.0-ts.3.tgz", + "integrity": "sha512-LrLowiF1YL5U+lQheCNMo8sbrSEoZAIlVFOGB7Edjein5TtZAeNgyJrhY5yFH5gAfJQzFRnZWVOxWFaMlD0GRg==" + }, + "node_modules/@rbxts/rowind-mini": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@rbxts/rowind-mini/-/rowind-mini-1.0.0.tgz", + "integrity": "sha512-VhuQVlWtQdd84dIraN/Kgssi5fDb0D6jhFSRIgq5urhcKe2oRUrFcq4YzqZWQjBQZSXR35InsmNbPOsWX07J2A==", + "dependencies": { + "@rbxts/log": "^0.6.3", + "@rbxts/object-utils": "^1.0.4", + "@rbxts/roact": "^1.4.4-ts.0", + "@rbxts/services": "^1.5.1", + "@rbxts/zircon": "^1.0.9" + } + }, + "node_modules/@rbxts/rust-classes": { + "version": "0.11.0-beta.1", + "resolved": "https://registry.npmjs.org/@rbxts/rust-classes/-/rust-classes-0.11.0-beta.1.tgz", + "integrity": "sha512-lZiXBIohK3fg3ImqQ0P+lRNp9EKeSXK4kA3yVf5Tc5bwQVyS6/O5XvlUeh4s7wRYcure+fd8s0qISQ7DP5Gw0Q==" + }, "node_modules/@rbxts/services": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/@rbxts/services/-/services-1.5.1.tgz", "integrity": "sha512-SRtfIjga0K4YYSXRpK+eH3kcTq7ZXo9OHOt0jszaOOoEOIJloMGlyuRPqesPHyhveh2AMXAZr3TYbRMSD+u+kQ==" }, + "node_modules/@rbxts/signal": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@rbxts/signal/-/signal-1.1.1.tgz", + "integrity": "sha512-WX+ONE+ld4pG9PvRkR8OgDld9NpaV1RfXyUIw+Q2oXP/5rehkYzvt20NWtrLAP3NhMc5inYInLd+hnufey6nFw==" + }, + "node_modules/@rbxts/snapdragon": { + "version": "2.0.0-beta.1", + "resolved": "https://registry.npmjs.org/@rbxts/snapdragon/-/snapdragon-2.0.0-beta.1.tgz", + "integrity": "sha512-cN2Qgg2Z+Tj5FZGXLFOrBz/QYq92du1al/vnLGtv7WDOb4SmhfQ8tNVCC4Jh/OBdmZuRYp/t07QSjKgYmolnlA==" + }, + "node_modules/@rbxts/string-utils": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rbxts/string-utils/-/string-utils-1.0.3.tgz", + "integrity": "sha512-nsZsPdGsrsBdwLg7qQ5RGHoVhfvK+U3GvZ/6S+7KufqaFrbHWk2lufESob/C3xYf5sAeXgTJKWUnDJknYBGTIQ==" + }, + "node_modules/@rbxts/t": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@rbxts/t/-/t-1.3.5.tgz", + "integrity": "sha512-Z1Lt7DhxQ/FwNgGhKSibHqT5FxgR+QwOF/v9DZN8bP8mJbqtlXwjd8gunL06DKO5xPMWlpbs9fMIgpMI4cl7zQ==", + "dependencies": { + "@rbxts/types": "^1.0.317" + }, + "peerDependencies": { + "@rbxts/types": "^1.0.232" + } + }, "node_modules/@rbxts/testez": { "version": "0.4.2-ts.0", "resolved": "https://registry.npmjs.org/@rbxts/testez/-/testez-0.4.2-ts.0.tgz", @@ -538,8 +651,66 @@ "node_modules/@rbxts/types": { "version": "1.0.647", "resolved": "https://registry.npmjs.org/@rbxts/types/-/types-1.0.647.tgz", - "integrity": "sha512-PCBQNTc/k7vjAFgJB7Z3ixFSAxbTQrb6Klc8mWElPlcO9UxQ7Juxjdv0StYEqZ0dzqktaBSdTQJLtCXoqYVNPg==", - "dev": true + "integrity": "sha512-PCBQNTc/k7vjAFgJB7Z3ixFSAxbTQrb6Klc8mWElPlcO9UxQ7Juxjdv0StYEqZ0dzqktaBSdTQJLtCXoqYVNPg==" + }, + "node_modules/@rbxts/zircon": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@rbxts/zircon/-/zircon-1.0.9.tgz", + "integrity": "sha512-+1Ls5UmKRzD/9/Ms3EmTetHKoMg4gv8GfqWSfETmxheppKAB0CQ/hlwjge3eIXCVfhMURcHZbQtS2n3GzE9TuQ==", + "dependencies": { + "@rbxts/flipper": "^2.0.1", + "@rbxts/log": "0.5.0-beta.1", + "@rbxts/maid": "^1.0.0-ts.1", + "@rbxts/message-templates": "^0.3.2", + "@rbxts/net": "^3.0.0-alpha.0", + "@rbxts/roact": ">=1.4.0-ts >= 1.4.1-ts >= 1.4.2-ts", + "@rbxts/roact-hooks": "=0.3.0-ts.2", + "@rbxts/roact-rodux": "=0.2.2-ts.5", + "@rbxts/rodux": "=3.0.0-ts.3", + "@rbxts/rust-classes": "=0.11.0-beta.1", + "@rbxts/services": "^1.2.0", + "@rbxts/signal": "^1.0.3", + "@rbxts/snapdragon": "2.0.0-beta.1", + "@rbxts/string-utils": "^1.0.3", + "@rbxts/t": "^1.3.5", + "@rbxts/zirconium": "^1.1.0" + } + }, + "node_modules/@rbxts/zircon/node_modules/@rbxts/log": { + "version": "0.5.0-beta.1", + "resolved": "https://registry.npmjs.org/@rbxts/log/-/log-0.5.0-beta.1.tgz", + "integrity": "sha512-MUVwRNTWU6bWMgehihaeTHF58s93AEHt1X+s8jF8+MdZc4hefZ6rT4b5OmskEoWw2r8niVKBCqjPXOGmnDj8xA==", + "dependencies": { + "@rbxts/message-templates": "^0.3.1" + } + }, + "node_modules/@rbxts/zircon/node_modules/@rbxts/roact": { + "version": "1.4.2-ts.3", + "resolved": "https://registry.npmjs.org/@rbxts/roact/-/roact-1.4.2-ts.3.tgz", + "integrity": "sha512-ViS9Tu0gzRdAnOc64CplMKKOG/ISdS7AwgOd+4ld+O3f4N0fPOuxY/sIZ/67fMxH9Isu1r4A6wyg5F5YkK2csA==" + }, + "node_modules/@rbxts/zircon/node_modules/@rbxts/roact-rodux": { + "version": "0.2.2-ts.5", + "resolved": "https://registry.npmjs.org/@rbxts/roact-rodux/-/roact-rodux-0.2.2-ts.5.tgz", + "integrity": "sha512-WzWpKuZLeUEKJG7dR8Zog1MKQlvz6zA2/GhF0N0wkzvZll2CU8CfhKFRHkMwkLjBLSe69sKDveYo+hBjN3Zl+Q==", + "peerDependencies": { + "@rbxts/roact": "1.4.0-ts.0", + "@rbxts/rodux": "3.0.0-ts.3", + "@rbxts/types": "^1.0.503" + } + }, + "node_modules/@rbxts/zirconium": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rbxts/zirconium/-/zirconium-1.1.0.tgz", + "integrity": "sha512-Yvs4H1JaQyUogrmp5mbKnkyhUsOxquyEXKPq9E3bovo17sQbgcsfmO9sfXvan3H5OObVziPjuoX3/nrmUML/Ww==", + "dependencies": { + "@rbxts/rust-classes": "^0.10.0" + } + }, + "node_modules/@rbxts/zirconium/node_modules/@rbxts/rust-classes": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@rbxts/rust-classes/-/rust-classes-0.10.0.tgz", + "integrity": "sha512-U2YhOLG9dDwVOmMTgjzGcoM2yk0mcJ/Y6Fmu6RUVM2y9XHGly6bWsjK7o3uaI4CDMfYZNKF2MkELIBeyFyEJ2Q==" }, "node_modules/@roblox-ts/luau-ast": { "version": "1.0.3", @@ -3383,11 +3554,111 @@ "integrity": "sha512-kRdXA7RzIUnLrQhjvVLQ//9Nwfndlui43Frqg3k8xrPVz+QJNIqzwx6LHLSwq4c1OBZpYcGgUWIQJkuKxwlskA==", "dev": true }, + "@rbxts/flipper": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@rbxts/flipper/-/flipper-2.0.1.tgz", + "integrity": "sha512-kxb5AZizP05XSmo3waS/QkcfNMD5b6HX4gGwyHOyBow260R5MIT4L/ZUPLvleXXyb9b67X4NVmHoac1tPXOLNA==" + }, + "@rbxts/log": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/@rbxts/log/-/log-0.6.3.tgz", + "integrity": "sha512-YZpDvjL7yif9aYuNAkuM9vnegcwQmOwX0CfvGfWvrzCpmARY4Ey2pTMhoEgxKo36HcdPPi3aLxmcuvn0NHrPPg==", + "requires": { + "@rbxts/message-templates": "^0.3.1" + } + }, + "@rbxts/maid": { + "version": "1.0.0-ts.1", + "resolved": "https://registry.npmjs.org/@rbxts/maid/-/maid-1.0.0-ts.1.tgz", + "integrity": "sha512-nm4eucrDE5NnpkHJaaZvMwFJjk9YLAXrLYyA/MWXHI8vr7jeGHmex1N2b90ewa9KqeH+RiWlkXmj2xBALonC4Q==" + }, + "@rbxts/message-templates": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@rbxts/message-templates/-/message-templates-0.3.2.tgz", + "integrity": "sha512-79onYskH3pgrBT73Zs+biQ31vAVvupKQaxGNWGjyGsxwNhO2YaN/qkut0bvOshaGa+ZzqAXApRVrN8ifIMPiMQ==" + }, + "@rbxts/net": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@rbxts/net/-/net-3.0.3.tgz", + "integrity": "sha512-sceVEOU+XcFZm7STWTUWzk9IZmdTC7WljSzzJAdMxbbCOxa0f39cfk29RwadI6UxTYb39qLPY36sDEPNWZ1pMw==" + }, + "@rbxts/object-utils": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@rbxts/object-utils/-/object-utils-1.0.4.tgz", + "integrity": "sha512-dLLhf022ipV+9i910sOE7kl9losKHoon0WgeerHqVMQA5EYsLUsVT2AxhJuhk8MiDn5oJ2GiFofE/LadY9TpJQ==" + }, + "@rbxts/roact": { + "version": "1.4.4-ts.0", + "resolved": "https://registry.npmjs.org/@rbxts/roact/-/roact-1.4.4-ts.0.tgz", + "integrity": "sha512-gn9mBoGG/Clzgv2kyOvLNVd9dh5t6z+jukC3ITv2HnfPqvf/sMbz/VMaBoiB7t5umuiIe0LjW0ctZrkrS+uTOA==" + }, + "@rbxts/roact-hooked": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@rbxts/roact-hooked/-/roact-hooked-2.1.3.tgz", + "integrity": "sha512-CPwpNknhqBnDJF86ekZasRfPjpnQ/7YdlpKl7RlnGkBOaknOVjie6NvHT1slKJDkCFK5Vb3VreE3uNehAtOubQ==", + "requires": {} + }, + "@rbxts/roact-hooks": { + "version": "0.3.0-ts.2", + "resolved": "https://registry.npmjs.org/@rbxts/roact-hooks/-/roact-hooks-0.3.0-ts.2.tgz", + "integrity": "sha512-k8rbqVAp9ZCIJ5EG/dY/UoQsN66o8s/Yc8GvDRqXkacGbf8u0In0ktyatXE3QZUljFf5IUyiBZuaSbbqGdnDfg==" + }, + "@rbxts/roact-rodux-hooked": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@rbxts/roact-rodux-hooked/-/roact-rodux-hooked-1.1.3.tgz", + "integrity": "sha512-Ino1CQmbkvn3WwQa74IKjfKeHm3Pr51CJNvV5KLeuzyrevKaJbjntYMu6gnALCJmmA4zsH309TOl0j69RHBA7A==", + "requires": {} + }, + "@rbxts/rodux": { + "version": "3.0.0-ts.3", + "resolved": "https://registry.npmjs.org/@rbxts/rodux/-/rodux-3.0.0-ts.3.tgz", + "integrity": "sha512-LrLowiF1YL5U+lQheCNMo8sbrSEoZAIlVFOGB7Edjein5TtZAeNgyJrhY5yFH5gAfJQzFRnZWVOxWFaMlD0GRg==" + }, + "@rbxts/rowind-mini": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@rbxts/rowind-mini/-/rowind-mini-1.0.0.tgz", + "integrity": "sha512-VhuQVlWtQdd84dIraN/Kgssi5fDb0D6jhFSRIgq5urhcKe2oRUrFcq4YzqZWQjBQZSXR35InsmNbPOsWX07J2A==", + "requires": { + "@rbxts/log": "^0.6.3", + "@rbxts/object-utils": "^1.0.4", + "@rbxts/roact": "^1.4.4-ts.0", + "@rbxts/services": "^1.5.1", + "@rbxts/zircon": "^1.0.9" + } + }, + "@rbxts/rust-classes": { + "version": "0.11.0-beta.1", + "resolved": "https://registry.npmjs.org/@rbxts/rust-classes/-/rust-classes-0.11.0-beta.1.tgz", + "integrity": "sha512-lZiXBIohK3fg3ImqQ0P+lRNp9EKeSXK4kA3yVf5Tc5bwQVyS6/O5XvlUeh4s7wRYcure+fd8s0qISQ7DP5Gw0Q==" + }, "@rbxts/services": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/@rbxts/services/-/services-1.5.1.tgz", "integrity": "sha512-SRtfIjga0K4YYSXRpK+eH3kcTq7ZXo9OHOt0jszaOOoEOIJloMGlyuRPqesPHyhveh2AMXAZr3TYbRMSD+u+kQ==" }, + "@rbxts/signal": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@rbxts/signal/-/signal-1.1.1.tgz", + "integrity": "sha512-WX+ONE+ld4pG9PvRkR8OgDld9NpaV1RfXyUIw+Q2oXP/5rehkYzvt20NWtrLAP3NhMc5inYInLd+hnufey6nFw==" + }, + "@rbxts/snapdragon": { + "version": "2.0.0-beta.1", + "resolved": "https://registry.npmjs.org/@rbxts/snapdragon/-/snapdragon-2.0.0-beta.1.tgz", + "integrity": "sha512-cN2Qgg2Z+Tj5FZGXLFOrBz/QYq92du1al/vnLGtv7WDOb4SmhfQ8tNVCC4Jh/OBdmZuRYp/t07QSjKgYmolnlA==" + }, + "@rbxts/string-utils": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rbxts/string-utils/-/string-utils-1.0.3.tgz", + "integrity": "sha512-nsZsPdGsrsBdwLg7qQ5RGHoVhfvK+U3GvZ/6S+7KufqaFrbHWk2lufESob/C3xYf5sAeXgTJKWUnDJknYBGTIQ==" + }, + "@rbxts/t": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@rbxts/t/-/t-1.3.5.tgz", + "integrity": "sha512-Z1Lt7DhxQ/FwNgGhKSibHqT5FxgR+QwOF/v9DZN8bP8mJbqtlXwjd8gunL06DKO5xPMWlpbs9fMIgpMI4cl7zQ==", + "requires": { + "@rbxts/types": "^1.0.317" + } + }, "@rbxts/testez": { "version": "0.4.2-ts.0", "resolved": "https://registry.npmjs.org/@rbxts/testez/-/testez-0.4.2-ts.0.tgz", @@ -3397,8 +3668,66 @@ "@rbxts/types": { "version": "1.0.647", "resolved": "https://registry.npmjs.org/@rbxts/types/-/types-1.0.647.tgz", - "integrity": "sha512-PCBQNTc/k7vjAFgJB7Z3ixFSAxbTQrb6Klc8mWElPlcO9UxQ7Juxjdv0StYEqZ0dzqktaBSdTQJLtCXoqYVNPg==", - "dev": true + "integrity": "sha512-PCBQNTc/k7vjAFgJB7Z3ixFSAxbTQrb6Klc8mWElPlcO9UxQ7Juxjdv0StYEqZ0dzqktaBSdTQJLtCXoqYVNPg==" + }, + "@rbxts/zircon": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@rbxts/zircon/-/zircon-1.0.9.tgz", + "integrity": "sha512-+1Ls5UmKRzD/9/Ms3EmTetHKoMg4gv8GfqWSfETmxheppKAB0CQ/hlwjge3eIXCVfhMURcHZbQtS2n3GzE9TuQ==", + "requires": { + "@rbxts/flipper": "^2.0.1", + "@rbxts/log": "0.5.0-beta.1", + "@rbxts/maid": "^1.0.0-ts.1", + "@rbxts/message-templates": "^0.3.2", + "@rbxts/net": "^3.0.0-alpha.0", + "@rbxts/roact": ">=1.4.0-ts >= 1.4.1-ts >= 1.4.2-ts", + "@rbxts/roact-hooks": "=0.3.0-ts.2", + "@rbxts/roact-rodux": "=0.2.2-ts.5", + "@rbxts/rodux": "=3.0.0-ts.3", + "@rbxts/rust-classes": "=0.11.0-beta.1", + "@rbxts/services": "^1.2.0", + "@rbxts/signal": "^1.0.3", + "@rbxts/snapdragon": "2.0.0-beta.1", + "@rbxts/string-utils": "^1.0.3", + "@rbxts/t": "^1.3.5", + "@rbxts/zirconium": "^1.1.0" + }, + "dependencies": { + "@rbxts/log": { + "version": "0.5.0-beta.1", + "resolved": "https://registry.npmjs.org/@rbxts/log/-/log-0.5.0-beta.1.tgz", + "integrity": "sha512-MUVwRNTWU6bWMgehihaeTHF58s93AEHt1X+s8jF8+MdZc4hefZ6rT4b5OmskEoWw2r8niVKBCqjPXOGmnDj8xA==", + "requires": { + "@rbxts/message-templates": "^0.3.1" + } + }, + "@rbxts/roact": { + "version": "1.4.2-ts.3", + "resolved": "https://registry.npmjs.org/@rbxts/roact/-/roact-1.4.2-ts.3.tgz", + "integrity": "sha512-ViS9Tu0gzRdAnOc64CplMKKOG/ISdS7AwgOd+4ld+O3f4N0fPOuxY/sIZ/67fMxH9Isu1r4A6wyg5F5YkK2csA==" + }, + "@rbxts/roact-rodux": { + "version": "0.2.2-ts.5", + "resolved": "https://registry.npmjs.org/@rbxts/roact-rodux/-/roact-rodux-0.2.2-ts.5.tgz", + "integrity": "sha512-WzWpKuZLeUEKJG7dR8Zog1MKQlvz6zA2/GhF0N0wkzvZll2CU8CfhKFRHkMwkLjBLSe69sKDveYo+hBjN3Zl+Q==", + "requires": {} + } + } + }, + "@rbxts/zirconium": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rbxts/zirconium/-/zirconium-1.1.0.tgz", + "integrity": "sha512-Yvs4H1JaQyUogrmp5mbKnkyhUsOxquyEXKPq9E3bovo17sQbgcsfmO9sfXvan3H5OObVziPjuoX3/nrmUML/Ww==", + "requires": { + "@rbxts/rust-classes": "^0.10.0" + }, + "dependencies": { + "@rbxts/rust-classes": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@rbxts/rust-classes/-/rust-classes-0.10.0.tgz", + "integrity": "sha512-U2YhOLG9dDwVOmMTgjzGcoM2yk0mcJ/Y6Fmu6RUVM2y9XHGly6bWsjK7o3uaI4CDMfYZNKF2MkELIBeyFyEJ2Q==" + } + } }, "@roblox-ts/luau-ast": { "version": "1.0.3", diff --git a/package.json b/package.json index 309a932..88cb5a7 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "@rbxts/tina", + "name": "tina", "version": "1.0.0", "description": "", "main": "out/init.lua", @@ -45,7 +45,12 @@ }, "dependencies": { "@eslint/github-action": "^0.1.0", + "@rbxts/roact": "^1.4.4-ts.0", + "@rbxts/roact-hooked": "^2.1.3", + "@rbxts/roact-rodux-hooked": "^1.1.3", + "@rbxts/rodux": "^3.0.0-ts.3", + "@rbxts/rowind-mini": "^1.0.0", "@rbxts/services": "^1.5.1", "roblox-ts": "^2.0.4" } -} \ No newline at end of file +} diff --git a/src/index.ts b/src/index.ts index cf7eed8..f9acbfd 100644 --- a/src/index.ts +++ b/src/index.ts @@ -14,6 +14,10 @@ import Scheduler from "./lib/process/scheduler"; import { Users } from "./lib/user"; import { AbstractUser } from "./lib/user/default"; import { UserType } from "./lib/user/default/types"; +/* User abstraction class */ +import { ConsoleActionName } from "./lib/user-interface/console/console-actions"; +import { ClientStore } from "./lib/user-interface/store"; +import { formatFlareTraceback } from "./lib/utilities/string-utils"; export enum Protocol { /** Create/Load Online User Data */ @@ -48,8 +52,6 @@ namespace Tina { Identifiers._init(); } - Logger.setName(name); - // TODO: Auto-Detect `manifest.tina.yml` and load it. return new TinaGame(); } @@ -81,8 +83,6 @@ namespace Tina { */ export function setUserClass(userClass: new (ref: Player | number) => UserType): void { Users.changeUserClass(userClass); // Changes internally the way user is defined and constructed - - Logger.warn("The User Class has been changed to:", userClass); // Not sure why this is being warned at all. } /** @@ -106,7 +106,18 @@ namespace Tina { return new Process(name, Scheduler); } - export const Logger = new Scope("unnamed"); + export function flare(eventName: string): void { + ClientStore.dispatch({ type: ConsoleActionName.AddFlare, eventName }); + } + + export function oops(eventName: string): void { + const message = formatFlareTraceback(debug.traceback(undefined, 1)); + ClientStore.dispatch({ type: ConsoleActionName.FireFlare, eventName, message }); + } + + export function getLogger(): void { + return; + } /** * Used to connect to Tina's internal events, such as when a user is registed, etc. diff --git a/src/lib/types/common.d.ts b/src/lib/types/common.d.ts new file mode 100644 index 0000000..14fdc6f --- /dev/null +++ b/src/lib/types/common.d.ts @@ -0,0 +1,2 @@ +export type IFlare = { eventName: string; amount: number; message?: string }; +export type EnumOrName = T | T["Name"]; diff --git a/src/lib/ui/console/console.story.tsx b/src/lib/ui/console/console.story.tsx new file mode 100644 index 0000000..8f815fe --- /dev/null +++ b/src/lib/ui/console/console.story.tsx @@ -0,0 +1,16 @@ +import Roact from "@rbxts/roact"; +import { Div } from "@rbxts/rowind-mini"; + +export = function (parent: Instance) { + const UI = ( +
+
+
+ ); + + const MountedUI = Roact.mount(UI, parent); + + return function () { + Roact.unmount(MountedUI); + }; +}; diff --git a/src/lib/user-interface/common/padding.tsx b/src/lib/user-interface/common/padding.tsx new file mode 100644 index 0000000..1360493 --- /dev/null +++ b/src/lib/user-interface/common/padding.tsx @@ -0,0 +1,32 @@ +import Roact from "@rbxts/roact"; + +interface Props { + All?: number; + Horizontal?: number; + Vertical?: number; + Top?: number; + Bottom?: number; + Left?: number; + Right?: number; +} + +const Padding: Roact.FunctionComponent = ({ + All = 0, + Horizontal = 0, + Vertical = 0, + Top = 0, + Bottom = 0, + Right = 0, + Left = 0, +}: Props) => { + return ( + + ); +}; + +export default Padding; diff --git a/src/lib/user-interface/console/components/circle.tsx b/src/lib/user-interface/console/components/circle.tsx new file mode 100644 index 0000000..3c7ff72 --- /dev/null +++ b/src/lib/user-interface/console/components/circle.tsx @@ -0,0 +1,15 @@ +import Roact, { JsxInstanceProperties } from "@rbxts/roact"; +import { withHooks } from "@rbxts/roact-hooked"; + +type CircleProps = JsxInstanceProperties; + +const Circle = withHooks((props: CircleProps) => { + return ( + + + + + ); +}); + +export default Circle; diff --git a/src/lib/user-interface/console/components/console.tsx b/src/lib/user-interface/console/components/console.tsx new file mode 100644 index 0000000..f76582d --- /dev/null +++ b/src/lib/user-interface/console/components/console.tsx @@ -0,0 +1,14 @@ +import Roact from "@rbxts/roact"; +import { withHooks } from "@rbxts/roact-hooked"; + +import Header from "./header"; + +const Console = withHooks(() => { + return ( + +
+ + ); +}); + +export default Console; diff --git a/src/lib/user-interface/console/components/flare-bar.tsx b/src/lib/user-interface/console/components/flare-bar.tsx new file mode 100644 index 0000000..b508d45 --- /dev/null +++ b/src/lib/user-interface/console/components/flare-bar.tsx @@ -0,0 +1,47 @@ +import Roact, { JsxInstanceProperties } from "@rbxts/roact"; +import { useCallback, useState, withHooks } from "@rbxts/roact-hooked"; +import { useSelector } from "@rbxts/roact-rodux-hooked"; + +import { IFlare } from "../../../types/common"; +import Padding from "../../common/padding"; +import { StoreState } from "../../store"; +import Flare from "./flare"; + +type FlareBarProps = Partial, "Position" | "AnchorPoint" | "Size">>; + +export const FlareBar = withHooks((props: FlareBarProps) => { + const { Size = new UDim2(1, 0, 0, 36) } = props; + const flares = useSelector((state: StoreState) => state.flares); + const [selected, setSelected] = useState(); + + const handleClick = useCallback((flare: IFlare) => { + setSelected(selected => { + if (flare.amount === 0) return; + return flare === selected ? undefined : flare; + }); + }, []); + + return ( + + + + {flares.map((flare, i) => ( + + ))} + + ); +}); diff --git a/src/lib/user-interface/console/components/flare.tsx b/src/lib/user-interface/console/components/flare.tsx new file mode 100644 index 0000000..8dfa15b --- /dev/null +++ b/src/lib/user-interface/console/components/flare.tsx @@ -0,0 +1,65 @@ +import Roact, { Element } from "@rbxts/roact"; +import { useRef, withHooksPure } from "@rbxts/roact-hooked"; +import { TextService } from "@rbxts/services"; + +import { IFlare } from "../../../types/common"; +import { getAbsolutePosition } from "../../../utilities/hoarcekat"; +import Padding from "../../common/padding"; +import { useTheme } from "../../theme/theme"; +import Circle from "./circle"; +import Tooltip from "./tooltip"; + +interface Props { + Info: IFlare; + Selected: boolean; + OnClick: (flare: IFlare) => void; +} + +const Flare = withHooksPure(({ Info, Selected, OnClick }: Props) => { + const { eventName, amount, message } = Info; + const theme = useTheme(); + const buttonRef = useRef(); + + const text = `${eventName} ${amount}x`; + const textSize = TextService.GetTextSize(text, theme.FontSize, theme.Font, new Vector2(math.huge, math.huge)); + const circleColour = amount > 0 ? Color3.fromRGB(255, 18, 18) : Color3.fromRGB(18, 18, 255); + + let tooltip: Element | undefined; + if (Selected) { + const button = buttonRef.getValue()!; + const { X: positionX, Y: positionY } = getAbsolutePosition(button); + const { Y: sizeY } = button.AbsoluteSize; + const tooltipPosition = UDim2.fromOffset(positionX - 3, positionY + sizeY + 8); + tooltip = ; + } + + return ( + OnClick(Info), + }} + > + + + + + + + {tooltip} + + ); +}); + +export default Flare; diff --git a/src/lib/user-interface/console/components/header.tsx b/src/lib/user-interface/console/components/header.tsx new file mode 100644 index 0000000..cda1948 --- /dev/null +++ b/src/lib/user-interface/console/components/header.tsx @@ -0,0 +1,21 @@ +import Roact from "@rbxts/roact"; +import { withHooksPure } from "@rbxts/roact-hooked"; + +import { useTheme } from "../../theme/theme"; +import { FlareBar } from "./flare-bar"; + +const Header = withHooksPure(() => { + const theme = useTheme(); + + return ( + + + + ); +}); + +export default Header; diff --git a/src/lib/user-interface/console/components/modal.tsx b/src/lib/user-interface/console/components/modal.tsx new file mode 100644 index 0000000..c0647cc --- /dev/null +++ b/src/lib/user-interface/console/components/modal.tsx @@ -0,0 +1,57 @@ +/// + +import Roact, { Children, Portal } from "@rbxts/roact"; +import { withHooks } from "@rbxts/roact-hooked"; +import { Players, RunService } from "@rbxts/services"; + +import { hoarcekatFrame } from "../../../utilities/hoarcekat"; + +const isGameRunning = RunService.IsRunning(); + +/** + * Modal which can be used with .story scripts. Generally a modal will be added directly to the PlayerGui, but + * since .story scripts are ran inside studio PlayerGui won't exists. Instead, we'll parent the modal directly + * to Hoarcekat's preview window, simulating a modal without running the game. + * + * This is not perfect as the AbsolutePosition of the preview window is about (154, 5) rather than (0, 0), so + * the position may be skewed when positioning components absolutely. But it's better than the component erroring. + */ +const HoarcekatModal = withHooks(props => { + const parent = hoarcekatFrame; + if (!parent) { + warn("Unable to find Hoarcekat preview window"); + return ; + } + + const made = ( + + + {props[Children]} + + + ); + + return made; +}); + +/** + * Modal which parents itself to the PlayerGui and renders children in a separate ScreenGui + */ +const GameRunningModal = withHooks(props => { + const playerGui = Players.LocalPlayer.FindFirstChildOfClass("PlayerGui")!; + return ( + + {props[Children]} + + ); +}); + +const Modal = withHooks(props => { + return isGameRunning ? ( + {props[Children]} + ) : ( + {props[Children]} + ); +}); + +export default Modal; diff --git a/src/lib/user-interface/console/components/tooltip.tsx b/src/lib/user-interface/console/components/tooltip.tsx new file mode 100644 index 0000000..4e9d550 --- /dev/null +++ b/src/lib/user-interface/console/components/tooltip.tsx @@ -0,0 +1,67 @@ +import Roact, { createRef } from "@rbxts/roact"; +import { useBinding, useEffect, withHooks } from "@rbxts/roact-hooked"; + +import { UDim2ToAbsolute } from "../../../utilities/ui"; +import Padding from "../../common/padding"; +import { useTheme } from "../../theme/theme"; +import Modal from "./modal"; + +interface TooltipProps { + Message?: string; + Position?: UDim2; +} + +const Tooltip = withHooks(({ Message, Position = new UDim2() }: TooltipProps) => { + const theme = useTheme(); + const labelRef = createRef(); + const [labelPosition, setLabelPosition] = useBinding(Position); + + // Reposition the tooltip within the bounds of the Modal (screen) + useEffect(() => { + const label = labelRef.getValue()!; + if (!label) return; + const parent = label.Parent as GuiBase2d; + + const constrainToWindow = (): void => { + const maxSize = parent.AbsoluteSize; + const size = label.AbsoluteSize; + const targetPosition = UDim2ToAbsolute(Position, maxSize); + + const constrainX = (): number => { + const max = maxSize.X; + const min = 0; + return math.clamp(targetPosition.X, min, math.max(max - size.X, min)); + }; + + setLabelPosition(UDim2.fromOffset(constrainX(), targetPosition.Y)); + }; + + const connection = parent.GetPropertyChangedSignal("AbsoluteSize").Connect(constrainToWindow); + constrainToWindow(); + + return () => { + connection.Disconnect(); + }; + }, []); + + return ( + + + + + + ); +}); + +export default Tooltip; diff --git a/src/lib/user-interface/console/console-actions.ts b/src/lib/user-interface/console/console-actions.ts new file mode 100644 index 0000000..adf3f1c --- /dev/null +++ b/src/lib/user-interface/console/console-actions.ts @@ -0,0 +1,22 @@ +import { Action } from "@rbxts/rodux"; + +export enum ConsoleActionName { + SetConsoleVisible = "SetConsoleVisible", + AddFlare = "AddFlare", + FireFlare = "FireFlare", +} + +export interface ActionSetConsoleVisible extends Action { + visible: boolean; +} + +export interface ActionAddFlare extends Action { + eventName: string; +} + +export interface ActionFireFlare extends Action { + eventName: string; + message: string; +} + +export type ConsoleActions = ActionSetConsoleVisible | ActionAddFlare | ActionFireFlare; diff --git a/src/lib/user-interface/console/console-reducer.ts b/src/lib/user-interface/console/console-reducer.ts new file mode 100644 index 0000000..95eb650 --- /dev/null +++ b/src/lib/user-interface/console/console-reducer.ts @@ -0,0 +1,49 @@ +import { createReducer } from "@rbxts/rodux"; + +import { IFlare } from "../../types/common"; +import { updateAtIndex } from "../../utilities/rodux-utils"; +import { ConsoleActions } from "./console-actions"; + +export interface ConsoleReducer { + visible: boolean; + flares: Array; +} + +const initialState: ConsoleReducer = { + visible: false, + flares: [], +}; + +export const consoleReducer = createReducer(initialState, { + SetConsoleVisible: (state, action) => ({ ...state, visible: action.visible }), + + AddFlare: (state, action) => { + const { eventName } = action; + const { flares } = state; + + // Check for duplicate flares + const flareExists = flares.find(f => f.eventName === eventName); + if (flareExists !== undefined) return state; + + // Create new flare and add to state + return { + ...state, + flares: [...flares, { eventName, amount: 0 }], + }; + }, + + FireFlare: (state, action) => { + // Get the index of the flare + const flareIndex = state.flares.findIndex(f => f.eventName === action.eventName); + + // Increment the amount of times the flare has been called + return { + ...state, + flares: updateAtIndex(state.flares, flareIndex, flare => ({ + ...flare, + amount: flare.amount + 1, + message: action.message, + })), + }; + }, +}); diff --git a/src/lib/user-interface/console/console.story.tsx b/src/lib/user-interface/console/console.story.tsx new file mode 100644 index 0000000..74f81b9 --- /dev/null +++ b/src/lib/user-interface/console/console.story.tsx @@ -0,0 +1,46 @@ +import Roact, { Children } from "@rbxts/roact"; +import { StoreProvider } from "@rbxts/roact-rodux-hooked"; + +import Tina from "../../.."; +import { ClientStore } from "../store"; +import { ThemeProvider } from "../theme/theme"; +import Console from "./components/console"; + +const Wrapper: Roact.FunctionComponent = ({ [Children]: children }) => { + return ( + + {children} + + ); +}; + +export = (parent: GuiBase2d) => { + const handle = Roact.mount( + + {/* Pretty picture so I can see how transparent the console is */} + + + , + parent, + ); + + // Create flares + Tina.flare("Hello World"); + Tina.flare("Death"); + Tina.flare("Respawn"); + Tina.flare("Eggs and Rice"); + Tina.flare("Remote"); + Tina.flare("Stanky Leg"); + Tina.flare("Lots and lots"); + Tina.flare("Onlytwentycharacters"); + + // Fire some flares + Tina.oops("Hello World"); + Tina.oops("Hello World"); + Tina.oops("Death"); + Tina.oops("Remote"); + + return () => { + Roact.unmount(handle); + }; +}; diff --git a/src/lib/user-interface/store.ts b/src/lib/user-interface/store.ts new file mode 100644 index 0000000..1140cec --- /dev/null +++ b/src/lib/user-interface/store.ts @@ -0,0 +1,10 @@ +import { Store } from "@rbxts/rodux"; + +import { ConsoleActions } from "./console/console-actions"; +import { ConsoleReducer, consoleReducer } from "./console/console-reducer"; + +export type StoreState = ConsoleReducer; +type StoreActions = ConsoleActions; + +export const ClientStore = new Store(consoleReducer); +export type ClientStore = typeof ClientStore; diff --git a/src/lib/user-interface/theme/theme-config.ts b/src/lib/user-interface/theme/theme-config.ts new file mode 100644 index 0000000..d0a129d --- /dev/null +++ b/src/lib/user-interface/theme/theme-config.ts @@ -0,0 +1,17 @@ +import { EnumOrName } from "../../types/common"; + +export interface Theme { + Font: EnumOrName; + FontSize: number; + PrimaryBackgroundColor3: Color3; + SecondaryBackgroundColor3: Color3; + PrimaryTextColor3: Color3; +} + +export const defaultTheme: Theme = { + Font: Enum.Font.Ubuntu, + FontSize: 14, + PrimaryBackgroundColor3: Color3.fromRGB(33, 37, 43), + SecondaryBackgroundColor3: Color3.fromRGB(24, 26, 31), + PrimaryTextColor3: Color3.fromRGB(230, 230, 230), +}; diff --git a/src/lib/user-interface/theme/theme.tsx b/src/lib/user-interface/theme/theme.tsx new file mode 100644 index 0000000..900a1e9 --- /dev/null +++ b/src/lib/user-interface/theme/theme.tsx @@ -0,0 +1,12 @@ +import Roact, { Children } from "@rbxts/roact"; +import { useContext } from "@rbxts/roact-hooked"; + +import { defaultTheme, Theme } from "./theme-config"; + +export const ThemeContext = Roact.createContext(defaultTheme); + +export const ThemeProvider: Roact.FunctionComponent = ({ [Children]: children }) => { + return {children}; +}; + +export const useTheme = (): Theme => useContext(ThemeContext); diff --git a/src/lib/utilities/hoarcekat.ts b/src/lib/utilities/hoarcekat.ts new file mode 100644 index 0000000..a7ca294 --- /dev/null +++ b/src/lib/utilities/hoarcekat.ts @@ -0,0 +1,30 @@ +import { RunService } from "@rbxts/services"; + +/** + * There isn't a reliable way to get Hoarcekat's preview window from a Roact component, so + * instead we will get it from the PluginGuiService since the structure is always the same (for this version). + * @returns Preview frame for Hoarcekat + */ +function findHoarcekatFrame(): Frame | undefined { + return game + .FindFirstChild("PluginGuiService") + ?.FindFirstChild("Hoarcekat") + ?.FindFirstChild("App") + ?.FindFirstChild("Preview") + ?.FindFirstChild("Preview") + ?.FindFirstChild("Preview") as Frame; +} + +// Store these values for later rather than evaluating with every new modal +export const hoarcekatFrame = RunService.IsRunning() ? undefined : findHoarcekatFrame(); + +/** + * Gets the AbsolutePosition of a frame. If the Hoarcekat preview window has been found then the position + * will be offset such that the top left of the preview frame is at (0, 0). + * @param guiObject GuiObject + * @returns The position of the frame relative to the Hoarcekat preview frame + */ +export function getAbsolutePosition(guiObject: GuiObject): Vector2 { + const hoarcekatOffset = hoarcekatFrame ? hoarcekatFrame.AbsolutePosition : Vector2.zero; + return guiObject.AbsolutePosition.sub(hoarcekatOffset); +} diff --git a/src/lib/utilities/rodux-utils.ts b/src/lib/utilities/rodux-utils.ts new file mode 100644 index 0000000..5974155 --- /dev/null +++ b/src/lib/utilities/rodux-utils.ts @@ -0,0 +1,17 @@ +/** + * Helper function to immutably update an array at the given index. + * If the value at the given index does not exist, the original array will be returned. + * @param array The array to update + * @param index The index to update + * @param updater The updater function + * @returns The updated array + */ +export function updateAtIndex(array: Array, index: number, updater: (value: T) => T): Array { + // No value to update + if (array[index] === undefined) return array; + + // Copy array and update value + const copy = table.clone(array); + copy[index] = updater(copy[index]); + return copy; +} diff --git a/src/lib/utilities/string-utils.ts b/src/lib/utilities/string-utils.ts new file mode 100644 index 0000000..6f52c72 --- /dev/null +++ b/src/lib/utilities/string-utils.ts @@ -0,0 +1,19 @@ +export function removeTrailingNewLine(str: string): string { + if (str.sub(-1, -1) === "\n") { + return str.sub(0, -2); + } + return str; +} + +/** + * Formats a traceback string to be displayed by a Flare tooltip + * @param str The traceback + * @returns Formatted string + */ +export function formatFlareTraceback(str: string): string { + let output = str.gsub("^.*function oops\n", "")[0]; // Remove Tina.oops from the traceback + output = str.gsub('%[string "', "[")[0]; // Remove 'string "' from the beginning of the file name + output = str.gsub('"%]', "]")[0]; // Remove the " at the end of the file name + output = removeTrailingNewLine(str); + return output; +} diff --git a/src/lib/utilities/ui.ts b/src/lib/utilities/ui.ts new file mode 100644 index 0000000..2b54e20 --- /dev/null +++ b/src/lib/utilities/ui.ts @@ -0,0 +1,5 @@ +export function UDim2ToAbsolute(udim2: UDim2, size: Vector2): Vector2 { + const x = udim2.X.Scale * size.X + udim2.X.Offset; + const y = udim2.Y.Scale * size.X + udim2.Y.Offset; + return new Vector2(x, y); +} diff --git a/src/services.d.ts b/src/services.d.ts index 8a0e462..6ee1c1d 100644 --- a/src/services.d.ts +++ b/src/services.d.ts @@ -1,7 +1,4 @@ interface ReplicatedStorage extends Instance { include: { node_modules: { "@rbxts": { testez: { src: ModuleScript } } } }; -} - -interface ServerScriptService extends Instance { Package: Folder; } diff --git a/src/testBootstrap.server.ts b/src/testBootstrap.server.ts index 0cbdc7c..77202d4 100644 --- a/src/testBootstrap.server.ts +++ b/src/testBootstrap.server.ts @@ -2,4 +2,4 @@ import type TestEZ from "@rbxts/testez"; const { TestBootstrap } = require(game.GetService("ReplicatedStorage").include.node_modules["@rbxts"].testez .src) as TestEZ; -TestBootstrap.run([game.GetService("ServerScriptService").Package]); // Run tests +TestBootstrap.run([game.GetService("ReplicatedStorage").Package]); // Run tests diff --git a/studio.project.json b/studio.project.json index 32f263d..5e70f7a 100644 --- a/studio.project.json +++ b/studio.project.json @@ -7,21 +7,23 @@ "tree": { "$className": "DataModel", "ReplicatedStorage": { - "include": { - "$path": "include", - "node_modules": { - "$className": "Folder", - "@rbxts": { - "$path": "node_modules/@rbxts" + "Package": { + "$path": "out", + "rbxts_include": { + "$path": "include", + + "node_modules": { + "$className": "Folder", + + "@rbxts": { + "$path": "node_modules/@rbxts" + } } } } }, "ServerScriptService": { "$className": "ServerScriptService", - "Package": { - "$path": "out" - }, "testBootstrap": { "$path": "out/testBootstrap.server.lua" } diff --git a/testez-companion.toml b/testez-companion.toml index ec9b156..e90ff03 100644 --- a/testez-companion.toml +++ b/testez-companion.toml @@ -1,2 +1,2 @@ # These are the locations of your .spec files (descendants are searched too) -roots = ["ServerScriptService/Package"] +roots = ["ReplicatedStorage/Package"] diff --git a/tsconfig.json b/tsconfig.json index c33a9d4..5936cc3 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -7,7 +7,7 @@ "downlevelIteration": true, "jsx": "react", "jsxFactory": "Roact.createElement", - "jsxFragmentFactory": "Roact.Fragment", + "jsxFragmentFactory": "Roact.createFragment", "module": "commonjs", "moduleResolution": "Node", "moduleDetection": "force",