diff --git a/ui/package-lock.json b/ui/package-lock.json index 40ea153..25d4050 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -10,6 +10,7 @@ "word_grid": "file:../pkg" }, "devDependencies": { + "@parcel/transformer-less": "^2.9.3", "@types/react": "^18.2.18", "@types/react-dom": "^18.2.7", "parcel": "^2.9.3", @@ -1346,6 +1347,25 @@ "url": "https://opencollective.com/parcel" } }, + "node_modules/@parcel/transformer-less": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/@parcel/transformer-less/-/transformer-less-2.9.3.tgz", + "integrity": "sha512-qwF5NQ8rPZjS79tv9RRPxzkZcwLcI4Xg2gHm9c1PvsgoaL2tVNpfjiRA6MOrzfJp+xr7xEzeMDZksOJ1WQiiQg==", + "dev": true, + "dependencies": { + "@parcel/plugin": "2.9.3", + "@parcel/source-map": "^2.1.1", + "less": "^4.1.1" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.9.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, "node_modules/@parcel/transformer-postcss": { "version": "2.9.3", "resolved": "https://registry.npmjs.org/@parcel/transformer-postcss/-/transformer-postcss-2.9.3.tgz", @@ -2167,6 +2187,18 @@ "node": ">= 10" } }, + "node_modules/copy-anything": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.6.tgz", + "integrity": "sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==", + "dev": true, + "dependencies": { + "is-what": "^3.14.1" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, "node_modules/cosmiconfig": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.2.0.tgz", @@ -2338,6 +2370,16 @@ "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==", "dev": true }, + "node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "optional": true, + "dependencies": { + "ms": "^2.1.1" + } + }, "node_modules/detect-libc": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", @@ -2447,6 +2489,19 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/errno": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", + "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", + "dev": true, + "optional": true, + "dependencies": { + "prr": "~1.0.1" + }, + "bin": { + "errno": "cli.js" + } + }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -2510,6 +2565,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "optional": true + }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -2585,6 +2647,32 @@ "entities": "^3.0.1" } }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/image-size": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", + "integrity": "sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==", + "dev": true, + "optional": true, + "bin": { + "image-size": "bin/image-size.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -2643,6 +2731,12 @@ "node": ">=0.12.0" } }, + "node_modules/is-what": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz", + "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==", + "dev": true + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -2678,6 +2772,32 @@ "node": ">=6" } }, + "node_modules/less": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/less/-/less-4.2.0.tgz", + "integrity": "sha512-P3b3HJDBtSzsXUl0im2L7gTO5Ubg8mEN6G8qoTS77iXxXX4Hvu4Qj540PZDvQ8V6DmX6iXo98k7Md0Cm1PrLaA==", + "dev": true, + "dependencies": { + "copy-anything": "^2.0.1", + "parse-node-version": "^1.0.1", + "tslib": "^2.3.0" + }, + "bin": { + "lessc": "bin/lessc" + }, + "engines": { + "node": ">=6" + }, + "optionalDependencies": { + "errno": "^0.1.1", + "graceful-fs": "^4.1.2", + "image-size": "~0.5.0", + "make-dir": "^2.1.0", + "mime": "^1.4.1", + "needle": "^3.1.0", + "source-map": "~0.6.0" + } + }, "node_modules/lightningcss": { "version": "1.21.5", "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.21.5.tgz", @@ -2933,6 +3053,30 @@ "node": ">=10" } }, + "node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "optional": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "optional": true, + "bin": { + "semver": "bin/semver" + } + }, "node_modules/mdn-data": { "version": "2.0.30", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", @@ -2954,6 +3098,26 @@ "node": ">=8.6" } }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "optional": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "optional": true + }, "node_modules/msgpackr": { "version": "1.9.6", "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.9.6.tgz", @@ -2997,6 +3161,24 @@ "node-gyp-build-optional-packages-test": "build-test.js" } }, + "node_modules/needle": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/needle/-/needle-3.2.0.tgz", + "integrity": "sha512-oUvzXnyLiVyVGoianLijF9O/RecZUf7TkBfimjGrLM4eQhXyeJwM6GeAWccwfQ9aa4gMCZKqhAOuLaMIcQxajQ==", + "dev": true, + "optional": true, + "dependencies": { + "debug": "^3.2.6", + "iconv-lite": "^0.6.3", + "sax": "^1.2.4" + }, + "bin": { + "needle": "bin/needle" + }, + "engines": { + "node": ">= 4.4.x" + } + }, "node_modules/node-addon-api": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.0.0.tgz", @@ -3106,6 +3288,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/parse-node-version": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", + "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -3133,6 +3324,16 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "optional": true, + "engines": { + "node": ">=6" + } + }, "node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", @@ -3197,6 +3398,13 @@ "node": ">= 0.6.0" } }, + "node_modules/prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", + "dev": true, + "optional": true + }, "node_modules/react": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", @@ -3270,6 +3478,20 @@ } ] }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "optional": true + }, + "node_modules/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "dev": true, + "optional": true + }, "node_modules/scheduler": { "version": "0.23.0", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", diff --git a/ui/package.json b/ui/package.json index 7829fdb..c763b1b 100644 --- a/ui/package.json +++ b/ui/package.json @@ -5,6 +5,7 @@ "word_grid": "file:../pkg" }, "devDependencies": { + "@parcel/transformer-less": "^2.9.3", "@types/react": "^18.2.18", "@types/react-dom": "^18.2.7", "parcel": "^2.9.3", diff --git a/ui/src/elements.tsx b/ui/src/elements.tsx new file mode 100644 index 0000000..571c7a3 --- /dev/null +++ b/ui/src/elements.tsx @@ -0,0 +1,34 @@ +import * as React from "react"; + +export interface LetterData { + text: string, + points: number, + ephemeral: boolean, + is_blank: boolean, +} + +export function Letter(props: {data: LetterData}): React.JSX.Element { + return
+
{props.data.text}
+
{props.data.points}
+
+} + +export function TileTray(props: { letters: Array }): React.JSX.Element { + + let elements = props.letters.map((ld, i) => { + if (ld === undefined) { + return
; + } else { + return + } + }) + .concat(); + + return ( +
+ {elements} +
+ ) + +} \ No newline at end of file diff --git a/ui/src/index.html b/ui/src/index.html index fccece6..06fa78b 100644 --- a/ui/src/index.html +++ b/ui/src/index.html @@ -2,11 +2,12 @@ - hello-wasm example + + Word Grid - +
diff --git a/ui/src/index.js b/ui/src/index.js index 8f4415e..c7a01ba 100644 --- a/ui/src/index.js +++ b/ui/src/index.js @@ -1,50 +1,49 @@ - // Use ES module import syntax to import functionality from the module - // that we have compiled. - // - // Note that the `default` import is an initialization function which - // will "boot" the module and make it ready to use. Currently browsers - // don't support natively imported WebAssembly as an ES module, but - // eventually the manual initialization won't be required! - import init, { greet, GameWasm } from '../node_modules/word_grid/word_grid.js'; +import init, {greet, GameWasm} from '../node_modules/word_grid/word_grid.js'; +import {TileTray} from "./elements"; +import ReactDOM from "react-dom"; +import {createRoot} from "react-dom/client"; - async function run() { - // First up we need to actually load the wasm file, so we use the - // default export to inform it where the wasm file is located on the - // server, and then we wait on the returned promise to wait for the - // wasm to be loaded. - // - // It may look like this: `await init('./pkg/without_a_bundler_bg.wasm');`, - // but there is also a handy default inside `init` function, which uses - // `import.meta` to locate the wasm file relatively to js file. - // - // Note that instead of a string you can also pass in any of the - // following things: - // - // * `WebAssembly.Module` - // - // * `ArrayBuffer` - // - // * `Response` - // - // * `Promise` which returns any of the above, e.g. `fetch("./path/to/wasm")` - // - // This gives you complete control over how the module is loaded - // and compiled. - // - // Also note that the promise, when resolved, yields the wasm module's - // exports which is the same as importing the `*_bg` module in other - // modes - await init(); +async function run() { + // First up we need to actually load the wasm file, so we use the + // default export to inform it where the wasm file is located on the + // server, and then we wait on the returned promise to wait for the + // wasm to be loaded. + // + // It may look like this: `await init('./pkg/without_a_bundler_bg.wasm');`, + // but there is also a handy default inside `init` function, which uses + // `import.meta` to locate the wasm file relatively to js file. + // + // Note that instead of a string you can also pass in any of the + // following things: + // + // * `WebAssembly.Module` + // + // * `ArrayBuffer` + // + // * `Response` + // + // * `Promise` which returns any of the above, e.g. `fetch("./path/to/wasm")` + // + // This gives you complete control over how the module is loaded + // and compiled. + // + // Also note that the promise, when resolved, yields the wasm module's + // exports which is the same as importing the `*_bg` module in other + // modes + await init(); - greet("Heyo!"); + greet("Heyo!"); - let game = new GameWasm(1234n); - let tray = game.get_tray(); + let game = new GameWasm(1234n); + let tray = game.get_tray(); - console.log({tray}); + console.log({tray}); - // And afterwards we can use all the functionality defined in wasm. + const root = createRoot(document.getElementById("root")); + root.render(); - } + // And afterwards we can use all the functionality defined in wasm. - run(); +} + +run(); diff --git a/ui/src/style.less b/ui/src/style.less new file mode 100644 index 0000000..e47a171 --- /dev/null +++ b/ui/src/style.less @@ -0,0 +1,34 @@ +@tile-width: 55px; +@tile-font-size: 35px; + +.tray { + display: grid; + grid-template-columns: repeat(7, @tile-width); + grid-gap: 5px; + height: @tile-width; + width: fit-content; + background-color: #bbb59d; + margin: 10px; +} + +.letter { + background-color: #e5cca9; + position: relative; // Used for the positioning of the sub-components + + .text { + position: absolute; + width: 100%; + text-align: center; + top: 5px; + font-size: @tile-font-size; + } + + .letter-points { + font-size: 15px; + position: absolute; + bottom: 2px; + right: -1px; + padding-right: 5px; + } + +} \ No newline at end of file