aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/input.gleam129
-rw-r--r--test/input.html52
2 files changed, 181 insertions, 0 deletions
diff --git a/test/input.gleam b/test/input.gleam
new file mode 100644
index 0000000..581630e
--- /dev/null
+++ b/test/input.gleam
@@ -0,0 +1,129 @@
+// IMPORTS ---------------------------------------------------------------------
+
+import gleam/dynamic
+import gleam/option.{None, Option, Some}
+import gleam/string
+import lustre
+import lustre/attribute.{attribute}
+import lustre/element.{Element}
+import lustre/event
+
+// MAIN ------------------------------------------------------------------------
+
+pub fn main() {
+ // A `simple` lustre application doesn't produce `Cmd`s. These are best to
+ // start with if you're just getting started with lustre or you know you don't
+ // need the runtime to manage any side effects.
+ let app = lustre.simple(init, update, render)
+ let assert Ok(_) = lustre.start(app, "body")
+
+ Nil
+}
+
+// MODEL -----------------------------------------------------------------------
+
+type Model {
+ Model(email: String, password: String, remember_me: Bool)
+}
+
+fn init() -> Model {
+ Model(email: "", password: "", remember_me: False)
+}
+
+// UPDATE ----------------------------------------------------------------------
+
+type Msg {
+ Typed(Input, String)
+ Toggled(Control, Bool)
+}
+
+type Input {
+ Email
+ Password
+}
+
+type Control {
+ RememberMe
+}
+
+fn update(model: Model, msg: Msg) -> Model {
+ case msg {
+ Typed(Email, email) -> Model(..model, email: email)
+ Typed(Password, password) -> Model(..model, password: password)
+ Toggled(RememberMe, remember_me) -> Model(..model, remember_me: remember_me)
+ }
+}
+
+// RENDER ----------------------------------------------------------------------
+
+fn render(model: Model) -> Element(Msg) {
+ element.div(
+ [attribute.class("container")],
+ [
+ card([
+ email_input(model.email),
+ password_input(model.password),
+ remember_checkbox(model.remember_me),
+ element.pre(
+ [attribute.class("debug")],
+ [element.text(string.inspect(model))],
+ ),
+ ]),
+ ],
+ )
+}
+
+fn card(content: List(Element(a))) -> Element(a) {
+ element.div([attribute.class("card")], [element.div([], content)])
+}
+
+fn email_input(value: String) -> Element(Msg) {
+ render_input(Email, "email", "email-input", value, "Email address")
+}
+
+fn password_input(value: String) -> Element(Msg) {
+ render_input(Password, "password", "password-input", value, "Password")
+}
+
+fn render_input(
+ field: Input,
+ type_: String,
+ id: String,
+ value: String,
+ label: String,
+) -> Element(Msg) {
+ element.div(
+ [attribute.class("input")],
+ [
+ element.label([attribute.for(id)], [element.text(label)]),
+ element.input([
+ attribute.id(id),
+ attribute.name(id),
+ attribute.type_(type_),
+ attribute.required(True),
+ attribute.value(dynamic.from(value)),
+ event.on_input(fn(value) { Typed(field, value) }),
+ ]),
+ ],
+ )
+}
+
+fn remember_checkbox(checked: Bool) -> Element(Msg) {
+ element.div(
+ [attribute.class("flex items-center")],
+ [
+ element.input([
+ attribute.id("remember-me"),
+ attribute.name("remember-me"),
+ attribute.type_("checkbox"),
+ attribute.checked(checked),
+ attribute.class("checkbox"),
+ event.on_click(Toggled(RememberMe, !checked)),
+ ]),
+ element.label(
+ [attribute.for("remember-me")],
+ [element.text("Remember me")],
+ ),
+ ],
+ )
+}
diff --git a/test/input.html b/test/input.html
new file mode 100644
index 0000000..20b60ca
--- /dev/null
+++ b/test/input.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html lang="en" class="h-full bg-gray-50">
+ <head>
+ <meta charset="UTF-8" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <title>lustre | forms</title>
+
+ <script src="https://cdn.tailwindcss.com"></script>
+ <style type="text/tailwindcss">
+ @layer components {
+ .container {
+ @apply flex min-h-full flex-col justify-center py-12 sm:px-6 lg:px-8;
+ }
+
+ .card {
+ @apply mt-10 sm:mx-auto sm:w-full sm:max-w-[480px];
+ }
+
+ .card > div {
+ @apply bg-white px-6 py-12 shadow sm:rounded-lg sm:px-12 space-y-6;
+ }
+
+ .debug {
+ @apply text-sm text-gray-400 whitespace-pre-line;
+ }
+
+ .input label {
+ @apply block text-sm font-medium leading-6 text-gray-900;
+ }
+
+ .input input {
+ @apply block w-full rounded-md border-0 p-1.5 mt-2 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-pink-600 sm:text-sm sm:leading-6;
+ }
+
+ .checkbox {
+ @apply h-4 w-4 rounded border-gray-300 text-pink-600 focus:ring-pink-600;
+ }
+
+ .checkbox + label {
+ @apply ml-3 block text-sm leading-6 text-gray-900;
+ }
+ }
+ </style>
+
+ <script type="module">
+ import { main } from "../build/dev/javascript/lustre/input.mjs";
+
+ document.addEventListener("DOMContentLoaded", main);
+ </script>
+ </head>
+ <body class="h-full"></body>
+</html>