aboutsummaryrefslogtreecommitdiff
path: root/examples/01-hello-world
diff options
context:
space:
mode:
Diffstat (limited to 'examples/01-hello-world')
-rw-r--r--examples/01-hello-world/index.html19
-rw-r--r--examples/01-hello-world/manifest.toml23
-rw-r--r--examples/01-hello-world/priv/static/app.mjs960
-rw-r--r--examples/01-hello-world/src/app.gleam25
4 files changed, 1007 insertions, 20 deletions
diff --git a/examples/01-hello-world/index.html b/examples/01-hello-world/index.html
new file mode 100644
index 0000000..36ddf10
--- /dev/null
+++ b/examples/01-hello-world/index.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<html lang="en">
+ <head>
+ <meta charset="UTF-8" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+
+ <title>🚧 app</title>
+
+ <link
+ rel="stylesheet"
+ href="./build/dev/javascript/lustre_ui/priv/static/lustre-ui.css"
+ />
+ <script type="module" src="./priv/static/app.mjs"></script>
+ </head>
+
+ <body>
+ <div id="app"></div>
+ </body>
+</html>
diff --git a/examples/01-hello-world/manifest.toml b/examples/01-hello-world/manifest.toml
index 7f82909..c0d1211 100644
--- a/examples/01-hello-world/manifest.toml
+++ b/examples/01-hello-world/manifest.toml
@@ -3,26 +3,39 @@
packages = [
{ name = "argv", version = "1.0.2", build_tools = ["gleam"], requirements = [], otp_app = "argv", source = "hex", outer_checksum = "BA1FF0929525DEBA1CE67256E5ADF77A7CDDFE729E3E3F57A5BDCAA031DED09D" },
+ { name = "birl", version = "1.6.1", build_tools = ["gleam"], requirements = ["gleam_stdlib", "ranger"], otp_app = "birl", source = "hex", outer_checksum = "976CFF85D34D50F7775896615A71745FBE0C325E50399787088F941B539A0497" },
+ { name = "exception", version = "2.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "exception", source = "hex", outer_checksum = "F5580D584F16A20B7FCDCABF9E9BE9A2C1F6AC4F9176FA6DD0B63E3B20D450AA" },
{ name = "filepath", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "filepath", source = "hex", outer_checksum = "EFB6FF65C98B2A16378ABC3EE2B14124168C0CE5201553DE652E2644DCFDB594" },
+ { name = "filespy", version = "0.3.0", build_tools = ["gleam"], requirements = ["fs", "gleam_erlang", "gleam_otp", "gleam_stdlib"], otp_app = "filespy", source = "hex", outer_checksum = "75F5910B31A528681D25316AAAE6C91CD3E977BD2492946564B7242FF941FB7A" },
+ { name = "fs", version = "8.6.1", build_tools = ["rebar3"], requirements = [], otp_app = "fs", source = "hex", outer_checksum = "61EA2BDAEDAE4E2024D0D25C63E44DCCF65622D4402DB4A2DF12868D1546503F" },
{ name = "gleam_community_ansi", version = "1.4.0", build_tools = ["gleam"], requirements = ["gleam_community_colour", "gleam_stdlib"], otp_app = "gleam_community_ansi", source = "hex", outer_checksum = "FE79E08BF97009729259B6357EC058315B6FBB916FAD1C2FF9355115FEB0D3A4" },
{ name = "gleam_community_colour", version = "1.4.0", build_tools = ["gleam"], requirements = ["gleam_json", "gleam_stdlib"], otp_app = "gleam_community_colour", source = "hex", outer_checksum = "795964217EBEDB3DA656F5EB8F67D7AD22872EB95182042D3E7AFEF32D3FD2FE" },
+ { name = "gleam_crypto", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_crypto", source = "hex", outer_checksum = "ADD058DEDE8F0341F1ADE3AAC492A224F15700829D9A3A3F9ADF370F875C51B7" },
{ name = "gleam_erlang", version = "0.25.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_erlang", source = "hex", outer_checksum = "054D571A7092D2A9727B3E5D183B7507DAB0DA41556EC9133606F09C15497373" },
+ { name = "gleam_http", version = "3.6.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_http", source = "hex", outer_checksum = "8C07DF9DF8CC7F054C650839A51C30A7D3C26482AC241C899C1CEA86B22DBE51" },
{ name = "gleam_json", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "thoas"], otp_app = "gleam_json", source = "hex", outer_checksum = "8B197DD5D578EA6AC2C0D4BDC634C71A5BCA8E7DB5F47091C263ECB411A60DF3" },
{ name = "gleam_otp", version = "0.10.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_stdlib"], otp_app = "gleam_otp", source = "hex", outer_checksum = "0B04FE915ACECE539B317F9652CAADBBC0F000184D586AAAF2D94C100945D72B" },
{ name = "gleam_package_interface", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_json", "gleam_stdlib"], otp_app = "gleam_package_interface", source = "hex", outer_checksum = "52A721BCA972C8099BB881195D821AAA64B9F2655BECC102165D5A1097731F01" },
{ name = "gleam_stdlib", version = "0.36.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "C0D14D807FEC6F8A08A7C9EF8DFDE6AE5C10E40E21325B2B29365965D82EB3D4" },
{ name = "glearray", version = "0.2.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "glearray", source = "hex", outer_checksum = "908154F695D330E06A37FAB2C04119E8F315D643206F8F32B6A6C14A8709FFF4" },
- { name = "gleeunit", version = "1.0.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "D364C87AFEB26BDB4FB8A5ABDE67D635DC9FA52D6AB68416044C35B096C6882D" },
+ { name = "gleeunit", version = "1.1.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "72CDC3D3F719478F26C4E2C5FED3E657AC81EC14A47D2D2DEBB8693CA3220C3B" },
{ name = "glint", version = "0.18.0", build_tools = ["gleam"], requirements = ["gleam_community_ansi", "gleam_community_colour", "gleam_stdlib", "snag"], otp_app = "glint", source = "hex", outer_checksum = "BB0F14643CC51C069A5DC6E9082EAFCD9967AFD1C9CC408803D1A40A3FD43B54" },
- { name = "lustre", version = "4.0.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_json", "gleam_otp", "gleam_stdlib"], otp_app = "lustre", source = "hex", outer_checksum = "1D40C1378279F7015687F8C9DB739D6880BB0B843F4428B85C61EDDA8BF21FC6" },
- { name = "lustre_dev_tools", version = "1.0.0", build_tools = ["gleam"], requirements = ["argv", "filepath", "gleam_community_ansi", "gleam_erlang", "gleam_json", "gleam_otp", "gleam_package_interface", "gleam_stdlib", "glint", "simplifile", "spinner", "tom"], otp_app = "lustre_dev_tools", source = "hex", outer_checksum = "66142ADDCA3D6C63A89E016CF6C21E07D06D6DC92479325182A07C360BD026D3" },
- { name = "lustre_ui", version = "0.5.0", build_tools = ["gleam"], requirements = ["gleam_community_colour", "gleam_json", "gleam_stdlib", "lustre"], otp_app = "lustre_ui", source = "hex", outer_checksum = "7ECB5414BE926082401891C62FAAA21221FC0B7A2F0568A492349F48DC2B02A0" },
+ { name = "glisten", version = "2.0.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_otp", "gleam_stdlib"], otp_app = "glisten", source = "hex", outer_checksum = "CF3A9383E9BA4A8CBAF2F7B799716290D02F2AC34E7A77556B49376B662B9314" },
+ { name = "hpack_erl", version = "0.3.0", build_tools = ["rebar3"], requirements = [], otp_app = "hpack", source = "hex", outer_checksum = "D6137D7079169D8C485C6962DFE261AF5B9EF60FBC557344511C1E65E3D95FB0" },
+ { name = "logging", version = "1.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "logging", source = "hex", outer_checksum = "82C112ED9B6C30C1772A6FE2613B94B13F62EA35F5869A2630D13948D297BD39" },
+ { name = "lustre", version = "4.1.7", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_json", "gleam_otp", "gleam_stdlib"], otp_app = "lustre", source = "hex", outer_checksum = "64F5D7E4DF51280185F70296ACB7D3DCC9B5DA09EFC5257F0E5601846DFBEF23" },
+ { name = "lustre_dev_tools", version = "1.2.1", build_tools = ["gleam"], requirements = ["argv", "filepath", "filespy", "fs", "gleam_community_ansi", "gleam_erlang", "gleam_http", "gleam_json", "gleam_otp", "gleam_package_interface", "gleam_stdlib", "glint", "glisten", "mist", "simplifile", "spinner", "tom", "wisp"], otp_app = "lustre_dev_tools", source = "hex", outer_checksum = "930BBE8C4E92A16857C31B7B12616651433E1643304696FB93B69D659CE3ADC2" },
+ { name = "lustre_ui", version = "0.6.0", build_tools = ["gleam"], requirements = ["gleam_community_colour", "gleam_json", "gleam_stdlib", "lustre"], otp_app = "lustre_ui", source = "hex", outer_checksum = "FA1F9E89D89CDD5DF376ED86ABA8A38441CB2E664CD4D402F22A49DA4D7BB56D" },
+ { name = "marceau", version = "1.1.0", build_tools = ["gleam"], requirements = [], otp_app = "marceau", source = "hex", outer_checksum = "1AAD727A30BE0F95562C3403BB9B27C823797AD90037714255EEBF617B1CDA81" },
+ { name = "mist", version = "1.0.0", build_tools = ["gleam"], requirements = ["birl", "gleam_erlang", "gleam_http", "gleam_otp", "gleam_stdlib", "glisten", "hpack_erl", "logging"], otp_app = "mist", source = "hex", outer_checksum = "7765E53DCC9ACCACF217B8E0CA3DE7E848C783BFAE5118B75011E81C2C80385C" },
+ { name = "ranger", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "ranger", source = "hex", outer_checksum = "1566C272B1D141B3BBA38B25CB761EF56E312E79EC0E2DFD4D3C19FB0CC1F98C" },
{ name = "repeatedly", version = "2.1.1", build_tools = ["gleam"], requirements = [], otp_app = "repeatedly", source = "hex", outer_checksum = "38808C3EC382B0CD981336D5879C24ECB37FCB9C1D1BD128F7A80B0F74404D79" },
- { name = "simplifile", version = "1.5.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "C44DB387524F90DC42142699C78C850003289D32C7C99C7D32873792A299CDF7" },
+ { name = "simplifile", version = "1.7.0", build_tools = ["gleam"], requirements = ["filepath", "gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "1D5DFA3A2F9319EC85825F6ED88B8E449F381B0D55A62F5E61424E748E7DDEB0" },
{ name = "snag", version = "0.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "snag", source = "hex", outer_checksum = "54D32E16E33655346AA3E66CBA7E191DE0A8793D2C05284E3EFB90AD2CE92BCC" },
{ name = "spinner", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_community_ansi", "gleam_erlang", "gleam_stdlib", "glearray", "repeatedly"], otp_app = "spinner", source = "hex", outer_checksum = "200BA3D4A04D468898E63C0D316E23F526E02514BC46454091975CB5BAE41E8F" },
{ name = "thoas", version = "0.4.1", build_tools = ["rebar3"], requirements = [], otp_app = "thoas", source = "hex", outer_checksum = "4918D50026C073C4AB1388437132C77A6F6F7C8AC43C60C13758CC0ADCE2134E" },
{ name = "tom", version = "0.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "tom", source = "hex", outer_checksum = "0831C73E45405A2153091226BF98FB485ED16376988602CC01A5FD086B82D577" },
+ { name = "wisp", version = "0.14.0", build_tools = ["gleam"], requirements = ["exception", "gleam_crypto", "gleam_erlang", "gleam_http", "gleam_json", "gleam_stdlib", "logging", "marceau", "mist", "simplifile"], otp_app = "wisp", source = "hex", outer_checksum = "9F5453AF1F9275E6F8707BC815D6A6A9DF41551921B16FBDBA52883773BAE684" },
]
[requirements]
diff --git a/examples/01-hello-world/priv/static/app.mjs b/examples/01-hello-world/priv/static/app.mjs
new file mode 100644
index 0000000..60d0114
--- /dev/null
+++ b/examples/01-hello-world/priv/static/app.mjs
@@ -0,0 +1,960 @@
+// build/dev/javascript/prelude.mjs
+var CustomType = class {
+ withFields(fields) {
+ let properties = Object.keys(this).map(
+ (label2) => label2 in fields ? fields[label2] : this[label2]
+ );
+ return new this.constructor(...properties);
+ }
+};
+var List = class {
+ static fromArray(array3, tail) {
+ let t = tail || new Empty();
+ for (let i = array3.length - 1; i >= 0; --i) {
+ t = new NonEmpty(array3[i], t);
+ }
+ return t;
+ }
+ [Symbol.iterator]() {
+ return new ListIterator(this);
+ }
+ toArray() {
+ return [...this];
+ }
+ // @internal
+ atLeastLength(desired) {
+ for (let _ of this) {
+ if (desired <= 0)
+ return true;
+ desired--;
+ }
+ return desired <= 0;
+ }
+ // @internal
+ hasLength(desired) {
+ for (let _ of this) {
+ if (desired <= 0)
+ return false;
+ desired--;
+ }
+ return desired === 0;
+ }
+ countLength() {
+ let length2 = 0;
+ for (let _ of this)
+ length2++;
+ return length2;
+ }
+};
+function prepend(element3, tail) {
+ return new NonEmpty(element3, tail);
+}
+function toList(elements, tail) {
+ return List.fromArray(elements, tail);
+}
+var ListIterator = class {
+ #current;
+ constructor(current) {
+ this.#current = current;
+ }
+ next() {
+ if (this.#current instanceof Empty) {
+ return { done: true };
+ } else {
+ let { head, tail } = this.#current;
+ this.#current = tail;
+ return { value: head, done: false };
+ }
+ }
+};
+var Empty = class extends List {
+};
+var NonEmpty = class extends List {
+ constructor(head, tail) {
+ super();
+ this.head = head;
+ this.tail = tail;
+ }
+};
+var Result = class _Result extends CustomType {
+ // @internal
+ static isResult(data) {
+ return data instanceof _Result;
+ }
+};
+var Ok = class extends Result {
+ constructor(value) {
+ super();
+ this[0] = value;
+ }
+ // @internal
+ isOk() {
+ return true;
+ }
+};
+var Error = class extends Result {
+ constructor(detail) {
+ super();
+ this[0] = detail;
+ }
+ // @internal
+ isOk() {
+ return false;
+ }
+};
+function isEqual(x, y) {
+ let values = [x, y];
+ while (values.length) {
+ let a = values.pop();
+ let b = values.pop();
+ if (a === b)
+ continue;
+ if (!isObject(a) || !isObject(b))
+ return false;
+ let unequal = !structurallyCompatibleObjects(a, b) || unequalDates(a, b) || unequalBuffers(a, b) || unequalArrays(a, b) || unequalMaps(a, b) || unequalSets(a, b) || unequalRegExps(a, b);
+ if (unequal)
+ return false;
+ const proto = Object.getPrototypeOf(a);
+ if (proto !== null && typeof proto.equals === "function") {
+ try {
+ if (a.equals(b))
+ continue;
+ else
+ return false;
+ } catch {
+ }
+ }
+ let [keys2, get2] = getters(a);
+ for (let k of keys2(a)) {
+ values.push(get2(a, k), get2(b, k));
+ }
+ }
+ return true;
+}
+function getters(object3) {
+ if (object3 instanceof Map) {
+ return [(x) => x.keys(), (x, y) => x.get(y)];
+ } else {
+ let extra = object3 instanceof globalThis.Error ? ["message"] : [];
+ return [(x) => [...extra, ...Object.keys(x)], (x, y) => x[y]];
+ }
+}
+function unequalDates(a, b) {
+ return a instanceof Date && (a > b || a < b);
+}
+function unequalBuffers(a, b) {
+ return a.buffer instanceof ArrayBuffer && a.BYTES_PER_ELEMENT && !(a.byteLength === b.byteLength && a.every((n, i) => n === b[i]));
+}
+function unequalArrays(a, b) {
+ return Array.isArray(a) && a.length !== b.length;
+}
+function unequalMaps(a, b) {
+ return a instanceof Map && a.size !== b.size;
+}
+function unequalSets(a, b) {
+ return a instanceof Set && (a.size != b.size || [...a].some((e) => !b.has(e)));
+}
+function unequalRegExps(a, b) {
+ return a instanceof RegExp && (a.source !== b.source || a.flags !== b.flags);
+}
+function isObject(a) {
+ return typeof a === "object" && a !== null;
+}
+function structurallyCompatibleObjects(a, b) {
+ if (typeof a !== "object" && typeof b !== "object" && (!a || !b))
+ return false;
+ let nonstructural = [Promise, WeakSet, WeakMap, Function];
+ if (nonstructural.some((c) => a instanceof c))
+ return false;
+ return a.constructor === b.constructor;
+}
+function makeError(variant, module, line, fn, message, extra) {
+ let error = new globalThis.Error(message);
+ error.gleam_error = variant;
+ error.module = module;
+ error.line = line;
+ error.fn = fn;
+ for (let k in extra)
+ error[k] = extra[k];
+ return error;
+}
+
+// build/dev/javascript/gleam_stdlib/gleam/option.mjs
+var None = class extends CustomType {
+};
+
+// build/dev/javascript/gleam_stdlib/dict.mjs
+var tempDataView = new DataView(new ArrayBuffer(8));
+var SHIFT = 5;
+var BUCKET_SIZE = Math.pow(2, SHIFT);
+var MASK = BUCKET_SIZE - 1;
+var MAX_INDEX_NODE = BUCKET_SIZE / 2;
+var MIN_ARRAY_NODE = BUCKET_SIZE / 4;
+
+// build/dev/javascript/gleam_stdlib/gleam_stdlib.mjs
+function identity(x) {
+ return x;
+}
+
+// build/dev/javascript/gleam_stdlib/gleam/list.mjs
+function fold(loop$list, loop$initial, loop$fun) {
+ while (true) {
+ let list = loop$list;
+ let initial = loop$initial;
+ let fun = loop$fun;
+ if (list.hasLength(0)) {
+ return initial;
+ } else {
+ let x = list.head;
+ let rest$1 = list.tail;
+ loop$list = rest$1;
+ loop$initial = fun(initial, x);
+ loop$fun = fun;
+ }
+ }
+}
+
+// build/dev/javascript/gleam_stdlib/gleam/dynamic.mjs
+function from(a) {
+ return identity(a);
+}
+
+// build/dev/javascript/gleam_stdlib/gleam/bool.mjs
+function guard(requirement, consequence, alternative) {
+ if (requirement) {
+ return consequence;
+ } else {
+ return alternative();
+ }
+}
+
+// build/dev/javascript/lustre/lustre/effect.mjs
+var Effect = class extends CustomType {
+ constructor(all) {
+ super();
+ this.all = all;
+ }
+};
+function none() {
+ return new Effect(toList([]));
+}
+
+// build/dev/javascript/lustre/lustre/internals/vdom.mjs
+var Text = class extends CustomType {
+ constructor(content) {
+ super();
+ this.content = content;
+ }
+};
+var Element = class extends CustomType {
+ constructor(key, namespace, tag2, attrs, children, self_closing, void$) {
+ super();
+ this.key = key;
+ this.namespace = namespace;
+ this.tag = tag2;
+ this.attrs = attrs;
+ this.children = children;
+ this.self_closing = self_closing;
+ this.void = void$;
+ }
+};
+var Attribute = class extends CustomType {
+ constructor(x0, x1, as_property) {
+ super();
+ this[0] = x0;
+ this[1] = x1;
+ this.as_property = as_property;
+ }
+};
+
+// build/dev/javascript/lustre/lustre/attribute.mjs
+function attribute(name, value) {
+ return new Attribute(name, from(value), false);
+}
+function style(properties) {
+ return attribute(
+ "style",
+ fold(
+ properties,
+ "",
+ (styles, _use1) => {
+ let name$1 = _use1[0];
+ let value$1 = _use1[1];
+ return styles + name$1 + ":" + value$1 + ";";
+ }
+ )
+ );
+}
+function class$(name) {
+ return attribute("class", name);
+}
+
+// build/dev/javascript/lustre/lustre/element.mjs
+function element(tag2, attrs, children) {
+ if (tag2 === "area") {
+ return new Element("", "", tag2, attrs, toList([]), false, true);
+ } else if (tag2 === "base") {
+ return new Element("", "", tag2, attrs, toList([]), false, true);
+ } else if (tag2 === "br") {
+ return new Element("", "", tag2, attrs, toList([]), false, true);
+ } else if (tag2 === "col") {
+ return new Element("", "", tag2, attrs, toList([]), false, true);
+ } else if (tag2 === "embed") {
+ return new Element("", "", tag2, attrs, toList([]), false, true);
+ } else if (tag2 === "hr") {
+ return new Element("", "", tag2, attrs, toList([]), false, true);
+ } else if (tag2 === "img") {
+ return new Element("", "", tag2, attrs, toList([]), false, true);
+ } else if (tag2 === "input") {
+ return new Element("", "", tag2, attrs, toList([]), false, true);
+ } else if (tag2 === "link") {
+ return new Element("", "", tag2, attrs, toList([]), false, true);
+ } else if (tag2 === "meta") {
+ return new Element("", "", tag2, attrs, toList([]), false, true);
+ } else if (tag2 === "param") {
+ return new Element("", "", tag2, attrs, toList([]), false, true);
+ } else if (tag2 === "source") {
+ return new Element("", "", tag2, attrs, toList([]), false, true);
+ } else if (tag2 === "track") {
+ return new Element("", "", tag2, attrs, toList([]), false, true);
+ } else if (tag2 === "wbr") {
+ return new Element("", "", tag2, attrs, toList([]), false, true);
+ } else {
+ return new Element("", "", tag2, attrs, children, false, false);
+ }
+}
+function text(content) {
+ return new Text(content);
+}
+
+// build/dev/javascript/lustre/lustre/internals/runtime.mjs
+var Dispatch = class extends CustomType {
+ constructor(x0) {
+ super();
+ this[0] = x0;
+ }
+};
+var Shutdown = class extends CustomType {
+};
+
+// build/dev/javascript/lustre/vdom.ffi.mjs
+function morph(prev, next, dispatch, isComponent = false) {
+ let out;
+ let stack2 = [{ prev, next, parent: prev.parentNode }];
+ while (stack2.length) {
+ let { prev: prev2, next: next2, parent } = stack2.pop();
+ if (next2.subtree !== void 0)
+ next2 = next2.subtree();
+ if (next2.content !== void 0) {
+ if (!prev2) {
+ const created = document.createTextNode(next2.content);
+ parent.appendChild(created);
+ out ??= created;
+ } else if (prev2.nodeType === Node.TEXT_NODE) {
+ if (prev2.textContent !== next2.content)
+ prev2.textContent = next2.content;
+ out ??= prev2;
+ } else {
+ const created = document.createTextNode(next2.content);
+ parent.replaceChild(created, prev2);
+ out ??= created;
+ }
+ } else if (next2.tag !== void 0) {
+ const created = createElementNode({
+ prev: prev2,
+ next: next2,
+ dispatch,
+ stack: stack2,
+ isComponent
+ });
+ if (!prev2) {
+ parent.appendChild(created);
+ } else if (prev2 !== created) {
+ parent.replaceChild(created, prev2);
+ }
+ out ??= created;
+ }
+ }
+ return out;
+}
+function createElementNode({ prev, next, dispatch, stack: stack2 }) {
+ const namespace = next.namespace || "http://www.w3.org/1999/xhtml";
+ const canMorph = prev && prev.nodeType === Node.ELEMENT_NODE && prev.localName === next.tag && prev.namespaceURI === (next.namespace || "http://www.w3.org/1999/xhtml");
+ const el2 = canMorph ? prev : namespace ? document.createElementNS(namespace, next.tag) : document.createElement(next.tag);
+ let handlersForEl;
+ if (!registeredHandlers.has(el2)) {
+ const emptyHandlers = /* @__PURE__ */ new Map();
+ registeredHandlers.set(el2, emptyHandlers);
+ handlersForEl = emptyHandlers;
+ } else {
+ handlersForEl = registeredHandlers.get(el2);
+ }
+ const prevHandlers = canMorph ? new Set(handlersForEl.keys()) : null;
+ const prevAttributes = canMorph ? new Set(Array.from(prev.attributes, (a) => a.name)) : null;
+ let className = null;
+ let style2 = null;
+ let innerHTML = null;
+ for (const attr of next.attrs) {
+ const name = attr[0];
+ const value = attr[1];
+ const isProperty = attr[2];
+ if (isProperty) {
+ el2[name] = value;
+ } else if (name.startsWith("on")) {
+ const eventName = name.slice(2);
+ const callback = dispatch(value);
+ if (!handlersForEl.has(eventName)) {
+ el2.addEventListener(eventName, lustreGenericEventHandler);
+ }
+ handlersForEl.set(eventName, callback);
+ if (canMorph)
+ prevHandlers.delete(eventName);
+ } else if (name.startsWith("data-lustre-on-")) {
+ const eventName = name.slice(15);
+ const callback = dispatch(lustreServerEventHandler);
+ if (!handlersForEl.has(eventName)) {
+ el2.addEventListener(eventName, lustreGenericEventHandler);
+ }
+ handlersForEl.set(eventName, callback);
+ el2.setAttribute(name, value);
+ } else if (name === "class") {
+ className = className === null ? value : className + " " + value;
+ } else if (name === "style") {
+ style2 = style2 === null ? value : style2 + value;
+ } else if (name === "dangerous-unescaped-html") {
+ innerHTML = value;
+ } else {
+ el2.setAttribute(name, value);
+ if (name === "value")
+ el2[name] = value;
+ if (canMorph)
+ prevAttributes.delete(name);
+ }
+ }
+ if (className !== null) {
+ el2.setAttribute("class", className);
+ if (canMorph)
+ prevAttributes.delete("class");
+ }
+ if (style2 !== null) {
+ el2.setAttribute("style", style2);
+ if (canMorph)
+ prevAttributes.delete("style");
+ }
+ if (canMorph) {
+ for (const attr of prevAttributes) {
+ el2.removeAttribute(attr);
+ }
+ for (const eventName of prevHandlers) {
+ handlersForEl.delete(eventName);
+ el2.removeEventListener(eventName, lustreGenericEventHandler);
+ }
+ }
+ if (next.key !== void 0 && next.key !== "") {
+ el2.setAttribute("data-lustre-key", next.key);
+ } else if (innerHTML !== null) {
+ el2.innerHTML = innerHTML;
+ return el2;
+ }
+ let prevChild = el2.firstChild;
+ let seenKeys = null;
+ let keyedChildren = null;
+ let incomingKeyedChildren = null;
+ let firstChild = next.children[Symbol.iterator]().next().value;
+ if (canMorph && firstChild !== void 0 && // Explicit checks are more verbose but truthy checks force a bunch of comparisons
+ // we don't care about: it's never gonna be a number etc.
+ firstChild.key !== void 0 && firstChild.key !== "") {
+ seenKeys = /* @__PURE__ */ new Set();
+ keyedChildren = getKeyedChildren(prev);
+ incomingKeyedChildren = getKeyedChildren(next);
+ }
+ for (const child of next.children) {
+ if (child.key !== void 0 && seenKeys !== null) {
+ while (prevChild && !incomingKeyedChildren.has(prevChild.getAttribute("data-lustre-key"))) {
+ const nextChild = prevChild.nextSibling;
+ el2.removeChild(prevChild);
+ prevChild = nextChild;
+ }
+ if (keyedChildren.size === 0) {
+ stack2.unshift({ prev: prevChild, next: child, parent: el2 });
+ prevChild = prevChild?.nextSibling;
+ continue;
+ }
+ if (seenKeys.has(child.key)) {
+ console.warn(`Duplicate key found in Lustre vnode: ${child.key}`);
+ stack2.unshift({ prev: null, next: child, parent: el2 });
+ continue;
+ }
+ seenKeys.add(child.key);
+ const keyedChild = keyedChildren.get(child.key);
+ if (!keyedChild && !prevChild) {
+ stack2.unshift({ prev: null, next: child, parent: el2 });
+ continue;
+ }
+ if (!keyedChild && prevChild !== null) {
+ const placeholder = document.createTextNode("");
+ el2.insertBefore(placeholder, prevChild);
+ stack2.unshift({ prev: placeholder, next: child, parent: el2 });
+ continue;
+ }
+ if (!keyedChild || keyedChild === prevChild) {
+ stack2.unshift({ prev: prevChild, next: child, parent: el2 });
+ prevChild = prevChild?.nextSibling;
+ continue;
+ }
+ el2.insertBefore(keyedChild, prevChild);
+ stack2.unshift({ prev: keyedChild, next: child, parent: el2 });
+ } else {
+ stack2.unshift({ prev: prevChild, next: child, parent: el2 });
+ prevChild = prevChild?.nextSibling;
+ }
+ }
+ while (prevChild) {
+ const next2 = prevChild.nextSibling;
+ el2.removeChild(prevChild);
+ prevChild = next2;
+ }
+ return el2;
+}
+var registeredHandlers = /* @__PURE__ */ new WeakMap();
+function lustreGenericEventHandler(event) {
+ const target = event.currentTarget;
+ if (!registeredHandlers.has(target)) {
+ target.removeEventListener(event.type, lustreGenericEventHandler);
+ return;
+ }
+ const handlersForEventTarget = registeredHandlers.get(target);
+ if (!handlersForEventTarget.has(event.type)) {
+ target.removeEventListener(event.type, lustreGenericEventHandler);
+ return;
+ }
+ handlersForEventTarget.get(event.type)(event);
+}
+function lustreServerEventHandler(event) {
+ const el2 = event.target;
+ const tag2 = el2.getAttribute(`data-lustre-on-${event.type}`);
+ const data = JSON.parse(el2.getAttribute("data-lustre-data") || "{}");
+ const include = JSON.parse(el2.getAttribute("data-lustre-include") || "[]");
+ switch (event.type) {
+ case "input":
+ case "change":
+ include.push("target.value");
+ break;
+ }
+ return {
+ tag: tag2,
+ data: include.reduce(
+ (data2, property) => {
+ const path = property.split(".");
+ for (let i = 0, o = data2, e = event; i < path.length; i++) {
+ if (i === path.length - 1) {
+ o[path[i]] = e[path[i]];
+ } else {
+ o[path[i]] ??= {};
+ e = e[path[i]];
+ o = o[path[i]];
+ }
+ }
+ return data2;
+ },
+ { data }
+ )
+ };
+}
+function getKeyedChildren(el2) {
+ const keyedChildren = /* @__PURE__ */ new Map();
+ if (el2) {
+ for (const child of el2.children) {
+ const key = child.key || child?.getAttribute("data-lustre-key");
+ if (key)
+ keyedChildren.set(key, child);
+ }
+ }
+ return keyedChildren;
+}
+
+// build/dev/javascript/lustre/client-runtime.ffi.mjs
+var LustreClientApplication2 = class _LustreClientApplication {
+ #root = null;
+ #queue = [];
+ #effects = [];
+ #didUpdate = false;
+ #isComponent = false;
+ #model = null;
+ #update = null;
+ #view = null;
+ static start(flags, selector, init2, update2, view) {
+ if (!is_browser())
+ return new Error(new NotABrowser());
+ const root2 = selector instanceof HTMLElement ? selector : document.querySelector(selector);
+ if (!root2)
+ return new Error(new ElementNotFound(selector));
+ const app = new _LustreClientApplication(init2(flags), update2, view, root2);
+ return new Ok((msg) => app.send(msg));
+ }
+ constructor([model, effects], update2, view, root2 = document.body, isComponent = false) {
+ this.#model = model;
+ this.#update = update2;
+ this.#view = view;
+ this.#root = root2;
+ this.#effects = effects.all.toArray();
+ this.#didUpdate = true;
+ this.#isComponent = isComponent;
+ window.requestAnimationFrame(() => this.#tick());
+ }
+ send(action) {
+ switch (true) {
+ case action instanceof Dispatch: {
+ this.#queue.push(action[0]);
+ this.#tick();
+ return;
+ }
+ case action instanceof Shutdown: {
+ this.#shutdown();
+ return;
+ }
+ default:
+ return;
+ }
+ }
+ emit(event, data) {
+ this.#root.dispatchEvent(
+ new CustomEvent(event, {
+ bubbles: true,
+ detail: data,
+ composed: true
+ })
+ );
+ }
+ #tick() {
+ this.#flush_queue();
+ const vdom = this.#view(this.#model);
+ const dispatch = (handler) => (e) => {
+ const result = handler(e);
+ if (result instanceof Ok) {
+ this.send(new Dispatch(result[0]));
+ }
+ };
+ this.#didUpdate = false;
+ this.#root = morph(this.#root, vdom, dispatch, this.#isComponent);
+ }
+ #flush_queue(iterations = 0) {
+ while (this.#queue.length) {
+ const [next, effects] = this.#update(this.#model, this.#queue.shift());
+ this.#didUpdate ||= !isEqual(this.#model, next);
+ this.#model = next;
+ this.#effects = this.#effects.concat(effects.all.toArray());
+ }
+ while (this.#effects.length) {
+ this.#effects.shift()(
+ (msg) => this.send(new Dispatch(msg)),
+ (event, data) => this.emit(event, data)
+ );
+ }
+ if (this.#queue.length) {
+ if (iterations < 5) {
+ this.#flush_queue(++iterations);
+ } else {
+ window.requestAnimationFrame(() => this.#tick());
+ }
+ }
+ }
+ #shutdown() {
+ this.#root.remove();
+ this.#root = null;
+ this.#model = null;
+ this.#queue = [];
+ this.#effects = [];
+ this.#didUpdate = false;
+ this.#update = () => {
+ };
+ this.#view = () => {
+ };
+ }
+};
+var start = (app, selector, flags) => LustreClientApplication2.start(
+ flags,
+ selector,
+ app.init,
+ app.update,
+ app.view
+);
+var is_browser = () => window && window.document;
+
+// build/dev/javascript/lustre/lustre.mjs
+var App = class extends CustomType {
+ constructor(init2, update2, view, on_attribute_change) {
+ super();
+ this.init = init2;
+ this.update = update2;
+ this.view = view;
+ this.on_attribute_change = on_attribute_change;
+ }
+};
+var ElementNotFound = class extends CustomType {
+ constructor(selector) {
+ super();
+ this.selector = selector;
+ }
+};
+var NotABrowser = class extends CustomType {
+};
+function application(init2, update2, view) {
+ return new App(init2, update2, view, new None());
+}
+function element2(html) {
+ let init2 = (_) => {
+ return [void 0, none()];
+ };
+ let update2 = (_, _1) => {
+ return [void 0, none()];
+ };
+ let view = (_) => {
+ return html;
+ };
+ return application(init2, update2, view);
+}
+function start3(app, selector, flags) {
+ return guard(
+ !is_browser(),
+ new Error(new NotABrowser()),
+ () => {
+ return start(app, selector, flags);
+ }
+ );
+}
+
+// build/dev/javascript/lustre/lustre/element/html.mjs
+function h1(attrs, children) {
+ return element("h1", attrs, children);
+}
+function h2(attrs, children) {
+ return element("h2", attrs, children);
+}
+function div(attrs, children) {
+ return element("div", attrs, children);
+}
+
+// build/dev/javascript/lustre_ui/lustre/ui/layout/centre.mjs
+function of2(element3, attributes, children) {
+ return element3(
+ prepend(class$("lustre-ui-centre"), attributes),
+ toList([children])
+ );
+}
+function centre(attributes, children) {
+ return of2(div, attributes, children);
+}
+
+// build/dev/javascript/gleam_community_colour/gleam_community/colour.mjs
+var Rgba = class extends CustomType {
+ constructor(r, g, b, a) {
+ super();
+ this.r = r;
+ this.g = g;
+ this.b = b;
+ this.a = a;
+ }
+};
+var light_red = new Rgba(
+ 0.9372549019607843,
+ 0.1607843137254902,
+ 0.1607843137254902,
+ 1
+);
+var red = new Rgba(0.8, 0, 0, 1);
+var dark_red = new Rgba(0.6431372549019608, 0, 0, 1);
+var light_orange = new Rgba(
+ 0.9882352941176471,
+ 0.6862745098039216,
+ 0.24313725490196078,
+ 1
+);
+var orange = new Rgba(0.9607843137254902, 0.4745098039215686, 0, 1);
+var dark_orange = new Rgba(
+ 0.807843137254902,
+ 0.3607843137254902,
+ 0,
+ 1
+);
+var light_yellow = new Rgba(
+ 1,
+ 0.9137254901960784,
+ 0.30980392156862746,
+ 1
+);
+var yellow = new Rgba(0.9294117647058824, 0.8313725490196079, 0, 1);
+var dark_yellow = new Rgba(
+ 0.7686274509803922,
+ 0.6274509803921569,
+ 0,
+ 1
+);
+var light_green = new Rgba(
+ 0.5411764705882353,
+ 0.8862745098039215,
+ 0.20392156862745098,
+ 1
+);
+var green = new Rgba(
+ 0.45098039215686275,
+ 0.8235294117647058,
+ 0.08627450980392157,
+ 1
+);
+var dark_green = new Rgba(
+ 0.3058823529411765,
+ 0.6039215686274509,
+ 0.023529411764705882,
+ 1
+);
+var light_blue = new Rgba(
+ 0.4470588235294118,
+ 0.6235294117647059,
+ 0.8117647058823529,
+ 1
+);
+var blue = new Rgba(
+ 0.20392156862745098,
+ 0.396078431372549,
+ 0.6431372549019608,
+ 1
+);
+var dark_blue = new Rgba(
+ 0.12549019607843137,
+ 0.2901960784313726,
+ 0.5294117647058824,
+ 1
+);
+var light_purple = new Rgba(
+ 0.6784313725490196,
+ 0.4980392156862745,
+ 0.6588235294117647,
+ 1
+);
+var purple = new Rgba(
+ 0.4588235294117647,
+ 0.3137254901960784,
+ 0.4823529411764706,
+ 1
+);
+var dark_purple = new Rgba(
+ 0.3607843137254902,
+ 0.20784313725490197,
+ 0.4,
+ 1
+);
+var light_brown = new Rgba(
+ 0.9137254901960784,
+ 0.7254901960784313,
+ 0.43137254901960786,
+ 1
+);
+var brown = new Rgba(
+ 0.7568627450980392,
+ 0.49019607843137253,
+ 0.06666666666666667,
+ 1
+);
+var dark_brown = new Rgba(
+ 0.5607843137254902,
+ 0.34901960784313724,
+ 0.00784313725490196,
+ 1
+);
+var black = new Rgba(0, 0, 0, 1);
+var white = new Rgba(1, 1, 1, 1);
+var light_grey = new Rgba(
+ 0.9333333333333333,
+ 0.9333333333333333,
+ 0.9254901960784314,
+ 1
+);
+var grey = new Rgba(
+ 0.8274509803921568,
+ 0.8431372549019608,
+ 0.8117647058823529,
+ 1
+);
+var dark_grey = new Rgba(
+ 0.7294117647058823,
+ 0.7411764705882353,
+ 0.7137254901960784,
+ 1
+);
+var light_gray = new Rgba(
+ 0.9333333333333333,
+ 0.9333333333333333,
+ 0.9254901960784314,
+ 1
+);
+var gray = new Rgba(
+ 0.8274509803921568,
+ 0.8431372549019608,
+ 0.8117647058823529,
+ 1
+);
+var dark_gray = new Rgba(
+ 0.7294117647058823,
+ 0.7411764705882353,
+ 0.7137254901960784,
+ 1
+);
+var light_charcoal = new Rgba(
+ 0.5333333333333333,
+ 0.5411764705882353,
+ 0.5215686274509804,
+ 1
+);
+var charcoal = new Rgba(
+ 0.3333333333333333,
+ 0.3411764705882353,
+ 0.3254901960784314,
+ 1
+);
+var dark_charcoal = new Rgba(
+ 0.1803921568627451,
+ 0.20392156862745098,
+ 0.21176470588235294,
+ 1
+);
+var pink = new Rgba(1, 0.6862745098039216, 0.9529411764705882, 1);
+
+// build/dev/javascript/lustre_ui/lustre/ui.mjs
+var centre2 = centre;
+
+// build/dev/javascript/app/app.mjs
+function main() {
+ let styles = toList([
+ ["width", "100vw"],
+ ["height", "100vh"],
+ ["padding", "1rem"]
+ ]);
+ let app = element2(
+ centre2(
+ toList([style(styles)]),
+ div(
+ toList([]),
+ toList([
+ h1(toList([]), toList([text("Hello, world.")])),
+ h2(toList([]), toList([text("Welcome to Lustre.")]))
+ ])
+ )
+ )
+ );
+ let $ = start3(app, "#app", void 0);
+ if (!$.isOk()) {
+ throw makeError(
+ "assignment_no_match",
+ "app",
+ 17,
+ "main",
+ "Assignment pattern did not match",
+ { value: $ }
+ );
+ }
+ return void 0;
+}
+
+// build/.lustre/entry.mjs
+main();
diff --git a/examples/01-hello-world/src/app.gleam b/examples/01-hello-world/src/app.gleam
index 38c1f68..57b9492 100644
--- a/examples/01-hello-world/src/app.gleam
+++ b/examples/01-hello-world/src/app.gleam
@@ -2,24 +2,19 @@ import lustre
import lustre/attribute
import lustre/element
import lustre/element/html
-// These examples are written with `lustre/ui` in mind. They'll work regardless,
-// but to see what `lustre/ui` can do make sure to run each of these examples with
-// the `--use-example-styles` flag:
-//
-// $ gleam run -m lustre/dev start --use-example-styles
-//
-// In your own apps, make sure to add the `lustre/ui` dependency and include the
-// stylesheet somewhere.
import lustre/ui
pub fn main() {
let styles = [#("width", "100vw"), #("height", "100vh"), #("padding", "1rem")]
+ let app =
+ lustre.element(ui.centre(
+ [attribute.style(styles)],
+ html.div([], [
+ html.h1([], [element.text("Hello, world.")]),
+ html.h2([], [element.text("Welcome to Lustre.")]),
+ ]),
+ ))
+ let assert Ok(_) = lustre.start(app, "#app", Nil)
- lustre.element(ui.centre(
- [attribute.style(styles)],
- html.div([], [
- html.h1([], [element.text("Hello, world.")]),
- html.h2([], [element.text("Welcome to Lustre.")]),
- ]),
- ))
+ Nil
}