mirror of
https://github.com/urbit/shrub.git
synced 2024-11-24 04:58:08 +03:00
re-implement sky (and window wrapper) as iframes composer
This commit is contained in:
parent
f34bfe5b76
commit
177999824e
@ -1561,6 +1561,8 @@
|
||||
(emit (do-card #/[p/our.bowl]/sky %make %sky ~ ~))
|
||||
=. run
|
||||
(emit (do-card #/[p/our.bowl]/srv/hawk %make %hawk-eyre ~ ~))
|
||||
=. run
|
||||
(emit (do-card #/[p/our.bowl]/srv/tree %make %tree-eyre ~ ~))
|
||||
=. run
|
||||
(emit (do-card #/[p/our.bowl]/srv/sky %make %sky-eyre ~ ~))
|
||||
run
|
||||
|
@ -3,6 +3,8 @@
|
||||
/- feather-icons
|
||||
/* date-now
|
||||
/* a-i-r
|
||||
/* s-k-y
|
||||
/* wi-nd
|
||||
/* feather
|
||||
/* reset
|
||||
/* hawk-icon
|
||||
@ -20,27 +22,12 @@
|
||||
?: menu.sky m
|
||||
m(a.g [[%closed ""] a.g.m])
|
||||
^- manx
|
||||
;a-i-r.wf.hf.relative
|
||||
;s-k-y.wf.hf.relative
|
||||
=our (scow %p our.bowl)
|
||||
=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
|
||||
@ -135,15 +122,12 @@
|
||||
?: =(pith /) ""
|
||||
(en-tape:pith:neo pith)
|
||||
=/ idt `tape`(zing (scan +:(scow %da id) (most dot (star ;~(less dot prn)))))
|
||||
;div.wf.hf.fc.jc.ac.f2.s3.spinner
|
||||
;wi-nd
|
||||
:: =sandbox "allow-scripts allow-forms allow-same-origin"
|
||||
=slot "s{<a>}"
|
||||
=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
|
||||
:: =here "/neo/hawk{ext}?slot={<a>}&hawk-id={<id>}&no-save"
|
||||
=here ext
|
||||
;
|
||||
==
|
||||
++ nav
|
||||
;nav.wf.hf.p2.fc.g2.sky-nav
|
||||
@ -187,16 +171,15 @@
|
||||
});
|
||||
$(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');
|
||||
:: '''
|
||||
=/ 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');
|
||||
'''
|
||||
;div
|
||||
=id "hawk-tab-{idt}"
|
||||
=hx-ext "ignore:html-enc"
|
||||
@ -204,11 +187,15 @@
|
||||
;button
|
||||
=class "loader p2 tl br1 hover grow {color}"
|
||||
=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
|
||||
=hx-on-htmx-before-send maximize-hawk-js
|
||||
=hx-on-htmx-after-request
|
||||
"""
|
||||
$(this).emit('hawks-moved');
|
||||
"""
|
||||
=hawk idt
|
||||
=hx-target "find .loading"
|
||||
=hx-swap "outerHTML"
|
||||
:: =hx-swap "outerHTML"
|
||||
=hx-swap "none"
|
||||
;span.loaded: {(en-tape:pith:neo pith)}
|
||||
;span.loading
|
||||
;+ loading.feather-icons
|
||||
@ -446,14 +433,19 @@
|
||||
;script: {(trip htmx-response-targets)}
|
||||
;script: {(trip htmx-idiomorph)}
|
||||
;script: {htmx-extensions}
|
||||
:: ;link
|
||||
:: =rel "stylesheet"
|
||||
:: =href "https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.15.1/cdn/themes/light.css"
|
||||
:: ;
|
||||
:: ==
|
||||
:: ;script
|
||||
:: =type "module"
|
||||
:: =src "https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.15.1/cdn/shoelace.js"
|
||||
:: ;
|
||||
:: ==
|
||||
;link
|
||||
=href "https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200"
|
||||
=rel "stylesheet"
|
||||
=href "https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.15.1/cdn/themes/light.css"
|
||||
;
|
||||
==
|
||||
;script
|
||||
=type "module"
|
||||
=src "https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.15.1/cdn/shoelace.js"
|
||||
;
|
||||
==
|
||||
;meta
|
||||
@ -484,6 +476,14 @@
|
||||
::==
|
||||
;style: {(trip reset)}
|
||||
;style: {(trip feather)}
|
||||
;script
|
||||
;+ ;/
|
||||
"""
|
||||
const sharedStyles = new CSSStyleSheet();
|
||||
sharedStyles.replaceSync(`{(trip reset)}\0a{(trip feather)}`);
|
||||
document.adoptedStyleSheets = [sharedStyles];
|
||||
"""
|
||||
==
|
||||
;script
|
||||
;+ ;/ %- trip
|
||||
'''
|
||||
@ -493,7 +493,11 @@
|
||||
}
|
||||
};
|
||||
jQuery.fn.log = function (msg) {
|
||||
if (msg) {
|
||||
console.log(msg, this);
|
||||
} else {
|
||||
console.log(this);
|
||||
}
|
||||
return this;
|
||||
};
|
||||
jQuery.fn.emit = function (name) {
|
||||
@ -505,6 +509,15 @@
|
||||
);
|
||||
return this;
|
||||
};
|
||||
jQuery.fn.poke = function (name) {
|
||||
(this[0]).dispatchEvent(
|
||||
new Event(
|
||||
name,
|
||||
{ bubbles: false, cancelable: true, composed: true }
|
||||
)
|
||||
);
|
||||
return this;
|
||||
};
|
||||
function urbitTimestamp() {
|
||||
let now = new Date();
|
||||
let year = now.getFullYear();
|
||||
@ -515,9 +528,60 @@
|
||||
let sec = String(now.getSeconds()).padStart(2, '0');
|
||||
return `~${year}.${month}.${date}..${hour}.${min}.${sec}`;
|
||||
}
|
||||
function urbitOur() {
|
||||
return document.body.getAttribute('our');
|
||||
}
|
||||
function hawkAtSlot(slot) {
|
||||
return document.querySelector(`.hawk[slot='${slot}']`);
|
||||
}
|
||||
function hawkDrag(event) {
|
||||
let fromHawk = $(event.target).closest('.hawk').get(0);
|
||||
event.dataTransfer.setData("text", fromHawk.slot);
|
||||
}
|
||||
function hawkDragEnter(event) {
|
||||
event.preventDefault();
|
||||
$('a-i-r').find('.drag-overlay').addClass('hidden');
|
||||
$(event.target).closest('.hawk').children('.drag-overlay').removeClass('hidden');
|
||||
}
|
||||
function hawkDragAllow(event) {
|
||||
event.preventDefault();
|
||||
}
|
||||
function hawkDragLeave(event) {
|
||||
event.preventDefault();
|
||||
}
|
||||
function hawkDrop(event) {
|
||||
event.preventDefault();
|
||||
$('a-i-r').find('.drag-overlay').addClass('hidden');
|
||||
let fromSlot = event.dataTransfer.getData("text");
|
||||
let fromHawk = $('a-i-r').children(`.hawk[slot='${fromSlot}']`).get(0);
|
||||
let toHawk = $(event.target).closest('.hawk').get(0);
|
||||
let toSlot = toHawk.slot;
|
||||
if (toSlot != fromSlot) {
|
||||
toHawk.setAttribute('slot', fromSlot);
|
||||
fromHawk.setAttribute('slot', toSlot);
|
||||
const formData = new URLSearchParams();
|
||||
formData.append('from', fromSlot.slice(1));
|
||||
formData.append('to', toSlot.slice(1));
|
||||
fetch(`/neo/hawk/${urbitOur()}/sky?stud=sky-diff&head=swap-hawks`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
},
|
||||
body: formData.toString(),
|
||||
})
|
||||
$('a-i-r').emit('hawks-moved');
|
||||
}
|
||||
}
|
||||
window.addEventListener('message', function(event) {
|
||||
let wid = event.data.wid;
|
||||
let path = event.data.path;
|
||||
document.querySelector(`[wid='${wid}']`)?.setAttribute('here', path);
|
||||
});
|
||||
'''
|
||||
==
|
||||
;script: {(trip a-i-r)}
|
||||
;script: {(trip s-k-y)}
|
||||
;script: {(trip wi-nd)}
|
||||
;script: {(trip date-now)}
|
||||
;+ favicon
|
||||
;+ manifest
|
||||
@ -528,6 +592,7 @@
|
||||
=hx-boost "true"
|
||||
=hx-history "false"
|
||||
=hx-replace-url "/neo/sky"
|
||||
=our (scow %p our.bowl)
|
||||
=style
|
||||
"""
|
||||
background-color: var(--b1);
|
||||
|
@ -14,7 +14,7 @@ class extends HTMLElement {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
::slotted(*) {
|
||||
overflow: auto;
|
||||
/* overflow: auto; */
|
||||
}
|
||||
:host {
|
||||
display: grid;
|
||||
|
@ -704,3 +704,6 @@ button {
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
.grabber {
|
||||
cursor: grab;
|
||||
}
|
||||
|
521
pkg/arvo/neo/cod/std/src/fil/s-k-y.js
Normal file
521
pkg/arvo/neo/cod/std/src/fil/s-k-y.js
Normal file
@ -0,0 +1,521 @@
|
||||
customElements.define('s-k-y',
|
||||
class extends HTMLElement {
|
||||
static get observedAttributes() {
|
||||
//
|
||||
return ["our", "closed", "hawks"];
|
||||
}
|
||||
constructor() {
|
||||
//
|
||||
super();
|
||||
const shadow = this.attachShadow({ mode: 'open' });
|
||||
shadow.adoptedStyleSheets = [sharedStyles];
|
||||
this.shadowRoot.innerHTML = `
|
||||
<style>
|
||||
@import url('https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200');
|
||||
.mso,
|
||||
.material-symbols-outlined {
|
||||
font-family: 'Material Symbols Outlined';
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-size: 1em;
|
||||
line-height: 1;
|
||||
letter-spacing: normal;
|
||||
text-transform: none;
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
word-wrap: normal;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
direction: ltr;
|
||||
-webkit-font-feature-settings: 'liga';
|
||||
-webkit-font-smoothing: antialiased;
|
||||
font-variation-settings:
|
||||
'FILL' 0,
|
||||
'wght' 400,
|
||||
'GRAD' 0,
|
||||
'opsz' 24;
|
||||
}
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
::slotted(*) {
|
||||
/* overflow: auto; */
|
||||
}
|
||||
:host {
|
||||
display: grid;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
max-height: 100%;
|
||||
overflow: hidden;
|
||||
margin: 0;
|
||||
grid-template-columns: 230px auto;
|
||||
grid-template-rows: auto 1fr;
|
||||
grid-template-areas:
|
||||
"tray main"
|
||||
"nav main";
|
||||
}
|
||||
:host(.closed) {
|
||||
grid-template-columns: 50px auto;
|
||||
grid-template-rows: auto 1fr;
|
||||
grid-template-areas:
|
||||
"tray main"
|
||||
"tray main";
|
||||
}
|
||||
:host(.closed) #nav {
|
||||
display: none;
|
||||
}
|
||||
#nav {
|
||||
grid-area: nav;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
align-items: stretch;
|
||||
gap: 12px;
|
||||
overflow: auto;
|
||||
}
|
||||
:host(.closed) #tray {
|
||||
display: flex;
|
||||
}
|
||||
#tray {
|
||||
grid-area: tray;
|
||||
display: none;
|
||||
padding-bottom: 15px;
|
||||
}
|
||||
/*
|
||||
* grid display
|
||||
*
|
||||
*/
|
||||
main {
|
||||
display: grid;
|
||||
grid-area: main;
|
||||
overflow: hidden;
|
||||
padding-left: var(--sky-inner-gap);
|
||||
}
|
||||
#s0, #s1, #s2, #s3 {
|
||||
overflow: auto;
|
||||
}
|
||||
#button {
|
||||
grid-area: btn;
|
||||
height: fit-content;
|
||||
}
|
||||
#s0 {
|
||||
grid-area: s0;
|
||||
}
|
||||
#s1 {
|
||||
grid-area: s1;
|
||||
}
|
||||
#s2 {
|
||||
grid-area: s2;
|
||||
}
|
||||
#s3 {
|
||||
grid-area: s3;
|
||||
}
|
||||
main.open-0 {
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: 1fr;
|
||||
grid-template-areas:
|
||||
".";
|
||||
}
|
||||
main.open-0 #s0,
|
||||
main.open-0 #s1,
|
||||
main.open-0 #s2,
|
||||
main.open-0 #s3 {
|
||||
display: none;
|
||||
}
|
||||
main.open-1 {
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: 1fr;
|
||||
grid-template-areas:
|
||||
"s0";
|
||||
}
|
||||
main.open-1 #s0 {
|
||||
display: block;
|
||||
}
|
||||
main.open-1 #s1,
|
||||
main.open-1 #s2,
|
||||
main.open-1 #s3 {
|
||||
display: none;
|
||||
}
|
||||
main.open-2 {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
grid-template-rows: 1fr;
|
||||
grid-template-areas:
|
||||
"s0 s1";
|
||||
}
|
||||
main.open-2 #s0,
|
||||
main.open-2 #s1 {
|
||||
display: block;
|
||||
}
|
||||
main.open-2 #s2,
|
||||
main.open-2 #s3 {
|
||||
display: none;
|
||||
}
|
||||
main.open-3 {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
grid-template-rows: 1fr 1fr;
|
||||
grid-template-areas:
|
||||
"s0 s1"
|
||||
"s0 s2";
|
||||
}
|
||||
main.open-3 #s0,
|
||||
main.open-3 #s1,
|
||||
main.open-3 #s2 {
|
||||
display: block;
|
||||
}
|
||||
main.open-3 #s3 {
|
||||
display: none;
|
||||
}
|
||||
main.open-4 {
|
||||
grid-template-columns: 2fr 1fr 1fr;
|
||||
grid-template-rows: 1fr 1fr;
|
||||
grid-template-areas:
|
||||
"s0 s1 s1"
|
||||
"s0 s2 s3";
|
||||
}
|
||||
main.open-4 #s0,
|
||||
main.open-4 #s1,
|
||||
main.open-4 #s2,
|
||||
main.open-4 #s3 {
|
||||
display: block;
|
||||
}
|
||||
/*
|
||||
* gaps
|
||||
*
|
||||
*/
|
||||
main.open-1 #s0 {
|
||||
padding-right: 0;
|
||||
}
|
||||
main.open-2 #s0,
|
||||
main.open-3 #s0,
|
||||
main.open-4 #s0 {
|
||||
padding-right: var(--sky-inner-gap);
|
||||
}
|
||||
main.open-1 #s1,
|
||||
main.open-2 #s1 {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
main.open-3 #s1,
|
||||
main.open-4 #s1 {
|
||||
padding-bottom: var(--sky-inner-gap);
|
||||
}
|
||||
main.open-1 #s2,
|
||||
main.open-2 #s2,
|
||||
main.open-3 #s2 {
|
||||
padding-right: 0;
|
||||
}
|
||||
main.open-4 #s2 {
|
||||
padding-right: var(--sky-inner-gap);
|
||||
}
|
||||
/*
|
||||
* mobile
|
||||
*
|
||||
*/
|
||||
@media (max-width: 900px) {
|
||||
:host {
|
||||
grid-template-columns: auto;
|
||||
grid-template-rows: 1fr auto;
|
||||
grid-template-areas:
|
||||
"main"
|
||||
"tray";
|
||||
padding: 0 !important;
|
||||
}
|
||||
:host(.closed) {
|
||||
grid-template-columns: auto;
|
||||
grid-template-rows: 1fr auto;
|
||||
grid-template-areas:
|
||||
"nav"
|
||||
"tray";
|
||||
}
|
||||
:host(.closed) main {
|
||||
display: none;
|
||||
}
|
||||
:host(:not(.closed)) main {
|
||||
display: grid;
|
||||
grid-template-columns: auto;
|
||||
grid-template-rows: auto;
|
||||
grid-template-areas:
|
||||
"s0";
|
||||
}
|
||||
:host(.closed) #tray,
|
||||
:host(:not(.closed)) #tray {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding: 6px 6px 10px 6px;
|
||||
}
|
||||
#tray .hideable {
|
||||
display: none;
|
||||
}
|
||||
#nav {
|
||||
padding: 8px;
|
||||
}
|
||||
#nav .hideable {
|
||||
display: none;
|
||||
}
|
||||
main {
|
||||
padding: 0;
|
||||
}
|
||||
main #s0 {
|
||||
display: block;
|
||||
padding: 0;
|
||||
padding-right: 0 !important;
|
||||
}
|
||||
main #s1 {
|
||||
display: none !important;
|
||||
}
|
||||
main #s2 {
|
||||
display: none !important;
|
||||
}
|
||||
main #s3 {
|
||||
display: none !important;
|
||||
}
|
||||
:host(.closed) #nav {
|
||||
display: flex;
|
||||
}
|
||||
:host(:not(.closed)) #nav {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<div id="tray" class="fc g2 js af">
|
||||
<button
|
||||
class="br1 p1 b2 hover fc js ac grow"
|
||||
onclick="this.getRootNode().host.dispatchEvent(new CustomEvent('sky-open', {bubbles:true, composed: true}))"
|
||||
>
|
||||
<span class="p1 s-1 bold">~</span>
|
||||
</button>
|
||||
<button class="p2 br1 bd1 b2 hover o7 hideable toggled">1</button>
|
||||
<button class="p2 br1 bd1 b2 hover o7 hideable">2</button>
|
||||
<button class="p2 br1 bd1 b2 hover o7 hideable">3</button>
|
||||
<button class="p2 br1 bd1 b3 hover f3"><span class="mso">settings</span></button>
|
||||
<button class="p2 br1 bd1 b3 hover f3"><span class="mso">notifications</span></button>
|
||||
</div>
|
||||
<nav id="nav" class="fc g8" style="padding-bottom: 15px;">
|
||||
<button
|
||||
class="br1 p1 b2 hover fc jc ac hideable"
|
||||
onclick="this.getRootNode().host.dispatchEvent(new CustomEvent('sky-open', {bubbles:true, composed: true}))"
|
||||
>
|
||||
<span class="p1 s-1 bold">~</span>
|
||||
</button>
|
||||
<div class="fc g3 grow scroll-y">
|
||||
<button
|
||||
onclick="this.getRootNode().host.dispatchEvent(new CustomEvent('new-window'))"
|
||||
class="wfc p2 br1 bd1 b2 hover fr g3 ac"
|
||||
>
|
||||
<span class="mso">add</span>
|
||||
<span class="f3">new window</span>
|
||||
</button>
|
||||
<div id="tabs" class="fc g2"></div>
|
||||
</div>
|
||||
<footer class="fc g2">
|
||||
<select class="fr p2 br1 bd1 b0">
|
||||
<option>workspace 1</option>
|
||||
<option>workspace 2</option>
|
||||
<option>workspace 3</option>
|
||||
</select>
|
||||
<button
|
||||
onclick="this.getRootNode().host.dispatchEvent(new CustomEvent('open-settings'))"
|
||||
class="p2 br1 bd1 b3 hover fr g3 ac f3 hideable"
|
||||
>
|
||||
<span class="mso">settings</span>
|
||||
settings
|
||||
</button>
|
||||
<button
|
||||
onclick="this.getRootNode().host.dispatchEvent(new CustomEvent('open-settings'))"
|
||||
class="p2 br1 bd1 b3 hover fr g3 ac f3 hideable"
|
||||
>
|
||||
<span class="mso">notifications</span>
|
||||
notifications
|
||||
</button>
|
||||
</footer>
|
||||
</nav>
|
||||
<main>
|
||||
<slot name="s0" id="s0"></slot>
|
||||
<slot name="s1" id="s1"></slot>
|
||||
<slot name="s2" id="s2"></slot>
|
||||
<slot name="s3" id="s3"></slot>
|
||||
</main>
|
||||
<slot id="default" style="display: none;"></slot>
|
||||
`
|
||||
}
|
||||
get hawks() {
|
||||
return parseInt(this.getAttribute("hawks") || "0");
|
||||
}
|
||||
get our() {
|
||||
return this.getAttribute('our');
|
||||
}
|
||||
get windows() {
|
||||
let slots = $(this).children('wi-nd[slot]').get().toSorted((a, b) => {
|
||||
let aSlot = parseFloat(a.getAttribute('slot').slice(1));
|
||||
let bSlot = parseFloat(b.getAttribute('slot').slice(1));
|
||||
if (aSlot > bSlot) return 1;
|
||||
if (aSlot < bSlot) return -1;
|
||||
return 0;
|
||||
});
|
||||
let noslots = $(this).children('wi-nd:not([slot])').get();
|
||||
return [...slots, ...noslots];
|
||||
}
|
||||
qs(sel) {
|
||||
return this.shadowRoot.querySelector(sel);
|
||||
}
|
||||
gid(id) {
|
||||
return this.shadowRoot.getElementById(id);
|
||||
}
|
||||
connectedCallback() {
|
||||
$(this).off();
|
||||
$(this).on("sky-open", (e) => {
|
||||
this.toggleAttribute("closed");
|
||||
})
|
||||
$(this).on('fix-slots', () => {
|
||||
this.fixSlots();
|
||||
})
|
||||
$(this).on('new-window', () => {
|
||||
let wind = document.createElement('wi-nd');
|
||||
$(wind).attr('here', `/${this.our}/home`);
|
||||
$(wind).attr('slot', `s-1`);
|
||||
$(this).append(wind);
|
||||
this.growFlock();
|
||||
this.fixSlots();
|
||||
})
|
||||
$(this).on('close-window', (e) => {
|
||||
let wind = $(e.target);
|
||||
if (wind.attr('slot') != undefined) {
|
||||
this.shrinkFlock();
|
||||
}
|
||||
wind.remove();
|
||||
this.fixSlots();
|
||||
this.renderTabs();
|
||||
})
|
||||
$(this).on('minimize-window', (e) => {
|
||||
let wind = $(e.target);
|
||||
if (wind.attr('slot') != undefined) {
|
||||
wind.removeAttr('slot');
|
||||
this.shrinkFlock();
|
||||
}
|
||||
this.fixSlots();
|
||||
this.renderTabs();
|
||||
})
|
||||
$(this).on('maximize-window', (e) => {
|
||||
let wind = $(e.target);
|
||||
if (!wind.attr('slot')) {
|
||||
this.growFlock();
|
||||
}
|
||||
wind.attr('slot', 's-1');
|
||||
this.fixSlots();
|
||||
this.renderTabs();
|
||||
})
|
||||
$(this).on('drag-start', (e) => {
|
||||
$(this.windows).attr('dragging', '');
|
||||
$(this.gid('nav')).addClass('active');
|
||||
})
|
||||
$(this).on('drag-end', (e) => {
|
||||
$(this.windows).removeAttr('dragging');
|
||||
})
|
||||
$(this).on('here-moved', () => {
|
||||
this.renderTabs();
|
||||
})
|
||||
$(this.gid('s0')).off();
|
||||
$(this.gid('s0')).on('slotchange', (e) => {
|
||||
this.renderTabs();
|
||||
});
|
||||
$(this.gid('s1')).off();
|
||||
$(this.gid('s1')).on('slotchange', () => {
|
||||
this.renderTabs();
|
||||
});
|
||||
$(this.gid('s2')).off();
|
||||
$(this.gid('s2')).on('slotchange', () => {
|
||||
this.renderTabs();
|
||||
});
|
||||
$(this.gid('s3')).off();
|
||||
$(this.gid('s3')).on('slotchange', () => {
|
||||
this.renderTabs();
|
||||
});
|
||||
$(this.gid('default')).off();
|
||||
$(this.gid('default')).on('slotchange', () => {
|
||||
this.renderTabs();
|
||||
});
|
||||
|
||||
$(this.gid('nav')).off();
|
||||
$(this.gid('nav')).on('dragover', (e) => {
|
||||
e.preventDefault();
|
||||
})
|
||||
$(this.gid('nav')).on('drop', (e) => {
|
||||
e.preventDefault();
|
||||
let wid = e.originalEvent.dataTransfer.getData('text/plain');
|
||||
let wind = $(`[wid='${wid}']`);
|
||||
wind.poke('minimize');
|
||||
});
|
||||
}
|
||||
attributeChangedCallback(name, oldValue, newValue) {
|
||||
//
|
||||
if (name === "closed") {
|
||||
this.classList.toggle("closed");
|
||||
} else if (name === "hawks") {
|
||||
this.qs("main").className = `open-${this.hawks}`;
|
||||
}
|
||||
}
|
||||
renderIcon(name) {
|
||||
let s = document.createElement('span');
|
||||
s.className = 'mso';
|
||||
s.textContent = name;
|
||||
return s;
|
||||
}
|
||||
renderTabs() {
|
||||
let tabs = $(this.gid('tabs'));
|
||||
tabs.children().remove();
|
||||
let hawks = this.hawks;
|
||||
let that = this;
|
||||
$(this.windows).each(function(i) {
|
||||
let wind = this;
|
||||
let tab = document.createElement('div');
|
||||
$(tab).addClass('b2 br1 fr ac js g1 bd1');
|
||||
if (i < hawks) {
|
||||
$(tab).addClass('toggled');
|
||||
}
|
||||
|
||||
let max = document.createElement('button');
|
||||
$(max).text($(wind).attr('here'));
|
||||
$(max).addClass('b2 hover br1 bd0 p2 grow tl');
|
||||
max.style = 'overflow: hidden; white-space: nowrap; text-overflow: ellipsis; text-align: left;';
|
||||
$(max).on('click', () => {
|
||||
$(wind).emit('maximize-window');
|
||||
});
|
||||
|
||||
let min = document.createElement('button');
|
||||
$(min).append(that.renderIcon('minimize'));
|
||||
$(min).addClass('b2 hover br1 bd0 p1 f3');
|
||||
$(min).on('click', () => {
|
||||
$(wind).emit('minimize-window');
|
||||
});
|
||||
if (i >= hawks) {
|
||||
$(min).hide();
|
||||
}
|
||||
|
||||
let close = document.createElement('button');
|
||||
$(close).append(that.renderIcon('close'));
|
||||
$(close).addClass('b2 hover br1 bd0 p1 f3');
|
||||
$(close).on('click', () => {
|
||||
$(wind).emit('close-window');
|
||||
});
|
||||
|
||||
$(tab).append(max);
|
||||
$(tab).append(min);
|
||||
$(tab).append(close);
|
||||
tabs.append(tab);
|
||||
})
|
||||
}
|
||||
fixSlots() {
|
||||
let slotted = $(this.windows).filter('[slot]').get().slice(0, 3);
|
||||
$(this.windows).removeAttr('slot');
|
||||
slotted.forEach((s, i) => {
|
||||
s.setAttribute('slot', `s${i}`);
|
||||
})
|
||||
}
|
||||
growFlock() {
|
||||
$(this).attr('hawks', Math.min(3, this.hawks + 1));
|
||||
}
|
||||
shrinkFlock() {
|
||||
$(this).attr('hawks', Math.max(0, this.hawks - 1));
|
||||
}
|
||||
});
|
285
pkg/arvo/neo/cod/std/src/fil/wi-nd.js
Normal file
285
pkg/arvo/neo/cod/std/src/fil/wi-nd.js
Normal file
@ -0,0 +1,285 @@
|
||||
customElements.define('wi-nd',
|
||||
class extends HTMLElement {
|
||||
static get observedAttributes() {
|
||||
//
|
||||
return [
|
||||
"wid",
|
||||
"here",
|
||||
"searching", // boolean. true is user is using the search bar in the header
|
||||
"tabs", // currently unused. soon be space-separated list of iframe prefixes for each renderer
|
||||
"current", // currently boolean. soon interpret to match prefix(tab)
|
||||
"dragging",
|
||||
];
|
||||
}
|
||||
constructor() {
|
||||
//
|
||||
super();
|
||||
const shadow = this.attachShadow({ mode: 'open' });
|
||||
shadow.adoptedStyleSheets = [sharedStyles];
|
||||
this.shadowRoot.innerHTML = `
|
||||
<style>
|
||||
@import url('https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200');
|
||||
.mso,
|
||||
.material-symbols-outlined {
|
||||
font-family: 'Material Symbols Outlined';
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-size: 1em;
|
||||
line-height: 1;
|
||||
letter-spacing: normal;
|
||||
text-transform: none;
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
word-wrap: normal;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
direction: ltr;
|
||||
-webkit-font-feature-settings: 'liga';
|
||||
-webkit-font-smoothing: antialiased;
|
||||
font-variation-settings:
|
||||
'FILL' 0,
|
||||
'wght' 400,
|
||||
'GRAD' 0,
|
||||
'opsz' 24;
|
||||
}
|
||||
:host {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
border-radius: 3px;
|
||||
}
|
||||
#drag-overlay {
|
||||
background: blue;
|
||||
opacity: 0%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 50;
|
||||
}
|
||||
:host(.dragging) #drag-overlay {
|
||||
opacity: 14%;
|
||||
}
|
||||
@media (max-width: 900px) {
|
||||
#axns {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<div hidden id="drag-overlay"></div>
|
||||
<header class="b2 p1 fr ac js g2">
|
||||
<button class="p-1 s-1 b3 br1 hover" id="tree-toggle"><span class="mso">sort</span></button>
|
||||
<div id="breadcrumbs" class="grow fr g1 af js"></div>
|
||||
<form id="searchbar" class="grow fr hidden">
|
||||
<input id="input-here" class="f2 grow b0 br1 p-1 s-1"/>
|
||||
</form>
|
||||
<div id="axns" class="fr g2">
|
||||
<button
|
||||
class="p1 s-1 b2 hover br1"
|
||||
onclick="this.getRootNode().host.dispatchEvent(new CustomEvent('minimize'))"
|
||||
>
|
||||
<span class="mso">minimize</span>
|
||||
</button>
|
||||
<button
|
||||
class="p1 s-1 b2 hover br1"
|
||||
onclick="this.getRootNode().host.dispatchEvent(new CustomEvent('close'))"
|
||||
>
|
||||
<span class="mso">close</span>
|
||||
</button>
|
||||
<div
|
||||
class="p1 s-1 b2 grabber f3"
|
||||
draggable="true"
|
||||
id="dragger"
|
||||
>
|
||||
<span class="mso">drag_indicator</span>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<div id="tabs" class="fc grow">
|
||||
</div>
|
||||
`
|
||||
}
|
||||
connectedCallback() {
|
||||
$(this.gid('searchbar')).off();
|
||||
$(this.gid('searchbar')).on('submit', (e) => {
|
||||
e.preventDefault();
|
||||
this.setAttribute('here', $(this.gid('input-here')).val());
|
||||
});
|
||||
$(this.gid('input-here')).off();
|
||||
$(this.gid('input-here')).on('focusout', (e) => {
|
||||
$(this).removeAttr('searching');
|
||||
});
|
||||
$(this.gid('input-here')).on('blur', (e) => {
|
||||
$(this).removeAttr('searching');
|
||||
});
|
||||
$(this.gid('tree-toggle')).off();
|
||||
$(this.gid('tree-toggle')).on('click', (e) => {
|
||||
this.toggleAttribute('current');
|
||||
});
|
||||
|
||||
$(this.gid('dragger')).off();
|
||||
$(this.gid('dragger')).on('dragstart', (e) => {
|
||||
$(this).emit('drag-start');
|
||||
e.originalEvent.dataTransfer.setData('text/plain', this.getAttribute('wid'));
|
||||
})
|
||||
$(this.gid('dragger')).on('dragend', () => {
|
||||
$(this).emit('drag-end');
|
||||
})
|
||||
|
||||
$(this).off();
|
||||
$(this).on('close', () => {
|
||||
$(this).emit('close-window');
|
||||
})
|
||||
$(this).on('minimize', () => {
|
||||
$(this).emit('minimize-window');
|
||||
})
|
||||
$(this).on('dragenter', (e) => {
|
||||
$(this).addClass('dragging');
|
||||
})
|
||||
$(this).on('dragover', (e) => {
|
||||
e.preventDefault();
|
||||
})
|
||||
$(this).on('dragleave', (e) => {
|
||||
$(this).removeClass('dragging');
|
||||
})
|
||||
$(this).on('drop', (e) => {
|
||||
e.preventDefault();
|
||||
$(this).removeClass('dragging');
|
||||
$(this).emit('drag-end');
|
||||
let wid = e.originalEvent.dataTransfer.getData('text/plain');
|
||||
let wind = $(`[wid='${wid}']`);
|
||||
let newSlot = parseInt(this.getAttribute('slot').slice(1));
|
||||
let oldSlot = parseInt(wind.attr('slot')?.slice(1));
|
||||
if (!isNaN(oldSlot) && oldSlot < newSlot) {
|
||||
newSlot = newSlot + 0.5;
|
||||
} else {
|
||||
newSlot = newSlot - 0.5;
|
||||
}
|
||||
wind.attr('slot', `s${newSlot}`);
|
||||
$(this).emit('fix-slots');
|
||||
})
|
||||
this.setAttribute('wid', `${Date.now()}`);
|
||||
}
|
||||
attributeChangedCallback(name, oldValue, newValue) {
|
||||
//
|
||||
if (name === "here") {
|
||||
if (oldValue !== newValue) {
|
||||
let tabs = $(this.gid('tabs'));
|
||||
tabs.children().remove();
|
||||
let hawk = this.createIframe('/neo/hawk', newValue, $(this).attr('current') != undefined);
|
||||
let tree = this.createIframe('/neo/tree', newValue, $(this).attr('current') == undefined);
|
||||
tabs.append(hawk);
|
||||
tabs.append(tree);
|
||||
this.buildBreadcrumbs();
|
||||
$(this.gid('input-here')).val(newValue);
|
||||
$(this).emit('here-moved');
|
||||
}
|
||||
} else if (name === "searching") {
|
||||
if (newValue === null) {
|
||||
$(this.gid('breadcrumbs')).removeClass('hidden');
|
||||
$(this.gid('searchbar')).addClass('hidden');
|
||||
} else {
|
||||
$(this.gid('breadcrumbs')).addClass('hidden');
|
||||
$(this.gid('searchbar')).removeClass('hidden');
|
||||
this.gid('input-here').focus();
|
||||
}
|
||||
} else if (name === "current") {
|
||||
if (newValue === null) {
|
||||
$(this.gid('tabs')).children(`[prefix='/neo/hawk']`).show()
|
||||
$(this.gid('tabs')).children(`[prefix='/neo/tree']`).hide();
|
||||
$(this.gid('tree-toggle')).removeClass('toggled');
|
||||
} else {
|
||||
$(this.gid('tabs')).children(`[prefix='/neo/hawk']`).hide()
|
||||
$(this.gid('tabs')).children(`[prefix='/neo/tree']`).show();
|
||||
$(this.gid('tree-toggle')).addClass('toggled');
|
||||
}
|
||||
} else if (name === "dragging") {
|
||||
if (newValue === null) {
|
||||
$(this).removeClass('dragging');
|
||||
$(this.gid('drag-overlay')).hide();
|
||||
} else {
|
||||
$(this.gid('drag-overlay')).show();
|
||||
}
|
||||
}
|
||||
}
|
||||
qs(sel) {
|
||||
return this.shadowRoot.querySelector(sel);
|
||||
}
|
||||
gid(id) {
|
||||
return this.shadowRoot.getElementById(id);
|
||||
}
|
||||
get path() {
|
||||
let here = this.getAttribute("here") || "/";
|
||||
return here.slice(1).split("/").filter(s => !!s.trim().length);
|
||||
}
|
||||
createIframe(prefix, here, hidden) {
|
||||
let el = document.createElement('iframe');
|
||||
el.setAttribute('prefix', prefix);
|
||||
el.setAttribute('lazy', '');
|
||||
el.setAttribute('src', prefix+here);
|
||||
el.setAttribute('style', 'width: 100%; flex-grow: 1; border: none; background: var(--b0);');
|
||||
if (hidden) {
|
||||
el.hidden = true;
|
||||
}
|
||||
el.addEventListener('load', () => {
|
||||
this.registerServiceWorker(el, prefix);
|
||||
});
|
||||
return el;
|
||||
}
|
||||
registerServiceWorker(iframe, prefix) {
|
||||
const iframeWindow = iframe.contentWindow;
|
||||
const iframeDoc = iframeWindow.document;
|
||||
let wid = this.getAttribute('wid');
|
||||
let pre = prefix.length;
|
||||
const inlineScript = iframeDoc.createElement('script');
|
||||
inlineScript.textContent = `
|
||||
function notifySky() {
|
||||
window.parent.postMessage({wid: '${wid}', path: window.location.pathname.slice(${pre})}, '*');
|
||||
}
|
||||
window.addEventListener('beforeunload', function (e) {
|
||||
notifySky();
|
||||
});
|
||||
window.addEventListener('htmx:beforeHistorySave', function (e) {
|
||||
notifySky();
|
||||
});
|
||||
window.addEventListener('htmx:beforeRequest', function (e) {
|
||||
notifySky();
|
||||
});
|
||||
window.addEventListener('htmx:afterSwap', function (e) {
|
||||
notifySky();
|
||||
});
|
||||
`;
|
||||
iframeDoc.body.appendChild(inlineScript);
|
||||
}
|
||||
buildBreadcrumbs() {
|
||||
let breadcrumbs = $(this.gid('breadcrumbs'));
|
||||
breadcrumbs.children().remove();
|
||||
//
|
||||
this.path.forEach((p, i) => {
|
||||
let chevron = $(document.createElement('span'));
|
||||
chevron.addClass('s-2 f4 o6 fc ac jc');
|
||||
chevron.text('›');
|
||||
breadcrumbs.append(chevron);
|
||||
//
|
||||
let crumb = $(document.createElement('button'));
|
||||
crumb.addClass((i === 0 ? 'p-1' : 'p1') + ' b2 hover br1 s-1 f2');
|
||||
crumb.text(i === 0 ? "/" : this.path[i]);
|
||||
crumb.on('click', () => {
|
||||
$(this).attr('here', "/"+this.path.slice(0, i+1).join("/"));
|
||||
});
|
||||
breadcrumbs.append(crumb);
|
||||
})
|
||||
let spacer = $(document.createElement('button'));
|
||||
spacer.addClass('grow b2 br1 hover')
|
||||
spacer.on('click', () => {
|
||||
$(this).attr('searching', '');
|
||||
});
|
||||
breadcrumbs.append(spacer);
|
||||
}
|
||||
});
|
@ -1,6 +1,7 @@
|
||||
/@ htmx-type=htmx
|
||||
/- feather-icons
|
||||
/- serv=sky-server
|
||||
/- sky-wrapper
|
||||
/> htmx
|
||||
/< node
|
||||
/< http-request
|
||||
@ -59,7 +60,7 @@
|
||||
bowl
|
||||
404
|
||||
['content-type' 'text/html']~
|
||||
~(lift hawk pit stub stub & meta)
|
||||
~(lift hawk pit stub stub & meta bowl)
|
||||
==
|
||||
=/ here p.u.src
|
||||
^- (list card:neo)
|
||||
@ -77,7 +78,7 @@
|
||||
bowl
|
||||
200
|
||||
['content-type' 'text/html']~
|
||||
~(lift hawk here.bol stub stub & meta)
|
||||
~(lift hawk here.bol stub stub & meta bowl)
|
||||
==
|
||||
=/ root=idea:neo u.reet
|
||||
=/ bol *bowl:neo
|
||||
@ -105,13 +106,14 @@
|
||||
==
|
||||
=; c
|
||||
?: (~(has by pam.purl) 'no-save') c
|
||||
[(sky-move-tab bol slot) c]
|
||||
c
|
||||
:: [(sky-move-tab bol slot) c]
|
||||
%: eyre-cards
|
||||
eyre-id
|
||||
bowl
|
||||
200
|
||||
['content-type' 'text/html']~
|
||||
~(lift hawk here.bol main (raw-view bol(kids q.u.src)) has-conversion meta)
|
||||
~(lift hawk here.bol main (raw-view bol(kids q.u.src)) has-conversion meta bowl)
|
||||
==
|
||||
::
|
||||
%'POST'
|
||||
@ -342,7 +344,7 @@
|
||||
==
|
||||
==
|
||||
++ hawk
|
||||
|_ [here=pith main=manx raw=manx has-app=? meta=[@da @ud]]
|
||||
|_ [here=pith main=manx raw=manx has-app=? meta=[@da @ud] =bowl:neo]
|
||||
++ our-tape
|
||||
=/ f (snag 0 here)
|
||||
?@(f (trip f) (scow f))
|
||||
@ -351,7 +353,7 @@
|
||||
++ slot-tag
|
||||
:: XX oh boy this is hacky.
|
||||
:: working with slots in ssr is tough
|
||||
?: =(slot 999) "s-1"
|
||||
?: =(slot 999) "s0"
|
||||
"s{<slot>}"
|
||||
++ idt `tape`(zing (scan +:(scow %da id) (most dot (star ;~(less dot prn)))))
|
||||
++ vals
|
||||
@ -362,7 +364,9 @@
|
||||
'}'
|
||||
++ lift
|
||||
^- manx
|
||||
;div.hawk.fc.wf.hf.br1
|
||||
%-
|
||||
~(lift sky-wrapper bowl)
|
||||
;div.hawk.fc.wf.hf.br1.iframe-switch
|
||||
=id "hawk-{idt}"
|
||||
=hawk-id (scow %da id)
|
||||
=slot slot-tag
|
||||
@ -371,7 +375,7 @@
|
||||
=hx-target "closest .hawk"
|
||||
=hx-target-x "closest .rendered"
|
||||
=hx-target-404 "this"
|
||||
;+ header
|
||||
:: ;+ header
|
||||
;div
|
||||
=class "raw wf hf b0 scroll-y scroll-x {(trip ?:(has-app 'hidden' ''))}"
|
||||
;+ raw
|
||||
@ -538,4 +542,713 @@
|
||||
==
|
||||
==
|
||||
--
|
||||
++ feather
|
||||
'''
|
||||
/** feather.css
|
||||
* ~2024.4.6
|
||||
*
|
||||
* styling resets
|
||||
* and
|
||||
* utility classes
|
||||
*
|
||||
**/
|
||||
|
||||
:root {
|
||||
|
||||
/* --font: 'Urbit Sans';
|
||||
--font-mono: 'Monaco';
|
||||
--mono-scale: 0.8;
|
||||
--letter-spacing: 0.024em;
|
||||
--line-height: 1.4;
|
||||
*/
|
||||
--0in: calc(0 * var(--1in));
|
||||
--1in: 4px;
|
||||
--font-size: calc(4 * var(--1in));
|
||||
--2in: calc(2 * var(--1in));
|
||||
--3in: calc(3 * var(--1in));
|
||||
--4in: calc(4 * var(--1in));
|
||||
--5in: calc(5 * var(--1in));
|
||||
--6in: calc(6 * var(--1in));
|
||||
--7in: calc(7 * var(--1in));
|
||||
--8in: calc(8 * var(--1in));
|
||||
--9in: calc(9 * var(--1in));
|
||||
|
||||
--10in: calc(10 * var(--1in));
|
||||
--11in: calc(11 * var(--1in));
|
||||
--12in: calc(12 * var(--1in));
|
||||
--13in: calc(13 * var(--1in));
|
||||
--14in: calc(14 * var(--1in));
|
||||
--15in: calc(15 * var(--1in));
|
||||
--16in: calc(16 * var(--1in));
|
||||
--17in: calc(17 * var(--1in));
|
||||
--18in: calc(18 * var(--1in));
|
||||
--19in: calc(19 * var(--1in));
|
||||
|
||||
--20in: calc(20 * var(--1in));
|
||||
--21in: calc(21 * var(--1in));
|
||||
--22in: calc(22 * var(--1in));
|
||||
--23in: calc(23 * var(--1in));
|
||||
--24in: calc(24 * var(--1in));
|
||||
--25in: calc(25 * var(--1in));
|
||||
--26in: calc(26 * var(--1in));
|
||||
--27in: calc(27 * var(--1in));
|
||||
--28in: calc(28 * var(--1in));
|
||||
--29in: calc(29 * var(--1in));
|
||||
|
||||
--30in: calc(30 * var(--1in));
|
||||
--31in: calc(31 * var(--1in));
|
||||
--32in: calc(32 * var(--1in));
|
||||
--33in: calc(33 * var(--1in));
|
||||
--34in: calc(34 * var(--1in));
|
||||
--35in: calc(35 * var(--1in));
|
||||
--36in: calc(36 * var(--1in));
|
||||
--37in: calc(37 * var(--1in));
|
||||
--38in: calc(38 * var(--1in));
|
||||
--39in: calc(39 * var(--1in));
|
||||
--40in: calc(40 * var(--1in));
|
||||
|
||||
|
||||
/* --light-b-3: #dd5522;
|
||||
--light-b-2: #ddaa33;
|
||||
--light-b-1: #55dd33;
|
||||
--light-b0: #dddddd;
|
||||
--light-b1: #cccccc;
|
||||
--light-b2: #bbbbbb;
|
||||
--light-b3: #aaaaaa;
|
||||
--light-b4: #999999;
|
||||
--light-f-3: #993311;
|
||||
--light-f-2: #aaaa22;
|
||||
--light-f-1: #339911;
|
||||
--light-f0: #111111;
|
||||
--light-f1: #333333;
|
||||
--light-f2: #444444;
|
||||
--light-f3: #555555;
|
||||
--light-f4: #777777;
|
||||
|
||||
--dark-b-3: #551111;
|
||||
--dark-b-2: #555511;
|
||||
--dark-b-1: #225511;
|
||||
--dark-b0: #222222;
|
||||
--dark-b1: #333333;
|
||||
--dark-b2: #444444;
|
||||
--dark-b3: #555555;
|
||||
--dark-b4: #666666;
|
||||
--dark-f-3: #ee7755;
|
||||
--dark-f-2: #ccbb33;
|
||||
--dark-f-1: #55cc33;
|
||||
--dark-f0: #eeeeee;
|
||||
--dark-f1: #cccccc;
|
||||
--dark-f2: #bbbbbb;
|
||||
--dark-f3: #aaaaaa;
|
||||
--dark-f4: #888888;
|
||||
*/
|
||||
--b-3: var(--light-b-3);
|
||||
--b-2: var(--light-b-2);
|
||||
--b-1: var(--light-b-1);
|
||||
--b0: var(--light-b0);
|
||||
--b1: var(--light-b1);
|
||||
--b2: var(--light-b2);
|
||||
--b3: var(--light-b3);
|
||||
--b4: var(--light-b4);
|
||||
--f-3: var(--light-f-3);
|
||||
--f-2: var(--light-f-2);
|
||||
--f-1: var(--light-f-1);
|
||||
--f0: var(--light-f0);
|
||||
--f1: var(--light-f1);
|
||||
--f2: var(--light-f2);
|
||||
--f3: var(--light-f3);
|
||||
--f4: var(--light-f4);
|
||||
}
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--b-3: var(--dark-b-3);
|
||||
--b-2: var(--dark-b-2);
|
||||
--b-1: var(--dark-b-1);
|
||||
--b0: var(--dark-b0);
|
||||
--b1: var(--dark-b1);
|
||||
--b2: var(--dark-b2);
|
||||
--b3: var(--dark-b3);
|
||||
--b4: var(--dark-b4);
|
||||
--f-3: var(--dark-f-3);
|
||||
--f-2: var(--dark-f-2);
|
||||
--f-1: var(--dark-f-1);
|
||||
--f0: var(--dark-f0);
|
||||
--f1: var(--dark-f1);
|
||||
--f2: var(--dark-f2);
|
||||
--f3: var(--dark-f3);
|
||||
--f4: var(--dark-f4);
|
||||
}
|
||||
}
|
||||
* {
|
||||
font-size: var(--font-size);
|
||||
}
|
||||
/*
|
||||
@media (max-width: 900px) {
|
||||
:root {
|
||||
--font-size: calc(1.3 * var(--font-size));
|
||||
}
|
||||
}
|
||||
*/
|
||||
body {
|
||||
font-family: var(--font);
|
||||
letter-spacing: var(--letter-spacing);
|
||||
line-height: 1;
|
||||
height: 100%;
|
||||
}
|
||||
button {
|
||||
border: inherit;
|
||||
background: inherit;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.break {
|
||||
word-break: break-word;
|
||||
}
|
||||
.action {
|
||||
touch-action: manipulation;
|
||||
}
|
||||
.hidden,
|
||||
.folded {
|
||||
display: none !important;
|
||||
}
|
||||
.jc {
|
||||
justify-content: center;
|
||||
}
|
||||
.jb {
|
||||
justify-content: space-between;
|
||||
}
|
||||
.ja {
|
||||
justify-content: space-around;
|
||||
}
|
||||
.js {
|
||||
justify-content: start;
|
||||
}
|
||||
.je {
|
||||
justify-content: end;
|
||||
}
|
||||
.js {
|
||||
justify-content: start;
|
||||
}
|
||||
.as {
|
||||
align-items: start;
|
||||
}
|
||||
.af {
|
||||
align-items: stretch;
|
||||
}
|
||||
.ae {
|
||||
align-items: end;
|
||||
}
|
||||
.ac {
|
||||
align-items: center;
|
||||
}
|
||||
.wfc {
|
||||
width: fit-content;
|
||||
}
|
||||
.wf {
|
||||
width: 100%;
|
||||
}
|
||||
.mw-page {
|
||||
max-width: 650px;
|
||||
}
|
||||
.hf {
|
||||
height: 100%;
|
||||
}
|
||||
.hfc {
|
||||
height: fit-content;
|
||||
}
|
||||
.mono {
|
||||
font-family: var(--font-mono), monospace;
|
||||
font-size: calc(1em * var(--mono-scale));
|
||||
}
|
||||
.italic {
|
||||
font-style: italic;
|
||||
}
|
||||
.underline {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
.strike {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.pre {
|
||||
white-space: pre;
|
||||
}
|
||||
.pre-line {
|
||||
white-space: pre-line;
|
||||
}
|
||||
|
||||
.tl {
|
||||
text-align: left;
|
||||
}
|
||||
.tc {
|
||||
text-align: center;
|
||||
}
|
||||
.tr {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.block {
|
||||
display: block;
|
||||
}
|
||||
.inline {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.fc {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.fcr {
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
}
|
||||
.fr {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
.frw {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.basis-full {
|
||||
flex-basis: 100%;
|
||||
}
|
||||
.basis-half {
|
||||
flex-basis: 50%;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.basis-none {
|
||||
flex-basis: 0%;
|
||||
flex-shrink: 1;
|
||||
}
|
||||
.shrink-0 {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.relative {
|
||||
position: relative;
|
||||
}
|
||||
.absolute {
|
||||
position: absolute;
|
||||
}
|
||||
.fixed {
|
||||
position: fixed;
|
||||
}
|
||||
.sticky {
|
||||
position: sticky;
|
||||
}
|
||||
|
||||
.z-2 {
|
||||
z-index: -20;
|
||||
}
|
||||
.z-1 {
|
||||
z-index: -10;
|
||||
}
|
||||
.z0 {
|
||||
z-index: 0;
|
||||
}
|
||||
.z1 {
|
||||
z-index: 10;
|
||||
}
|
||||
.z2 {
|
||||
z-index: 20;
|
||||
}
|
||||
|
||||
.grow {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.g0 {
|
||||
gap: 0;
|
||||
}
|
||||
.g1 {
|
||||
gap: 4px;
|
||||
}
|
||||
.g2 {
|
||||
gap: 8px;
|
||||
}
|
||||
.g3 {
|
||||
gap: 12px;
|
||||
}
|
||||
.g4 {
|
||||
gap: 16px;
|
||||
}
|
||||
.g5 {
|
||||
gap: 20px;
|
||||
}
|
||||
.g6 {
|
||||
gap: 24px;
|
||||
}
|
||||
.g7 {
|
||||
gap: 32px;
|
||||
}
|
||||
.g8 {
|
||||
gap: 40px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.p-8 {
|
||||
padding: 32px 64px;
|
||||
}
|
||||
.p-7 {
|
||||
padding: 28px 56px;
|
||||
}
|
||||
.p-6 {
|
||||
padding: 24px 48px;
|
||||
}
|
||||
.p-5 {
|
||||
padding: 20px 40px;
|
||||
}
|
||||
.p-4 {
|
||||
padding: 16px 32px;
|
||||
}
|
||||
.p-3 {
|
||||
padding: 12px 24px;
|
||||
}
|
||||
.p-2 {
|
||||
padding: 8px 16px;
|
||||
}
|
||||
.p-1 {
|
||||
padding: 4px 8px;
|
||||
}
|
||||
.p0 {
|
||||
padding: 0;
|
||||
}
|
||||
.p1 {
|
||||
padding: 4px;
|
||||
}
|
||||
.p2 {
|
||||
padding: 8px;
|
||||
}
|
||||
.p3 {
|
||||
padding: 12px;
|
||||
}
|
||||
.p4 {
|
||||
padding: 16px;
|
||||
}
|
||||
.p5 {
|
||||
padding: 24px;
|
||||
}
|
||||
.p6 {
|
||||
padding: 30px;
|
||||
}
|
||||
.p7 {
|
||||
padding: 34px;
|
||||
}
|
||||
.p8 {
|
||||
padding: 38px;
|
||||
}
|
||||
.p-page {
|
||||
padding-top: 30px;
|
||||
padding-bottom: 200px;
|
||||
padding-left: 12px;
|
||||
padding-right: 12px;
|
||||
}
|
||||
|
||||
|
||||
.ma {
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.mt1 {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
.mt2 {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
.mt3 {
|
||||
margin-top: 3rem;
|
||||
}
|
||||
|
||||
.m0 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
.o0 {
|
||||
opacity: 0%;
|
||||
}
|
||||
.o1 {
|
||||
opacity: 10%;
|
||||
}
|
||||
.o2 {
|
||||
opacity: 20%;
|
||||
}
|
||||
.o3 {
|
||||
opacity: 30%;
|
||||
}
|
||||
.o4 {
|
||||
opacity: 40%;
|
||||
}
|
||||
.o5 {
|
||||
opacity: 50%;
|
||||
}
|
||||
.o6 {
|
||||
opacity: 60%;
|
||||
}
|
||||
.o7 {
|
||||
opacity: 70%;
|
||||
}
|
||||
.o8 {
|
||||
opacity: 80%;
|
||||
}
|
||||
.o9 {
|
||||
opacity: 90%;
|
||||
}
|
||||
.o10 {
|
||||
opacity: 100%;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
.scroll-y {
|
||||
overflow-y: auto;
|
||||
}
|
||||
.scroll-x {
|
||||
overflow-x: auto;
|
||||
}
|
||||
.scroll-hidden {
|
||||
overflow: hidden;
|
||||
}
|
||||
.loader {
|
||||
position: relative;
|
||||
}
|
||||
.loading {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
pointer-events: none;
|
||||
}
|
||||
.loader .loading {
|
||||
opacity: 0;
|
||||
transition: opacity 300ms;
|
||||
}
|
||||
.htmx-request .loader .loading,
|
||||
.loader.htmx-request .loading {
|
||||
opacity: 1;
|
||||
}
|
||||
.loader .loaded {
|
||||
opacity: 1;
|
||||
transition: opacity 300ms;
|
||||
}
|
||||
.htmx-request .loader .loaded,
|
||||
.loader.htmx-request .loaded {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.f-3 {
|
||||
color: var(--f-3);
|
||||
}
|
||||
.f-2 {
|
||||
color: var(--f-2);
|
||||
}
|
||||
.f-1 {
|
||||
color: var(--f-1);
|
||||
}
|
||||
.f0 {
|
||||
color: var(--f0);
|
||||
}
|
||||
.f1 {
|
||||
color: var(--f1);
|
||||
}
|
||||
.f2 {
|
||||
color: var(--f2);
|
||||
}
|
||||
.f3 {
|
||||
color: var(--f3);
|
||||
}
|
||||
.f4 {
|
||||
color: var(--f4);
|
||||
}
|
||||
|
||||
.b-3 {
|
||||
background-color: var(--b-3);
|
||||
}
|
||||
.b-2 {
|
||||
background-color: var(--b-2);
|
||||
}
|
||||
.b-1 {
|
||||
background-color: var(--b-1);
|
||||
}
|
||||
.b0 {
|
||||
background-color: var(--b0);
|
||||
}
|
||||
.b1 {
|
||||
background-color: var(--b1);
|
||||
}
|
||||
.b2 {
|
||||
background-color: var(--b2);
|
||||
}
|
||||
.b3 {
|
||||
background-color: var(--b3);
|
||||
}
|
||||
.b4 {
|
||||
background-color: var(--b4);
|
||||
}
|
||||
|
||||
.s-2 {
|
||||
font-size: 0.7rem;
|
||||
}
|
||||
.s-1 {
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
.s0 {
|
||||
font-size: 1rem;
|
||||
}
|
||||
.s1 {
|
||||
font-size: 1.15rem;
|
||||
}
|
||||
.s2 {
|
||||
font-size: 1.3rem;
|
||||
}
|
||||
.s3 {
|
||||
font-size: 1.45rem;
|
||||
}
|
||||
.s4 {
|
||||
font-size: 1.6rem;
|
||||
}
|
||||
.s5 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
.s6 {
|
||||
font-size: 2.4rem;
|
||||
}
|
||||
.bd0 {
|
||||
border: none;
|
||||
}
|
||||
.bd1 {
|
||||
border: 0.8px solid var(--b3);
|
||||
}
|
||||
.bd2 {
|
||||
border: 0.8px solid var(--f3);
|
||||
}
|
||||
.bd3 {
|
||||
border: 2px solid var(--f1);
|
||||
}
|
||||
/* deprecated */
|
||||
.border {
|
||||
border: 0.8px solid var(--f3);
|
||||
}
|
||||
|
||||
.br1 {
|
||||
border-radius: 3px;
|
||||
}
|
||||
.br2 {
|
||||
border-radius: 6px;
|
||||
}
|
||||
.br3 {
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.hover:hover {
|
||||
filter: invert(20%);
|
||||
}
|
||||
.toggled {
|
||||
filter: invert(100%);
|
||||
}
|
||||
.hover.toggled:hover {
|
||||
filter: invert(100%);
|
||||
}
|
||||
.active,
|
||||
.selected {
|
||||
filter: invert(10%);
|
||||
}
|
||||
.hover.active:hover,
|
||||
.hover.selected:hover {
|
||||
filter: invert(25%);
|
||||
}
|
||||
.numbered > *:before {
|
||||
content: counter(line);
|
||||
display: inline-block;
|
||||
/* border-right: 1px solid var(--f3); */
|
||||
/* padding: 0 .5em; */
|
||||
/* margin-right: .5em; */
|
||||
color: var(--f3);
|
||||
/* min-width: 34px; */
|
||||
text-align: right;
|
||||
}
|
||||
.numbered > * {
|
||||
display: block;
|
||||
counter-increment: line;
|
||||
}
|
||||
.prose h1 {
|
||||
font-size: 1.45rem;
|
||||
margin: 1rem 0;
|
||||
}
|
||||
.prose h2 {
|
||||
font-size: 1.3rem;
|
||||
margin: 1rem 0;
|
||||
}
|
||||
.prose h3 {
|
||||
font-size: 1.15rem;
|
||||
margin: 1rem 0;
|
||||
}
|
||||
.prose h1, .prose h2, .prose h3 {
|
||||
font-weight: bold;
|
||||
}
|
||||
.prose p {
|
||||
margin-bottom: 1rem;
|
||||
line-height: var(--line-height);
|
||||
}
|
||||
.prose img {
|
||||
max-width: 100%;
|
||||
display: block;
|
||||
max-height: 350px;
|
||||
}
|
||||
.prose details {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
.prose a {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.prose blockquote {
|
||||
margin-left: 10px;
|
||||
border-left: 2px solid var(--b3);
|
||||
padding: 4px;
|
||||
padding-left: 12px;
|
||||
color: var(--f2);
|
||||
}
|
||||
.prose pre {
|
||||
font-family: var(--font-mono);
|
||||
font-size: calc(1em * var(--mono-scale));
|
||||
overflow-x: auto;
|
||||
width: 100%;
|
||||
display: block;
|
||||
padding: 8px;
|
||||
}
|
||||
.prose code {
|
||||
font-family: var(--font-mono);
|
||||
font-size: calc(1em * var(--mono-scale));
|
||||
color: var(--f2);
|
||||
}
|
||||
.prose ul,
|
||||
.prose ol {
|
||||
padding-left: 29px;
|
||||
line-height: calc(calc(1 + var(--line-height)) / 2);
|
||||
margin-bottom: 0.6rem;
|
||||
}
|
||||
.prose ul p,
|
||||
.prose ol p {
|
||||
margin-bottom: 0;
|
||||
line-height: var(--line-height);
|
||||
}
|
||||
.prose ul ul,
|
||||
.prose ol ul,
|
||||
.prose ul ol,
|
||||
.prose ol ol {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.prose summary {
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
'''
|
||||
--
|
||||
|
57
pkg/arvo/neo/cod/std/src/imp/tree-eyre.hoon
Normal file
57
pkg/arvo/neo/cod/std/src/imp/tree-eyre.hoon
Normal file
@ -0,0 +1,57 @@
|
||||
/@ eyre-reqs
|
||||
/- serv=server
|
||||
^- kook:neo
|
||||
|%
|
||||
++ state pro/%sig
|
||||
++ poke (sy %eyre-task ~)
|
||||
++ kids
|
||||
:+ ~ %y
|
||||
%- ~(gas by *lads:neo)
|
||||
~
|
||||
++ deps
|
||||
%- ~(gas by *band:neo)
|
||||
~
|
||||
::
|
||||
++ form
|
||||
|_ [=bowl:neo =aeon:neo =pail:neo]
|
||||
++ poke
|
||||
|= [=stud:neo vax=vase]
|
||||
^- (quip card:neo pail:neo)
|
||||
?+ stud ~|(bad-stud/stud !!)
|
||||
%eyre-task
|
||||
=+ !<(=task:eyre:neo vax)
|
||||
=/ [eyre-id=@ta req=inbound-request:eyre] task
|
||||
:_ sig/!>(~)
|
||||
=/ doc
|
||||
%- en-xml:html
|
||||
;html
|
||||
;body
|
||||
;style
|
||||
;+ ;/ %- trip
|
||||
'''
|
||||
body {
|
||||
color: red;
|
||||
}
|
||||
'''
|
||||
==
|
||||
;h1: tree stub: {(trip url.request.req)}
|
||||
==
|
||||
==
|
||||
=/ head=sign:eyre:neo [eyre-id %head [200 ~]]
|
||||
=/ data=sign:eyre:neo [eyre-id %data `(as-octt:mimes:html doc)]
|
||||
=/ done=sign:eyre:neo [eyre-id %done ~]
|
||||
:~ [#/[p/our.bowl]/$/eyre %poke eyre-sign/!>(head)]
|
||||
[#/[p/our.bowl]/$/eyre %poke eyre-sign/!>(data)]
|
||||
[#/[p/our.bowl]/$/eyre %poke eyre-sign/!>(done)]
|
||||
==
|
||||
==
|
||||
++ init
|
||||
|= pal=(unit pail:neo)
|
||||
:_ sig/!>(~)
|
||||
=/ =pith:neo #/[p/our.bowl]/$/eyre
|
||||
=/ =binding:eyre [~ ~[%neo %tree]]
|
||||
=/ =req:eyre:neo [%connect binding here.bowl]
|
||||
:~ [pith %poke eyre-req/!>(req)]
|
||||
==
|
||||
--
|
||||
--
|
425
pkg/arvo/neo/cod/std/src/lib/sky-wrapper.hoon
Normal file
425
pkg/arvo/neo/cod/std/src/lib/sky-wrapper.hoon
Normal file
@ -0,0 +1,425 @@
|
||||
/- feather-icons
|
||||
/* date-now
|
||||
/* a-i-r
|
||||
/* feather
|
||||
/* reset
|
||||
/* hawk-icon
|
||||
/* jquery
|
||||
/* htmx-js
|
||||
/* htmx-response-targets
|
||||
/* htmx-idiomorph
|
||||
|_ =bowl:neo
|
||||
++ 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
|
||||
%- zing
|
||||
%+ turn ~(tap by m)
|
||||
|= [key=@t val=@t]
|
||||
"""
|
||||
--{(trip key)}: {(trip val)};
|
||||
"""
|
||||
++ eye
|
||||
;div#eye.fixed.hidden
|
||||
=style "bottom: 30px; left: 30px;"
|
||||
=morph-no-swap ""
|
||||
;script
|
||||
;+ ;/ %- trip
|
||||
'''
|
||||
function handleKey(e) {
|
||||
let focused = document.activeElement;
|
||||
let textarea = ['TEXTAREA'].includes(focused.nodeName)
|
||||
let textinput = ['text', 'number', 'email', 'password'].includes(focused.type);
|
||||
if (textarea || textinput) {
|
||||
if (e.key === 'Escape') {
|
||||
document.activeElement.blur();
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (e.key === 'Escape') {
|
||||
closeEye();
|
||||
document.activeElement.blur();
|
||||
}
|
||||
else if (e.key === ' ') {
|
||||
e.preventDefault();
|
||||
if (window.eye.open) {
|
||||
closeEye();
|
||||
} else {
|
||||
openEye();
|
||||
}
|
||||
} else if (e.key === 'Escape') {
|
||||
e.preventDefault();
|
||||
document.activeElement.blur();
|
||||
} else if (!e.ctrlKey && !e.metaKey && !e.altKey) {
|
||||
if (window.eye?.open) {
|
||||
e.preventDefault();
|
||||
let area = window.eye?.spots?.filter(s => s[0][0] === e.key);
|
||||
if (area.length === 1) {
|
||||
let btn = area[0][1];
|
||||
btn.click();
|
||||
btn.focus();
|
||||
closeEye();
|
||||
}
|
||||
else if (!!area.length) {
|
||||
let news = area.map(c => (c[0].length < 2) ? c : [c[0].slice(1), c[1]]);
|
||||
window.eye.spots = news;
|
||||
closeEye(true);
|
||||
openEye();
|
||||
} else {
|
||||
closeEye();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function openEye() {
|
||||
window.eye.open = true;
|
||||
document.getElementById('eye').classList.remove('hidden');
|
||||
buildGazeSpots();
|
||||
}
|
||||
function closeEye(keep) {
|
||||
window.eye.open = false;
|
||||
if (!keep) {
|
||||
window.eye.spots = null;
|
||||
}
|
||||
document.getElementById('eye').classList.add('hidden');
|
||||
document.querySelectorAll('.gaze').forEach(g => g.remove());
|
||||
}
|
||||
function buildGazeSpots() {
|
||||
let buttons = window.eye?.spots?.map(s => s[1]) ||
|
||||
document.querySelectorAll(
|
||||
'a, button, summary, [role="button"], input, textarea, .clickable'
|
||||
);
|
||||
let chars = ['a', 's', 'd', 'f', 'k', 'm', 'n', 'r', 't', 'y', 'u', 'i', 'c', 'v', 'b'];
|
||||
buttons.forEach((b, i) => {
|
||||
let d = b.getBoundingClientRect();
|
||||
if (d.right > 0 && d.right > 0) {
|
||||
let t = document.createElement('div');
|
||||
var lent = Math.floor((i / chars.length) + 1);
|
||||
var word = ''
|
||||
while (lent > 0) {
|
||||
let ch = chars[i % chars.length];
|
||||
word = `${word}${ch}`;
|
||||
lent = lent - 1;
|
||||
}
|
||||
t.textContent = word.slice(-1);
|
||||
t.className = 'b-1 br2 p1 s0 bold fixed gaze z2'
|
||||
t.style = `top: ${Math.max(0, d.top - 10)}px; left: ${Math.max(0, d.left - 10)}px;`
|
||||
document.getElementById('eye')?.parentNode.appendChild(t);
|
||||
window.eye.spots = [[word, b], ...(window.eye?.spots || [])]
|
||||
}
|
||||
})
|
||||
}
|
||||
window.addEventListener('keydown', handleKey);
|
||||
'''
|
||||
==
|
||||
==
|
||||
++ 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']
|
||||
['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: hawk
|
||||
;script: {(trip jquery)}
|
||||
;script: {(trip htmx-js)}
|
||||
;script: {(trip htmx-response-targets)}
|
||||
;script: {(trip htmx-idiomorph)}
|
||||
;script: {htmx-extensions}
|
||||
:: ;link
|
||||
:: =rel "stylesheet"
|
||||
:: =href "https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.15.1/cdn/themes/light.css"
|
||||
:: ;
|
||||
:: ==
|
||||
:: ;script
|
||||
:: =type "module"
|
||||
:: =src "https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.15.1/cdn/shoelace.js"
|
||||
:: ;
|
||||
:: ==
|
||||
;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(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}`;
|
||||
}
|
||||
function urbitOur() {
|
||||
return document.body.getAttribute('our');
|
||||
}
|
||||
function hawkAtSlot(slot) {
|
||||
return document.querySelector(`.hawk[slot='${slot}']`);
|
||||
}
|
||||
function hawkDrag(event) {
|
||||
let fromHawk = $(event.target).closest('.hawk').get(0);
|
||||
event.dataTransfer.setData("text", fromHawk.slot);
|
||||
}
|
||||
function hawkDragEnter(event) {
|
||||
event.preventDefault();
|
||||
$('a-i-r').find('.drag-overlay').addClass('hidden');
|
||||
$(event.target).closest('.hawk').children('.drag-overlay').removeClass('hidden');
|
||||
}
|
||||
function hawkDragAllow(event) {
|
||||
event.preventDefault();
|
||||
}
|
||||
function hawkDragLeave(event) {
|
||||
event.preventDefault();
|
||||
}
|
||||
function hawkDrop(event) {
|
||||
event.preventDefault();
|
||||
$('a-i-r').find('.drag-overlay').addClass('hidden');
|
||||
let fromSlot = event.dataTransfer.getData("text");
|
||||
let fromHawk = $('a-i-r').children(`.hawk[slot='${fromSlot}']`).get(0);
|
||||
let toHawk = $(event.target).closest('.hawk').get(0);
|
||||
let toSlot = toHawk.slot;
|
||||
if (toSlot != fromSlot) {
|
||||
toHawk.setAttribute('slot', fromSlot);
|
||||
fromHawk.setAttribute('slot', toSlot);
|
||||
const formData = new URLSearchParams();
|
||||
formData.append('from', fromSlot.slice(1));
|
||||
formData.append('to', toSlot.slice(1));
|
||||
fetch(`/neo/hawk/${urbitOur()}/sky?stud=sky-diff&head=swap-hawks`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
},
|
||||
body: formData.toString(),
|
||||
})
|
||||
$('a-i-r').emit('hawks-moved');
|
||||
}
|
||||
}
|
||||
'''
|
||||
==
|
||||
;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"
|
||||
=our (scow %p our.bowl)
|
||||
=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
|
||||
;+ stub-styling
|
||||
==
|
||||
==
|
||||
++ stub-styling
|
||||
;style
|
||||
;+ ;/ %- trip
|
||||
'''
|
||||
html {
|
||||
--line-height: 1.4;
|
||||
--sky-outer-gap: 8px;
|
||||
--dark-b-1: #225511;
|
||||
--dark-b3: #555555;
|
||||
--light-b-1: #55dd33;
|
||||
--letter-spacing: 0.024em;
|
||||
--dark-f-2: #ccbb33;
|
||||
--light-b1: #cccccc;
|
||||
--light-b0: #dddddd;
|
||||
--light-b3: #aaaaaa;
|
||||
--light-b-3: #dd5522;
|
||||
--dark-b4: #666666;
|
||||
--light-f2: #444444;
|
||||
--dark-b-3: #551111;
|
||||
--dark-f4: #888888;
|
||||
--dark-f-3: #ee7755;
|
||||
--light-b-2: #ddaa33;
|
||||
--sky-opacity: 0.88;
|
||||
--dark-b0: #222222;
|
||||
--light-b2: #bbbbbb;
|
||||
--light-f-3: #993311;
|
||||
--light-f1: #333333;
|
||||
--dark-f-1: #55cc33;
|
||||
--dark-b1: #333333;
|
||||
--dark-f1: #cccccc;
|
||||
--light-f3: #555555;
|
||||
--light-b4: #999999;
|
||||
--sky-bg-url: ;
|
||||
--dark-f3: #aaaaaa;
|
||||
--light-f0: #111111;
|
||||
--sky-bg-size: contain;
|
||||
--light-f4: #777777;
|
||||
--1in: 4px;
|
||||
--font-mono: monospace;
|
||||
--dark-f0: #eeeeee;
|
||||
--sky-inner-gap: 8px;
|
||||
--dark-b2: #444444;
|
||||
--dark-b-2: #555511;
|
||||
--font: Urbit Sans, sans-serif;
|
||||
--mono-scale: 0.8;
|
||||
--light-f-2: #aaaa22;
|
||||
--dark-f2: #bbbbbb;
|
||||
--light-f-1: #339911;
|
||||
}
|
||||
'''
|
||||
==
|
||||
--
|
Loading…
Reference in New Issue
Block a user