mirror of
https://github.com/urbit/shrub.git
synced 2024-08-17 08:00:39 +03:00
move sky's ++lift into sky-htmx & optimistically render sky-diffs
This commit is contained in:
parent
5a63847b37
commit
ca8a21a33c
23
pkg/arvo/neo/cod/std/src/con/http-request-sky-diff.hoon
Normal file
23
pkg/arvo/neo/cod/std/src/con/http-request-sky-diff.hoon
Normal file
@ -0,0 +1,23 @@
|
||||
/@ sky-diff
|
||||
/@ http-request
|
||||
/- serv=sky-server
|
||||
:- [%http-request %$ %sky-diff]
|
||||
|= =http-request
|
||||
=/ pam (~(uni by pam:(parse-url:serv http-request)) (parse-form-body:serv http-request))
|
||||
=/ bod ~(. by pam)
|
||||
=/ head (@tas (got:bod 'head'))
|
||||
^- sky-diff
|
||||
?+ head ~|(bad-head/head !!)
|
||||
%new-hawk
|
||||
[head (slav %da (got:bod 'now'))]
|
||||
%close
|
||||
[head (slav %ud (got:bod 'slot'))]
|
||||
%maximize
|
||||
[head (slav %ud (got:bod 'slot'))]
|
||||
%slide-up
|
||||
[head (slav %ud (got:bod 'slot'))]
|
||||
%slide-down
|
||||
[head (slav %ud (got:bod 'slot'))]
|
||||
%minimize
|
||||
[head (slav %ud (got:bod 'slot'))]
|
||||
==
|
@ -10,17 +10,5 @@
|
||||
%menu
|
||||
=/ c ?~((get:mu %closed) %.y %.n)
|
||||
[%menu c]
|
||||
%new-tab
|
||||
[%new-tab ~]
|
||||
%minimize
|
||||
[%minimize (slav %ud (got:mu %hawk-slot))]
|
||||
%slide-up
|
||||
[%slide-up (slav %ud (got:mu %hawk-slot))]
|
||||
%slide-down
|
||||
[%slide-down (slav %ud (got:mu %hawk-slot))]
|
||||
%maximize
|
||||
[%maximize (slav %ud (got:mu %hawk-slot))]
|
||||
%close
|
||||
[%close (slav %ud (got:mu %hawk-slot))]
|
||||
::
|
||||
==
|
||||
|
@ -1,31 +1,65 @@
|
||||
/@ sky
|
||||
/@ sky-settings
|
||||
/- feather-icons
|
||||
/* date-now
|
||||
/* a-i-r
|
||||
/* feather
|
||||
/* reset
|
||||
/* hawk-icon
|
||||
/* jquery
|
||||
/* htmx-js
|
||||
/* htmx-response-targets
|
||||
/* htmx-idiomorph
|
||||
:- [%sky %$ %htmx]
|
||||
|= =sky
|
||||
|= =bowl:neo
|
||||
^- manx
|
||||
|^
|
||||
;div.wf.hf.relative
|
||||
;+
|
||||
=; m
|
||||
?: menu.sky m
|
||||
m(a.g [[%closed ""] a.g.m])
|
||||
^- manx
|
||||
;a-i-r.wf.hf.relative
|
||||
=style "opacity: var(--sky-opacity); padding: var(--sky-outer-gap);"
|
||||
=id "air"
|
||||
=hawks "{<open.sky>}"
|
||||
=morph-retain "closed"
|
||||
;+ menu-btn
|
||||
;+ menu-btn-style
|
||||
;+ theme-style
|
||||
;+ nav
|
||||
;* p:(spin (scag open.sky hawks.sky) 0 ha-wk)
|
||||
==
|
||||
;+ eye
|
||||
=; m
|
||||
%- lift
|
||||
?: menu.sky m
|
||||
m(a.g [[%closed ""] a.g.m])
|
||||
^- manx
|
||||
;a-i-r.wf.hf.relative
|
||||
=style "opacity: var(--sky-opacity); padding: var(--sky-outer-gap);"
|
||||
=id "air"
|
||||
=hawks "{<open.sky>}"
|
||||
=morph-retain "closed"
|
||||
=hx-on-hawks-moved hawks-moved-js
|
||||
=hx-on-htmx-after-request
|
||||
"""
|
||||
let verb = event.detail.requestConfig.verb;
|
||||
let url = new URL(event.detail.xhr.responseURL);
|
||||
let pams = new URLSearchParams(url.search);
|
||||
if (verb === 'get' &&
|
||||
url.pathname.startsWith('/neo/hawk/~') &&
|
||||
!pams.has('no-save')
|
||||
) \{
|
||||
$('.nav-refresher').emit('refresh');
|
||||
}
|
||||
"""
|
||||
;* p:(spin (scag open.sky hawks.sky) 0 ha-wk)
|
||||
;+ menu-btn
|
||||
;+ nav
|
||||
==
|
||||
::
|
||||
++ hawks-moved-js
|
||||
:: js to run whenever the order or number of hawks changed.
|
||||
:: it will:
|
||||
:: - trigger a refresh of the nav
|
||||
:: - loop through any slotted hawks and reslot them starting from 0
|
||||
%- trip
|
||||
'''
|
||||
let air = $(this);
|
||||
let num = parseInt(air.attr('hawks'));
|
||||
let hawks = air.children('[slot]').filter('.hawk').get();
|
||||
hawks.sort((a, b) => {
|
||||
return (a.getAttribute('slot') < b.getAttribute('slot')) ? -1 : 1;
|
||||
}).forEach((h, i) => {
|
||||
h.setAttribute('slot', `s${i}`);
|
||||
});
|
||||
air.find('.nav-refresher').emit('refresh');
|
||||
'''
|
||||
++ map-to-css-tape
|
||||
|= m=(map @t @t)
|
||||
^- tape
|
||||
@ -102,26 +136,30 @@
|
||||
?: =(pith /) ""
|
||||
(en-tape:pith:neo pith)
|
||||
=/ idt `tape`(zing (scan +:(scow %da id) (most dot (star ;~(less dot prn)))))
|
||||
;div.wf.hf.br1
|
||||
;div.wf.hf.fc.jc.ac.f2.s3.spinner
|
||||
=slot "s{<a>}"
|
||||
=id "hawk-windshield-{idt}"
|
||||
;div.wf.hf.fc.jc.ac.f2.s3.spinner
|
||||
=id "hawk-{idt}"
|
||||
=morph-if-class "spinner"
|
||||
;+ loading.feather-icons
|
||||
==
|
||||
;div.hidden
|
||||
=hx-get "/neo/hawk{ext}?slot={<a>}&hawk-id={<id>}&no-save"
|
||||
=hx-trigger "load"
|
||||
=hx-target "#hawk-{idt}"
|
||||
=hx-swap "morph"
|
||||
;
|
||||
==
|
||||
=id "hawk-{idt}"
|
||||
=hx-get "/neo/hawk{ext}?slot={<a>}&hawk-id={<id>}&no-save"
|
||||
=morph-retain "slot"
|
||||
=hx-trigger "load"
|
||||
=hx-target "this"
|
||||
=hx-swap "morph"
|
||||
;+ loading.feather-icons
|
||||
==
|
||||
++ nav
|
||||
;nav.wf.hf.p2.fc.g2
|
||||
;nav.wf.hf.p2.fc.g2.sky-nav
|
||||
=slot "nav"
|
||||
;div.mt2.o0;
|
||||
;div.nav-refresher.loader.p3
|
||||
=hx-get "/neo/sky"
|
||||
=hx-swap "outerHTML"
|
||||
=hx-target "closest nav"
|
||||
=hx-select "nav.sky-nav"
|
||||
=hx-trigger "refresh"
|
||||
;span.loaded;
|
||||
;span.loading
|
||||
;+ loading.feather-icons
|
||||
==
|
||||
==
|
||||
;+ new-tab
|
||||
;*
|
||||
=< p
|
||||
@ -132,16 +170,46 @@
|
||||
:_ +(a)
|
||||
=/ idt `tape`(zing (scan +:(scow %da id) (most dot (star ;~(less dot prn)))))
|
||||
=/ color (trip ?:((lth a open.sky) 'b2' 'b1'))
|
||||
=/ close-hawk-js
|
||||
%- trip
|
||||
'''
|
||||
let toClose = parseInt(this.getAttribute('close'));
|
||||
let air = $('a-i-r');
|
||||
let num = parseInt(air.attr('hawks'));
|
||||
let hawks = air.children('[slot]').filter('.hawk');
|
||||
if (toClose < num) {
|
||||
air.attr('hawks', hawks.length-1);
|
||||
}
|
||||
hawks.each(function() {
|
||||
let slot = parseInt($(this).attr('slot').slice(1));
|
||||
if (slot == toClose) {
|
||||
$(this).remove();
|
||||
}
|
||||
});
|
||||
$(this).emit('hawks-moved');
|
||||
'''
|
||||
:: =/ maximize-hawk-js
|
||||
:: %- trip
|
||||
:: '''
|
||||
:: let air = $('a-i-r');
|
||||
:: let num = parseInt(air.attr('hawks'));
|
||||
:: air.attr('hawks', num+1);
|
||||
:: let toMax = '#hawk-' + this.getAttribute('hawk');
|
||||
:: $(toMax).attr('slot', 's-1');
|
||||
:: $(this).emit('hawks-moved');
|
||||
:: '''
|
||||
;div
|
||||
=id "hawk-tab-{idt}"
|
||||
=hx-ext "ignore:html-enc"
|
||||
=class "fr ac br1 {color}"
|
||||
;button
|
||||
=class "loader p2 tl br1 hover grow {color}"
|
||||
=hx-post "/neo/hawk/{<our.bowl>}/sky?stud=sky-diff"
|
||||
=hx-post "/neo/hawk/{<our.bowl>}/sky?stud=sky-diff&head=maximize&slot={<a>}"
|
||||
:: XX optimistically render
|
||||
::=hx-on-htmx-after-request maximize-hawk-js
|
||||
=hawk idt
|
||||
=hx-target "find .loading"
|
||||
=hx-swap "outerHTML"
|
||||
=head "maximize"
|
||||
=hawk-slot "{<a>}"
|
||||
;span.loaded: {(en-tape:pith:neo pith)}
|
||||
;span.loading
|
||||
;+ loading.feather-icons
|
||||
@ -149,11 +217,10 @@
|
||||
==
|
||||
;button
|
||||
=class "loader p2 tl br1 hover {color}"
|
||||
=hx-post "/neo/hawk/{<our.bowl>}/sky?stud=sky-diff"
|
||||
=hx-target "find .loading"
|
||||
=hx-swap "outerHTML"
|
||||
=head "close"
|
||||
=hawk-slot "{<a>}"
|
||||
=close "{<a>}"
|
||||
=hx-post "/neo/hawk/{<our.bowl>}/sky?stud=sky-diff&head=close&slot={<a>}"
|
||||
=hx-swap "none"
|
||||
=hx-on-htmx-after-request close-hawk-js
|
||||
;span.loaded.f3
|
||||
;+ close.feather-icons
|
||||
==
|
||||
@ -164,12 +231,15 @@
|
||||
==
|
||||
==
|
||||
++ new-tab
|
||||
:: XX optimistically render
|
||||
;button.loader.b2.p2.tc.br1.hover.wfc.s-1
|
||||
=hx-post "/neo/hawk/{<our.bowl>}/sky?stud=sky-diff"
|
||||
=hx-ext "ignore:html-enc"
|
||||
=hx-post "/neo/hawk/{<our.bowl>}/sky?stud=sky-diff&head=new-hawk"
|
||||
=hx-target "find .loading"
|
||||
=hx-swap "outerHTML"
|
||||
=hx-on-htmx-after-request "$(this).emit('hawks-moved')"
|
||||
=type "button"
|
||||
=head "new-tab"
|
||||
=hx-vals (trip 'js:{now: urbitTimestamp()}')
|
||||
;span.loaded.fr.ac.js.g2
|
||||
;+ add.feather-icons
|
||||
;span.f3: new window
|
||||
@ -269,4 +339,194 @@
|
||||
'''
|
||||
==
|
||||
==
|
||||
++ icon-url
|
||||
^~
|
||||
%- trip
|
||||
%^ cat
|
||||
3
|
||||
'data:image/png;base64,'
|
||||
%- ~(en base64:mimes:html & |)
|
||||
(as-octs:mimes:html hawk-icon)
|
||||
++ favicon
|
||||
^~
|
||||
=; m m(a.g [[%href icon-url] a.g.m])
|
||||
^- manx
|
||||
;link
|
||||
=rel "icon"
|
||||
=type "image/png"
|
||||
;
|
||||
==
|
||||
++ manifest-url
|
||||
^~
|
||||
%- trip
|
||||
%^ cat
|
||||
3
|
||||
'data:application/json;utf-8,'
|
||||
%- en:json:html
|
||||
%- pairs:enjs:format
|
||||
:~
|
||||
['name' s+'sky']
|
||||
['description' s+'an urbit namespace viewer']
|
||||
['start_url' s+'http://localhost/neo/sky'] :: XX
|
||||
['display' s+'standalone']
|
||||
['background_color' s+'black']
|
||||
:+ 'icons' %a
|
||||
:~
|
||||
%- pairs:enjs:format
|
||||
:~
|
||||
['src' s+(crip icon-url)]
|
||||
['sizes' s+'196x196']
|
||||
['type' s+'image/png']
|
||||
==
|
||||
==
|
||||
==
|
||||
++ manifest
|
||||
^~
|
||||
=; m m(a.g [[%href manifest-url] a.g.m])
|
||||
^- manx
|
||||
;link
|
||||
=rel "manifest"
|
||||
;
|
||||
==
|
||||
++ htmx-extensions
|
||||
:: htmx extension which encodes the request
|
||||
:: as the serialized HTML of the calling element
|
||||
::
|
||||
:: XX usage of this should be optional.
|
||||
:: requests should default to form-encoded.
|
||||
%- trip
|
||||
'''
|
||||
htmx.defineExtension('html-enc', {
|
||||
onEvent: function (name, evt) {
|
||||
if (name === "htmx:configRequest") {
|
||||
evt.detail.headers['Content-Type'] = "text/html";
|
||||
}
|
||||
},
|
||||
encodeParameters : function(xhr, parameters, elt) {
|
||||
xhr.overrideMimeType('text/html');
|
||||
let xmls = new XMLSerializer();
|
||||
return (xmls.serializeToString(elt));
|
||||
}
|
||||
});
|
||||
Idiomorph.defaults.ignoreActive = true;
|
||||
Idiomorph.defaults.callbacks.beforeAttributeUpdated = (name, node, type) => {
|
||||
if (node.hasAttribute('morph-retain')) {
|
||||
let ribs = node.getAttribute('morph-retain').split(',').map(t => t.trim());
|
||||
if (ribs.includes(name)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Idiomorph.defaults.callbacks.beforeNodeMorphed = (oldNode, newNode) => {
|
||||
if (oldNode?.nodeName !== "#text") {
|
||||
if (oldNode.hasAttribute('morph-no-swap') && oldNode.id === newNode.id) {
|
||||
return false;
|
||||
}
|
||||
else if (
|
||||
newNode.hasAttribute('morph-if-class') &&
|
||||
!oldNode.classList.contains(newNode.getAttribute('morph-if-class'))
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
'''
|
||||
::
|
||||
++ lift
|
||||
|= in=manx
|
||||
^- manx
|
||||
;html
|
||||
;head
|
||||
;meta(charset "UTF-8");
|
||||
;title: s k y
|
||||
;script: {(trip jquery)}
|
||||
;script: {(trip htmx-js)}
|
||||
;script: {(trip htmx-response-targets)}
|
||||
;script: {(trip htmx-idiomorph)}
|
||||
;script: {htmx-extensions}
|
||||
;meta
|
||||
=name "viewport"
|
||||
=content
|
||||
"""
|
||||
width=device-width,
|
||||
initial-scale=1.0,
|
||||
maximum-scale=1.0
|
||||
"""
|
||||
;
|
||||
==
|
||||
;meta
|
||||
=name "htmx-config"
|
||||
=content (trip '{"ignoreTitle":"true"}')
|
||||
;
|
||||
==
|
||||
::;style
|
||||
:: ;+ ;/ %- trip
|
||||
:: '''
|
||||
:: @font-face {
|
||||
:: font-family: 'Urbit Sans';
|
||||
:: src: url("https://media.urbit.org/fonts/UrbitSans/UrbitSansVFWeb-Regular.woff2") format("woff2");
|
||||
:: font-style: normal;
|
||||
:: font-weight: 100 700;
|
||||
:: }
|
||||
:: '''
|
||||
::==
|
||||
;style: {(trip reset)}
|
||||
;style: {(trip feather)}
|
||||
;script
|
||||
;+ ;/ %- trip
|
||||
'''
|
||||
window.log = function() {
|
||||
if (this.console) {
|
||||
console.log(Array.prototype.slice.call(arguments));
|
||||
}
|
||||
};
|
||||
jQuery.fn.log = function (msg) {
|
||||
console.log(msg, this);
|
||||
return this;
|
||||
};
|
||||
jQuery.fn.emit = function (name) {
|
||||
(this[0]).dispatchEvent(
|
||||
new Event(
|
||||
name,
|
||||
{ bubbles: true, cancelable: true, composed: true }
|
||||
)
|
||||
);
|
||||
return this;
|
||||
};
|
||||
function urbitTimestamp() {
|
||||
let now = new Date();
|
||||
let year = now.getFullYear();
|
||||
let month = now.getMonth() + 1;
|
||||
let date = now.getDate();
|
||||
let hour = String(now.getHours()).padStart(2, '0');
|
||||
let min = String(now.getMinutes()).padStart(2, '0');
|
||||
let sec = String(now.getSeconds()).padStart(2, '0');
|
||||
return `~${year}.${month}.${date}..${hour}.${min}.${sec}`;
|
||||
}
|
||||
'''
|
||||
==
|
||||
;script: {(trip a-i-r)}
|
||||
;script: {(trip date-now)}
|
||||
;+ favicon
|
||||
;+ manifest
|
||||
==
|
||||
;body
|
||||
=hx-ext "html-enc,response-targets,morph"
|
||||
=hx-swap "outerHTML"
|
||||
=hx-boost "true"
|
||||
=hx-history "false"
|
||||
=hx-replace-url "/neo/sky"
|
||||
=style
|
||||
"""
|
||||
background-color: var(--b1);
|
||||
background-image: var(--sky-bg-url);
|
||||
background-size: var(--sky-bg-size);
|
||||
background-repeat: var(--sky-bg-repeat);
|
||||
"""
|
||||
;+ in
|
||||
;+ eye
|
||||
;+ menu-btn-style
|
||||
;+ theme-style
|
||||
==
|
||||
==
|
||||
--
|
||||
|
@ -3,6 +3,7 @@
|
||||
/- serv=sky-server
|
||||
/> htmx
|
||||
/< node
|
||||
/< http-request
|
||||
=<
|
||||
^- kook:neo
|
||||
|%
|
||||
@ -38,7 +39,7 @@
|
||||
:_ [stud vase]
|
||||
=/ purl (parse-url:serv request.req)
|
||||
=/ id=@da (slav %da (~(gut by pam.purl) 'hawk-id' '~2000.1.1'))
|
||||
=/ slot=@ud (slav %ud (~(gut by pam.purl) 'slot' '99'))
|
||||
=/ slot=@ud (slav %ud (~(gut by pam.purl) 'slot' '999'))
|
||||
=/ meta [id slot]
|
||||
?~ src=(~(get by deps.bowl) %src)
|
||||
=/ stub
|
||||
@ -115,12 +116,21 @@
|
||||
::
|
||||
%'POST'
|
||||
=/ purl (parse-url:serv request.req)
|
||||
=/ content-type (~(gut by pam.purl) 'content-type' 'text/html')
|
||||
~& content-type
|
||||
=/ body (parse-body:serv request.req)
|
||||
=/ poke-stud
|
||||
^- stud:neo
|
||||
~| %no-stud-specified
|
||||
(~(got by pam.purl) 'stud')
|
||||
=/ mul (mule |.((node [poke-stud body])))
|
||||
=/ mul
|
||||
%- mule
|
||||
|.
|
||||
?: =(content-type 'application/x-www-form-urlencoded')
|
||||
~& poke-stud
|
||||
=/ fine (http-request [poke-stud `request:http`request.req])
|
||||
fine
|
||||
(node [poke-stud body])
|
||||
?- -.mul
|
||||
%.n
|
||||
%: eyre-cards
|
||||
@ -277,12 +287,27 @@
|
||||
?@(f (trip f) (scow f))
|
||||
++ id -.meta
|
||||
++ slot +.meta
|
||||
++ slot-tag
|
||||
:: XX oh boy this is hacky.
|
||||
:: working with slots in ssr is tough
|
||||
?: =(slot 999) "s-1"
|
||||
"s{<slot>}"
|
||||
++ idt `tape`(zing (scan +:(scow %da id) (most dot (star ;~(less dot prn)))))
|
||||
++ vals
|
||||
%^ cat 3 'js:{'
|
||||
%^ cat 3 '"hawk-id": $(event?.target)?.closest("[slot]").attr("hawk-id") || "~2001.1.1"'
|
||||
%^ cat 3 ', '
|
||||
%^ cat 3 'slot: $(event?.target)?.closest("[slot]").attr("slot")?.slice(1) || "0"'
|
||||
'}'
|
||||
++ lift
|
||||
^- manx
|
||||
;div.hawk.fc.wf.hf
|
||||
=id "hawk-{idt}"
|
||||
=hawk-id (scow %da id)
|
||||
=slot slot-tag
|
||||
=hx-params "hawk-id,slot"
|
||||
=hx-vals "\{\"hawk-id\": \"{<id>}\", \"slot\": \"{<slot>}\"}"
|
||||
=hx-vals (trip vals)
|
||||
=hx-target "closest .hawk"
|
||||
=hx-target-x "closest .rendered"
|
||||
=hx-target-404 "this"
|
||||
;+ header
|
||||
@ -368,12 +393,24 @@
|
||||
==
|
||||
;div.fr.ac.jc.g1.hawk-actions
|
||||
=id "hawk-actions-{idt}"
|
||||
=hx-ext "ignore:html-enc"
|
||||
;button.p1.hover.b2.br1.loader.s-1
|
||||
=hx-post "/neo/hawk/{our-tape}/sky?stud=sky-diff"
|
||||
=hx-target "find .loading"
|
||||
=hx-swap "outerHTML"
|
||||
=head "slide-up"
|
||||
=hawk-slot "{<slot>}"
|
||||
=hx-post "/neo/hawk/{our-tape}/sky?stud=sky-diff&head=slide-up"
|
||||
=hx-on-htmx-after-request
|
||||
"""
|
||||
let swaper = $(this).closest('[slot]');
|
||||
let slot = parseInt(swaper.attr('slot').slice(1));
|
||||
let swapee = $(this).closest('a-i-r').find(`[slot='s$\{slot-1}']`);
|
||||
if (swaper.length && swapee.length) \{
|
||||
let ee = swapee.attr('slot');
|
||||
let er = swaper.attr('slot');
|
||||
swapee.attr('slot', er);
|
||||
swaper.attr('slot', ee);
|
||||
}
|
||||
$(this).emit('hawks-moved');
|
||||
"""
|
||||
=type "button"
|
||||
=hx-swap "none"
|
||||
;span.loaded
|
||||
;+ chevron-left:feather-icons
|
||||
==
|
||||
@ -382,11 +419,22 @@
|
||||
==
|
||||
==
|
||||
;button.p1.hover.b2.br1.loader.s-1
|
||||
=hx-post "/neo/hawk/{our-tape}/sky?stud=sky-diff"
|
||||
=hx-target "find .loading"
|
||||
=hx-swap "outerHTML"
|
||||
=head "slide-down"
|
||||
=hawk-slot "{<slot>}"
|
||||
=hx-post "/neo/hawk/{our-tape}/sky?stud=sky-diff&head=slide-down"
|
||||
=hx-on-htmx-after-request
|
||||
"""
|
||||
let swaper = $(this).closest('[slot]');
|
||||
let slot = parseInt(swaper.attr('slot').slice(1));
|
||||
let swapee = $(this).closest('a-i-r').find(`[slot='s$\{slot+1}']`);
|
||||
if (swaper.length && swapee.length) \{
|
||||
let ee = swapee.attr('slot');
|
||||
let er = swaper.attr('slot');
|
||||
swapee.attr('slot', er);
|
||||
swaper.attr('slot', ee);
|
||||
}
|
||||
$(this).emit('hawks-moved');
|
||||
"""
|
||||
=hx-swap "none"
|
||||
=type "button"
|
||||
;span.loaded
|
||||
;+ chevron-right:feather-icons
|
||||
==
|
||||
@ -395,11 +443,17 @@
|
||||
==
|
||||
==
|
||||
;button.p1.hover.b2.br1.loader.s-1
|
||||
=hx-post "/neo/hawk/{our-tape}/sky?stud=sky-diff"
|
||||
=hx-target "find .loading"
|
||||
=hx-swap "outerHTML"
|
||||
=head "minimize"
|
||||
=hawk-slot "{<slot>}"
|
||||
=hx-post "/neo/hawk/{our-tape}/sky?stud=sky-diff&head=minimize"
|
||||
=hx-swap "none"
|
||||
=type "button"
|
||||
=hx-on-htmx-after-request
|
||||
"""
|
||||
let air = $(this).closest('a-i-r');
|
||||
let now = parseInt(air.attr('hawks')) - 1;
|
||||
air.attr('hawks', now);
|
||||
$(this).closest('[slot]')[0].removeAttribute('slot');
|
||||
$(this).emit('hawks-moved');
|
||||
"""
|
||||
;span.loaded
|
||||
;+ minimize:feather-icons
|
||||
==
|
||||
|
@ -1,253 +1,62 @@
|
||||
/@ htmx
|
||||
/- feather-icons
|
||||
/* date-now
|
||||
/* a-i-r
|
||||
/* feather
|
||||
/* reset
|
||||
/* hawk-icon
|
||||
/* jquery
|
||||
/* htmx-js
|
||||
/* htmx-response-targets
|
||||
/* htmx-idiomorph
|
||||
=<
|
||||
^- kook:neo
|
||||
|%
|
||||
++ state pro/%eyre-task
|
||||
++ poke *(set stud:neo)
|
||||
++ kids
|
||||
:+ ~ %y
|
||||
%- ~(gas by *lads:neo)
|
||||
~
|
||||
++ deps
|
||||
%- ~(gas by *band:neo)
|
||||
:~ :- %src
|
||||
^- fief:neo
|
||||
:- req=|
|
||||
^- quay:neo
|
||||
:- [pro/%htmx ~]
|
||||
^- (unit port:neo)
|
||||
:+ ~ %y
|
||||
%- ~(gas by *lads:neo)
|
||||
:~ :- &
|
||||
`lash:neo`[any/~ ~]
|
||||
==
|
||||
==
|
||||
::
|
||||
++ form
|
||||
|_ [=bowl:neo =aeon:neo =pail:neo]
|
||||
++ poke
|
||||
|= [=stud:neo vax=vase]
|
||||
^- (quip card:neo pail:neo)
|
||||
`pail
|
||||
++ init
|
||||
|= pal=(unit pail:neo)
|
||||
=/ [=stud:neo =vase] (need pal)
|
||||
=+ !<([eyre-id=@ta req=inbound-request:eyre] vase)
|
||||
:_ [stud vase]
|
||||
=/ =pith:neo #/[p/our.bowl]/$/eyre
|
||||
=; =manx
|
||||
=/ head=sign:eyre:neo [eyre-id %head [200 [['content-type' 'text/html'] ~]]]
|
||||
=/ data=sign:eyre:neo [eyre-id %data `(manx-to-octs manx)]
|
||||
=/ done=sign:eyre:neo [eyre-id %done ~]
|
||||
:~ [pith %poke eyre-sign/!>(head)]
|
||||
[pith %poke eyre-sign/!>(data)]
|
||||
[pith %poke eyre-sign/!>(done)]
|
||||
[here.bowl %cull ~]
|
||||
==
|
||||
?~ src=(~(get by deps.bowl) %src)
|
||||
;div: 404
|
||||
=/ root=idea:neo (~(got of:neo q.u.src) /)
|
||||
?> =(%htmx p.pail.root)
|
||||
=/ bol *bowl:neo
|
||||
=. here.bol p.u.src
|
||||
=. our.bol our.bowl
|
||||
=. now.bol now.bowl
|
||||
=. eny.bol eny.bowl
|
||||
=. kids.bol q.u.src
|
||||
:: XX src.bowl
|
||||
(lift (!<(htmx q.pail.root) bol))
|
||||
--
|
||||
--
|
||||
^- kook:neo
|
||||
|%
|
||||
++ manx-to-octs
|
||||
|= man=manx
|
||||
%- as-octt:mimes:html
|
||||
%+ welp "<!DOCTYPE html>"
|
||||
(en-xml:html man)
|
||||
++ state pro/%eyre-task
|
||||
++ poke *(set stud:neo)
|
||||
++ kids
|
||||
:+ ~ %y
|
||||
%- ~(gas by *lads:neo)
|
||||
~
|
||||
++ deps
|
||||
%- ~(gas by *band:neo)
|
||||
:~ :- %src
|
||||
^- fief:neo
|
||||
:- req=|
|
||||
^- quay:neo
|
||||
:- [pro/%htmx ~]
|
||||
^- (unit port:neo)
|
||||
:+ ~ %y
|
||||
%- ~(gas by *lads:neo)
|
||||
:~ :- &
|
||||
`lash:neo`[any/~ ~]
|
||||
==
|
||||
==
|
||||
::
|
||||
++ icon-url
|
||||
^~
|
||||
%- trip
|
||||
%^ cat
|
||||
3
|
||||
'data:image/png;base64,'
|
||||
%- ~(en base64:mimes:html & |)
|
||||
(as-octs:mimes:html hawk-icon)
|
||||
++ favicon
|
||||
^~
|
||||
=; m m(a.g [[%href icon-url] a.g.m])
|
||||
^- manx
|
||||
;link
|
||||
=rel "icon"
|
||||
=type "image/png"
|
||||
;
|
||||
==
|
||||
++ manifest-url
|
||||
^~
|
||||
%- trip
|
||||
%^ cat
|
||||
3
|
||||
'data:application/json;utf-8,'
|
||||
%- en:json:html
|
||||
%- pairs:enjs:format
|
||||
:~
|
||||
['name' s+'sky']
|
||||
['description' s+'an urbit namespace viewer']
|
||||
['start_url' s+'http://localhost/neo/sky'] :: XX
|
||||
['display' s+'standalone']
|
||||
['background_color' s+'black']
|
||||
:+ 'icons' %a
|
||||
:~
|
||||
%- pairs:enjs:format
|
||||
:~
|
||||
['src' s+(crip icon-url)]
|
||||
['sizes' s+'196x196']
|
||||
['type' s+'image/png']
|
||||
++ form
|
||||
|_ [=bowl:neo =aeon:neo =pail:neo]
|
||||
++ poke
|
||||
|= [=stud:neo vax=vase]
|
||||
^- (quip card:neo pail:neo)
|
||||
`pail
|
||||
++ init
|
||||
|= pal=(unit pail:neo)
|
||||
=/ [=stud:neo =vase] (need pal)
|
||||
=+ !<([eyre-id=@ta req=inbound-request:eyre] vase)
|
||||
:_ [stud vase]
|
||||
=/ =pith:neo #/[p/our.bowl]/$/eyre
|
||||
=; =manx
|
||||
=/ octs
|
||||
%- as-octt:mimes:html
|
||||
%+ welp "<!DOCTYPE html>"
|
||||
(en-xml:html manx)
|
||||
=/ head=sign:eyre:neo [eyre-id %head [200 [['content-type' 'text/html'] ~]]]
|
||||
=/ data=sign:eyre:neo [eyre-id %data `octs]
|
||||
=/ done=sign:eyre:neo [eyre-id %done ~]
|
||||
:~ [pith %poke eyre-sign/!>(head)]
|
||||
[pith %poke eyre-sign/!>(data)]
|
||||
[pith %poke eyre-sign/!>(done)]
|
||||
[here.bowl %cull ~]
|
||||
==
|
||||
==
|
||||
==
|
||||
++ manifest
|
||||
^~
|
||||
=; m m(a.g [[%href manifest-url] a.g.m])
|
||||
^- manx
|
||||
;link
|
||||
=rel "manifest"
|
||||
;
|
||||
==
|
||||
++ htmx-extensions
|
||||
:: htmx extension which encodes the request
|
||||
:: as the serialized HTML of the calling element
|
||||
%- trip
|
||||
'''
|
||||
htmx.defineExtension('html-enc', {
|
||||
onEvent: function (name, evt) {
|
||||
if (name === "htmx:configRequest") {
|
||||
evt.detail.headers['Content-Type'] = "text/html";
|
||||
}
|
||||
},
|
||||
encodeParameters : function(xhr, parameters, elt) {
|
||||
xhr.overrideMimeType('text/html');
|
||||
let xmls = new XMLSerializer();
|
||||
return (xmls.serializeToString(elt));
|
||||
}
|
||||
});
|
||||
Idiomorph.defaults.ignoreActive = true;
|
||||
Idiomorph.defaults.callbacks.beforeAttributeUpdated = (name, node, type) => {
|
||||
if (node.hasAttribute('morph-retain')) {
|
||||
let ribs = node.getAttribute('morph-retain').split(',').map(t => t.trim());
|
||||
if (ribs.includes(name)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Idiomorph.defaults.callbacks.beforeNodeMorphed = (oldNode, newNode) => {
|
||||
if (oldNode?.nodeName !== "#text") {
|
||||
if (oldNode.hasAttribute('morph-no-swap') && oldNode.id === newNode.id) {
|
||||
return false;
|
||||
}
|
||||
else if (
|
||||
newNode.hasAttribute('morph-if-class') &&
|
||||
!oldNode.classList.contains(newNode.getAttribute('morph-if-class'))
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
'''
|
||||
::
|
||||
++ lift
|
||||
|= in=manx
|
||||
^- manx
|
||||
;html
|
||||
;head
|
||||
;meta(charset "UTF-8");
|
||||
;title: s k y
|
||||
;script: {(trip jquery)}
|
||||
;script: {(trip htmx-js)}
|
||||
;script: {(trip htmx-response-targets)}
|
||||
;script: {(trip htmx-idiomorph)}
|
||||
;script: {htmx-extensions}
|
||||
;meta
|
||||
=name "viewport"
|
||||
=content
|
||||
"""
|
||||
width=device-width,
|
||||
initial-scale=1.0,
|
||||
maximum-scale=1.0
|
||||
"""
|
||||
;
|
||||
==
|
||||
;meta
|
||||
=name "htmx-config"
|
||||
=content (trip '{"ignoreTitle":"true"}')
|
||||
;
|
||||
==
|
||||
::;style
|
||||
:: ;+ ;/ %- trip
|
||||
:: '''
|
||||
:: @font-face {
|
||||
:: font-family: 'Urbit Sans';
|
||||
:: src: url("https://media.urbit.org/fonts/UrbitSans/UrbitSansVFWeb-Regular.woff2") format("woff2");
|
||||
:: font-style: normal;
|
||||
:: font-weight: 100 700;
|
||||
:: }
|
||||
:: '''
|
||||
::==
|
||||
;style: {(trip reset)}
|
||||
;style: {(trip feather)}
|
||||
;script
|
||||
;+ ;/ %- trip
|
||||
'''
|
||||
window.log = function() {
|
||||
if (this.console) {
|
||||
console.log(Array.prototype.slice.call(arguments));
|
||||
}
|
||||
};
|
||||
jQuery.fn.log = function (msg) {
|
||||
console.log(msg, this);
|
||||
return this;
|
||||
};
|
||||
jQuery.fn.emit = function (name) {
|
||||
(this[0]).dispatchEvent(
|
||||
new Event(
|
||||
name,
|
||||
{ bubbles: true, cancelable: true, composed: true }
|
||||
)
|
||||
);
|
||||
return this;
|
||||
};
|
||||
'''
|
||||
==
|
||||
;script: {(trip a-i-r)}
|
||||
;script: {(trip date-now)}
|
||||
;+ favicon
|
||||
;+ manifest
|
||||
==
|
||||
;body
|
||||
=hx-ext "html-enc,response-targets,morph"
|
||||
=hx-swap "outerHTML"
|
||||
=hx-boost "true"
|
||||
=hx-history "false"
|
||||
=hx-replace-url "/neo/sky"
|
||||
=hx-target "closest .hawk"
|
||||
=style
|
||||
"""
|
||||
background-color: var(--b1);
|
||||
background-image: var(--sky-bg-url);
|
||||
background-size: var(--sky-bg-size);
|
||||
background-repeat: var(--sky-bg-repeat);
|
||||
"""
|
||||
;+ in
|
||||
==
|
||||
==
|
||||
?~ src=(~(get by deps.bowl) %src)
|
||||
;div: 404
|
||||
=/ root=idea:neo (~(got of:neo q.u.src) /)
|
||||
?> =(%htmx p.pail.root)
|
||||
=/ bol *bowl:neo
|
||||
=. here.bol p.u.src
|
||||
=. our.bol our.bowl
|
||||
=. now.bol now.bowl
|
||||
=. eny.bol eny.bowl
|
||||
=. kids.bol q.u.src
|
||||
(!<(htmx q.pail.root) bol)
|
||||
--
|
||||
--
|
||||
|
@ -27,9 +27,9 @@
|
||||
:- ~
|
||||
=. menu.this menu.poke
|
||||
sky/!>(this)
|
||||
%new-tab
|
||||
%new-hawk
|
||||
:- ~
|
||||
=. hawks.this [[now.bowl #/[p/our.bowl]/home] hawks.this]
|
||||
=. hawks.this [[now.poke #/[p/our.bowl]/home] hawks.this]
|
||||
=. open.this (min 4 +(open.this))
|
||||
sky/!>(this)
|
||||
%move-tab
|
||||
|
@ -17,4 +17,14 @@
|
||||
%+ fall
|
||||
(de-xml:html q:(fall body.request [p=0 q='']))
|
||||
*manx
|
||||
++ parse-form-body
|
||||
|= =request:http
|
||||
^- (map @t @t)
|
||||
=/ body q:(fall body.request [p=0 q=''])
|
||||
=/ form (cat 3 '?' body)
|
||||
%- malt
|
||||
^- (list [@t @t])
|
||||
%+ fall
|
||||
(rush form yque:de-purl:html)
|
||||
~
|
||||
--
|
||||
|
1
pkg/arvo/neo/cod/std/src/pro/http-request.hoon
Normal file
1
pkg/arvo/neo/cod/std/src/pro/http-request.hoon
Normal file
@ -0,0 +1 @@
|
||||
,request:http
|
@ -2,7 +2,7 @@ $%
|
||||
[%theme mode=?(%light %dark) palette=(map @t @t)]
|
||||
[%hawks hawks=(list pith) slots=@]
|
||||
[%menu menu=?]
|
||||
[%new-tab ~]
|
||||
[%new-hawk now=@da]
|
||||
[%move-tab slot=@ud =pith]
|
||||
[%minimize slot=@ud]
|
||||
[%maximize slot=@ud]
|
||||
|
Loading…
Reference in New Issue
Block a user