diff options
author | Andy Thompson <andrew.thompson@qmul.ac.uk> | 2022-02-11 01:01:48 +0000 |
---|---|---|
committer | Andy Thompson <andrew.thompson@qmul.ac.uk> | 2022-02-11 01:01:48 +0000 |
commit | 06e3827589771da31bf033d304da4ba3a40c9cde (patch) | |
tree | 9e0d705693a3bc78099c49b37f7ba824eb52b45c | |
parent | 72f64a5192da97307156c1529838556f15e94ffa (diff) | |
download | lustre-06e3827589771da31bf033d304da4ba3a40c9cde.tar.gz lustre-06e3827589771da31bf033d304da4ba3a40c9cde.zip |
:construction: Begin experimenting with html/dom api.
-rw-r--r-- | src/index.html | 17 | ||||
-rw-r--r-- | src/js/test.js | 5 | ||||
-rw-r--r-- | src/lustre/dom/html.ffi.mjs | 14 | ||||
-rw-r--r-- | src/lustre/dom/html.gleam | 54 | ||||
-rw-r--r-- | src/lustre/dom/html/attr.ffi.mjs | 6 | ||||
-rw-r--r-- | src/lustre/dom/html/attr.gleam | 61 | ||||
-rw-r--r-- | src/lustre/dom/svg.gleam | 32 | ||||
-rw-r--r-- | src/lustre/dom/svg/attr.gleam | 92 | ||||
-rw-r--r-- | src/lustre/test.gleam | 11 |
9 files changed, 292 insertions, 0 deletions
diff --git a/src/index.html b/src/index.html new file mode 100644 index 0000000..e807f2a --- /dev/null +++ b/src/index.html @@ -0,0 +1,17 @@ +<!DOCTYPE html> +<html lang="en"> + +<head> + <meta charset="UTF-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Document</title> + + <script type="module" src="./js/test.js"></script> +</head> + +<body> + +</body> + +</html>
\ No newline at end of file diff --git a/src/js/test.js b/src/js/test.js new file mode 100644 index 0000000..ef7923a --- /dev/null +++ b/src/js/test.js @@ -0,0 +1,5 @@ +import * as Lustre from 'lustre/test.mjs' + +document.documentElement.append( + Lustre.html_test() +)
\ No newline at end of file diff --git a/src/lustre/dom/html.ffi.mjs b/src/lustre/dom/html.ffi.mjs new file mode 100644 index 0000000..2cbe58d --- /dev/null +++ b/src/lustre/dom/html.ffi.mjs @@ -0,0 +1,14 @@ +export const createNode = (tag, namespace, attrs, children) => { + const el = namespace == '' + ? document.createElement(tag) + : document.createElementNS(namespace, tag) + + for (const attr of attrs) el.setAttributeNode(attr) + for (const node of children) el.append(node) + + return el +} + +export const createText = (content) => { + return document.createTextNode(content) +}
\ No newline at end of file diff --git a/src/lustre/dom/html.gleam b/src/lustre/dom/html.gleam new file mode 100644 index 0000000..12ac25a --- /dev/null +++ b/src/lustre/dom/html.gleam @@ -0,0 +1,54 @@ +import lustre/dom/html/attr.{Attr} + +// TYPES ----------------------------------------------------------------------- + +pub external type Html + +// GENERIC CONSTRUCTORS -------------------------------------------------------- + +external fn create_node (String, String, List(Attr), List(Html)) -> Html = "./html.ffi.mjs" "createNode" + +external fn create_text (String) -> Html = + "./html.ffi.mjs" "createText" + +pub fn node (tag: String, attrs: List(Attr), children: List(Html)) -> Html { + create_node(tag, "", attrs, children) +} + +pub fn node_ns (tag: String, namespace: String, attrs: List(Attr), children: List(Html)) -> Html { + create_node(tag, namespace, attrs, children) +} + +pub fn text (content: String) -> Html { + create_text(content) +} + +// COMMON CONSTRUCTORS --------------------------------------------------------- + +pub fn div (attrs: List(Attr), children: List(Html)) -> Html { + node("div", attrs, children) +} + +pub fn p (attrs: List(Attr), children: List(Html)) -> Html { + node("p", attrs, children) +} + +pub fn span (attrs: List(Attr), children: List(Html)) -> Html { + node("span", attrs, children) +} + +pub fn button (attrs: List(Attr), children: List(Html)) -> Html { + node("button", attrs, children) +} + +// INPUT CONSTRUCTORS ---------------------------------------------------------- + +pub fn input (attrs: List(Attr)) -> Html { + node("input", attrs, []) +} + +// GRAPHICS CONSTRUCTORS ------------------------------------------------------- + +pub fn img (attrs: List(Attr)) -> Html { + node("img", attrs, []) +}
\ No newline at end of file diff --git a/src/lustre/dom/html/attr.ffi.mjs b/src/lustre/dom/html/attr.ffi.mjs new file mode 100644 index 0000000..b75c37a --- /dev/null +++ b/src/lustre/dom/html/attr.ffi.mjs @@ -0,0 +1,6 @@ +export const createAttr = (name, value) => { + const attr = document.createAttribute(name) + attr.value = value + + return attr +}
\ No newline at end of file diff --git a/src/lustre/dom/html/attr.gleam b/src/lustre/dom/html/attr.gleam new file mode 100644 index 0000000..ac86cdf --- /dev/null +++ b/src/lustre/dom/html/attr.gleam @@ -0,0 +1,61 @@ +import gleam/float +import gleam/int + +// TYPES ----------------------------------------------------------------------- + +pub external type Attr + +// GENERIC CONSTRUCTORS -------------------------------------------------------- + +external fn create_attr (String, String) -> Attr = + "./attr.ffi.mjs" "createAttr" + +pub fn from_string (name: String, val: String) -> Attr { + create_attr(name, val) +} + +pub fn from_float (name: String, val: Float) -> Attr { + create_attr(name, float.to_string(val)) +} + +pub fn from_int (name: String, val: Int) -> Attr { + create_attr(name, int.to_string(val)) +} + +pub fn from_bool (name: String, val: Bool) -> Attr { + create_attr(name, case val { + True -> + "true" + + False -> + "false" + }) +} + +// COMMON ATTRIBUTES ----------------------------------------------------------- + +pub fn style (styles: String) -> Attr { + from_string("style", styles) +} + +pub fn class (class: String) -> Attr { + from_string("class", class) +} + +pub fn id (id: String) -> Attr { + from_string("id", id) +} + +// INPUT ATTRIBUTES ------------------------------------------------------------ + +pub fn type_ (type_: String) -> Attr { + from_string("type", type_) +} + +pub fn value (value: String) -> Attr { + from_string("value", value) +} + +pub fn checked (checked: Bool) -> Attr { + from_bool("checked", checked) +} diff --git a/src/lustre/dom/svg.gleam b/src/lustre/dom/svg.gleam new file mode 100644 index 0000000..e356e42 --- /dev/null +++ b/src/lustre/dom/svg.gleam @@ -0,0 +1,32 @@ +import lustre/dom/html.{Html} +import lustre/dom/html/attr.{Attr} + +// CONSTANTS ------------------------------------------------------------------- + +const svg_namespace = "http://www.w3.org/2000/svg" + +// COMMON CONSTRUCTORS --------------------------------------------------------- + +pub fn svg (attrs: List(Attr), children: List(Html)) -> Html { + html.node_ns("svg", svg_namespace, attrs, children) +} + +pub fn rect (attrs: List(Attr), children: List(Html)) -> Html { + html.node_ns("rect", svg_namespace, attrs, children) +} + +pub fn circle (attrs: List(Attr), children: List(Html)) -> Html { + html.node_ns("circle", svg_namespace, attrs, children) +} + +pub fn ellipse (attrs: List(Attr), children: List(Html)) -> Html { + html.node_ns("ellipse", svg_namespace, attrs, children) +} + +pub fn line (attrs: List(Attr), children: List(Html)) -> Html { + html.node_ns("line", svg_namespace, attrs, children) +} + +pub fn text (attrs: List(Attr), children: List(Html)) -> Html { + html.node_ns("text", svg_namespace, attrs, children) +} diff --git a/src/lustre/dom/svg/attr.gleam b/src/lustre/dom/svg/attr.gleam new file mode 100644 index 0000000..c2ce5cc --- /dev/null +++ b/src/lustre/dom/svg/attr.gleam @@ -0,0 +1,92 @@ +import gleam/float +import gleam/list +import gleam/string +import lustre/dom/html/attr + +// TYPES ----------------------------------------------------------------------- + +pub type Attr = attr.Attr + +// COMMON CONSTRUCTORS --------------------------------------------------------- + +pub fn x (x: Float) -> Attr { + attr.from_float("x", x) +} + +pub fn x1 (x1: Float) -> Attr { + attr.from_float("x1", x1) +} + +pub fn x2 (x2: Float) -> Attr { + attr.from_float("x2", x2) +} + +pub fn y (y: Float) -> Attr { + attr.from_float("y", y) +} + +pub fn y1 (y1: Float) -> Attr { + attr.from_float("y1", y1) +} + +pub fn y2 (y2: Float) -> Attr { + attr.from_float("y2", y2) +} + +pub fn width (width: Float) -> Attr { + attr.from_float("width", width) +} + +pub fn height (height: Float) -> Attr { + attr.from_float("height", height) +} + +pub fn viewbox (min_x: Float, min_y: Float, width: Float, height: Float) -> Attr { + attr.from_string("viewbox", [ min_x, min_y, width, height ] |> list.map(float.to_string) |> string.join(" ")) +} + +// STYLING CONSTRUCTORS -------------------------------------------------------- + +pub fn rgb (r: Float, g: Float, b: Float) -> String { + rgba(r, g, b, 1.0) +} + +pub fn rgba (r: Float, g: Float, b: Float, a: Float) -> String { + let r = clamp(r, between: 0.0, and: 255.0) |> float.to_string + let g = clamp(g, between: 0.0, and: 255.0) |> float.to_string + let b = clamp(b, between: 0.0, and: 255.0) |> float.to_string + let a = clamp(a, between: 0.0, and: 1.0) |> float.to_string + + string.concat([ "rgba(", r, ",", g, ",", b, ",", a, ")" ]) +} + +pub fn fill (color: String) -> Attr { + attr.from_string("fill", color) +} + +pub fn stroke (color: String) -> Attr { + attr.from_string("stroke", color) +} + +pub fn stroke_width (width: Float) -> Attr { + attr.from_float("stroke-width", width) +} + +pub fn opacity (opacity: Float) -> Attr { + attr.from_float("opacity", clamp(opacity, between: 0.0, and: 1.0)) +} + +// UTILS ----------------------------------------------------------------------- + +fn clamp (val: Float, between min: Float, and max: Float) -> Float { + case val { + _ if val <. min -> + min + + _else if val >. max -> + max + + _else -> + val + } +}
\ No newline at end of file diff --git a/src/lustre/test.gleam b/src/lustre/test.gleam new file mode 100644 index 0000000..f8f913b --- /dev/null +++ b/src/lustre/test.gleam @@ -0,0 +1,11 @@ +import lustre/dom/html +import lustre/dom/html/attr + +pub fn html_test () { + html.div([ attr.class("foo") ], [ + html.p([], [ + html.text("testing") + ]), + html.input([ attr.value("hello") ]) + ]) +} |