diff --git a/PubSub.js b/PubSub.js new file mode 100644 index 0000000..10ebec4 --- /dev/null +++ b/PubSub.js @@ -0,0 +1,39 @@ +let PubSub = ()=>{ + // state: + let subscriptions_by_event = {}; // by event name, that is + let subscriptions_by_name = {}; // subscriptions can be named, for easy unsubscribing + + // methods: + let pub = (e, ...params)=>{ + if(subscriptions_by_event[e]){ + subscriptions_by_event[e].forEach(subscription=>subscription.cb(...params)) + } + }; + let sub = (e, cb, name)=>{ // 'name' is for unsubbing + if(typeof subscriptions_by_event[e] === 'undefined'){ + subscriptions_by_event[e] = []; + } + + let subscription = { e, cb, name: name || '' }; + + subscriptions_by_event[e].push(subscription); + if(subscription.name !== ''){ + if(typeof subscriptions_by_name[name] !== 'undefined'){ console.warn('Already subscription with name "'+name+'". Overwriting nonetheless.'); } + subscriptions_by_name[name] = subscription; + } + }; + let unsub = (name)=>{ + // check if such a named subscription exists: + if(typeof subscriptions_by_name[name] !== 'undefined'){ + // get ref to subscription object for later: + let subscription = subscriptions_by_name[name]; + // delete subscription from both lists: + subscriptions_by_event[subscription.e].splice(subscriptions_by_event[subscription.e].indexOf(subscription), 1); + delete subscriptions_by_name[name]; + } + }; + + return {pub, sub, unsub}; + } + +export default PubSub; \ No newline at end of file diff --git a/behaviors.js b/behaviors.js new file mode 100644 index 0000000..f521e0b --- /dev/null +++ b/behaviors.js @@ -0,0 +1,16 @@ +import {pub, sub} from './pubsub.js'; +import state from './state.js'; +import redraw from './redraw.js'; + +// "raw" event listeners, which publish meaningful events, which are listened-to further-down: +// ... + + +// "meaningful" event listeners: +//sub('set-current-node', (node_vm)=>{ +// state.current_node_vm = node_vm; +// redraw(); +// }); + + +export default null; \ No newline at end of file diff --git a/components/App.js b/components/App.js new file mode 100644 index 0000000..f7456ef --- /dev/null +++ b/components/App.js @@ -0,0 +1,15 @@ +import {elementOpen as o, elementClose as c, text as t} from '../vendor/incremental-dom.js'; +import state from '../state.js'; +import {pub} from '../pubsub.js'; + + +const App = ()=>{ + o('div', null, null, + 'id', 'header'); + o('h1'); + t('Options Calendar-Spread Optimizer'); + c('h1'); + c('div'); + } + +export default App; \ No newline at end of file diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 0000000..6b6fda9 Binary files /dev/null and b/favicon.ico differ diff --git a/index.css b/index.css new file mode 100644 index 0000000..9d88b99 --- /dev/null +++ b/index.css @@ -0,0 +1,33 @@ +* { + box-sizing: border-box; + } + +.node, .node > .content, .node > .node-children-container { + display: inline-block; + width: min-content; + } + +.node { + margin-top: 5px; + margin-bottom: 5px; + } + +.node > .content { + box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px; + } +.node[currently-selected-node] > .content { + /* background-color: #7ea6fc; */ + box-shadow: rgba(0, 0, 0, 0.25) 0px 54px 55px, rgba(0, 0, 0, 0.12) 0px -12px 30px, rgba(0, 0, 0, 0.12) 0px 4px 6px, rgba(0, 0, 0, 0.17) 0px 12px 13px, rgba(0, 0, 0, 0.09) 0px -3px 5px; + } + +.node > .content > textarea { + background: transparent; + resize: none; + width: 80em; + outline: none; + border: none; + } + +.node > .node-children-container { + margin-left: 5em; + } \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..c268352 --- /dev/null +++ b/index.html @@ -0,0 +1,13 @@ + + + + + + Calendar Optimizer + + + + +
+ + \ No newline at end of file diff --git a/index.js b/index.js new file mode 100644 index 0000000..6752a5b --- /dev/null +++ b/index.js @@ -0,0 +1,16 @@ +import redraw from './redraw.js'; +import state from './state.js'; +import x from './behaviors.js'; + +// bootstrap initial state: + + +redraw(); + + +/* TODO */ +/* +* + + +*/ \ No newline at end of file diff --git a/pubsub.js b/pubsub.js new file mode 100644 index 0000000..ba4c9d4 --- /dev/null +++ b/pubsub.js @@ -0,0 +1,7 @@ +// global PubSub instance: +import PubSub from './PubSub.js'; + +const pubsub = PubSub(); +export const {pub, sub, unsub} = pubsub; + +export default pubsub; \ No newline at end of file diff --git a/redraw.js b/redraw.js new file mode 100644 index 0000000..b75ccfa --- /dev/null +++ b/redraw.js @@ -0,0 +1,10 @@ +import {patch} from './vendor/incremental-dom.js'; +import App from './components/App.js'; + +export const redraw = ()=>{ + const root = document.getElementById('root'); + + patch(root, App); + } + +export default redraw; \ No newline at end of file diff --git a/state.js b/state.js new file mode 100644 index 0000000..6fb71e1 --- /dev/null +++ b/state.js @@ -0,0 +1,8 @@ + +let state = { + + }; + + + +export default state; \ No newline at end of file diff --git a/vendor/incremental-dom.js b/vendor/incremental-dom.js new file mode 100644 index 0000000..971cfd3 --- /dev/null +++ b/vendor/incremental-dom.js @@ -0,0 +1,7 @@ +/** + * Bundled by jsDelivr using Rollup v2.60.2 and Terser v5.10.0. + * Original file: /npm/incremental-dom@0.7.0/dist/incremental-dom-cjs.js + * + * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files + */ +var t={};Object.defineProperty(t,"__esModule",{value:!0});let e="key";let n=!1,r=!1,o=!1;function l(t){if(!t)throw new Error("Expected value to be defined");return t}function i(t){if(!o)throw new Error("Cannot call "+t+"() unless in patch.")}function c(t){if(n)throw new Error(t+"() can not be called between elementOpenStart() and elementOpenEnd().")}function s(t){if(r)throw new Error(t+"() may not be called inside an element that has called skip().")}function u(t){if(!n)throw new Error(t+"() can only be called after calling elementOpenStart().")}function a(t){o=null!=t}function f(t){const e=n;return n=t,e}function p(t){const e=r;return r=t,e}const d=Object.prototype.hasOwnProperty;function h(){}function m(){return new h}function g(t,e){for(;t.length>e;)t.pop()}h.prototype=Object.create(null);const y={default:"__default"};function w(t,e,n){if(null==n)t.removeAttribute(e);else{const r=function(t){return 0===t.lastIndexOf("xml:",0)?"http://www.w3.org/XML/1998/namespace":0===t.lastIndexOf("xlink:",0)?"http://www.w3.org/1999/xlink":null}(e);r?t.setAttributeNS(r,e,String(n)):t.setAttribute(e,String(n))}}function b(t,e,n){t[e]=n}function O(t,e,n){e.indexOf("-")>=0?t.setProperty(e,n):t[e]=n}const x=m();function A(t,e,n){(x[e]||x[y.default])(t,e,n)}x[y.default]=function(t,e,n){const r=typeof n;"object"===r||"function"===r?b(t,e,n):w(t,e,n)},x.style=function(t,e,n){l("style"in t);const r=t.style;if("string"==typeof n)r.cssText=n;else{r.cssText="";for(const t in n)o=n,i=t,d.call(o,i)&&O(r,t,n[t])}var o,i};const S={nodesCreated:null,nodesDeleted:null};class E{constructor(){this.created=[],this.deleted=[]}markCreated(t){this.created.push(t)}markDeleted(t){this.deleted.push(t)}notifyChanges(){S.nodesCreated&&this.created.length>0&&S.nodesCreated(this.created),S.nodesDeleted&&this.deleted.length>0&&S.nodesDeleted(this.deleted)}}function C(t){return 1===t.nodeType}const D="undefined"!=typeof Node&&Node.prototype.getRootNode||function(){let t=this,e=t;for(;t;)e=t,t=t.parentNode;return e};function _(t,e){const n=function(t){const e=D.call(t);return function(t){return 11===t.nodeType||9===t.nodeType}(e)?e.activeElement:null}(t);return n&&t.contains(n)?function(t,e){const n=[];let r=t;for(;r!==e;){const t=l(r);n.push(t),r=t.parentNode}return n}(n,e):[]}class k{constructor(t,e,n){this._attrsArr=null,this.staticsApplied=!1,this.nameOrCtor=t,this.key=e,this.text=n}hasEmptyAttrsArr(){const t=this._attrsArr;return!t||!t.length}getAttrsArr(t){return this._attrsArr||(this._attrsArr=function(t){const e=new Array(t);return g(e,0),e}(t))}}function N(t,e,n,r){const o=new k(e,n,r);return t.__incrementalDOMData=o,o}function v(t,n){if(t.__incrementalDOMData)return t.__incrementalDOMData;const r=C(t)?t.localName:t.nodeName,o=e,l=C(t)&&null!=o?t.getAttribute(o):null,i=N(t,r,C(t)?l||n:null);return C(t)&&function(t,e){const n=t.attributes,r=n.length;if(!r)return;const o=e.getAttrsArr(r);for(let t=0,e=0;t=0?function(t,e,n){const r=e.nextSibling;let o=n;for(;null!==o&&o!==e;){const e=o.nextSibling;t.insertBefore(o,r),o=e}}(K,r,j):K.insertBefore(r,j),j=r)}function Z(t,e){return Y(t,e),G(),K}function $(){return p(!1),H(),j}function tt(){return Y("#text",null),j}function et(){return i("currentElement"),c("currentElement"),K}function nt(t,e={}){const{matches:r=I}=e;return(e,o,l)=>{const i=T,c=B,s=L,u=z,d=V,h=j,m=K,g=R;let y=!1,w=!1;B=e.ownerDocument,T=new E,R=r,z=[],V=[],j=null,K=e.parentNode,L=_(e,K),y=f(!1),w=p(!1),a(T);try{const r=t(e,o,l);return function(){if(n)throw new Error("elementOpenEnd() must be called after calling elementOpenStart().")}(),r}finally{T.notifyChanges(),B=c,T=i,R=g,z=u,V=d,j=h,K=m,L=s,f(y),p(w),a(T)}}}function rt(t){return nt(((t,e,n)=>(j=t,G(),e(n),H(),function(t,e){if(t===e)return;let n=t;const r=[];for(;n&&n!==e;)r.push(n.nodeName.toLowerCase()),n=n.parentNode;throw new Error("One or more tags were not closed:\n"+r.join("\n"))}(j,t),t)),t)}function ot(t){return nt(((t,e,n)=>{const r={nextSibling:t};let o=null,i=null;return o=t.nextSibling,i=t.previousSibling,j=r,e(n),K||console.warn("patchOuter requires the node have a parent if there is a key."),function(t,e,n,r){const o=l(t),i=l(e),c=i.nextSibling===n&&i.previousSibling===r,s=i.nextSibling===o.nextSibling&&i.previousSibling===r;if(!c&&!s&&i!==o)throw new Error("There must be exactly one top level call corresponding to the patched element.")}(r,j,o,i),K&&X(K,F(),t.nextSibling),r===j?null:j}),t)}const lt=rt(),it=ot(),ct=[];let st=0;function ut(t,e,n,r){ct.push(t),ct.push(e),ct.push(n),ct.push(r)}const at=m();function ft(t,e,n,r){const o=!t.length;let l=0;for(;lcrypto.getRandomValues(new Uint8Array(t)),r=(t,e,r)=>{let l=(2<{let a="";for(;;){let e=r(n),g=n;for(;g--;)if(a+=t[e[g]&l]||"",a.length===o)return a}}},l=(t,l=21)=>r(t,l,e),n=(t=21)=>{let e="",r=crypto.getRandomValues(new Uint8Array(t));for(;t--;){let l=63&r[t];e+=l<36?l.toString(36):l<62?(l-26).toString(36).toUpperCase():l<63?"_":"-"}return e};export{l as customAlphabet,r as customRandom,n as nanoid,e as random,t as urlAlphabet};export default null;