summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--fig-frontend-client/.psc-ide-port1
-rw-r--r--fig-frontend-client/assets/iosevka-comfy-regular.ttfbin0 -> 7811628 bytes
-rw-r--r--fig-frontend-client/assets/mrgreen.pngbin0 -> 714 bytes
-rwxr-xr-xfig-frontend-client/deploy.sh3
-rw-r--r--fig-frontend-client/index.html18
-rw-r--r--fig-frontend-client/main.css49
-rw-r--r--fig-frontend-client/main.js2493
-rw-r--r--fig-frontend-client/src/Main.purs269
-rw-r--r--fig-frontend/client/package-lock.json598
-rw-r--r--fig-frontend/client/package.json19
-rw-r--r--fig-frontend/client/src/assets/blueprint.jpgbin1308988 -> 0 bytes
-rw-r--r--fig-frontend/client/src/components/backdrop.ts41
-rw-r--r--fig-frontend/client/src/components/footer.ts72
-rw-r--r--fig-frontend/client/src/components/gizmo.ts34
-rw-r--r--fig-frontend/client/src/components/globals.d.ts2
-rw-r--r--fig-frontend/client/src/components/header.ts34
-rw-r--r--fig-frontend/client/src/components/login.ts34
-rw-r--r--fig-frontend/client/src/components/window.ts130
-rw-r--r--fig-frontend/client/src/config.ts4
-rw-r--r--fig-frontend/client/src/index.css14
-rw-r--r--fig-frontend/client/src/index.ts10
-rw-r--r--fig-frontend/client/src/state.ts13
-rw-r--r--fig-frontend/client/src/twitch.ts43
-rw-r--r--fig-frontend/client/tsconfig.json18
-rw-r--r--fig-frontend/src/Fig/Frontend.hs25
-rw-r--r--fig-monitor-bullfrog/fig-monitor-bullfrog.cabal3
-rw-r--r--fig-monitor-twitch/fig-monitor-twitch.cabal3
-rw-r--r--flake.lock276
-rw-r--r--flake.nix44
30 files changed, 3158 insertions, 1095 deletions
diff --git a/.gitignore b/.gitignore
index 93328ad..d82ba86 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,4 +3,5 @@ dist-newstyle
node_modules
fig-monitor-*.toml
fig-frontend.toml
-fig-frontend-assets \ No newline at end of file
+fig-frontend-assets
+fig-frontend-client/output/* \ No newline at end of file
diff --git a/fig-frontend-client/.psc-ide-port b/fig-frontend-client/.psc-ide-port
new file mode 100644
index 0000000..48a9dfe
--- /dev/null
+++ b/fig-frontend-client/.psc-ide-port
@@ -0,0 +1 @@
+15776 \ No newline at end of file
diff --git a/fig-frontend-client/assets/iosevka-comfy-regular.ttf b/fig-frontend-client/assets/iosevka-comfy-regular.ttf
new file mode 100644
index 0000000..b474adc
--- /dev/null
+++ b/fig-frontend-client/assets/iosevka-comfy-regular.ttf
Binary files differ
diff --git a/fig-frontend-client/assets/mrgreen.png b/fig-frontend-client/assets/mrgreen.png
new file mode 100644
index 0000000..1f1edca
--- /dev/null
+++ b/fig-frontend-client/assets/mrgreen.png
Binary files differ
diff --git a/fig-frontend-client/deploy.sh b/fig-frontend-client/deploy.sh
new file mode 100755
index 0000000..f68b833
--- /dev/null
+++ b/fig-frontend-client/deploy.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+purs-nix bundle
+scp -r main.css main.js index.html assets/ pub.colonq.computer:~/public_html
diff --git a/fig-frontend-client/index.html b/fig-frontend-client/index.html
new file mode 100644
index 0000000..ef70156
--- /dev/null
+++ b/fig-frontend-client/index.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
+ <title>LCOLONQ</title>
+ <link rel="icon" href="./assets/mrgreen.png">
+ <link rel="stylesheet" type="text/css" href="./main.css">
+ <script type="module" src="./main.js"></script>
+ </head>
+ <body>
+ <div id="lcolonq-title">
+ LCOLONQ
+ <div id="lcolonq-subtitle">hi</div>
+ </div>
+ <canvas id="lcolonq-canvas"></canvas>
+ </body>
+</html>
diff --git a/fig-frontend-client/main.css b/fig-frontend-client/main.css
new file mode 100644
index 0000000..a4b49a3
--- /dev/null
+++ b/fig-frontend-client/main.css
@@ -0,0 +1,49 @@
+@font-face {
+ font-family: "Iosevka Comfy";
+ src: url("assets/iosevka-comfy-regular.ttf") format("truetype");
+}
+
+html, body {
+ overflow: hidden;
+ margin: 0 !important;
+ padding: 0 !important;
+ height: 100%;
+ width: 100%;
+}
+
+body {
+ font-family: "Iosevka Comfy";
+ font-weight: bold;
+ background-color: #050505;
+ color: white;
+ user-select: none;
+ image-rendering: pixelated;
+}
+
+#lcolonq-title {
+ position: absolute;
+ top: 0px;
+ bottom: 0px;
+ left: 0px;
+ right: 0px;
+ text-align: center;
+ font-size: 20vw;
+}
+
+#lcolonq-subtitle {
+ font-size: 5vw;
+}
+
+#lcolonq-canvas {
+ position: absolute;
+ top: 0px;
+ bottom: 0px;
+ left: 0px;
+ right: 0px;
+ width: 100%;
+ height: 100%;
+}
+
+button {
+ color: red;
+}
diff --git a/fig-frontend-client/main.js b/fig-frontend-client/main.js
new file mode 100644
index 0000000..5cf9335
--- /dev/null
+++ b/fig-frontend-client/main.js
@@ -0,0 +1,2493 @@
+// output/Control.Semigroupoid/index.js
+var semigroupoidFn = {
+ compose: function(f) {
+ return function(g) {
+ return function(x) {
+ return f(g(x));
+ };
+ };
+ }
+};
+
+// output/Control.Category/index.js
+var identity = function(dict) {
+ return dict.identity;
+};
+var categoryFn = {
+ identity: function(x) {
+ return x;
+ },
+ Semigroupoid0: function() {
+ return semigroupoidFn;
+ }
+};
+
+// output/Data.Boolean/index.js
+var otherwise = true;
+
+// output/Data.Function/index.js
+var flip = function(f) {
+ return function(b) {
+ return function(a) {
+ return f(a)(b);
+ };
+ };
+};
+var $$const = function(a) {
+ return function(v) {
+ return a;
+ };
+};
+
+// output/Data.Functor/foreign.js
+var arrayMap = function(f) {
+ return function(arr) {
+ var l = arr.length;
+ var result = new Array(l);
+ for (var i = 0; i < l; i++) {
+ result[i] = f(arr[i]);
+ }
+ return result;
+ };
+};
+
+// output/Data.Unit/foreign.js
+var unit = void 0;
+
+// output/Type.Proxy/index.js
+var $$Proxy = /* @__PURE__ */ function() {
+ function $$Proxy2() {
+ }
+ ;
+ $$Proxy2.value = new $$Proxy2();
+ return $$Proxy2;
+}();
+
+// output/Data.Functor/index.js
+var map = function(dict) {
+ return dict.map;
+};
+var $$void = function(dictFunctor) {
+ return map(dictFunctor)($$const(unit));
+};
+var functorArray = {
+ map: arrayMap
+};
+
+// output/Control.Apply/index.js
+var identity2 = /* @__PURE__ */ identity(categoryFn);
+var apply = function(dict) {
+ return dict.apply;
+};
+var applySecond = function(dictApply) {
+ var apply1 = apply(dictApply);
+ var map4 = map(dictApply.Functor0());
+ return function(a) {
+ return function(b) {
+ return apply1(map4($$const(identity2))(a))(b);
+ };
+ };
+};
+
+// output/Control.Applicative/index.js
+var pure = function(dict) {
+ return dict.pure;
+};
+var when = function(dictApplicative) {
+ var pure12 = pure(dictApplicative);
+ return function(v) {
+ return function(v1) {
+ if (v) {
+ return v1;
+ }
+ ;
+ if (!v) {
+ return pure12(unit);
+ }
+ ;
+ throw new Error("Failed pattern match at Control.Applicative (line 63, column 1 - line 63, column 63): " + [v.constructor.name, v1.constructor.name]);
+ };
+ };
+};
+var liftA1 = function(dictApplicative) {
+ var apply2 = apply(dictApplicative.Apply0());
+ var pure12 = pure(dictApplicative);
+ return function(f) {
+ return function(a) {
+ return apply2(pure12(f))(a);
+ };
+ };
+};
+
+// output/Control.Bind/index.js
+var discard = function(dict) {
+ return dict.discard;
+};
+var bind = function(dict) {
+ return dict.bind;
+};
+var discardUnit = {
+ discard: function(dictBind) {
+ return bind(dictBind);
+ }
+};
+
+// output/Data.Bounded/foreign.js
+var topInt = 2147483647;
+var bottomInt = -2147483648;
+var topChar = String.fromCharCode(65535);
+var bottomChar = String.fromCharCode(0);
+var topNumber = Number.POSITIVE_INFINITY;
+var bottomNumber = Number.NEGATIVE_INFINITY;
+
+// output/Data.Ord/foreign.js
+var unsafeCompareImpl = function(lt) {
+ return function(eq3) {
+ return function(gt) {
+ return function(x) {
+ return function(y) {
+ return x < y ? lt : x === y ? eq3 : gt;
+ };
+ };
+ };
+ };
+};
+var ordIntImpl = unsafeCompareImpl;
+
+// output/Data.Eq/foreign.js
+var refEq = function(r1) {
+ return function(r2) {
+ return r1 === r2;
+ };
+};
+var eqBooleanImpl = refEq;
+var eqIntImpl = refEq;
+
+// output/Data.Symbol/index.js
+var reflectSymbol = function(dict) {
+ return dict.reflectSymbol;
+};
+
+// output/Record.Unsafe/foreign.js
+var unsafeGet = function(label4) {
+ return function(rec) {
+ return rec[label4];
+ };
+};
+
+// output/Data.Eq/index.js
+var eqRowNil = {
+ eqRecord: function(v) {
+ return function(v1) {
+ return function(v2) {
+ return true;
+ };
+ };
+ }
+};
+var eqRecord = function(dict) {
+ return dict.eqRecord;
+};
+var eqRec = function() {
+ return function(dictEqRecord) {
+ return {
+ eq: eqRecord(dictEqRecord)($$Proxy.value)
+ };
+ };
+};
+var eqInt = {
+ eq: eqIntImpl
+};
+var eqBoolean = {
+ eq: eqBooleanImpl
+};
+var eq = function(dict) {
+ return dict.eq;
+};
+var eq2 = /* @__PURE__ */ eq(eqBoolean);
+var eqRowCons = function(dictEqRecord) {
+ var eqRecord1 = eqRecord(dictEqRecord);
+ return function() {
+ return function(dictIsSymbol) {
+ var reflectSymbol2 = reflectSymbol(dictIsSymbol);
+ return function(dictEq) {
+ var eq3 = eq(dictEq);
+ return {
+ eqRecord: function(v) {
+ return function(ra) {
+ return function(rb) {
+ var tail = eqRecord1($$Proxy.value)(ra)(rb);
+ var key = reflectSymbol2($$Proxy.value);
+ var get2 = unsafeGet(key);
+ return eq3(get2(ra))(get2(rb)) && tail;
+ };
+ };
+ }
+ };
+ };
+ };
+ };
+};
+var notEq = function(dictEq) {
+ var eq3 = eq(dictEq);
+ return function(x) {
+ return function(y) {
+ return eq2(eq3(x)(y))(false);
+ };
+ };
+};
+
+// output/Data.Ordering/index.js
+var LT = /* @__PURE__ */ function() {
+ function LT2() {
+ }
+ ;
+ LT2.value = new LT2();
+ return LT2;
+}();
+var GT = /* @__PURE__ */ function() {
+ function GT2() {
+ }
+ ;
+ GT2.value = new GT2();
+ return GT2;
+}();
+var EQ = /* @__PURE__ */ function() {
+ function EQ2() {
+ }
+ ;
+ EQ2.value = new EQ2();
+ return EQ2;
+}();
+var eqOrdering = {
+ eq: function(v) {
+ return function(v1) {
+ if (v instanceof LT && v1 instanceof LT) {
+ return true;
+ }
+ ;
+ if (v instanceof GT && v1 instanceof GT) {
+ return true;
+ }
+ ;
+ if (v instanceof EQ && v1 instanceof EQ) {
+ return true;
+ }
+ ;
+ return false;
+ };
+ }
+};
+
+// output/Data.Ord/index.js
+var eqRec2 = /* @__PURE__ */ eqRec();
+var notEq2 = /* @__PURE__ */ notEq(eqOrdering);
+var ordRecordNil = {
+ compareRecord: function(v) {
+ return function(v1) {
+ return function(v2) {
+ return EQ.value;
+ };
+ };
+ },
+ EqRecord0: function() {
+ return eqRowNil;
+ }
+};
+var ordInt = /* @__PURE__ */ function() {
+ return {
+ compare: ordIntImpl(LT.value)(EQ.value)(GT.value),
+ Eq0: function() {
+ return eqInt;
+ }
+ };
+}();
+var compareRecord = function(dict) {
+ return dict.compareRecord;
+};
+var ordRecord = function() {
+ return function(dictOrdRecord) {
+ var eqRec1 = eqRec2(dictOrdRecord.EqRecord0());
+ return {
+ compare: compareRecord(dictOrdRecord)($$Proxy.value),
+ Eq0: function() {
+ return eqRec1;
+ }
+ };
+ };
+};
+var compare = function(dict) {
+ return dict.compare;
+};
+var ordRecordCons = function(dictOrdRecord) {
+ var compareRecord1 = compareRecord(dictOrdRecord);
+ var eqRowCons2 = eqRowCons(dictOrdRecord.EqRecord0())();
+ return function() {
+ return function(dictIsSymbol) {
+ var reflectSymbol2 = reflectSymbol(dictIsSymbol);
+ var eqRowCons1 = eqRowCons2(dictIsSymbol);
+ return function(dictOrd) {
+ var compare3 = compare(dictOrd);
+ var eqRowCons22 = eqRowCons1(dictOrd.Eq0());
+ return {
+ compareRecord: function(v) {
+ return function(ra) {
+ return function(rb) {
+ var key = reflectSymbol2($$Proxy.value);
+ var left = compare3(unsafeGet(key)(ra))(unsafeGet(key)(rb));
+ var $95 = notEq2(left)(EQ.value);
+ if ($95) {
+ return left;
+ }
+ ;
+ return compareRecord1($$Proxy.value)(ra)(rb);
+ };
+ };
+ },
+ EqRecord0: function() {
+ return eqRowCons22;
+ }
+ };
+ };
+ };
+ };
+};
+
+// output/Data.Bounded/index.js
+var top = function(dict) {
+ return dict.top;
+};
+var boundedInt = {
+ top: topInt,
+ bottom: bottomInt,
+ Ord0: function() {
+ return ordInt;
+ }
+};
+var bottom = function(dict) {
+ return dict.bottom;
+};
+
+// output/Data.Semigroup/foreign.js
+var concatArray = function(xs) {
+ return function(ys) {
+ if (xs.length === 0)
+ return ys;
+ if (ys.length === 0)
+ return xs;
+ return xs.concat(ys);
+ };
+};
+
+// output/Data.Semigroup/index.js
+var semigroupArray = {
+ append: concatArray
+};
+var append = function(dict) {
+ return dict.append;
+};
+
+// output/Data.Monoid/index.js
+var mempty = function(dict) {
+ return dict.mempty;
+};
+
+// output/Data.Tuple/index.js
+var Tuple = /* @__PURE__ */ function() {
+ function Tuple2(value0, value1) {
+ this.value0 = value0;
+ this.value1 = value1;
+ }
+ ;
+ Tuple2.create = function(value0) {
+ return function(value1) {
+ return new Tuple2(value0, value1);
+ };
+ };
+ return Tuple2;
+}();
+var snd = function(v) {
+ return v.value1;
+};
+var fst = function(v) {
+ return v.value0;
+};
+
+// output/Control.Monad.State.Class/index.js
+var state = function(dict) {
+ return dict.state;
+};
+var put = function(dictMonadState) {
+ var state1 = state(dictMonadState);
+ return function(s) {
+ return state1(function(v) {
+ return new Tuple(unit, s);
+ });
+ };
+};
+var modify_ = function(dictMonadState) {
+ var state1 = state(dictMonadState);
+ return function(f) {
+ return state1(function(s) {
+ return new Tuple(unit, f(s));
+ });
+ };
+};
+var get = function(dictMonadState) {
+ return state(dictMonadState)(function(s) {
+ return new Tuple(s, s);
+ });
+};
+
+// output/Control.Monad/index.js
+var ap = function(dictMonad) {
+ var bind2 = bind(dictMonad.Bind1());
+ var pure3 = pure(dictMonad.Applicative0());
+ return function(f) {
+ return function(a) {
+ return bind2(f)(function(f$prime) {
+ return bind2(a)(function(a$prime) {
+ return pure3(f$prime(a$prime));
+ });
+ });
+ };
+ };
+};
+
+// output/Data.Maybe/index.js
+var identity3 = /* @__PURE__ */ identity(categoryFn);
+var Nothing = /* @__PURE__ */ function() {
+ function Nothing2() {
+ }
+ ;
+ Nothing2.value = new Nothing2();
+ return Nothing2;
+}();
+var Just = /* @__PURE__ */ function() {
+ function Just2(value0) {
+ this.value0 = value0;
+ }
+ ;
+ Just2.create = function(value0) {
+ return new Just2(value0);
+ };
+ return Just2;
+}();
+var maybe = function(v) {
+ return function(v1) {
+ return function(v2) {
+ if (v2 instanceof Nothing) {
+ return v;
+ }
+ ;
+ if (v2 instanceof Just) {
+ return v1(v2.value0);
+ }
+ ;
+ throw new Error("Failed pattern match at Data.Maybe (line 237, column 1 - line 237, column 51): " + [v.constructor.name, v1.constructor.name, v2.constructor.name]);
+ };
+ };
+};
+var isNothing = /* @__PURE__ */ maybe(true)(/* @__PURE__ */ $$const(false));
+var fromMaybe = function(a) {
+ return maybe(a)(identity3);
+};
+var fromJust = function() {
+ return function(v) {
+ if (v instanceof Just) {
+ return v.value0;
+ }
+ ;
+ throw new Error("Failed pattern match at Data.Maybe (line 288, column 1 - line 288, column 46): " + [v.constructor.name]);
+ };
+};
+
+// output/Effect/foreign.js
+var pureE = function(a) {
+ return function() {
+ return a;
+ };
+};
+var bindE = function(a) {
+ return function(f) {
+ return function() {
+ return f(a())();
+ };
+ };
+};
+
+// output/Effect/index.js
+var $runtime_lazy = function(name15, moduleName, init) {
+ var state3 = 0;
+ var val;
+ return function(lineNumber) {
+ if (state3 === 2)
+ return val;
+ if (state3 === 1)
+ throw new ReferenceError(name15 + " was needed before it finished initializing (module " + moduleName + ", line " + lineNumber + ")", moduleName, lineNumber);
+ state3 = 1;
+ val = init();
+ state3 = 2;
+ return val;
+ };
+};
+var monadEffect = {
+ Applicative0: function() {
+ return applicativeEffect;
+ },
+ Bind1: function() {
+ return bindEffect;
+ }
+};
+var bindEffect = {
+ bind: bindE,
+ Apply0: function() {
+ return $lazy_applyEffect(0);
+ }
+};
+var applicativeEffect = {
+ pure: pureE,
+ Apply0: function() {
+ return $lazy_applyEffect(0);
+ }
+};
+var $lazy_functorEffect = /* @__PURE__ */ $runtime_lazy("functorEffect", "Effect", function() {
+ return {
+ map: liftA1(applicativeEffect)
+ };
+});
+var $lazy_applyEffect = /* @__PURE__ */ $runtime_lazy("applyEffect", "Effect", function() {
+ return {
+ apply: ap(monadEffect),
+ Functor0: function() {
+ return $lazy_functorEffect(0);
+ }
+ };
+});
+var functorEffect = /* @__PURE__ */ $lazy_functorEffect(20);
+var applyEffect = /* @__PURE__ */ $lazy_applyEffect(23);
+
+// output/Effect.Ref/foreign.js
+var _new = function(val) {
+ return function() {
+ return { value: val };
+ };
+};
+var read = function(ref) {
+ return function() {
+ return ref.value;
+ };
+};
+var write = function(val) {
+ return function(ref) {
+ return function() {
+ ref.value = val;
+ };
+ };
+};
+
+// output/Effect.Ref/index.js
+var $$new = _new;
+
+// output/Control.Monad.Trans.Class/index.js
+var lift = function(dict) {
+ return dict.lift;
+};
+
+// output/Effect.Class/index.js
+var monadEffectEffect = {
+ liftEffect: /* @__PURE__ */ identity(categoryFn),
+ Monad0: function() {
+ return monadEffect;
+ }
+};
+var liftEffect = function(dict) {
+ return dict.liftEffect;
+};
+
+// output/Control.Monad.State.Trans/index.js
+var runStateT = function(v) {
+ return v;
+};
+var monadTransStateT = {
+ lift: function(dictMonad) {
+ var bind2 = bind(dictMonad.Bind1());
+ var pure3 = pure(dictMonad.Applicative0());
+ return function(m) {
+ return function(s) {
+ return bind2(m)(function(x) {
+ return pure3(new Tuple(x, s));
+ });
+ };
+ };
+ }
+};
+var lift3 = /* @__PURE__ */ lift(monadTransStateT);
+var functorStateT = function(dictFunctor) {
+ var map4 = map(dictFunctor);
+ return {
+ map: function(f) {
+ return function(v) {
+ return function(s) {
+ return map4(function(v1) {
+ return new Tuple(f(v1.value0), v1.value1);
+ })(v(s));
+ };
+ };
+ }
+ };
+};
+var monadStateT = function(dictMonad) {
+ return {
+ Applicative0: function() {
+ return applicativeStateT(dictMonad);
+ },
+ Bind1: function() {
+ return bindStateT(dictMonad);
+ }
+ };
+};
+var bindStateT = function(dictMonad) {
+ var bind2 = bind(dictMonad.Bind1());
+ return {
+ bind: function(v) {
+ return function(f) {
+ return function(s) {
+ return bind2(v(s))(function(v1) {
+ var v3 = f(v1.value0);
+ return v3(v1.value1);
+ });
+ };
+ };
+ },
+ Apply0: function() {
+ return applyStateT(dictMonad);
+ }
+ };
+};
+var applyStateT = function(dictMonad) {
+ var functorStateT1 = functorStateT(dictMonad.Bind1().Apply0().Functor0());
+ return {
+ apply: ap(monadStateT(dictMonad)),
+ Functor0: function() {
+ return functorStateT1;
+ }
+ };
+};
+var applicativeStateT = function(dictMonad) {
+ var pure3 = pure(dictMonad.Applicative0());
+ return {
+ pure: function(a) {
+ return function(s) {
+ return pure3(new Tuple(a, s));
+ };
+ },
+ Apply0: function() {
+ return applyStateT(dictMonad);
+ }
+ };
+};
+var monadEffectState = function(dictMonadEffect) {
+ var Monad0 = dictMonadEffect.Monad0();
+ var monadStateT1 = monadStateT(Monad0);
+ return {
+ liftEffect: function() {
+ var $197 = lift3(Monad0);
+ var $198 = liftEffect(dictMonadEffect);
+ return function($199) {
+ return $197($198($199));
+ };
+ }(),
+ Monad0: function() {
+ return monadStateT1;
+ }
+ };
+};
+var monadStateStateT = function(dictMonad) {
+ var pure3 = pure(dictMonad.Applicative0());
+ var monadStateT1 = monadStateT(dictMonad);
+ return {
+ state: function(f) {
+ return function($200) {
+ return pure3(f($200));
+ };
+ },
+ Monad0: function() {
+ return monadStateT1;
+ }
+ };
+};
+
+// output/Data.Array/foreign.js
+var rangeImpl = function(start2, end) {
+ var step2 = start2 > end ? -1 : 1;
+ var result = new Array(step2 * (end - start2) + 1);
+ var i = start2, n = 0;
+ while (i !== end) {
+ result[n++] = i;
+ i += step2;
+ }
+ result[n] = i;
+ return result;
+};
+var replicateFill = function(count, value12) {
+ if (count < 1) {
+ return [];
+ }
+ var result = new Array(count);
+ return result.fill(value12);
+};
+var replicatePolyfill = function(count, value12) {
+ var result = [];
+ var n = 0;
+ for (var i = 0; i < count; i++) {
+ result[n++] = value12;
+ }
+ return result;
+};
+var replicateImpl = typeof Array.prototype.fill === "function" ? replicateFill : replicatePolyfill;
+var length = function(xs) {
+ return xs.length;
+};
+var unconsImpl = function(empty3, next, xs) {
+ return xs.length === 0 ? empty3({}) : next(xs[0])(xs.slice(1));
+};
+var indexImpl = function(just, nothing, xs, i) {
+ return i < 0 || i >= xs.length ? nothing : just(xs[i]);
+};
+var concat = function(xss) {
+ if (xss.length <= 1e4) {
+ return Array.prototype.concat.apply([], xss);
+ }
+ var result = [];
+ for (var i = 0, l = xss.length; i < l; i++) {
+ var xs = xss[i];
+ for (var j = 0, m = xs.length; j < m; j++) {
+ result.push(xs[j]);
+ }
+ }
+ return result;
+};
+
+// output/Data.Foldable/foreign.js
+var foldrArray = function(f) {
+ return function(init) {
+ return function(xs) {
+ var acc = init;
+ var len = xs.length;
+ for (var i = len - 1; i >= 0; i--) {
+ acc = f(xs[i])(acc);
+ }
+ return acc;
+ };
+ };
+};
+var foldlArray = function(f) {
+ return function(init) {
+ return function(xs) {
+ var acc = init;
+ var len = xs.length;
+ for (var i = 0; i < len; i++) {
+ acc = f(acc)(xs[i]);
+ }
+ return acc;
+ };
+ };
+};
+
+// output/Unsafe.Coerce/foreign.js
+var unsafeCoerce2 = function(x) {
+ return x;
+};
+
+// output/Data.Foldable/index.js
+var foldr = function(dict) {
+ return dict.foldr;
+};
+var foldl = function(dict) {
+ return dict.foldl;
+};
+var foldMapDefaultR = function(dictFoldable) {
+ var foldr2 = foldr(dictFoldable);
+ return function(dictMonoid) {
+ var append4 = append(dictMonoid.Semigroup0());
+ var mempty2 = mempty(dictMonoid);
+ return function(f) {
+ return foldr2(function(x) {
+ return function(acc) {
+ return append4(f(x))(acc);
+ };
+ })(mempty2);
+ };
+ };
+};
+var foldableArray = {
+ foldr: foldrArray,
+ foldl: foldlArray,
+ foldMap: function(dictMonoid) {
+ return foldMapDefaultR(foldableArray)(dictMonoid);
+ }
+};
+
+// output/Data.Function.Uncurried/foreign.js
+var runFn2 = function(fn) {
+ return function(a) {
+ return function(b) {
+ return fn(a, b);
+ };
+ };
+};
+var runFn3 = function(fn) {
+ return function(a) {
+ return function(b) {
+ return function(c) {
+ return fn(a, b, c);
+ };
+ };
+ };
+};
+var runFn4 = function(fn) {
+ return function(a) {
+ return function(b) {
+ return function(c) {
+ return function(d) {
+ return fn(a, b, c, d);
+ };
+ };
+ };
+ };
+};
+
+// output/Data.FunctorWithIndex/foreign.js
+var mapWithIndexArray = function(f) {
+ return function(xs) {
+ var l = xs.length;
+ var result = Array(l);
+ for (var i = 0; i < l; i++) {
+ result[i] = f(i)(xs[i]);
+ }
+ return result;
+ };
+};
+
+// output/Data.FunctorWithIndex/index.js
+var mapWithIndex = function(dict) {
+ return dict.mapWithIndex;
+};
+var functorWithIndexArray = {
+ mapWithIndex: mapWithIndexArray,
+ Functor0: function() {
+ return functorArray;
+ }
+};
+
+// output/Data.Traversable/foreign.js
+var traverseArrayImpl = /* @__PURE__ */ function() {
+ function array1(a) {
+ return [a];
+ }
+ function array2(a) {
+ return function(b) {
+ return [a, b];
+ };
+ }
+ function array3(a) {
+ return function(b) {
+ return function(c) {
+ return [a, b, c];
+ };
+ };
+ }
+ function concat2(xs) {
+ return function(ys) {
+ return xs.concat(ys);
+ };
+ }
+ return function(apply2) {
+ return function(map4) {
+ return function(pure3) {
+ return function(f) {
+ return function(array) {
+ function go2(bot, top3) {
+ switch (top3 - bot) {
+ case 0:
+ return pure3([]);
+ case 1:
+ return map4(array1)(f(array[bot]));
+ case 2:
+ return apply2(map4(array2)(f(array[bot])))(f(array[bot + 1]));
+ case 3:
+ return apply2(apply2(map4(array3)(f(array[bot])))(f(array[bot + 1])))(f(array[bot + 2]));
+ default:
+ var pivot = bot + Math.floor((top3 - bot) / 4) * 2;
+ return apply2(map4(concat2)(go2(bot, pivot)))(go2(pivot, top3));
+ }
+ }
+ return go2(0, array.length);
+ };
+ };
+ };
+ };
+ };
+}();
+
+// output/Data.Traversable/index.js
+var identity4 = /* @__PURE__ */ identity(categoryFn);
+var traverse = function(dict) {
+ return dict.traverse;
+};
+var sequenceDefault = function(dictTraversable) {
+ var traverse2 = traverse(dictTraversable);
+ return function(dictApplicative) {
+ return traverse2(dictApplicative)(identity4);
+ };
+};
+var traversableArray = {
+ traverse: function(dictApplicative) {
+ var Apply0 = dictApplicative.Apply0();
+ return traverseArrayImpl(apply(Apply0))(map(Apply0.Functor0()))(pure(dictApplicative));
+ },
+ sequence: function(dictApplicative) {
+ return sequenceDefault(traversableArray)(dictApplicative);
+ },
+ Functor0: function() {
+ return functorArray;
+ },
+ Foldable1: function() {
+ return foldableArray;
+ }
+};
+var $$for = function(dictApplicative) {
+ return function(dictTraversable) {
+ var traverse2 = traverse(dictTraversable)(dictApplicative);
+ return function(x) {
+ return function(f) {
+ return traverse2(f)(x);
+ };
+ };
+ };
+};
+
+// output/Data.Unfoldable/foreign.js
+var unfoldrArrayImpl = function(isNothing2) {
+ return function(fromJust4) {
+ return function(fst2) {
+ return function(snd2) {
+ return function(f) {
+ return function(b) {
+ var result = [];
+ var value12 = b;
+ while (true) {
+ var maybe2 = f(value12);
+ if (isNothing2(maybe2))
+ return result;
+ var tuple = fromJust4(maybe2);
+ result.push(fst2(tuple));
+ value12 = snd2(tuple);
+ }
+ };
+ };
+ };
+ };
+ };
+};
+
+// output/Data.Unfoldable1/foreign.js
+var unfoldr1ArrayImpl = function(isNothing2) {
+ return function(fromJust4) {
+ return function(fst2) {
+ return function(snd2) {
+ return function(f) {
+ return function(b) {
+ var result = [];
+ var value12 = b;
+ while (true) {
+ var tuple = f(value12);
+ result.push(fst2(tuple));
+ var maybe2 = snd2(tuple);
+ if (isNothing2(maybe2))
+ return result;
+ value12 = fromJust4(maybe2);
+ }
+ };
+ };
+ };
+ };
+ };
+};
+
+// output/Data.Unfoldable1/index.js
+var fromJust2 = /* @__PURE__ */ fromJust();
+var unfoldable1Array = {
+ unfoldr1: /* @__PURE__ */ unfoldr1ArrayImpl(isNothing)(fromJust2)(fst)(snd)
+};
+
+// output/Data.Unfoldable/index.js
+var fromJust3 = /* @__PURE__ */ fromJust();
+var unfoldr = function(dict) {
+ return dict.unfoldr;
+};
+var unfoldableArray = {
+ unfoldr: /* @__PURE__ */ unfoldrArrayImpl(isNothing)(fromJust3)(fst)(snd),
+ Unfoldable10: function() {
+ return unfoldable1Array;
+ }
+};
+
+// output/Data.Array/index.js
+var append2 = /* @__PURE__ */ append(semigroupArray);
+var uncons = /* @__PURE__ */ function() {
+ return runFn3(unconsImpl)($$const(Nothing.value))(function(x) {
+ return function(xs) {
+ return new Just({
+ head: x,
+ tail: xs
+ });
+ };
+ });
+}();
+var range2 = /* @__PURE__ */ runFn2(rangeImpl);
+var mapWithIndex2 = /* @__PURE__ */ mapWithIndex(functorWithIndexArray);
+var index = /* @__PURE__ */ function() {
+ return runFn4(indexImpl)(Just.create)(Nothing.value);
+}();
+var head = function(xs) {
+ return index(xs)(0);
+};
+var cons = function(x) {
+ return function(xs) {
+ return append2([x])(xs);
+ };
+};
+
+// output/Data.Int/foreign.js
+var fromNumberImpl = function(just) {
+ return function(nothing) {
+ return function(n) {
+ return (n | 0) === n ? just(n) : nothing;
+ };
+ };
+};
+var toNumber = function(n) {
+ return n;
+};
+var rem = function(x) {
+ return function(y) {
+ return x % y;
+ };
+};
+
+// output/Data.Number/foreign.js
+var isFiniteImpl = isFinite;
+var ceil = Math.ceil;
+var floor = Math.floor;
+
+// output/Data.Int/index.js
+var top2 = /* @__PURE__ */ top(boundedInt);
+var bottom2 = /* @__PURE__ */ bottom(boundedInt);
+var fromNumber = /* @__PURE__ */ function() {
+ return fromNumberImpl(Just.create)(Nothing.value);
+}();
+var unsafeClamp = function(x) {
+ if (!isFiniteImpl(x)) {
+ return 0;
+ }
+ ;
+ if (x >= toNumber(top2)) {
+ return top2;
+ }
+ ;
+ if (x <= toNumber(bottom2)) {
+ return bottom2;
+ }
+ ;
+ if (otherwise) {
+ return fromMaybe(0)(fromNumber(x));
+ }
+ ;
+ throw new Error("Failed pattern match at Data.Int (line 72, column 1 - line 72, column 29): " + [x.constructor.name]);
+};
+var floor2 = function($39) {
+ return unsafeClamp(floor($39));
+};
+var ceil2 = function($40) {
+ return unsafeClamp(ceil($40));
+};
+
+// output/Data.Map.Internal/index.js
+var $runtime_lazy2 = function(name15, moduleName, init) {
+ var state3 = 0;
+ var val;
+ return function(lineNumber) {
+ if (state3 === 2)
+ return val;
+ if (state3 === 1)
+ throw new ReferenceError(name15 + " was needed before it finished initializing (module " + moduleName + ", line " + lineNumber + ")", moduleName, lineNumber);
+ state3 = 1;
+ val = init();
+ state3 = 2;
+ return val;
+ };
+};
+var Leaf = /* @__PURE__ */ function() {
+ function Leaf2() {
+ }
+ ;
+ Leaf2.value = new Leaf2();
+ return Leaf2;
+}();
+var Node = /* @__PURE__ */ function() {
+ function Node2(value0, value1, value22, value32, value42, value52) {
+ this.value0 = value0;
+ this.value1 = value1;
+ this.value2 = value22;
+ this.value3 = value32;
+ this.value4 = value42;
+ this.value5 = value52;
+ }
+ ;
+ Node2.create = function(value0) {
+ return function(value1) {
+ return function(value22) {
+ return function(value32) {
+ return function(value42) {
+ return function(value52) {
+ return new Node2(value0, value1, value22, value32, value42, value52);
+ };
+ };
+ };
+ };
+ };
+ };
+ return Node2;
+}();
+var IterLeaf = /* @__PURE__ */ function() {
+ function IterLeaf2() {
+ }
+ ;
+ IterLeaf2.value = new IterLeaf2();
+ return IterLeaf2;
+}();
+var IterEmit = /* @__PURE__ */ function() {
+ function IterEmit2(value0, value1, value22) {
+ this.value0 = value0;
+ this.value1 = value1;
+ this.value2 = value22;
+ }
+ ;
+ IterEmit2.create = function(value0) {
+ return function(value1) {
+ return function(value22) {
+ return new IterEmit2(value0, value1, value22);
+ };
+ };
+ };
+ return IterEmit2;
+}();
+var IterNode = /* @__PURE__ */ function() {
+ function IterNode2(value0, value1) {
+ this.value0 = value0;
+ this.value1 = value1;
+ }
+ ;
+ IterNode2.create = function(value0) {
+ return function(value1) {
+ return new IterNode2(value0, value1);
+ };
+ };
+ return IterNode2;
+}();
+var Split = /* @__PURE__ */ function() {
+ function Split2(value0, value1, value22) {
+ this.value0 = value0;
+ this.value1 = value1;
+ this.value2 = value22;
+ }
+ ;
+ Split2.create = function(value0) {
+ return function(value1) {
+ return function(value22) {
+ return new Split2(value0, value1, value22);
+ };
+ };
+ };
+ return Split2;
+}();
+var SplitLast = /* @__PURE__ */ function() {
+ function SplitLast2(value0, value1, value22) {
+ this.value0 = value0;
+ this.value1 = value1;
+ this.value2 = value22;
+ }
+ ;
+ SplitLast2.create = function(value0) {
+ return function(value1) {
+ return function(value22) {
+ return new SplitLast2(value0, value1, value22);
+ };
+ };
+ };
+ return SplitLast2;
+}();
+var unsafeNode = function(k, v, l, r) {
+ if (l instanceof Leaf) {
+ if (r instanceof Leaf) {
+ return new Node(1, 1, k, v, l, r);
+ }
+ ;
+ if (r instanceof Node) {
+ return new Node(1 + r.value0 | 0, 1 + r.value1 | 0, k, v, l, r);
+ }
+ ;
+ throw new Error("Failed pattern match at Data.Map.Internal (line 680, column 5 - line 684, column 39): " + [r.constructor.name]);
+ }
+ ;
+ if (l instanceof Node) {
+ if (r instanceof Leaf) {
+ return new Node(1 + l.value0 | 0, 1 + l.value1 | 0, k, v, l, r);
+ }
+ ;
+ if (r instanceof Node) {
+ return new Node(1 + function() {
+ var $277 = l.value0 > r.value0;
+ if ($277) {
+ return l.value0;
+ }
+ ;
+ return r.value0;
+ }() | 0, (1 + l.value1 | 0) + r.value1 | 0, k, v, l, r);
+ }
+ ;
+ throw new Error("Failed pattern match at Data.Map.Internal (line 686, column 5 - line 690, column 68): " + [r.constructor.name]);
+ }
+ ;
+ throw new Error("Failed pattern match at Data.Map.Internal (line 678, column 32 - line 690, column 68): " + [l.constructor.name]);
+};
+var toMapIter = /* @__PURE__ */ function() {
+ return flip(IterNode.create)(IterLeaf.value);
+}();
+var stepWith = function(f) {
+ return function(next) {
+ return function(done) {
+ var go2 = function($copy_v) {
+ var $tco_done = false;
+ var $tco_result;
+ function $tco_loop(v) {
+ if (v instanceof IterLeaf) {
+ $tco_done = true;
+ return done(unit);
+ }
+ ;
+ if (v instanceof IterEmit) {
+ $tco_done = true;
+ return next(v.value0, v.value1, v.value2);
+ }
+ ;
+ if (v instanceof IterNode) {
+ $copy_v = f(v.value1)(v.value0);
+ return;
+ }
+ ;
+ throw new Error("Failed pattern match at Data.Map.Internal (line 918, column 8 - line 924, column 20): " + [v.constructor.name]);
+ }
+ ;
+ while (!$tco_done) {
+ $tco_result = $tco_loop($copy_v);
+ }
+ ;
+ return $tco_result;
+ };
+ return go2;
+ };
+ };
+};
+var singleton3 = function(k) {
+ return function(v) {
+ return new Node(1, 1, k, v, Leaf.value, Leaf.value);
+ };
+};
+var unsafeBalancedNode = /* @__PURE__ */ function() {
+ var height8 = function(v) {
+ if (v instanceof Leaf) {
+ return 0;
+ }
+ ;
+ if (v instanceof Node) {
+ return v.value0;
+ }
+ ;
+ throw new Error("Failed pattern match at Data.Map.Internal (line 735, column 12 - line 737, column 26): " + [v.constructor.name]);
+ };
+ var rotateLeft = function(k, v, l, rk, rv, rl, rr) {
+ if (rl instanceof Node && rl.value0 > height8(rr)) {
+ return unsafeNode(rl.value2, rl.value3, unsafeNode(k, v, l, rl.value4), unsafeNode(rk, rv, rl.value5, rr));
+ }
+ ;
+ return unsafeNode(rk, rv, unsafeNode(k, v, l, rl), rr);
+ };
+ var rotateRight = function(k, v, lk, lv, ll, lr, r) {
+ if (lr instanceof Node && height8(ll) <= lr.value0) {
+ return unsafeNode(lr.value2, lr.value3, unsafeNode(lk, lv, ll, lr.value4), unsafeNode(k, v, lr.value5, r));
+ }
+ ;
+ return unsafeNode(lk, lv, ll, unsafeNode(k, v, lr, r));
+ };
+ return function(k, v, l, r) {
+ if (l instanceof Leaf) {
+ if (r instanceof Leaf) {
+ return singleton3(k)(v);
+ }
+ ;
+ if (r instanceof Node && r.value0 > 1) {
+ return rotateLeft(k, v, l, r.value2, r.value3, r.value4, r.value5);
+ }
+ ;
+ return unsafeNode(k, v, l, r);
+ }
+ ;
+ if (l instanceof Node) {
+ if (r instanceof Node) {
+ if (r.value0 > (l.value0 + 1 | 0)) {
+ return rotateLeft(k, v, l, r.value2, r.value3, r.value4, r.value5);
+ }
+ ;
+ if (l.value0 > (r.value0 + 1 | 0)) {
+ return rotateRight(k, v, l.value2, l.value3, l.value4, l.value5, r);
+ }
+ ;
+ }
+ ;
+ if (r instanceof Leaf && l.value0 > 1) {
+ return rotateRight(k, v, l.value2, l.value3, l.value4, l.value5, r);
+ }
+ ;
+ return unsafeNode(k, v, l, r);
+ }
+ ;
+ throw new Error("Failed pattern match at Data.Map.Internal (line 695, column 40 - line 716, column 34): " + [l.constructor.name]);
+ };
+}();
+var $lazy_unsafeSplit = /* @__PURE__ */ $runtime_lazy2("unsafeSplit", "Data.Map.Internal", function() {
+ return function(comp, k, m) {
+ if (m instanceof Leaf) {
+ return new Split(Nothing.value, Leaf.value, Leaf.value);
+ }
+ ;
+ if (m instanceof Node) {
+ var v = comp(k)(m.value2);
+ if (v instanceof LT) {
+ var v1 = $lazy_unsafeSplit(771)(comp, k, m.value4);
+ return new Split(v1.value0, v1.value1, unsafeBalancedNode(m.value2, m.value3, v1.value2, m.value5));
+ }
+ ;
+ if (v instanceof GT) {
+ var v1 = $lazy_unsafeSplit(774)(comp, k, m.value5);
+ return new Split(v1.value0, unsafeBalancedNode(m.value2, m.value3, m.value4, v1.value1), v1.value2);
+ }
+ ;
+ if (v instanceof EQ) {
+ return new Split(new Just(m.value3), m.value4, m.value5);
+ }
+ ;
+ throw new Error("Failed pattern match at Data.Map.Internal (line 769, column 5 - line 777, column 30): " + [v.constructor.name]);
+ }
+ ;
+ throw new Error("Failed pattern match at Data.Map.Internal (line 765, column 34 - line 777, column 30): " + [m.constructor.name]);
+ };
+});
+var unsafeSplit = /* @__PURE__ */ $lazy_unsafeSplit(764);
+var $lazy_unsafeSplitLast = /* @__PURE__ */ $runtime_lazy2("unsafeSplitLast", "Data.Map.Internal", function() {
+ return function(k, v, l, r) {
+ if (r instanceof Leaf) {
+ return new SplitLast(k, v, l);
+ }
+ ;
+ if (r instanceof Node) {
+ var v1 = $lazy_unsafeSplitLast(757)(r.value2, r.value3, r.value4, r.value5);
+ return new SplitLast(v1.value0, v1.value1, unsafeBalancedNode(k, v, l, v1.value2));
+ }
+ ;
+ throw new Error("Failed pattern match at Data.Map.Internal (line 754, column 37 - line 758, column 57): " + [r.constructor.name]);
+ };
+});
+var unsafeSplitLast = /* @__PURE__ */ $lazy_unsafeSplitLast(753);
+var unsafeJoinNodes = function(v, v1) {
+ if (v instanceof Leaf) {
+ return v1;
+ }
+ ;
+ if (v instanceof Node) {
+ var v2 = unsafeSplitLast(v.value2, v.value3, v.value4, v.value5);
+ return unsafeBalancedNode(v2.value0, v2.value1, v2.value2, v1);
+ }
+ ;
+ throw new Error("Failed pattern match at Data.Map.Internal (line 742, column 25 - line 746, column 38): " + [v.constructor.name, v1.constructor.name]);
+};
+var $lazy_unsafeUnionWith = /* @__PURE__ */ $runtime_lazy2("unsafeUnionWith", "Data.Map.Internal", function() {
+ return function(comp, app, l, r) {
+ if (l instanceof Leaf) {
+ return r;
+ }
+ ;
+ if (r instanceof Leaf) {
+ return l;
+ }
+ ;
+ if (r instanceof Node) {
+ var v = unsafeSplit(comp, r.value2, l);
+ var l$prime = $lazy_unsafeUnionWith(787)(comp, app, v.value1, r.value4);
+ var r$prime = $lazy_unsafeUnionWith(788)(comp, app, v.value2, r.value5);
+ if (v.value0 instanceof Just) {
+ return unsafeBalancedNode(r.value2, app(v.value0.value0)(r.value3), l$prime, r$prime);
+ }
+ ;
+ if (v.value0 instanceof Nothing) {
+ return unsafeBalancedNode(r.value2, r.value3, l$prime, r$prime);
+ }
+ ;
+ throw new Error("Failed pattern match at Data.Map.Internal (line 789, column 5 - line 793, column 46): " + [v.value0.constructor.name]);
+ }
+ ;
+ throw new Error("Failed pattern match at Data.Map.Internal (line 782, column 42 - line 793, column 46): " + [l.constructor.name, r.constructor.name]);
+ };
+});
+var unsafeUnionWith = /* @__PURE__ */ $lazy_unsafeUnionWith(781);
+var unionWith = function(dictOrd) {
+ var compare2 = compare(dictOrd);
+ return function(app) {
+ return function(m1) {
+ return function(m2) {
+ return unsafeUnionWith(compare2, app, m1, m2);
+ };
+ };
+ };
+};
+var union = function(dictOrd) {
+ return unionWith(dictOrd)($$const);
+};
+var member = function(dictOrd) {
+ var compare2 = compare(dictOrd);
+ return function(k) {
+ var go2 = function($copy_v) {
+ var $tco_done = false;
+ var $tco_result;
+ function $tco_loop(v) {
+ if (v instanceof Leaf) {
+ $tco_done = true;
+ return false;
+ }
+ ;
+ if (v instanceof Node) {
+ var v1 = compare2(k)(v.value2);
+ if (v1 instanceof LT) {
+ $copy_v = v.value4;
+ return;
+ }
+ ;
+ if (v1 instanceof GT) {
+ $copy_v = v.value5;
+ return;
+ }
+ ;
+ if (v1 instanceof EQ) {
+ $tco_done = true;
+ return true;
+ }
+ ;
+ throw new Error("Failed pattern match at Data.Map.Internal (line 457, column 7 - line 460, column 19): " + [v1.constructor.name]);
+ }
+ ;
+ throw new Error("Failed pattern match at Data.Map.Internal (line 454, column 8 - line 460, column 19): " + [v.constructor.name]);
+ }
+ ;
+ while (!$tco_done) {
+ $tco_result = $tco_loop($copy_v);
+ }
+ ;
+ return $tco_result;
+ };
+ return go2;
+ };
+};
+var lookup = function(dictOrd) {
+ var compare2 = compare(dictOrd);
+ return function(k) {
+ var go2 = function($copy_v) {
+ var $tco_done = false;
+ var $tco_result;
+ function $tco_loop(v) {
+ if (v instanceof Leaf) {
+ $tco_done = true;
+ return Nothing.value;
+ }
+ ;
+ if (v instanceof Node) {
+ var v1 = compare2(k)(v.value2);
+ if (v1 instanceof LT) {
+ $copy_v = v.value4;
+ return;
+ }
+ ;
+ if (v1 instanceof GT) {
+ $copy_v = v.value5;
+ return;
+ }
+ ;
+ if (v1 instanceof EQ) {
+ $tco_done = true;
+ return new Just(v.value3);
+ }
+ ;
+ throw new Error("Failed pattern match at Data.Map.Internal (line 281, column 7 - line 284, column 22): " + [v1.constructor.name]);
+ }
+ ;
+ throw new Error("Failed pattern match at Data.Map.Internal (line 278, column 8 - line 284, column 22): " + [v.constructor.name]);
+ }
+ ;
+ while (!$tco_done) {
+ $tco_result = $tco_loop($copy_v);
+ }
+ ;
+ return $tco_result;
+ };
+ return go2;
+ };
+};
+var iterMapL = /* @__PURE__ */ function() {
+ var go2 = function($copy_iter) {
+ return function($copy_v) {
+ var $tco_var_iter = $copy_iter;
+ var $tco_done = false;
+ var $tco_result;
+ function $tco_loop(iter, v) {
+ if (v instanceof Leaf) {
+ $tco_done = true;
+ return iter;
+ }
+ ;
+ if (v instanceof Node) {
+ if (v.value5 instanceof Leaf) {
+ $tco_var_iter = new IterEmit(v.value2, v.value3, iter);
+ $copy_v = v.value4;
+ return;
+ }
+ ;
+ $tco_var_iter = new IterEmit(v.value2, v.value3, new IterNode(v.value5, iter));
+ $copy_v = v.value4;
+ return;
+ }
+ ;
+ throw new Error("Failed pattern match at Data.Map.Internal (line 929, column 13 - line 936, column 48): " + [v.constructor.name]);
+ }
+ ;
+ while (!$tco_done) {
+ $tco_result = $tco_loop($tco_var_iter, $copy_v);
+ }
+ ;
+ return $tco_result;
+ };
+ };
+ return go2;
+}();
+var stepAscCps = /* @__PURE__ */ stepWith(iterMapL);
+var stepUnfoldr = /* @__PURE__ */ function() {
+ var step2 = function(k, v, next) {
+ return new Just(new Tuple(new Tuple(k, v), next));
+ };
+ return stepAscCps(step2)(function(v) {
+ return Nothing.value;
+ });
+}();
+var toUnfoldable = function(dictUnfoldable) {
+ var $767 = unfoldr(dictUnfoldable)(stepUnfoldr);
+ return function($768) {
+ return $767(toMapIter($768));
+ };
+};
+var isEmpty = function(v) {
+ if (v instanceof Leaf) {
+ return true;
+ }
+ ;
+ return false;
+};
+var insert = function(dictOrd) {
+ var compare2 = compare(dictOrd);
+ return function(k) {
+ return function(v) {
+ var go2 = function(v1) {
+ if (v1 instanceof Leaf) {
+ return singleton3(k)(v);
+ }
+ ;
+ if (v1 instanceof Node) {
+ var v2 = compare2(k)(v1.value2);
+ if (v2 instanceof LT) {
+ return unsafeBalancedNode(v1.value2, v1.value3, go2(v1.value4), v1.value5);
+ }
+ ;
+ if (v2 instanceof GT) {
+ return unsafeBalancedNode(v1.value2, v1.value3, v1.value4, go2(v1.value5));
+ }
+ ;
+ if (v2 instanceof EQ) {
+ return new Node(v1.value0, v1.value1, k, v, v1.value4, v1.value5);
+ }
+ ;
+ throw new Error("Failed pattern match at Data.Map.Internal (line 469, column 7 - line 472, column 35): " + [v2.constructor.name]);
+ }
+ ;
+ throw new Error("Failed pattern match at Data.Map.Internal (line 466, column 8 - line 472, column 35): " + [v1.constructor.name]);
+ };
+ return go2;
+ };
+ };
+};
+var filterWithKey = function(dictOrd) {
+ return function(f) {
+ var go2 = function(v) {
+ if (v instanceof Leaf) {
+ return Leaf.value;
+ }
+ ;
+ if (v instanceof Node) {
+ if (f(v.value2)(v.value3)) {
+ return unsafeBalancedNode(v.value2, v.value3, go2(v.value4), go2(v.value5));
+ }
+ ;
+ if (otherwise) {
+ return unsafeJoinNodes(go2(v.value4), go2(v.value5));
+ }
+ ;
+ }
+ ;
+ throw new Error("Failed pattern match at Data.Map.Internal (line 625, column 8 - line 631, column 47): " + [v.constructor.name]);
+ };
+ return go2;
+ };
+};
+var filter = function(dictOrd) {
+ var $769 = filterWithKey(dictOrd);
+ return function($770) {
+ return $769($$const($770));
+ };
+};
+var empty2 = /* @__PURE__ */ function() {
+ return Leaf.value;
+}();
+var fromFoldable = function(dictOrd) {
+ var insert1 = insert(dictOrd);
+ return function(dictFoldable) {
+ return foldl(dictFoldable)(function(m) {
+ return function(v) {
+ return insert1(v.value0)(v.value1)(m);
+ };
+ })(empty2);
+ };
+};
+var unions = function(dictOrd) {
+ var union1 = union(dictOrd);
+ return function(dictFoldable) {
+ return foldl(dictFoldable)(union1)(empty2);
+ };
+};
+var $$delete = function(dictOrd) {
+ var compare2 = compare(dictOrd);
+ return function(k) {
+ var go2 = function(v) {
+ if (v instanceof Leaf) {
+ return Leaf.value;
+ }
+ ;
+ if (v instanceof Node) {
+ var v1 = compare2(k)(v.value2);
+ if (v1 instanceof LT) {
+ return unsafeBalancedNode(v.value2, v.value3, go2(v.value4), v.value5);
+ }
+ ;
+ if (v1 instanceof GT) {
+ return unsafeBalancedNode(v.value2, v.value3, v.value4, go2(v.value5));
+ }
+ ;
+ if (v1 instanceof EQ) {
+ return unsafeJoinNodes(v.value4, v.value5);
+ }
+ ;
+ throw new Error("Failed pattern match at Data.Map.Internal (line 496, column 7 - line 499, column 43): " + [v1.constructor.name]);
+ }
+ ;
+ throw new Error("Failed pattern match at Data.Map.Internal (line 493, column 8 - line 499, column 43): " + [v.constructor.name]);
+ };
+ return go2;
+ };
+};
+
+// output/Data.String.CodeUnits/foreign.js
+var toCharArray = function(s) {
+ return s.split("");
+};
+var singleton4 = function(c) {
+ return c;
+};
+var _charAt = function(just) {
+ return function(nothing) {
+ return function(i) {
+ return function(s) {
+ return i >= 0 && i < s.length ? just(s.charAt(i)) : nothing;
+ };
+ };
+ };
+};
+var length2 = function(s) {
+ return s.length;
+};
+
+// output/Data.String.CodeUnits/index.js
+var charAt2 = /* @__PURE__ */ function() {
+ return _charAt(Just.create)(Nothing.value);
+}();
+
+// output/Effect.Console/foreign.js
+var log2 = function(s) {
+ return function() {
+ console.log(s);
+ };
+};
+
+// output/Effect.Random/foreign.js
+var random = Math.random;
+
+// output/Effect.Random/index.js
+var randomInt = function(low2) {
+ return function(high2) {
+ return function __do3() {
+ var n = random();
+ var asNumber = (toNumber(high2) - toNumber(low2) + 1) * n + toNumber(low2);
+ return floor2(asNumber);
+ };
+ };
+};
+
+// output/Graphics.Canvas/foreign.js
+function getCanvasElementByIdImpl(id, Just2, Nothing2) {
+ return function() {
+ var el = document.getElementById(id);
+ if (el && el instanceof HTMLCanvasElement) {
+ return Just2(el);
+ } else {
+ return Nothing2;
+ }
+ };
+}
+function getContext2D(c) {
+ return function() {
+ return c.getContext("2d");
+ };
+}
+function setCanvasWidth(canvas) {
+ return function(width8) {
+ return function() {
+ canvas.width = width8;
+ };
+ };
+}
+function setCanvasHeight(canvas) {
+ return function(height8) {
+ return function() {
+ canvas.height = height8;
+ };
+ };
+}
+function setFillStyle(ctx) {
+ return function(style) {
+ return function() {
+ ctx.fillStyle = style;
+ };
+ };
+}
+function fillRect(ctx) {
+ return function(r) {
+ return function() {
+ ctx.fillRect(r.x, r.y, r.width, r.height);
+ };
+ };
+}
+function clearRect(ctx) {
+ return function(r) {
+ return function() {
+ ctx.clearRect(r.x, r.y, r.width, r.height);
+ };
+ };
+}
+function setFont(ctx) {
+ return function(fontspec) {
+ return function() {
+ ctx.font = fontspec;
+ };
+ };
+}
+function fillText(ctx) {
+ return function(text5) {
+ return function(x) {
+ return function(y) {
+ return function() {
+ ctx.fillText(text5, x, y);
+ };
+ };
+ };
+ };
+}
+
+// output/Graphics.Canvas/index.js
+var applySecond2 = /* @__PURE__ */ applySecond(applyEffect);
+var setCanvasDimensions = function(ce) {
+ return function(d) {
+ return applySecond2(setCanvasHeight(ce)(d.height))(setCanvasWidth(ce)(d.width));
+ };
+};
+var getCanvasElementById = function(elId) {
+ return getCanvasElementByIdImpl(elId, Just.create, Nothing.value);
+};
+
+// output/Web.Event.EventTarget/foreign.js
+function eventListener(fn) {
+ return function() {
+ return function(event) {
+ return fn(event)();
+ };
+ };
+}
+function addEventListener(type) {
+ return function(listener) {
+ return function(useCapture) {
+ return function(target5) {
+ return function() {
+ return target5.addEventListener(type, listener, useCapture);
+ };
+ };
+ };
+ };
+}
+
+// output/Web.HTML/foreign.js
+var windowImpl = function() {
+ return window;
+};
+
+// output/Web.Internal.FFI/foreign.js
+function _unsafeReadProtoTagged(nothing, just, name15, value12) {
+ if (typeof window !== "undefined") {
+ var ty = window[name15];
+ if (ty != null && value12 instanceof ty) {
+ return just(value12);
+ }
+ }
+ var obj = value12;
+ while (obj != null) {
+ var proto = Object.getPrototypeOf(obj);
+ var constructorName = proto.constructor.name;
+ if (constructorName === name15) {
+ return just(value12);
+ } else if (constructorName === "Object") {
+ return nothing;
+ }
+ obj = proto;
+ }
+ return nothing;
+}
+
+// output/Web.Internal.FFI/index.js
+var unsafeReadProtoTagged = function(name15) {
+ return function(value12) {
+ return _unsafeReadProtoTagged(Nothing.value, Just.create, name15, value12);
+ };
+};
+
+// output/Data.Nullable/foreign.js
+function nullable(a, r, f) {
+ return a == null ? r : f(a);
+}
+
+// output/Data.Nullable/index.js
+var toMaybe = function(n) {
+ return nullable(n, Nothing.value, Just.create);
+};
+
+// output/Web.HTML.Window/foreign.js
+function innerWidth(window2) {
+ return function() {
+ return window2.innerWidth;
+ };
+}
+function innerHeight(window2) {
+ return function() {
+ return window2.innerHeight;
+ };
+}
+function _open(url) {
+ return function(name15) {
+ return function(features) {
+ return function(window2) {
+ return function() {
+ return window2.open(url, name15, features);
+ };
+ };
+ };
+ };
+}
+function requestAnimationFrame(fn) {
+ return function(window2) {
+ return function() {
+ return window2.requestAnimationFrame(fn);
+ };
+ };
+}
+
+// output/Web.HTML.Window/index.js
+var map2 = /* @__PURE__ */ map(functorEffect);
+var toEventTarget = unsafeCoerce2;
+var open = function(url$prime) {
+ return function(name15) {
+ return function(features) {
+ return function(window2) {
+ return map2(toMaybe)(_open(url$prime)(name15)(features)(window2));
+ };
+ };
+ };
+};
+
+// output/Web.UIEvent.MouseEvent/foreign.js
+function pageX(e) {
+ return e.pageX;
+}
+function pageY(e) {
+ return e.pageY;
+}
+
+// output/Web.UIEvent.MouseEvent/index.js
+var fromEvent = /* @__PURE__ */ unsafeReadProtoTagged("MouseEvent");
+
+// output/Main/index.js
+var ordRecord2 = /* @__PURE__ */ ordRecord()(/* @__PURE__ */ ordRecordCons(/* @__PURE__ */ ordRecordCons(ordRecordNil)()({
+ reflectSymbol: function() {
+ return "y";
+ }
+})(ordInt))()({
+ reflectSymbol: function() {
+ return "x";
+ }
+})(ordInt));
+var filter2 = /* @__PURE__ */ filter(ordRecord2);
+var toUnfoldable2 = /* @__PURE__ */ toUnfoldable(unfoldableArray);
+var pure2 = /* @__PURE__ */ pure(applicativeEffect);
+var insert2 = /* @__PURE__ */ insert(ordRecord2);
+var $$delete2 = /* @__PURE__ */ $$delete(ordRecord2);
+var map3 = /* @__PURE__ */ map(functorEffect);
+var discard2 = /* @__PURE__ */ discard(discardUnit);
+var fromFoldable2 = /* @__PURE__ */ fromFoldable(ordRecord2)(foldableArray);
+var $$void2 = /* @__PURE__ */ $$void(functorEffect);
+var unions2 = /* @__PURE__ */ unions(ordRecord2)(foldableArray);
+var map1 = /* @__PURE__ */ map(functorArray);
+var union2 = /* @__PURE__ */ union(ordRecord2);
+var append3 = /* @__PURE__ */ append(semigroupArray);
+var lookup2 = /* @__PURE__ */ lookup(ordRecord2);
+var member2 = /* @__PURE__ */ member(ordRecord2);
+var $$for2 = /* @__PURE__ */ $$for(applicativeEffect)(traversableArray);
+var discard22 = /* @__PURE__ */ discard2(/* @__PURE__ */ bindStateT(monadEffect));
+var monadStateStateT2 = /* @__PURE__ */ monadStateStateT(monadEffect);
+var monadEffectState2 = /* @__PURE__ */ monadEffectState(monadEffectEffect);
+var applicativeStateT2 = /* @__PURE__ */ applicativeStateT(monadEffect);
+var pure1 = /* @__PURE__ */ pure(applicativeStateT2);
+var when2 = /* @__PURE__ */ when(applicativeStateT2);
+var void1 = /* @__PURE__ */ $$void(/* @__PURE__ */ functorStateT(functorEffect));
+var for1 = /* @__PURE__ */ $$for(applicativeStateT2)(traversableArray);
+var GfxWhiteout = /* @__PURE__ */ function() {
+ function GfxWhiteout2() {
+ }
+ ;
+ GfxWhiteout2.value = new GfxWhiteout2();
+ return GfxWhiteout2;
+}();
+var EventGfx = /* @__PURE__ */ function() {
+ function EventGfx2(value0) {
+ this.value0 = value0;
+ }
+ ;
+ EventGfx2.create = function(value0) {
+ return new EventGfx2(value0);
+ };
+ return EventGfx2;
+}();
+var EventMouseClick = /* @__PURE__ */ function() {
+ function EventMouseClick2(value0, value1) {
+ this.value0 = value0;
+ this.value1 = value1;
+ }
+ ;
+ EventMouseClick2.create = function(value0) {
+ return function(value1) {
+ return new EventMouseClick2(value0, value1);
+ };
+ };
+ return EventMouseClick2;
+}();
+var EventMouseMove = /* @__PURE__ */ function() {
+ function EventMouseMove2(value0, value1) {
+ this.value0 = value0;
+ this.value1 = value1;
+ }
+ ;
+ EventMouseMove2.create = function(value0) {
+ return function(value1) {
+ return new EventMouseMove2(value0, value1);
+ };
+ };
+ return EventMouseMove2;
+}();
+var tick = function(dictMonadState) {
+ return modify_(dictMonadState)(function(st) {
+ var $109 = {};
+ for (var $110 in st) {
+ if ({}.hasOwnProperty.call(st, $110)) {
+ $109[$110] = st[$110];
+ }
+ ;
+ }
+ ;
+ $109.tick = st.tick + 1 | 0;
+ $109.transitions = function() {
+ var v1 = uncons(st.transitions);
+ if (v1 instanceof Nothing) {
+ return st.transitions;
+ }
+ ;
+ if (v1 instanceof Just) {
+ var $105 = isEmpty(v1.value0.head.cells);
+ if ($105) {
+ return v1.value0.tail;
+ }
+ ;
+ return st.transitions;
+ }
+ ;
+ throw new Error("Failed pattern match at Main (line 217, column 19 - line 219, column 79): " + [v1.constructor.name]);
+ }();
+ $109.inverse = filter2(function(v1) {
+ return st.tick <= v1;
+ })(st.inverse);
+ return $109;
+ });
+};
+var tick1 = /* @__PURE__ */ tick(monadStateStateT2);
+var pickRandom = function(cells2) {
+ var arr = toUnfoldable2(cells2);
+ return function __do3() {
+ var idx = randomInt(0)(length(arr) - 1 | 0)();
+ var v = index(arr)(idx);
+ if (v instanceof Nothing) {
+ return Nothing.value;
+ }
+ ;
+ if (v instanceof Just) {
+ return new Just(v.value0);
+ }
+ ;
+ throw new Error("Failed pattern match at Main (line 135, column 3 - line 137, column 28): " + [v.constructor.name]);
+ };
+};
+var pickCell = function(dictMonadState) {
+ var get2 = get(dictMonadState);
+ var put2 = put(dictMonadState);
+ return function(dictMonadEffect) {
+ var Monad0 = dictMonadEffect.Monad0();
+ var bind1 = bind(Monad0.Bind1());
+ var pure22 = pure(Monad0.Applicative0());
+ var liftEffect2 = liftEffect(dictMonadEffect);
+ return bind1(get2)(function(st) {
+ var v = uncons(st.transitions);
+ if (v instanceof Nothing) {
+ return pure22(unit);
+ }
+ ;
+ if (v instanceof Just) {
+ return bind1(liftEffect2(v.value0.head.picker(v.value0.head.cells)))(function(v1) {
+ if (v1 instanceof Nothing) {
+ return pure22(unit);
+ }
+ ;
+ if (v1 instanceof Just) {
+ return put2(function() {
+ var $119 = {};
+ for (var $120 in st) {
+ if ({}.hasOwnProperty.call(st, $120)) {
+ $119[$120] = st[$120];
+ }
+ ;
+ }
+ ;
+ $119.cells = insert2(v1.value0.value0)(v1.value0.value1)(st.cells);
+ $119.transitions = cons(function() {
+ var $116 = {};
+ for (var $117 in v.value0.head) {
+ if ({}.hasOwnProperty.call(v.value0.head, $117)) {
+ $116[$117] = v["value0"]["head"][$117];
+ }
+ ;
+ }
+ ;
+ $116.cells = $$delete2(v1.value0.value0)(v.value0.head.cells);
+ return $116;
+ }())(v.value0.tail);
+ return $119;
+ }());
+ }
+ ;
+ throw new Error("Failed pattern match at Main (line 249, column 49 - line 252, column 120): " + [v1.constructor.name]);
+ });
+ }
+ ;
+ throw new Error("Failed pattern match at Main (line 246, column 3 - line 252, column 120): " + [v.constructor.name]);
+ });
+ };
+};
+var pickCell1 = /* @__PURE__ */ pickCell(monadStateStateT2)(monadEffectState2);
+var newContext = function __do() {
+ var w = windowImpl();
+ var v = getCanvasElementById("lcolonq-canvas")();
+ if (v instanceof Nothing) {
+ return Nothing.value;
+ }
+ ;
+ if (v instanceof Just) {
+ var width8 = map3(toNumber)(innerWidth(w))();
+ var height8 = map3(toNumber)(innerHeight(w))();
+ setCanvasDimensions(v.value0)({
+ width: width8,
+ height: height8
+ })();
+ var render = getContext2D(v.value0)();
+ setFont(render)("bold 0.8vw Iosevka Comfy")();
+ var cellDim = toNumber(ceil2(width8 / 100));
+ return new Just({
+ window: w,
+ canvas: v.value0,
+ render,
+ width: width8,
+ height: height8,
+ cellDim,
+ widthCells: ceil2(100),
+ heightCells: ceil2(height8 / cellDim),
+ events: [new EventGfx(GfxWhiteout.value)]
+ });
+ }
+ ;
+ throw new Error("Failed pattern match at Main (line 77, column 45 - line 97, column 10): " + [v.constructor.name]);
+};
+var initialState = {
+ tick: 0,
+ cells: empty2,
+ inverse: empty2,
+ transitions: []
+};
+var gfxTransitions = function(ctx) {
+ return function(v) {
+ var link = function(y) {
+ return function(fgc) {
+ return function(bgc) {
+ return function(str) {
+ return function(url) {
+ return fromFoldable2(mapWithIndex2(function(i) {
+ return function(c) {
+ return new Tuple({
+ x: i,
+ y
+ }, {
+ bg: bgc,
+ fg: fgc,
+ "char": singleton4(c),
+ click: function(st) {
+ return function __do3() {
+ $$void2(open(url)("_blank")("")(ctx.window))();
+ return st;
+ };
+ }
+ });
+ };
+ })(toCharArray(str)));
+ };
+ };
+ };
+ };
+ };
+ var fg = unions2([link(0)("purple")("white")("twitch.tv/lcolonq")("https://twitch.tv/lcolonq"), link(1)("blue")("white")("twitter.com/lcolonq")("https://twitter.com/lcolonq")]);
+ var bg = fromFoldable2(concat(flip(map1)(range2(0)(ctx.widthCells))(function(x) {
+ return flip(map1)(range2(0)(ctx.heightCells))(function(y) {
+ return new Tuple({
+ x,
+ y
+ }, {
+ bg: "white",
+ fg: "black",
+ click: pure2,
+ "char": function() {
+ var v1 = charAt2(rem(x + y | 0)(length2("LCOLONQ")))("LCOLONQ");
+ if (v1 instanceof Nothing) {
+ return "?";
+ }
+ ;
+ if (v1 instanceof Just) {
+ return singleton4(v1.value0);
+ }
+ ;
+ throw new Error("Failed pattern match at Main (line 182, column 12 - line 184, column 39): " + [v1.constructor.name]);
+ }()
+ });
+ });
+ })));
+ var cells2 = union2(fg)(bg);
+ return [{
+ cells: cells2,
+ speed: 20,
+ cadence: 1,
+ picker: pickRandom
+ }];
+ };
+};
+var pullEvents = function(dictMonadState) {
+ var get2 = get(dictMonadState);
+ var put2 = put(dictMonadState);
+ return function(dictMonadEffect) {
+ var Monad0 = dictMonadEffect.Monad0();
+ var Bind1 = Monad0.Bind1();
+ var bind1 = bind(Bind1);
+ var liftEffect2 = liftEffect(dictMonadEffect);
+ var pure22 = pure(Monad0.Applicative0());
+ var discard3 = discard2(Bind1);
+ return function(rc) {
+ return bind1(liftEffect2(read(rc)))(function(ctx) {
+ return bind1(get2)(function(st) {
+ return bind1(function() {
+ var v = uncons(ctx.events);
+ if (v instanceof Nothing) {
+ return pure22(st);
+ }
+ ;
+ if (v instanceof Just) {
+ return discard3(liftEffect2(write({
+ canvas: ctx.canvas,
+ cellDim: ctx.cellDim,
+ height: ctx.height,
+ heightCells: ctx.heightCells,
+ render: ctx.render,
+ width: ctx.width,
+ widthCells: ctx.widthCells,
+ window: ctx.window,
+ events: v.value0.tail
+ })(rc)))(function() {
+ if (v.value0.head instanceof EventGfx) {
+ return pure22({
+ cells: st.cells,
+ inverse: st.inverse,
+ tick: st.tick,
+ transitions: append3(st.transitions)(gfxTransitions(ctx)(v.value0.head.value0))
+ });
+ }
+ ;
+ if (v.value0.head instanceof EventMouseClick) {
+ var v1 = lookup2({
+ x: v.value0.head.value0,
+ y: v.value0.head.value1
+ })(st.cells);
+ if (v1 instanceof Nothing) {
+ return pure22(st);
+ }
+ ;
+ if (v1 instanceof Just) {
+ return liftEffect2(v1.value0.click(st));
+ }
+ ;
+ throw new Error("Failed pattern match at Main (line 234, column 11 - line 236, column 53): " + [v1.constructor.name]);
+ }
+ ;
+ if (v.value0.head instanceof EventMouseMove) {
+ var inv = fromFoldable2(concat(flip(map1)(range2(v.value0.head.value0 - 1 | 0)(v.value0.head.value0 + 1 | 0))(function(x) {
+ return flip(map1)(range2(v.value0.head.value1 - 1 | 0)(v.value0.head.value1 + 1 | 0))(function(y) {
+ return new Tuple({
+ x,
+ y
+ }, st.tick + 30 | 0);
+ });
+ })));
+ return pure22({
+ cells: st.cells,
+ tick: st.tick,
+ transitions: st.transitions,
+ inverse: union2(inv)(st.inverse)
+ });
+ }
+ ;
+ throw new Error("Failed pattern match at Main (line 231, column 7 - line 240, column 53): " + [v.value0.head.constructor.name]);
+ });
+ }
+ ;
+ throw new Error("Failed pattern match at Main (line 227, column 10 - line 240, column 53): " + [v.constructor.name]);
+ }())(function(st$prime) {
+ return put2(st$prime);
+ });
+ });
+ });
+ };
+ };
+};
+var pullEvents1 = /* @__PURE__ */ pullEvents(monadStateStateT2)(monadEffectState2);
+var drawCell = function(ctx) {
+ return function(st) {
+ return function(v) {
+ return function(pos) {
+ var x = toNumber(pos.x) * ctx.cellDim;
+ var y = toNumber(pos.y) * ctx.cellDim;
+ var fg = function() {
+ var $150 = member2({
+ x: pos.x,
+ y: pos.y
+ })(st.inverse);
+ if ($150) {
+ return v.bg;
+ }
+ ;
+ return v.fg;
+ }();
+ var bg = function() {
+ var $151 = member2({
+ x: pos.x,
+ y: pos.y
+ })(st.inverse);
+ if ($151) {
+ return v.fg;
+ }
+ ;
+ return v.bg;
+ }();
+ return function __do3() {
+ setFillStyle(ctx.render)(bg)();
+ fillRect(ctx.render)({
+ x,
+ y,
+ width: ctx.cellDim,
+ height: ctx.cellDim
+ })();
+ setFillStyle(ctx.render)(fg)();
+ return fillText(ctx.render)(v["char"])(x + ctx.cellDim / 4)(y + ctx.cellDim / 1.4)();
+ };
+ };
+ };
+ };
+};
+var drawCells = function(ctx) {
+ return function(st) {
+ return function(cells2) {
+ return $$void2($$for2(toUnfoldable2(cells2))(function(v) {
+ return drawCell(ctx)(st)(v.value1)(v.value0);
+ }));
+ };
+ };
+};
+var loop2 = function(rc) {
+ return function(st) {
+ return function __do3() {
+ var ctx = read(rc)();
+ clearRect(ctx.render)({
+ x: 0,
+ y: 0,
+ width: ctx.width,
+ height: ctx.height
+ })();
+ drawCells(ctx)(st)(st.cells)();
+ var v = flip(runStateT)(st)(discard22(tick1)(function() {
+ return discard22(pullEvents1(rc))(function() {
+ var v2 = head(st.transitions);
+ if (v2 instanceof Nothing) {
+ return pure1(unit);
+ }
+ ;
+ if (v2 instanceof Just) {
+ return when2(rem(st.tick)(v2.value0.cadence) === 0)(void1(for1(range2(0)(v2.value0.speed))(function(v1) {
+ return pickCell1;
+ })));
+ }
+ ;
+ throw new Error("Failed pattern match at Main (line 264, column 5 - line 268, column 58): " + [v2.constructor.name]);
+ });
+ }))();
+ return $$void2(requestAnimationFrame(loop2(rc)(v.value1))(ctx.window))();
+ };
+ };
+};
+var main = function __do2() {
+ var w = windowImpl();
+ (function __do3() {
+ var v = newContext();
+ if (v instanceof Nothing) {
+ return log2("failed to find canvas")();
+ }
+ ;
+ if (v instanceof Just) {
+ var rc = $$new(v.value0)();
+ var lresize = eventListener(function(_e) {
+ return function __do4() {
+ var v1 = newContext();
+ if (v1 instanceof Nothing) {
+ return log2("failed to find canvas")();
+ }
+ ;
+ if (v1 instanceof Just) {
+ return write(v1.value0)(rc)();
+ }
+ ;
+ throw new Error("Failed pattern match at Main (line 56, column 24 - line 58, column 41): " + [v1.constructor.name]);
+ };
+ })();
+ addEventListener("resize")(lresize)(false)(toEventTarget(w))();
+ var lmouse = function(h) {
+ return eventListener(function(e) {
+ var v1 = fromEvent(e);
+ if (v1 instanceof Nothing) {
+ return pure2(unit);
+ }
+ ;
+ if (v1 instanceof Just) {
+ var px = toNumber(pageX(v1.value0));
+ var py = toNumber(pageY(v1.value0));
+ return function __do4() {
+ var ctx = read(rc)();
+ return write({
+ canvas: ctx.canvas,
+ cellDim: ctx.cellDim,
+ height: ctx.height,
+ heightCells: ctx.heightCells,
+ render: ctx.render,
+ width: ctx.width,
+ widthCells: ctx.widthCells,
+ window: ctx.window,
+ events: cons(h(floor2(px / ctx.cellDim))(floor2(py / ctx.cellDim)))(ctx.events)
+ })(rc)();
+ };
+ }
+ ;
+ throw new Error("Failed pattern match at Main (line 60, column 42 - line 66, column 116): " + [v1.constructor.name]);
+ });
+ };
+ var lmouseclick = lmouse(EventMouseClick.create)();
+ addEventListener("click")(lmouseclick)(false)(toEventTarget(w))();
+ var lmousemove = lmouse(EventMouseMove.create)();
+ addEventListener("mousemove")(lmousemove)(false)(toEventTarget(w))();
+ return loop2(rc)(initialState)();
+ }
+ ;
+ throw new Error("Failed pattern match at Main (line 51, column 18 - line 71, column 27): " + [v.constructor.name]);
+ })();
+ return unit;
+};
+
+// <stdin>
+main();
diff --git a/fig-frontend-client/src/Main.purs b/fig-frontend-client/src/Main.purs
new file mode 100644
index 0000000..723acd8
--- /dev/null
+++ b/fig-frontend-client/src/Main.purs
@@ -0,0 +1,269 @@
+module Main where
+
+import Prelude
+
+import Control.Monad.State (class MonadState, get, modify_, put, runStateT)
+import Data.Array (concat, cons, head, length, mapWithIndex, range, uncons, zip, (!!))
+import Data.Int (ceil, floor, rem, round, toNumber)
+import Data.Map (Map, delete, empty, filter, fromFoldable, insert, isEmpty, lookup, member, toUnfoldable, union, unions)
+import Data.Maybe (Maybe(..))
+import Data.Set (Set)
+import Data.Set as Set
+import Data.String.CodeUnits (toCharArray)
+import Data.String.CodeUnits as String
+import Data.Traversable (for)
+import Data.Tuple (Tuple(..))
+import Effect (Effect)
+import Effect.Class (class MonadEffect, liftEffect)
+import Effect.Console (log)
+import Effect.Random (randomInt)
+import Effect.Ref (Ref, new, read, write)
+import Graphics.Canvas (CanvasElement, Context2D, clearRect, fillRect, fillText, getCanvasElementById, getContext2D, setCanvasDimensions, setFillStyle, setFont)
+import Web.Event.Event (EventType(..))
+import Web.Event.EventTarget (addEventListener, eventListener)
+import Web.HTML (window)
+import Web.HTML.Window (Window, innerHeight, innerWidth, open, requestAnimationFrame)
+import Web.HTML.Window as Window
+import Web.UIEvent.MouseEvent (fromEvent, pageX, pageY)
+
+type Context =
+ { window :: Window
+ , canvas :: CanvasElement
+ , render :: Context2D
+ , width :: Number
+ , height :: Number
+ , cellDim :: Number
+ , widthCells :: Int
+ , heightCells :: Int
+ , events :: Array Event
+ }
+
+main :: Effect Unit
+main = do
+ -- d <- toDocument <$> document w
+ -- getElementById "foo" (toNonElementParentNode d) >>= case _ of
+ -- Nothing -> log "failed to find foo"
+ -- Just e -> do
+ -- l <- eventListener \_e ->
+ -- log "click"
+ -- addEventListener click l false $ toEventTarget e
+ w <- window
+ newContext >>= case _ of
+ Nothing -> log "failed to find canvas"
+ Just ictx -> do
+ rc <- new ictx
+ lresize <- eventListener \_e -> do
+ newContext >>= case _ of
+ Nothing -> log "failed to find canvas"
+ Just newctx -> write newctx rc
+ addEventListener (EventType "resize") lresize false $ Window.toEventTarget w
+ let lmouse h = eventListener \e -> case fromEvent e of
+ Nothing -> pure unit
+ Just me -> do
+ let px = toNumber $ pageX me
+ let py = toNumber $ pageY me
+ ctx <- read rc
+ write (ctx { events = cons (h (floor $ px / ctx.cellDim) (floor $ py / ctx.cellDim)) ctx.events }) rc
+ lmouseclick <- lmouse EventMouseClick
+ addEventListener (EventType "click") lmouseclick false $ Window.toEventTarget w
+ lmousemove <- lmouse EventMouseMove
+ addEventListener (EventType "mousemove") lmousemove false $ Window.toEventTarget w
+ loop rc initialState
+ pure unit
+
+newContext :: Effect (Maybe Context)
+newContext = do
+ w <- window
+ getCanvasElementById "lcolonq-canvas" >>= case _ of
+ Nothing -> pure Nothing
+ Just canvas -> do
+ width <- toNumber <$> innerWidth w
+ height <- toNumber <$> innerHeight w
+ setCanvasDimensions canvas { width, height }
+ render <- getContext2D canvas
+ setFont render "bold 0.8vw Iosevka Comfy"
+ let widthCells = 100.0
+ let cellDim = toNumber $ ceil $ width / widthCells
+ pure $ Just
+ { window: w
+ , canvas
+ , render
+ , width
+ , height
+ , cellDim
+ , widthCells: ceil widthCells
+ , heightCells: ceil $ height / cellDim
+ , events: [EventGfx GfxWhiteout]
+ }
+
+newtype Cell = Cell
+ { fg :: String
+ , bg :: String
+ , char :: String
+ , click :: State -> Effect State
+ }
+
+drawCell :: forall t. Context -> State -> Cell -> { x :: Int, y :: Int | t } -> Effect Unit
+drawCell ctx st (Cell c) pos = do
+ let x = toNumber pos.x * ctx.cellDim
+ let y = toNumber pos.y * ctx.cellDim
+ let fg = if member { x: pos.x, y: pos.y } st.inverse then c.bg else c.fg
+ let bg = if member { x: pos.x, y: pos.y } st.inverse then c.fg else c.bg
+ setFillStyle ctx.render bg
+ fillRect ctx.render
+ { x
+ , y
+ , width: ctx.cellDim
+ , height: ctx.cellDim
+ }
+ setFillStyle ctx.render fg
+ fillText ctx.render c.char (x + ctx.cellDim / 4.0) (y + ctx.cellDim / 1.4)
+
+type Cells = Map { x :: Int, y :: Int } Cell
+
+drawCells :: Context -> State -> Cells -> Effect Unit
+drawCells ctx st cells = do
+ void $ for (toUnfoldable cells :: Array _) \(Tuple pos c) -> do
+ drawCell ctx st c pos
+
+type Picker = Cells -> Effect (Maybe (Tuple { x :: Int, y :: Int} Cell))
+
+pickRandom :: Picker
+pickRandom cells = do
+ let arr = toUnfoldable cells
+ idx <- randomInt 0 $ length arr - 1
+ case arr !! idx of
+ Nothing -> pure Nothing
+ Just c -> pure $ Just c
+
+type Transition =
+ { cells :: Cells
+ , speed :: Int
+ , cadence :: Int
+ , picker :: Picker
+ }
+
+type State =
+ { tick :: Int
+ , cells :: Cells
+ , inverse :: Map { x :: Int, y :: Int } Int
+ , transitions :: Array Transition
+ }
+
+initialState :: State
+initialState =
+ { tick: 0
+ , cells: empty
+ , inverse: empty
+ , transitions: []
+ }
+
+data Event
+ = EventGfx Gfx
+ | EventMouseClick Int Int
+ | EventMouseMove Int Int
+
+data Gfx
+ = GfxWhiteout
+
+gfxTransitions :: Context -> Gfx -> Array Transition
+gfxTransitions ctx GfxWhiteout =
+ let
+ bg = fromFoldable $ concat $ flip map (range 0 ctx.widthCells) \x ->
+ flip map (range 0 ctx.heightCells) \y ->
+ Tuple
+ { x, y }
+ $ Cell
+ { bg: "white"
+ , fg: "black"
+ , click: pure
+ , char:
+ let base = "LCOLONQ"
+ in case String.charAt (rem (x + y) (String.length base)) base of
+ Nothing -> "?"
+ Just c -> String.singleton c
+ }
+ link :: Int -> String -> String -> String -> String -> Cells
+ link y fgc bgc str url =
+ fromFoldable $ mapWithIndex
+ (\i c ->
+ Tuple { x: i, y }
+ $ Cell
+ { bg: bgc, fg: fgc, char: String.singleton c
+ , click: \st -> do
+ void $ open url "_blank" "" ctx.window
+ pure st
+ }
+ )
+ $ toCharArray str
+ fg =
+ unions
+ [ link 0 "purple" "white" "twitch.tv/lcolonq" "https://twitch.tv/lcolonq"
+ , link 1 "blue" "white" "twitter.com/lcolonq" "https://twitter.com/lcolonq"
+ ]
+ cells = union fg bg
+ in
+ [ { cells
+ , speed: 20
+ , cadence: 1
+ , picker: pickRandom
+ }
+ ]
+
+tick :: forall m. MonadState State m => m Unit
+tick = modify_ \st ->
+ st
+ { tick = st.tick + 1
+ , transitions = case uncons st.transitions of
+ Nothing -> st.transitions
+ Just { head, tail } -> if isEmpty head.cells then tail else st.transitions
+ , inverse = filter (st.tick <= _) st.inverse
+ }
+
+pullEvents :: forall m. MonadState State m => MonadEffect m => Ref Context -> m Unit
+pullEvents rc = do
+ ctx <- liftEffect $ read rc
+ st <- get
+ st' <- case uncons ctx.events of
+ Nothing -> pure st
+ Just { head, tail } -> do
+ liftEffect $ write (ctx { events = tail }) rc
+ case head of
+ EventGfx gfx -> pure $ st { transitions = st.transitions <> gfxTransitions ctx gfx }
+ EventMouseClick mx my ->
+ case lookup { x: mx, y: my } st.cells of
+ Nothing -> pure st
+ Just (Cell c) -> liftEffect $ c.click st
+ EventMouseMove mx my -> do
+ let inv = fromFoldable $ concat $ flip map (range (mx - 1) (mx + 1)) \x ->
+ flip map (range (my - 1) (my + 1)) \y -> Tuple { x, y } (st.tick + 30)
+ pure st { inverse = union inv st.inverse }
+ put st'
+
+pickCell :: forall m. MonadState State m => MonadEffect m => m Unit
+pickCell = do
+ st <- get
+ case uncons st.transitions of
+ Nothing -> pure unit
+ Just { head: trans, tail } ->
+ liftEffect (trans.picker trans.cells) >>= case _ of
+ Nothing -> pure unit
+ Just (Tuple pk pv) ->
+ put st { cells = insert pk pv st.cells, transitions = cons (trans { cells = (delete pk trans.cells) }) tail }
+
+loop :: Ref Context -> State -> Effect Unit
+loop rc st = do
+ ctx <- read rc
+ -- render
+ clearRect ctx.render { x: 0.0, y: 0.0, width: ctx.width, height: ctx.height }
+ drawCells ctx st st.cells
+ -- update
+ Tuple _ st' <- flip runStateT st do
+ tick
+ pullEvents rc
+ case head st.transitions of
+ Nothing -> pure unit
+ Just trans -> do
+ when (rem st.tick trans.cadence == 0) do
+ void $ for (range 0 trans.speed) \_ -> pickCell
+ void $ requestAnimationFrame (loop rc st') ctx.window
diff --git a/fig-frontend/client/package-lock.json b/fig-frontend/client/package-lock.json
deleted file mode 100644
index ab2278b..0000000
--- a/fig-frontend/client/package-lock.json
+++ /dev/null
@@ -1,598 +0,0 @@
-{
- "name": "fig-frontend",
- "version": "1.0.0",
- "lockfileVersion": 3,
- "requires": true,
- "packages": {
- "": {
- "name": "fig-frontend",
- "version": "1.0.0",
- "dependencies": {
- "@adobe/lit-mobx": "^2.2.1",
- "interactjs": "^1.10.26",
- "lit": "^3.0.0",
- "mobx": "^6.12.0"
- },
- "devDependencies": {
- "esbuild": "^0.17.18",
- "typescript": "^5.0.4",
- "typescript-formatter": "^7.2.2",
- "typescript-language-server": "^4.0.0"
- }
- },
- "node_modules/@adobe/lit-mobx": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/@adobe/lit-mobx/-/lit-mobx-2.2.1.tgz",
- "integrity": "sha512-5CCGIjPkzOG5k1pyJSzpQMhj/BSWy3hzykawtxZ4oM/wItqgEitfxypqHlAIDhfMhhp4J4OlFlqCzbnEL6sYzQ==",
- "peerDependencies": {
- "lit": "^2.0.0 || ^3.0.0",
- "mobx": "^5.0.0 || ^6.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/mobx": {
- "version": "6.12.0",
- "resolved": "https://registry.npmjs.org/mobx/-/mobx-6.12.0.tgz",
- "integrity": "sha512-Mn6CN6meXEnMa0a5u6a5+RKrqRedHBhZGd15AWLk9O6uFY4KYHzImdt8JI8WODo1bjTSRnwXhJox+FCUZhCKCQ==",
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/mobx"
- }
- },
- "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
deleted file mode 100644
index 2812cd4..0000000
--- a/fig-frontend/client/package.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "name": "fig-frontend",
- "version": "1.0.0",
- "scripts": {
- "build": "esbuild src/index.ts --loader:.jpg=file --outdir=../../fig-frontend-assets/js --bundle --minify"
- },
- "dependencies": {
- "@adobe/lit-mobx": "^2.2.1",
- "interactjs": "^1.10.26",
- "lit": "^3.0.0",
- "mobx": "^6.12.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/assets/blueprint.jpg b/fig-frontend/client/src/assets/blueprint.jpg
deleted file mode 100644
index 6efe89d..0000000
--- a/fig-frontend/client/src/assets/blueprint.jpg
+++ /dev/null
Binary files differ
diff --git a/fig-frontend/client/src/components/backdrop.ts b/fig-frontend/client/src/components/backdrop.ts
deleted file mode 100644
index d35d205..0000000
--- a/fig-frontend/client/src/components/backdrop.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-import { html, css, LitElement, unsafeCSS } from "lit";
-import { customElement } from "lit/decorators.js";
-
-import * as Config from "../config";
-
-import blueprint from "../assets/blueprint.jpg";
-
-@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("${unsafeCSS(new URL(blueprint, Config.SCRIPT_URL))}");
-}
-#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>
-`;
- }
-}
diff --git a/fig-frontend/client/src/components/footer.ts b/fig-frontend/client/src/components/footer.ts
deleted file mode 100644
index 64e35ae..0000000
--- a/fig-frontend/client/src/components/footer.ts
+++ /dev/null
@@ -1,72 +0,0 @@
-import { html, css, LitElement } from "lit";
-import { customElement, state } from "lit/decorators.js";
-
-import * as Config from "../config";
-import * as State from "../state";
-import * as Twitch from "../twitch";
-
-@customElement("fig-footer")
-export class Footer extends LitElement {
- private global = State.global;
- static styles = css`
-#footer {
- position: absolute;
- bottom: 0px;
- left: 0px;
- right: 0px;
- height: 4ex;
- background: linear-gradient(0deg, rgba(79,39,0,1) 0%, rgba(212,151,113,1) 50%, rgba(213,139,45,1) 100%);
-}
-button {
- font-family: "Rubik Maps";
- height: 100%;
- color: black;
- border-style: none;
- background: linear-gradient(0deg, rgba(79,39,0,1) 0%, rgba(212,151,113,1) 50%, rgba(213,139,45,1) 100%);
- filter: brightness(125%);
-}
-button:hover {
- filter: brightness(150%);
-}
-button:active {
- filter: brightness(75%);
-}
-`;
-
- // twitch login
- login() {
- Twitch.startTwitchAuth();
- }
- async check() {
- const resp = await fetch(`${Config.API_URL}/check`);
- console.log(await resp.text());
- }
- button_login() {
- const token = Twitch.getAuthToken();
- console.log(token);
- if (token) {
- return html`
-<button @click=${this.check}>CHECK</button>
-`;
- } else {
- return html`
-<button @click=${this.login}>LOGIN</button>
-`;
- }
- }
-
- // toggle gizmo pane
- toggle_gizmo() {
- console.log(this.global.gizmo_active);
- this.global.toggle_gizmo();
- }
-
- render() {
- return html`
-<div id="footer">
- ${this.button_login()}
- <button @click=${this.toggle_gizmo}>GIZMO</button>
-</div>
-`;
- }
-}
diff --git a/fig-frontend/client/src/components/gizmo.ts b/fig-frontend/client/src/components/gizmo.ts
deleted file mode 100644
index bd1285c..0000000
--- a/fig-frontend/client/src/components/gizmo.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import { MobxLitElement } from "@adobe/lit-mobx";
-import { html, css } from "lit";
-import { customElement } from "lit/decorators.js";
-
-import * as State from "../state";
-
-@customElement("fig-gizmo")
-export class Gizmo extends MobxLitElement {
- private global = State.global;
-
- static style = css`
-`;
-
- static get(id: string): Gizmo | null {
- const e = document.getElementById(id);
- if (e instanceof Gizmo) return e;
- return null;
- }
-
- constructor() {
- super();
- }
-
- render() {
- console.log("render", this.global.gizmo_active);
- if (this.global.gizmo_active) {
- return html`
-<fig-window>
-<h1>hi</h1>
-</fig-window>
-`;
- }
- }
-}
diff --git a/fig-frontend/client/src/components/globals.d.ts b/fig-frontend/client/src/components/globals.d.ts
deleted file mode 100644
index 65e20c0..0000000
--- a/fig-frontend/client/src/components/globals.d.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-declare module "*.png";
-declare module "*.jpg";
diff --git a/fig-frontend/client/src/components/header.ts b/fig-frontend/client/src/components/header.ts
deleted file mode 100644
index c4c709f..0000000
--- a/fig-frontend/client/src/components/header.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import { html, css, LitElement } from "lit";
-import { customElement } from "lit/decorators.js";
-
-@customElement("fig-header")
-export class Header extends LitElement {
- static styles = css`
-#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;
-}
-#header:hover {
- filter: brightness(150%);
-}
-h1 {
- color: #b5a642;
- font-family: "Rubik Maps";
-}
-`;
- render() {
- return html`
-<div id="header">
- <h1>"The JunkYard"</h1>
-</div>
-`;
- }
-}
diff --git a/fig-frontend/client/src/components/login.ts b/fig-frontend/client/src/components/login.ts
deleted file mode 100644
index 195c97f..0000000
--- a/fig-frontend/client/src/components/login.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import { html, css, LitElement } from "lit";
-import { customElement } from "lit/decorators.js";
-
-import * as Config from "../config";
-import * as Twitch from "../twitch";
-
-@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>
-`;
- }
- }
-}
diff --git a/fig-frontend/client/src/components/window.ts b/fig-frontend/client/src/components/window.ts
deleted file mode 100644
index 9a8f93a..0000000
--- a/fig-frontend/client/src/components/window.ts
+++ /dev/null
@@ -1,130 +0,0 @@
-import { html, css, LitElement } from "lit";
-import { customElement, property } from "lit/decorators.js";
-
-import interact from "interactjs";
-
-@customElement("fig-window")
-export class Window extends LitElement {
- static z: number = 0;
-
- x: number;
- y: number;
-
- @property()
- title: string;
-
- @property()
- hidden: boolean;
-
- static styles = css`
-#windowcontainer {
- z-index: 0;
- position: relative;
- width: 100%;
- height: 100%;
- display: grid;
- grid-template-columns: auto;
- grid-template-rows: 4ex 1fr;
- user-select: none;
-}
-#title {
- font-family: "Rubik Maps";
- font-size: 150%;
- color: black;
- grid-column: 1;
- grid-row: 1;
- height: 2.2ex;
- overflow: hidden;
- z-index: 2;
- margin-bottom: -1ex;
- background: linear-gradient(0deg, rgba(89,89,89,1) 35%, rgba(158,158,158,1) 100%);
- border-radius: 100px;
- border-style: solid;
- border-color: silver;
- border-width: 5px;
- text-align: center;
-}
-#window {
- overflow: hidden;
- grid-column: 1;
- grid-row-start: 2;
- grid-row-end: 2;
- z-index: 1;
- background-color: white;
- border-radius: 5ex;
- border-style: solid;
- border-color: black;
- border-width: 2px;
- border-top-width: 0px;
- padding-top: 1ex;
- padding-left: 2ex;
- padding-right: 2ex;
-}
-`;
-
- static get(id: string): Window | null {
- const e = document.getElementById(id);
- if (e instanceof Window) return e;
- return null;
- }
-
- constructor() {
- super();
- this.x = 0;
- this.y = 0;
- this.style.left = `${this.x}px`
- this.style.top = `${this.y}px`
- this.style.width = "300px"
- this.style.height = "300px"
- interact(this).draggable({
- allowFrom: "#title",
- modifiers: [
- interact.modifiers.restrict({
- restriction: "body",
- endOnly: true
- })
- ],
- 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`
- },
- }
- }).resizable({
- edges: { top: false, bottom: true, left: true, right: true },
- listeners: {
- move(event) {
- event.target.x += event.deltaRect.left
- event.target.y += event.deltaRect.top
- event.target.style.left = `${event.target.x}px`
- event.target.style.top = `${event.target.y}px`
- event.target.style.width = `${Math.max(event.rect.width, 300)}px`
- event.target.style.height = `${Math.max(event.rect.height, 300)}px`
- },
- },
- });
- }
-
- toggle() {
- this.hidden = !this.hidden;
- }
-
- click() {
- this.style.zIndex = `${++Window.z}`;
- }
-
- render() {
- if (!this.hidden) {
- return html`
-<div id="windowcontainer" @pointerdown=${this.click}>
- <div id="title">${this.title}</slot></div>
- <div id="window">
- <slot></slot>
- </div>
-</div>
-`;
- }
- }
-}
diff --git a/fig-frontend/client/src/config.ts b/fig-frontend/client/src/config.ts
deleted file mode 100644
index e001107..0000000
--- a/fig-frontend/client/src/config.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export const URL = "http://localhost:8000";
-export const API_URL = `${URL}/api/`;
-export const SCRIPT_URL = `${URL}/js/`;
-export const CLIENT_ID = "q486jugzn2my4iw6l181o006ugye4j";
diff --git a/fig-frontend/client/src/index.css b/fig-frontend/client/src/index.css
deleted file mode 100644
index b1c8427..0000000
--- a/fig-frontend/client/src/index.css
+++ /dev/null
@@ -1,14 +0,0 @@
-body {
- margin: 0px;
- position: absolute;
- left: 0px;
- top: 0px;
- width: 100vw;
- height: 100vh;
- overflow: hidden;
-}
-
-fig-window {
- display: block;
- position: absolute;
-}
diff --git a/fig-frontend/client/src/index.ts b/fig-frontend/client/src/index.ts
deleted file mode 100644
index be0b0c5..0000000
--- a/fig-frontend/client/src/index.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import "./components/backdrop";
-import "./components/header";
-import "./components/footer";
-import "./components/login";
-import "./components/window";
-import "./components/gizmo";
-
-import "./index.css";
-
-console.log("welcome to \"the junkyard\"");
diff --git a/fig-frontend/client/src/state.ts b/fig-frontend/client/src/state.ts
deleted file mode 100644
index 19bc5d9..0000000
--- a/fig-frontend/client/src/state.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import { observable, action } from 'mobx';
-
-class Global {
- @observable
- public gizmo_active: boolean = true;
-
- @action
- public toggle_gizmo() {
- this.gizmo_active = !this.gizmo_active;
- }
-}
-
-export const global = new Global();
diff --git a/fig-frontend/client/src/twitch.ts b/fig-frontend/client/src/twitch.ts
deleted file mode 100644
index 4c264be..0000000
--- a/fig-frontend/client/src/twitch.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-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
deleted file mode 100644
index d529f64..0000000
--- a/fig-frontend/client/tsconfig.json
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- "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
- }
-}
diff --git a/fig-frontend/src/Fig/Frontend.hs b/fig-frontend/src/Fig/Frontend.hs
index b1c6aed..fd2754c 100644
--- a/fig-frontend/src/Fig/Frontend.hs
+++ b/fig-frontend/src/Fig/Frontend.hs
@@ -6,7 +6,7 @@ import Control.Lens (use)
import Data.Text (toLower)
--- import qualified Network.Wai.Middleware.Static as Wai.Static
+import qualified Network.Wai.Middleware.Static as Wai.Static
import qualified Network.Wai.Handler.Warp as Warp
import qualified Web.Twain as Tw
@@ -36,16 +36,19 @@ app cfg = do
st <- stateRef
pure $ foldr' @[] ($)
(Tw.notFound . Tw.send $ Tw.text "not found")
- -- [ Wai.Static.staticPolicy $ Wai.Static.addBase cfg.assetPath
- [ Tw.get "/"
- . Tw.send . Tw.html
- . L.renderBS
- $ L.doctypehtml_ do
- L.head_ do
- L.title_ "clonk zone api home page"
- L.link_ [L.rel_ "icon", L.href_ "data:;base64,iVBORw0KGgo="]
- L.body_ do
- "hello"
+ [ Wai.Static.staticPolicy $ Wai.Static.addBase cfg.assetPath
+ -- , Tw.get "/"
+ -- . Tw.send . Tw.html
+ -- . L.renderBS
+ -- $ L.doctypehtml_ do
+ -- L.head_ do
+ -- L.title_ "clonk zone api home page"
+ -- L.link_ [L.rel_ "icon", L.href_ "data:;base64,iVBORw0KGgo="]
+ -- L.link_ [L.rel_ "stylesheet", L.href_ "main.css"]
+ -- L.script_ [L.type_ "module", L.src_ "main.js"] ("" :: L.Html ())
+ -- L.body_ do
+ -- L.button_ [L.id_ "foo"] do
+ -- "hello"
, Tw.get "/api/check" $ authed cfg \auth -> do
Tw.send $ Tw.json @[Text] [auth.id, auth.name]
, Tw.put "/api/buffer" do
diff --git a/fig-monitor-bullfrog/fig-monitor-bullfrog.cabal b/fig-monitor-bullfrog/fig-monitor-bullfrog.cabal
index 2d06268..0cc111e 100644
--- a/fig-monitor-bullfrog/fig-monitor-bullfrog.cabal
+++ b/fig-monitor-bullfrog/fig-monitor-bullfrog.cabal
@@ -25,7 +25,6 @@ common deps
, mtl
, network
, safe-exceptions
- , scotty
, text
, time
, tomland
@@ -52,4 +51,4 @@ executable fig-monitor-bullfrog
build-depends: fig-monitor-bullfrog, optparse-applicative
hs-source-dirs:
main
- main-is: Main.hs \ No newline at end of file
+ main-is: Main.hs
diff --git a/fig-monitor-twitch/fig-monitor-twitch.cabal b/fig-monitor-twitch/fig-monitor-twitch.cabal
index b177d32..5c63bc5 100644
--- a/fig-monitor-twitch/fig-monitor-twitch.cabal
+++ b/fig-monitor-twitch/fig-monitor-twitch.cabal
@@ -25,7 +25,6 @@ common deps
, mtl
, network
, safe-exceptions
- , scotty
, text
, time
, tomland
@@ -55,4 +54,4 @@ executable fig-monitor-twitch
build-depends: fig-monitor-twitch, optparse-applicative
hs-source-dirs:
main
- main-is: Main.hs \ No newline at end of file
+ main-is: Main.hs
diff --git a/flake.lock b/flake.lock
index 5fbfcc3..66db5b4 100644
--- a/flake.lock
+++ b/flake.lock
@@ -1,24 +1,290 @@
{
"nodes": {
+ "docs-search": {
+ "flake": false,
+ "locked": {
+ "lastModified": 1675992564,
+ "narHash": "sha256-Tk9VSogFHXtXe9O9vuCEfM/PV/S7plMIO0I++fCZn7U=",
+ "owner": "purs-nix",
+ "repo": "purescript-docs-search",
+ "rev": "35822b1d6ce65b1a07f80dd9e2caf15c3ee83e2c",
+ "type": "github"
+ },
+ "original": {
+ "owner": "purs-nix",
+ "repo": "purescript-docs-search",
+ "type": "github"
+ }
+ },
+ "flake-utils": {
+ "locked": {
+ "lastModified": 1644229661,
+ "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=",
+ "owner": "numtide",
+ "repo": "flake-utils",
+ "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797",
+ "type": "github"
+ },
+ "original": {
+ "owner": "numtide",
+ "repo": "flake-utils",
+ "type": "github"
+ }
+ },
+ "flake-utils_2": {
+ "locked": {
+ "lastModified": 1618217525,
+ "narHash": "sha256-WGrhVczjXTiswQaoxQ+0PTfbLNeOQM6M36zvLn78AYg=",
+ "owner": "numtide",
+ "repo": "flake-utils",
+ "rev": "c6169a2772643c4a93a0b5ac1c61e296cba68544",
+ "type": "github"
+ },
+ "original": {
+ "owner": "numtide",
+ "repo": "flake-utils",
+ "type": "github"
+ }
+ },
+ "flake-utils_3": {
+ "locked": {
+ "lastModified": 1618217525,
+ "narHash": "sha256-WGrhVczjXTiswQaoxQ+0PTfbLNeOQM6M36zvLn78AYg=",
+ "owner": "numtide",
+ "repo": "flake-utils",
+ "rev": "c6169a2772643c4a93a0b5ac1c61e296cba68544",
+ "type": "github"
+ },
+ "original": {
+ "owner": "numtide",
+ "repo": "flake-utils",
+ "type": "github"
+ }
+ },
+ "get-flake": {
+ "locked": {
+ "lastModified": 1644686428,
+ "narHash": "sha256-zkhYsURWFrvEZLkIoBeqFBzSu+cA2u5mo6M8vq9LN7M=",
+ "owner": "ursi",
+ "repo": "get-flake",
+ "rev": "703f15558daa56dfae19d1858bb3046afe68831a",
+ "type": "github"
+ },
+ "original": {
+ "owner": "ursi",
+ "repo": "get-flake",
+ "type": "github"
+ }
+ },
+ "lint-utils": {
+ "inputs": {
+ "flake-utils": "flake-utils",
+ "nixpkgs": [
+ "purs-nix",
+ "nixpkgs"
+ ]
+ },
+ "locked": {
+ "lastModified": 1707777931,
+ "narHash": "sha256-PsPb5xMBZ9dPDP04o9vqKEUIEG80Z84/74fPuOMs0ZI=",
+ "owner": "homotopic",
+ "repo": "lint-utils",
+ "rev": "5f11e3e51d8f1aa4ed62a89e90f05953931e105a",
+ "type": "github"
+ },
+ "original": {
+ "owner": "homotopic",
+ "repo": "lint-utils",
+ "type": "github"
+ }
+ },
+ "make-shell": {
+ "locked": {
+ "lastModified": 1634940815,
+ "narHash": "sha256-P69OmveboXzS+es1vQGS4bt+ckwbeIExqxfGLjGuJqA=",
+ "owner": "ursi",
+ "repo": "nix-make-shell",
+ "rev": "8add91681170924e4d0591b22f294aee3f5516f9",
+ "type": "github"
+ },
+ "original": {
+ "owner": "ursi",
+ "ref": "1",
+ "repo": "nix-make-shell",
+ "type": "github"
+ }
+ },
+ "make-shell_2": {
+ "locked": {
+ "lastModified": 1634940815,
+ "narHash": "sha256-P69OmveboXzS+es1vQGS4bt+ckwbeIExqxfGLjGuJqA=",
+ "owner": "ursi",
+ "repo": "nix-make-shell",
+ "rev": "8add91681170924e4d0591b22f294aee3f5516f9",
+ "type": "github"
+ },
+ "original": {
+ "owner": "ursi",
+ "ref": "1",
+ "repo": "nix-make-shell",
+ "type": "github"
+ }
+ },
"nixpkgs": {
"locked": {
- "lastModified": 1696697597,
- "narHash": "sha256-q26Qv4DQ+h6IeozF2o1secyQG0jt2VUT3V0K58jr3pg=",
+ "lastModified": 1708815994,
+ "narHash": "sha256-hL7N/ut2Xu0NaDxDMsw2HagAjgDskToGiyZOWriiLYM=",
"owner": "NixOS",
"repo": "nixpkgs",
- "rev": "5a237aecb57296f67276ac9ab296a41c23981f56",
+ "rev": "9a9dae8f6319600fa9aebde37f340975cab4b8c0",
"type": "github"
},
"original": {
"owner": "NixOS",
- "ref": "nixos-23.05",
+ "ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
+ "nixpkgs_2": {
+ "locked": {
+ "lastModified": 1704161960,
+ "narHash": "sha256-QGua89Pmq+FBAro8NriTuoO/wNaUtugt29/qqA8zeeM=",
+ "owner": "NixOS",
+ "repo": "nixpkgs",
+ "rev": "63143ac2c9186be6d9da6035fa22620018c85932",
+ "type": "github"
+ },
+ "original": {
+ "owner": "NixOS",
+ "ref": "nixpkgs-unstable",
+ "repo": "nixpkgs",
+ "type": "github"
+ }
+ },
+ "nixpkgs_3": {
+ "locked": {
+ "lastModified": 1656549732,
+ "narHash": "sha256-eILutFZGjfk2bEzfim8S/qyYc//0S1KsCeO+OWbtoR0=",
+ "owner": "NixOS",
+ "repo": "nixpkgs",
+ "rev": "d3248619647234b5dc74a6921bcdf6dd8323eb22",
+ "type": "github"
+ },
+ "original": {
+ "owner": "NixOS",
+ "ref": "nixpkgs-unstable",
+ "repo": "nixpkgs",
+ "type": "github"
+ }
+ },
+ "parsec": {
+ "locked": {
+ "lastModified": 1635533376,
+ "narHash": "sha256-/HrG0UPGnI5VdkhrNrpDiM2+nhdL6lD/bqyGtYv0QDE=",
+ "owner": "nprindle",
+ "repo": "nix-parsec",
+ "rev": "1bf25dd9c5de1257a1c67de3c81c96d05e8beb5e",
+ "type": "github"
+ },
+ "original": {
+ "owner": "nprindle",
+ "repo": "nix-parsec",
+ "type": "github"
+ }
+ },
+ "ps-tools": {
+ "inputs": {
+ "make-shell": "make-shell_2",
+ "nixpkgs": "nixpkgs_3",
+ "utils": "utils"
+ },
+ "locked": {
+ "lastModified": 1704567308,
+ "narHash": "sha256-WbFPIkKLtyQOPBUjintckKIYnfs7MvIbmfVsLRSAPlc=",
+ "owner": "purs-nix",
+ "repo": "purescript-tools",
+ "rev": "ac626313141cbee78f06eb3c5e90359f695aef9b",
+ "type": "github"
+ },
+ "original": {
+ "owner": "purs-nix",
+ "repo": "purescript-tools",
+ "type": "github"
+ }
+ },
+ "purs-nix": {
+ "inputs": {
+ "docs-search": "docs-search",
+ "get-flake": "get-flake",
+ "lint-utils": "lint-utils",
+ "make-shell": "make-shell",
+ "nixpkgs": "nixpkgs_2",
+ "parsec": "parsec",
+ "ps-tools": "ps-tools",
+ "utils": "utils_2"
+ },
+ "locked": {
+ "lastModified": 1707933489,
+ "narHash": "sha256-LP05KSBQ02mgBDiVdW53h9ViFBtFQIo4dT3FCebucI0=",
+ "owner": "purs-nix",
+ "repo": "purs-nix",
+ "rev": "72c9a8b7df0e53ff8b24fef00d9ea74d3a5b6522",
+ "type": "github"
+ },
+ "original": {
+ "owner": "purs-nix",
+ "ref": "ps-0.15",
+ "repo": "purs-nix",
+ "type": "github"
+ }
+ },
"root": {
"inputs": {
- "nixpkgs": "nixpkgs"
+ "nixpkgs": "nixpkgs",
+ "ps-tools": [
+ "purs-nix",
+ "ps-tools"
+ ],
+ "purs-nix": "purs-nix"
+ }
+ },
+ "utils": {
+ "inputs": {
+ "flake-utils": "flake-utils_2"
+ },
+ "locked": {
+ "lastModified": 1656044990,
+ "narHash": "sha256-f01BB7CaOyntOab9XnpH9HD63rGcnu2iyL4M2ubs5F8=",
+ "owner": "ursi",
+ "repo": "flake-utils",
+ "rev": "f53b674a2c90f6202a2f4cd491aba121775490b5",
+ "type": "github"
+ },
+ "original": {
+ "owner": "ursi",
+ "ref": "8",
+ "repo": "flake-utils",
+ "type": "github"
+ }
+ },
+ "utils_2": {
+ "inputs": {
+ "flake-utils": "flake-utils_3"
+ },
+ "locked": {
+ "lastModified": 1656044990,
+ "narHash": "sha256-f01BB7CaOyntOab9XnpH9HD63rGcnu2iyL4M2ubs5F8=",
+ "owner": "ursi",
+ "repo": "flake-utils",
+ "rev": "f53b674a2c90f6202a2f4cd491aba121775490b5",
+ "type": "github"
+ },
+ "original": {
+ "owner": "ursi",
+ "ref": "8",
+ "repo": "flake-utils",
+ "type": "github"
}
}
},
diff --git a/flake.nix b/flake.nix
index dabef91..fc97f9d 100644
--- a/flake.nix
+++ b/flake.nix
@@ -1,12 +1,20 @@
{
description = "fig";
- inputs.nixpkgs.url = github:NixOS/nixpkgs/nixos-23.05;
+ inputs = {
+ nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
+ ps-tools.follows = "purs-nix/ps-tools";
+ purs-nix.url = "github:purs-nix/purs-nix/ps-0.15";
+ };
- outputs = { self, nixpkgs }:
+ outputs = { self, nixpkgs, ... }@inputs:
let
- pkgs = nixpkgs.legacyPackages.x86_64-linux;
- overrides = self: super: {
+ system = "x86_64-linux";
+ pkgs = nixpkgs.legacyPackages.${system};
+ ps-tools = inputs.ps-tools.legacyPackages.${system};
+ purs-nix = inputs.purs-nix { inherit system; };
+
+ haskellOverrides = self: super: {
discord-haskell = self.callCabal2nix "discord-haskell" ./deps/discord-haskell {};
irc-conduit = self.callCabal2nix "irc-conduit" ./deps/irc-conduit {};
irc-client = self.callCabal2nix "irc-client" ./deps/irc-client {};
@@ -20,11 +28,26 @@
fig-frontend = self.callCabal2nix "fig-frontend" ./fig-frontend {};
};
haskellPackages = pkgs.haskell.packages.ghc94.override {
- inherit overrides;
+ overrides = haskellOverrides;
};
- # haskellPackagesStatic = pkgs.pkgsStatic.haskell.packages.ghc94.override {
- # inherit overrides;
- # };
+
+ purescript = purs-nix.purs {
+ dependencies = [
+ "console"
+ "effect"
+ "prelude"
+ "random"
+ "refs"
+ "web-html"
+ "web-dom"
+ "web-uievents"
+ "canvas"
+ ];
+ dir = ./fig-frontend-client;
+ srcs = [ "src" ];
+ };
+ fig-frontend-client = purescript.bundle {};
+
figBusModule = { config, lib, ... }:
let
cfg = config.colonq.services.fig-bus;
@@ -233,6 +256,11 @@
withHoogle = true;
buildInputs = [
haskellPackages.haskell-language-server
+ pkgs.nodejs
+ (purescript.command {})
+ ps-tools.for-0_15.purescript-language-server
+ purs-nix.esbuild
+ purs-nix.purescript
];
};
packages.x86_64-linux = {