aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authors-ol <s-ol@users.noreply.github.com>2018-05-03 21:51:07 +0000
committers-ol <s-ol@users.noreply.github.com>2018-05-03 21:53:41 +0000
commitd8e5f36cd7fc2d063f7f4bc992d2168b34f68b1c (patch)
tree323ee024080f35d1e206548757a7d72a8b658943
parentadd submodule tracking gh-pages (diff)
downloadmmm-d8e5f36cd7fc2d063f7f4bc992d2168b34f68b1c.tar.gz
mmm-d8e5f36cd7fc2d063f7f4bc992d2168b34f68b1c.zip
add component framework + todo
-rw-r--r--app/component.moon93
-rw-r--r--app/html.moon2
-rw-r--r--app/index.moon9
-rw-r--r--app/todo.moon30
m---------dist0
-rw-r--r--webpack.config.js2
6 files changed, 131 insertions, 5 deletions
diff --git a/app/component.moon b/app/component.moon
new file mode 100644
index 0000000..1f56679
--- /dev/null
+++ b/app/component.moon
@@ -0,0 +1,93 @@
+{ :document } = js.global
+
+asnode = (val) ->
+ if 'table' == type val
+ assert val.node, "Table doesn't have .node"
+ val = val.node
+ if 'string' == type val
+ val = document\createTextNode val
+ if 'userdata' == type val
+ assert (js.instanceof val, js.global.Node), "userdata is not a Node"
+ val
+ else
+ error "not a Node: #{val}, #{type val}"
+
+iscallback = (val) -> 'table' == (type val) and val.subscribe
+
+class Callback
+ new: (@value) =>
+ @listeners = setmetatable {}, __mode: 'kv'
+
+ set: (value) =>
+ old = @value
+ @value = value
+ for k, callback in pairs @listeners
+ callback @value, old
+
+ get: => @value
+
+ subscribe: (callback) =>
+ with callback
+ @listeners[callback] = callback
+
+ unsubscribe: (callback) =>
+ @listeners[callback] = nil
+
+ chain: (transform) =>
+ with Callback transform @value
+ .upstream = @subscribe (...) -> \set transform ...
+
+class CallbackElement
+ new: (element, attributes, ...) =>
+ @node = document\createElement element
+ @_callbacks = {}
+
+ children = { ... }
+
+ if 'table' != (type attributes) or attributes.__class == @@ or attributes.__class == Callback
+ table.insert children, 1, attributes
+ attributes = {}
+
+ for k,v in pairs attributes
+ @set k, v if 'string' == type k
+ for child in *children
+ @append child
+
+ set: (attr, value) =>
+ if 'table' == (type value) and value.__class == Callback
+ table.insert @_callbacks, value\subscribe (...) -> @set attr, ...
+ value = value\get!
+
+ if attr == 'style' and 'table' == type value
+ for k,v in pairs value
+ @node.style[k] = v
+ return
+
+ @node[attr] = value
+
+ append: (child, last) =>
+ if iscallback child
+ table.insert @_callbacks, child\subscribe (...) -> @append ...
+ child = child\get!
+
+ child = asnode child
+ ok, last = pcall asnode, last
+ if ok
+ @node\removeChild last
+ @node\appendChild child
+
+ remove: (child) =>
+ @node\removeChild asnode child
+
+text = (...) -> document\createTextNode table.concat { ... }, ' '
+
+with exports = {
+ :Callback,
+ :CallbackElement,
+ :text,
+ }
+ add = (e) -> exports[e] = (...) -> CallbackElement e, ...
+
+ for e in *{'div', 'form', 'span', 'a', 'p', 'button', 'ul', 'li', 'i', 'b', 'u', 'tt'} do add e
+ for e in *{'br', 'img', 'input', 'p', 'textarea'} do add e
+ for i=1,8 do add "h" .. i
diff --git a/app/html.moon b/app/html.moon
index cf4a6e6..3565f32 100644
--- a/app/html.moon
+++ b/app/html.moon
@@ -4,7 +4,7 @@ element = (element) -> (attrs = {}, ...) ->
if 'table' != type attrs
attrs = { attrs, ... }
with e = document\createElement element
- for k,v in pairs(attrs)
+ for k,v in pairs attrs
continue unless 'string' == type k
e[k] = v
for child in *attrs
diff --git a/app/index.moon b/app/index.moon
index b501d57..e43b318 100644
--- a/app/index.moon
+++ b/app/index.moon
@@ -8,12 +8,15 @@ back_button = ->
document.body\appendChild p a { '< back', href: '/' }
switch window.location.search
- when "?twisted"
+ when '?twisted'
back_button!
require './twisted.moon'
- when "?center-of-mass" then
+ when '?center-of-mass' then
back_button!
require './centerofmass.moon'
+ when '?todo' then
+ back_button!
+ require './todo.moon'
else
document.body\appendChild h1 'mmm'
document.body\appendChild p {
@@ -29,7 +32,7 @@ switch window.location.search
'.'
}
document.body\appendChild p 'current demos:'
- document.body\appendChild ul for name in *{'twisted', 'center-of-mass'}
+ document.body\appendChild ul for name in *{'twisted', 'center-of-mass', 'todo'}
li a { name, href: "/?#{name}" }
document.body\appendChild p {
diff --git a/app/todo.moon b/app/todo.moon
new file mode 100644
index 0000000..c38ce26
--- /dev/null
+++ b/app/todo.moon
@@ -0,0 +1,30 @@
+{ :document } = js.global
+import Callback, CallbackElement, text, div, form, span, h3, a, input, textarea, button from require './component.moon'
+
+parent = div!
+todoItem = (desc, done) ->
+ -- convert into reactive data sources
+ desc, done = (Callback desc), Callback done
+ with me = div style:
+ margin: '8px'
+ padding: '8px'
+ background: '#eeeeee'
+ \append h3 style: 'margin: 0;', desc
+ \append span done\chain (done) -> text if done then 'done' else 'not done yet'
+ \append input type: 'checkbox', checked: done, onchange: (e) => done\set e.target.checked
+ \append a href: '#', onclick: ((e) => parent\remove me), text 'delete'
+
+parent\append todoItem 'write a Component System'
+parent\append todoItem 'eat Lasagna', true
+
+form = with form action: '', style: 'margin 2px;'
+ desc = input type: 'text', value: 'start'
+ \append desc
+ \append input type: 'submit', value: 'add'
+ \set 'onsubmit', (e) =>
+ e\preventDefault!
+ parent\append todoItem desc.node.value
+ desc.node.value = ''
+
+document.body\appendChild parent.node
+document.body\appendChild form.node
diff --git a/dist b/dist
-Subproject 8de7ba386d87e74ffd83fec00d50ad8f6bfd301
+Subproject b1ee5409d7fcf9ee3c24afbcfcce1ef1e20eb7d
diff --git a/webpack.config.js b/webpack.config.js
index c5d22c3..1ac757b 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -17,6 +17,6 @@ module.exports = {
]
},
plugins: [
- new HtmlWebpackPlugin('MMM: lunar low-gravity scripting playground'),
+ new HtmlWebpackPlugin({ title: 'MMM: lunar low-gravity scripting playground' }),
],
}