git.iko.soy/purestack-dev/purescript-plum
on master help sign in
.gitignore+1
since splitsnapshots
unifiedsplit
@@ -8,3 +8,4 @@
8/.purs*
8/.purs*
9/.psa*
9/.psa*
10/.spago
10/.spago
11+plum/index.js
plum/index.jsdeleted−1467
@@ -1,1467 +0,0 @@
1−(() => {
2− // output/Data.Functor/foreign.js
3− var arrayMap = function(f) {
4− return function(arr) {
5− var l = arr.length;
6− var result = new Array(l);
7− for (var i = 0; i < l; i++) {
8− result[i] = f(arr[i]);
9− }
10− return result;
11− };
12− };
13−
14− // output/Data.Unit/foreign.js
15− var unit = void 0;
16−
17− // output/Data.Functor/index.js
18− var map = function(dict) {
19− return dict.map;
20− };
21− var functorArray = {
22− map: arrayMap
23− };
24−
25− // output/Control.Apply/index.js
26− var apply = function(dict) {
27− return dict.apply;
28− };
29−
30− // output/Control.Applicative/index.js
31− var pure = function(dict) {
32− return dict.pure;
33− };
34− var liftA1 = function(dictApplicative) {
35− var apply2 = apply(dictApplicative.Apply0());
36− var pure1 = pure(dictApplicative);
37− return function(f) {
38− return function(a) {
39− return apply2(pure1(f))(a);
40− };
41− };
42− };
43−
44− // output/Effect/foreign.js
45− var pureE = function(a) {
46− return function() {
47− return a;
48− };
49− };
50− var bindE = function(a) {
51− return function(f) {
52− return function() {
53− return f(a())();
54− };
55− };
56− };
57−
58− // output/Control.Bind/foreign.js
59− var arrayBind = typeof Array.prototype.flatMap === "function" ? function(arr) {
60− return function(f) {
61− return arr.flatMap(f);
62− };
63− } : function(arr) {
64− return function(f) {
65− var result = [];
66− var l = arr.length;
67− for (var i = 0; i < l; i++) {
68− var xs = f(arr[i]);
69− var k = xs.length;
70− for (var j = 0; j < k; j++) {
71− result.push(xs[j]);
72− }
73− }
74− return result;
75− };
76− };
77−
78− // output/Control.Bind/index.js
79− var bind = function(dict) {
80− return dict.bind;
81− };
82−
83− // output/Control.Monad/index.js
84− var ap = function(dictMonad) {
85− var bind3 = bind(dictMonad.Bind1());
86− var pure3 = pure(dictMonad.Applicative0());
87− return function(f) {
88− return function(a) {
89− return bind3(f)(function(f$prime) {
90− return bind3(a)(function(a$prime) {
91− return pure3(f$prime(a$prime));
92− });
93− });
94− };
95− };
96− };
97−
98− // output/Data.Semigroup/index.js
99− var append = function(dict) {
100− return dict.append;
101− };
102−
103− // output/Data.Monoid/index.js
104− var mempty = function(dict) {
105− return dict.mempty;
106− };
107−
108− // output/Effect/index.js
109− var $runtime_lazy = function(name14, moduleName, init) {
110− var state2 = 0;
111− var val;
112− return function(lineNumber) {
113− if (state2 === 2) return val;
114− if (state2 === 1) throw new ReferenceError(name14 + " was needed before it finished initializing (module " + moduleName + ", line " + lineNumber + ")", moduleName, lineNumber);
115− state2 = 1;
116− val = init();
117− state2 = 2;
118− return val;
119− };
120− };
121− var monadEffect = {
122− Applicative0: function() {
123− return applicativeEffect;
124− },
125− Bind1: function() {
126− return bindEffect;
127− }
128− };
129− var bindEffect = {
130− bind: bindE,
131− Apply0: function() {
132− return $lazy_applyEffect(0);
133− }
134− };
135− var applicativeEffect = {
136− pure: pureE,
137− Apply0: function() {
138− return $lazy_applyEffect(0);
139− }
140− };
141− var $lazy_functorEffect = /* @__PURE__ */ $runtime_lazy("functorEffect", "Effect", function() {
142− return {
143− map: liftA1(applicativeEffect)
144− };
145− });
146− var $lazy_applyEffect = /* @__PURE__ */ $runtime_lazy("applyEffect", "Effect", function() {
147− return {
148− apply: ap(monadEffect),
149− Functor0: function() {
150− return $lazy_functorEffect(0);
151− }
152− };
153− });
154− var functorEffect = /* @__PURE__ */ $lazy_functorEffect(20);
155−
156− // output/Data.Bounded/foreign.js
157− var topChar = String.fromCharCode(65535);
158− var bottomChar = String.fromCharCode(0);
159− var topNumber = Number.POSITIVE_INFINITY;
160− var bottomNumber = Number.NEGATIVE_INFINITY;
161−
162− // output/Data.Show/foreign.js
163− var showIntImpl = function(n) {
164− return n.toString();
165− };
166−
167− // output/Data.Show/index.js
168− var showInt = {
169− show: showIntImpl
170− };
171− var show = function(dict) {
172− return dict.show;
173− };
174−
175− // output/Data.Maybe/index.js
176− var Nothing = /* @__PURE__ */ function() {
177− function Nothing2() {
178− }
179− ;
180− Nothing2.value = new Nothing2();
181− return Nothing2;
182− }();
183− var Just = /* @__PURE__ */ function() {
184− function Just2(value0) {
185− this.value0 = value0;
186− }
187− ;
188− Just2.create = function(value0) {
189− return new Just2(value0);
190− };
191− return Just2;
192− }();
193−
194− // output/Effect.Ref/foreign.js
195− var _new = function(val) {
196− return function() {
197− return { value: val };
198− };
199− };
200− var read = function(ref) {
201− return function() {
202− return ref.value;
203− };
204− };
205− var write = function(val) {
206− return function(ref) {
207− return function() {
208− ref.value = val;
209− };
210− };
211− };
212−
213− // output/Effect.Ref/index.js
214− var $$new = _new;
215−
216− // output/Maquette/foreign.js
217− var NAMESPACE_W3 = "http://www.w3.org/";
218− var NAMESPACE_SVG = NAMESPACE_W3 + "2000/svg";
219− var NAMESPACE_XLINK = NAMESPACE_W3 + "1999/xlink";
220− var emptyArray = [];
221− var extend = function(base, overrides) {
222− var result = {};
223− Object.keys(base).forEach(function(key) {
224− result[key] = base[key];
225− });
226− if (overrides) {
227− Object.keys(overrides).forEach(function(key) {
228− result[key] = overrides[key];
229− });
230− }
231− return result;
232− };
233− var same = function(vnode1, vnode2) {
234− if (vnode1.vnodeSelector !== vnode2.vnodeSelector) {
235− return false;
236− }
237− if (vnode1.properties && vnode2.properties) {
238− if (vnode1.properties.key !== vnode2.properties.key) {
239− return false;
240− }
241− return vnode1.properties.bind === vnode2.properties.bind;
242− }
243− return !vnode1.properties && !vnode2.properties;
244− };
245− var checkStyleValue = function(styleValue) {
246− if (typeof styleValue !== "string") {
247− throw new Error("Style values must be strings");
248− }
249− };
250− var findIndexOfChild = function(children, sameAs, start2) {
251− if (sameAs.vnodeSelector !== "") {
252− for (var i = start2; i < children.length; i++) {
253− if (same(children[i], sameAs)) {
254− return i;
255− }
256− }
257− }
258− return -1;
259− };
260− var checkDistinguishable = function(childNodes, indexToCheck, parentVNode, operation) {
261− var childNode = childNodes[indexToCheck];
262− if (childNode.vnodeSelector === "") {
263− return;
264− }
265− var properties = childNode.properties;
266− var key = properties ? properties.key === void 0 ? properties.bind : properties.key : void 0;
267− if (!key) {
268− for (var i = 0; i < childNodes.length; i++) {
269− if (i !== indexToCheck) {
270− var node = childNodes[i];
271− if (same(node, childNode)) {
272− throw {
273− error: new Error(parentVNode.vnodeSelector + " had a " + childNode.vnodeSelector + " child " + (operation === "added" ? operation : "removed") + ", but there is now more than one. You must add unique key properties to make them distinguishable."),
274− parentNode: parentVNode,
275− childNode
276− };
277− }
278− }
279− }
280− }
281− };
282− var nodeAdded = function(vNode) {
283− if (vNode.properties) {
284− var enterAnimation = vNode.properties.enterAnimation;
285− if (enterAnimation) {
286− enterAnimation(vNode.domNode, vNode.properties);
287− }
288− }
289− };
290− var removedNodes = [];
291− var requestedIdleCallback = false;
292− var visitRemovedNode = function(node) {
293− (node.children || []).forEach(visitRemovedNode);
294− if (node.properties && node.properties.afterRemoved) {
295− node.properties.afterRemoved.apply(node.properties.bind || node.properties, [
296− node.domNode
297− ]);
298− }
299− };
300− var processPendingNodeRemovals = function() {
301− requestedIdleCallback = false;
302− removedNodes.forEach(visitRemovedNode);
303− removedNodes.length = 0;
304− };
305− var scheduleNodeRemoval = function(vNode) {
306− removedNodes.push(vNode);
307− if (!requestedIdleCallback) {
308− requestedIdleCallback = true;
309− if (typeof window !== "undefined" && "requestIdleCallback" in window) {
310− window.requestIdleCallback(processPendingNodeRemovals, { timeout: 16 });
311− } else {
312− setTimeout(processPendingNodeRemovals, 16);
313− }
314− }
315− };
316− var nodeToRemove = function(vNode) {
317− var domNode = vNode.domNode;
318− if (vNode.properties) {
319− var exitAnimation = vNode.properties.exitAnimation;
320− if (exitAnimation) {
321− domNode.style.pointerEvents = "none";
322− var removeDomNode = function() {
323− if (domNode.parentNode) {
324− domNode.parentNode.removeChild(domNode);
325− scheduleNodeRemoval(vNode);
326− }
327− };
328− exitAnimation(domNode, removeDomNode, vNode.properties);
329− return;
330− }
331− }
332− if (domNode.parentNode) {
333− domNode.parentNode.removeChild(domNode);
334− scheduleNodeRemoval(vNode);
335− }
336− };
337− var vnodeOnlyProps = [
338− "afterCreate",
339− "afterUpdate",
340− "afterRemoved",
341− "enterAnimation",
342− "exitAnimation",
343− "updateAnimation"
344− ];
345− function filterVNodeOnlyProps(name14) {
346− return !vnodeOnlyProps.includes(name14);
347− }
348− var setProperties = function(domNode, properties, projectionOptions) {
349− if (!properties) {
350− return;
351− }
352− var eventHandlerInterceptor = projectionOptions.eventHandlerInterceptor;
353− var propNames = Object.keys(properties).filter(filterVNodeOnlyProps);
354− var propCount = propNames.length;
355− for (var i = 0; i < propCount; i++) {
356− var propName = propNames[i];
357− var propValue = properties[propName];
358− if (propName === "className") {
359− throw new Error('Property "className" is not supported, use "class".');
360− } else if (propName === "class") {
361− toggleClasses(domNode, propValue, true);
362− } else if (propName === "classes") {
363− var classNames = Object.keys(propValue);
364− var classNameCount = classNames.length;
365− for (var j = 0; j < classNameCount; j++) {
366− var className = classNames[j];
367− if (propValue[className]) {
368− domNode.classList.add(className);
369− }
370− }
371− } else if (propName === "styles") {
372− var styleNames = Object.keys(propValue);
373− var styleCount = styleNames.length;
374− for (var j = 0; j < styleCount; j++) {
375− var styleName = styleNames[j];
376− var styleValue = propValue[styleName];
377− if (styleValue) {
378− checkStyleValue(styleValue);
379− projectionOptions.styleApplyer(domNode, styleName, styleValue);
380− }
381− }
382− } else if (propName === "on" && propValue) {
383− for (var _i = 0, _a = Object.entries(properties.on); _i < _a.length; _i++) {
384− var _b = _a[_i], key = _b[0], handler = _b[1];
385− var listener = typeof handler === "function" ? handler : handler.listener;
386− if (eventHandlerInterceptor) {
387− listener = eventHandlerInterceptor(key, listener, domNode, properties);
388− }
389− if (listener) {
390− domNode.addEventListener(key, listener, typeof handler === "function" ? void 0 : handler.options);
391− }
392− }
393− } else if (propName !== "key" && propValue !== null && propValue !== void 0) {
394− var type = typeof propValue;
395− if (type === "function") {
396− if (propName.lastIndexOf("on", 0) === 0) {
397− if (eventHandlerInterceptor) {
398− propValue = eventHandlerInterceptor(propName, propValue, domNode, properties);
399− }
400− }
401− domNode[propName] = propValue;
402− } else if (projectionOptions.namespace === NAMESPACE_SVG) {
403− if (propName === "href") {
404− domNode.setAttributeNS(NAMESPACE_XLINK, propName, propValue);
405− } else {
406− domNode.setAttribute(propName, propValue);
407− }
408− } else if (type === "string" && propName !== "value" && propName !== "innerHTML") {
409− domNode.setAttribute(propName, propValue);
410− } else {
411− domNode[propName] = propValue;
412− }
413− }
414− }
415− };
416− var addChildren = function(domNode, children, projectionOptions) {
417− if (!children) {
418− return;
419− }
420− for (var _i = 0, children_1 = children; _i < children_1.length; _i++) {
421− var child = children_1[_i];
422− createDom(child, domNode, void 0, projectionOptions);
423− }
424− };
425− var initPropertiesAndChildren = function(domNode, vnode, projectionOptions) {
426− addChildren(domNode, vnode.children, projectionOptions);
427− if (vnode.text) {
428− domNode.textContent = vnode.text;
429− }
430− setProperties(domNode, vnode.properties, projectionOptions);
431− if (vnode.properties && vnode.properties.afterCreate) {
432− vnode.properties.afterCreate.apply(vnode.properties.bind || vnode.properties, [
433− domNode,
434− projectionOptions,
435− vnode.vnodeSelector,
436− vnode.properties,
437− vnode.children
438− ]);
439− }
440− };
441− var createDom = function(vnode, parentNode, insertBefore, projectionOptions) {
442− var _a;
443− var domNode;
444− var start2 = 0;
445− var vnodeSelector = vnode.vnodeSelector;
446− var doc = parentNode.ownerDocument;
447− if (vnodeSelector === "") {
448− if (vnode.domNode) {
449− vnode.domNode.nodeValue = vnode.text;
450− } else {
451− domNode = vnode.domNode = doc.createTextNode(vnode.text);
452− if (insertBefore !== void 0) {
453− parentNode.insertBefore(domNode, insertBefore);
454− } else {
455− parentNode.appendChild(domNode);
456− }
457− }
458− } else {
459− for (var i = 0; i <= vnodeSelector.length; ++i) {
460− var c = vnodeSelector.charAt(i);
461− if (i === vnodeSelector.length || c === "." || c === "#") {
462− var type = vnodeSelector.charAt(start2 - 1);
463− var found = vnodeSelector.slice(start2, i);
464− if (type === ".") {
465− domNode.classList.add(found);
466− } else if (type === "#") {
467− domNode.id = found;
468− } else {
469− if (found === "svg") {
470− projectionOptions = extend(projectionOptions, {
471− namespace: NAMESPACE_SVG
472− });
473− }
474− if (projectionOptions.namespace !== void 0) {
475− domNode = vnode.domNode = doc.createElementNS(projectionOptions.namespace, found);
476− } else {
477− domNode = vnode.domNode = vnode.domNode || (((_a = vnode.properties) === null || _a === void 0 ? void 0 : _a.is) ? doc.createElement(found, { is: vnode.properties.is }) : doc.createElement(found));
478− if (found === "input" && vnode.properties && vnode.properties.type !== void 0) {
479− domNode.setAttribute("type", vnode.properties.type);
480− }
481− }
482− if (insertBefore !== void 0) {
483− parentNode.insertBefore(domNode, insertBefore);
484− } else if (domNode.parentNode !== parentNode) {
485− parentNode.appendChild(domNode);
486− }
487− }
488− start2 = i + 1;
489− }
490− }
491− initPropertiesAndChildren(domNode, vnode, projectionOptions);
492− }
493− };
494− var updateDom;
495− var toggleClasses = function(domNode, classes, on2) {
496− if (!classes) {
497− return;
498− }
499− classes.split(" ").forEach(function(classToToggle) {
500− if (classToToggle) {
501− domNode.classList.toggle(classToToggle, on2);
502− }
503− });
504− };
505− var updateProperties = function(domNode, previousProperties, properties, projectionOptions) {
506− if (!properties) {
507− return;
508− }
509− var propertiesUpdated = false;
510− var propNames = Object.keys(properties).filter(filterVNodeOnlyProps);
511− var propCount = propNames.length;
512− for (var i = 0; i < propCount; i++) {
513− var propName = propNames[i];
514− var propValue = properties[propName];
515− var previousValue = previousProperties[propName];
516− if (propName === "class") {
517− if (previousValue !== propValue) {
518− toggleClasses(domNode, previousValue, false);
519− toggleClasses(domNode, propValue, true);
520− }
521− } else if (propName === "classes") {
522− var classList = domNode.classList;
523− var classNames = Object.keys(propValue);
524− var classNameCount = classNames.length;
525− for (var j = 0; j < classNameCount; j++) {
526− var className = classNames[j];
527− var on2 = !!propValue[className];
528− var previousOn = !!previousValue[className];
529− if (on2 === previousOn) {
530− continue;
531− }
532− propertiesUpdated = true;
533− if (on2) {
534− classList.add(className);
535− } else {
536− classList.remove(className);
537− }
538− }
539− } else if (propName === "styles") {
540− var styleNames = Object.keys(propValue);
541− var styleCount = styleNames.length;
542− for (var j = 0; j < styleCount; j++) {
543− var styleName = styleNames[j];
544− var newStyleValue = propValue[styleName];
545− var oldStyleValue = previousValue[styleName];
546− if (newStyleValue === oldStyleValue) {
547− continue;
548− }
549− propertiesUpdated = true;
550− if (newStyleValue) {
551− checkStyleValue(newStyleValue);
552− projectionOptions.styleApplyer(domNode, styleName, newStyleValue);
553− } else {
554− projectionOptions.styleApplyer(domNode, styleName, "");
555− }
556− }
557− } else {
558− if (!propValue && typeof previousValue === "string") {
559− propValue = "";
560− }
561− if (propName === "value") {
562− var domValue = domNode[propName];
563− if (domValue !== propValue && // The 'value' in the DOM tree !== newValue
564− propValue !== previousValue) {
565− domNode[propName] = propValue;
566− }
567− if (propValue !== previousValue) {
568− propertiesUpdated = true;
569− }
570− } else if (propValue !== previousValue) {
571− var type = typeof propValue;
572− if (type !== "function" || !projectionOptions.eventHandlerInterceptor) {
573− if (projectionOptions.namespace === NAMESPACE_SVG) {
574− if (propName === "href") {
575− domNode.setAttributeNS(NAMESPACE_XLINK, propName, propValue);
576− } else {
577− domNode.setAttribute(propName, propValue);
578− }
579− } else if (type === "string" && propName !== "innerHTML") {
580− if (propName === "role" && propValue === "") {
581− domNode.removeAttribute(propName);
582− } else {
583− domNode.setAttribute(propName, propValue);
584− }
585− } else if (domNode[propName] !== propValue) {
586− domNode[propName] = propValue;
587− }
588− propertiesUpdated = true;
589− }
590− }
591− }
592− }
593− return propertiesUpdated;
594− };
595− var updateChildren = function(vnode, domNode, oldChildren, newChildren, projectionOptions) {
596− if (oldChildren === newChildren) {
597− return false;
598− }
599− oldChildren = oldChildren || emptyArray;
600− newChildren = newChildren || emptyArray;
601− var oldChildrenLength = oldChildren.length;
602− var newChildrenLength = newChildren.length;
603− var oldIndex = 0;
604− var newIndex = 0;
605− var i;
606− var textUpdated = false;
607− while (newIndex < newChildrenLength) {
608− var oldChild = oldIndex < oldChildrenLength ? oldChildren[oldIndex] : void 0;
609− var newChild = newChildren[newIndex];
610− if (oldChild !== void 0 && same(oldChild, newChild)) {
611− textUpdated = updateDom(oldChild, newChild, projectionOptions, domNode, oldChildren) || textUpdated;
612− oldIndex++;
613− } else {
614− var findOldIndex = findIndexOfChild(oldChildren, newChild, oldIndex + 1);
615− if (findOldIndex >= 0) {
616− for (i = oldIndex; i < findOldIndex; i++) {
617− nodeToRemove(oldChildren[i]);
618− checkDistinguishable(oldChildren, i, vnode, "removed");
619− }
620− textUpdated = updateDom(oldChildren[findOldIndex], newChild, projectionOptions, domNode, oldChildren) || textUpdated;
621− oldIndex = findOldIndex + 1;
622− } else {
623− createDom(newChild, domNode, oldIndex < oldChildrenLength ? oldChildren[oldIndex].domNode : void 0, projectionOptions);
624− nodeAdded(newChild);
625− checkDistinguishable(newChildren, newIndex, vnode, "added");
626− }
627− }
628− newIndex++;
629− }
630− if (oldChildrenLength > oldIndex) {
631− for (i = oldIndex; i < oldChildrenLength; i++) {
632− nodeToRemove(oldChildren[i]);
633− checkDistinguishable(oldChildren, i, vnode, "removed");
634− }
635− }
636− return textUpdated;
637− };
638− updateDom = function(previous, vnode, projectionOptions, parentNode, oldChildren) {
639− var domNode = previous.domNode;
640− var textUpdated = false;
641− if (previous === vnode) {
642− return false;
643− }
644− var updated = false;
645− if (vnode.vnodeSelector === "") {
646− if (vnode.text !== previous.text) {
647− var newTextNode = domNode.ownerDocument.createTextNode(vnode.text);
648− try {
649− parentNode.replaceChild(newTextNode, domNode);
650− } catch (e) {
651− parentNode.replaceChild(newTextNode, parentNode.childNodes[oldChildren.indexOf(previous)]);
652− }
653− vnode.domNode = newTextNode;
654− textUpdated = true;
655− return textUpdated;
656− }
657− vnode.domNode = domNode;
658− } else {
659− if (vnode.vnodeSelector.lastIndexOf("svg", 0) === 0) {
660− projectionOptions = extend(projectionOptions, {
661− namespace: NAMESPACE_SVG
662− });
663− }
664− if (previous.text !== vnode.text) {
665− updated = true;
666− if (vnode.text === void 0) {
667− domNode.removeChild(domNode.firstChild);
668− } else {
669− domNode.textContent = vnode.text;
670− }
671− }
672− vnode.domNode = domNode;
673− updated = updateChildren(vnode, domNode, previous.children, vnode.children, projectionOptions) || updated;
674− updated = updateProperties(domNode, previous.properties, vnode.properties, projectionOptions) || updated;
675− if (vnode.properties && vnode.properties.afterUpdate) {
676− vnode.properties.afterUpdate.apply(vnode.properties.bind || vnode.properties, [
677− domNode,
678− projectionOptions,
679− vnode.vnodeSelector,
680− vnode.properties,
681− vnode.children
682− ]);
683− }
684− }
685− if (updated && vnode.properties && vnode.properties.updateAnimation) {
686− vnode.properties.updateAnimation(domNode, vnode.properties, previous.properties);
687− }
688− return textUpdated;
689− };
690− var createProjection = function(vnode, projectionOptions) {
691− return {
692− getLastRender: function() {
693− return vnode;
694− },
695− update: function(updatedVnode) {
696− if (vnode.vnodeSelector !== updatedVnode.vnodeSelector) {
697− throw new Error("The selector for the root VNode may not be changed. (consider using dom.merge and add one extra level to the virtual DOM)");
698− }
699− var previousVNode = vnode;
700− vnode = updatedVnode;
701− updateDom(previousVNode, updatedVnode, projectionOptions, previousVNode.domNode.parentNode, [previousVNode]);
702− },
703− domNode: vnode.domNode
704− };
705− };
706− var DEFAULT_PROJECTION_OPTIONS = {
707− namespace: void 0,
708− performanceLogger: function() {
709− return void 0;
710− },
711− eventHandlerInterceptor: void 0,
712− styleApplyer: function(domNode, styleName, value12) {
713− if (styleName.charAt(0) === "-") {
714− domNode.style.setProperty(styleName, value12);
715− } else {
716− domNode.style[styleName] = value12;
717− }
718− }
719− };
720− var applyDefaultProjectionOptions = function(projectorOptions) {
721− return extend(DEFAULT_PROJECTION_OPTIONS, projectorOptions);
722− };
723− var dom = {
724− /**
725− * Creates a real DOM tree from `vnode`. The [[Projection]] object returned will contain the resulting DOM Node in
726− * its [[Projection.domNode|domNode]] property.
727− * This is a low-level method. Users will typically use a [[Projector]] instead.
728− * @param vnode - The root of the virtual DOM tree that was created using the [[h]] function. NOTE: [[VNode]]
729− * objects may only be rendered once.
730− * @param projectionOptions - Options to be used to create and update the projection.
731− * @returns The [[Projection]] which also contains the DOM Node that was created.
732− */
733− create: function(vnode, projectionOptions) {
734− projectionOptions = applyDefaultProjectionOptions(projectionOptions);
735− createDom(vnode, document.createElement("div"), void 0, projectionOptions);
736− return createProjection(vnode, projectionOptions);
737− },
738− /**
739− * Appends a new child node to the DOM which is generated from a [[VNode]].
740− * This is a low-level method. Users will typically use a [[Projector]] instead.
741− * @param parentNode - The parent node for the new child node.
742− * @param vnode - The root of the virtual DOM tree that was created using the [[h]] function. NOTE: [[VNode]]
743− * objects may only be rendered once.
744− * @param projectionOptions - Options to be used to create and update the [[Projection]].
745− * @returns The [[Projection]] that was created.
746− */
747− append: function(parentNode, vnode, projectionOptions) {
748− projectionOptions = applyDefaultProjectionOptions(projectionOptions);
749− createDom(vnode, parentNode, void 0, projectionOptions);
750− return createProjection(vnode, projectionOptions);
751− },
752− /**
753− * Inserts a new DOM node which is generated from a [[VNode]].
754− * This is a low-level method. Users wil typically use a [[Projector]] instead.
755− * @param beforeNode - The node that the DOM Node is inserted before.
756− * @param vnode - The root of the virtual DOM tree that was created using the [[h]] function.
757− * NOTE: [[VNode]] objects may only be rendered once.
758− * @param projectionOptions - Options to be used to create and update the projection, see [[createProjector]].
759− * @returns The [[Projection]] that was created.
760− */
761− insertBefore: function(beforeNode, vnode, projectionOptions) {
762− projectionOptions = applyDefaultProjectionOptions(projectionOptions);
763− createDom(vnode, beforeNode.parentNode, beforeNode, projectionOptions);
764− return createProjection(vnode, projectionOptions);
765− },
766− /**
767− * Merges a new DOM node which is generated from a [[VNode]] with an existing DOM Node.
768− * This means that the virtual DOM and the real DOM will have one overlapping element.
769− * Therefore the selector for the root [[VNode]] will be ignored, but its properties and children will be applied to the Element provided.
770− * This is a low-level method. Users wil typically use a [[Projector]] instead.
771− * @param element - The existing element to adopt as the root of the new virtual DOM. Existing attributes and child nodes are preserved.
772− * @param vnode - The root of the virtual DOM tree that was created using the [[h]] function. NOTE: [[VNode]] objects
773− * may only be rendered once.
774− * @param projectionOptions - Options to be used to create and update the projection, see [[createProjector]].
775− * @returns The [[Projection]] that was created.
776− */
777− merge: function(element, vnode, projectionOptions) {
778− projectionOptions = applyDefaultProjectionOptions(projectionOptions);
779− vnode.domNode = element;
780− initPropertiesAndChildren(element, vnode, projectionOptions);
781− return createProjection(vnode, projectionOptions);
782− },
783− /**
784− * Replaces an existing DOM node with a node generated from a [[VNode]].
785− * This is a low-level method. Users will typically use a [[Projector]] instead.
786− * @param element - The node for the [[VNode]] to replace.
787− * @param vnode - The root of the virtual DOM tree that was created using the [[h]] function. NOTE: [[VNode]]
788− * objects may only be rendered once.
789− * @param projectionOptions - Options to be used to create and update the [[Projection]].
790− * @returns The [[Projection]] that was created.
791− */
792− replace: function(element, vnode, projectionOptions) {
793− projectionOptions = applyDefaultProjectionOptions(projectionOptions);
794− createDom(vnode, element.parentNode, element, projectionOptions);
795− element.parentNode.removeChild(element);
796− return createProjection(vnode, projectionOptions);
797− }
798− };
799− var toTextVNode = function(data) {
800− return {
801− vnodeSelector: "",
802− properties: void 0,
803− children: void 0,
804− text: data.toString(),
805− domNode: null
806− };
807− };
808− var appendChildren = function(parentSelector, insertions, main2) {
809− for (var i = 0, length_1 = insertions.length; i < length_1; i++) {
810− var item = insertions[i];
811− if (Array.isArray(item)) {
812− appendChildren(parentSelector, item, main2);
813− } else {
814− if (item !== null && item !== void 0 && item !== false) {
815− if (typeof item === "string") {
816− item = toTextVNode(item);
817− }
818− main2.push(item);
819− }
820− }
821− }
822− };
823− function h(selector, properties, children) {
824− if (Array.isArray(properties)) {
825− children = properties;
826− properties = void 0;
827− } else if (properties && (typeof properties === "string" || properties.vnodeSelector) || children && (typeof children === "string" || children.vnodeSelector)) {
828− throw new Error("h called with invalid arguments");
829− }
830− var text5;
831− var flattenedChildren;
832− if (children && children.length === 1 && typeof children[0] === "string") {
833− text5 = children[0];
834− } else if (children) {
835− flattenedChildren = [];
836− appendChildren(selector, children, flattenedChildren);
837− if (flattenedChildren.length === 0) {
838− flattenedChildren = void 0;
839− }
840− }
841− return {
842− vnodeSelector: selector,
843− properties,
844− children: flattenedChildren,
845− text: text5 === "" ? void 0 : text5,
846− domNode: null
847− };
848− }
849− var createParentNodePath = function(node, rootNode) {
850− var parentNodePath = [];
851− while (node && node !== rootNode) {
852− parentNodePath.push(node);
853− node = node.parentNode;
854− }
855− return parentNodePath;
856− };
857− var find;
858− if (Array.prototype.find) {
859− find = function(items, predicate) {
860− return items.find(predicate);
861− };
862− } else {
863− find = function(items, predicate) {
864− return items.filter(predicate)[0];
865− };
866− }
867− var findVNodeByParentNodePath = function(vnode, parentNodePath) {
868− var result = vnode;
869− parentNodePath.forEach(function(node) {
870− result = result && result.children ? find(result.children, function(child) {
871− return child.domNode === node;
872− }) : void 0;
873− });
874− return result;
875− };
876− var createEventHandlerInterceptor = function(projector, getProjection, performanceLogger) {
877− return function(propertyName, eventHandler, domNode, properties) {
878− return modifiedEventHandler;
879− };
880− function modifiedEventHandler(evt) {
881− var _a, _b;
882− performanceLogger("domEvent", evt);
883− var projection = getProjection();
884− var parentNodePath = createParentNodePath(evt.currentTarget, projection.domNode);
885− parentNodePath.reverse();
886− var matchingVNode = findVNodeByParentNodePath(projection.getLastRender(), parentNodePath);
887− projector.scheduleRender();
888− var result;
889− if (matchingVNode) {
890− var listener = (_b = (_a = matchingVNode.properties["on" + evt.type]) !== null && _a !== void 0 ? _a : matchingVNode.properties.on[evt.type].listener) !== null && _b !== void 0 ? _b : matchingVNode.properties.on[evt.type];
891− result = listener.apply(matchingVNode.properties.bind || this, arguments);
892− }
893− performanceLogger("domEventProcessed", evt);
894− return result;
895− }
896− };
897− var createProjector = function(projectorOptions) {
898− var projector;
899− var projectionOptions = applyDefaultProjectionOptions(projectorOptions);
900− var performanceLogger = projectionOptions.performanceLogger;
901− var renderCompleted = true;
902− var scheduled;
903− var stopped = false;
904− var projections = [];
905− var renderFunctions = [];
906− var addProjection = function(domFunction, node, renderFunction) {
907− var projection;
908− var getProjection = function() {
909− return projection;
910− };
911− projectionOptions.eventHandlerInterceptor = createEventHandlerInterceptor(projector, getProjection, performanceLogger);
912− projection = domFunction(node, renderFunction(), projectionOptions);
913− projections.push(projection);
914− renderFunctions.push(renderFunction);
915− };
916− var doRender = function() {
917− scheduled = void 0;
918− if (!renderCompleted) {
919− return;
920− }
921− renderCompleted = false;
922− performanceLogger("renderStart", void 0);
923− for (var i = 0; i < projections.length; i++) {
924− var updatedVnode = renderFunctions[i]();
925− performanceLogger("rendered", void 0);
926− projections[i].update(updatedVnode);
927− performanceLogger("patched", void 0);
928− }
929− performanceLogger("renderDone", void 0);
930− renderCompleted = true;
931− };
932− projector = {
933− renderNow: doRender,
934− scheduleRender: function() {
935− if (!scheduled && !stopped) {
936− scheduled = requestAnimationFrame(doRender);
937− }
938− },
939− stop: function() {
940− if (scheduled) {
941− cancelAnimationFrame(scheduled);
942− scheduled = void 0;
943− }
944− stopped = true;
945− },
946− resume: function() {
947− stopped = false;
948− renderCompleted = true;
949− projector.scheduleRender();
950− },
951− append: function(parentNode, renderFunction) {
952− addProjection(dom.append, parentNode, renderFunction);
953− },
954− insertBefore: function(beforeNode, renderFunction) {
955− addProjection(dom.insertBefore, beforeNode, renderFunction);
956− },
957− merge: function(domNode, renderFunction) {
958− addProjection(dom.merge, domNode, renderFunction);
959− },
960− replace: function(domNode, renderFunction) {
961− addProjection(dom.replace, domNode, renderFunction);
962− },
963− detach: function(renderFunction) {
964− for (var i = 0; i < renderFunctions.length; i++) {
965− if (renderFunctions[i] === renderFunction) {
966− renderFunctions.splice(i, 1);
967− return projections.splice(i, 1)[0];
968− }
969− }
970− throw new Error("renderFunction was not found");
971− }
972− };
973− return projector;
974− };
975− function _h(selector) {
976− return function(properties) {
977− return function(children) {
978− return h(selector, properties, children);
979− };
980− };
981− }
982− function replace(projector) {
983− return function(el) {
984− return function(render) {
985− return function() {
986− projector.replace(el, render);
987− };
988− };
989− };
990− }
991−
992− // output/Unsafe.Coerce/foreign.js
993− var unsafeCoerce2 = function(x) {
994− return x;
995− };
996−
997− // output/Maquette/index.js
998− var string = unsafeCoerce2;
999− var h2 = _h;
1000−
1001− // output/Data.Array/foreign.js
1002− var replicateFill = function(count, value12) {
1003− if (count < 1) {
1004− return [];
1005− }
1006− var result = new Array(count);
1007− return result.fill(value12);
1008− };
1009− var replicatePolyfill = function(count, value12) {
1010− var result = [];
1011− var n = 0;
1012− for (var i = 0; i < count; i++) {
1013− result[n++] = value12;
1014− }
1015− return result;
1016− };
1017− var replicateImpl = typeof Array.prototype.fill === "function" ? replicateFill : replicatePolyfill;
1018−
1019− // output/Control.Monad.ST.Internal/foreign.js
1020− var map_ = function(f) {
1021− return function(a) {
1022− return function() {
1023− return f(a());
1024− };
1025− };
1026− };
1027− var pure_ = function(a) {
1028− return function() {
1029− return a;
1030− };
1031− };
1032− var bind_ = function(a) {
1033− return function(f) {
1034− return function() {
1035− return f(a())();
1036− };
1037− };
1038− };
1039−
1040− // output/Control.Monad.ST.Internal/index.js
1041− var $runtime_lazy2 = function(name14, moduleName, init) {
1042− var state2 = 0;
1043− var val;
1044− return function(lineNumber) {
1045− if (state2 === 2) return val;
1046− if (state2 === 1) throw new ReferenceError(name14 + " was needed before it finished initializing (module " + moduleName + ", line " + lineNumber + ")", moduleName, lineNumber);
1047− state2 = 1;
1048− val = init();
1049− state2 = 2;
1050− return val;
1051− };
1052− };
1053− var functorST = {
1054− map: map_
1055− };
1056− var monadST = {
1057− Applicative0: function() {
1058− return applicativeST;
1059− },
1060− Bind1: function() {
1061− return bindST;
1062− }
1063− };
1064− var bindST = {
1065− bind: bind_,
1066− Apply0: function() {
1067− return $lazy_applyST(0);
1068− }
1069− };
1070− var applicativeST = {
1071− pure: pure_,
1072− Apply0: function() {
1073− return $lazy_applyST(0);
1074− }
1075− };
1076− var $lazy_applyST = /* @__PURE__ */ $runtime_lazy2("applyST", "Control.Monad.ST.Internal", function() {
1077− return {
1078− apply: ap(monadST),
1079− Functor0: function() {
1080− return functorST;
1081− }
1082− };
1083− });
1084−
1085− // output/Data.Foldable/foreign.js
1086− var foldrArray = function(f) {
1087− return function(init) {
1088− return function(xs) {
1089− var acc = init;
1090− var len = xs.length;
1091− for (var i = len - 1; i >= 0; i--) {
1092− acc = f(xs[i])(acc);
1093− }
1094− return acc;
1095− };
1096− };
1097− };
1098− var foldlArray = function(f) {
1099− return function(init) {
1100− return function(xs) {
1101− var acc = init;
1102− var len = xs.length;
1103− for (var i = 0; i < len; i++) {
1104− acc = f(acc)(xs[i]);
1105− }
1106− return acc;
1107− };
1108− };
1109− };
1110−
1111− // output/Data.Foldable/index.js
1112− var foldr = function(dict) {
1113− return dict.foldr;
1114− };
1115− var foldMapDefaultR = function(dictFoldable) {
1116− var foldr2 = foldr(dictFoldable);
1117− return function(dictMonoid) {
1118− var append2 = append(dictMonoid.Semigroup0());
1119− var mempty2 = mempty(dictMonoid);
1120− return function(f) {
1121− return foldr2(function(x) {
1122− return function(acc) {
1123− return append2(f(x))(acc);
1124− };
1125− })(mempty2);
1126− };
1127− };
1128− };
1129− var foldableArray = {
1130− foldr: foldrArray,
1131− foldl: foldlArray,
1132− foldMap: function(dictMonoid) {
1133− return foldMapDefaultR(foldableArray)(dictMonoid);
1134− }
1135− };
1136− var foldMap = function(dict) {
1137− return dict.foldMap;
1138− };
1139−
1140− // output/Data.Array/index.js
1141− var foldMap1 = /* @__PURE__ */ foldMap(foldableArray);
1142− var foldMap2 = function(dictMonoid) {
1143− return foldMap1(dictMonoid);
1144− };
1145−
1146− // output/Foreign.Object/foreign.js
1147− function _copyST(m) {
1148− return function() {
1149− var r = {};
1150− for (var k in m) {
1151− if (hasOwnProperty.call(m, k)) {
1152− r[k] = m[k];
1153− }
1154− }
1155− return r;
1156− };
1157− }
1158− var empty2 = {};
1159− function runST(f) {
1160− return f();
1161− }
1162− function _foldM(bind3) {
1163− return function(f) {
1164− return function(mz) {
1165− return function(m) {
1166− var acc = mz;
1167− function g(k2) {
1168− return function(z) {
1169− return f(z)(k2)(m[k2]);
1170− };
1171− }
1172− for (var k in m) {
1173− if (hasOwnProperty.call(m, k)) {
1174− acc = bind3(acc)(g(k));
1175− }
1176− }
1177− return acc;
1178− };
1179− };
1180− };
1181− }
1182− function toArrayWithKey(f) {
1183− return function(m) {
1184− var r = [];
1185− for (var k in m) {
1186− if (hasOwnProperty.call(m, k)) {
1187− r.push(f(k)(m[k]));
1188− }
1189− }
1190− return r;
1191− };
1192− }
1193− var keys = Object.keys || toArrayWithKey(function(k) {
1194− return function() {
1195− return k;
1196− };
1197− });
1198−
1199− // output/Foreign.Object.ST/foreign.js
1200− function poke2(k) {
1201− return function(v) {
1202− return function(m) {
1203− return function() {
1204− m[k] = v;
1205− return m;
1206− };
1207− };
1208− };
1209− }
1210−
1211− // output/Foreign.Object/index.js
1212− var thawST = _copyST;
1213− var mutate = function(f) {
1214− return function(m) {
1215− return runST(function __do() {
1216− var s2 = thawST(m)();
1217− f(s2)();
1218− return s2;
1219− });
1220− };
1221− };
1222− var insert = function(k) {
1223− return function(v) {
1224− return mutate(poke2(k)(v));
1225− };
1226− };
1227− var fromHomogeneous = function() {
1228− return unsafeCoerce2;
1229− };
1230− var foldM = function(dictMonad) {
1231− var bind1 = bind(dictMonad.Bind1());
1232− var pure1 = pure(dictMonad.Applicative0());
1233− return function(f) {
1234− return function(z) {
1235− return _foldM(bind1)(f)(pure1(z));
1236− };
1237− };
1238− };
1239− var foldM1 = /* @__PURE__ */ foldM(monadST);
1240− var union = function(m) {
1241− return mutate(function(s2) {
1242− return foldM1(function(s$prime) {
1243− return function(k) {
1244− return function(v) {
1245− return poke2(k)(v)(s$prime);
1246− };
1247− };
1248− })(s2)(m);
1249− });
1250− };
1251−
1252− // output/Plum.View/index.js
1253− var fromHomogeneous2 = /* @__PURE__ */ fromHomogeneous();
1254− var show2 = /* @__PURE__ */ show(showInt);
1255− var map2 = /* @__PURE__ */ map(functorArray);
1256− var Flexbox = /* @__PURE__ */ function() {
1257− function Flexbox2() {
1258− }
1259− ;
1260− Flexbox2.value = new Flexbox2();
1261− return Flexbox2;
1262− }();
1263− var Spacing = /* @__PURE__ */ function() {
1264− function Spacing2(value0, value1) {
1265− this.value0 = value0;
1266− this.value1 = value1;
1267− }
1268− ;
1269− Spacing2.create = function(value0) {
1270− return function(value1) {
1271− return new Spacing2(value0, value1);
1272− };
1273− };
1274− return Spacing2;
1275− }();
1276− var semigroupRenderedAttribut = {
1277− append: function(v1) {
1278− return function(v2) {
1279− return {
1280− styles: union(v1.styles)(v2.styles)
1281− };
1282− };
1283− }
1284− };
1285− var monoidRenderedAttribute = {
1286− mempty: {
1287− styles: empty2
1288− },
1289− Semigroup0: function() {
1290− return semigroupRenderedAttribut;
1291− }
1292− };
1293− var foldMap3 = /* @__PURE__ */ foldMap2(monoidRenderedAttribute);
1294− var withStyles = function() {
1295− return function(v1) {
1296− return function(styles) {
1297− return {
1298− styles: union(v1.styles)(fromHomogeneous2(styles))
1299− };
1300− };
1301− };
1302− };
1303− var withStyles1 = /* @__PURE__ */ withStyles();
1304− var unView = function(v1) {
1305− return v1;
1306− };
1307− var spacing = function(x) {
1308− return new Spacing(x, x);
1309− };
1310− var s = function(x) {
1311− return function(v1) {
1312− return string(x);
1313− };
1314− };
1315− var renderAttribute = function(_ctx) {
1316− return function(attr) {
1317− return {
1318− styles: insert("gap")(show2(attr.value0) + ("px " + (show2(attr.value1) + "px")))(empty2)
1319− };
1320− };
1321− };
1322− var renderAttributes = function(ctx) {
1323− return foldMap3(renderAttribute(ctx));
1324− };
1325− var renderWithStyles = function() {
1326− return function(ctx) {
1327− return function(attrs) {
1328− return function(styles) {
1329− return withStyles1(renderAttributes(ctx)(attrs))(styles);
1330− };
1331− };
1332− };
1333− };
1334− var renderWithStyles1 = /* @__PURE__ */ renderWithStyles();
1335− var button = function(v1) {
1336− return function(v2) {
1337− return function(fire) {
1338− return h2("div")({
1339− onclick: fire(v2.onPress)
1340− })([unView(v2.view)(fire)]);
1341− };
1342− };
1343− };
1344− var _v = function(el) {
1345− return function(attr) {
1346− return function(children) {
1347− return function(fire) {
1348− return h2(el)(attr)(map2(function(v1) {
1349− return v1(fire);
1350− })(children));
1351− };
1352− };
1353− };
1354− };
1355− var row = function(attrs) {
1356− return function(children) {
1357− return _v("div")(renderWithStyles1(Flexbox.value)(attrs)({
1358− display: "flex",
1359− "flex-direction": "row"
1360− }))(children);
1361− };
1362− };
1363−
1364− // output/Web.DOM.NonElementParentNode/foreign.js
1365− function _getElementById(id) {
1366− return function(node) {
1367− return function() {
1368− return node.getElementById(id);
1369− };
1370− };
1371− }
1372−
1373− // output/Data.Nullable/foreign.js
1374− function nullable(a, r, f) {
1375− return a == null ? r : f(a);
1376− }
1377−
1378− // output/Data.Nullable/index.js
1379− var toMaybe = function(n) {
1380− return nullable(n, Nothing.value, Just.create);
1381− };
1382−
1383− // output/Web.DOM.NonElementParentNode/index.js
1384− var map3 = /* @__PURE__ */ map(functorEffect);
1385− var getElementById = function(eid) {
1386− var $2 = map3(toMaybe);
1387− var $3 = _getElementById(eid);
1388− return function($4) {
1389− return $2($3($4));
1390− };
1391− };
1392−
1393− // output/Web.HTML/foreign.js
1394− var windowImpl = function() {
1395− return window;
1396− };
1397−
1398− // output/Web.HTML.HTMLDocument/index.js
1399− var toNonElementParentNode = unsafeCoerce2;
1400−
1401− // output/Web.HTML.Window/foreign.js
1402− function document2(window2) {
1403− return function() {
1404− return window2.document;
1405− };
1406− }
1407−
1408− // output/Plum/index.js
1409− var bind2 = /* @__PURE__ */ bind(bindEffect);
1410− var run3 = function(id) {
1411− return function(plum2) {
1412− return function __do() {
1413− var modelRef = bind2(plum2.init)($$new)();
1414− var v = bind2(bind2(windowImpl)(document2))(function() {
1415− var $6 = getElementById(id);
1416− return function($7) {
1417− return $6(toNonElementParentNode($7));
1418− };
1419− }())();
1420− if (v instanceof Just) {
1421− var projector = createProjector();
1422− return replace(projector)(v.value0)(function __do2() {
1423− var model = read(modelRef)();
1424− return unView(plum2.view(model))(function(msg) {
1425− return function __do3() {
1426− var m = read(modelRef)();
1427− var m_ = plum2.update(msg)(m)();
1428− return write(m_)(modelRef)();
1429− };
1430− });
1431− })();
1432− }
1433− ;
1434− if (v instanceof Nothing) {
1435− return unit;
1436− }
1437− ;
1438− throw new Error("Failed pattern match at Plum (line 24, column 92 - line 36, column 25): " + [v.constructor.name]);
1439− };
1440− };
1441− };
1442−
1443− // output/Main/index.js
1444− var pure2 = /* @__PURE__ */ pure(applicativeEffect);
1445− var plum = {
1446− init: /* @__PURE__ */ pure2({
1447− text: "Test"
1448− }),
1449− view: function(model) {
1450− return row([spacing(16)])([s(model.text), button([])({
1451− onPress: unit,
1452− view: s("Button")
1453− })]);
1454− },
1455− update: function(msg) {
1456− return function(model) {
1457− return pure2({
1458− text: "Button pressed"
1459− });
1460− };
1461− }
1462− };
1463− var main = /* @__PURE__ */ run3("plum")(plum);
1464−
1465− // <stdin>
1466− main();
1467−})();
plum/spago.dhall+10
@@ -4,17 +4,27 @@
4 , "console"
4 , "console"
5 , "debug"
5 , "debug"
6 , "effect"
6 , "effect"
7+ , "foldable-traversable"
7 , "foreign-object"
8 , "foreign-object"
9+ , "functions"
10+ , "integers"
11+ , "literals"
8 , "maybe"
12 , "maybe"
9 , "numbers"
13 , "numbers"
10 , "prelude"
14 , "prelude"
15+ , "record"
11 , "refs"
16 , "refs"
17+ , "strings"
12 , "strings-extra"
18 , "strings-extra"
19+ , "transformers"
20+ , "tuples"
13 , "typelevel-prelude"
21 , "typelevel-prelude"
14 , "unsafe-coerce"
22 , "unsafe-coerce"
15 , "untagged-union"
23 , "untagged-union"
16 , "web-dom"
24 , "web-dom"
25+ , "web-events"
17 , "web-html"
26 , "web-html"
27+ , "web-uievents"
18 ]
28 ]
19, packages = ../packages.dhall
29, packages = ../packages.dhall
20, sources = [ "src/**/*.purs", "test/**/*.purs" ]
30, sources = [ "src/**/*.purs", "test/**/*.purs" ]
plum/src/Main.purs+44−19
@@ -1,34 +1,59 @@
1module Main where
1module Main where
2
2
3+import Plum.View
3import Prelude
4import Prelude
4−import Web.HTML
5
5
6−import Data.Maybe (Maybe(..))
7import Effect (Effect)
6import Effect (Effect)
8−import Effect.Console (log)
9−import Maquette (createProjector, h, replace, scheduleRender, string)
10import Plum as Plum
7import Plum as Plum
11−import Plum.View (button, s)
12−import Plum.View as V
13−import Web.DOM.NonElementParentNode as Web
14−import Web.HTML as Web
15−import Web.HTML.HTMLDocument as Web
16−import Web.HTML.Window as Web
17
8
18main :: Effect Unit
9main :: Effect Unit
19main = do
10main = do
20 Plum.run "plum" plum
11 Plum.run "plum" plum
21
12
22−type Model = { text :: String }
13+type Model = { text :: String, numberOfClicks :: Int }
23
14
15+data Msg = Clicked | UpdateText String
16+
24−plum :: Plum.Plum Unit Model
17+plum :: Plum.Plum Msg Model
25plum =
18plum =
26− { init: pure { text: "Test" }
19+ { init: pure { text: "Test", numberOfClicks: 0 }
27− , view: \model ->
20+ , view: \model -> do
28− V.row [ V.spacing 16 ]
21+ column do
29− [ s model.text
22+ stack do
30− , button [] { onPress: unit, view: s "Button" }
23+ align Y End
31− ]
24+ height Fit
25+ row do
26+ align Y End
27+ column do
28+ bgColor $ rgb 0.0 0.0 0.0
29+ height (Px 10)
30+ column mempty
31+ pure unit
32+ column do
33+ font "sans-serif"
34+ column do
35+ height (Px 100)
36+ width Fit
37+ align Y Start
38+ width Fill
39+ column $ do
40+ width Fill
41+ width Fit
42+ height Fit
43+ text "PureStack" do
44+ fontSize 72
45+ fontWeight 1000
46+ column do
47+ bgColor $ rgb 0.0 0.0 0.0
48+ height (Px 10)
49+ width Fill
50+ column do
51+ width Fill
52+ row do
53+ text (model.text <> ": " <> show model.numberOfClicks) mempty
54+ onClick Clicked
55+ textInput { onChange: UpdateText, value: model.text } mempty
32 , update: \msg model -> case msg of
56 , update: \msg model -> case msg of
33− _ -> pure { text: "Button pressed" }
57+ Clicked -> pure model { text = "Button pressed", numberOfClicks = model.numberOfClicks + 1 }
58+ UpdateText text -> pure model { text = text }
34 }
59 }
plum/src/Maquette.jsdeleted−953
@@ -1,953 +0,0 @@
1−'use strict';
2−
3−var NAMESPACE_W3 = "http://www.w3.org/";
4−var NAMESPACE_SVG = NAMESPACE_W3 + "2000/svg";
5−var NAMESPACE_XLINK = NAMESPACE_W3 + "1999/xlink";
6−var emptyArray = [];
7−var extend = function (base, overrides) {
8− var result = {};
9− Object.keys(base).forEach(function (key) {
10− result[key] = base[key];
11− });
12− if (overrides) {
13− Object.keys(overrides).forEach(function (key) {
14− result[key] = overrides[key];
15− });
16− }
17− return result;
18−};
19−var same = function (vnode1, vnode2) {
20− if (vnode1.vnodeSelector !== vnode2.vnodeSelector) {
21− return false;
22− }
23− if (vnode1.properties && vnode2.properties) {
24− if (vnode1.properties.key !== vnode2.properties.key) {
25− return false;
26− }
27− return vnode1.properties.bind === vnode2.properties.bind;
28− }
29− return !vnode1.properties && !vnode2.properties;
30−};
31−var checkStyleValue = function (styleValue) {
32− if (typeof styleValue !== "string") {
33− throw new Error("Style values must be strings");
34− }
35−};
36−var findIndexOfChild = function (children, sameAs, start) {
37− if (sameAs.vnodeSelector !== "") {
38− // Never scan for text-nodes
39− for (var i = start; i < children.length; i++) {
40− if (same(children[i], sameAs)) {
41− return i;
42− }
43− }
44− }
45− return -1;
46−};
47−var checkDistinguishable = function (childNodes, indexToCheck, parentVNode, operation) {
48− var childNode = childNodes[indexToCheck];
49− if (childNode.vnodeSelector === "") {
50− return; // Text nodes need not be distinguishable
51− }
52− var properties = childNode.properties;
53− var key = properties
54− ? properties.key === undefined
55− ? properties.bind
56− : properties.key
57− : undefined;
58− if (!key) {
59− // A key is just assumed to be unique
60− for (var i = 0; i < childNodes.length; i++) {
61− if (i !== indexToCheck) {
62− var node = childNodes[i];
63− if (same(node, childNode)) {
64− throw {
65− error: new Error(parentVNode.vnodeSelector + " had a " + childNode.vnodeSelector + " child " + (operation === "added" ? operation : "removed") + ", but there is now more than one. You must add unique key properties to make them distinguishable."),
66− parentNode: parentVNode,
67− childNode: childNode,
68− };
69− }
70− }
71− }
72− }
73−};
74−var nodeAdded = function (vNode) {
75− if (vNode.properties) {
76− var enterAnimation = vNode.properties.enterAnimation;
77− if (enterAnimation) {
78− enterAnimation(vNode.domNode, vNode.properties);
79− }
80− }
81−};
82−var removedNodes = [];
83−var requestedIdleCallback = false;
84−var visitRemovedNode = function (node) {
85− (node.children || []).forEach(visitRemovedNode);
86− if (node.properties && node.properties.afterRemoved) {
87− node.properties.afterRemoved.apply(node.properties.bind || node.properties, [
88− node.domNode,
89− ]);
90− }
91−};
92−var processPendingNodeRemovals = function () {
93− requestedIdleCallback = false;
94− removedNodes.forEach(visitRemovedNode);
95− removedNodes.length = 0;
96−};
97−var scheduleNodeRemoval = function (vNode) {
98− removedNodes.push(vNode);
99− if (!requestedIdleCallback) {
100− requestedIdleCallback = true;
101− if (typeof window !== "undefined" && "requestIdleCallback" in window) {
102− window.requestIdleCallback(processPendingNodeRemovals, { timeout: 16 });
103− }
104− else {
105− setTimeout(processPendingNodeRemovals, 16);
106− }
107− }
108−};
109−var nodeToRemove = function (vNode) {
110− var domNode = vNode.domNode;
111− if (vNode.properties) {
112− var exitAnimation = vNode.properties.exitAnimation;
113− if (exitAnimation) {
114− domNode.style.pointerEvents = "none";
115− var removeDomNode = function () {
116− if (domNode.parentNode) {
117− domNode.parentNode.removeChild(domNode);
118− scheduleNodeRemoval(vNode);
119− }
120− };
121− exitAnimation(domNode, removeDomNode, vNode.properties);
122− return;
123− }
124− }
125− if (domNode.parentNode) {
126− domNode.parentNode.removeChild(domNode);
127− scheduleNodeRemoval(vNode);
128− }
129−};
130−var vnodeOnlyProps = [
131− "afterCreate",
132− "afterUpdate",
133− "afterRemoved",
134− "enterAnimation",
135− "exitAnimation",
136− "updateAnimation",
137−];
138−function filterVNodeOnlyProps(name) {
139− return !vnodeOnlyProps.includes(name);
140−}
141−var setProperties = function (domNode, properties, projectionOptions) {
142− if (!properties) {
143− return;
144− }
145− var eventHandlerInterceptor = projectionOptions.eventHandlerInterceptor;
146− var propNames = Object.keys(properties).filter(filterVNodeOnlyProps);
147− var propCount = propNames.length;
148− for (var i = 0; i < propCount; i++) {
149− var propName = propNames[i];
150− var propValue = properties[propName];
151− if (propName === "className") {
152− throw new Error('Property "className" is not supported, use "class".');
153− }
154− else if (propName === "class") {
155− toggleClasses(domNode, propValue, true);
156− }
157− else if (propName === "classes") {
158− // object with string keys and boolean values
159− var classNames = Object.keys(propValue);
160− var classNameCount = classNames.length;
161− for (var j = 0; j < classNameCount; j++) {
162− var className = classNames[j];
163− if (propValue[className]) {
164− domNode.classList.add(className);
165− }
166− }
167− }
168− else if (propName === "styles") {
169− // object with string keys and string (!) values
170− var styleNames = Object.keys(propValue);
171− var styleCount = styleNames.length;
172− for (var j = 0; j < styleCount; j++) {
173− var styleName = styleNames[j];
174− var styleValue = propValue[styleName];
175− if (styleValue) {
176− checkStyleValue(styleValue);
177− projectionOptions.styleApplyer(domNode, styleName, styleValue);
178− }
179− }
180− }
181− else if (propName === "on" && propValue) {
182− // object with string keys and function values
183− for (var _i = 0, _a = Object.entries(properties.on); _i < _a.length; _i++) {
184− var _b = _a[_i], key = _b[0], handler = _b[1];
185− var listener = typeof handler === "function" ? handler : handler.listener;
186− if (eventHandlerInterceptor) {
187− listener = eventHandlerInterceptor(key, listener, domNode, properties);
188− }
189− if (listener) {
190− domNode.addEventListener(key, listener, typeof handler === "function" ? undefined : handler.options);
191− }
192− }
193− }
194− else if (propName !== "key" && propValue !== null && propValue !== undefined) {
195− var type = typeof propValue;
196− if (type === "function") {
197− if (propName.lastIndexOf("on", 0) === 0) {
198− // lastIndexOf(,0)===0 -> startsWith
199− if (eventHandlerInterceptor) {
200− propValue = eventHandlerInterceptor(propName, propValue, domNode, properties); // intercept eventhandlers
201− }
202− }
203− domNode[propName] = propValue;
204− }
205− else if (projectionOptions.namespace === NAMESPACE_SVG) {
206− if (propName === "href") {
207− domNode.setAttributeNS(NAMESPACE_XLINK, propName, propValue);
208− }
209− else {
210− // all SVG attributes are read-only in DOM, so...
211− domNode.setAttribute(propName, propValue);
212− }
213− }
214− else if (type === "string" && propName !== "value" && propName !== "innerHTML") {
215− domNode.setAttribute(propName, propValue);
216− }
217− else {
218− domNode[propName] = propValue;
219− }
220− }
221− }
222−};
223−var addChildren = function (domNode, children, projectionOptions) {
224− if (!children) {
225− return;
226− }
227− for (var _i = 0, children_1 = children; _i < children_1.length; _i++) {
228− var child = children_1[_i];
229− createDom(child, domNode, undefined, projectionOptions);
230− }
231−};
232−var initPropertiesAndChildren = function (domNode, vnode, projectionOptions) {
233− addChildren(domNode, vnode.children, projectionOptions); // children before properties, needed for value property of <select>.
234− if (vnode.text) {
235− domNode.textContent = vnode.text;
236− }
237− setProperties(domNode, vnode.properties, projectionOptions);
238− if (vnode.properties && vnode.properties.afterCreate) {
239− vnode.properties.afterCreate.apply(vnode.properties.bind || vnode.properties, [
240− domNode,
241− projectionOptions,
242− vnode.vnodeSelector,
243− vnode.properties,
244− vnode.children,
245− ]);
246− }
247−};
248−var createDom = function (vnode, parentNode, insertBefore, projectionOptions) {
249− var _a;
250− var domNode;
251− var start = 0;
252− var vnodeSelector = vnode.vnodeSelector;
253− var doc = parentNode.ownerDocument;
254− if (vnodeSelector === "") {
255− if (vnode.domNode) {
256− vnode.domNode.nodeValue = vnode.text;
257− }
258− else {
259− domNode = vnode.domNode = doc.createTextNode(vnode.text);
260− if (insertBefore !== undefined) {
261− parentNode.insertBefore(domNode, insertBefore);
262− }
263− else {
264− parentNode.appendChild(domNode);
265− }
266− }
267− }
268− else {
269− for (var i = 0; i <= vnodeSelector.length; ++i) {
270− var c = vnodeSelector.charAt(i);
271− if (i === vnodeSelector.length || c === "." || c === "#") {
272− var type = vnodeSelector.charAt(start - 1);
273− var found = vnodeSelector.slice(start, i);
274− if (type === ".") {
275− domNode.classList.add(found);
276− }
277− else if (type === "#") {
278− domNode.id = found;
279− }
280− else {
281− if (found === "svg") {
282− projectionOptions = extend(projectionOptions, {
283− namespace: NAMESPACE_SVG,
284− });
285− }
286− if (projectionOptions.namespace !== undefined) {
287− domNode = vnode.domNode = doc.createElementNS(projectionOptions.namespace, found);
288− }
289− else {
290− domNode = vnode.domNode =
291− vnode.domNode ||
292− (((_a = vnode.properties) === null || _a === void 0 ? void 0 : _a.is) ? doc.createElement(found, { is: vnode.properties.is })
293− : doc.createElement(found));
294− if (found === "input" && vnode.properties && vnode.properties.type !== undefined) {
295− // IE8 and older don't support setting input type after the DOM Node has been added to the document
296− domNode.setAttribute("type", vnode.properties.type);
297− }
298− }
299− if (insertBefore !== undefined) {
300− parentNode.insertBefore(domNode, insertBefore);
301− }
302− else if (domNode.parentNode !== parentNode) {
303− parentNode.appendChild(domNode);
304− }
305− }
306− start = i + 1;
307− }
308− }
309− initPropertiesAndChildren(domNode, vnode, projectionOptions);
310− }
311−};
312−var updateDom;
313−/**
314− * Adds or removes classes from an Element
315− * @param domNode the element
316− * @param classes a string separated list of classes
317− * @param on true means add classes, false means remove
318− */
319−var toggleClasses = function (domNode, classes, on) {
320− if (!classes) {
321− return;
322− }
323− classes.split(" ").forEach(function (classToToggle) {
324− if (classToToggle) {
325− domNode.classList.toggle(classToToggle, on);
326− }
327− });
328−};
329−var updateProperties = function (domNode, previousProperties, properties, projectionOptions) {
330− if (!properties) {
331− return;
332− }
333− var propertiesUpdated = false;
334− var propNames = Object.keys(properties).filter(filterVNodeOnlyProps);
335− var propCount = propNames.length;
336− for (var i = 0; i < propCount; i++) {
337− var propName = propNames[i];
338− // assuming that properties will be nullified instead of missing is by design
339− var propValue = properties[propName];
340− var previousValue = previousProperties[propName];
341− if (propName === "class") {
342− if (previousValue !== propValue) {
343− toggleClasses(domNode, previousValue, false);
344− toggleClasses(domNode, propValue, true);
345− }
346− }
347− else if (propName === "classes") {
348− var classList = domNode.classList;
349− var classNames = Object.keys(propValue);
350− var classNameCount = classNames.length;
351− for (var j = 0; j < classNameCount; j++) {
352− var className = classNames[j];
353− var on = !!propValue[className];
354− var previousOn = !!previousValue[className];
355− if (on === previousOn) {
356− continue;
357− }
358− propertiesUpdated = true;
359− if (on) {
360− classList.add(className);
361− }
362− else {
363− classList.remove(className);
364− }
365− }
366− }
367− else if (propName === "styles") {
368− var styleNames = Object.keys(propValue);
369− var styleCount = styleNames.length;
370− for (var j = 0; j < styleCount; j++) {
371− var styleName = styleNames[j];
372− var newStyleValue = propValue[styleName];
373− var oldStyleValue = previousValue[styleName];
374− if (newStyleValue === oldStyleValue) {
375− continue;
376− }
377− propertiesUpdated = true;
378− if (newStyleValue) {
379− checkStyleValue(newStyleValue);
380− projectionOptions.styleApplyer(domNode, styleName, newStyleValue);
381− }
382− else {
383− projectionOptions.styleApplyer(domNode, styleName, "");
384− }
385− }
386− }
387− else {
388− if (!propValue && typeof previousValue === "string") {
389− propValue = "";
390− }
391− if (propName === "value") {
392− // value can be manipulated by the user directly and using event.preventDefault() is not an option
393− var domValue = domNode[propName];
394− if (domValue !== propValue && // The 'value' in the DOM tree !== newValue
395− propValue !== previousValue // Only update the value if the vdom changed
396− ) {
397− // The edge cases are described in the tests
398− domNode[propName] = propValue; // Reset the value, even if the virtual DOM did not change
399− } // else do not update the domNode, otherwise the cursor position would be changed
400− if (propValue !== previousValue) {
401− propertiesUpdated = true;
402− }
403− }
404− else if (propValue !== previousValue) {
405− var type = typeof propValue;
406− if (type !== "function" || !projectionOptions.eventHandlerInterceptor) {
407− // Function updates are expected to be handled by the EventHandlerInterceptor
408− if (projectionOptions.namespace === NAMESPACE_SVG) {
409− if (propName === "href") {
410− domNode.setAttributeNS(NAMESPACE_XLINK, propName, propValue);
411− }
412− else {
413− // all SVG attributes are read-only in DOM, so...
414− domNode.setAttribute(propName, propValue);
415− }
416− }
417− else if (type === "string" && propName !== "innerHTML") {
418− if (propName === "role" && propValue === "") {
419− domNode.removeAttribute(propName);
420− }
421− else {
422− domNode.setAttribute(propName, propValue);
423− }
424− }
425− else if (domNode[propName] !== propValue) {
426− // Comparison is here for side-effects in Edge with scrollLeft and scrollTop
427− domNode[propName] = propValue;
428− }
429− propertiesUpdated = true;
430− }
431− }
432− }
433− }
434− return propertiesUpdated;
435−};
436−var updateChildren = function (vnode, domNode, oldChildren, newChildren, projectionOptions) {
437− if (oldChildren === newChildren) {
438− return false;
439− }
440− oldChildren = oldChildren || emptyArray;
441− newChildren = newChildren || emptyArray;
442− var oldChildrenLength = oldChildren.length;
443− var newChildrenLength = newChildren.length;
444− var oldIndex = 0;
445− var newIndex = 0;
446− var i;
447− var textUpdated = false;
448− while (newIndex < newChildrenLength) {
449− var oldChild = oldIndex < oldChildrenLength ? oldChildren[oldIndex] : undefined;
450− var newChild = newChildren[newIndex];
451− if (oldChild !== undefined && same(oldChild, newChild)) {
452− textUpdated =
453− updateDom(oldChild, newChild, projectionOptions, domNode, oldChildren) || textUpdated;
454− oldIndex++;
455− }
456− else {
457− var findOldIndex = findIndexOfChild(oldChildren, newChild, oldIndex + 1);
458− if (findOldIndex >= 0) {
459− // Remove preceding missing children
460− for (i = oldIndex; i < findOldIndex; i++) {
461− nodeToRemove(oldChildren[i]);
462− checkDistinguishable(oldChildren, i, vnode, "removed");
463− }
464− textUpdated =
465− updateDom(oldChildren[findOldIndex], newChild, projectionOptions, domNode, oldChildren) ||
466− textUpdated;
467− oldIndex = findOldIndex + 1;
468− }
469− else {
470− // New child
471− createDom(newChild, domNode, oldIndex < oldChildrenLength ? oldChildren[oldIndex].domNode : undefined, projectionOptions);
472− nodeAdded(newChild);
473− checkDistinguishable(newChildren, newIndex, vnode, "added");
474− }
475− }
476− newIndex++;
477− }
478− if (oldChildrenLength > oldIndex) {
479− // Remove child fragments
480− for (i = oldIndex; i < oldChildrenLength; i++) {
481− nodeToRemove(oldChildren[i]);
482− checkDistinguishable(oldChildren, i, vnode, "removed");
483− }
484− }
485− return textUpdated;
486−};
487−updateDom = function (previous, vnode, projectionOptions, parentNode, oldChildren) {
488− var domNode = previous.domNode;
489− var textUpdated = false;
490− if (previous === vnode) {
491− return false; // By contract, VNode objects may not be modified anymore after passing them to maquette
492− }
493− var updated = false;
494− if (vnode.vnodeSelector === "") {
495− if (vnode.text !== previous.text) {
496− var newTextNode = domNode.ownerDocument.createTextNode(vnode.text);
497− try {
498− parentNode.replaceChild(newTextNode, domNode);
499− }
500− catch (e) {
501− // Text nodes can be substituted by google translate
502− parentNode.replaceChild(newTextNode, parentNode.childNodes[oldChildren.indexOf(previous)]);
503− }
504− vnode.domNode = newTextNode;
505− textUpdated = true;
506− return textUpdated;
507− }
508− vnode.domNode = domNode;
509− }
510− else {
511− if (vnode.vnodeSelector.lastIndexOf("svg", 0) === 0) {
512− // lastIndexOf(needle,0)===0 means StartsWith
513− projectionOptions = extend(projectionOptions, {
514− namespace: NAMESPACE_SVG,
515− });
516− }
517− if (previous.text !== vnode.text) {
518− updated = true;
519− if (vnode.text === undefined) {
520− domNode.removeChild(domNode.firstChild); // the only textnode presumably
521− }
522− else {
523− domNode.textContent = vnode.text;
524− }
525− }
526− vnode.domNode = domNode;
527− updated =
528− updateChildren(vnode, domNode, previous.children, vnode.children, projectionOptions) ||
529− updated;
530− updated =
531− updateProperties(domNode, previous.properties, vnode.properties, projectionOptions) ||
532− updated;
533− if (vnode.properties && vnode.properties.afterUpdate) {
534− vnode.properties.afterUpdate.apply(vnode.properties.bind || vnode.properties, [
535− domNode,
536− projectionOptions,
537− vnode.vnodeSelector,
538− vnode.properties,
539− vnode.children,
540− ]);
541− }
542− }
543− if (updated && vnode.properties && vnode.properties.updateAnimation) {
544− vnode.properties.updateAnimation(domNode, vnode.properties, previous.properties);
545− }
546− return textUpdated;
547−};
548−var createProjection = function (vnode, projectionOptions) {
549− return {
550− getLastRender: function () { return vnode; },
551− update: function (updatedVnode) {
552− if (vnode.vnodeSelector !== updatedVnode.vnodeSelector) {
553− throw new Error("The selector for the root VNode may not be changed. (consider using dom.merge and add one extra level to the virtual DOM)");
554− }
555− var previousVNode = vnode;
556− vnode = updatedVnode;
557− updateDom(previousVNode, updatedVnode, projectionOptions, previousVNode.domNode.parentNode, [previousVNode]);
558− },
559− domNode: vnode.domNode,
560− };
561−};
562−
563−var DEFAULT_PROJECTION_OPTIONS = {
564− namespace: undefined,
565− performanceLogger: function () { return undefined; },
566− eventHandlerInterceptor: undefined,
567− styleApplyer: function (domNode, styleName, value) {
568− if (styleName.charAt(0) === "-") {
569− // CSS variables must be set using setProperty
570− domNode.style.setProperty(styleName, value);
571− }
572− else {
573− // properties like 'backgroundColor' must be set as a js-property
574− domNode.style[styleName] = value;
575− }
576− },
577−};
578−var applyDefaultProjectionOptions = function (projectorOptions) {
579− return extend(DEFAULT_PROJECTION_OPTIONS, projectorOptions);
580−};
581−export var dom = {
582− /**
583− * Creates a real DOM tree from `vnode`. The [[Projection]] object returned will contain the resulting DOM Node in
584− * its [[Projection.domNode|domNode]] property.
585− * This is a low-level method. Users will typically use a [[Projector]] instead.
586− * @param vnode - The root of the virtual DOM tree that was created using the [[h]] function. NOTE: [[VNode]]
587− * objects may only be rendered once.
588− * @param projectionOptions - Options to be used to create and update the projection.
589− * @returns The [[Projection]] which also contains the DOM Node that was created.
590− */
591− create: function (vnode, projectionOptions) {
592− projectionOptions = applyDefaultProjectionOptions(projectionOptions);
593− createDom(vnode, document.createElement("div"), undefined, projectionOptions);
594− return createProjection(vnode, projectionOptions);
595− },
596− /**
597− * Appends a new child node to the DOM which is generated from a [[VNode]].
598− * This is a low-level method. Users will typically use a [[Projector]] instead.
599− * @param parentNode - The parent node for the new child node.
600− * @param vnode - The root of the virtual DOM tree that was created using the [[h]] function. NOTE: [[VNode]]
601− * objects may only be rendered once.
602− * @param projectionOptions - Options to be used to create and update the [[Projection]].
603− * @returns The [[Projection]] that was created.
604− */
605− append: function (parentNode, vnode, projectionOptions) {
606− projectionOptions = applyDefaultProjectionOptions(projectionOptions);
607− createDom(vnode, parentNode, undefined, projectionOptions);
608− return createProjection(vnode, projectionOptions);
609− },
610− /**
611− * Inserts a new DOM node which is generated from a [[VNode]].
612− * This is a low-level method. Users wil typically use a [[Projector]] instead.
613− * @param beforeNode - The node that the DOM Node is inserted before.
614− * @param vnode - The root of the virtual DOM tree that was created using the [[h]] function.
615− * NOTE: [[VNode]] objects may only be rendered once.
616− * @param projectionOptions - Options to be used to create and update the projection, see [[createProjector]].
617− * @returns The [[Projection]] that was created.
618− */
619− insertBefore: function (beforeNode, vnode, projectionOptions) {
620− projectionOptions = applyDefaultProjectionOptions(projectionOptions);
621− createDom(vnode, beforeNode.parentNode, beforeNode, projectionOptions);
622− return createProjection(vnode, projectionOptions);
623− },
624− /**
625− * Merges a new DOM node which is generated from a [[VNode]] with an existing DOM Node.
626− * This means that the virtual DOM and the real DOM will have one overlapping element.
627− * Therefore the selector for the root [[VNode]] will be ignored, but its properties and children will be applied to the Element provided.
628− * This is a low-level method. Users wil typically use a [[Projector]] instead.
629− * @param element - The existing element to adopt as the root of the new virtual DOM. Existing attributes and child nodes are preserved.
630− * @param vnode - The root of the virtual DOM tree that was created using the [[h]] function. NOTE: [[VNode]] objects
631− * may only be rendered once.
632− * @param projectionOptions - Options to be used to create and update the projection, see [[createProjector]].
633− * @returns The [[Projection]] that was created.
634− */
635− merge: function (element, vnode, projectionOptions) {
636− projectionOptions = applyDefaultProjectionOptions(projectionOptions);
637− vnode.domNode = element;
638− initPropertiesAndChildren(element, vnode, projectionOptions);
639− return createProjection(vnode, projectionOptions);
640− },
641− /**
642− * Replaces an existing DOM node with a node generated from a [[VNode]].
643− * This is a low-level method. Users will typically use a [[Projector]] instead.
644− * @param element - The node for the [[VNode]] to replace.
645− * @param vnode - The root of the virtual DOM tree that was created using the [[h]] function. NOTE: [[VNode]]
646− * objects may only be rendered once.
647− * @param projectionOptions - Options to be used to create and update the [[Projection]].
648− * @returns The [[Projection]] that was created.
649− */
650− replace: function (element, vnode, projectionOptions) {
651− projectionOptions = applyDefaultProjectionOptions(projectionOptions);
652− createDom(vnode, element.parentNode, element, projectionOptions);
653− element.parentNode.removeChild(element);
654− return createProjection(vnode, projectionOptions);
655− },
656−};
657−
658−var toTextVNode = function (data) {
659− return {
660− vnodeSelector: "",
661− properties: undefined,
662− children: undefined,
663− text: data.toString(),
664− domNode: null,
665− };
666−};
667−var appendChildren = function (parentSelector, insertions, main) {
668− for (var i = 0, length_1 = insertions.length; i < length_1; i++) {
669− var item = insertions[i];
670− if (Array.isArray(item)) {
671− appendChildren(parentSelector, item, main);
672− }
673− else {
674− if (item !== null && item !== undefined && item !== false) {
675− if (typeof item === "string") {
676− item = toTextVNode(item);
677− }
678− main.push(item);
679− }
680− }
681− }
682−};
683−function h(selector, properties, children) {
684− if (Array.isArray(properties)) {
685− children = properties;
686− properties = undefined;
687− }
688− else if ((properties && (typeof properties === "string" || properties.vnodeSelector)) ||
689− (children && (typeof children === "string" || children.vnodeSelector))) {
690− throw new Error("h called with invalid arguments");
691− }
692− var text;
693− var flattenedChildren;
694− // Recognize a common special case where there is only a single text node
695− if (children && children.length === 1 && typeof children[0] === "string") {
696− text = children[0];
697− }
698− else if (children) {
699− flattenedChildren = [];
700− appendChildren(selector, children, flattenedChildren);
701− if (flattenedChildren.length === 0) {
702− flattenedChildren = undefined;
703− }
704− }
705− return {
706− vnodeSelector: selector,
707− properties: properties,
708− children: flattenedChildren,
709− text: text === "" ? undefined : text,
710− domNode: null,
711− };
712−}
713−
714−var createParentNodePath = function (node, rootNode) {
715− var parentNodePath = [];
716− while (node && node !== rootNode) {
717− parentNodePath.push(node);
718− node = node.parentNode;
719− }
720− return parentNodePath;
721−};
722−var find;
723−if (Array.prototype.find) {
724− find = function (items, predicate) { return items.find(predicate); };
725−}
726−else {
727− find = function (items, predicate) { return items.filter(predicate)[0]; };
728−}
729−var findVNodeByParentNodePath = function (vnode, parentNodePath) {
730− var result = vnode;
731− parentNodePath.forEach(function (node) {
732− result =
733− result && result.children
734− ? find(result.children, function (child) { return child.domNode === node; })
735− : undefined;
736− });
737− return result;
738−};
739−var createEventHandlerInterceptor = function (projector, getProjection, performanceLogger) {
740− return function (propertyName, eventHandler, domNode, properties) { return modifiedEventHandler; };
741− function modifiedEventHandler(evt) {
742− var _a, _b;
743− performanceLogger("domEvent", evt);
744− var projection = getProjection();
745− var parentNodePath = createParentNodePath(evt.currentTarget, projection.domNode);
746− parentNodePath.reverse();
747− var matchingVNode = findVNodeByParentNodePath(projection.getLastRender(), parentNodePath);
748− projector.scheduleRender();
749− var result;
750− if (matchingVNode) {
751− /* eslint-disable prefer-rest-params */
752− var listener = (_b = (_a = matchingVNode.properties["on" + evt.type]) !== null && _a !== void 0 ? _a : matchingVNode.properties.on[evt.type].listener) !== null && _b !== void 0 ? _b : matchingVNode.properties.on[evt.type];
753− result = listener.apply(matchingVNode.properties.bind || this, arguments);
754− /* eslint-enable prefer-rest-params */
755− }
756− performanceLogger("domEventProcessed", evt);
757− return result;
758− }
759−};
760−/**
761− * Creates a [[Projector]] instance using the provided projectionOptions.
762− *
763− * For more information, see [[Projector]].
764− *
765− * @param projectorOptions Options that influence how the DOM is rendered and updated.
766− */
767−export var createProjector = function (projectorOptions) {
768− var projector;
769− var projectionOptions = applyDefaultProjectionOptions(projectorOptions);
770− var performanceLogger = projectionOptions.performanceLogger;
771− var renderCompleted = true;
772− var scheduled;
773− var stopped = false;
774− var projections = [];
775− var renderFunctions = []; // matches the projections array
776− var addProjection = function (
777− /* one of: dom.append, dom.insertBefore, dom.replace, dom.merge */
778− domFunction,
779− /* the parameter of the domFunction */
780− node, renderFunction) {
781− var projection;
782− var getProjection = function () { return projection; };
783− projectionOptions.eventHandlerInterceptor = createEventHandlerInterceptor(projector, getProjection, performanceLogger);
784− projection = domFunction(node, renderFunction(), projectionOptions);
785− projections.push(projection);
786− renderFunctions.push(renderFunction);
787− };
788− var doRender = function () {
789− scheduled = undefined;
790− if (!renderCompleted) {
791− return; // The last render threw an error, it should have been logged in the browser console.
792− }
793− renderCompleted = false;
794− performanceLogger("renderStart", undefined);
795− for (var i = 0; i < projections.length; i++) {
796− var updatedVnode = renderFunctions[i]();
797− performanceLogger("rendered", undefined);
798− projections[i].update(updatedVnode);
799− performanceLogger("patched", undefined);
800− }
801− performanceLogger("renderDone", undefined);
802− renderCompleted = true;
803− };
804− projector = {
805− renderNow: doRender,
806− scheduleRender: function () {
807− if (!scheduled && !stopped) {
808− scheduled = requestAnimationFrame(doRender);
809− }
810− },
811− stop: function () {
812− if (scheduled) {
813− cancelAnimationFrame(scheduled);
814− scheduled = undefined;
815− }
816− stopped = true;
817− },
818− resume: function () {
819− stopped = false;
820− renderCompleted = true;
821− projector.scheduleRender();
822− },
823− append: function (parentNode, renderFunction) {
824− addProjection(dom.append, parentNode, renderFunction);
825− },
826− insertBefore: function (beforeNode, renderFunction) {
827− addProjection(dom.insertBefore, beforeNode, renderFunction);
828− },
829− merge: function (domNode, renderFunction) {
830− addProjection(dom.merge, domNode, renderFunction);
831− },
832− replace: function (domNode, renderFunction) {
833− addProjection(dom.replace, domNode, renderFunction);
834− },
835− detach: function (renderFunction) {
836− for (var i = 0; i < renderFunctions.length; i++) {
837− if (renderFunctions[i] === renderFunction) {
838− renderFunctions.splice(i, 1);
839− return projections.splice(i, 1)[0];
840− }
841− }
842− throw new Error("renderFunction was not found");
843− },
844− };
845− return projector;
846−};
847−
848−/**
849− * Creates a [[CalculationCache]] object, useful for caching [[VNode]] trees.
850− * In practice, caching of [[VNode]] trees is not needed, because achieving 60 frames per second is almost never a problem.
851− * For more information, see [[CalculationCache]].
852− *
853− * @param <Result> The type of the value that is cached.
854− */
855−export var createCache = function () {
856− var cachedInputs;
857− var cachedOutcome;
858− return {
859− invalidate: function () {
860− cachedOutcome = undefined;
861− cachedInputs = undefined;
862− },
863− result: function (inputs, calculation) {
864− if (cachedInputs) {
865− for (var i = 0; i < inputs.length; i++) {
866− if (cachedInputs[i] !== inputs[i]) {
867− cachedOutcome = undefined;
868− }
869− }
870− }
871− if (!cachedOutcome) {
872− cachedOutcome = calculation();
873− cachedInputs = inputs;
874− }
875− return cachedOutcome;
876− },
877− };
878−};
879−
880−/**
881− * Creates a {@link Mapping} instance that keeps an array of result objects synchronized with an array of source objects.
882− * See {@link http://maquettejs.org/docs/arrays.html Working with arrays}.
883− *
884− * @param <Source> The type of source items. A database-record for instance.
885− * @param <Target> The type of target items. A [[MaquetteComponent]] for instance.
886− * @param getSourceKey `function(source)` that must return a key to identify each source object. The result must either be a string or a number.
887− * @param createResult `function(source, index)` that must create a new result object from a given source. This function is identical
888− * to the `callback` argument in `Array.map(callback)`.
889− * @param updateResult `function(source, target, index)` that updates a result to an updated source.
890− */
891−export var createMapping = function (getSourceKey, createResult, updateResult) {
892− var keys = [];
893− var results = [];
894− return {
895− results: results,
896− map: function (newSources) {
897− var newKeys = newSources.map(getSourceKey);
898− var oldTargets = results.slice();
899− var oldIndex = 0;
900− for (var i = 0; i < newSources.length; i++) {
901− var source = newSources[i];
902− var sourceKey = newKeys[i];
903− if (sourceKey === keys[oldIndex]) {
904− results[i] = oldTargets[oldIndex];
905− updateResult(source, oldTargets[oldIndex], i);
906− oldIndex++;
907− }
908− else {
909− var found = false;
910− for (var j = 1; j < keys.length + 1; j++) {
911− var searchIndex = (oldIndex + j) % keys.length;
912− if (keys[searchIndex] === sourceKey) {
913− results[i] = oldTargets[searchIndex];
914− updateResult(newSources[i], oldTargets[searchIndex], i);
915− oldIndex = searchIndex + 1;
916− found = true;
917− break;
918− }
919− }
920− if (!found) {
921− results[i] = createResult(source, i);
922− }
923− }
924− }
925− results.length = newSources.length;
926− keys = newKeys;
927− },
928− };
929−};
930−
931−export function _h(selector) {
932− return function (properties) {
933− return function (children) {
934− return h(selector, properties, children)
935− }
936− }
937−}
938−
939−export function scheduleRender(projector) {
940− return function () {
941− projector.scheduleRender()
942− }
943−}
944−
945−export function replace(projector) {
946− return function (el) {
947− return function (render) {
948− return function () {
949− projector.replace(el, render)
950− }
951− }
952− }
953−}
plum/src/Maquette.pursdeleted−33
@@ -1,33 +0,0 @@
1−module Maquette
2− ( Projector
3− , createProjector
4− , string
5− , VNode
6− , h
7− , replace
8− , scheduleRender
9− ) where
10−
11−import Prelude
12−
13−import Effect (Effect)
14−import Unsafe.Coerce (unsafeCoerce)
15−import Web.DOM (Element)
16−
17−foreign import data Projector :: Type
18−
19−foreign import createProjector :: Effect Projector
20−
21−foreign import data VNode :: Type
22−
23−foreign import _h :: forall props. String -> { | props } -> Array VNode -> VNode
24−
25−h :: forall props. String -> Record props -> Array VNode -> VNode
26−h = _h
27−
28−string :: String -> VNode
29−string = unsafeCoerce
30−
31−foreign import scheduleRender :: Projector -> Effect Unit
32−
33−foreign import replace :: Projector -> Element -> Effect VNode -> Effect Unit
plum/src/Plum.purs+64−14
@@ -2,11 +2,16 @@ module Plum (Plum, run) where
2
2
3import Prelude
3import Prelude
4
4
5+import Data.Array as Array
5import Data.Maybe (Maybe(..))
6import Data.Maybe (Maybe(..))
6import Effect (Effect)
7import Effect (Effect)
8+import Effect.Console (log)
7import Effect.Ref as Ref
9import Effect.Ref as Ref
8−import Maquette as Maquette
10+import Foreign.Object as Object
11+import Literals.Undefined (undefined)
9−import Plum.View (View, unView)
12+import Plum.View (GenericUI(..), UI, grow)
13+import Snabbdom as Snabbdom
14+import Untagged.Union (asOneOf)
10import Web.DOM.NonElementParentNode (getElementById) as Web
15import Web.DOM.NonElementParentNode (getElementById) as Web
11import Web.HTML (window) as Web
16import Web.HTML (window) as Web
12import Web.HTML.HTMLDocument (toNonElementParentNode) as Web
17import Web.HTML.HTMLDocument (toNonElementParentNode) as Web
@@ -15,22 +20,67 @@ import Web.HTML.Window (document) as Web
15type Plum msg model =
20type Plum msg model =
16 { init :: Effect model
21 { init :: Effect model
17 , update :: msg -> model -> Effect model
22 , update :: msg -> model -> Effect model
18− , view :: model -> View msg
23+ , view :: model -> UI msg Unit
19 }
24 }
20
25
21run :: forall msg model. String -> Plum msg model -> Effect Unit
26run :: forall msg model. String -> Plum msg model -> Effect Unit
22run id plum = do
27run id plum = do
23− modelRef <- plum.init >>= Ref.new
24 Web.window >>= Web.document >>= Web.getElementById id <<< Web.toNonElementParentNode >>= case _ of
28 Web.window >>= Web.document >>= Web.getElementById id <<< Web.toNonElementParentNode >>= case _ of
25 Just element -> do
29 Just element -> do
26− projector <- Maquette.createProjector
30+ let node = Snabbdom.toVNode element
27− Maquette.replace projector element do
31+ patch <- Snabbdom.init
28− model <- Ref.read modelRef
32+ initModel <- plum.init
33+ modelRef <- Ref.new { model: initModel, lastNode: node }
34+ let
35+ view model = do
29− pure $ unView (plum.view model)
36+ let UI { children } _ = plum.view model
37+ case Array.uncons children of
38+ Just { head: child } -> do
39+ let
40+ { node, style } = grow
30− ( \msg -> do
41+ ( \msg -> do
42+ log "in"
31− m <- Ref.read modelRef
43+ { model: m, lastNode } <- Ref.read modelRef
32− m_ <- plum.update msg m
44+ m_ <- plum.update msg m
45+ node <- view m_
46+ newNode <- patch lastNode node
33− Ref.write m_ modelRef
47+ Ref.write { model: m_, lastNode: newNode } modelRef
48+ pure unit
34− )
49+ )
35−
50+ child
51+ pure $
52+ Snabbdom.h "div"
53+ { attrs: Object.empty
54+ , on: Object.empty
55+ , style: Object.empty
56+ , props: Object.empty
57+ }
58+ [ Snabbdom.h "style"
59+ { attrs: Object.empty
60+ , on: Object.empty
61+ , style: Object.empty
62+ , props: Object.empty
63+ }
64+ []
65+ (asOneOf $ outerStyle <> style)
66+ , node
67+ ]
68+ (asOneOf undefined)
69+ Nothing -> pure $
70+ Snabbdom.h "div"
71+ { attrs: Object.empty
72+ , on: Object.empty
73+ , style: Object.empty
74+ , props: Object.empty
75+ }
76+ []
77+ (asOneOf undefined)
78+ newNode <- view initModel
79+ newNode_ <- patch node newNode
80+ log "patched"
81+ Ref.write { model: initModel, lastNode: newNode_ } modelRef
82+ pure unit
36 Nothing -> pure unit
83 Nothing -> pure unit
84+
85+outerStyle :: String
86+outerStyle = "html,body{height:100%;padding:0;margin:0;}"
plum/src/Plum/View.purs+664−78
@@ -1,114 +1,700 @@
1module Plum.View
1module Plum.View
2 ( View
2 ( View
3− , unView
3+ , Nerve(..)
4− , Attribute
4+ , Meat(..)
5− , spacing
5+ , Font
6− , row
6+ , BorderStyle(..)
7− , wrappedRow
7+ , Corner(..)
8+ , Shadow(..)
9+ , ShadowCfg
10+ , Side(..)
11+ , Bones(..)
12+ , grow
13+ , Direction(..)
14+ , Alignment(..)
15+ , Length(..)
16+ , Color(..)
17+ , rgb255
18+ , rgba255
19+ , rgb
20+ , rgba
21+ , UI
22+ , GenericUI(..)
23+ , GenericUIView
8 , column
24 , column
9− , wrappedColumn
25+ , row
10− , v
26+ , stack
11− , s
27+ , text
12− , button
28+ , link
29+ , newTabLink
30+ , download
31+ , downloadAs
32+ , image
33+ , textInput
34+ , spacing
35+ , explain
36+ , align
37+ , width
38+ , height
39+ , wrapped
40+ , bgColor
41+ , padding
42+ , spread
43+ , opacity
44+ , pointer
45+ , move
46+ , clip
47+ , borders
48+ , border
49+ , borderStyle
50+ , roundAll
51+ , round
52+ , shadow
53+ , innerShadow
54+ , onHover
55+ , onMouseDown
56+ , font
57+ , fontSize
58+ , fontWeight
59+ , onClick
13 ) where
60 ) where
14
61
15import Prelude
62import Prelude
16
63
64+import Control.Monad.Writer (Writer, runWriter, tell)
65+import Control.Monad.Writer.Trans (mapWriterT)
66+import Data.Array (foldMap)
17import Data.Array as Array
67import Data.Array as Array
68+import Data.Array.NonEmpty (concatMap)
69+import Data.Int as Int
70+import Data.Maybe (Maybe(..))
71+import Data.Maybe as Maybe
72+import Data.String as String
73+import Data.Traversable (traverse)
74+import Data.TraversableWithIndex (traverseWithIndex)
75+import Data.Tuple.Nested (type (/\), (/\))
18import Effect (Effect)
76import Effect (Effect)
19import Foreign.Object (Object)
77import Foreign.Object (Object)
20import Foreign.Object as Object
78import Foreign.Object as Object
21−import Maquette (VNode, h, string)
79+import Literals.Undefined (undefined)
80+import Prim.TypeError (class Warn)
81+import Prim.TypeError as TypeError
82+import Snabbdom (VNode)
83+import Snabbdom as Snabbdom
22import Type.Row.Homogeneous (class Homogeneous)
84import Type.Row.Homogeneous (class Homogeneous)
23import Unsafe.Coerce (unsafeCoerce)
85import Unsafe.Coerce (unsafeCoerce)
86+import Untagged.Union (asOneOf)
87+import Web.DOM.Element as Element
88+import Web.DOM.ParentNode (firstElementChild)
89+import Web.Event.Event (Event)
90+import Web.Event.Event as Event
91+import Web.UIEvent.InputEvent as InputEvent
92+import Web.HTML.HTMLInputElement as HTMLInputElement
24
93
25−newtype View :: Type -> Type
94+type GenericUIView children msg =
26−newtype View msg = View ((msg -> Effect Unit) -> VNode)
95+ { nerves :: Array (Nerve msg)
96+ , meat :: Array Meat
97+ , hover :: Array Meat
98+ , down :: Array Meat
99+ , children :: children
100+ }
27
101
28−unView :: forall msg. View msg -> (msg -> Effect Unit) -> VNode
102+type UIView msg = GenericUIView (Array (View msg)) msg
29−unView (View node) = node
30
103
31−data Attribute msg =
104+data GenericUI children msg a = UI (GenericUIView children msg) a
32− Spacing Int Int
33
105
34−spacing :: forall msg. Int -> Attribute msg
106+instance (Semigroup children, Semigroup a) => Semigroup (GenericUI children msg a) where
35−spacing x = Spacing x x
107+ append (UI v a) (UI v' a') = UI (v <> v') (a <> a')
36
108
37−data Context = Flexbox
109+instance (Monoid children, Monoid a) => Monoid (GenericUI children msg a) where
110+ mempty = UI mempty mempty
38
111
39−newtype RenderedAttribute = RenderedAttribute { styles :: Object String }
112+type UI msg a = GenericUI (Array (View msg)) msg a
40
113
41−instance Semigroup RenderedAttribute where
114+instance Functor (GenericUI children msg) where
42− append (RenderedAttribute x) (RenderedAttribute y) =
115+ map f (UI v a) = UI v $ f a
43− RenderedAttribute { styles: Object.union x.styles y.styles }
44
116
45−instance Monoid RenderedAttribute where
117+instance Monoid children => Apply (GenericUI children msg) where
46− mempty = RenderedAttribute $ { styles: Object.empty }
118+ apply (UI views f) (UI views' a) = UI (views <> views') (f a)
47
119
48−renderAttribute :: forall msg. Context -> Attribute msg -> RenderedAttribute
120+instance Monoid children => Applicative (GenericUI children msg) where
49−renderAttribute _ctx attr = RenderedAttribute $ case attr of
121+ pure = UI mempty
50− Spacing x y -> { styles: Object.insert "gap" (show x <> "px " <> show y <> "px") Object.empty }
51
122
52−renderWithStyles :: forall styles msg. Homogeneous styles String => Context -> Array (Attribute msg) -> { | styles } -> RenderedAttribute
123+instance Monoid children => Bind (GenericUI children msg) where
53−renderWithStyles ctx attrs styles = withStyles (renderAttributes ctx attrs) styles
124+ bind (UI views a) f =
125+ let
126+ UI views' b = f a
127+ in
128+ UI (views <> views') b
54
129
55−withStyles :: forall styles. Homogeneous styles String => RenderedAttribute -> { | styles } -> RenderedAttribute
130+instance Monoid children => Monad (GenericUI children msg)
56−withStyles (RenderedAttribute x) styles =
57− RenderedAttribute $ { styles: Object.union x.styles (Object.fromHomogeneous styles) }
58
131
59−renderAttributes :: forall msg. Context -> Array (Attribute msg) -> RenderedAttribute
132+column :: forall msg. UI msg Unit -> UI msg Unit
60−renderAttributes ctx = Array.foldMap (renderAttribute ctx)
133+column (UI { nerves, meat, hover, down, children } _) =
134+ UI (mempty :: UIView msg) { children = [ { meat, nerves, hover, down } /\ Column children ] } unit
61
135
62−v :: forall msg. Array (Attribute msg) -> View msg -> View msg
136+row :: forall msg a. UI msg a -> UI msg a
63−v _ (View child) = View $ \fire -> h "div" {} [ child fire ]
137+row (UI { nerves, meat, hover, down, children } a) =
138+ UI (mempty :: UIView msg) { children = [ { meat, nerves, hover, down } /\ Row children ] } a
64
139
65−row :: forall msg. Array (Attribute msg) -> Array (View msg) -> View msg
140+stack :: forall msg a. UI msg a -> UI msg a
66−row attrs children =
141+stack (UI { nerves, meat, hover, down, children } a) =
67− _v "div"
142+ UI (mempty :: UIView msg) { children = [ { meat, nerves, hover, down } /\ Stack children ] } a
68− ( renderWithStyles Flexbox attrs
69− { display: "flex"
70− , "flex-direction": "row"
71− }
72− )
73− children
74
143
75−wrappedRow :: forall msg. Array (Attribute msg) -> Array (View msg) -> View msg
144+text :: forall msg. String -> GenericUI Unit msg Unit -> UI msg Unit
76−wrappedRow attrs children =
145+text s (UI { nerves, meat, hover, down } a) = UI (mempty :: UIView msg) { children = [ { meat, nerves, hover, down } /\ Text s ] } a
77− _v "div"
146+
78− ( renderWithStyles Flexbox attrs
147+link :: forall msg a. String -> UI msg a -> UI msg a
79− { display: "flex"
148+link url (UI { nerves, meat, hover, down, children } a) = UI
80− , "flex-direction": "row"
149+ (mempty :: UIView msg)
81− , "flex-wrap": "wrap"
150+ { children =
151+ [ { meat
152+ , nerves
153+ , hover
154+ , down
155+ } /\ Link url { newTab: false } (Maybe.fromMaybe none $ Array.head children)
156+ ]
82− }
157+ }
83− )
158+ a
159+
160+newTabLink :: forall msg a. String -> UI msg a -> UI msg a
161+newTabLink url (UI { nerves, meat, hover, down, children } a) = UI
162+ (mempty :: UIView msg)
163+ { children =
164+ [ { meat
165+ , nerves
166+ , hover
167+ , down
168+ } /\ Link url { newTab: true } (Maybe.fromMaybe none $ Array.head children)
169+ ]
170+ }
171+ a
172+
173+download :: forall msg a. String -> UI msg a -> UI msg a
174+download url (UI { nerves, meat, children, down, hover } a) = UI
175+ (mempty :: UIView msg)
176+ { children =
177+ [ { meat
178+ , nerves
179+ , down
180+ , hover
181+ } /\ Download url { filename: Nothing } (Maybe.fromMaybe none $ Array.head children)
182+ ]
183+ }
184+ a
185+
186+downloadAs :: forall msg a. String -> { filename :: String } -> UI msg a -> UI msg a
187+downloadAs url { filename } (UI { nerves, meat, hover, down, children } a) = UI
188+ (mempty :: UIView msg)
189+ { children =
190+ [ { meat
191+ , nerves
192+ , hover
193+ , down
194+ } /\ Download url { filename: Just filename } (Maybe.fromMaybe none $ Array.head children)
195+ ]
196+ }
197+ a
198+
199+image :: forall msg a. String -> { description :: String } -> GenericUI Unit msg a -> UI msg a
200+image url description (UI { nerves, meat, hover, down } a) =
201+ UI (mempty :: UIView msg) { children = [ { meat, nerves, hover, down } /\ Image url description ] } a
202+
203+textInput :: forall msg a. { value :: String, onChange :: String -> msg } -> GenericUI Unit msg a -> UI msg a
204+textInput props (UI { nerves, meat, hover, down } a) =
205+ UI (mempty :: UIView msg) { children = [ { meat, nerves, hover, down } /\ TextInput props ] } a
206+
207+string :: String -> Classes -> WiredNerves -> String -> VNode
208+string elem classes (WiredNerves on) s =
209+ Snabbdom.h elem
210+ { attrs: Object.singleton "class" (Array.intercalate " " classes)
211+ , on
212+ , style: Object.empty
213+ , props: Object.empty
214+ }
215+ []
216+ (asOneOf s)
217+
218+h :: String -> Classes -> WiredNerves -> Array VNode -> VNode
219+h elem classes (WiredNerves on) children =
220+ Snabbdom.h elem
221+ { attrs: Object.singleton "class" (Array.intercalate " " classes)
222+ , on
223+ , props: Object.empty
224+ , style: Object.empty
225+ }
84 children
226 children
227+ (asOneOf undefined)
85
228
86−column :: forall msg. Array (Attribute msg) -> Array (View msg) -> View msg
229+hWith :: forall props. Homogeneous props String => String -> Record props -> Classes -> WiredNerves -> Array VNode -> VNode
87−column attrs children =
230+hWith elem props classes (WiredNerves on) children =
88− _v "div"
231+ Snabbdom.h elem
89− ( renderWithStyles Flexbox attrs
232+ { attrs: Object.singleton "class" (Array.intercalate " " classes)
90− { display: "flex"
233+ , on
91− , "flex-direction": "column"
234+ , props: Object.fromHomogeneous props
235+ , style: Object.empty
92− }
236+ }
93− )
94 children
237 children
238+ (asOneOf undefined)
239+
240+data Length = Px Int | Fill | Fit | Max Int Length | Min Int Length
241+
242+data Alignment = Start | Center | End
243+
244+data Direction = X | Y
245+
246+n :: forall ch msg. Monoid ch => Nerve msg -> GenericUI ch msg Unit
247+n nerve = UI (mempty :: GenericUIView ch msg) { nerves = [ nerve ] } mempty
248+
249+onClick :: forall ch msg. Monoid ch => msg -> GenericUI ch msg Unit
250+onClick msg = n $ OnClick msg
251+
252+m :: forall ch msg. Monoid ch => Meat -> GenericUI ch msg Unit
253+m meat = UI (mempty :: GenericUIView ch msg) { meat = [ meat ] } mempty
254+
255+spacing :: forall ch msg. Monoid ch => { x :: Int, y :: Int } -> GenericUI ch msg Unit
256+spacing { x, y } = m $ Spacing x y
257+
258+explain :: forall ch msg. Monoid ch => Warn (TypeError.Text "Debug explain present") => GenericUI ch msg Unit
259+explain = m Explain
260+
261+align :: forall ch msg. Monoid ch => Direction -> Alignment -> GenericUI ch msg Unit
262+align dir al = m $ Align dir al
263+
264+width :: forall ch msg. Monoid ch => Length -> GenericUI ch msg Unit
265+width l = m $ Width l
266+
267+height :: forall ch msg. Monoid ch => Length -> GenericUI ch msg Unit
268+height l = m $ Height l
269+
270+wrapped :: forall ch msg. Monoid ch => GenericUI ch msg Unit
271+wrapped = m Wrapped
272+
273+bgColor :: forall ch msg. Monoid ch => Color -> GenericUI ch msg Unit
274+bgColor c = m $ BackgroundColor c
275+
276+padding :: forall ch msg. Monoid ch => Side -> Int -> GenericUI ch msg Unit
277+padding s l = m $ Padding s l
278+
279+spread :: forall ch msg. Monoid ch => GenericUI ch msg Unit
280+spread = m Spread
281+
282+opacity :: forall ch msg. Monoid ch => Number -> GenericUI ch msg Unit
283+opacity o = m $ Opacity o
284+
285+pointer :: forall ch msg. Monoid ch => GenericUI ch msg Unit
286+pointer = m Pointer
287+
288+move :: forall ch msg. Monoid ch => { x :: Int, y :: Int } -> GenericUI ch msg Unit
289+move a = m $ Move a
290+
291+clip :: forall ch msg. Monoid ch => Direction -> GenericUI ch msg Unit
292+clip dir = m $ Clip dir
293+
294+onHover :: forall ch msg. Monoid ch => GenericUI Unit msg Unit -> GenericUI ch msg Unit
295+onHover (UI { meat } a) = UI (mempty :: GenericUIView ch msg) { hover = meat } a
296+
297+onMouseDown :: forall ch msg. Monoid ch => GenericUI Unit msg Unit -> GenericUI ch msg Unit
298+onMouseDown (UI { meat } a) = UI (mempty :: GenericUIView ch msg) { down = meat } a
299+
300+borders :: forall ch msg. Monoid ch => Int -> GenericUI ch msg Unit
301+borders l = Array.foldMap (\s -> m $ BorderWidth s l) [ Top, Right, Bottom, Left ]
302+
303+border :: forall ch msg. Monoid ch => Side -> Int -> GenericUI ch msg Unit
304+border s l = m $ BorderWidth s l
305+
306+borderStyle :: forall ch msg. Monoid ch => BorderStyle -> GenericUI ch msg Unit
307+borderStyle s = m $ BorderStyle s
308+
309+roundAll :: forall ch msg. Monoid ch => Int -> GenericUI ch msg Unit
310+roundAll l = Array.foldMap (\c -> m $ Round c l) [ TopLeft, TopRight, BottomRight, BottomLeft ]
311+
312+round :: forall ch msg. Monoid ch => Corner -> Int -> GenericUI ch msg Unit
313+round c l = m $ Round c l
314+
315+shadow :: forall ch msg. Monoid ch => ShadowCfg -> GenericUI ch msg Unit
316+shadow cfg = m $ Shadow $ ShadowCfg cfg
317+
318+innerShadow :: forall ch msg. Monoid ch => ShadowCfg -> GenericUI ch msg Unit
319+innerShadow cfg = m $ InnerShadow $ ShadowCfg cfg
320+
321+font :: forall ch msg. Monoid ch => String -> GenericUI ch msg Unit
322+font f = m $ Font f
323+
324+fontSize :: forall ch msg. Monoid ch => Int -> GenericUI ch msg Unit
325+fontSize f = m $ FontSize f
326+
327+fontWeight :: forall ch msg. Monoid ch => Int -> GenericUI ch msg Unit
328+fontWeight f = m $ FontWeight f
329+
330+data Meat
331+ = Spacing Int Int
332+ | Explain
333+ | Align Direction Alignment
334+ | Width Length
335+ | Height Length
336+ | Wrapped
337+ | BackgroundColor Color
338+ | Padding Side Int
339+ | Spread
340+ | Opacity Number
341+ | Pointer
342+ | Move { x :: Int, y :: Int }
343+ | Clip Direction
344+ | BorderWidth Side Int
345+ | BorderStyle BorderStyle
346+ | Round Corner Int
347+ | Shadow Shadow
348+ | InnerShadow Shadow
349+ | FontColor Color
350+ | FontWeight Int
351+ | FontSize Int
352+ | Font Font
95
353
96−wrappedColumn :: forall msg. Array (Attribute msg) -> Array (View msg) -> View msg
354+type Font = String
97−wrappedColumn attrs children =
355+
98− _v "div"
356+type ShadowCfg = { offset :: { x :: Int, y :: Int }, size :: Number, blur :: Number, color :: Color }
99− ( renderWithStyles Flexbox attrs
357+
100− { display: "flex"
358+newtype Shadow = ShadowCfg ShadowCfg
101− , "flex-direction": "column"
359+
102− , "flex-wrap": "wrap"
360+instance Renderable Shadow where
361+ render (ShadowCfg s) = show s.offset.x <> "px " <> show s.offset.y <> "px " <> show s.blur <> "px " <> show s.size <> "px " <> render s.color
362+ renderKey (ShadowCfg s) = show s.offset.x <> "-" <> show s.offset.y <> "-" <> show s.blur <> "-" <> show s.size <> "-" <> renderKey s.color
363+
364+data Corner = TopLeft | TopRight | BottomRight | BottomLeft
365+
366+instance Renderable Corner where
367+ render = case _ of
368+ TopLeft -> "top-left"
369+ TopRight -> "top-right"
370+ BottomRight -> "bottom-right"
371+ BottomLeft -> "bottom-left"
372+ renderKey = case _ of
373+ TopLeft -> "top-left"
374+ TopRight -> "top-right"
375+ BottomRight -> "bottom-right"
376+ BottomLeft -> "bottom-left"
377+
378+data BorderStyle = Solid | Dashed | Dotted
379+
380+instance Renderable BorderStyle where
381+ render = case _ of
382+ Solid -> "solid"
383+ Dashed -> "dashed"
384+ Dotted -> "dotted"
385+ renderKey = case _ of
386+ Solid -> "solid"
387+ Dashed -> "dashed"
388+ Dotted -> "dotted"
389+
390+data Side = Top | Right | Bottom | Left
391+
392+instance Renderable Side where
393+ render = case _ of
394+ Top -> "top"
395+ Right -> "right"
396+ Bottom -> "bottom"
397+ Left -> "left"
398+ renderKey = case _ of
399+ Top -> "top"
400+ Right -> "right"
401+ Bottom -> "bottom"
402+ Left -> "left"
403+
404+data Nerve msg = OnClick msg
405+
406+newtype WiredNerves = WiredNerves (Object (Event -> Effect Unit))
407+
408+instance Semigroup WiredNerves where
409+ append (WiredNerves x) (WiredNerves y) =
410+ WiredNerves $ Object.unionWith (\f g ev -> f ev *> g ev) x y
411+
412+instance Monoid WiredNerves where
413+ mempty = WiredNerves Object.empty
414+
415+wireNerve :: forall msg. (msg -> Effect Unit) -> Nerve msg -> WiredNerves
416+wireNerve fire nerve = WiredNerves $ case nerve of
417+ OnClick msg -> Object.singleton "click" $ \_ev -> fire msg
418+
419+type View msg =
420+ { nerves :: Array (Nerve msg)
421+ , meat :: Array Meat
422+ , hover :: Array Meat
423+ , down :: Array Meat
424+ } /\ Bones msg
425+
426+none :: forall msg. View msg
427+none = mempty /\ None
428+
429+newtype Skin = Skin (Object String)
430+
431+sk :: String -> String -> String -> Writer SkinGrowth Classes
432+sk cName key value = do
433+ tell $ SkinGrowth $ { meat: Object.singleton cName { key, value }, hover: Object.empty, down: Object.empty }
434+ pure [ cName ]
435+
436+instance Semigroup Skin where
437+ append (Skin x) (Skin y) = Skin $ Object.union x y
438+
439+instance Monoid Skin where
440+ mempty = Skin Object.empty
441+
442+data Context = Grid | Flexbox Direction | Generic | Span
443+
444+skin :: Context -> Meat -> Writer SkinGrowth Classes
445+skin ctx = case _ of
446+ Spacing x y -> sk ("spacing-" <> show x <> "-" <> show y) "gap" (show x <> "px " <> show y <> "px")
447+ Explain -> sk "explain" "border" "dashed magenta"
448+ Align dir alignment -> case ctx of
449+ Generic -> mempty
450+ Span -> mempty
451+ Grid ->
452+ let
453+ k =
454+ ( case dir of
455+ X -> "justify-items"
456+ Y -> "align-items"
457+ )
458+ v =
459+ ( case alignment of
460+ Start -> "start"
461+ Center -> "center"
462+ End -> "end"
463+ )
464+ in
465+ sk ("align-grid-" <> k <> "-" <> v) k v
466+
467+ Flexbox flexDir ->
468+ let
469+ k =
470+ ( case flexDir /\ dir of
471+ X /\ X -> "justify-content"
472+ X /\ Y -> "align-items"
473+ Y /\ X -> "align-items"
474+ Y /\ Y -> "justify-content"
475+ )
476+
477+ v =
478+ ( case alignment of
479+ Start -> "flex-start"
480+ Center -> "center"
481+ End -> "flex-end"
482+ )
483+ in
484+ sk ("align-flexbox-" <> k <> "-" <> v) k v
485+ Width l -> sk ("width-" <> renderKey l) "width" (render l)
486+ Height l -> sk ("height-" <> renderKey l) "height" (render l)
487+ Wrapped -> case ctx of
488+ Flexbox _ -> sk "wrapped" "flex-wrap" "wrap"
489+ _ -> pure []
490+ BackgroundColor color -> sk ("bg-color-" <> renderKey color) "background-color" (render color)
491+ Padding side l ->
492+ sk
493+ ("padding-" <> renderKey side <> "-" <> show l)
494+ ("padding-" <> render side)
495+ (show l <> "px")
496+ Spread -> case ctx of
497+ Flexbox _ -> sk "spread" "justify-content" "space-between"
498+ _ -> pure []
499+ Opacity o -> sk ("opacity-" <> show o) "opacity" (show o)
500+ Pointer -> sk "pointer" "cursor" "pointer"
501+ Move { x, y } -> sk ("move-" <> show x <> "-" <> show y) "transform" ("translate(" <> show x <> "px, " <> show y <> "px)")
502+ Clip X -> sk "clip-x" "overflow-x" "hidden"
503+ Clip Y -> sk "clip-y" "overflow-y" "hidden"
504+ BorderWidth side l -> sk ("border-width-" <> renderKey side <> "-" <> show l) ("border-" <> render side <> "-width") (show l <> "px")
505+ BorderStyle s -> sk ("border-style-" <> renderKey s) "border-style" (render s)
506+ Round corner l -> sk ("round-" <> renderKey corner <> "-" <> show l) ("border-" <> render corner <> "-radius") (show l <> "px")
507+ Shadow s -> sk ("shadow-" <> renderKey s) "box-shadow" (render s)
508+ InnerShadow s -> sk ("inner-shadow-" <> renderKey s) "box-shadow" (render s <> " inset")
509+ FontColor c -> sk ("font-color-" <> renderKey c) "color" (render c)
510+ FontSize l -> sk ("font-size-" <> show l) "font-size" (show l <> "px")
511+ Font f -> sk ("font-" <> removeSpaces f) "font-family" f
512+ FontWeight w -> sk ("font-weight-" <> show w) "font-weight" (show w)
513+
514+removeSpaces :: String -> String
515+removeSpaces = String.replaceAll (String.Pattern " ") (String.Replacement "-")
516+
517+class Renderable x where
518+ render :: x -> String
519+ renderKey :: x -> String
520+
521+instance Renderable Length where
522+ render = case _ of
523+ Px px -> show px <> "px"
524+ Fit -> "fit-content"
525+ Fill -> "100%"
526+ Max px l -> "max(" <> show px <> "px," <> render l <> ")"
527+ Min px l -> "min(" <> show px <> "px," <> render l <> ")"
528+ renderKey = case _ of
529+ Px px -> show px
530+ Fit -> "fit-content"
531+ Fill -> "fill"
532+ Max px l -> "max-" <> show px <> "-" <> renderKey l
533+ Min px l -> "min-" <> show px <> "-" <> renderKey l
534+
535+newtype Color = Color { r :: Int, g :: Int, b :: Int, a :: Int }
536+
537+rgb255 :: Int -> Int -> Int -> Color
538+rgb255 r g b = Color { r, g, b, a: 100 }
539+
540+rgba255 :: Int -> Int -> Int -> Int -> Color
541+rgba255 r g b a = Color { r, g, b, a }
542+
543+rgb :: Number -> Number -> Number -> Color
544+rgb r g b = Color { r: Int.round (r * 255.0), g: Int.round (g * 255.0), b: Int.round (b * 255.0), a: 100 }
545+
546+rgba :: Number -> Number -> Number -> Number -> Color
547+rgba r g b a = Color { r: Int.round (r * 255.0), g: Int.round (g * 255.0), b: Int.round (b * 255.0), a: Int.round (a * 100.0) }
548+
549+instance Renderable Color where
550+ render (Color { r, g, b, a }) = "rgb(" <> show r <> "," <> show g <> "," <> show b <> "," <> show a <> "%)"
551+ renderKey (Color { r, g, b, a }) = show r <> "-" <> show g <> "-" <> show b <> "-" <> show a
552+
553+data Bones :: Type -> Type
554+data Bones msg
555+ = Column (Array (View msg))
556+ | Row (Array (View msg))
557+ | Stack (Array (View msg))
558+ | Wrapper (View msg)
559+ | Text String
560+ | Link String { newTab :: Boolean } (View msg)
561+ | Download String { filename :: Maybe String } (View msg)
562+ | Image String { description :: String }
563+ | TextInput { value :: String, onChange :: String -> msg }
564+ | None
565+
566+type Classes = Array String
567+
568+newtype Mutation = Mutation { extraSkin :: Classes }
569+
570+instance Semigroup Mutation where
571+ append (Mutation x) (Mutation y) = Mutation { extraSkin: x.extraSkin <> y.extraSkin }
572+
573+instance Monoid Mutation where
574+ mempty = Mutation { extraSkin: mempty }
575+
576+newtype SkinGrowth = SkinGrowth
577+ { meat :: Object { key :: String, value :: String }
578+ , hover :: Object { key :: String, value :: String }
579+ , down :: Object { key :: String, value :: String }
580+ }
581+
582+styleSkinGrowth :: SkinGrowth -> String
583+styleSkinGrowth (SkinGrowth o) =
584+ Object.foldMap (\className { key, value } -> "." <> className <> "{" <> key <> ":" <> value <> ";}") o.meat
585+ <> Object.foldMap (\className { key, value } -> "." <> className <> "{" <> key <> ":" <> value <> ";}") o.hover
586+ <> Object.foldMap (\className { key, value } -> "." <> className <> "{" <> key <> ":" <> value <> ";}") o.down
587+
588+instance Semigroup SkinGrowth where
589+ append (SkinGrowth x) (SkinGrowth y) = SkinGrowth $
590+ { meat: Object.union x.meat y.meat
591+ , hover: Object.union x.hover y.hover
592+ , down: Object.union x.down y.down
593+ }
594+
595+instance Monoid SkinGrowth where
596+ mempty = SkinGrowth mempty
597+
598+growSkin :: forall msg. (msg -> Effect Unit) -> Mutation -> View msg -> Writer SkinGrowth VNode
599+growSkin fire (Mutation mutation) ({ meat, hover, down, nerves } /\ bones) = do
600+ let
601+ wiredNerves = Array.foldMap (wireNerve fire) nerves
602+ alignCenter = [ Align X Center, Align Y Center ]
603+ widthFill = [ Width Fill, Height Fill ]
604+ skn ctx = do
605+ meatClasses <- ((_ <> mutation.extraSkin) <<< Array.concat) <$> traverse (skin ctx)
606+ ( meat
607+ <> case ctx of
608+ Span -> mempty
609+ Grid -> widthFill
610+ Flexbox _ -> widthFill
611+ Generic -> widthFill
612+ <> case ctx of
613+ Grid -> alignCenter
614+ Flexbox _ -> alignCenter
615+ Span -> mempty
616+ Generic -> alignCenter
617+ )
618+ let hoverClasses /\ (SkinGrowth hover') = runWriter $ traverse (skin ctx) hover
619+ _ <- traverseWithIndex
620+ ( \key val -> tell $ SkinGrowth $
621+ { meat: Object.empty
622+ , hover: Object.singleton (key <> "-hover:hover") val
623+ , down: Object.empty
624+ }
625+ )
626+ hover'.meat
627+ let downClasses /\ (SkinGrowth down') = runWriter $ traverse (skin ctx) down
628+ _ <- traverseWithIndex
629+ ( \key val -> tell $ SkinGrowth $
630+ { meat: Object.empty
631+ , hover: Object.empty
632+ , down: Object.singleton (key <> "-down:active") val
633+ }
634+ )
635+ down'.meat
636+
637+ pure $ meatClasses <> map (_ <> "-hover") (Array.concat hoverClasses) <> map (_ <> "-down") (Array.concat downClasses)
638+
639+ case bones of
640+ Text t -> (\c -> string "span" c wiredNerves t) <$> (skn Span)
641+ Wrapper x -> do
642+ classes <- (skn (Flexbox X) <> sk "display-flex" "display" "flex" <> sk "flex-direction-row" "flex-direction" "row")
643+ x' <- growSkin fire mempty x
644+ pure $ h "div" classes wiredNerves [ x' ]
645+ Stack children -> do
646+ classes <- (skn Grid <> sk "display-grid" "display" "grid")
647+ extraSkin <- sk "grid-row-1" "grid-row" "1" <> sk "grid-column-1" "grid-column" "1"
648+ children' <- (traverse (growSkin fire $ Mutation { extraSkin }) children)
649+ pure $ h "div" classes wiredNerves children'
650+
651+ Row children -> do
652+ classes <- (skn (Flexbox X) <> sk "display-flex" "display" "flex" <> sk "flex-direction-row" "flex-direction" "row")
653+ children' <- traverse (growSkin fire mempty) children
654+ pure $ h "div" classes wiredNerves children'
655+ Column children -> do
656+ classes <- (skn (Flexbox Y) <> sk "display-flex" "display" "flex" <> sk "flex-direction-column" "flex-direction" "column")
657+ children' <- traverse (growSkin fire mempty) children
658+ pure $ h "div" classes wiredNerves children'
659+ Link href { newTab } child -> do
660+ classes <- (skn (Flexbox X) <> sk "display-flex" "display" "flex" <> sk "flex-direction-row" "flex-direction" "row")
661+ child' <- growSkin fire mempty child
662+ pure $ hWith "a"
663+ { href
664+ , rel: "noopener noreferrer"
665+ , target: if newTab then "_blank" else "_self"
103 }
666 }
104− )
667+ classes
105− children
668+ wiredNerves
669+ [ child' ]
106
670
107−button :: forall msg. Array (Attribute msg) -> { onPress :: msg, view :: View msg } -> View msg
671+ Download href { filename } child -> do
108−button _ { onPress, view } = View $ \fire -> h "div" { onclick: fire onPress } [ unView view fire ]
672+ classes <- (skn (Flexbox X) <> sk "display-flex" "display" "flex" <> sk "flex-direction-row" "flex-direction" "row")
673+ child' <- growSkin fire mempty child
674+ pure $ hWith "a"
675+ { href
676+ , download: Maybe.fromMaybe "" filename
677+ }
678+ classes
679+ wiredNerves
680+ [ child' ]
681+ Image src { description } -> (\c -> hWith "img" { src, alt: description } c wiredNerves []) <$> (skn Generic)
682+ TextInput { value, onChange } -> do
683+ classes <- skn Generic
684+ let
685+ onInputNerve = WiredNerves $ Object.singleton "input" $ \ev ->
686+ case Event.currentTarget ev >>= HTMLInputElement.fromEventTarget of
687+ Nothing -> pure unit
688+ Just inputEl -> do
689+ val <- HTMLInputElement.value inputEl
690+ fire $ onChange val
691+ pure $ hWith "input" { value } classes (wiredNerves <> onInputNerve) []
692+ None -> pure $ h "div" mempty wiredNerves []
109
693
110−s :: forall msg. String -> View msg
694+grow :: forall msg. (msg -> Effect Unit) -> View msg -> { node :: VNode, style :: String }
111−s x = View $ \_ -> string x
695+grow fire v =
696+ let
697+ node /\ skinGrowth = runWriter (growSkin fire mempty v)
698+ in
699+ { node, style: styleSkinGrowth skinGrowth }
112
700
113−_v :: forall msg. String -> RenderedAttribute -> Array (View msg) -> View msg
114−_v el attr children = View $ \fire -> h el (unsafeCoerce attr) (map (\(View f) -> f fire) children)
plum/src/Snabbdom.jsnew file+1
@@ -0,0 +1 @@
1+function m(f,G){let z,W=G.elm,X=f.data.attrs,Z=G.data.attrs;if(!X&&!Z)return;if(X===Z)return;X=X||{},Z=Z||{};for(z in Z){let K=Z[z];if(X[z]!==K)if(K===!0)W.setAttribute(z,"");else if(K===!1)W.removeAttribute(z);else if(z.charCodeAt(0)!==120)W.setAttribute(z,K);else if(z.charCodeAt(3)===58)W.setAttributeNS("http://www.w3.org/XML/1998/namespace",z,K);else if(z.charCodeAt(5)===58)z.charCodeAt(1)===109?W.setAttributeNS("http://www.w3.org/2000/xmlns/",z,K):W.setAttributeNS("http://www.w3.org/1999/xlink",z,K);else W.setAttribute(z,K)}for(z in X)if(!(z in Z))W.removeAttribute(z)}var s={create:m,update:m};function r(f,G,z){if(typeof f==="function")f.call(G,z,G);else if(typeof f==="object")for(let W=0;W<f.length;W++)r(f[W],G,z)}function G0(f,G){let z=f.type,W=G.data.on;if(W&&W[z])r(W[z],G,f)}function J0(){return function f(G){G0(G,f.vnode)}}function x(f,G){let z=f.data.on,W=f.listener,X=f.elm,Z=G&&G.data.on,K=G&&G.elm,U;if(z===Z)return;if(z&&W){if(!Z)for(U in z)X.removeEventListener(U,W,!1);else for(U in z)if(!Z[U])X.removeEventListener(U,W,!1)}if(Z){let D=G.listener=f.listener||J0();if(D.vnode=G,!z)for(U in Z)K.addEventListener(U,D,!1);else for(U in Z)if(!z[U])K.addEventListener(U,D,!1)}}var l={create:x,update:x,destroy:x};function N(f,G,z,W,X){let Z=G===void 0?void 0:G.key;return{sel:f,data:G,children:z,text:W,elm:X,key:Z}}var u=Array.isArray;function a(f){return typeof f==="string"||typeof f==="number"||f instanceof String||f instanceof Number}function Y0(f,G){return document.createElement(f,G)}function Z0(f,G,z){return document.createElementNS(f,G,z)}function $0(){return I(document.createDocumentFragment())}function B0(f){return document.createTextNode(f)}function q0(f){return document.createComment(f)}function K0(f,G,z){if(S(f)){let W=f;while(W&&S(W))W=I(W).parent;f=W!==null&&W!==void 0?W:f}if(S(G))G=I(G,f);if(z&&S(z))z=I(z).firstChildNode;f.insertBefore(G,z)}function P0(f,G){f.removeChild(G)}function H0(f,G){if(S(G))G=I(G,f);f.appendChild(G)}function t(f){if(S(f)){while(f&&S(f))f=I(f).parent;return f!==null&&f!==void 0?f:null}return f.parentNode}function O0(f){var G;if(S(f)){let z=I(f),W=t(z);if(W&&z.lastChildNode){let X=Array.from(W.childNodes),Z=X.indexOf(z.lastChildNode);return(G=X[Z+1])!==null&&G!==void 0?G:null}return null}return f.nextSibling}function U0(f){return f.tagName}function R0(f,G){f.textContent=G}function T0(f){return f.textContent}function L0(f){return f.nodeType===1}function M0(f){return f.nodeType===3}function D0(f){return f.nodeType===8}function S(f){return f.nodeType===11}function I(f,G){var z,W,X;let Z=f;return(z=Z.parent)!==null&&z!==void 0||(Z.parent=G!==null&&G!==void 0?G:null),(W=Z.firstChildNode)!==null&&W!==void 0||(Z.firstChildNode=f.firstChild),(X=Z.lastChildNode)!==null&&X!==void 0||(Z.lastChildNode=f.lastChild),Z}var E={createElement:Y0,createElementNS:Z0,createTextNode:B0,createDocumentFragment:$0,createComment:q0,insertBefore:K0,removeChild:P0,appendChild:H0,parentNode:t,nextSibling:O0,tagName:U0,setTextContent:R0,getTextContent:T0,isElement:L0,isText:M0,isComment:D0,isDocumentFragment:S};var V=N("",{},[],void 0,void 0);function w(f,G){var z,W;let X=f.key===G.key,Z=((z=f.data)===null||z===void 0?void 0:z.is)===((W=G.data)===null||W===void 0?void 0:W.is),K=f.sel===G.sel,U=!f.sel&&f.sel===G.sel?typeof f.text===typeof G.text:!0;return K&&X&&Z&&U}function A0(){throw new Error("The document fragment is not supported on this platform.")}function j0(f,G){return f.isElement(G)}function F0(f,G){return f.isDocumentFragment(G)}function Q0(f,G,z){var W;let X={};for(let Z=G;Z<=z;++Z){let K=(W=f[Z])===null||W===void 0?void 0:W.key;if(K!==void 0)X[K]=Z}return X}var g0=["create","update","remove","destroy","pre","post"];function n(f,G,z){let W={create:[],update:[],remove:[],destroy:[],pre:[],post:[]},X=G!==void 0?G:E;for(let J of g0)for(let Y of f){let $=Y[J];if($!==void 0)W[J].push($)}function Z(J){let Y=J.id?"#"+J.id:"",$=J.getAttribute("class"),B=$?"."+$.split(" ").join("."):"";return N(X.tagName(J).toLowerCase()+Y+B,{},[],void 0,J)}function K(J){return N(void 0,{},[],void 0,J)}function U(J,Y){return function $(){if(--Y===0){let B=X.parentNode(J);if(B!==null)X.removeChild(B,J)}}}function D(J,Y){var $,B,P,O,L;let q,R=J.data,M=R===null||R===void 0?void 0:R.hook;($=M===null||M===void 0?void 0:M.init)===null||$===void 0||$.call(M,J);let{children:T,sel:H}=J;if(H==="!")(B=J.text)!==null&&B!==void 0||(J.text=""),J.elm=X.createComment(J.text);else if(H==="")J.elm=X.createTextNode(J.text);else if(H!==void 0){let A=H.indexOf("#"),j=H.indexOf(".",A),F=A>0?A:H.length,b=j>0?j:H.length,i=A!==-1||j!==-1?H.slice(0,Math.min(F,b)):H,p=R===null||R===void 0?void 0:R.ns,_=p===void 0?X.createElement(i,R):X.createElementNS(p,i,R);if(J.elm=_,F<b)_.setAttribute("id",H.slice(F+1,b));if(j>0)_.setAttribute("class",H.slice(b+1).replace(/\./g," "));for(q=0;q<W.create.length;++q)W.create[q](V,J);if(a(J.text)&&(!u(T)||T.length===0))X.appendChild(_,X.createTextNode(J.text));if(u(T))for(q=0;q<T.length;++q){let v=T[q];if(v!=null)X.appendChild(_,D(v,Y))}if(M!==void 0){if((P=M.create)===null||P===void 0||P.call(M,V,J),M.insert!==void 0)Y.push(J)}}else if(((O=z===null||z===void 0?void 0:z.experimental)===null||O===void 0?void 0:O.fragments)&&J.children){J.elm=((L=X.createDocumentFragment)!==null&&L!==void 0?L:A0)();for(q=0;q<W.create.length;++q)W.create[q](V,J);for(q=0;q<J.children.length;++q){let A=J.children[q];if(A!=null)X.appendChild(J.elm,D(A,Y))}}else J.elm=X.createTextNode(J.text);return J.elm}function y(J,Y,$,B,P,O){for(;B<=P;++B){let L=$[B];if(L!=null)X.insertBefore(J,D(L,O),Y)}}function k(J){var Y,$;let B=J.data;if(B!==void 0){($=(Y=B===null||B===void 0?void 0:B.hook)===null||Y===void 0?void 0:Y.destroy)===null||$===void 0||$.call(Y,J);for(let P=0;P<W.destroy.length;++P)W.destroy[P](J);if(J.children!==void 0)for(let P=0;P<J.children.length;++P){let O=J.children[P];if(O!=null&&typeof O!=="string")k(O)}}}function g(J,Y,$,B){var P,O;for(;$<=B;++$){let L,q=Y[$];if(q!=null)if(q.sel!==void 0){k(q),L=W.remove.length+1;let R=U(q.elm,L);for(let T=0;T<W.remove.length;++T)W.remove[T](q,R);let M=(O=(P=q===null||q===void 0?void 0:q.data)===null||P===void 0?void 0:P.hook)===null||O===void 0?void 0:O.remove;if(M!==void 0)M(q,R);else R()}else if(q.children)k(q),g(J,q.children,0,q.children.length-1);else X.removeChild(J,q.elm)}}function C(J,Y,$,B){let P=0,O=0,L=Y.length-1,q=Y[0],R=Y[L],M=$.length-1,T=$[0],H=$[M],A,j,F,b;while(P<=L&&O<=M)if(q==null)q=Y[++P];else if(R==null)R=Y[--L];else if(T==null)T=$[++O];else if(H==null)H=$[--M];else if(w(q,T))Q(q,T,B),q=Y[++P],T=$[++O];else if(w(R,H))Q(R,H,B),R=Y[--L],H=$[--M];else if(w(q,H))Q(q,H,B),X.insertBefore(J,q.elm,X.nextSibling(R.elm)),q=Y[++P],H=$[--M];else if(w(R,T))Q(R,T,B),X.insertBefore(J,R.elm,q.elm),R=Y[--L],T=$[++O];else{if(A===void 0)A=Q0(Y,P,L);if(j=A[T.key],j===void 0)X.insertBefore(J,D(T,B),q.elm),T=$[++O];else if(A[H.key]===void 0)X.insertBefore(J,D(H,B),X.nextSibling(R.elm)),H=$[--M];else{if(F=Y[j],F.sel!==T.sel)X.insertBefore(J,D(T,B),q.elm);else Q(F,T,B),Y[j]=void 0,X.insertBefore(J,F.elm,q.elm);T=$[++O]}}if(O<=M)b=$[M+1]==null?null:$[M+1].elm,y(J,b,$,O,M,B);if(P<=L)g(J,Y,P,L)}function Q(J,Y,$){var B,P,O,L,q,R,M,T;let H=(B=Y.data)===null||B===void 0?void 0:B.hook;(P=H===null||H===void 0?void 0:H.prepatch)===null||P===void 0||P.call(H,J,Y);let A=Y.elm=J.elm;if(J===Y)return;if(Y.data!==void 0||Y.text!==void 0&&Y.text!==J.text){(O=Y.data)!==null&&O!==void 0||(Y.data={}),(L=J.data)!==null&&L!==void 0||(J.data={});for(let b=0;b<W.update.length;++b)W.update[b](J,Y);(M=(R=(q=Y.data)===null||q===void 0?void 0:q.hook)===null||R===void 0?void 0:R.update)===null||M===void 0||M.call(R,J,Y)}let j=J.children,F=Y.children;if(Y.text===void 0){if(j!==void 0&&F!==void 0){if(j!==F)C(A,j,F,$)}else if(F!==void 0){if(J.text!==void 0)X.setTextContent(A,"");y(A,null,F,0,F.length-1,$)}else if(j!==void 0)g(A,j,0,j.length-1);else if(J.text!==void 0)X.setTextContent(A,"")}else if(J.text!==Y.text){if(j!==void 0)g(A,j,0,j.length-1);X.setTextContent(A,Y.text)}(T=H===null||H===void 0?void 0:H.postpatch)===null||T===void 0||T.call(H,J,Y)}return function J(Y,$){let B,P,O,L=[];for(B=0;B<W.pre.length;++B)W.pre[B]();if(j0(X,Y))Y=Z(Y);else if(F0(X,Y))Y=K(Y);if(w(Y,$))Q(Y,$,L);else if(P=Y.elm,O=X.parentNode(P),D($,L),O!==null)X.insertBefore(O,$.elm,X.nextSibling(P)),g(O,[Y],0,0);for(B=0;B<L.length;++B)L[B].data.hook.insert(L[B]);for(B=0;B<W.post.length;++B)W.post[B]();return $}}var o=typeof(window===null||window===void 0?void 0:window.requestAnimationFrame)==="function"?window.requestAnimationFrame.bind(window):setTimeout,b0=(f)=>{o(()=>{o(f)})},c=!1;function k0(f,G,z){b0(()=>{f[G]=z})}function d(f,G){let z,W,X=G.elm,Z=f.data.style,K=G.data.style;if(!Z&&!K)return;if(Z===K)return;Z=Z||{},K=K||{};let U="delayed"in Z;for(W in Z)if(!(W in K))if(W[0]==="-"&&W[1]==="-")X.style.removeProperty(W);else X.style[W]="";for(W in K)if(z=K[W],W==="delayed"&&K.delayed){for(let D in K.delayed)if(z=K.delayed[D],!U||z!==Z.delayed[D])k0(X.style,D,z)}else if(W!=="remove"&&z!==Z[W])if(W[0]==="-"&&W[1]==="-")X.style.setProperty(W,z);else X.style[W]=z}function N0(f){let G,z,W=f.elm,X=f.data.style;if(!X||!(G=X.destroy))return;for(z in G)W.style[z]=G[z]}function S0(f,G){let z=f.data.style;if(!z||!z.remove){G();return}if(!c)f.elm.offsetLeft,c=!0;let W,X=f.elm,Z=0,K=z.remove,U=0,D=[];for(W in K)D.push(W),X.style[W]=K[W];let k=getComputedStyle(X)["transition-property"].split(", ");for(;Z<k.length;++Z)if(D.indexOf(k[Z])!==-1)U++;X.addEventListener("transitionend",(g)=>{if(g.target===X)--U;if(U===0)G()})}function y0(){c=!1}var e={pre:y0,create:d,update:d,destroy:N0,remove:S0};function f0(f,G){let z,W,X,Z=G.elm,K=f.data.props,U=G.data.props;if(!K&&!U)return;if(K===U)return;K=K||{},U=U||{};for(z in U)if(W=U[z],X=K[z],X!==W&&(z!=="value"||Z[z]!==W))Z[z]=W}var W0={create:f0,update:f0};function h(f,G,z){if(f.ns="http://www.w3.org/2000/svg",z!=="foreignObject"&&G!==void 0)for(let W=0;W<G.length;++W){let X=G[W];if(typeof X==="string")continue;let Z=X.data;if(Z!==void 0)h(Z,X.children,X.sel)}}function I0(f){return f.slice(5).replace(/-([a-z])/g,(G,z)=>z.toUpperCase())}function z0(f,G){var z;let W=G!==void 0?G:E,X;if(W.isElement(f)){let Z=f.id?"#"+f.id:"",K=(z=f.getAttribute("class"))===null||z===void 0?void 0:z.match(/[^\t\r\n\f ]+/g),U=K?"."+K.join("."):"",D=W.tagName(f).toLowerCase()+Z+U,y={},k={},g={},C=[],Q,J,Y,$=f.attributes,B=f.childNodes;for(J=0,Y=$.length;J<Y;J++)if(Q=$[J].nodeName,Q.startsWith("data-"))k[I0(Q)]=$[J].nodeValue||"";else if(Q!=="id"&&Q!=="class")y[Q]=$[J].nodeValue;for(J=0,Y=B.length;J<Y;J++)C.push(z0(B[J],G));if(Object.keys(y).length>0)g.attrs=y;if(Object.keys(k).length>0)g.dataset=k;if(D.startsWith("svg")&&(D.length===3||D[3]==="."||D[3]==="#"))h(g,C,D);return N(D,g,C,void 0,f)}else if(W.isText(f))return X=W.getTextContent(f),N(void 0,void 0,void 0,X,f);else if(W.isComment(f))return X=W.getTextContent(f),N("!",{},[],X,f);else return N("",{},[],void 0,f)}function o0(){return n([s,l,e,W0])}export{N as vnode,z0 as toVNode,o0 as initWithModules};
plum/src/Snabbdom.pursnew file+45
@@ -0,0 +1,45 @@
1+module Snabbdom (h, VNode, init, toVNode) where
2+
3+import Prelude
4+
5+import Data.Function.Uncurried (Fn4, runFn4)
6+import Effect (Effect)
7+import Effect.Uncurried (EffectFn1, EffectFn2, mkEffectFn1, runEffectFn2)
8+import Foreign.Object (Object)
9+import Literals.Undefined (Undefined)
10+import Untagged.Union (type (|+|))
11+import Web.DOM (Element)
12+import Web.Event.Event (Event)
13+
14+foreign import data VNode :: Type
15+
16+foreign import initWithModules :: Effect (EffectFn2 VNode VNode VNode)
17+
18+init :: Effect (VNode -> VNode -> Effect VNode)
19+init = initWithModules <#> runEffectFn2
20+
21+foreign import vnode :: forall props. Fn4 String (Record props) (Array VNode) (String |+| Undefined) VNode
22+
23+h
24+ :: String
25+ -> { attrs :: Object String
26+ , on :: Object (Event -> Effect Unit)
27+ , style :: Object String
28+ , props :: Object String
29+ }
30+ -> Array VNode
31+ -> (String |+| Undefined)
32+ -> VNode
33+h tag props children text = runFn4 vnode
34+ tag
35+ ( props { on = mkEffectFn1 <$> props.on }
36+ :: { attrs :: Object String
37+ , on :: Object (EffectFn1 Event Unit)
38+ , style :: Object String
39+ , props :: Object String
40+ }
41+ )
42+ children
43+ text
44+
45+foreign import toVNode :: Element -> VNode