diff options
Diffstat (limited to 'lib/mmmfs/browser.moon')
| -rw-r--r-- | lib/mmmfs/browser.moon | 153 |
1 files changed, 73 insertions, 80 deletions
diff --git a/lib/mmmfs/browser.moon b/lib/mmmfs/browser.moon index a4080c2..ce7709f 100644 --- a/lib/mmmfs/browser.moon +++ b/lib/mmmfs/browser.moon @@ -1,79 +1,70 @@ require = relative ..., 1 import Key from require '.fileder' import get_conversions from require '.conversion' -import ReactiveVar, ReactiveElement, text, elements from require 'lib.component' +import ReactiveVar, get_or_create, text, elements from require 'lib.component' import div, span, a, select, option from elements -limit = (list, num) -> [v for i,v in ipairs list when i <= num] - class Browser - new: (@root, @path={}, rehydrate=false) => - @path = ReactiveVar @path - -- @path\subscribe (path) -> window.location.hash = '/' .. table.concat path, '/' - @prop = ReactiveVar (@root\find 'mmm/dom') or next @root.props - @active = @path\map (path) -> - fileder = @root - for name in *path - local next - for child in *fileder.children - if name == child\get 'name', 'alpha' - next = child - break + new: (@root, path='/', rehydrate=false) => + -- root fileder + assert @root, 'root fileder is nil' - if not next - return + -- active path + @path = ReactiveVar path - fileder = next + if MODE == 'CLIENT' + -- update URL bar + @path\subscribe (path) -> + path ..= '/' unless path\match '/$' + window.history\pushState nil, '', path - fileder + -- active fileder + -- (re)set every time @path changes + @active = @path\map @root\walk - @active\subscribe (fileder) -> @prop\set (fileder\find 'mmm/dom') or next fileder.props + -- currently active property + -- (re)set to default every time @active changes + @prop = @active\map (fileder) -> + return unless fileder + (fileder\find 'mmm/dom') or next fileder.props -- retrieve or create the root - root = 'div' - root = document\getElementById 'browser-root' if rehydrate - @dom = ReactiveElement root, { - id: 'browser-root' - style: { - position: 'absolute', - top: 0, - bottom: 0, - left: 0, - right: 0, - display: 'flex', - overflow: 'hidden', - 'flex-direction': 'column', - 'justify-content': 'space-between', - } - } + @dom = get_or_create 'div', 'browser-root' - -- add or prepend the navbar - if MODE == 'CLIENT' - @dom\prepend div { - style: { - padding: '1em', - flex: '0 0 auto', - display: 'flex', - 'justify-content': 'space-between', - background: '#eeeeee', - }, + -- prepend the navbar + if MODE == 'SERVER' + @dom\append div id: 'browser-navbar' + else + @dom\prepend get_or_create 'div', 'browser-navbar', { span 'path: ', @path\map (path) -> with div style: { display: 'inline-block' } - \append a 'root', href: '#', onclick: (_, e) -> - e\preventDefault! - @navigate {} + path_segment = (name, href) -> + a name, :href, onclick: (_, e) -> + e\preventDefault! + @navigate href + + href = '' + path = path\match '^/(.*)' + + \append path_segment 'root', '/' + + while path + name, rest = path\match '^(%w+)/(.*)' + if not name + name = path + + path = rest + href = "#{href}/#{name}" - for i,name in ipairs path \append '/' - \append a name, href: '#', onclick: (_, e) -> - e\preventDefault! - @navigate limit path, i + \append path_segment name, href span 'view property: ', @active\map (fileder) -> onchange = (_, e) -> @prop\set Key e.target.value - current = @prop\get!\tostring! - with select :onchange + current = @prop\get! + current = current and current\tostring! + with select :onchange, disabled: not fileder if fileder for key, _ in pairs fileder.props value = key\tostring! @@ -81,49 +72,51 @@ class Browser } -- append or patch #browser-content - node = 'div' - node = document\getElementById 'browser-content' if rehydrate - @dom\append ReactiveElement node, { - id: 'browser-content', - style: { - flex: '1 0 0', - overflow: 'auto', - padding: '1em 2em', - }, - @get_content rehydrate and node - } + @dom\append with get_or_create 'div', 'browser-content' + \append @get_content!, (rehydrate and .node.lastChild) + + if rehydrate + -- force one rerender to set onclick handlers etc + @prop\set @prop\get! + -- export mmm/component interface @node = @dom.node @render = @dom\render - get_content: (wrapper) => - var = @prop\map (prop) -> + -- render #browser-content + get_content: () => + disp_error = (msg) -> span msg, style: { color: '#f00' } + @prop\map (prop) -> active = @active\get! - ok, res = pcall -> - conversions = assert (get_conversions 'mmm/dom', prop.type), "no conversion path" + return disp_error "fileder not found!" unless active + return disp_error "property not found!" unless prop + + convert = -> + conversions = get_conversions 'mmm/dom', prop.type value = assert (active\get prop), "value went missing?" + return unless conversions + for i=#conversions,1,-1 { :inp, :out, :transform } = conversions[i] value = transform value, active value - if ok and res - res + ok, res = if MODE == 'CLIENT' + pcall convert else - warn "error: ", res unless ok - span "cannot display!", style: { color: '#f00' } - - -- wrapper was built already so take over the old value - if wrapper - var\set wrapper.lastElementChild + true, convert! - var + if ok + res or disp_error "[no conversion path to mmm/dom]" + else + warn "error: ", res unless ok + disp_error "[unknown error displaying]" navigate: (new) => @path\set new { - :Browser, + :Browser } |
