summaryrefslogtreecommitdiff
path: root/fig-frontend/client
diff options
context:
space:
mode:
Diffstat (limited to 'fig-frontend/client')
-rw-r--r--fig-frontend/client/package-lock.json578
-rw-r--r--fig-frontend/client/package.json17
-rw-r--r--fig-frontend/client/src/blueprint.jpgbin0 -> 1308988 bytes
-rw-r--r--fig-frontend/client/src/config.ts3
-rw-r--r--fig-frontend/client/src/index.css30
-rw-r--r--fig-frontend/client/src/index.ts119
-rw-r--r--fig-frontend/client/src/twitch.ts43
-rw-r--r--fig-frontend/client/tsconfig.json18
8 files changed, 808 insertions, 0 deletions
diff --git a/fig-frontend/client/package-lock.json b/fig-frontend/client/package-lock.json
new file mode 100644
index 0000000..01fb3ce
--- /dev/null
+++ b/fig-frontend/client/package-lock.json
@@ -0,0 +1,578 @@
+{
+ "name": "fig-frontend",
+ "version": "1.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "fig-frontend",
+ "version": "1.0.0",
+ "dependencies": {
+ "interactjs": "^1.10.26",
+ "lit": "^3.0.0"
+ },
+ "devDependencies": {
+ "esbuild": "^0.17.18",
+ "typescript": "^5.0.4",
+ "typescript-formatter": "^7.2.2",
+ "typescript-language-server": "^4.0.0"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.17.19",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.19.tgz",
+ "integrity": "sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.17.19",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.19.tgz",
+ "integrity": "sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.17.19",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.19.tgz",
+ "integrity": "sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.17.19",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.19.tgz",
+ "integrity": "sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.17.19",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.19.tgz",
+ "integrity": "sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.17.19",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.19.tgz",
+ "integrity": "sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.17.19",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.19.tgz",
+ "integrity": "sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.17.19",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.19.tgz",
+ "integrity": "sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.17.19",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.19.tgz",
+ "integrity": "sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.17.19",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.19.tgz",
+ "integrity": "sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.17.19",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.19.tgz",
+ "integrity": "sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.17.19",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.19.tgz",
+ "integrity": "sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.17.19",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.19.tgz",
+ "integrity": "sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.17.19",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.19.tgz",
+ "integrity": "sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.17.19",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.19.tgz",
+ "integrity": "sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.17.19",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.19.tgz",
+ "integrity": "sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.17.19",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.19.tgz",
+ "integrity": "sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.17.19",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.19.tgz",
+ "integrity": "sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.17.19",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.19.tgz",
+ "integrity": "sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.17.19",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.19.tgz",
+ "integrity": "sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.17.19",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.19.tgz",
+ "integrity": "sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.17.19",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.19.tgz",
+ "integrity": "sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@interactjs/types": {
+ "version": "1.10.26",
+ "resolved": "https://registry.npmjs.org/@interactjs/types/-/types-1.10.26.tgz",
+ "integrity": "sha512-DekYpdkMV3XJVd/0k3f4pJluZAsCiG86yEtVXvGLK0lS/Fj0+OzYEv7HoMpcBZSkQ8s7//yaeEBgnxy2tV81lA=="
+ },
+ "node_modules/@lit-labs/ssr-dom-shim": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.1.2.tgz",
+ "integrity": "sha512-jnOD+/+dSrfTWYfSXBXlo5l5f0q1UuJo3tkbMDCYA2lKUYq79jaxqtGEvnRoh049nt1vdo1+45RinipU6FGY2g=="
+ },
+ "node_modules/@lit/reactive-element": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.0.2.tgz",
+ "integrity": "sha512-SVOwLAWUQg3Ji1egtOt1UiFe4zdDpnWHyc5qctSceJ5XIu0Uc76YmGpIjZgx9YJ0XtdW0Jm507sDvjOu+HnB8w==",
+ "dependencies": {
+ "@lit-labs/ssr-dom-shim": "^1.1.2"
+ }
+ },
+ "node_modules/@types/trusted-types": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
+ "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="
+ },
+ "node_modules/commander": {
+ "version": "2.20.3",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
+ "dev": true
+ },
+ "node_modules/commandpost": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/commandpost/-/commandpost-1.4.0.tgz",
+ "integrity": "sha512-aE2Y4MTFJ870NuB/+2z1cXBhSBBzRydVVjzhFC4gtenEhpnj15yu0qptWGJsO9YGrcPZ3ezX8AWb1VA391MKpQ==",
+ "dev": true
+ },
+ "node_modules/editorconfig": {
+ "version": "0.15.3",
+ "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz",
+ "integrity": "sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==",
+ "dev": true,
+ "dependencies": {
+ "commander": "^2.19.0",
+ "lru-cache": "^4.1.5",
+ "semver": "^5.6.0",
+ "sigmund": "^1.0.1"
+ },
+ "bin": {
+ "editorconfig": "bin/editorconfig"
+ }
+ },
+ "node_modules/esbuild": {
+ "version": "0.17.19",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.19.tgz",
+ "integrity": "sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "optionalDependencies": {
+ "@esbuild/android-arm": "0.17.19",
+ "@esbuild/android-arm64": "0.17.19",
+ "@esbuild/android-x64": "0.17.19",
+ "@esbuild/darwin-arm64": "0.17.19",
+ "@esbuild/darwin-x64": "0.17.19",
+ "@esbuild/freebsd-arm64": "0.17.19",
+ "@esbuild/freebsd-x64": "0.17.19",
+ "@esbuild/linux-arm": "0.17.19",
+ "@esbuild/linux-arm64": "0.17.19",
+ "@esbuild/linux-ia32": "0.17.19",
+ "@esbuild/linux-loong64": "0.17.19",
+ "@esbuild/linux-mips64el": "0.17.19",
+ "@esbuild/linux-ppc64": "0.17.19",
+ "@esbuild/linux-riscv64": "0.17.19",
+ "@esbuild/linux-s390x": "0.17.19",
+ "@esbuild/linux-x64": "0.17.19",
+ "@esbuild/netbsd-x64": "0.17.19",
+ "@esbuild/openbsd-x64": "0.17.19",
+ "@esbuild/sunos-x64": "0.17.19",
+ "@esbuild/win32-arm64": "0.17.19",
+ "@esbuild/win32-ia32": "0.17.19",
+ "@esbuild/win32-x64": "0.17.19"
+ }
+ },
+ "node_modules/interactjs": {
+ "version": "1.10.26",
+ "resolved": "https://registry.npmjs.org/interactjs/-/interactjs-1.10.26.tgz",
+ "integrity": "sha512-5gNTNDTfEHp2EifqtWGi5VkD3CMZVJSTGmtK/IsVRd+rkOk3E63iVs5Z+IeD5K1Lr0qZpU2754VHAwf5i+Z9xg==",
+ "dependencies": {
+ "@interactjs/types": "1.10.26"
+ }
+ },
+ "node_modules/lit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/lit/-/lit-3.1.0.tgz",
+ "integrity": "sha512-rzo/hmUqX8zmOdamDAeydfjsGXbbdtAFqMhmocnh2j9aDYqbu0fjXygjCa0T99Od9VQ/2itwaGrjZz/ZELVl7w==",
+ "dependencies": {
+ "@lit/reactive-element": "^2.0.0",
+ "lit-element": "^4.0.0",
+ "lit-html": "^3.1.0"
+ }
+ },
+ "node_modules/lit-element": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-4.0.2.tgz",
+ "integrity": "sha512-/W6WQZUa5VEXwC7H9tbtDMdSs9aWil3Ou8hU6z2cOKWbsm/tXPAcsoaHVEtrDo0zcOIE5GF6QgU55tlGL2Nihg==",
+ "dependencies": {
+ "@lit-labs/ssr-dom-shim": "^1.1.2",
+ "@lit/reactive-element": "^2.0.0",
+ "lit-html": "^3.1.0"
+ }
+ },
+ "node_modules/lit-html": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-3.1.0.tgz",
+ "integrity": "sha512-FwAjq3iNsaO6SOZXEIpeROlJLUlrbyMkn4iuv4f4u1H40Jw8wkeR/OUXZUHUoiYabGk8Y4Y0F/rgq+R4MrOLmA==",
+ "dependencies": {
+ "@types/trusted-types": "^2.0.2"
+ }
+ },
+ "node_modules/lru-cache": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
+ "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
+ "dev": true,
+ "dependencies": {
+ "pseudomap": "^1.0.2",
+ "yallist": "^2.1.2"
+ }
+ },
+ "node_modules/pseudomap": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
+ "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==",
+ "dev": true
+ },
+ "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,
+ "bin": {
+ "semver": "bin/semver"
+ }
+ },
+ "node_modules/sigmund": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz",
+ "integrity": "sha512-fCvEXfh6NWpm+YSuY2bpXb/VIihqWA6hLsgboC+0nl71Q7N7o2eaCW8mJa/NLvQhs6jpd3VZV4UiUQlV6+lc8g==",
+ "dev": true
+ },
+ "node_modules/typescript": {
+ "version": "5.3.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz",
+ "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==",
+ "dev": true,
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/typescript-formatter": {
+ "version": "7.2.2",
+ "resolved": "https://registry.npmjs.org/typescript-formatter/-/typescript-formatter-7.2.2.tgz",
+ "integrity": "sha512-V7vfI9XArVhriOTYHPzMU2WUnm5IMdu9X/CPxs8mIMGxmTBFpDABlbkBka64PZJ9/xgQeRpK8KzzAG4MPzxBDQ==",
+ "dev": true,
+ "dependencies": {
+ "commandpost": "^1.0.0",
+ "editorconfig": "^0.15.0"
+ },
+ "bin": {
+ "tsfmt": "bin/tsfmt"
+ },
+ "engines": {
+ "node": ">= 4.2.0"
+ },
+ "peerDependencies": {
+ "typescript": "^2.1.6 || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev"
+ }
+ },
+ "node_modules/typescript-language-server": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/typescript-language-server/-/typescript-language-server-4.2.0.tgz",
+ "integrity": "sha512-1yKDqKeWLTQkN4mN+CT84aBr7ckp6sNVb8DZg+eXl0TDl14edn6Yh1wPqPA1rQ4AGVJc02fYbXTFsklaVYy4Uw==",
+ "dev": true,
+ "bin": {
+ "typescript-language-server": "lib/cli.mjs"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/yallist": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
+ "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==",
+ "dev": true
+ }
+ }
+}
diff --git a/fig-frontend/client/package.json b/fig-frontend/client/package.json
new file mode 100644
index 0000000..52b6451
--- /dev/null
+++ b/fig-frontend/client/package.json
@@ -0,0 +1,17 @@
+{
+ "name": "fig-frontend",
+ "version": "1.0.0",
+ "scripts": {
+ "build": "esbuild src/index.ts --loader:.jpg=file --outdir=../../fig-frontend-assets/js --bundle --minify"
+ },
+ "dependencies": {
+ "interactjs": "^1.10.26",
+ "lit": "^3.0.0"
+ },
+ "devDependencies": {
+ "esbuild": "^0.17.18",
+ "typescript": "^5.0.4",
+ "typescript-formatter": "^7.2.2",
+ "typescript-language-server": "^4.0.0"
+ }
+}
diff --git a/fig-frontend/client/src/blueprint.jpg b/fig-frontend/client/src/blueprint.jpg
new file mode 100644
index 0000000..6efe89d
--- /dev/null
+++ b/fig-frontend/client/src/blueprint.jpg
Binary files differ
diff --git a/fig-frontend/client/src/config.ts b/fig-frontend/client/src/config.ts
new file mode 100644
index 0000000..5498e16
--- /dev/null
+++ b/fig-frontend/client/src/config.ts
@@ -0,0 +1,3 @@
+export const URL = "http://localhost:8000";
+export const API_URL = "http://localhost:8000/api";
+export const CLIENT_ID = "q486jugzn2my4iw6l181o006ugye4j";
diff --git a/fig-frontend/client/src/index.css b/fig-frontend/client/src/index.css
new file mode 100644
index 0000000..891c5fd
--- /dev/null
+++ b/fig-frontend/client/src/index.css
@@ -0,0 +1,30 @@
+body {
+ margin: 0px;
+ position: absolute;
+ left: 0px;
+ top: 0px;
+ width: 100vw;
+ height: 100vh;
+}
+
+fig-window {
+ display: block;
+ position: absolute;
+}
+
+fig-header {
+ position: absolute;
+ text-align: center;
+ border-radius: 100px;
+ border-style: solid;
+ border-color: silver;
+ border-width: 5px;
+ background: linear-gradient(0deg, rgba(89,89,89,1) 35%, rgba(158,158,158,1) 100%);
+ top: 1em;
+ left: 33vw;
+ width: 33vw;
+}
+
+fig-header:hover {
+ filter: brightness(150%);
+}
diff --git a/fig-frontend/client/src/index.ts b/fig-frontend/client/src/index.ts
new file mode 100644
index 0000000..899c7fd
--- /dev/null
+++ b/fig-frontend/client/src/index.ts
@@ -0,0 +1,119 @@
+import { html, css, LitElement } from "lit";
+import { customElement, property } from "lit/decorators.js";
+
+import interact from "interactjs";
+
+import * as Config from "./config";
+import * as Twitch from "./twitch";
+
+import "./index.css";
+
+console.log("welcome to \"the junkyard\"");
+
+@customElement("fig-window")
+export class Window extends LitElement {
+ x: number;
+ y: number;
+
+ constructor() {
+ super();
+ this.x = 0;
+ this.y = 0;
+ interact(this).draggable({
+ listeners: {
+ move(event) {
+ event.target.x += event.dx
+ event.target.y += event.dy
+ event.target.style.left = `${event.target.x}px`
+ event.target.style.top = `${event.target.y}px`
+ },
+ }
+ });
+ }
+
+ render() {
+ console.log("render");
+ return html`
+<slot></slot>
+`;
+ }
+}
+
+@customElement("fig-backdrop")
+export class Backdrop extends LitElement {
+ static styles = css`
+#backdrop {
+ z-index: -2;
+ position: absolute;
+ left: 0px;
+ top: 0px;
+ width: 100vw;
+ height: 100vh;
+ background-image: url("blueprint.jpg");
+}
+#blur {
+ z-index: -1;
+ backdrop-filter: blur(3px);
+ position: absolute;
+ left: 0px;
+ top: 0px;
+ width: 100vw;
+ height: 100vh;
+ background-size: 100px 100px;
+ background-position: -20px -20px;
+ background-image:
+ linear-gradient(to right, lightgrey 1px, transparent 1px),
+ linear-gradient(to bottom, lightgrey 1px, transparent 1px);
+}
+`;
+ render() {
+ return html`
+<div id="backdrop"></div>
+<div id="blur"></div>
+`;
+ }
+}
+
+@customElement("fig-login")
+export class Login extends LitElement {
+ static styles = css`
+ `;
+
+ login() {
+ Twitch.startTwitchAuth();
+ }
+
+ async check() {
+ const resp = await fetch(`${Config.API_URL}/check`);
+ console.log(await resp.text());
+ }
+
+ render() {
+ const token = Twitch.getAuthToken();
+ console.log(token);
+ if (token) {
+ return html`
+<button @click=${this.check}>check token</button>
+`;
+ } else {
+ return html`
+<button @click=${this.login}>login</button>
+`;
+ }
+ }
+}
+
+@customElement("fig-header")
+export class Header extends LitElement {
+ static styles = css`
+h1 {
+ color: #b5a642;
+ font-family: "Rubik Maps";
+}
+`;
+ render() {
+ return html`
+<h1>Welcome To "The JunkYard"</h1>
+`;
+ }
+}
diff --git a/fig-frontend/client/src/twitch.ts b/fig-frontend/client/src/twitch.ts
new file mode 100644
index 0000000..4c264be
--- /dev/null
+++ b/fig-frontend/client/src/twitch.ts
@@ -0,0 +1,43 @@
+import * as Config from "./config";
+
+function generateNonce(): string {
+ var arr = new Uint8Array(20);
+ window.crypto.getRandomValues(arr);
+ return Array.from(arr, b => b.toString(16).padStart(2, "0")).join("");
+}
+
+export function startTwitchAuth() {
+ const nonce = generateNonce();
+ document.cookie = `authnonce=${nonce}; path=/;`;
+ window.location.href =
+ `https://id.twitch.tv/oauth2/authorize?response_type=id_token`
+ + `&client_id=${Config.CLIENT_ID}`
+ + `&redirect_uri=${Config.URL}`
+ + `&scope=openid`
+ + `&nonce=${nonce}`
+ + `&claims=${{id_token: {preferred_username: null}}}`
+ ;
+}
+
+export function getFragmentQuery(): Map<string, string> {
+ let query = new Map();
+ const hashQuery = document.location.hash.slice(1).split("&");
+ for (let equals of hashQuery) {
+ const pair = equals.split("=");
+ query.set(decodeURIComponent(pair[0]), decodeURIComponent(pair[1]));
+ }
+ return query;
+}
+
+export function getAuthToken(): String | null {
+ const frag = getFragmentQuery();
+ const token = frag.get("id_token");
+ if (token) {
+ document.cookie = `id_token=${token}; path=/; SameSite=Strict`;
+ }
+ for (let c of document.cookie.split("; ")) {
+ const [k, v] = c.split("=");
+ if (k === "id_token") return v;
+ }
+ return null;
+}
diff --git a/fig-frontend/client/tsconfig.json b/fig-frontend/client/tsconfig.json
new file mode 100644
index 0000000..d529f64
--- /dev/null
+++ b/fig-frontend/client/tsconfig.json
@@ -0,0 +1,18 @@
+{
+ "compilerOptions": {
+ "rootDir": "./src",
+ "module": "esnext",
+ "moduleResolution": "node",
+ "target": "es6",
+ "lib": ["ESNext", "dom"],
+ "skipLibCheck": true,
+ "useDefineForClassFields": false,
+ "experimentalDecorators": true,
+ "strictPropertyInitialization": false,
+ "noImplicitAny": true,
+ "strictNullChecks": true,
+ "removeComments": true,
+ "preserveConstEnums": true,
+ "sourceMap": true
+ }
+}