diff --git a/tilda-web/docusaurus.config.ts b/tilda-web/docusaurus.config.ts index 653f652..3d5b6ea 100644 --- a/tilda-web/docusaurus.config.ts +++ b/tilda-web/docusaurus.config.ts @@ -48,6 +48,11 @@ const config: Config = { themeConfig: { // Replace with your project's social card + docs: { + sidebar: { + hideable: true, + }, + }, image: 'img/docusaurus-social-card.jpg', navbar: { title: 'Tilda', @@ -67,9 +72,9 @@ const config: Config = { position: 'right', }, { - href: 'https://tilda.run/generator', - label: 'Generator', + href: '/generator', position: 'left', + label: 'Generator', }, { href: 'https://github.com/BrewInteractive/tilda', diff --git a/tilda-web/package-lock.json b/tilda-web/package-lock.json index 81998ce..4fe7304 100644 --- a/tilda-web/package-lock.json +++ b/tilda-web/package-lock.json @@ -11,7 +11,11 @@ "@docusaurus/core": "3.2.0", "@docusaurus/plugin-content-pages": "^3.3.2", "@docusaurus/preset-classic": "3.2.0", + "@emotion/react": "^11.11.4", + "@emotion/styled": "^11.11.5", "@mdx-js/react": "^3.0.0", + "@mui/icons-material": "^5.15.20", + "@mui/material": "^5.15.20", "clsx": "^2.0.0", "prism-react-renderer": "^2.3.0", "react": "^18.0.0", @@ -3997,6 +4001,186 @@ "node": ">=18.0" } }, + "node_modules/@emotion/babel-plugin": { + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz", + "integrity": "sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==", + "dependencies": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/serialize": "^1.1.2", + "babel-plugin-macros": "^3.1.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/babel-plugin/node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" + }, + "node_modules/@emotion/babel-plugin/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@emotion/cache": { + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.11.0.tgz", + "integrity": "sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==", + "dependencies": { + "@emotion/memoize": "^0.8.1", + "@emotion/sheet": "^1.2.2", + "@emotion/utils": "^1.2.1", + "@emotion/weak-memoize": "^0.3.1", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/hash": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", + "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" + }, + "node_modules/@emotion/is-prop-valid": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz", + "integrity": "sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==", + "dependencies": { + "@emotion/memoize": "^0.8.1" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" + }, + "node_modules/@emotion/react": { + "version": "11.11.4", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.4.tgz", + "integrity": "sha512-t8AjMlF0gHpvvxk5mAtCqR4vmxiGHCeJBaQO6gncUSdklELOgtwjerNY2yuJNfwnc6vi16U/+uMF+afIawJ9iw==", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.11.0", + "@emotion/cache": "^11.11.0", + "@emotion/serialize": "^1.1.3", + "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", + "@emotion/utils": "^1.2.1", + "@emotion/weak-memoize": "^0.3.1", + "hoist-non-react-statics": "^3.3.1" + }, + "peerDependencies": { + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/serialize": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.4.tgz", + "integrity": "sha512-RIN04MBT8g+FnDwgvIUi8czvr1LU1alUMI05LekWB5DGyTm8cCBMCRpq3GqaiyEDRptEXOyXnvZ58GZYu4kBxQ==", + "dependencies": { + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/unitless": "^0.8.1", + "@emotion/utils": "^1.2.1", + "csstype": "^3.0.2" + } + }, + "node_modules/@emotion/sheet": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.2.tgz", + "integrity": "sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==" + }, + "node_modules/@emotion/styled": { + "version": "11.11.5", + "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.11.5.tgz", + "integrity": "sha512-/ZjjnaNKvuMPxcIiUkf/9SHoG4Q196DRl1w82hQ3WCsjo1IUR8uaGWrC6a87CrYAW0Kb/pK7hk8BnLgLRi9KoQ==", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.11.0", + "@emotion/is-prop-valid": "^1.2.2", + "@emotion/serialize": "^1.1.4", + "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", + "@emotion/utils": "^1.2.1" + }, + "peerDependencies": { + "@emotion/react": "^11.0.0-rc.0", + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/unitless": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", + "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==" + }, + "node_modules/@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz", + "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==", + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@emotion/utils": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.1.tgz", + "integrity": "sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==" + }, + "node_modules/@emotion/weak-memoize": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz", + "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==" + }, + "node_modules/@floating-ui/core": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.2.tgz", + "integrity": "sha512-+2XpQV9LLZeanU4ZevzRnGFg2neDeKHgFLjP6YLW+tly0IvrhqT4u8enLGjLH3qeh85g19xY5rsAusfwTdn5lg==", + "dependencies": { + "@floating-ui/utils": "^0.2.0" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.5.tgz", + "integrity": "sha512-Nsdud2X65Dz+1RHjAIP0t8z5e2ff/IRbei6BqFrl1urT8sDVzM1HMQ+R0XcU5ceRfyO3I6ayeqIfh+6Wb8LGTw==", + "dependencies": { + "@floating-ui/core": "^1.0.0", + "@floating-ui/utils": "^0.2.0" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.0.tgz", + "integrity": "sha512-lNzj5EQmEKn5FFKc04+zasr09h/uX8RtJRNj5gUXsSQIXHVWTVh+hVAg1vOMCexkX8EgvemMvIFpQfkosnVNyA==", + "dependencies": { + "@floating-ui/dom": "^1.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.2.tgz", + "integrity": "sha512-J4yDIIthosAsRZ5CPYP/jQvUAQtlZTTD/4suA08/FEnlxqW3sKS9iAhgsa9VYLZ6vDHn/ixJgIqRQPotoBjxIw==" + }, "node_modules/@hapi/hoek": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", @@ -4144,6 +4328,261 @@ "react": ">=16" } }, + "node_modules/@mui/base": { + "version": "5.0.0-beta.40", + "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.40.tgz", + "integrity": "sha512-I/lGHztkCzvwlXpjD2+SNmvNQvB4227xBXhISPjEaJUXGImOQ9f3D2Yj/T3KasSI/h0MLWy74X0J6clhPmsRbQ==", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@floating-ui/react-dom": "^2.0.8", + "@mui/types": "^7.2.14", + "@mui/utils": "^5.15.14", + "@popperjs/core": "^2.11.8", + "clsx": "^2.1.0", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/core-downloads-tracker": { + "version": "5.15.20", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.15.20.tgz", + "integrity": "sha512-DoL2ppgldL16utL8nNyj/P12f8mCNdx/Hb/AJnX9rLY4b52hCMIx1kH83pbXQ6uMy6n54M3StmEbvSGoj2OFuA==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + } + }, + "node_modules/@mui/icons-material": { + "version": "5.15.20", + "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.15.20.tgz", + "integrity": "sha512-oGcKmCuHaYbAAoLN67WKSXtHmEgyWcJToT1uRtmPyxMj9N5uqwc/mRtEnst4Wj/eGr+zYH2FiZQ79v9k7kSk1Q==", + "dependencies": { + "@babel/runtime": "^7.23.9" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@mui/material": "^5.0.0", + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/material": { + "version": "5.15.20", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.15.20.tgz", + "integrity": "sha512-tVq3l4qoXx/NxUgIx/x3lZiPn/5xDbdTE8VrLczNpfblLYZzlrbxA7kb9mI8NoBF6+w9WE9IrxWnKK5KlPI2bg==", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@mui/base": "5.0.0-beta.40", + "@mui/core-downloads-tracker": "^5.15.20", + "@mui/system": "^5.15.20", + "@mui/types": "^7.2.14", + "@mui/utils": "^5.15.20", + "@types/react-transition-group": "^4.4.10", + "clsx": "^2.1.0", + "csstype": "^3.1.3", + "prop-types": "^15.8.1", + "react-is": "^18.2.0", + "react-transition-group": "^4.4.5" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/material/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" + }, + "node_modules/@mui/private-theming": { + "version": "5.15.20", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.15.20.tgz", + "integrity": "sha512-BK8F94AIqSrnaPYXf2KAOjGZJgWfvqAVQ2gVR3EryvQFtuBnG6RwodxrCvd3B48VuMy6Wsk897+lQMUxJyk+6g==", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@mui/utils": "^5.15.20", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/styled-engine": { + "version": "5.15.14", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.15.14.tgz", + "integrity": "sha512-RILkuVD8gY6PvjZjqnWhz8fu68dVkqhM5+jYWfB5yhlSQKg+2rHkmEwm75XIeAqI3qwOndK6zELK5H6Zxn4NHw==", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@emotion/cache": "^11.11.0", + "csstype": "^3.1.3", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.4.1", + "@emotion/styled": "^11.3.0", + "react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + } + } + }, + "node_modules/@mui/system": { + "version": "5.15.20", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.15.20.tgz", + "integrity": "sha512-LoMq4IlAAhxzL2VNUDBTQxAb4chnBe8JvRINVNDiMtHE2PiPOoHlhOPutSxEbaL5mkECPVWSv6p8JEV+uykwIA==", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@mui/private-theming": "^5.15.20", + "@mui/styled-engine": "^5.15.14", + "@mui/types": "^7.2.14", + "@mui/utils": "^5.15.20", + "clsx": "^2.1.0", + "csstype": "^3.1.3", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/types": { + "version": "7.2.14", + "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.14.tgz", + "integrity": "sha512-MZsBZ4q4HfzBsywtXgM1Ksj6HDThtiwmOKUXH1pKYISI9gAVXCNHNpo7TlGoGrBaYWZTdNoirIN7JsQcQUjmQQ==", + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/utils": { + "version": "5.15.20", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.15.20.tgz", + "integrity": "sha512-mAbYx0sovrnpAu1zHc3MDIhPqL8RPVC5W5xcO1b7PiSCJPtckIZmBkp8hefamAvUiAV8gpfMOM6Zb+eSisbI2A==", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@types/prop-types": "^15.7.11", + "prop-types": "^15.8.1", + "react-is": "^18.2.0" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/utils/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -4218,6 +4657,15 @@ "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.25.tgz", "integrity": "sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==" }, + "node_modules/@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, "node_modules/@sideway/address": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", @@ -4796,6 +5244,14 @@ "@types/react-router": "*" } }, + "node_modules/@types/react-transition-group": { + "version": "4.4.10", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.10.tgz", + "integrity": "sha512-hT/+s0VQs2ojCX823m60m5f0sL5idt9SO6Tj6Dg+rdphGPIeJbJ6CxvBYkgkGKrYeDjvIpKTR38UzmtHJOGW3Q==", + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@types/retry": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", @@ -5347,6 +5803,20 @@ "object.assign": "^4.1.0" } }, + "node_modules/babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "dependencies": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + } + }, "node_modules/babel-plugin-polyfill-corejs2": { "version": "0.4.10", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.10.tgz", @@ -6826,6 +7296,15 @@ "utila": "~0.4" } }, + "node_modules/dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "dependencies": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, "node_modules/dom-serializer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", @@ -7561,6 +8040,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==" + }, "node_modules/find-up": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", @@ -13260,6 +13744,21 @@ "react": ">=15" } }, + "node_modules/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "dependencies": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": ">=16.6.0", + "react-dom": ">=16.6.0" + } + }, "node_modules/readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", @@ -14504,6 +15003,11 @@ "postcss": "^8.2.15" } }, + "node_modules/stylis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", diff --git a/tilda-web/package.json b/tilda-web/package.json index 111ddee..c6ade1f 100644 --- a/tilda-web/package.json +++ b/tilda-web/package.json @@ -18,7 +18,11 @@ "@docusaurus/core": "3.2.0", "@docusaurus/plugin-content-pages": "^3.3.2", "@docusaurus/preset-classic": "3.2.0", + "@emotion/react": "^11.11.4", + "@emotion/styled": "^11.11.5", "@mdx-js/react": "^3.0.0", + "@mui/icons-material": "^5.15.20", + "@mui/material": "^5.15.20", "clsx": "^2.0.0", "prism-react-renderer": "^2.3.0", "react": "^18.0.0", diff --git a/tilda-web/src/components/Generator/App.tsx b/tilda-web/src/components/Generator/App.tsx new file mode 100644 index 0000000..0f22ffb --- /dev/null +++ b/tilda-web/src/components/Generator/App.tsx @@ -0,0 +1,114 @@ +import React, { useEffect, useRef, useState } from 'react'; +import { Container, Grid, TextField } from '@mui/material'; +import Fields from './Fields'; +import Hooks from './Hooks'; +import sampleManifestJson from './sample-manifest.json'; +import { FormManifest, Manifest } from './models'; + +function App() { + const [manifestJson, setManifestJson] = useState('{}'); + const isUpdatingFromForm = useRef(false); + const isUpdatingFromJson = useRef(true); + + const [formManifest, setManifestForm] = useState({ + fields: [], + }); + + const resetForm = () => { + setManifestForm({ + fields: [ + { + name: 'defaultField', + label: 'Default Field', + inputName: 'default_field', + const: [], + validators: [], + }, + ], + }); + }; + + useEffect(() => { + if (isUpdatingFromJson.current && manifestJson && manifestJson !== '{}') { + try { + const parsedJson = JSON.parse(manifestJson); + const form = Manifest.toForm(parsedJson); + setManifestForm(form); + } catch (e) { + console.error(e); + resetForm(); + isUpdatingFromJson.current = true; + isUpdatingFromForm.current = false; + } + } + if ( + isUpdatingFromJson.current && + (manifestJson === '{}' || manifestJson === '' || !manifestJson) + ) { + resetForm(); + isUpdatingFromJson.current = true; + isUpdatingFromForm.current = false; + } else { + isUpdatingFromForm.current = false; + isUpdatingFromJson.current = false; + } + }, [manifestJson]); + + useEffect(() => { + if (isUpdatingFromForm.current && formManifest) { + console.log('form to json', formManifest); + + const manifest = FormManifest.toManifest(formManifest); + setManifestJson(JSON.stringify({ manifest }, null, 2)); + } + isUpdatingFromJson.current = false; + isUpdatingFromForm.current = false; + }, [formManifest]); + + useEffect(() => { + isUpdatingFromJson.current = true; + setManifestJson(JSON.stringify(sampleManifestJson, null, 2)); + }, []); + + return ( + + + + { + isUpdatingFromForm.current = true; + isUpdatingFromJson.current = false; + setManifestForm(newManifestForm); + }} + /> + { + isUpdatingFromForm.current = true; + isUpdatingFromJson.current = false; + setManifestForm(newManifestForm); + }} + /> + + + { + isUpdatingFromJson.current = true; + isUpdatingFromForm.current = false; + setManifestJson(e.target.value); + }} + value={manifestJson} + > + + + + ); +} + +export default App; diff --git a/tilda-web/src/components/Generator/Fields.tsx b/tilda-web/src/components/Generator/Fields.tsx new file mode 100644 index 0000000..69856ec --- /dev/null +++ b/tilda-web/src/components/Generator/Fields.tsx @@ -0,0 +1,591 @@ +import { + Add, + Delete, + GppBadRounded, + GppGoodRounded, + } from "@mui/icons-material"; + import { + FormControl, + Grid, + IconButton, + InputLabel, + MenuItem, + Select, + Switch, + TextField, + } from "@mui/material"; + import { FormField, FormManifest, FormValidator } from "./models"; + + //create Fields class component + function Fields(props: { + formManifest: FormManifest; + updateManifest: (formManifest: FormManifest) => void; + }) { + return ( + + + Fields + { + const newForm: FormManifest = { + fields: [ + ...props.formManifest.fields, + { + name: props.formManifest.fields.length + ". Field", + label: "", + inputName: "", + const: [], + validators: [], + }, + ], + hooks: props.formManifest.hooks, + }; + props.updateManifest(newForm); + }} + > + + + + + {props.formManifest.fields.map((field: FormField, fieldIndex: number) => ( + + + + { + const newForm: FormManifest = { + fields: props.formManifest.fields.map((f, i) => + i === fieldIndex ? { ...f, name: e.target.value } : f + ), + hooks: props.formManifest.hooks, + }; + props.updateManifest(newForm); + }} + value={field.name} + > + + + + { + //find by index and update inputName + const newForm: FormManifest = { + fields: props.formManifest.fields.map((f, i) => + i === fieldIndex ? { ...f, inputName: e.target.value } : f + ), + hooks: props.formManifest.hooks, + }; + props.updateManifest(newForm); + }} + value={field.inputName} + >{" "} + + + + { + //find by index and update inputName + const newForm: FormManifest = { + fields: props.formManifest.fields.map((f, i) => + i === fieldIndex ? { ...f, label: e.target.value } : f + ), + hooks: props.formManifest.hooks, + }; + props.updateManifest(newForm); + }} + value={field.label} + > + + + + { + const newForm: FormManifest = { + fields: props.formManifest.fields.filter( + (f, i) => i !== fieldIndex + ), + hooks: props.formManifest.hooks, + }; + props.updateManifest(newForm); + }} + aria-label="delete" + > + + + + + + + Constant Values + { + //find field by fieldIndex and add new const + const newForm: FormManifest = { + fields: props.formManifest.fields.map((f, i) => + i === fieldIndex + ? { + ...f, + const: [ + ...f.const, + { + name: f.const.length + 1 + ". const", + value: "", + isSecure: false, + }, + ], + } + : f + ), + hooks: props.formManifest.hooks, + }; + props.updateManifest(newForm); + }} + > + + + + {field.const.length > 0 && ( + + {field.const.map((c: any, constIndex: number) => ( + + + { + //find field by fieldIndex and const by constIndex and update name + const newForm: FormManifest = { + fields: props.formManifest.fields.map((f, i) => + i === fieldIndex + ? { + ...f, + const: f.const.map((c, j) => + j === constIndex + ? { ...c, name: e.target.value } + : c + ), + } + : f + ), + hooks: props.formManifest.hooks, + }; + props.updateManifest(newForm); + }} + value={c.name} + > + + + { + //find field by fieldIndex and const by constIndex and update value + const newForm: FormManifest = { + fields: props.formManifest.fields.map((f, i) => + i === fieldIndex + ? { + ...f, + const: f.const.map((c, j) => + j === constIndex + ? { + ...c, + value: e.target.value, + } + : c + ), + } + : f + ), + hooks: props.formManifest.hooks, + }; + props.updateManifest(newForm); + }} + value={c.value} + > + + + { + const newForm: FormManifest = { + fields: props.formManifest.fields.map((f, i) => + i === fieldIndex + ? { + ...f, + const: f.const.filter( + (c, j) => j !== constIndex + ), + } + : f + ), + hooks: props.formManifest.hooks, + }; + props.updateManifest(newForm); + }} + aria-label="delete" + > + + + + + { + //find field by fieldIndex and const by constIndex and update isSecure + const newForm: FormManifest = { + fields: props.formManifest.fields.map((f, i) => + i === fieldIndex + ? { + ...f, + const: f.const.map((c, j) => + j === constIndex + ? { + ...c, + isSecure: !c.isSecure, + } + : c + ), + } + : f + ), + hooks: props.formManifest.hooks, + }; + props.updateManifest(newForm); + }} + aria-label="delete" + > + {c.isSecure ? ( + + ) : ( + + )} + + + + ))} + + )} + + + Validators + { + //find field by fieldIndex and add new const + const newForm: FormManifest = { + fields: props.formManifest.fields.map((f, i) => + i === fieldIndex + ? { + ...f, + validators: [ + ...f.validators, + { + factory: "alpha", + }, + ], + } + : f + ), + hooks: props.formManifest.hooks, + }; + props.updateManifest(newForm); + }} + > + + + + {field.validators.length > 0 && ( + + {field.validators.map( + (v: FormValidator, validatorIndex: number) => ( + + + <> + + + + + + {v.factory === "length" && ( + <> + + { + //find field by fieldIndex and validator by validatorIndex and update minLength + const newForm: FormManifest = { + fields: props.formManifest.fields.map((f, i) => + i === fieldIndex + ? { + ...f, + validators: f.validators.map((c, j) => + j === validatorIndex + ? { + ...c, + minLength: parseInt( + e.target.value + ), + } + : c + ), + } + : f + ), + hooks: props.formManifest.hooks, + }; + props.updateManifest(newForm); + }} + value={v.minLength} + > + + + { + //find field by fieldIndex and validator by validatorIndex and update maxLength + const newForm: FormManifest = { + fields: props.formManifest.fields.map((f, i) => + i === fieldIndex + ? { + ...f, + validators: f.validators.map((c, j) => + j === validatorIndex + ? { + ...c, + maxLength: parseInt( + e.target.value + ), + } + : c + ), + } + : f + ), + hooks: props.formManifest.hooks, + }; + props.updateManifest(newForm); + }} + value={v.maxLength} + > + + + )} + {v.factory === "regex" && ( + <> + + { + //find field by fieldIndex and validator by validatorIndex and update regex + const newForm: FormManifest = { + fields: props.formManifest.fields.map((f, i) => + i === fieldIndex + ? { + ...f, + validators: f.validators.map((c, j) => + j === validatorIndex + ? { + ...c, + regex: e.target.value, + } + : c + ), + } + : f + ), + hooks: props.formManifest.hooks, + }; + props.updateManifest(newForm); + }} + value={v.regex} + > + + + <> + Match/Fail + { + //find field by fieldIndex and validator by validatorIndex and update onMatch + const newForm: FormManifest = { + fields: props.formManifest.fields.map( + (f, i) => + i === fieldIndex + ? { + ...f, + validators: f.validators.map( + (c, j) => + j === validatorIndex + ? { + ...c, + onMatch: e.target.checked + ? "pass" + : "fail", + } + : c + ), + } + : f + ), + hooks: props.formManifest.hooks, + }; + props.updateManifest(newForm); + }} + > + + + + )} + + { + const newForm: FormManifest = { + fields: props.formManifest.fields.map((f, i) => + i === fieldIndex + ? { + ...f, + validators: f.validators.filter( + (c, j) => j !== validatorIndex + ), + } + : f + ), + hooks: props.formManifest.hooks, + }; + props.updateManifest(newForm); + }} + aria-label="delete" + > + + + + + ) + )} + + )} + + ))} + + ); + } + + export default Fields; + \ No newline at end of file diff --git a/tilda-web/src/components/Generator/Hooks.tsx b/tilda-web/src/components/Generator/Hooks.tsx new file mode 100644 index 0000000..6d7494e --- /dev/null +++ b/tilda-web/src/components/Generator/Hooks.tsx @@ -0,0 +1,50 @@ +import { FormField, FormManifest, FormValidator } from "./models"; +import { Grid, IconButton } from "@mui/material"; + +import { Add } from "@mui/icons-material"; + +//create Fields class component +function Hooks(props: { + formManifest: FormManifest; + updateManifest: (formManifest: FormManifest) => void; +}) { + return ( + + + + Add Pre Hook + {}}> + + + + + + + Add Post Hook + {}}> + + + + + + ); +} + +export default Hooks; diff --git a/tilda-web/src/components/Generator/index.css b/tilda-web/src/components/Generator/index.css new file mode 100644 index 0000000..04b3e5b --- /dev/null +++ b/tilda-web/src/components/Generator/index.css @@ -0,0 +1,15 @@ +html { +} + +body { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', + 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', + sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +code { + font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', + monospace; +} diff --git a/tilda-web/src/components/Generator/models/Constant.ts b/tilda-web/src/components/Generator/models/Constant.ts new file mode 100644 index 0000000..a843236 --- /dev/null +++ b/tilda-web/src/components/Generator/models/Constant.ts @@ -0,0 +1,4 @@ + +export interface Constant { + [key: string]: string; +} diff --git a/tilda-web/src/components/Generator/models/Fields.ts b/tilda-web/src/components/Generator/models/Fields.ts new file mode 100644 index 0000000..ec8f93f --- /dev/null +++ b/tilda-web/src/components/Generator/models/Fields.ts @@ -0,0 +1,12 @@ +import { Constant } from "./Constant"; +import { Ui } from "./Ui"; +import { Validator } from "./Validator"; + +export interface Fields { + [key: string]: { + inputName: string; + ui: Ui; + const: Constant; + validators: Validator[]; + }; +} diff --git a/tilda-web/src/components/Generator/models/FormConst.ts b/tilda-web/src/components/Generator/models/FormConst.ts new file mode 100644 index 0000000..060350a --- /dev/null +++ b/tilda-web/src/components/Generator/models/FormConst.ts @@ -0,0 +1,6 @@ + +export interface FormConst { + name: string; + value: string; + isSecure: boolean; +} diff --git a/tilda-web/src/components/Generator/models/FormField.ts b/tilda-web/src/components/Generator/models/FormField.ts new file mode 100644 index 0000000..4606563 --- /dev/null +++ b/tilda-web/src/components/Generator/models/FormField.ts @@ -0,0 +1,10 @@ +import { FormConst } from "./FormConst"; +import { FormValidator } from "./FormValidator"; + +export interface FormField { + name: string; + label: string; + inputName: string; + const: FormConst[]; + validators: FormValidator[]; +} diff --git a/tilda-web/src/components/Generator/models/FormHook.ts b/tilda-web/src/components/Generator/models/FormHook.ts new file mode 100644 index 0000000..45e7ef9 --- /dev/null +++ b/tilda-web/src/components/Generator/models/FormHook.ts @@ -0,0 +1,3 @@ +export interface FormHook { + factory: string; +} diff --git a/tilda-web/src/components/Generator/models/FormHooks.ts b/tilda-web/src/components/Generator/models/FormHooks.ts new file mode 100644 index 0000000..94ccf8a --- /dev/null +++ b/tilda-web/src/components/Generator/models/FormHooks.ts @@ -0,0 +1,6 @@ +import { FormHook } from "./FormHook"; + +export interface FormHooks { + pre: FormHook[]; + post: FormHook[]; +} diff --git a/tilda-web/src/components/Generator/models/FormManifest.ts b/tilda-web/src/components/Generator/models/FormManifest.ts new file mode 100644 index 0000000..33e206e --- /dev/null +++ b/tilda-web/src/components/Generator/models/FormManifest.ts @@ -0,0 +1,60 @@ +import { Fields, FormField, FormHooks, Manifest, Validator } from "."; + +export class FormManifest { + constructor() { + this.fields = []; + this.hooks = {} as FormHooks; + } + + fields: FormField[]; + hooks?: FormHooks; + + static toManifest(formData: FormManifest): Manifest { + const fields: Fields = {}; + + formData.fields.forEach((element) => { + const constObject: { + [key: string]: string; + } = {}; + element.const.forEach((c) => { + const suffix = c.isSecure ? ":enc" : ""; + constObject[c.name + suffix] = c.value; + }); + + const validatorsArr: Validator[] = []; + + element.validators.forEach((v) => { + const validator: Validator = { + factory: v.factory, + }; + if (v.factory === "length") { + validator.minLength = v.minLength; + validator.maxLength = v.maxLength; + } + if (v.factory === "regex") { + validator.value = v.regex; + validator.onMatch = v.onMatch; + } + if (v.factory === "enum") { + validator.values = v.enumValues; + } + validatorsArr.push(validator); + }); + + fields[element.name] = { + inputName: element.inputName, + ui: { + label: element.label, + }, + const: constObject, + validators: validatorsArr, + }; + }); + + return { + data: { + fields: fields, + }, + } as Manifest; + } +} diff --git a/tilda-web/src/components/Generator/models/FormValidator.ts b/tilda-web/src/components/Generator/models/FormValidator.ts new file mode 100644 index 0000000..8a273e8 --- /dev/null +++ b/tilda-web/src/components/Generator/models/FormValidator.ts @@ -0,0 +1,14 @@ +export interface FormValidator { + factory: "alpha" | + "numeric" | + "alphanumeric" | + "regex" | + "length" | + "notEmpty" | + "enum"; + minLength?: number; + maxLength?: number; + onMatch?: "fail" | "pass"; + enumValues?: string[]; + regex?: string; +} diff --git a/tilda-web/src/components/Generator/models/Manifest.ts b/tilda-web/src/components/Generator/models/Manifest.ts new file mode 100644 index 0000000..952a87e --- /dev/null +++ b/tilda-web/src/components/Generator/models/Manifest.ts @@ -0,0 +1,59 @@ +import { Fields, FormConst, FormField, FormManifest, FormValidator } from "."; + +export class Manifest { + constructor() { + this.data = { + fields: {} as Fields, + }; + } + data: { + fields: Fields; + }; + + static toForm(object: { manifest: Manifest }): FormManifest { + const arr: FormField[] = []; + + for (const key in object.manifest.data.fields) { + const fieldObj = object.manifest.data.fields[key]; + + const constsObj = fieldObj.const; + const constsArr: FormConst[] = []; + for (const constKey in constsObj) { + constsArr.push({ + isSecure: constKey.endsWith(":enc"), + name: constKey.split(":")[0], + value: constsObj[constKey], + } as FormConst); + } + + const validatorsObj = fieldObj.validators; + const validatorsArr: FormValidator[] = []; + for (const validatorKey in validatorsObj) { + const validator = validatorsObj[validatorKey]; + validatorsArr.push({ + factory: validator.factory, + minLength: validator.minLength, + maxLength: validator.maxLength, + onMatch: validator.onMatch, + enumValues: validator.values, + regex: validator.value, + }); + } + + arr.push({ + name: key, + label: fieldObj.ui?.label, + inputName: fieldObj.inputName, + const: constsArr, + validators: validatorsArr, + }); + } + return { + fields: arr, + hooks: { + pre: [], + post: [], + }, + }; + } +} diff --git a/tilda-web/src/components/Generator/models/Ui.ts b/tilda-web/src/components/Generator/models/Ui.ts new file mode 100644 index 0000000..8dbb9e2 --- /dev/null +++ b/tilda-web/src/components/Generator/models/Ui.ts @@ -0,0 +1,4 @@ + +export interface Ui { + label: string; +} diff --git a/tilda-web/src/components/Generator/models/Validator.ts b/tilda-web/src/components/Generator/models/Validator.ts new file mode 100644 index 0000000..893f79f --- /dev/null +++ b/tilda-web/src/components/Generator/models/Validator.ts @@ -0,0 +1,15 @@ + +export interface Validator { + factory: "alpha" | + "numeric" | + "alphanumeric" | + "regex" | + "length" | + "notEmpty" | + "enum"; + minLength?: number; + maxLength?: number; + onMatch?: "fail" | "pass"; + values?: string[]; + value?: string; +} diff --git a/tilda-web/src/components/Generator/models/index.ts b/tilda-web/src/components/Generator/models/index.ts new file mode 100644 index 0000000..40fd0bd --- /dev/null +++ b/tilda-web/src/components/Generator/models/index.ts @@ -0,0 +1,11 @@ +export * from "./Manifest"; +export * from "./FormHook"; +export * from "./FormHooks"; +export * from "./FormField"; +export * from "./FormManifest"; +export * from "./Fields"; +export * from "./Constant"; +export * from "./FormConst"; +export * from "./FormValidator"; +export * from "./Validator"; +export * from "./Ui"; diff --git a/tilda-web/src/components/Generator/sample-manifest.json b/tilda-web/src/components/Generator/sample-manifest.json new file mode 100644 index 0000000..94c2ab1 --- /dev/null +++ b/tilda-web/src/components/Generator/sample-manifest.json @@ -0,0 +1,60 @@ +{ + "manifest": { + "data": { + "fields": { + "firstName": { + "inputName": "first_name", + "ui": { + "label": "First Name" + }, + "const": {}, + "validators": [ + { + "factory": "alpha" + } + ] + }, + "lastName": { + "inputName": "last_name", + "ui": { + "label": "Last Name" + }, + "const": {}, + "validators": [ + { + "factory": "alpha" + } + ] + }, + "citizenId": { + "inputName": "citizen_id", + "ui": { + "label": "Citizen ID" + }, + "const": { + "taxId:enc": "1234567890" + }, + "validators": [ + { + "factory": "regex", + "value": "^[1-9]{1}[0-9]{9}[02468]{1}$", + "onMatch": "pass" + } + ] + }, + "age": { + "inputName": "age", + "ui": { + "label": "Age" + }, + "const": {}, + "validators": [ + { + "factory": "numeric" + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/tilda-web/src/components/NoSidebarLayout.module.css b/tilda-web/src/components/NoSidebarLayout.module.css new file mode 100644 index 0000000..628e1be --- /dev/null +++ b/tilda-web/src/components/NoSidebarLayout.module.css @@ -0,0 +1,11 @@ +.noSidebar { + display: flex; + flex-direction: column; + align-items: center; + width: 100%; + } + + .main-wrapper { + margin-left: 0 !important; + } + \ No newline at end of file diff --git a/tilda-web/src/components/NoSidebarLayout.tsx b/tilda-web/src/components/NoSidebarLayout.tsx new file mode 100644 index 0000000..3cbea54 --- /dev/null +++ b/tilda-web/src/components/NoSidebarLayout.tsx @@ -0,0 +1,16 @@ +import React from 'react'; +import Layout from '@theme/Layout'; +import clsx from 'clsx'; +import styles from './NoSidebarLayout.module.css'; + +function NoSidebarLayout({ children }) { + return ( + +
+ {children} +
+
+ ); +} + +export default NoSidebarLayout; diff --git a/tilda-web/src/pages/generator.tsx b/tilda-web/src/pages/generator.tsx new file mode 100644 index 0000000..2a17efb --- /dev/null +++ b/tilda-web/src/pages/generator.tsx @@ -0,0 +1,13 @@ +import React from 'react'; +import App from '@site/src/components/Generator/App'; +import NoSidebarLayout from '@site/src/components/NoSidebarLayout'; + +const GeneratorPage: React.FC = () => { + return ( + + + + ); +}; + +export default GeneratorPage;