diff options
Diffstat (limited to 'examples/03-controlled-inputs')
-rw-r--r-- | examples/03-controlled-inputs/index.html | 19 | ||||
-rw-r--r-- | examples/03-controlled-inputs/manifest.toml | 23 | ||||
-rw-r--r-- | examples/03-controlled-inputs/priv/static/app.mjs | 2139 | ||||
-rw-r--r-- | examples/03-controlled-inputs/src/app.gleam | 10 |
4 files changed, 2177 insertions, 14 deletions
diff --git a/examples/03-controlled-inputs/index.html b/examples/03-controlled-inputs/index.html new file mode 100644 index 0000000..36ddf10 --- /dev/null +++ b/examples/03-controlled-inputs/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/03-controlled-inputs/manifest.toml b/examples/03-controlled-inputs/manifest.toml index 7f82909..c0d1211 100644 --- a/examples/03-controlled-inputs/manifest.toml +++ b/examples/03-controlled-inputs/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/03-controlled-inputs/priv/static/app.mjs b/examples/03-controlled-inputs/priv/static/app.mjs new file mode 100644 index 0000000..9fdf4b2 --- /dev/null +++ b/examples/03-controlled-inputs/priv/static/app.mjs @@ -0,0 +1,2139 @@ +// 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 length3 = 0; + for (let _ of this) + length3++; + return length3; + } +}; +function prepend(element2, tail) { + return new NonEmpty(element2, 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 BitArray = class _BitArray { + constructor(buffer) { + if (!(buffer instanceof Uint8Array)) { + throw "BitArray can only be constructed from a Uint8Array"; + } + this.buffer = buffer; + } + // @internal + get length() { + return this.buffer.length; + } + // @internal + byteAt(index2) { + return this.buffer[index2]; + } + // @internal + floatAt(index2) { + return byteArrayToFloat(this.buffer.slice(index2, index2 + 8)); + } + // @internal + intFromSlice(start4, end) { + return byteArrayToInt(this.buffer.slice(start4, end)); + } + // @internal + binaryFromSlice(start4, end) { + return new _BitArray(this.buffer.slice(start4, end)); + } + // @internal + sliceAfter(index2) { + return new _BitArray(this.buffer.slice(index2)); + } +}; +function byteArrayToInt(byteArray) { + byteArray = byteArray.reverse(); + let value3 = 0; + for (let i = byteArray.length - 1; i >= 0; i--) { + value3 = value3 * 256 + byteArray[i]; + } + return value3; +} +function byteArrayToFloat(byteArray) { + return new Float64Array(byteArray.reverse().buffer)[0]; +} +var Result = class _Result extends CustomType { + // @internal + static isResult(data) { + return data instanceof _Result; + } +}; +var Ok = class extends Result { + constructor(value3) { + super(); + this[0] = value3; + } + // @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 Some = class extends CustomType { + constructor(x0) { + super(); + this[0] = x0; + } +}; +var None = class extends CustomType { +}; +function to_result(option, e) { + if (option instanceof Some) { + let a = option[0]; + return new Ok(a); + } else { + return new Error(e); + } +} + +// build/dev/javascript/gleam_stdlib/gleam/list.mjs +function do_reverse_acc(loop$remaining, loop$accumulator) { + while (true) { + let remaining = loop$remaining; + let accumulator = loop$accumulator; + if (remaining.hasLength(0)) { + return accumulator; + } else { + let item = remaining.head; + let rest$1 = remaining.tail; + loop$remaining = rest$1; + loop$accumulator = prepend(item, accumulator); + } + } +} +function do_reverse(list) { + return do_reverse_acc(list, toList([])); +} +function reverse(xs) { + return do_reverse(xs); +} +function do_map(loop$list, loop$fun, loop$acc) { + while (true) { + let list = loop$list; + let fun = loop$fun; + let acc = loop$acc; + if (list.hasLength(0)) { + return reverse(acc); + } else { + let x = list.head; + let xs = list.tail; + loop$list = xs; + loop$fun = fun; + loop$acc = prepend(fun(x), acc); + } + } +} +function map(list, fun) { + return do_map(list, fun, toList([])); +} +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/result.mjs +function map2(result, fun) { + if (result.isOk()) { + let x = result[0]; + return new Ok(fun(x)); + } else { + let e = result[0]; + return new Error(e); + } +} +function map_error(result, fun) { + if (result.isOk()) { + let x = result[0]; + return new Ok(x); + } else { + let error = result[0]; + return new Error(fun(error)); + } +} +function try$(result, fun) { + if (result.isOk()) { + let x = result[0]; + return fun(x); + } else { + let e = result[0]; + return new Error(e); + } +} + +// build/dev/javascript/gleam_stdlib/gleam/string_builder.mjs +function from_strings(strings) { + return concat(strings); +} +function to_string(builder) { + return identity(builder); +} + +// build/dev/javascript/gleam_stdlib/gleam/dynamic.mjs +var DecodeError = class extends CustomType { + constructor(expected, found, path) { + super(); + this.expected = expected; + this.found = found; + this.path = path; + } +}; +function from(a) { + return identity(a); +} +function string(data) { + return decode_string(data); +} +function classify(data) { + return classify_dynamic(data); +} +function int(data) { + return decode_int(data); +} +function any(decoders) { + return (data) => { + if (decoders.hasLength(0)) { + return new Error( + toList([new DecodeError("another type", classify(data), toList([]))]) + ); + } else { + let decoder2 = decoders.head; + let decoders$1 = decoders.tail; + let $ = decoder2(data); + if ($.isOk()) { + let decoded = $[0]; + return new Ok(decoded); + } else { + return any(decoders$1)(data); + } + } + }; +} +function push_path(error, name) { + let name$1 = from(name); + let decoder2 = any( + toList([string, (x) => { + return map2(int(x), to_string2); + }]) + ); + let name$2 = (() => { + let $ = decoder2(name$1); + if ($.isOk()) { + let name$22 = $[0]; + return name$22; + } else { + let _pipe = toList(["<", classify(name$1), ">"]); + let _pipe$1 = from_strings(_pipe); + return to_string(_pipe$1); + } + })(); + return error.withFields({ path: prepend(name$2, error.path) }); +} +function map_errors(result, f) { + return map_error( + result, + (_capture) => { + return map(_capture, f); + } + ); +} +function field(name, inner_type) { + return (value3) => { + let missing_field_error = new DecodeError("field", "nothing", toList([])); + return try$( + decode_field(value3, name), + (maybe_inner) => { + let _pipe = maybe_inner; + let _pipe$1 = to_result(_pipe, toList([missing_field_error])); + let _pipe$2 = try$(_pipe$1, inner_type); + return map_errors( + _pipe$2, + (_capture) => { + return push_path(_capture, name); + } + ); + } + ); + }; +} + +// build/dev/javascript/gleam_stdlib/dict.mjs +var referenceMap = /* @__PURE__ */ new WeakMap(); +var tempDataView = new DataView(new ArrayBuffer(8)); +var referenceUID = 0; +function hashByReference(o) { + const known = referenceMap.get(o); + if (known !== void 0) { + return known; + } + const hash = referenceUID++; + if (referenceUID === 2147483647) { + referenceUID = 0; + } + referenceMap.set(o, hash); + return hash; +} +function hashMerge(a, b) { + return a ^ b + 2654435769 + (a << 6) + (a >> 2) | 0; +} +function hashString(s) { + let hash = 0; + const len = s.length; + for (let i = 0; i < len; i++) { + hash = Math.imul(31, hash) + s.charCodeAt(i) | 0; + } + return hash; +} +function hashNumber(n) { + tempDataView.setFloat64(0, n); + const i = tempDataView.getInt32(0); + const j = tempDataView.getInt32(4); + return Math.imul(73244475, i >> 16 ^ i) ^ j; +} +function hashBigInt(n) { + return hashString(n.toString()); +} +function hashObject(o) { + const proto = Object.getPrototypeOf(o); + if (proto !== null && typeof proto.hashCode === "function") { + try { + const code = o.hashCode(o); + if (typeof code === "number") { + return code; + } + } catch { + } + } + if (o instanceof Promise || o instanceof WeakSet || o instanceof WeakMap) { + return hashByReference(o); + } + if (o instanceof Date) { + return hashNumber(o.getTime()); + } + let h = 0; + if (o instanceof ArrayBuffer) { + o = new Uint8Array(o); + } + if (Array.isArray(o) || o instanceof Uint8Array) { + for (let i = 0; i < o.length; i++) { + h = Math.imul(31, h) + getHash(o[i]) | 0; + } + } else if (o instanceof Set) { + o.forEach((v) => { + h = h + getHash(v) | 0; + }); + } else if (o instanceof Map) { + o.forEach((v, k) => { + h = h + hashMerge(getHash(v), getHash(k)) | 0; + }); + } else { + const keys2 = Object.keys(o); + for (let i = 0; i < keys2.length; i++) { + const k = keys2[i]; + const v = o[k]; + h = h + hashMerge(getHash(v), hashString(k)) | 0; + } + } + return h; +} +function getHash(u) { + if (u === null) + return 1108378658; + if (u === void 0) + return 1108378659; + if (u === true) + return 1108378657; + if (u === false) + return 1108378656; + switch (typeof u) { + case "number": + return hashNumber(u); + case "string": + return hashString(u); + case "bigint": + return hashBigInt(u); + case "object": + return hashObject(u); + case "symbol": + return hashByReference(u); + case "function": + return hashByReference(u); + default: + return 0; + } +} +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; +var ENTRY = 0; +var ARRAY_NODE = 1; +var INDEX_NODE = 2; +var COLLISION_NODE = 3; +var EMPTY = { + type: INDEX_NODE, + bitmap: 0, + array: [] +}; +function mask(hash, shift) { + return hash >>> shift & MASK; +} +function bitpos(hash, shift) { + return 1 << mask(hash, shift); +} +function bitcount(x) { + x -= x >> 1 & 1431655765; + x = (x & 858993459) + (x >> 2 & 858993459); + x = x + (x >> 4) & 252645135; + x += x >> 8; + x += x >> 16; + return x & 127; +} +function index(bitmap, bit) { + return bitcount(bitmap & bit - 1); +} +function cloneAndSet(arr, at, val) { + const len = arr.length; + const out = new Array(len); + for (let i = 0; i < len; ++i) { + out[i] = arr[i]; + } + out[at] = val; + return out; +} +function spliceIn(arr, at, val) { + const len = arr.length; + const out = new Array(len + 1); + let i = 0; + let g = 0; + while (i < at) { + out[g++] = arr[i++]; + } + out[g++] = val; + while (i < len) { + out[g++] = arr[i++]; + } + return out; +} +function spliceOut(arr, at) { + const len = arr.length; + const out = new Array(len - 1); + let i = 0; + let g = 0; + while (i < at) { + out[g++] = arr[i++]; + } + ++i; + while (i < len) { + out[g++] = arr[i++]; + } + return out; +} +function createNode(shift, key1, val1, key2hash, key2, val2) { + const key1hash = getHash(key1); + if (key1hash === key2hash) { + return { + type: COLLISION_NODE, + hash: key1hash, + array: [ + { type: ENTRY, k: key1, v: val1 }, + { type: ENTRY, k: key2, v: val2 } + ] + }; + } + const addedLeaf = { val: false }; + return assoc( + assocIndex(EMPTY, shift, key1hash, key1, val1, addedLeaf), + shift, + key2hash, + key2, + val2, + addedLeaf + ); +} +function assoc(root2, shift, hash, key, val, addedLeaf) { + switch (root2.type) { + case ARRAY_NODE: + return assocArray(root2, shift, hash, key, val, addedLeaf); + case INDEX_NODE: + return assocIndex(root2, shift, hash, key, val, addedLeaf); + case COLLISION_NODE: + return assocCollision(root2, shift, hash, key, val, addedLeaf); + } +} +function assocArray(root2, shift, hash, key, val, addedLeaf) { + const idx = mask(hash, shift); + const node = root2.array[idx]; + if (node === void 0) { + addedLeaf.val = true; + return { + type: ARRAY_NODE, + size: root2.size + 1, + array: cloneAndSet(root2.array, idx, { type: ENTRY, k: key, v: val }) + }; + } + if (node.type === ENTRY) { + if (isEqual(key, node.k)) { + if (val === node.v) { + return root2; + } + return { + type: ARRAY_NODE, + size: root2.size, + array: cloneAndSet(root2.array, idx, { + type: ENTRY, + k: key, + v: val + }) + }; + } + addedLeaf.val = true; + return { + type: ARRAY_NODE, + size: root2.size, + array: cloneAndSet( + root2.array, + idx, + createNode(shift + SHIFT, node.k, node.v, hash, key, val) + ) + }; + } + const n = assoc(node, shift + SHIFT, hash, key, val, addedLeaf); + if (n === node) { + return root2; + } + return { + type: ARRAY_NODE, + size: root2.size, + array: cloneAndSet(root2.array, idx, n) + }; +} +function assocIndex(root2, shift, hash, key, val, addedLeaf) { + const bit = bitpos(hash, shift); + const idx = index(root2.bitmap, bit); + if ((root2.bitmap & bit) !== 0) { + const node = root2.array[idx]; + if (node.type !== ENTRY) { + const n = assoc(node, shift + SHIFT, hash, key, val, addedLeaf); + if (n === node) { + return root2; + } + return { + type: INDEX_NODE, + bitmap: root2.bitmap, + array: cloneAndSet(root2.array, idx, n) + }; + } + const nodeKey = node.k; + if (isEqual(key, nodeKey)) { + if (val === node.v) { + return root2; + } + return { + type: INDEX_NODE, + bitmap: root2.bitmap, + array: cloneAndSet(root2.array, idx, { + type: ENTRY, + k: key, + v: val + }) + }; + } + addedLeaf.val = true; + return { + type: INDEX_NODE, + bitmap: root2.bitmap, + array: cloneAndSet( + root2.array, + idx, + createNode(shift + SHIFT, nodeKey, node.v, hash, key, val) + ) + }; + } else { + const n = root2.array.length; + if (n >= MAX_INDEX_NODE) { + const nodes = new Array(32); + const jdx = mask(hash, shift); + nodes[jdx] = assocIndex(EMPTY, shift + SHIFT, hash, key, val, addedLeaf); + let j = 0; + let bitmap = root2.bitmap; + for (let i = 0; i < 32; i++) { + if ((bitmap & 1) !== 0) { + const node = root2.array[j++]; + nodes[i] = node; + } + bitmap = bitmap >>> 1; + } + return { + type: ARRAY_NODE, + size: n + 1, + array: nodes + }; + } else { + const newArray = spliceIn(root2.array, idx, { + type: ENTRY, + k: key, + v: val + }); + addedLeaf.val = true; + return { + type: INDEX_NODE, + bitmap: root2.bitmap | bit, + array: newArray + }; + } + } +} +function assocCollision(root2, shift, hash, key, val, addedLeaf) { + if (hash === root2.hash) { + const idx = collisionIndexOf(root2, key); + if (idx !== -1) { + const entry = root2.array[idx]; + if (entry.v === val) { + return root2; + } + return { + type: COLLISION_NODE, + hash, + array: cloneAndSet(root2.array, idx, { type: ENTRY, k: key, v: val }) + }; + } + const size = root2.array.length; + addedLeaf.val = true; + return { + type: COLLISION_NODE, + hash, + array: cloneAndSet(root2.array, size, { type: ENTRY, k: key, v: val }) + }; + } + return assoc( + { + type: INDEX_NODE, + bitmap: bitpos(root2.hash, shift), + array: [root2] + }, + shift, + hash, + key, + val, + addedLeaf + ); +} +function collisionIndexOf(root2, key) { + const size = root2.array.length; + for (let i = 0; i < size; i++) { + if (isEqual(key, root2.array[i].k)) { + return i; + } + } + return -1; +} +function find(root2, shift, hash, key) { + switch (root2.type) { + case ARRAY_NODE: + return findArray(root2, shift, hash, key); + case INDEX_NODE: + return findIndex(root2, shift, hash, key); + case COLLISION_NODE: + return findCollision(root2, key); + } +} +function findArray(root2, shift, hash, key) { + const idx = mask(hash, shift); + const node = root2.array[idx]; + if (node === void 0) { + return void 0; + } + if (node.type !== ENTRY) { + return find(node, shift + SHIFT, hash, key); + } + if (isEqual(key, node.k)) { + return node; + } + return void 0; +} +function findIndex(root2, shift, hash, key) { + const bit = bitpos(hash, shift); + if ((root2.bitmap & bit) === 0) { + return void 0; + } + const idx = index(root2.bitmap, bit); + const node = root2.array[idx]; + if (node.type !== ENTRY) { + return find(node, shift + SHIFT, hash, key); + } + if (isEqual(key, node.k)) { + return node; + } + return void 0; +} +function findCollision(root2, key) { + const idx = collisionIndexOf(root2, key); + if (idx < 0) { + return void 0; + } + return root2.array[idx]; +} +function without(root2, shift, hash, key) { + switch (root2.type) { + case ARRAY_NODE: + return withoutArray(root2, shift, hash, key); + case INDEX_NODE: + return withoutIndex(root2, shift, hash, key); + case COLLISION_NODE: + return withoutCollision(root2, key); + } +} +function withoutArray(root2, shift, hash, key) { + const idx = mask(hash, shift); + const node = root2.array[idx]; + if (node === void 0) { + return root2; + } + let n = void 0; + if (node.type === ENTRY) { + if (!isEqual(node.k, key)) { + return root2; + } + } else { + n = without(node, shift + SHIFT, hash, key); + if (n === node) { + return root2; + } + } + if (n === void 0) { + if (root2.size <= MIN_ARRAY_NODE) { + const arr = root2.array; + const out = new Array(root2.size - 1); + let i = 0; + let j = 0; + let bitmap = 0; + while (i < idx) { + const nv = arr[i]; + if (nv !== void 0) { + out[j] = nv; + bitmap |= 1 << i; + ++j; + } + ++i; + } + ++i; + while (i < arr.length) { + const nv = arr[i]; + if (nv !== void 0) { + out[j] = nv; + bitmap |= 1 << i; + ++j; + } + ++i; + } + return { + type: INDEX_NODE, + bitmap, + array: out + }; + } + return { + type: ARRAY_NODE, + size: root2.size - 1, + array: cloneAndSet(root2.array, idx, n) + }; + } + return { + type: ARRAY_NODE, + size: root2.size, + array: cloneAndSet(root2.array, idx, n) + }; +} +function withoutIndex(root2, shift, hash, key) { + const bit = bitpos(hash, shift); + if ((root2.bitmap & bit) === 0) { + return root2; + } + const idx = index(root2.bitmap, bit); + const node = root2.array[idx]; + if (node.type !== ENTRY) { + const n = without(node, shift + SHIFT, hash, key); + if (n === node) { + return root2; + } + if (n !== void 0) { + return { + type: INDEX_NODE, + bitmap: root2.bitmap, + array: cloneAndSet(root2.array, idx, n) + }; + } + if (root2.bitmap === bit) { + return void 0; + } + return { + type: INDEX_NODE, + bitmap: root2.bitmap ^ bit, + array: spliceOut(root2.array, idx) + }; + } + if (isEqual(key, node.k)) { + if (root2.bitmap === bit) { + return void 0; + } + return { + type: INDEX_NODE, + bitmap: root2.bitmap ^ bit, + array: spliceOut(root2.array, idx) + }; + } + return root2; +} +function withoutCollision(root2, key) { + const idx = collisionIndexOf(root2, key); + if (idx < 0) { + return root2; + } + if (root2.array.length === 1) { + return void 0; + } + return { + type: COLLISION_NODE, + hash: root2.hash, + array: spliceOut(root2.array, idx) + }; +} +function forEach(root2, fn) { + if (root2 === void 0) { + return; + } + const items = root2.array; + const size = items.length; + for (let i = 0; i < size; i++) { + const item = items[i]; + if (item === void 0) { + continue; + } + if (item.type === ENTRY) { + fn(item.v, item.k); + continue; + } + forEach(item, fn); + } +} +var Dict = class _Dict { + /** + * @template V + * @param {Record<string,V>} o + * @returns {Dict<string,V>} + */ + static fromObject(o) { + const keys2 = Object.keys(o); + let m = _Dict.new(); + for (let i = 0; i < keys2.length; i++) { + const k = keys2[i]; + m = m.set(k, o[k]); + } + return m; + } + /** + * @template K,V + * @param {Map<K,V>} o + * @returns {Dict<K,V>} + */ + static fromMap(o) { + let m = _Dict.new(); + o.forEach((v, k) => { + m = m.set(k, v); + }); + return m; + } + static new() { + return new _Dict(void 0, 0); + } + /** + * @param {undefined | Node<K,V>} root + * @param {number} size + */ + constructor(root2, size) { + this.root = root2; + this.size = size; + } + /** + * @template NotFound + * @param {K} key + * @param {NotFound} notFound + * @returns {NotFound | V} + */ + get(key, notFound) { + if (this.root === void 0) { + return notFound; + } + const found = find(this.root, 0, getHash(key), key); + if (found === void 0) { + return notFound; + } + return found.v; + } + /** + * @param {K} key + * @param {V} val + * @returns {Dict<K,V>} + */ + set(key, val) { + const addedLeaf = { val: false }; + const root2 = this.root === void 0 ? EMPTY : this.root; + const newRoot = assoc(root2, 0, getHash(key), key, val, addedLeaf); + if (newRoot === this.root) { + return this; + } + return new _Dict(newRoot, addedLeaf.val ? this.size + 1 : this.size); + } + /** + * @param {K} key + * @returns {Dict<K,V>} + */ + delete(key) { + if (this.root === void 0) { + return this; + } + const newRoot = without(this.root, 0, getHash(key), key); + if (newRoot === this.root) { + return this; + } + if (newRoot === void 0) { + return _Dict.new(); + } + return new _Dict(newRoot, this.size - 1); + } + /** + * @param {K} key + * @returns {boolean} + */ + has(key) { + if (this.root === void 0) { + return false; + } + return find(this.root, 0, getHash(key), key) !== void 0; + } + /** + * @returns {[K,V][]} + */ + entries() { + if (this.root === void 0) { + return []; + } + const result = []; + this.forEach((v, k) => result.push([k, v])); + return result; + } + /** + * + * @param {(val:V,key:K)=>void} fn + */ + forEach(fn) { + forEach(this.root, fn); + } + hashCode() { + let h = 0; + this.forEach((v, k) => { + h = h + hashMerge(getHash(v), getHash(k)) | 0; + }); + return h; + } + /** + * @param {unknown} o + * @returns {boolean} + */ + equals(o) { + if (!(o instanceof _Dict) || this.size !== o.size) { + return false; + } + let equal2 = true; + this.forEach((v, k) => { + equal2 = equal2 && isEqual(o.get(k, !v), v); + }); + return equal2; + } +}; + +// build/dev/javascript/gleam_stdlib/gleam_stdlib.mjs +var Nil = void 0; +var NOT_FOUND = {}; +function identity(x) { + return x; +} +function to_string3(term) { + return term.toString(); +} +function string_length(string3) { + if (string3 === "") { + return 0; + } + const iterator = graphemes_iterator(string3); + if (iterator) { + let i = 0; + for (const _ of iterator) { + i++; + } + return i; + } else { + return string3.match(/./gsu).length; + } +} +function graphemes_iterator(string3) { + if (Intl && Intl.Segmenter) { + return new Intl.Segmenter().segment(string3)[Symbol.iterator](); + } +} +function concat(xs) { + let result = ""; + for (const x of xs) { + result = result + x; + } + return result; +} +function map_get(map4, key) { + const value3 = map4.get(key, NOT_FOUND); + if (value3 === NOT_FOUND) { + return new Error(Nil); + } + return new Ok(value3); +} +function classify_dynamic(data) { + if (typeof data === "string") { + return "String"; + } else if (data instanceof Result) { + return "Result"; + } else if (data instanceof List) { + return "List"; + } else if (data instanceof BitArray) { + return "BitArray"; + } else if (data instanceof Dict) { + return "Dict"; + } else if (Number.isInteger(data)) { + return "Int"; + } else if (Array.isArray(data)) { + return `Tuple of ${data.length} elements`; + } else if (typeof data === "number") { + return "Float"; + } else if (data === null) { + return "Null"; + } else if (data === void 0) { + return "Nil"; + } else { + const type = typeof data; + return type.charAt(0).toUpperCase() + type.slice(1); + } +} +function decoder_error(expected, got) { + return decoder_error_no_classify(expected, classify_dynamic(got)); +} +function decoder_error_no_classify(expected, got) { + return new Error( + List.fromArray([new DecodeError(expected, got, List.fromArray([]))]) + ); +} +function decode_string(data) { + return typeof data === "string" ? new Ok(data) : decoder_error("String", data); +} +function decode_int(data) { + return Number.isInteger(data) ? new Ok(data) : decoder_error("Int", data); +} +function decode_field(value3, name) { + const not_a_map_error = () => decoder_error("Dict", value3); + if (value3 instanceof Dict || value3 instanceof WeakMap || value3 instanceof Map) { + const entry = map_get(value3, name); + return new Ok(entry.isOk() ? new Some(entry[0]) : new None()); + } else if (value3 === null) { + return not_a_map_error(); + } else if (Object.getPrototypeOf(value3) == Object.prototype) { + return try_get_field(value3, name, () => new Ok(new None())); + } else { + return try_get_field(value3, name, not_a_map_error); + } +} +function try_get_field(value3, field4, or_else) { + try { + return field4 in value3 ? new Ok(new Some(value3[field4])) : or_else(); + } catch { + return or_else(); + } +} + +// build/dev/javascript/gleam_stdlib/gleam/int.mjs +function to_string2(x) { + return to_string3(x); +} + +// build/dev/javascript/gleam_stdlib/gleam/string.mjs +function length2(string3) { + return string_length(string3); +} + +// 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; + } +}; +var Event = class extends CustomType { + constructor(x0, x1) { + super(); + this[0] = x0; + this[1] = x1; + } +}; + +// build/dev/javascript/lustre/lustre/attribute.mjs +function attribute(name, value3) { + return new Attribute(name, from(value3), false); +} +function property(name, value3) { + return new Attribute(name, from(value3), true); +} +function on(name, handler) { + return new Event("on" + name, handler); +} +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); +} +function type_(name) { + return attribute("type", name); +} +function value(val) { + return property("value", from(val)); +} + +// 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 value3 = attr[1]; + const isProperty = attr[2]; + if (isProperty) { + el2[name] = value3; + } else if (name.startsWith("on")) { + const eventName = name.slice(2); + const callback = dispatch(value3); + 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, value3); + } else if (name === "class") { + className = className === null ? value3 : className + " " + value3; + } else if (name === "style") { + style2 = style2 === null ? value3 : style2 + value3; + } else if (name === "dangerous-unescaped-html") { + innerHTML = value3; + } else { + el2.setAttribute(name, value3); + if (name === "value") + el2[name] = value3; + 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(event2) { + const target = event2.currentTarget; + if (!registeredHandlers.has(target)) { + target.removeEventListener(event2.type, lustreGenericEventHandler); + return; + } + const handlersForEventTarget = registeredHandlers.get(target); + if (!handlersForEventTarget.has(event2.type)) { + target.removeEventListener(event2.type, lustreGenericEventHandler); + return; + } + handlersForEventTarget.get(event2.type)(event2); +} +function lustreServerEventHandler(event2) { + const el2 = event2.target; + const tag2 = el2.getAttribute(`data-lustre-on-${event2.type}`); + const data = JSON.parse(el2.getAttribute("data-lustre-data") || "{}"); + const include = JSON.parse(el2.getAttribute("data-lustre-include") || "[]"); + switch (event2.type) { + case "input": + case "change": + include.push("target.value"); + break; + } + return { + tag: tag2, + data: include.reduce( + (data2, property2) => { + const path = property2.split("."); + for (let i = 0, o = data2, e = event2; 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, init3, update3, view2) { + 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(init3(flags), update3, view2, root2); + return new Ok((msg) => app.send(msg)); + } + constructor([model, effects], update3, view2, root2 = document.body, isComponent = false) { + this.#model = model; + this.#update = update3; + this.#view = view2; + 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(event2, data) { + this.#root.dispatchEvent( + new CustomEvent(event2, { + 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)), + (event2, data) => this.emit(event2, 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(init3, update3, view2, on_attribute_change) { + super(); + this.init = init3; + this.update = update3; + this.view = view2; + 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(init3, update3, view2) { + return new App(init3, update3, view2, new None()); +} +function simple(init3, update3, view2) { + let init$1 = (flags) => { + return [init3(flags), none()]; + }; + let update$1 = (model, msg) => { + return [update3(model, msg), none()]; + }; + return application(init$1, update$1, view2); +} +function start3(app, selector, flags) { + return guard( + !is_browser(), + new Error(new NotABrowser()), + () => { + return start(app, selector, flags); + } + ); +} + +// build/dev/javascript/lustre/lustre/event.mjs +function on2(name, handler) { + return on(name, handler); +} +function on_click(msg) { + return on2("click", (_) => { + return new Ok(msg); + }); +} +function value2(event2) { + let _pipe = event2; + return field("target", field("value", string))( + _pipe + ); +} +function on_input(msg) { + return on2( + "input", + (event2) => { + let _pipe = value2(event2); + return map2(_pipe, msg); + } + ); +} + +// build/dev/javascript/lustre/lustre/element/html.mjs +function div(attrs, children) { + return element("div", attrs, children); +} +function span(attrs, children) { + return element("span", attrs, children); +} +function button(attrs, children) { + return element("button", attrs, children); +} +function input(attrs) { + return element("input", attrs, toList([])); +} +function label(attrs, children) { + return element("label", attrs, children); +} + +// build/dev/javascript/lustre_ui/lustre/ui/button.mjs +function button2(attributes, children) { + return button( + prepend( + class$("lustre-ui-button"), + prepend(type_("button"), attributes) + ), + children + ); +} + +// build/dev/javascript/lustre_ui/lustre/ui/layout/stack.mjs +function of(element2, attributes, children) { + return element2( + prepend(class$("lustre-ui-stack"), attributes), + children + ); +} +function packed() { + return class$("packed"); +} + +// build/dev/javascript/lustre_ui/lustre/ui/field.mjs +function of2(element2, attributes, label2, input4, message) { + return of( + element2, + prepend( + class$("lustre-ui-field"), + prepend(packed(), attributes) + ), + toList([ + span(toList([class$("label")]), label2), + input4, + span(toList([class$("message")]), message) + ]) + ); +} +function field2(attributes, label2, input4, message) { + return of2(label, attributes, label2, input4, message); +} + +// build/dev/javascript/lustre_ui/lustre/ui/input.mjs +function input2(attributes) { + return input( + prepend(class$("lustre-ui-input"), attributes) + ); +} + +// build/dev/javascript/lustre_ui/lustre/ui/layout/aside.mjs +function of3(element2, attributes, side, main2) { + return element2( + prepend(class$("lustre-ui-aside"), attributes), + toList([side, main2]) + ); +} +function aside(attributes, side, main2) { + return of3(div, attributes, side, main2); +} +function content_first() { + return class$("content-first"); +} +function align_centre() { + return class$("align-centre"); +} + +// build/dev/javascript/lustre_ui/lustre/ui/layout/centre.mjs +function of4(element2, attributes, children) { + return element2( + prepend(class$("lustre-ui-centre"), attributes), + toList([children]) + ); +} +function centre(attributes, children) { + return of4(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 aside2 = aside; +var button3 = button2; +var centre2 = centre; +var field3 = field2; +var input3 = input2; + +// build/dev/javascript/app/app.mjs +var Model = class extends CustomType { + constructor(value3, length3, max2) { + super(); + this.value = value3; + this.length = length3; + this.max = max2; + } +}; +var UserUpdatedMessage = class extends CustomType { + constructor(value3) { + super(); + this.value = value3; + } +}; +var UserResetMessage = class extends CustomType { +}; +function init2(_) { + return new Model("", 0, 10); +} +function update2(model, msg) { + if (msg instanceof UserUpdatedMessage) { + let value3 = msg.value; + let length3 = length2(value3); + let $ = length3 <= model.max; + if ($) { + return model.withFields({ value: value3, length: length3 }); + } else { + return model; + } + } else { + return model.withFields({ value: "", length: 0 }); + } +} +function view(model) { + let styles = toList([ + ["width", "100vw"], + ["height", "100vh"], + ["padding", "1rem"] + ]); + let length3 = to_string2(model.length); + let max2 = to_string2(model.max); + return centre2( + toList([style(styles)]), + aside2( + toList([content_first(), align_centre()]), + field3( + toList([]), + toList([text("Write a message:")]), + input3( + toList([ + value(model.value), + on_input((var0) => { + return new UserUpdatedMessage(var0); + }) + ]) + ), + toList([text(length3 + "/" + max2)]) + ), + button3( + toList([on_click(new UserResetMessage())]), + toList([text("Reset")]) + ) + ) + ); +} +function main() { + let app = simple(init2, update2, view); + let $ = start3(app, "#app", void 0); + if (!$.isOk()) { + throw makeError( + "assignment_no_match", + "app", + 14, + "main", + "Assignment pattern did not match", + { value: $ } + ); + } + return $; +} + +// build/.lustre/entry.mjs +main(); diff --git a/examples/03-controlled-inputs/src/app.gleam b/examples/03-controlled-inputs/src/app.gleam index b4a29c2..d44e1ae 100644 --- a/examples/03-controlled-inputs/src/app.gleam +++ b/examples/03-controlled-inputs/src/app.gleam @@ -4,16 +4,8 @@ import lustre import lustre/attribute import lustre/element.{type Element} import lustre/event -// 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 -import lustre/ui/aside +import lustre/ui/layout/aside // MAIN ------------------------------------------------------------------------ |